]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - fs/cifs/connect.c
[CIFS] Fix allocation of buffers for new session setup routine to allow
[mirror_ubuntu-jammy-kernel.git] / fs / cifs / connect.c
1 /*
2 * fs/cifs/connect.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 #include <linux/fs.h>
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/ipv6.h>
27 #include <linux/pagemap.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/mempool.h>
31 #include <linux/delay.h>
32 #include <linux/completion.h>
33 #include <linux/pagevec.h>
34 #include <asm/uaccess.h>
35 #include <asm/processor.h>
36 #include "cifspdu.h"
37 #include "cifsglob.h"
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41 #include "cifs_fs_sb.h"
42 #include "ntlmssp.h"
43 #include "nterr.h"
44 #include "rfc1002pdu.h"
45 #include "cn_cifs.h"
46
47 #define CIFS_PORT 445
48 #define RFC1001_PORT 139
49
50 static DECLARE_COMPLETION(cifsd_complete);
51
52 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54
55 extern mempool_t *cifs_req_poolp;
56
57 struct smb_vol {
58 char *username;
59 char *password;
60 char *domainname;
61 char *UNC;
62 char *UNCip;
63 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
64 char *iocharset; /* local code page for mapping to and from Unicode */
65 char source_rfc1001_name[16]; /* netbios name of client */
66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
67 uid_t linux_uid;
68 gid_t linux_gid;
69 mode_t file_mode;
70 mode_t dir_mode;
71 unsigned secFlg;
72 unsigned rw:1;
73 unsigned retry:1;
74 unsigned intr:1;
75 unsigned setuids:1;
76 unsigned noperm:1;
77 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
78 unsigned cifs_acl:1;
79 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
80 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
81 unsigned direct_io:1;
82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
84 unsigned sfu_emul:1;
85 unsigned nullauth:1; /* attempt to authenticate with null user */
86 unsigned nocase; /* request case insensitive filenames */
87 unsigned nobrl; /* disable sending byte range locks to srv */
88 unsigned int rsize;
89 unsigned int wsize;
90 unsigned int sockopt;
91 unsigned short int port;
92 };
93
94 static int ipv4_connect(struct sockaddr_in *psin_server,
95 struct socket **csocket,
96 char * netb_name,
97 char * server_netb_name);
98 static int ipv6_connect(struct sockaddr_in6 *psin_server,
99 struct socket **csocket);
100
101
102 /*
103 * cifs tcp session reconnection
104 *
105 * mark tcp session as reconnecting so temporarily locked
106 * mark all smb sessions as reconnecting for tcp session
107 * reconnect tcp session
108 * wake up waiters on reconnection? - (not needed currently)
109 */
110
111 int
112 cifs_reconnect(struct TCP_Server_Info *server)
113 {
114 int rc = 0;
115 struct list_head *tmp;
116 struct cifsSesInfo *ses;
117 struct cifsTconInfo *tcon;
118 struct mid_q_entry * mid_entry;
119
120 spin_lock(&GlobalMid_Lock);
121 if(server->tcpStatus == CifsExiting) {
122 /* the demux thread will exit normally
123 next time through the loop */
124 spin_unlock(&GlobalMid_Lock);
125 return rc;
126 } else
127 server->tcpStatus = CifsNeedReconnect;
128 spin_unlock(&GlobalMid_Lock);
129 server->maxBuf = 0;
130
131 cFYI(1, ("Reconnecting tcp session"));
132
133 /* before reconnecting the tcp session, mark the smb session (uid)
134 and the tid bad so they are not used until reconnected */
135 read_lock(&GlobalSMBSeslock);
136 list_for_each(tmp, &GlobalSMBSessionList) {
137 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
138 if (ses->server) {
139 if (ses->server == server) {
140 ses->status = CifsNeedReconnect;
141 ses->ipc_tid = 0;
142 }
143 }
144 /* else tcp and smb sessions need reconnection */
145 }
146 list_for_each(tmp, &GlobalTreeConnectionList) {
147 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
148 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
149 tcon->tidStatus = CifsNeedReconnect;
150 }
151 }
152 read_unlock(&GlobalSMBSeslock);
153 /* do not want to be sending data on a socket we are freeing */
154 down(&server->tcpSem);
155 if(server->ssocket) {
156 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
157 server->ssocket->flags));
158 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
159 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
160 server->ssocket->flags));
161 sock_release(server->ssocket);
162 server->ssocket = NULL;
163 }
164
165 spin_lock(&GlobalMid_Lock);
166 list_for_each(tmp, &server->pending_mid_q) {
167 mid_entry = list_entry(tmp, struct
168 mid_q_entry,
169 qhead);
170 if(mid_entry) {
171 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
172 /* Mark other intransit requests as needing
173 retry so we do not immediately mark the
174 session bad again (ie after we reconnect
175 below) as they timeout too */
176 mid_entry->midState = MID_RETRY_NEEDED;
177 }
178 }
179 }
180 spin_unlock(&GlobalMid_Lock);
181 up(&server->tcpSem);
182
183 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
184 {
185 if(server->protocolType == IPV6) {
186 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
187 } else {
188 rc = ipv4_connect(&server->addr.sockAddr,
189 &server->ssocket,
190 server->workstation_RFC1001_name,
191 server->server_RFC1001_name);
192 }
193 if(rc) {
194 cFYI(1,("reconnect error %d",rc));
195 msleep(3000);
196 } else {
197 atomic_inc(&tcpSesReconnectCount);
198 spin_lock(&GlobalMid_Lock);
199 if(server->tcpStatus != CifsExiting)
200 server->tcpStatus = CifsGood;
201 server->sequence_number = 0;
202 spin_unlock(&GlobalMid_Lock);
203 /* atomic_set(&server->inFlight,0);*/
204 wake_up(&server->response_q);
205 }
206 }
207 return rc;
208 }
209
210 /*
211 return codes:
212 0 not a transact2, or all data present
213 >0 transact2 with that much data missing
214 -EINVAL = invalid transact2
215
216 */
217 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
218 {
219 struct smb_t2_rsp * pSMBt;
220 int total_data_size;
221 int data_in_this_rsp;
222 int remaining;
223
224 if(pSMB->Command != SMB_COM_TRANSACTION2)
225 return 0;
226
227 /* check for plausible wct, bcc and t2 data and parm sizes */
228 /* check for parm and data offset going beyond end of smb */
229 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
230 cFYI(1,("invalid transact2 word count"));
231 return -EINVAL;
232 }
233
234 pSMBt = (struct smb_t2_rsp *)pSMB;
235
236 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
237 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
238
239 remaining = total_data_size - data_in_this_rsp;
240
241 if(remaining == 0)
242 return 0;
243 else if(remaining < 0) {
244 cFYI(1,("total data %d smaller than data in frame %d",
245 total_data_size, data_in_this_rsp));
246 return -EINVAL;
247 } else {
248 cFYI(1,("missing %d bytes from transact2, check next response",
249 remaining));
250 if(total_data_size > maxBufSize) {
251 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
252 total_data_size,maxBufSize));
253 return -EINVAL;
254 }
255 return remaining;
256 }
257 }
258
259 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
260 {
261 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
262 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
263 int total_data_size;
264 int total_in_buf;
265 int remaining;
266 int total_in_buf2;
267 char * data_area_of_target;
268 char * data_area_of_buf2;
269 __u16 byte_count;
270
271 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
272
273 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
274 cFYI(1,("total data sizes of primary and secondary t2 differ"));
275 }
276
277 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
278
279 remaining = total_data_size - total_in_buf;
280
281 if(remaining < 0)
282 return -EINVAL;
283
284 if(remaining == 0) /* nothing to do, ignore */
285 return 0;
286
287 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
288 if(remaining < total_in_buf2) {
289 cFYI(1,("transact2 2nd response contains too much data"));
290 }
291
292 /* find end of first SMB data area */
293 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
294 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
295 /* validate target area */
296
297 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
298 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
299
300 data_area_of_target += total_in_buf;
301
302 /* copy second buffer into end of first buffer */
303 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
304 total_in_buf += total_in_buf2;
305 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
306 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
307 byte_count += total_in_buf2;
308 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
309
310 byte_count = pTargetSMB->smb_buf_length;
311 byte_count += total_in_buf2;
312
313 /* BB also add check that we are not beyond maximum buffer size */
314
315 pTargetSMB->smb_buf_length = byte_count;
316
317 if(remaining == total_in_buf2) {
318 cFYI(1,("found the last secondary response"));
319 return 0; /* we are done */
320 } else /* more responses to go */
321 return 1;
322
323 }
324
325 static int
326 cifs_demultiplex_thread(struct TCP_Server_Info *server)
327 {
328 int length;
329 unsigned int pdu_length, total_read;
330 struct smb_hdr *smb_buffer = NULL;
331 struct smb_hdr *bigbuf = NULL;
332 struct smb_hdr *smallbuf = NULL;
333 struct msghdr smb_msg;
334 struct kvec iov;
335 struct socket *csocket = server->ssocket;
336 struct list_head *tmp;
337 struct cifsSesInfo *ses;
338 struct task_struct *task_to_wake = NULL;
339 struct mid_q_entry *mid_entry;
340 char temp;
341 int isLargeBuf = FALSE;
342 int isMultiRsp;
343 int reconnect;
344
345 daemonize("cifsd");
346 allow_signal(SIGKILL);
347 current->flags |= PF_MEMALLOC;
348 server->tsk = current; /* save process info to wake at shutdown */
349 cFYI(1, ("Demultiplex PID: %d", current->pid));
350 write_lock(&GlobalSMBSeslock);
351 atomic_inc(&tcpSesAllocCount);
352 length = tcpSesAllocCount.counter;
353 write_unlock(&GlobalSMBSeslock);
354 complete(&cifsd_complete);
355 if(length > 1) {
356 mempool_resize(cifs_req_poolp,
357 length + cifs_min_rcv,
358 GFP_KERNEL);
359 }
360
361 while (server->tcpStatus != CifsExiting) {
362 if (try_to_freeze())
363 continue;
364 if (bigbuf == NULL) {
365 bigbuf = cifs_buf_get();
366 if (!bigbuf) {
367 cERROR(1, ("No memory for large SMB response"));
368 msleep(3000);
369 /* retry will check if exiting */
370 continue;
371 }
372 } else if (isLargeBuf) {
373 /* we are reusing a dirty large buf, clear its start */
374 memset(bigbuf, 0, sizeof (struct smb_hdr));
375 }
376
377 if (smallbuf == NULL) {
378 smallbuf = cifs_small_buf_get();
379 if (!smallbuf) {
380 cERROR(1, ("No memory for SMB response"));
381 msleep(1000);
382 /* retry will check if exiting */
383 continue;
384 }
385 /* beginning of smb buffer is cleared in our buf_get */
386 } else /* if existing small buf clear beginning */
387 memset(smallbuf, 0, sizeof (struct smb_hdr));
388
389 isLargeBuf = FALSE;
390 isMultiRsp = FALSE;
391 smb_buffer = smallbuf;
392 iov.iov_base = smb_buffer;
393 iov.iov_len = 4;
394 smb_msg.msg_control = NULL;
395 smb_msg.msg_controllen = 0;
396 length =
397 kernel_recvmsg(csocket, &smb_msg,
398 &iov, 1, 4, 0 /* BB see socket.h flags */);
399
400 if (server->tcpStatus == CifsExiting) {
401 break;
402 } else if (server->tcpStatus == CifsNeedReconnect) {
403 cFYI(1, ("Reconnect after server stopped responding"));
404 cifs_reconnect(server);
405 cFYI(1, ("call to reconnect done"));
406 csocket = server->ssocket;
407 continue;
408 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
409 msleep(1); /* minimum sleep to prevent looping
410 allowing socket to clear and app threads to set
411 tcpStatus CifsNeedReconnect if server hung */
412 continue;
413 } else if (length <= 0) {
414 if (server->tcpStatus == CifsNew) {
415 cFYI(1, ("tcp session abend after SMBnegprot"));
416 /* some servers kill the TCP session rather than
417 returning an SMB negprot error, in which
418 case reconnecting here is not going to help,
419 and so simply return error to mount */
420 break;
421 }
422 if (!try_to_freeze() && (length == -EINTR)) {
423 cFYI(1,("cifsd thread killed"));
424 break;
425 }
426 cFYI(1,("Reconnect after unexpected peek error %d",
427 length));
428 cifs_reconnect(server);
429 csocket = server->ssocket;
430 wake_up(&server->response_q);
431 continue;
432 } else if (length < 4) {
433 cFYI(1,
434 ("Frame under four bytes received (%d bytes long)",
435 length));
436 cifs_reconnect(server);
437 csocket = server->ssocket;
438 wake_up(&server->response_q);
439 continue;
440 }
441
442 /* The right amount was read from socket - 4 bytes */
443 /* so we can now interpret the length field */
444
445 /* the first byte big endian of the length field,
446 is actually not part of the length but the type
447 with the most common, zero, as regular data */
448 temp = *((char *) smb_buffer);
449
450 /* Note that FC 1001 length is big endian on the wire,
451 but we convert it here so it is always manipulated
452 as host byte order */
453 pdu_length = ntohl(smb_buffer->smb_buf_length);
454 smb_buffer->smb_buf_length = pdu_length;
455
456 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
457
458 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
459 continue;
460 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
461 cFYI(1,("Good RFC 1002 session rsp"));
462 continue;
463 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
464 /* we get this from Windows 98 instead of
465 an error on SMB negprot response */
466 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
467 pdu_length));
468 if(server->tcpStatus == CifsNew) {
469 /* if nack on negprot (rather than
470 ret of smb negprot error) reconnecting
471 not going to help, ret error to mount */
472 break;
473 } else {
474 /* give server a second to
475 clean up before reconnect attempt */
476 msleep(1000);
477 /* always try 445 first on reconnect
478 since we get NACK on some if we ever
479 connected to port 139 (the NACK is
480 since we do not begin with RFC1001
481 session initialize frame) */
482 server->addr.sockAddr.sin_port =
483 htons(CIFS_PORT);
484 cifs_reconnect(server);
485 csocket = server->ssocket;
486 wake_up(&server->response_q);
487 continue;
488 }
489 } else if (temp != (char) 0) {
490 cERROR(1,("Unknown RFC 1002 frame"));
491 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
492 length);
493 cifs_reconnect(server);
494 csocket = server->ssocket;
495 continue;
496 }
497
498 /* else we have an SMB response */
499 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
500 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
501 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
502 length, pdu_length+4));
503 cifs_reconnect(server);
504 csocket = server->ssocket;
505 wake_up(&server->response_q);
506 continue;
507 }
508
509 /* else length ok */
510 reconnect = 0;
511
512 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
513 isLargeBuf = TRUE;
514 memcpy(bigbuf, smallbuf, 4);
515 smb_buffer = bigbuf;
516 }
517 length = 0;
518 iov.iov_base = 4 + (char *)smb_buffer;
519 iov.iov_len = pdu_length;
520 for (total_read = 0; total_read < pdu_length;
521 total_read += length) {
522 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
523 pdu_length - total_read, 0);
524 if((server->tcpStatus == CifsExiting) ||
525 (length == -EINTR)) {
526 /* then will exit */
527 reconnect = 2;
528 break;
529 } else if (server->tcpStatus == CifsNeedReconnect) {
530 cifs_reconnect(server);
531 csocket = server->ssocket;
532 /* Reconnect wakes up rspns q */
533 /* Now we will reread sock */
534 reconnect = 1;
535 break;
536 } else if ((length == -ERESTARTSYS) ||
537 (length == -EAGAIN)) {
538 msleep(1); /* minimum sleep to prevent looping,
539 allowing socket to clear and app
540 threads to set tcpStatus
541 CifsNeedReconnect if server hung*/
542 continue;
543 } else if (length <= 0) {
544 cERROR(1,("Received no data, expecting %d",
545 pdu_length - total_read));
546 cifs_reconnect(server);
547 csocket = server->ssocket;
548 reconnect = 1;
549 break;
550 }
551 }
552 if(reconnect == 2)
553 break;
554 else if(reconnect == 1)
555 continue;
556
557 length += 4; /* account for rfc1002 hdr */
558
559
560 dump_smb(smb_buffer, length);
561 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
562 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
563 continue;
564 }
565
566
567 task_to_wake = NULL;
568 spin_lock(&GlobalMid_Lock);
569 list_for_each(tmp, &server->pending_mid_q) {
570 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
571
572 if ((mid_entry->mid == smb_buffer->Mid) &&
573 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
574 (mid_entry->command == smb_buffer->Command)) {
575 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
576 /* We have a multipart transact2 resp */
577 isMultiRsp = TRUE;
578 if(mid_entry->resp_buf) {
579 /* merge response - fix up 1st*/
580 if(coalesce_t2(smb_buffer,
581 mid_entry->resp_buf)) {
582 mid_entry->multiRsp = 1;
583 break;
584 } else {
585 /* all parts received */
586 mid_entry->multiEnd = 1;
587 goto multi_t2_fnd;
588 }
589 } else {
590 if(!isLargeBuf) {
591 cERROR(1,("1st trans2 resp needs bigbuf"));
592 /* BB maybe we can fix this up, switch
593 to already allocated large buffer? */
594 } else {
595 /* Have first buffer */
596 mid_entry->resp_buf =
597 smb_buffer;
598 mid_entry->largeBuf = 1;
599 bigbuf = NULL;
600 }
601 }
602 break;
603 }
604 mid_entry->resp_buf = smb_buffer;
605 if(isLargeBuf)
606 mid_entry->largeBuf = 1;
607 else
608 mid_entry->largeBuf = 0;
609 multi_t2_fnd:
610 task_to_wake = mid_entry->tsk;
611 mid_entry->midState = MID_RESPONSE_RECEIVED;
612 #ifdef CONFIG_CIFS_STATS2
613 mid_entry->when_received = jiffies;
614 #endif
615 break;
616 }
617 }
618 spin_unlock(&GlobalMid_Lock);
619 if (task_to_wake) {
620 /* Was previous buf put in mpx struct for multi-rsp? */
621 if(!isMultiRsp) {
622 /* smb buffer will be freed by user thread */
623 if(isLargeBuf) {
624 bigbuf = NULL;
625 } else
626 smallbuf = NULL;
627 }
628 wake_up_process(task_to_wake);
629 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
630 && (isMultiRsp == FALSE)) {
631 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
632 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
633 sizeof(struct smb_hdr));
634 #ifdef CONFIG_CIFS_DEBUG2
635 cifs_dump_detail(smb_buffer);
636 cifs_dump_mids(server);
637 #endif /* CIFS_DEBUG2 */
638
639 }
640 } /* end while !EXITING */
641
642 spin_lock(&GlobalMid_Lock);
643 server->tcpStatus = CifsExiting;
644 server->tsk = NULL;
645 /* check if we have blocked requests that need to free */
646 /* Note that cifs_max_pending is normally 50, but
647 can be set at module install time to as little as two */
648 if(atomic_read(&server->inFlight) >= cifs_max_pending)
649 atomic_set(&server->inFlight, cifs_max_pending - 1);
650 /* We do not want to set the max_pending too low or we
651 could end up with the counter going negative */
652 spin_unlock(&GlobalMid_Lock);
653 /* Although there should not be any requests blocked on
654 this queue it can not hurt to be paranoid and try to wake up requests
655 that may haven been blocked when more than 50 at time were on the wire
656 to the same server - they now will see the session is in exit state
657 and get out of SendReceive. */
658 wake_up_all(&server->request_q);
659 /* give those requests time to exit */
660 msleep(125);
661
662 if(server->ssocket) {
663 sock_release(csocket);
664 server->ssocket = NULL;
665 }
666 /* buffer usuallly freed in free_mid - need to free it here on exit */
667 if (bigbuf != NULL)
668 cifs_buf_release(bigbuf);
669 if (smallbuf != NULL)
670 cifs_small_buf_release(smallbuf);
671
672 read_lock(&GlobalSMBSeslock);
673 if (list_empty(&server->pending_mid_q)) {
674 /* loop through server session structures attached to this and
675 mark them dead */
676 list_for_each(tmp, &GlobalSMBSessionList) {
677 ses =
678 list_entry(tmp, struct cifsSesInfo,
679 cifsSessionList);
680 if (ses->server == server) {
681 ses->status = CifsExiting;
682 ses->server = NULL;
683 }
684 }
685 read_unlock(&GlobalSMBSeslock);
686 } else {
687 /* although we can not zero the server struct pointer yet,
688 since there are active requests which may depnd on them,
689 mark the corresponding SMB sessions as exiting too */
690 list_for_each(tmp, &GlobalSMBSessionList) {
691 ses = list_entry(tmp, struct cifsSesInfo,
692 cifsSessionList);
693 if (ses->server == server) {
694 ses->status = CifsExiting;
695 }
696 }
697
698 spin_lock(&GlobalMid_Lock);
699 list_for_each(tmp, &server->pending_mid_q) {
700 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
701 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
702 cFYI(1,
703 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
704 task_to_wake = mid_entry->tsk;
705 if(task_to_wake) {
706 wake_up_process(task_to_wake);
707 }
708 }
709 }
710 spin_unlock(&GlobalMid_Lock);
711 read_unlock(&GlobalSMBSeslock);
712 /* 1/8th of sec is more than enough time for them to exit */
713 msleep(125);
714 }
715
716 if (!list_empty(&server->pending_mid_q)) {
717 /* mpx threads have not exited yet give them
718 at least the smb send timeout time for long ops */
719 /* due to delays on oplock break requests, we need
720 to wait at least 45 seconds before giving up
721 on a request getting a response and going ahead
722 and killing cifsd */
723 cFYI(1, ("Wait for exit from demultiplex thread"));
724 msleep(46000);
725 /* if threads still have not exited they are probably never
726 coming home not much else we can do but free the memory */
727 }
728
729 write_lock(&GlobalSMBSeslock);
730 atomic_dec(&tcpSesAllocCount);
731 length = tcpSesAllocCount.counter;
732
733 /* last chance to mark ses pointers invalid
734 if there are any pointing to this (e.g
735 if a crazy root user tried to kill cifsd
736 kernel thread explicitly this might happen) */
737 list_for_each(tmp, &GlobalSMBSessionList) {
738 ses = list_entry(tmp, struct cifsSesInfo,
739 cifsSessionList);
740 if (ses->server == server) {
741 ses->server = NULL;
742 }
743 }
744 write_unlock(&GlobalSMBSeslock);
745
746 kfree(server);
747 if(length > 0) {
748 mempool_resize(cifs_req_poolp,
749 length + cifs_min_rcv,
750 GFP_KERNEL);
751 }
752
753 complete_and_exit(&cifsd_complete, 0);
754 return 0;
755 }
756
757 static int
758 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
759 {
760 char *value;
761 char *data;
762 unsigned int temp_len, i, j;
763 char separator[2];
764
765 separator[0] = ',';
766 separator[1] = 0;
767
768 memset(vol->source_rfc1001_name,0x20,15);
769 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
770 /* does not have to be a perfect mapping since the field is
771 informational, only used for servers that do not support
772 port 445 and it can be overridden at mount time */
773 vol->source_rfc1001_name[i] =
774 toupper(system_utsname.nodename[i]);
775 }
776 vol->source_rfc1001_name[15] = 0;
777 /* null target name indicates to use *SMBSERVR default called name
778 if we end up sending RFC1001 session initialize */
779 vol->target_rfc1001_name[0] = 0;
780 vol->linux_uid = current->uid; /* current->euid instead? */
781 vol->linux_gid = current->gid;
782 vol->dir_mode = S_IRWXUGO;
783 /* 2767 perms indicate mandatory locking support */
784 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
785
786 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
787 vol->rw = TRUE;
788 /* default is always to request posix paths. */
789 vol->posix_paths = 1;
790
791 if (!options)
792 return 1;
793
794 if(strncmp(options,"sep=",4) == 0) {
795 if(options[4] != 0) {
796 separator[0] = options[4];
797 options += 5;
798 } else {
799 cFYI(1,("Null separator not allowed"));
800 }
801 }
802
803 while ((data = strsep(&options, separator)) != NULL) {
804 if (!*data)
805 continue;
806 if ((value = strchr(data, '=')) != NULL)
807 *value++ = '\0';
808
809 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
810 vol->no_xattr = 0;
811 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
812 vol->no_xattr = 1;
813 } else if (strnicmp(data, "user", 4) == 0) {
814 if (!value || !*value) {
815 printk(KERN_WARNING
816 "CIFS: invalid or missing username\n");
817 return 1; /* needs_arg; */
818 }
819 if (strnlen(value, 200) < 200) {
820 vol->username = value;
821 } else {
822 printk(KERN_WARNING "CIFS: username too long\n");
823 return 1;
824 }
825 } else if (strnicmp(data, "pass", 4) == 0) {
826 if (!value) {
827 vol->password = NULL;
828 continue;
829 } else if(value[0] == 0) {
830 /* check if string begins with double comma
831 since that would mean the password really
832 does start with a comma, and would not
833 indicate an empty string */
834 if(value[1] != separator[0]) {
835 vol->password = NULL;
836 continue;
837 }
838 }
839 temp_len = strlen(value);
840 /* removed password length check, NTLM passwords
841 can be arbitrarily long */
842
843 /* if comma in password, the string will be
844 prematurely null terminated. Commas in password are
845 specified across the cifs mount interface by a double
846 comma ie ,, and a comma used as in other cases ie ','
847 as a parameter delimiter/separator is single and due
848 to the strsep above is temporarily zeroed. */
849
850 /* NB: password legally can have multiple commas and
851 the only illegal character in a password is null */
852
853 if ((value[temp_len] == 0) &&
854 (value[temp_len+1] == separator[0])) {
855 /* reinsert comma */
856 value[temp_len] = separator[0];
857 temp_len+=2; /* move after the second comma */
858 while(value[temp_len] != 0) {
859 if (value[temp_len] == separator[0]) {
860 if (value[temp_len+1] ==
861 separator[0]) {
862 /* skip second comma */
863 temp_len++;
864 } else {
865 /* single comma indicating start
866 of next parm */
867 break;
868 }
869 }
870 temp_len++;
871 }
872 if(value[temp_len] == 0) {
873 options = NULL;
874 } else {
875 value[temp_len] = 0;
876 /* point option to start of next parm */
877 options = value + temp_len + 1;
878 }
879 /* go from value to value + temp_len condensing
880 double commas to singles. Note that this ends up
881 allocating a few bytes too many, which is ok */
882 vol->password = kzalloc(temp_len, GFP_KERNEL);
883 if(vol->password == NULL) {
884 printk("CIFS: no memory for pass\n");
885 return 1;
886 }
887 for(i=0,j=0;i<temp_len;i++,j++) {
888 vol->password[j] = value[i];
889 if(value[i] == separator[0]
890 && value[i+1] == separator[0]) {
891 /* skip second comma */
892 i++;
893 }
894 }
895 vol->password[j] = 0;
896 } else {
897 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
898 if(vol->password == NULL) {
899 printk("CIFS: no memory for pass\n");
900 return 1;
901 }
902 strcpy(vol->password, value);
903 }
904 } else if (strnicmp(data, "ip", 2) == 0) {
905 if (!value || !*value) {
906 vol->UNCip = NULL;
907 } else if (strnlen(value, 35) < 35) {
908 vol->UNCip = value;
909 } else {
910 printk(KERN_WARNING "CIFS: ip address too long\n");
911 return 1;
912 }
913 } else if (strnicmp(data, "sec", 3) == 0) {
914 if (!value || !*value) {
915 cERROR(1,("no security value specified"));
916 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->secFlg |= CIFSSEC_MAY_KRB5 |
919 CIFSSEC_MUST_SIGN;
920 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
922 CIFSSEC_MAY_KRB5; */
923 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->secFlg |= CIFSSEC_MAY_KRB5;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
929 CIFSSEC_MUST_SIGN;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->secFlg |= CIFSSEC_MAY_NTLM |
934 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */
937 vol->secFlg |= CIFSSEC_MAY_NTLM;
938 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 /* BB is there a better way to do this? */
940 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
941 #ifdef CONFIG_CIFS_WEAK_PW_HASH
942 } else if (strnicmp(value, "lanman", 6) == 0) {
943 vol->secFlg |= CIFSSEC_MAY_LANMAN;
944 #endif
945 } else if (strnicmp(value, "none", 4) == 0) {
946 vol->nullauth = 1;
947 } else {
948 cERROR(1,("bad security option: %s", value));
949 return 1;
950 }
951 } else if ((strnicmp(data, "unc", 3) == 0)
952 || (strnicmp(data, "target", 6) == 0)
953 || (strnicmp(data, "path", 4) == 0)) {
954 if (!value || !*value) {
955 printk(KERN_WARNING
956 "CIFS: invalid path to network resource\n");
957 return 1; /* needs_arg; */
958 }
959 if ((temp_len = strnlen(value, 300)) < 300) {
960 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
961 if(vol->UNC == NULL)
962 return 1;
963 strcpy(vol->UNC,value);
964 if (strncmp(vol->UNC, "//", 2) == 0) {
965 vol->UNC[0] = '\\';
966 vol->UNC[1] = '\\';
967 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
968 printk(KERN_WARNING
969 "CIFS: UNC Path does not begin with // or \\\\ \n");
970 return 1;
971 }
972 } else {
973 printk(KERN_WARNING "CIFS: UNC name too long\n");
974 return 1;
975 }
976 } else if ((strnicmp(data, "domain", 3) == 0)
977 || (strnicmp(data, "workgroup", 5) == 0)) {
978 if (!value || !*value) {
979 printk(KERN_WARNING "CIFS: invalid domain name\n");
980 return 1; /* needs_arg; */
981 }
982 /* BB are there cases in which a comma can be valid in
983 a domain name and need special handling? */
984 if (strnlen(value, 256) < 256) {
985 vol->domainname = value;
986 cFYI(1, ("Domain name set"));
987 } else {
988 printk(KERN_WARNING "CIFS: domain name too long\n");
989 return 1;
990 }
991 } else if (strnicmp(data, "iocharset", 9) == 0) {
992 if (!value || !*value) {
993 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
994 return 1; /* needs_arg; */
995 }
996 if (strnlen(value, 65) < 65) {
997 if(strnicmp(value,"default",7))
998 vol->iocharset = value;
999 /* if iocharset not set load_nls_default used by caller */
1000 cFYI(1, ("iocharset set to %s",value));
1001 } else {
1002 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
1003 return 1;
1004 }
1005 } else if (strnicmp(data, "uid", 3) == 0) {
1006 if (value && *value) {
1007 vol->linux_uid =
1008 simple_strtoul(value, &value, 0);
1009 }
1010 } else if (strnicmp(data, "gid", 3) == 0) {
1011 if (value && *value) {
1012 vol->linux_gid =
1013 simple_strtoul(value, &value, 0);
1014 }
1015 } else if (strnicmp(data, "file_mode", 4) == 0) {
1016 if (value && *value) {
1017 vol->file_mode =
1018 simple_strtoul(value, &value, 0);
1019 }
1020 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1021 if (value && *value) {
1022 vol->dir_mode =
1023 simple_strtoul(value, &value, 0);
1024 }
1025 } else if (strnicmp(data, "dirmode", 4) == 0) {
1026 if (value && *value) {
1027 vol->dir_mode =
1028 simple_strtoul(value, &value, 0);
1029 }
1030 } else if (strnicmp(data, "port", 4) == 0) {
1031 if (value && *value) {
1032 vol->port =
1033 simple_strtoul(value, &value, 0);
1034 }
1035 } else if (strnicmp(data, "rsize", 5) == 0) {
1036 if (value && *value) {
1037 vol->rsize =
1038 simple_strtoul(value, &value, 0);
1039 }
1040 } else if (strnicmp(data, "wsize", 5) == 0) {
1041 if (value && *value) {
1042 vol->wsize =
1043 simple_strtoul(value, &value, 0);
1044 }
1045 } else if (strnicmp(data, "sockopt", 5) == 0) {
1046 if (value && *value) {
1047 vol->sockopt =
1048 simple_strtoul(value, &value, 0);
1049 }
1050 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1051 if (!value || !*value || (*value == ' ')) {
1052 cFYI(1,("invalid (empty) netbiosname specified"));
1053 } else {
1054 memset(vol->source_rfc1001_name,0x20,15);
1055 for(i=0;i<15;i++) {
1056 /* BB are there cases in which a comma can be
1057 valid in this workstation netbios name (and need
1058 special handling)? */
1059
1060 /* We do not uppercase netbiosname for user */
1061 if (value[i]==0)
1062 break;
1063 else
1064 vol->source_rfc1001_name[i] = value[i];
1065 }
1066 /* The string has 16th byte zero still from
1067 set at top of the function */
1068 if((i==15) && (value[i] != 0))
1069 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1070 }
1071 } else if (strnicmp(data, "servern", 7) == 0) {
1072 /* servernetbiosname specified override *SMBSERVER */
1073 if (!value || !*value || (*value == ' ')) {
1074 cFYI(1,("empty server netbiosname specified"));
1075 } else {
1076 /* last byte, type, is 0x20 for servr type */
1077 memset(vol->target_rfc1001_name,0x20,16);
1078
1079 for(i=0;i<15;i++) {
1080 /* BB are there cases in which a comma can be
1081 valid in this workstation netbios name (and need
1082 special handling)? */
1083
1084 /* user or mount helper must uppercase netbiosname */
1085 if (value[i]==0)
1086 break;
1087 else
1088 vol->target_rfc1001_name[i] = value[i];
1089 }
1090 /* The string has 16th byte zero still from
1091 set at top of the function */
1092 if((i==15) && (value[i] != 0))
1093 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1094 }
1095 } else if (strnicmp(data, "credentials", 4) == 0) {
1096 /* ignore */
1097 } else if (strnicmp(data, "version", 3) == 0) {
1098 /* ignore */
1099 } else if (strnicmp(data, "guest",5) == 0) {
1100 /* ignore */
1101 } else if (strnicmp(data, "rw", 2) == 0) {
1102 vol->rw = TRUE;
1103 } else if ((strnicmp(data, "suid", 4) == 0) ||
1104 (strnicmp(data, "nosuid", 6) == 0) ||
1105 (strnicmp(data, "exec", 4) == 0) ||
1106 (strnicmp(data, "noexec", 6) == 0) ||
1107 (strnicmp(data, "nodev", 5) == 0) ||
1108 (strnicmp(data, "noauto", 6) == 0) ||
1109 (strnicmp(data, "dev", 3) == 0)) {
1110 /* The mount tool or mount.cifs helper (if present)
1111 uses these opts to set flags, and the flags are read
1112 by the kernel vfs layer before we get here (ie
1113 before read super) so there is no point trying to
1114 parse these options again and set anything and it
1115 is ok to just ignore them */
1116 continue;
1117 } else if (strnicmp(data, "ro", 2) == 0) {
1118 vol->rw = FALSE;
1119 } else if (strnicmp(data, "hard", 4) == 0) {
1120 vol->retry = 1;
1121 } else if (strnicmp(data, "soft", 4) == 0) {
1122 vol->retry = 0;
1123 } else if (strnicmp(data, "perm", 4) == 0) {
1124 vol->noperm = 0;
1125 } else if (strnicmp(data, "noperm", 6) == 0) {
1126 vol->noperm = 1;
1127 } else if (strnicmp(data, "mapchars", 8) == 0) {
1128 vol->remap = 1;
1129 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1130 vol->remap = 0;
1131 } else if (strnicmp(data, "sfu", 3) == 0) {
1132 vol->sfu_emul = 1;
1133 } else if (strnicmp(data, "nosfu", 5) == 0) {
1134 vol->sfu_emul = 0;
1135 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1136 vol->posix_paths = 1;
1137 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1138 vol->posix_paths = 0;
1139 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1140 (strnicmp(data, "ignorecase", 10) == 0)) {
1141 vol->nocase = 1;
1142 } else if (strnicmp(data, "brl", 3) == 0) {
1143 vol->nobrl = 0;
1144 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1145 (strnicmp(data, "nolock", 6) == 0)) {
1146 vol->nobrl = 1;
1147 /* turn off mandatory locking in mode
1148 if remote locking is turned off since the
1149 local vfs will do advisory */
1150 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1151 vol->file_mode = S_IALLUGO;
1152 } else if (strnicmp(data, "setuids", 7) == 0) {
1153 vol->setuids = 1;
1154 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1155 vol->setuids = 0;
1156 } else if (strnicmp(data, "nohard", 6) == 0) {
1157 vol->retry = 0;
1158 } else if (strnicmp(data, "nosoft", 6) == 0) {
1159 vol->retry = 1;
1160 } else if (strnicmp(data, "nointr", 6) == 0) {
1161 vol->intr = 0;
1162 } else if (strnicmp(data, "intr", 4) == 0) {
1163 vol->intr = 1;
1164 } else if (strnicmp(data, "serverino",7) == 0) {
1165 vol->server_ino = 1;
1166 } else if (strnicmp(data, "noserverino",9) == 0) {
1167 vol->server_ino = 0;
1168 } else if (strnicmp(data, "cifsacl",7) == 0) {
1169 vol->cifs_acl = 1;
1170 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1171 vol->cifs_acl = 0;
1172 } else if (strnicmp(data, "acl",3) == 0) {
1173 vol->no_psx_acl = 0;
1174 } else if (strnicmp(data, "noacl",5) == 0) {
1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "sign",4) == 0) {
1177 vol->secFlg |= CIFSSEC_MUST_SIGN;
1178 /* } else if (strnicmp(data, "seal",4) == 0) {
1179 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1180 } else if (strnicmp(data, "direct",6) == 0) {
1181 vol->direct_io = 1;
1182 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1183 vol->direct_io = 1;
1184 } else if (strnicmp(data, "in6_addr",8) == 0) {
1185 if (!value || !*value) {
1186 vol->in6_addr = NULL;
1187 } else if (strnlen(value, 49) == 48) {
1188 vol->in6_addr = value;
1189 } else {
1190 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1191 return 1;
1192 }
1193 } else if (strnicmp(data, "noac", 4) == 0) {
1194 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1195 } else
1196 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1197 }
1198 if (vol->UNC == NULL) {
1199 if(devname == NULL) {
1200 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1201 return 1;
1202 }
1203 if ((temp_len = strnlen(devname, 300)) < 300) {
1204 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1205 if(vol->UNC == NULL)
1206 return 1;
1207 strcpy(vol->UNC,devname);
1208 if (strncmp(vol->UNC, "//", 2) == 0) {
1209 vol->UNC[0] = '\\';
1210 vol->UNC[1] = '\\';
1211 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1212 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1213 return 1;
1214 }
1215 } else {
1216 printk(KERN_WARNING "CIFS: UNC name too long\n");
1217 return 1;
1218 }
1219 }
1220 if(vol->UNCip == NULL)
1221 vol->UNCip = &vol->UNC[2];
1222
1223 return 0;
1224 }
1225
1226 static struct cifsSesInfo *
1227 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1228 struct in6_addr *target_ip6_addr,
1229 char *userName, struct TCP_Server_Info **psrvTcp)
1230 {
1231 struct list_head *tmp;
1232 struct cifsSesInfo *ses;
1233 *psrvTcp = NULL;
1234 read_lock(&GlobalSMBSeslock);
1235
1236 list_for_each(tmp, &GlobalSMBSessionList) {
1237 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1238 if (ses->server) {
1239 if((target_ip_addr &&
1240 (ses->server->addr.sockAddr.sin_addr.s_addr
1241 == target_ip_addr->s_addr)) || (target_ip6_addr
1242 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1243 target_ip6_addr,sizeof(*target_ip6_addr)))){
1244 /* BB lock server and tcp session and increment use count here?? */
1245 *psrvTcp = ses->server; /* found a match on the TCP session */
1246 /* BB check if reconnection needed */
1247 if (strncmp
1248 (ses->userName, userName,
1249 MAX_USERNAME_SIZE) == 0){
1250 read_unlock(&GlobalSMBSeslock);
1251 return ses; /* found exact match on both tcp and SMB sessions */
1252 }
1253 }
1254 }
1255 /* else tcp and smb sessions need reconnection */
1256 }
1257 read_unlock(&GlobalSMBSeslock);
1258 return NULL;
1259 }
1260
1261 static struct cifsTconInfo *
1262 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1263 {
1264 struct list_head *tmp;
1265 struct cifsTconInfo *tcon;
1266
1267 read_lock(&GlobalSMBSeslock);
1268 list_for_each(tmp, &GlobalTreeConnectionList) {
1269 cFYI(1, ("Next tcon - "));
1270 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1271 if (tcon->ses) {
1272 if (tcon->ses->server) {
1273 cFYI(1,
1274 (" old ip addr: %x == new ip %x ?",
1275 tcon->ses->server->addr.sockAddr.sin_addr.
1276 s_addr, new_target_ip_addr));
1277 if (tcon->ses->server->addr.sockAddr.sin_addr.
1278 s_addr == new_target_ip_addr) {
1279 /* BB lock tcon and server and tcp session and increment use count here? */
1280 /* found a match on the TCP session */
1281 /* BB check if reconnection needed */
1282 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1283 tcon->treeName, uncName));
1284 if (strncmp
1285 (tcon->treeName, uncName,
1286 MAX_TREE_SIZE) == 0) {
1287 cFYI(1,
1288 ("Matched UNC, old user: %s == new: %s ?",
1289 tcon->treeName, uncName));
1290 if (strncmp
1291 (tcon->ses->userName,
1292 userName,
1293 MAX_USERNAME_SIZE) == 0) {
1294 read_unlock(&GlobalSMBSeslock);
1295 return tcon;/* also matched user (smb session)*/
1296 }
1297 }
1298 }
1299 }
1300 }
1301 }
1302 read_unlock(&GlobalSMBSeslock);
1303 return NULL;
1304 }
1305
1306 int
1307 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1308 const char *old_path, const struct nls_table *nls_codepage,
1309 int remap)
1310 {
1311 unsigned char *referrals = NULL;
1312 unsigned int num_referrals;
1313 int rc = 0;
1314
1315 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1316 &num_referrals, &referrals, remap);
1317
1318 /* BB Add in code to: if valid refrl, if not ip address contact
1319 the helper that resolves tcp names, mount to it, try to
1320 tcon to it unmount it if fail */
1321
1322 kfree(referrals);
1323
1324 return rc;
1325 }
1326
1327 int
1328 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1329 const char *old_path, const struct nls_table *nls_codepage,
1330 unsigned int *pnum_referrals,
1331 unsigned char ** preferrals, int remap)
1332 {
1333 char *temp_unc;
1334 int rc = 0;
1335
1336 *pnum_referrals = 0;
1337
1338 if (pSesInfo->ipc_tid == 0) {
1339 temp_unc = kmalloc(2 /* for slashes */ +
1340 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1341 + 1 + 4 /* slash IPC$ */ + 2,
1342 GFP_KERNEL);
1343 if (temp_unc == NULL)
1344 return -ENOMEM;
1345 temp_unc[0] = '\\';
1346 temp_unc[1] = '\\';
1347 strcpy(temp_unc + 2, pSesInfo->serverName);
1348 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1349 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1350 cFYI(1,
1351 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1352 kfree(temp_unc);
1353 }
1354 if (rc == 0)
1355 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1356 pnum_referrals, nls_codepage, remap);
1357
1358 return rc;
1359 }
1360
1361 /* See RFC1001 section 14 on representation of Netbios names */
1362 static void rfc1002mangle(char * target,char * source, unsigned int length)
1363 {
1364 unsigned int i,j;
1365
1366 for(i=0,j=0;i<(length);i++) {
1367 /* mask a nibble at a time and encode */
1368 target[j] = 'A' + (0x0F & (source[i] >> 4));
1369 target[j+1] = 'A' + (0x0F & source[i]);
1370 j+=2;
1371 }
1372
1373 }
1374
1375
1376 static int
1377 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1378 char * netbios_name, char * target_name)
1379 {
1380 int rc = 0;
1381 int connected = 0;
1382 __be16 orig_port = 0;
1383
1384 if(*csocket == NULL) {
1385 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1386 if (rc < 0) {
1387 cERROR(1, ("Error %d creating socket",rc));
1388 *csocket = NULL;
1389 return rc;
1390 } else {
1391 /* BB other socket options to set KEEPALIVE, NODELAY? */
1392 cFYI(1,("Socket created"));
1393 (*csocket)->sk->sk_allocation = GFP_NOFS;
1394 }
1395 }
1396
1397 psin_server->sin_family = AF_INET;
1398 if(psin_server->sin_port) { /* user overrode default port */
1399 rc = (*csocket)->ops->connect(*csocket,
1400 (struct sockaddr *) psin_server,
1401 sizeof (struct sockaddr_in),0);
1402 if (rc >= 0)
1403 connected = 1;
1404 }
1405
1406 if(!connected) {
1407 /* save original port so we can retry user specified port
1408 later if fall back ports fail this time */
1409 orig_port = psin_server->sin_port;
1410
1411 /* do not retry on the same port we just failed on */
1412 if(psin_server->sin_port != htons(CIFS_PORT)) {
1413 psin_server->sin_port = htons(CIFS_PORT);
1414
1415 rc = (*csocket)->ops->connect(*csocket,
1416 (struct sockaddr *) psin_server,
1417 sizeof (struct sockaddr_in),0);
1418 if (rc >= 0)
1419 connected = 1;
1420 }
1421 }
1422 if (!connected) {
1423 psin_server->sin_port = htons(RFC1001_PORT);
1424 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1425 psin_server, sizeof (struct sockaddr_in),0);
1426 if (rc >= 0)
1427 connected = 1;
1428 }
1429
1430 /* give up here - unless we want to retry on different
1431 protocol families some day */
1432 if (!connected) {
1433 if(orig_port)
1434 psin_server->sin_port = orig_port;
1435 cFYI(1,("Error %d connecting to server via ipv4",rc));
1436 sock_release(*csocket);
1437 *csocket = NULL;
1438 return rc;
1439 }
1440 /* Eventually check for other socket options to change from
1441 the default. sock_setsockopt not used because it expects
1442 user space buffer */
1443 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1444 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1445 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1446 /* make the bufsizes depend on wsize/rsize and max requests */
1447 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1448 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1449 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1450 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1451
1452 /* send RFC1001 sessinit */
1453 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1454 /* some servers require RFC1001 sessinit before sending
1455 negprot - BB check reconnection in case where second
1456 sessinit is sent but no second negprot */
1457 struct rfc1002_session_packet * ses_init_buf;
1458 struct smb_hdr * smb_buf;
1459 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1460 if(ses_init_buf) {
1461 ses_init_buf->trailer.session_req.called_len = 32;
1462 if(target_name && (target_name[0] != 0)) {
1463 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1464 target_name, 16);
1465 } else {
1466 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1467 DEFAULT_CIFS_CALLED_NAME,16);
1468 }
1469
1470 ses_init_buf->trailer.session_req.calling_len = 32;
1471 /* calling name ends in null (byte 16) from old smb
1472 convention. */
1473 if(netbios_name && (netbios_name[0] !=0)) {
1474 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1475 netbios_name,16);
1476 } else {
1477 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1478 "LINUX_CIFS_CLNT",16);
1479 }
1480 ses_init_buf->trailer.session_req.scope1 = 0;
1481 ses_init_buf->trailer.session_req.scope2 = 0;
1482 smb_buf = (struct smb_hdr *)ses_init_buf;
1483 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1484 smb_buf->smb_buf_length = 0x81000044;
1485 rc = smb_send(*csocket, smb_buf, 0x44,
1486 (struct sockaddr *)psin_server);
1487 kfree(ses_init_buf);
1488 msleep(1); /* RFC1001 layer in at least one server
1489 requires very short break before negprot
1490 presumably because not expecting negprot
1491 to follow so fast. This is a simple
1492 solution that works without
1493 complicating the code and causes no
1494 significant slowing down on mount
1495 for everyone else */
1496 }
1497 /* else the negprot may still work without this
1498 even though malloc failed */
1499
1500 }
1501
1502 return rc;
1503 }
1504
1505 static int
1506 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1507 {
1508 int rc = 0;
1509 int connected = 0;
1510 __be16 orig_port = 0;
1511
1512 if(*csocket == NULL) {
1513 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1514 if (rc < 0) {
1515 cERROR(1, ("Error %d creating ipv6 socket",rc));
1516 *csocket = NULL;
1517 return rc;
1518 } else {
1519 /* BB other socket options to set KEEPALIVE, NODELAY? */
1520 cFYI(1,("ipv6 Socket created"));
1521 (*csocket)->sk->sk_allocation = GFP_NOFS;
1522 }
1523 }
1524
1525 psin_server->sin6_family = AF_INET6;
1526
1527 if(psin_server->sin6_port) { /* user overrode default port */
1528 rc = (*csocket)->ops->connect(*csocket,
1529 (struct sockaddr *) psin_server,
1530 sizeof (struct sockaddr_in6),0);
1531 if (rc >= 0)
1532 connected = 1;
1533 }
1534
1535 if(!connected) {
1536 /* save original port so we can retry user specified port
1537 later if fall back ports fail this time */
1538
1539 orig_port = psin_server->sin6_port;
1540 /* do not retry on the same port we just failed on */
1541 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1542 psin_server->sin6_port = htons(CIFS_PORT);
1543
1544 rc = (*csocket)->ops->connect(*csocket,
1545 (struct sockaddr *) psin_server,
1546 sizeof (struct sockaddr_in6),0);
1547 if (rc >= 0)
1548 connected = 1;
1549 }
1550 }
1551 if (!connected) {
1552 psin_server->sin6_port = htons(RFC1001_PORT);
1553 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1554 psin_server, sizeof (struct sockaddr_in6),0);
1555 if (rc >= 0)
1556 connected = 1;
1557 }
1558
1559 /* give up here - unless we want to retry on different
1560 protocol families some day */
1561 if (!connected) {
1562 if(orig_port)
1563 psin_server->sin6_port = orig_port;
1564 cFYI(1,("Error %d connecting to server via ipv6",rc));
1565 sock_release(*csocket);
1566 *csocket = NULL;
1567 return rc;
1568 }
1569 /* Eventually check for other socket options to change from
1570 the default. sock_setsockopt not used because it expects
1571 user space buffer */
1572 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1573
1574 return rc;
1575 }
1576
1577 int
1578 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1579 char *mount_data, const char *devname)
1580 {
1581 int rc = 0;
1582 int xid;
1583 int address_type = AF_INET;
1584 struct socket *csocket = NULL;
1585 struct sockaddr_in sin_server;
1586 struct sockaddr_in6 sin_server6;
1587 struct smb_vol volume_info;
1588 struct cifsSesInfo *pSesInfo = NULL;
1589 struct cifsSesInfo *existingCifsSes = NULL;
1590 struct cifsTconInfo *tcon = NULL;
1591 struct TCP_Server_Info *srvTcp = NULL;
1592
1593 xid = GetXid();
1594
1595 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1596
1597 memset(&volume_info,0,sizeof(struct smb_vol));
1598 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1599 kfree(volume_info.UNC);
1600 kfree(volume_info.password);
1601 FreeXid(xid);
1602 return -EINVAL;
1603 }
1604
1605 if (volume_info.username) {
1606 /* BB fixme parse for domain name here */
1607 cFYI(1, ("Username: %s ", volume_info.username));
1608
1609 } else {
1610 cifserror("No username specified");
1611 /* In userspace mount helper we can get user name from alternate
1612 locations such as env variables and files on disk */
1613 kfree(volume_info.UNC);
1614 kfree(volume_info.password);
1615 FreeXid(xid);
1616 return -EINVAL;
1617 }
1618
1619 if (volume_info.UNCip && volume_info.UNC) {
1620 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1621
1622 if(rc <= 0) {
1623 /* not ipv4 address, try ipv6 */
1624 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1625 if(rc > 0)
1626 address_type = AF_INET6;
1627 } else {
1628 address_type = AF_INET;
1629 }
1630
1631 if(rc <= 0) {
1632 /* we failed translating address */
1633 kfree(volume_info.UNC);
1634 kfree(volume_info.password);
1635 FreeXid(xid);
1636 return -EINVAL;
1637 }
1638
1639 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1640 /* success */
1641 rc = 0;
1642 } else if (volume_info.UNCip){
1643 /* BB using ip addr as server name connect to the DFS root below */
1644 cERROR(1,("Connecting to DFS root not implemented yet"));
1645 kfree(volume_info.UNC);
1646 kfree(volume_info.password);
1647 FreeXid(xid);
1648 return -EINVAL;
1649 } else /* which servers DFS root would we conect to */ {
1650 cERROR(1,
1651 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1652 kfree(volume_info.UNC);
1653 kfree(volume_info.password);
1654 FreeXid(xid);
1655 return -EINVAL;
1656 }
1657
1658 /* this is needed for ASCII cp to Unicode converts */
1659 if(volume_info.iocharset == NULL) {
1660 cifs_sb->local_nls = load_nls_default();
1661 /* load_nls_default can not return null */
1662 } else {
1663 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1664 if(cifs_sb->local_nls == NULL) {
1665 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1666 kfree(volume_info.UNC);
1667 kfree(volume_info.password);
1668 FreeXid(xid);
1669 return -ELIBACC;
1670 }
1671 }
1672
1673 if(address_type == AF_INET)
1674 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1675 NULL /* no ipv6 addr */,
1676 volume_info.username, &srvTcp);
1677 else if(address_type == AF_INET6)
1678 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1679 &sin_server6.sin6_addr,
1680 volume_info.username, &srvTcp);
1681 else {
1682 kfree(volume_info.UNC);
1683 kfree(volume_info.password);
1684 FreeXid(xid);
1685 return -EINVAL;
1686 }
1687
1688
1689 if (srvTcp) {
1690 cFYI(1, ("Existing tcp session with server found"));
1691 } else { /* create socket */
1692 if(volume_info.port)
1693 sin_server.sin_port = htons(volume_info.port);
1694 else
1695 sin_server.sin_port = 0;
1696 rc = ipv4_connect(&sin_server,&csocket,
1697 volume_info.source_rfc1001_name,
1698 volume_info.target_rfc1001_name);
1699 if (rc < 0) {
1700 cERROR(1,
1701 ("Error connecting to IPv4 socket. Aborting operation"));
1702 if(csocket != NULL)
1703 sock_release(csocket);
1704 kfree(volume_info.UNC);
1705 kfree(volume_info.password);
1706 FreeXid(xid);
1707 return rc;
1708 }
1709
1710 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1711 if (srvTcp == NULL) {
1712 rc = -ENOMEM;
1713 sock_release(csocket);
1714 kfree(volume_info.UNC);
1715 kfree(volume_info.password);
1716 FreeXid(xid);
1717 return rc;
1718 } else {
1719 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1720 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1721 atomic_set(&srvTcp->inFlight,0);
1722 /* BB Add code for ipv6 case too */
1723 srvTcp->ssocket = csocket;
1724 srvTcp->protocolType = IPV4;
1725 init_waitqueue_head(&srvTcp->response_q);
1726 init_waitqueue_head(&srvTcp->request_q);
1727 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1728 /* at this point we are the only ones with the pointer
1729 to the struct since the kernel thread not created yet
1730 so no need to spinlock this init of tcpStatus */
1731 srvTcp->tcpStatus = CifsNew;
1732 init_MUTEX(&srvTcp->tcpSem);
1733 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1734 CLONE_FS | CLONE_FILES | CLONE_VM);
1735 if(rc < 0) {
1736 rc = -ENOMEM;
1737 sock_release(csocket);
1738 kfree(volume_info.UNC);
1739 kfree(volume_info.password);
1740 FreeXid(xid);
1741 return rc;
1742 }
1743 wait_for_completion(&cifsd_complete);
1744 rc = 0;
1745 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1746 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1747 srvTcp->sequence_number = 0;
1748 }
1749 }
1750
1751 if (existingCifsSes) {
1752 pSesInfo = existingCifsSes;
1753 cFYI(1, ("Existing smb sess found"));
1754 kfree(volume_info.password);
1755 /* volume_info.UNC freed at end of function */
1756 } else if (!rc) {
1757 cFYI(1, ("Existing smb sess not found"));
1758 pSesInfo = sesInfoAlloc();
1759 if (pSesInfo == NULL)
1760 rc = -ENOMEM;
1761 else {
1762 pSesInfo->server = srvTcp;
1763 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1764 NIPQUAD(sin_server.sin_addr.s_addr));
1765 }
1766
1767 if (!rc){
1768 /* volume_info.password freed at unmount */
1769 if (volume_info.password)
1770 pSesInfo->password = volume_info.password;
1771 if (volume_info.username)
1772 strncpy(pSesInfo->userName,
1773 volume_info.username,MAX_USERNAME_SIZE);
1774 if (volume_info.domainname) {
1775 int len = strlen(volume_info.domainname);
1776 pSesInfo->domainName =
1777 kmalloc(len + 1, GFP_KERNEL);
1778 if(pSesInfo->domainName)
1779 strcpy(pSesInfo->domainName,
1780 volume_info.domainname);
1781 }
1782 pSesInfo->linux_uid = volume_info.linux_uid;
1783 pSesInfo->overrideSecFlg = volume_info.secFlg;
1784 down(&pSesInfo->sesSem);
1785 /* BB FIXME need to pass vol->secFlgs BB */
1786 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1787 up(&pSesInfo->sesSem);
1788 if(!rc)
1789 atomic_inc(&srvTcp->socketUseCount);
1790 } else
1791 kfree(volume_info.password);
1792 }
1793
1794 /* search for existing tcon to this server share */
1795 if (!rc) {
1796 if(volume_info.rsize > CIFSMaxBufSize) {
1797 cERROR(1,("rsize %d too large, using MaxBufSize",
1798 volume_info.rsize));
1799 cifs_sb->rsize = CIFSMaxBufSize;
1800 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1801 cifs_sb->rsize = volume_info.rsize;
1802 else /* default */
1803 cifs_sb->rsize = CIFSMaxBufSize;
1804
1805 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1806 cERROR(1,("wsize %d too large using 4096 instead",
1807 volume_info.wsize));
1808 cifs_sb->wsize = 4096;
1809 } else if(volume_info.wsize)
1810 cifs_sb->wsize = volume_info.wsize;
1811 else
1812 cifs_sb->wsize =
1813 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1814 127*1024);
1815 /* old default of CIFSMaxBufSize was too small now
1816 that SMB Write2 can send multiple pages in kvec.
1817 RFC1001 does not describe what happens when frame
1818 bigger than 128K is sent so use that as max in
1819 conjunction with 52K kvec constraint on arch with 4K
1820 page size */
1821
1822 if(cifs_sb->rsize < 2048) {
1823 cifs_sb->rsize = 2048;
1824 /* Windows ME may prefer this */
1825 cFYI(1,("readsize set to minimum 2048"));
1826 }
1827 cifs_sb->mnt_uid = volume_info.linux_uid;
1828 cifs_sb->mnt_gid = volume_info.linux_gid;
1829 cifs_sb->mnt_file_mode = volume_info.file_mode;
1830 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1831 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1832 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1833
1834 if(volume_info.noperm)
1835 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1836 if(volume_info.setuids)
1837 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1838 if(volume_info.server_ino)
1839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1840 if(volume_info.remap)
1841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1842 if(volume_info.no_xattr)
1843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1844 if(volume_info.sfu_emul)
1845 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1846 if(volume_info.nobrl)
1847 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1848 if(volume_info.cifs_acl)
1849 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1850
1851 if(volume_info.direct_io) {
1852 cFYI(1,("mounting share using direct i/o"));
1853 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1854 }
1855
1856 tcon =
1857 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1858 volume_info.username);
1859 if (tcon) {
1860 cFYI(1, ("Found match on UNC path"));
1861 /* we can have only one retry value for a connection
1862 to a share so for resources mounted more than once
1863 to the same server share the last value passed in
1864 for the retry flag is used */
1865 tcon->retry = volume_info.retry;
1866 tcon->nocase = volume_info.nocase;
1867 } else {
1868 tcon = tconInfoAlloc();
1869 if (tcon == NULL)
1870 rc = -ENOMEM;
1871 else {
1872 /* check for null share name ie connect to dfs root */
1873
1874 /* BB check if this works for exactly length three strings */
1875 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1876 && (strchr(volume_info.UNC + 3, '/') ==
1877 NULL)) {
1878 rc = connect_to_dfs_path(xid, pSesInfo,
1879 "", cifs_sb->local_nls,
1880 cifs_sb->mnt_cifs_flags &
1881 CIFS_MOUNT_MAP_SPECIAL_CHR);
1882 kfree(volume_info.UNC);
1883 FreeXid(xid);
1884 return -ENODEV;
1885 } else {
1886 rc = CIFSTCon(xid, pSesInfo,
1887 volume_info.UNC,
1888 tcon, cifs_sb->local_nls);
1889 cFYI(1, ("CIFS Tcon rc = %d", rc));
1890 }
1891 if (!rc) {
1892 atomic_inc(&pSesInfo->inUse);
1893 tcon->retry = volume_info.retry;
1894 tcon->nocase = volume_info.nocase;
1895 }
1896 }
1897 }
1898 }
1899 if(pSesInfo) {
1900 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1901 sb->s_maxbytes = (u64) 1 << 63;
1902 } else
1903 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1904 }
1905
1906 sb->s_time_gran = 100;
1907
1908 /* on error free sesinfo and tcon struct if needed */
1909 if (rc) {
1910 /* if session setup failed, use count is zero but
1911 we still need to free cifsd thread */
1912 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1913 spin_lock(&GlobalMid_Lock);
1914 srvTcp->tcpStatus = CifsExiting;
1915 spin_unlock(&GlobalMid_Lock);
1916 if(srvTcp->tsk) {
1917 send_sig(SIGKILL,srvTcp->tsk,1);
1918 wait_for_completion(&cifsd_complete);
1919 }
1920 }
1921 /* If find_unc succeeded then rc == 0 so we can not end */
1922 if (tcon) /* up accidently freeing someone elses tcon struct */
1923 tconInfoFree(tcon);
1924 if (existingCifsSes == NULL) {
1925 if (pSesInfo) {
1926 if ((pSesInfo->server) &&
1927 (pSesInfo->status == CifsGood)) {
1928 int temp_rc;
1929 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1930 /* if the socketUseCount is now zero */
1931 if((temp_rc == -ESHUTDOWN) &&
1932 (pSesInfo->server->tsk)) {
1933 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1934 wait_for_completion(&cifsd_complete);
1935 }
1936 } else
1937 cFYI(1, ("No session or bad tcon"));
1938 sesInfoFree(pSesInfo);
1939 /* pSesInfo = NULL; */
1940 }
1941 }
1942 } else {
1943 atomic_inc(&tcon->useCount);
1944 cifs_sb->tcon = tcon;
1945 tcon->ses = pSesInfo;
1946
1947 /* do not care if following two calls succeed - informational */
1948 CIFSSMBQFSDeviceInfo(xid, tcon);
1949 CIFSSMBQFSAttributeInfo(xid, tcon);
1950
1951 if (tcon->ses->capabilities & CAP_UNIX) {
1952 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1953 __u64 cap =
1954 le64_to_cpu(tcon->fsUnixInfo.Capability);
1955 cap &= CIFS_UNIX_CAP_MASK;
1956 if(volume_info.no_psx_acl)
1957 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1958 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1959 cFYI(1,("negotiated posix acl support"));
1960 sb->s_flags |= MS_POSIXACL;
1961 }
1962
1963 if(volume_info.posix_paths == 0)
1964 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1965 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1966 cFYI(1,("negotiate posix pathnames"));
1967 cifs_sb->mnt_cifs_flags |=
1968 CIFS_MOUNT_POSIX_PATHS;
1969 }
1970
1971 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1972
1973 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1974 cFYI(1,("setting capabilities failed"));
1975 }
1976 }
1977 }
1978 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1979 cifs_sb->wsize = min(cifs_sb->wsize,
1980 (tcon->ses->server->maxBuf -
1981 MAX_CIFS_HDR_SIZE));
1982 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1983 cifs_sb->rsize = min(cifs_sb->rsize,
1984 (tcon->ses->server->maxBuf -
1985 MAX_CIFS_HDR_SIZE));
1986 }
1987
1988 /* volume_info.password is freed above when existing session found
1989 (in which case it is not needed anymore) but when new sesion is created
1990 the password ptr is put in the new session structure (in which case the
1991 password will be freed at unmount time) */
1992 kfree(volume_info.UNC);
1993 FreeXid(xid);
1994 return rc;
1995 }
1996
1997 static int
1998 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1999 char session_key[CIFS_SESS_KEY_SIZE],
2000 const struct nls_table *nls_codepage)
2001 {
2002 struct smb_hdr *smb_buffer;
2003 struct smb_hdr *smb_buffer_response;
2004 SESSION_SETUP_ANDX *pSMB;
2005 SESSION_SETUP_ANDX *pSMBr;
2006 char *bcc_ptr;
2007 char *user;
2008 char *domain;
2009 int rc = 0;
2010 int remaining_words = 0;
2011 int bytes_returned = 0;
2012 int len;
2013 __u32 capabilities;
2014 __u16 count;
2015
2016 cFYI(1, ("In sesssetup"));
2017 if(ses == NULL)
2018 return -EINVAL;
2019 user = ses->userName;
2020 domain = ses->domainName;
2021 smb_buffer = cifs_buf_get();
2022 if (smb_buffer == NULL) {
2023 return -ENOMEM;
2024 }
2025 smb_buffer_response = smb_buffer;
2026 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2027
2028 /* send SMBsessionSetup here */
2029 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2030 NULL /* no tCon exists yet */ , 13 /* wct */ );
2031
2032 smb_buffer->Mid = GetNextMid(ses->server);
2033 pSMB->req_no_secext.AndXCommand = 0xFF;
2034 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2035 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2036
2037 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2038 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2039
2040 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2041 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2042 if (ses->capabilities & CAP_UNICODE) {
2043 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2044 capabilities |= CAP_UNICODE;
2045 }
2046 if (ses->capabilities & CAP_STATUS32) {
2047 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2048 capabilities |= CAP_STATUS32;
2049 }
2050 if (ses->capabilities & CAP_DFS) {
2051 smb_buffer->Flags2 |= SMBFLG2_DFS;
2052 capabilities |= CAP_DFS;
2053 }
2054 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2055
2056 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2057 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2058
2059 pSMB->req_no_secext.CaseSensitivePasswordLength =
2060 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2061 bcc_ptr = pByteArea(smb_buffer);
2062 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2063 bcc_ptr += CIFS_SESS_KEY_SIZE;
2064 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2065 bcc_ptr += CIFS_SESS_KEY_SIZE;
2066
2067 if (ses->capabilities & CAP_UNICODE) {
2068 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2069 *bcc_ptr = 0;
2070 bcc_ptr++;
2071 }
2072 if(user == NULL)
2073 bytes_returned = 0; /* skip null user */
2074 else
2075 bytes_returned =
2076 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2077 nls_codepage);
2078 /* convert number of 16 bit words to bytes */
2079 bcc_ptr += 2 * bytes_returned;
2080 bcc_ptr += 2; /* trailing null */
2081 if (domain == NULL)
2082 bytes_returned =
2083 cifs_strtoUCS((__le16 *) bcc_ptr,
2084 "CIFS_LINUX_DOM", 32, nls_codepage);
2085 else
2086 bytes_returned =
2087 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2088 nls_codepage);
2089 bcc_ptr += 2 * bytes_returned;
2090 bcc_ptr += 2;
2091 bytes_returned =
2092 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2093 32, nls_codepage);
2094 bcc_ptr += 2 * bytes_returned;
2095 bytes_returned =
2096 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2097 32, nls_codepage);
2098 bcc_ptr += 2 * bytes_returned;
2099 bcc_ptr += 2;
2100 bytes_returned =
2101 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2102 64, nls_codepage);
2103 bcc_ptr += 2 * bytes_returned;
2104 bcc_ptr += 2;
2105 } else {
2106 if(user != NULL) {
2107 strncpy(bcc_ptr, user, 200);
2108 bcc_ptr += strnlen(user, 200);
2109 }
2110 *bcc_ptr = 0;
2111 bcc_ptr++;
2112 if (domain == NULL) {
2113 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2114 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2115 } else {
2116 strncpy(bcc_ptr, domain, 64);
2117 bcc_ptr += strnlen(domain, 64);
2118 *bcc_ptr = 0;
2119 bcc_ptr++;
2120 }
2121 strcpy(bcc_ptr, "Linux version ");
2122 bcc_ptr += strlen("Linux version ");
2123 strcpy(bcc_ptr, system_utsname.release);
2124 bcc_ptr += strlen(system_utsname.release) + 1;
2125 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2126 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2127 }
2128 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2129 smb_buffer->smb_buf_length += count;
2130 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2131
2132 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2133 &bytes_returned, 1);
2134 if (rc) {
2135 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2136 } else if ((smb_buffer_response->WordCount == 3)
2137 || (smb_buffer_response->WordCount == 4)) {
2138 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2139 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2140 if (action & GUEST_LOGIN)
2141 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2142 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2143 cFYI(1, ("UID = %d ", ses->Suid));
2144 /* response can have either 3 or 4 word count - Samba sends 3 */
2145 bcc_ptr = pByteArea(smb_buffer_response);
2146 if ((pSMBr->resp.hdr.WordCount == 3)
2147 || ((pSMBr->resp.hdr.WordCount == 4)
2148 && (blob_len < pSMBr->resp.ByteCount))) {
2149 if (pSMBr->resp.hdr.WordCount == 4)
2150 bcc_ptr += blob_len;
2151
2152 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2153 if ((long) (bcc_ptr) % 2) {
2154 remaining_words =
2155 (BCC(smb_buffer_response) - 1) /2;
2156 bcc_ptr++; /* Unicode strings must be word aligned */
2157 } else {
2158 remaining_words =
2159 BCC(smb_buffer_response) / 2;
2160 }
2161 len =
2162 UniStrnlen((wchar_t *) bcc_ptr,
2163 remaining_words - 1);
2164 /* We look for obvious messed up bcc or strings in response so we do not go off
2165 the end since (at least) WIN2K and Windows XP have a major bug in not null
2166 terminating last Unicode string in response */
2167 if(ses->serverOS)
2168 kfree(ses->serverOS);
2169 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
2170 if(ses->serverOS == NULL)
2171 goto sesssetup_nomem;
2172 cifs_strfromUCS_le(ses->serverOS,
2173 (__le16 *)bcc_ptr, len,nls_codepage);
2174 bcc_ptr += 2 * (len + 1);
2175 remaining_words -= len + 1;
2176 ses->serverOS[2 * len] = 0;
2177 ses->serverOS[1 + (2 * len)] = 0;
2178 if (remaining_words > 0) {
2179 len = UniStrnlen((wchar_t *)bcc_ptr,
2180 remaining_words-1);
2181 kfree(ses->serverNOS);
2182 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2183 if(ses->serverNOS == NULL)
2184 goto sesssetup_nomem;
2185 cifs_strfromUCS_le(ses->serverNOS,
2186 (__le16 *)bcc_ptr,len,nls_codepage);
2187 bcc_ptr += 2 * (len + 1);
2188 ses->serverNOS[2 * len] = 0;
2189 ses->serverNOS[1 + (2 * len)] = 0;
2190 if(strncmp(ses->serverNOS,
2191 "NT LAN Manager 4",16) == 0) {
2192 cFYI(1,("NT4 server"));
2193 ses->flags |= CIFS_SES_NT4;
2194 }
2195 remaining_words -= len + 1;
2196 if (remaining_words > 0) {
2197 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2198 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2199 if(ses->serverDomain)
2200 kfree(ses->serverDomain);
2201 ses->serverDomain =
2202 kzalloc(2*(len+1),GFP_KERNEL);
2203 if(ses->serverDomain == NULL)
2204 goto sesssetup_nomem;
2205 cifs_strfromUCS_le(ses->serverDomain,
2206 (__le16 *)bcc_ptr,len,nls_codepage);
2207 bcc_ptr += 2 * (len + 1);
2208 ses->serverDomain[2*len] = 0;
2209 ses->serverDomain[1+(2*len)] = 0;
2210 } /* else no more room so create dummy domain string */
2211 else {
2212 if(ses->serverDomain)
2213 kfree(ses->serverDomain);
2214 ses->serverDomain =
2215 kzalloc(2, GFP_KERNEL);
2216 }
2217 } else { /* no room so create dummy domain and NOS string */
2218 /* if these kcallocs fail not much we
2219 can do, but better to not fail the
2220 sesssetup itself */
2221 kfree(ses->serverDomain);
2222 ses->serverDomain =
2223 kzalloc(2, GFP_KERNEL);
2224 kfree(ses->serverNOS);
2225 ses->serverNOS =
2226 kzalloc(2, GFP_KERNEL);
2227 }
2228 } else { /* ASCII */
2229 len = strnlen(bcc_ptr, 1024);
2230 if (((long) bcc_ptr + len) - (long)
2231 pByteArea(smb_buffer_response)
2232 <= BCC(smb_buffer_response)) {
2233 kfree(ses->serverOS);
2234 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2235 if(ses->serverOS == NULL)
2236 goto sesssetup_nomem;
2237 strncpy(ses->serverOS,bcc_ptr, len);
2238
2239 bcc_ptr += len;
2240 bcc_ptr[0] = 0; /* null terminate the string */
2241 bcc_ptr++;
2242
2243 len = strnlen(bcc_ptr, 1024);
2244 kfree(ses->serverNOS);
2245 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2246 if(ses->serverNOS == NULL)
2247 goto sesssetup_nomem;
2248 strncpy(ses->serverNOS, bcc_ptr, len);
2249 bcc_ptr += len;
2250 bcc_ptr[0] = 0;
2251 bcc_ptr++;
2252
2253 len = strnlen(bcc_ptr, 1024);
2254 if(ses->serverDomain)
2255 kfree(ses->serverDomain);
2256 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
2257 if(ses->serverDomain == NULL)
2258 goto sesssetup_nomem;
2259 strncpy(ses->serverDomain, bcc_ptr, len);
2260 bcc_ptr += len;
2261 bcc_ptr[0] = 0;
2262 bcc_ptr++;
2263 } else
2264 cFYI(1,
2265 ("Variable field of length %d extends beyond end of smb ",
2266 len));
2267 }
2268 } else {
2269 cERROR(1,
2270 (" Security Blob Length extends beyond end of SMB"));
2271 }
2272 } else {
2273 cERROR(1,
2274 (" Invalid Word count %d: ",
2275 smb_buffer_response->WordCount));
2276 rc = -EIO;
2277 }
2278 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2279 since that could make reconnection harder, and
2280 reconnection might be needed to free memory */
2281 if (smb_buffer)
2282 cifs_buf_release(smb_buffer);
2283
2284 return rc;
2285 }
2286
2287 static int
2288 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2289 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2290 const struct nls_table *nls_codepage)
2291 {
2292 struct smb_hdr *smb_buffer;
2293 struct smb_hdr *smb_buffer_response;
2294 SESSION_SETUP_ANDX *pSMB;
2295 SESSION_SETUP_ANDX *pSMBr;
2296 char *bcc_ptr;
2297 char *domain;
2298 int rc = 0;
2299 int remaining_words = 0;
2300 int bytes_returned = 0;
2301 int len;
2302 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2303 PNEGOTIATE_MESSAGE SecurityBlob;
2304 PCHALLENGE_MESSAGE SecurityBlob2;
2305 __u32 negotiate_flags, capabilities;
2306 __u16 count;
2307
2308 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2309 if(ses == NULL)
2310 return -EINVAL;
2311 domain = ses->domainName;
2312 *pNTLMv2_flag = FALSE;
2313 smb_buffer = cifs_buf_get();
2314 if (smb_buffer == NULL) {
2315 return -ENOMEM;
2316 }
2317 smb_buffer_response = smb_buffer;
2318 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2319 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2320
2321 /* send SMBsessionSetup here */
2322 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2323 NULL /* no tCon exists yet */ , 12 /* wct */ );
2324
2325 smb_buffer->Mid = GetNextMid(ses->server);
2326 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2327 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2328
2329 pSMB->req.AndXCommand = 0xFF;
2330 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2331 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2332
2333 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2334 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2335
2336 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2337 CAP_EXTENDED_SECURITY;
2338 if (ses->capabilities & CAP_UNICODE) {
2339 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2340 capabilities |= CAP_UNICODE;
2341 }
2342 if (ses->capabilities & CAP_STATUS32) {
2343 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2344 capabilities |= CAP_STATUS32;
2345 }
2346 if (ses->capabilities & CAP_DFS) {
2347 smb_buffer->Flags2 |= SMBFLG2_DFS;
2348 capabilities |= CAP_DFS;
2349 }
2350 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2351
2352 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2353 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2354 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2355 SecurityBlob->MessageType = NtLmNegotiate;
2356 negotiate_flags =
2357 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2358 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2359 NTLMSSP_NEGOTIATE_56 |
2360 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2361 if(sign_CIFS_PDUs)
2362 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2363 /* if(ntlmv2_support)
2364 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2365 /* setup pointers to domain name and workstation name */
2366 bcc_ptr += SecurityBlobLength;
2367
2368 SecurityBlob->WorkstationName.Buffer = 0;
2369 SecurityBlob->WorkstationName.Length = 0;
2370 SecurityBlob->WorkstationName.MaximumLength = 0;
2371
2372 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2373 along with username on auth request (ie the response to challenge) */
2374 SecurityBlob->DomainName.Buffer = 0;
2375 SecurityBlob->DomainName.Length = 0;
2376 SecurityBlob->DomainName.MaximumLength = 0;
2377 if (ses->capabilities & CAP_UNICODE) {
2378 if ((long) bcc_ptr % 2) {
2379 *bcc_ptr = 0;
2380 bcc_ptr++;
2381 }
2382
2383 bytes_returned =
2384 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2385 32, nls_codepage);
2386 bcc_ptr += 2 * bytes_returned;
2387 bytes_returned =
2388 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2389 nls_codepage);
2390 bcc_ptr += 2 * bytes_returned;
2391 bcc_ptr += 2; /* null terminate Linux version */
2392 bytes_returned =
2393 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2394 64, nls_codepage);
2395 bcc_ptr += 2 * bytes_returned;
2396 *(bcc_ptr + 1) = 0;
2397 *(bcc_ptr + 2) = 0;
2398 bcc_ptr += 2; /* null terminate network opsys string */
2399 *(bcc_ptr + 1) = 0;
2400 *(bcc_ptr + 2) = 0;
2401 bcc_ptr += 2; /* null domain */
2402 } else { /* ASCII */
2403 strcpy(bcc_ptr, "Linux version ");
2404 bcc_ptr += strlen("Linux version ");
2405 strcpy(bcc_ptr, system_utsname.release);
2406 bcc_ptr += strlen(system_utsname.release) + 1;
2407 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2408 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2409 bcc_ptr++; /* empty domain field */
2410 *bcc_ptr = 0;
2411 }
2412 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2413 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2414 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2415 smb_buffer->smb_buf_length += count;
2416 pSMB->req.ByteCount = cpu_to_le16(count);
2417
2418 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2419 &bytes_returned, 1);
2420
2421 if (smb_buffer_response->Status.CifsError ==
2422 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2423 rc = 0;
2424
2425 if (rc) {
2426 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2427 } else if ((smb_buffer_response->WordCount == 3)
2428 || (smb_buffer_response->WordCount == 4)) {
2429 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2430 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2431
2432 if (action & GUEST_LOGIN)
2433 cFYI(1, (" Guest login"));
2434 /* Do we want to set anything in SesInfo struct when guest login? */
2435
2436 bcc_ptr = pByteArea(smb_buffer_response);
2437 /* response can have either 3 or 4 word count - Samba sends 3 */
2438
2439 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2440 if (SecurityBlob2->MessageType != NtLmChallenge) {
2441 cFYI(1,
2442 ("Unexpected NTLMSSP message type received %d",
2443 SecurityBlob2->MessageType));
2444 } else if (ses) {
2445 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2446 cFYI(1, ("UID = %d", ses->Suid));
2447 if ((pSMBr->resp.hdr.WordCount == 3)
2448 || ((pSMBr->resp.hdr.WordCount == 4)
2449 && (blob_len <
2450 pSMBr->resp.ByteCount))) {
2451
2452 if (pSMBr->resp.hdr.WordCount == 4) {
2453 bcc_ptr += blob_len;
2454 cFYI(1, ("Security Blob Length %d",
2455 blob_len));
2456 }
2457
2458 cFYI(1, ("NTLMSSP Challenge rcvd"));
2459
2460 memcpy(ses->server->cryptKey,
2461 SecurityBlob2->Challenge,
2462 CIFS_CRYPTO_KEY_SIZE);
2463 if(SecurityBlob2->NegotiateFlags &
2464 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2465 *pNTLMv2_flag = TRUE;
2466
2467 if((SecurityBlob2->NegotiateFlags &
2468 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2469 || (sign_CIFS_PDUs > 1))
2470 ses->server->secMode |=
2471 SECMODE_SIGN_REQUIRED;
2472 if ((SecurityBlob2->NegotiateFlags &
2473 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2474 ses->server->secMode |=
2475 SECMODE_SIGN_ENABLED;
2476
2477 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2478 if ((long) (bcc_ptr) % 2) {
2479 remaining_words =
2480 (BCC(smb_buffer_response)
2481 - 1) / 2;
2482 bcc_ptr++; /* Unicode strings must be word aligned */
2483 } else {
2484 remaining_words =
2485 BCC
2486 (smb_buffer_response) / 2;
2487 }
2488 len =
2489 UniStrnlen((wchar_t *) bcc_ptr,
2490 remaining_words - 1);
2491 /* We look for obvious messed up bcc or strings in response so we do not go off
2492 the end since (at least) WIN2K and Windows XP have a major bug in not null
2493 terminating last Unicode string in response */
2494 if(ses->serverOS)
2495 kfree(ses->serverOS);
2496 ses->serverOS =
2497 kzalloc(2 * (len + 1), GFP_KERNEL);
2498 cifs_strfromUCS_le(ses->serverOS,
2499 (__le16 *)
2500 bcc_ptr, len,
2501 nls_codepage);
2502 bcc_ptr += 2 * (len + 1);
2503 remaining_words -= len + 1;
2504 ses->serverOS[2 * len] = 0;
2505 ses->serverOS[1 + (2 * len)] = 0;
2506 if (remaining_words > 0) {
2507 len = UniStrnlen((wchar_t *)
2508 bcc_ptr,
2509 remaining_words
2510 - 1);
2511 kfree(ses->serverNOS);
2512 ses->serverNOS =
2513 kzalloc(2 * (len + 1),
2514 GFP_KERNEL);
2515 cifs_strfromUCS_le(ses->
2516 serverNOS,
2517 (__le16 *)
2518 bcc_ptr,
2519 len,
2520 nls_codepage);
2521 bcc_ptr += 2 * (len + 1);
2522 ses->serverNOS[2 * len] = 0;
2523 ses->serverNOS[1 +
2524 (2 * len)] = 0;
2525 remaining_words -= len + 1;
2526 if (remaining_words > 0) {
2527 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2528 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2529 kfree(ses->serverDomain);
2530 ses->serverDomain =
2531 kzalloc(2 *
2532 (len +
2533 1),
2534 GFP_KERNEL);
2535 cifs_strfromUCS_le
2536 (ses->serverDomain,
2537 (__le16 *)bcc_ptr,
2538 len, nls_codepage);
2539 bcc_ptr +=
2540 2 * (len + 1);
2541 ses->serverDomain[2*len]
2542 = 0;
2543 ses->serverDomain
2544 [1 + (2 * len)]
2545 = 0;
2546 } /* else no more room so create dummy domain string */
2547 else {
2548 kfree(ses->serverDomain);
2549 ses->serverDomain =
2550 kzalloc(2,
2551 GFP_KERNEL);
2552 }
2553 } else { /* no room so create dummy domain and NOS string */
2554 kfree(ses->serverDomain);
2555 ses->serverDomain =
2556 kzalloc(2, GFP_KERNEL);
2557 kfree(ses->serverNOS);
2558 ses->serverNOS =
2559 kzalloc(2, GFP_KERNEL);
2560 }
2561 } else { /* ASCII */
2562 len = strnlen(bcc_ptr, 1024);
2563 if (((long) bcc_ptr + len) - (long)
2564 pByteArea(smb_buffer_response)
2565 <= BCC(smb_buffer_response)) {
2566 if(ses->serverOS)
2567 kfree(ses->serverOS);
2568 ses->serverOS =
2569 kzalloc(len + 1,
2570 GFP_KERNEL);
2571 strncpy(ses->serverOS,
2572 bcc_ptr, len);
2573
2574 bcc_ptr += len;
2575 bcc_ptr[0] = 0; /* null terminate string */
2576 bcc_ptr++;
2577
2578 len = strnlen(bcc_ptr, 1024);
2579 kfree(ses->serverNOS);
2580 ses->serverNOS =
2581 kzalloc(len + 1,
2582 GFP_KERNEL);
2583 strncpy(ses->serverNOS, bcc_ptr, len);
2584 bcc_ptr += len;
2585 bcc_ptr[0] = 0;
2586 bcc_ptr++;
2587
2588 len = strnlen(bcc_ptr, 1024);
2589 kfree(ses->serverDomain);
2590 ses->serverDomain =
2591 kzalloc(len + 1,
2592 GFP_KERNEL);
2593 strncpy(ses->serverDomain, bcc_ptr, len);
2594 bcc_ptr += len;
2595 bcc_ptr[0] = 0;
2596 bcc_ptr++;
2597 } else
2598 cFYI(1,
2599 ("Variable field of length %d extends beyond end of smb",
2600 len));
2601 }
2602 } else {
2603 cERROR(1,
2604 (" Security Blob Length extends beyond end of SMB"));
2605 }
2606 } else {
2607 cERROR(1, ("No session structure passed in."));
2608 }
2609 } else {
2610 cERROR(1,
2611 (" Invalid Word count %d:",
2612 smb_buffer_response->WordCount));
2613 rc = -EIO;
2614 }
2615
2616 if (smb_buffer)
2617 cifs_buf_release(smb_buffer);
2618
2619 return rc;
2620 }
2621 static int
2622 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2623 char *ntlm_session_key, int ntlmv2_flag,
2624 const struct nls_table *nls_codepage)
2625 {
2626 struct smb_hdr *smb_buffer;
2627 struct smb_hdr *smb_buffer_response;
2628 SESSION_SETUP_ANDX *pSMB;
2629 SESSION_SETUP_ANDX *pSMBr;
2630 char *bcc_ptr;
2631 char *user;
2632 char *domain;
2633 int rc = 0;
2634 int remaining_words = 0;
2635 int bytes_returned = 0;
2636 int len;
2637 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2638 PAUTHENTICATE_MESSAGE SecurityBlob;
2639 __u32 negotiate_flags, capabilities;
2640 __u16 count;
2641
2642 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2643 if(ses == NULL)
2644 return -EINVAL;
2645 user = ses->userName;
2646 domain = ses->domainName;
2647 smb_buffer = cifs_buf_get();
2648 if (smb_buffer == NULL) {
2649 return -ENOMEM;
2650 }
2651 smb_buffer_response = smb_buffer;
2652 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2653 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2654
2655 /* send SMBsessionSetup here */
2656 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2657 NULL /* no tCon exists yet */ , 12 /* wct */ );
2658
2659 smb_buffer->Mid = GetNextMid(ses->server);
2660 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2661 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2662 pSMB->req.AndXCommand = 0xFF;
2663 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2664 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2665
2666 pSMB->req.hdr.Uid = ses->Suid;
2667
2668 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2669 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2670
2671 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2672 CAP_EXTENDED_SECURITY;
2673 if (ses->capabilities & CAP_UNICODE) {
2674 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2675 capabilities |= CAP_UNICODE;
2676 }
2677 if (ses->capabilities & CAP_STATUS32) {
2678 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2679 capabilities |= CAP_STATUS32;
2680 }
2681 if (ses->capabilities & CAP_DFS) {
2682 smb_buffer->Flags2 |= SMBFLG2_DFS;
2683 capabilities |= CAP_DFS;
2684 }
2685 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2686
2687 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2688 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2689 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2690 SecurityBlob->MessageType = NtLmAuthenticate;
2691 bcc_ptr += SecurityBlobLength;
2692 negotiate_flags =
2693 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2694 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2695 0x80000000 | NTLMSSP_NEGOTIATE_128;
2696 if(sign_CIFS_PDUs)
2697 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2698 if(ntlmv2_flag)
2699 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2700
2701 /* setup pointers to domain name and workstation name */
2702
2703 SecurityBlob->WorkstationName.Buffer = 0;
2704 SecurityBlob->WorkstationName.Length = 0;
2705 SecurityBlob->WorkstationName.MaximumLength = 0;
2706 SecurityBlob->SessionKey.Length = 0;
2707 SecurityBlob->SessionKey.MaximumLength = 0;
2708 SecurityBlob->SessionKey.Buffer = 0;
2709
2710 SecurityBlob->LmChallengeResponse.Length = 0;
2711 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2712 SecurityBlob->LmChallengeResponse.Buffer = 0;
2713
2714 SecurityBlob->NtChallengeResponse.Length =
2715 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2716 SecurityBlob->NtChallengeResponse.MaximumLength =
2717 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2718 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
2719 SecurityBlob->NtChallengeResponse.Buffer =
2720 cpu_to_le32(SecurityBlobLength);
2721 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
2722 bcc_ptr += CIFS_SESS_KEY_SIZE;
2723
2724 if (ses->capabilities & CAP_UNICODE) {
2725 if (domain == NULL) {
2726 SecurityBlob->DomainName.Buffer = 0;
2727 SecurityBlob->DomainName.Length = 0;
2728 SecurityBlob->DomainName.MaximumLength = 0;
2729 } else {
2730 __u16 len =
2731 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2732 nls_codepage);
2733 len *= 2;
2734 SecurityBlob->DomainName.MaximumLength =
2735 cpu_to_le16(len);
2736 SecurityBlob->DomainName.Buffer =
2737 cpu_to_le32(SecurityBlobLength);
2738 bcc_ptr += len;
2739 SecurityBlobLength += len;
2740 SecurityBlob->DomainName.Length =
2741 cpu_to_le16(len);
2742 }
2743 if (user == NULL) {
2744 SecurityBlob->UserName.Buffer = 0;
2745 SecurityBlob->UserName.Length = 0;
2746 SecurityBlob->UserName.MaximumLength = 0;
2747 } else {
2748 __u16 len =
2749 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
2750 nls_codepage);
2751 len *= 2;
2752 SecurityBlob->UserName.MaximumLength =
2753 cpu_to_le16(len);
2754 SecurityBlob->UserName.Buffer =
2755 cpu_to_le32(SecurityBlobLength);
2756 bcc_ptr += len;
2757 SecurityBlobLength += len;
2758 SecurityBlob->UserName.Length =
2759 cpu_to_le16(len);
2760 }
2761
2762 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
2763 SecurityBlob->WorkstationName.Length *= 2;
2764 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2765 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2766 bcc_ptr += SecurityBlob->WorkstationName.Length;
2767 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2768 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2769
2770 if ((long) bcc_ptr % 2) {
2771 *bcc_ptr = 0;
2772 bcc_ptr++;
2773 }
2774 bytes_returned =
2775 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2776 32, nls_codepage);
2777 bcc_ptr += 2 * bytes_returned;
2778 bytes_returned =
2779 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2780 nls_codepage);
2781 bcc_ptr += 2 * bytes_returned;
2782 bcc_ptr += 2; /* null term version string */
2783 bytes_returned =
2784 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2785 64, nls_codepage);
2786 bcc_ptr += 2 * bytes_returned;
2787 *(bcc_ptr + 1) = 0;
2788 *(bcc_ptr + 2) = 0;
2789 bcc_ptr += 2; /* null terminate network opsys string */
2790 *(bcc_ptr + 1) = 0;
2791 *(bcc_ptr + 2) = 0;
2792 bcc_ptr += 2; /* null domain */
2793 } else { /* ASCII */
2794 if (domain == NULL) {
2795 SecurityBlob->DomainName.Buffer = 0;
2796 SecurityBlob->DomainName.Length = 0;
2797 SecurityBlob->DomainName.MaximumLength = 0;
2798 } else {
2799 __u16 len;
2800 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2801 strncpy(bcc_ptr, domain, 63);
2802 len = strnlen(domain, 64);
2803 SecurityBlob->DomainName.MaximumLength =
2804 cpu_to_le16(len);
2805 SecurityBlob->DomainName.Buffer =
2806 cpu_to_le32(SecurityBlobLength);
2807 bcc_ptr += len;
2808 SecurityBlobLength += len;
2809 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2810 }
2811 if (user == NULL) {
2812 SecurityBlob->UserName.Buffer = 0;
2813 SecurityBlob->UserName.Length = 0;
2814 SecurityBlob->UserName.MaximumLength = 0;
2815 } else {
2816 __u16 len;
2817 strncpy(bcc_ptr, user, 63);
2818 len = strnlen(user, 64);
2819 SecurityBlob->UserName.MaximumLength =
2820 cpu_to_le16(len);
2821 SecurityBlob->UserName.Buffer =
2822 cpu_to_le32(SecurityBlobLength);
2823 bcc_ptr += len;
2824 SecurityBlobLength += len;
2825 SecurityBlob->UserName.Length = cpu_to_le16(len);
2826 }
2827 /* BB fill in our workstation name if known BB */
2828
2829 strcpy(bcc_ptr, "Linux version ");
2830 bcc_ptr += strlen("Linux version ");
2831 strcpy(bcc_ptr, system_utsname.release);
2832 bcc_ptr += strlen(system_utsname.release) + 1;
2833 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2834 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2835 bcc_ptr++; /* null domain */
2836 *bcc_ptr = 0;
2837 }
2838 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2839 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2840 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2841 smb_buffer->smb_buf_length += count;
2842 pSMB->req.ByteCount = cpu_to_le16(count);
2843
2844 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2845 &bytes_returned, 1);
2846 if (rc) {
2847 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2848 } else if ((smb_buffer_response->WordCount == 3)
2849 || (smb_buffer_response->WordCount == 4)) {
2850 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2851 __u16 blob_len =
2852 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2853 if (action & GUEST_LOGIN)
2854 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2855 /* if(SecurityBlob2->MessageType != NtLm??){
2856 cFYI("Unexpected message type on auth response is %d "));
2857 } */
2858 if (ses) {
2859 cFYI(1,
2860 ("Does UID on challenge %d match auth response UID %d ",
2861 ses->Suid, smb_buffer_response->Uid));
2862 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2863 bcc_ptr = pByteArea(smb_buffer_response);
2864 /* response can have either 3 or 4 word count - Samba sends 3 */
2865 if ((pSMBr->resp.hdr.WordCount == 3)
2866 || ((pSMBr->resp.hdr.WordCount == 4)
2867 && (blob_len <
2868 pSMBr->resp.ByteCount))) {
2869 if (pSMBr->resp.hdr.WordCount == 4) {
2870 bcc_ptr +=
2871 blob_len;
2872 cFYI(1,
2873 ("Security Blob Length %d ",
2874 blob_len));
2875 }
2876
2877 cFYI(1,
2878 ("NTLMSSP response to Authenticate "));
2879
2880 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2881 if ((long) (bcc_ptr) % 2) {
2882 remaining_words =
2883 (BCC(smb_buffer_response)
2884 - 1) / 2;
2885 bcc_ptr++; /* Unicode strings must be word aligned */
2886 } else {
2887 remaining_words = BCC(smb_buffer_response) / 2;
2888 }
2889 len =
2890 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2891 /* We look for obvious messed up bcc or strings in response so we do not go off
2892 the end since (at least) WIN2K and Windows XP have a major bug in not null
2893 terminating last Unicode string in response */
2894 if(ses->serverOS)
2895 kfree(ses->serverOS);
2896 ses->serverOS =
2897 kzalloc(2 * (len + 1), GFP_KERNEL);
2898 cifs_strfromUCS_le(ses->serverOS,
2899 (__le16 *)
2900 bcc_ptr, len,
2901 nls_codepage);
2902 bcc_ptr += 2 * (len + 1);
2903 remaining_words -= len + 1;
2904 ses->serverOS[2 * len] = 0;
2905 ses->serverOS[1 + (2 * len)] = 0;
2906 if (remaining_words > 0) {
2907 len = UniStrnlen((wchar_t *)
2908 bcc_ptr,
2909 remaining_words
2910 - 1);
2911 kfree(ses->serverNOS);
2912 ses->serverNOS =
2913 kzalloc(2 * (len + 1),
2914 GFP_KERNEL);
2915 cifs_strfromUCS_le(ses->
2916 serverNOS,
2917 (__le16 *)
2918 bcc_ptr,
2919 len,
2920 nls_codepage);
2921 bcc_ptr += 2 * (len + 1);
2922 ses->serverNOS[2 * len] = 0;
2923 ses->serverNOS[1+(2*len)] = 0;
2924 remaining_words -= len + 1;
2925 if (remaining_words > 0) {
2926 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2927 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2928 if(ses->serverDomain)
2929 kfree(ses->serverDomain);
2930 ses->serverDomain =
2931 kzalloc(2 *
2932 (len +
2933 1),
2934 GFP_KERNEL);
2935 cifs_strfromUCS_le
2936 (ses->
2937 serverDomain,
2938 (__le16 *)
2939 bcc_ptr, len,
2940 nls_codepage);
2941 bcc_ptr +=
2942 2 * (len + 1);
2943 ses->
2944 serverDomain[2
2945 * len]
2946 = 0;
2947 ses->
2948 serverDomain[1
2949 +
2950 (2
2951 *
2952 len)]
2953 = 0;
2954 } /* else no more room so create dummy domain string */
2955 else {
2956 if(ses->serverDomain)
2957 kfree(ses->serverDomain);
2958 ses->serverDomain = kzalloc(2,GFP_KERNEL);
2959 }
2960 } else { /* no room so create dummy domain and NOS string */
2961 if(ses->serverDomain)
2962 kfree(ses->serverDomain);
2963 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2964 kfree(ses->serverNOS);
2965 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2966 }
2967 } else { /* ASCII */
2968 len = strnlen(bcc_ptr, 1024);
2969 if (((long) bcc_ptr + len) -
2970 (long) pByteArea(smb_buffer_response)
2971 <= BCC(smb_buffer_response)) {
2972 if(ses->serverOS)
2973 kfree(ses->serverOS);
2974 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2975 strncpy(ses->serverOS,bcc_ptr, len);
2976
2977 bcc_ptr += len;
2978 bcc_ptr[0] = 0; /* null terminate the string */
2979 bcc_ptr++;
2980
2981 len = strnlen(bcc_ptr, 1024);
2982 kfree(ses->serverNOS);
2983 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
2984 strncpy(ses->serverNOS, bcc_ptr, len);
2985 bcc_ptr += len;
2986 bcc_ptr[0] = 0;
2987 bcc_ptr++;
2988
2989 len = strnlen(bcc_ptr, 1024);
2990 if(ses->serverDomain)
2991 kfree(ses->serverDomain);
2992 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
2993 strncpy(ses->serverDomain, bcc_ptr, len);
2994 bcc_ptr += len;
2995 bcc_ptr[0] = 0;
2996 bcc_ptr++;
2997 } else
2998 cFYI(1,
2999 ("Variable field of length %d extends beyond end of smb ",
3000 len));
3001 }
3002 } else {
3003 cERROR(1,
3004 (" Security Blob Length extends beyond end of SMB"));
3005 }
3006 } else {
3007 cERROR(1, ("No session structure passed in."));
3008 }
3009 } else {
3010 cERROR(1,
3011 (" Invalid Word count %d: ",
3012 smb_buffer_response->WordCount));
3013 rc = -EIO;
3014 }
3015
3016 if (smb_buffer)
3017 cifs_buf_release(smb_buffer);
3018
3019 return rc;
3020 }
3021
3022 int
3023 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3024 const char *tree, struct cifsTconInfo *tcon,
3025 const struct nls_table *nls_codepage)
3026 {
3027 struct smb_hdr *smb_buffer;
3028 struct smb_hdr *smb_buffer_response;
3029 TCONX_REQ *pSMB;
3030 TCONX_RSP *pSMBr;
3031 unsigned char *bcc_ptr;
3032 int rc = 0;
3033 int length;
3034 __u16 count;
3035
3036 if (ses == NULL)
3037 return -EIO;
3038
3039 smb_buffer = cifs_buf_get();
3040 if (smb_buffer == NULL) {
3041 return -ENOMEM;
3042 }
3043 smb_buffer_response = smb_buffer;
3044
3045 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3046 NULL /*no tid */ , 4 /*wct */ );
3047
3048 smb_buffer->Mid = GetNextMid(ses->server);
3049 smb_buffer->Uid = ses->Suid;
3050 pSMB = (TCONX_REQ *) smb_buffer;
3051 pSMBr = (TCONX_RSP *) smb_buffer_response;
3052
3053 pSMB->AndXCommand = 0xFF;
3054 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3055 bcc_ptr = &pSMB->Password[0];
3056 if((ses->server->secMode) & SECMODE_USER) {
3057 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3058 *bcc_ptr = 0; /* password is null byte */
3059 bcc_ptr++; /* skip password */
3060 /* already aligned so no need to do it below */
3061 } else {
3062 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3063 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3064 specified as required (when that support is added to
3065 the vfs in the future) as only NTLM or the much
3066 weaker LANMAN (which we do not send by default) is accepted
3067 by Samba (not sure whether other servers allow
3068 NTLMv2 password here) */
3069 #ifdef CONFIG_CIFS_WEAK_PW_HASH
3070 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3071 (ses->server->secType == LANMAN))
3072 calc_lanman_hash(ses, bcc_ptr);
3073 else
3074 #endif /* CIFS_WEAK_PW_HASH */
3075 SMBNTencrypt(ses->password,
3076 ses->server->cryptKey,
3077 bcc_ptr);
3078
3079 bcc_ptr += CIFS_SESS_KEY_SIZE;
3080 if(ses->capabilities & CAP_UNICODE) {
3081 /* must align unicode strings */
3082 *bcc_ptr = 0; /* null byte password */
3083 bcc_ptr++;
3084 }
3085 }
3086
3087 if(ses->server->secMode &
3088 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3089 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3090
3091 if (ses->capabilities & CAP_STATUS32) {
3092 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3093 }
3094 if (ses->capabilities & CAP_DFS) {
3095 smb_buffer->Flags2 |= SMBFLG2_DFS;
3096 }
3097 if (ses->capabilities & CAP_UNICODE) {
3098 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3099 length =
3100 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3101 6 /* max utf8 char length in bytes */ *
3102 (/* server len*/ + 256 /* share len */), nls_codepage);
3103 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
3104 bcc_ptr += 2; /* skip trailing null */
3105 } else { /* ASCII */
3106 strcpy(bcc_ptr, tree);
3107 bcc_ptr += strlen(tree) + 1;
3108 }
3109 strcpy(bcc_ptr, "?????");
3110 bcc_ptr += strlen("?????");
3111 bcc_ptr += 1;
3112 count = bcc_ptr - &pSMB->Password[0];
3113 pSMB->hdr.smb_buf_length += count;
3114 pSMB->ByteCount = cpu_to_le16(count);
3115
3116 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3117
3118 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3119 /* above now done in SendReceive */
3120 if ((rc == 0) && (tcon != NULL)) {
3121 tcon->tidStatus = CifsGood;
3122 tcon->tid = smb_buffer_response->Tid;
3123 bcc_ptr = pByteArea(smb_buffer_response);
3124 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3125 /* skip service field (NB: this field is always ASCII) */
3126 bcc_ptr += length + 1;
3127 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3128 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3129 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3130 if ((bcc_ptr + (2 * length)) -
3131 pByteArea(smb_buffer_response) <=
3132 BCC(smb_buffer_response)) {
3133 kfree(tcon->nativeFileSystem);
3134 tcon->nativeFileSystem =
3135 kzalloc(length + 2, GFP_KERNEL);
3136 cifs_strfromUCS_le(tcon->nativeFileSystem,
3137 (__le16 *) bcc_ptr,
3138 length, nls_codepage);
3139 bcc_ptr += 2 * length;
3140 bcc_ptr[0] = 0; /* null terminate the string */
3141 bcc_ptr[1] = 0;
3142 bcc_ptr += 2;
3143 }
3144 /* else do not bother copying these informational fields */
3145 } else {
3146 length = strnlen(bcc_ptr, 1024);
3147 if ((bcc_ptr + length) -
3148 pByteArea(smb_buffer_response) <=
3149 BCC(smb_buffer_response)) {
3150 kfree(tcon->nativeFileSystem);
3151 tcon->nativeFileSystem =
3152 kzalloc(length + 1, GFP_KERNEL);
3153 strncpy(tcon->nativeFileSystem, bcc_ptr,
3154 length);
3155 }
3156 /* else do not bother copying these informational fields */
3157 }
3158 if(smb_buffer_response->WordCount == 3)
3159 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3160 else
3161 tcon->Flags = 0;
3162 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3163 } else if ((rc == 0) && tcon == NULL) {
3164 /* all we need to save for IPC$ connection */
3165 ses->ipc_tid = smb_buffer_response->Tid;
3166 }
3167
3168 if (smb_buffer)
3169 cifs_buf_release(smb_buffer);
3170 return rc;
3171 }
3172
3173 int
3174 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3175 {
3176 int rc = 0;
3177 int xid;
3178 struct cifsSesInfo *ses = NULL;
3179 struct task_struct *cifsd_task;
3180
3181 xid = GetXid();
3182
3183 if (cifs_sb->tcon) {
3184 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3185 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3186 if (rc == -EBUSY) {
3187 FreeXid(xid);
3188 return 0;
3189 }
3190 tconInfoFree(cifs_sb->tcon);
3191 if ((ses) && (ses->server)) {
3192 /* save off task so we do not refer to ses later */
3193 cifsd_task = ses->server->tsk;
3194 cFYI(1, ("About to do SMBLogoff "));
3195 rc = CIFSSMBLogoff(xid, ses);
3196 if (rc == -EBUSY) {
3197 FreeXid(xid);
3198 return 0;
3199 } else if (rc == -ESHUTDOWN) {
3200 cFYI(1,("Waking up socket by sending it signal"));
3201 if(cifsd_task) {
3202 send_sig(SIGKILL,cifsd_task,1);
3203 wait_for_completion(&cifsd_complete);
3204 }
3205 rc = 0;
3206 } /* else - we have an smb session
3207 left on this socket do not kill cifsd */
3208 } else
3209 cFYI(1, ("No session or bad tcon"));
3210 }
3211
3212 cifs_sb->tcon = NULL;
3213 if (ses)
3214 schedule_timeout_interruptible(msecs_to_jiffies(500));
3215 if (ses)
3216 sesInfoFree(ses);
3217
3218 FreeXid(xid);
3219 return rc; /* BB check if we should always return zero here */
3220 }
3221
3222 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3223 struct nls_table * nls_info)
3224 {
3225 int rc = 0;
3226 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3227 int ntlmv2_flag = FALSE;
3228 int first_time = 0;
3229
3230 /* what if server changes its buffer size after dropping the session? */
3231 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3232 rc = CIFSSMBNegotiate(xid, pSesInfo);
3233 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3234 rc = CIFSSMBNegotiate(xid, pSesInfo);
3235 if(rc == -EAGAIN)
3236 rc = -EHOSTDOWN;
3237 }
3238 if(rc == 0) {
3239 spin_lock(&GlobalMid_Lock);
3240 if(pSesInfo->server->tcpStatus != CifsExiting)
3241 pSesInfo->server->tcpStatus = CifsGood;
3242 else
3243 rc = -EHOSTDOWN;
3244 spin_unlock(&GlobalMid_Lock);
3245
3246 }
3247 first_time = 1;
3248 }
3249 if (!rc) {
3250 pSesInfo->capabilities = pSesInfo->server->capabilities;
3251 if(linuxExtEnabled == 0)
3252 pSesInfo->capabilities &= (~CAP_UNIX);
3253 /* pSesInfo->sequence_number = 0;*/
3254 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3255 pSesInfo->server->secMode,
3256 pSesInfo->server->capabilities,
3257 pSesInfo->server->timeZone));
3258 if(experimEnabled < 2)
3259 rc = CIFS_SessSetup(xid, pSesInfo,
3260 first_time, nls_info);
3261 else if (extended_security
3262 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3263 && (pSesInfo->server->secType == NTLMSSP)) {
3264 rc = -EOPNOTSUPP;
3265 } else if (extended_security
3266 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3267 && (pSesInfo->server->secType == RawNTLMSSP)) {
3268 cFYI(1, ("NTLMSSP sesssetup"));
3269 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3270 pSesInfo,
3271 &ntlmv2_flag,
3272 nls_info);
3273 if (!rc) {
3274 if(ntlmv2_flag) {
3275 char * v2_response;
3276 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3277 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3278 nls_info)) {
3279 rc = -ENOMEM;
3280 goto ss_err_exit;
3281 } else
3282 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3283 if(v2_response) {
3284 CalcNTLMv2_response(pSesInfo,v2_response);
3285 /* if(first_time)
3286 cifs_calculate_ntlmv2_mac_key(
3287 pSesInfo->server->mac_signing_key,
3288 response, ntlm_session_key, */
3289 kfree(v2_response);
3290 /* BB Put dummy sig in SessSetup PDU? */
3291 } else {
3292 rc = -ENOMEM;
3293 goto ss_err_exit;
3294 }
3295
3296 } else {
3297 SMBNTencrypt(pSesInfo->password,
3298 pSesInfo->server->cryptKey,
3299 ntlm_session_key);
3300
3301 if(first_time)
3302 cifs_calculate_mac_key(
3303 pSesInfo->server->mac_signing_key,
3304 ntlm_session_key,
3305 pSesInfo->password);
3306 }
3307 /* for better security the weaker lanman hash not sent
3308 in AuthSessSetup so we no longer calculate it */
3309
3310 rc = CIFSNTLMSSPAuthSessSetup(xid,
3311 pSesInfo,
3312 ntlm_session_key,
3313 ntlmv2_flag,
3314 nls_info);
3315 }
3316 } else { /* old style NTLM 0.12 session setup */
3317 SMBNTencrypt(pSesInfo->password,
3318 pSesInfo->server->cryptKey,
3319 ntlm_session_key);
3320
3321 if(first_time)
3322 cifs_calculate_mac_key(
3323 pSesInfo->server->mac_signing_key,
3324 ntlm_session_key, pSesInfo->password);
3325
3326 rc = CIFSSessSetup(xid, pSesInfo,
3327 ntlm_session_key, nls_info);
3328 }
3329 if (rc) {
3330 cERROR(1,("Send error in SessSetup = %d",rc));
3331 } else {
3332 cFYI(1,("CIFS Session Established successfully"));
3333 pSesInfo->status = CifsGood;
3334 }
3335 }
3336 ss_err_exit:
3337 return rc;
3338 }
3339