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