4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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 <asm/uaccess.h>
32 #include <asm/processor.h>
35 #include "cifsproto.h"
36 #include "cifs_unicode.h"
37 #include "cifs_debug.h"
38 #include "cifs_fs_sb.h"
41 #include "rfc1002pdu.h"
44 #define RFC1001_PORT 139
46 extern void SMBencrypt(unsigned char *passwd
, unsigned char *c8
,
48 extern void SMBNTencrypt(unsigned char *passwd
, unsigned char *c8
,
51 extern mempool_t
*cifs_req_poolp
;
59 char *in6_addr
; /* ipv6 address as human readable form of in6_addr */
60 char *iocharset
; /* local code page for mapping to and from Unicode */
61 char source_rfc1001_name
[16]; /* netbios name of client */
71 unsigned no_psx_acl
:1; /* set if posix acl support should be disabled */
72 unsigned no_xattr
:1; /* set if xattr (EA) support should be disabled*/
73 unsigned server_ino
:1; /* use inode numbers from server ie UniqueId */
75 unsigned remap
:1; /* set to remap seven reserved chars in filenames */
79 unsigned short int port
;
82 static int ipv4_connect(struct sockaddr_in
*psin_server
,
83 struct socket
**csocket
,
85 static int ipv6_connect(struct sockaddr_in6
*psin_server
,
86 struct socket
**csocket
);
90 * cifs tcp session reconnection
92 * mark tcp session as reconnecting so temporarily locked
93 * mark all smb sessions as reconnecting for tcp session
94 * reconnect tcp session
95 * wake up waiters on reconnection? - (not needed currently)
99 cifs_reconnect(struct TCP_Server_Info
*server
)
102 struct list_head
*tmp
;
103 struct cifsSesInfo
*ses
;
104 struct cifsTconInfo
*tcon
;
105 struct mid_q_entry
* mid_entry
;
107 spin_lock(&GlobalMid_Lock
);
108 if(server
->tcpStatus
== CifsExiting
) {
109 /* the demux thread will exit normally
110 next time through the loop */
111 spin_unlock(&GlobalMid_Lock
);
114 server
->tcpStatus
= CifsNeedReconnect
;
115 spin_unlock(&GlobalMid_Lock
);
118 cFYI(1, ("Reconnecting tcp session "));
120 /* before reconnecting the tcp session, mark the smb session (uid)
121 and the tid bad so they are not used until reconnected */
122 read_lock(&GlobalSMBSeslock
);
123 list_for_each(tmp
, &GlobalSMBSessionList
) {
124 ses
= list_entry(tmp
, struct cifsSesInfo
, cifsSessionList
);
126 if (ses
->server
== server
) {
127 ses
->status
= CifsNeedReconnect
;
131 /* else tcp and smb sessions need reconnection */
133 list_for_each(tmp
, &GlobalTreeConnectionList
) {
134 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
135 if((tcon
) && (tcon
->ses
) && (tcon
->ses
->server
== server
)) {
136 tcon
->tidStatus
= CifsNeedReconnect
;
139 read_unlock(&GlobalSMBSeslock
);
140 /* do not want to be sending data on a socket we are freeing */
141 down(&server
->tcpSem
);
142 if(server
->ssocket
) {
143 cFYI(1,("State: 0x%x Flags: 0x%lx", server
->ssocket
->state
,
144 server
->ssocket
->flags
));
145 server
->ssocket
->ops
->shutdown(server
->ssocket
,SEND_SHUTDOWN
);
146 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server
->ssocket
->state
,
147 server
->ssocket
->flags
));
148 sock_release(server
->ssocket
);
149 server
->ssocket
= NULL
;
152 spin_lock(&GlobalMid_Lock
);
153 list_for_each(tmp
, &server
->pending_mid_q
) {
154 mid_entry
= list_entry(tmp
, struct
158 if(mid_entry
->midState
== MID_REQUEST_SUBMITTED
) {
159 /* Mark other intransit requests as needing retry so
160 we do not immediately mark the session bad again
161 (ie after we reconnect below) as they timeout too */
162 mid_entry
->midState
= MID_RETRY_NEEDED
;
166 spin_unlock(&GlobalMid_Lock
);
169 while ((server
->tcpStatus
!= CifsExiting
) && (server
->tcpStatus
!= CifsGood
))
171 if(server
->protocolType
== IPV6
) {
172 rc
= ipv6_connect(&server
->addr
.sockAddr6
,&server
->ssocket
);
174 rc
= ipv4_connect(&server
->addr
.sockAddr
,
176 server
->workstation_RFC1001_name
);
179 set_current_state(TASK_INTERRUPTIBLE
);
180 schedule_timeout(3 * HZ
);
182 atomic_inc(&tcpSesReconnectCount
);
183 spin_lock(&GlobalMid_Lock
);
184 if(server
->tcpStatus
!= CifsExiting
)
185 server
->tcpStatus
= CifsGood
;
186 server
->sequence_number
= 0;
187 spin_unlock(&GlobalMid_Lock
);
188 /* atomic_set(&server->inFlight,0);*/
189 wake_up(&server
->response_q
);
196 cifs_demultiplex_thread(struct TCP_Server_Info
*server
)
199 unsigned int pdu_length
, total_read
;
200 struct smb_hdr
*smb_buffer
= NULL
;
201 struct msghdr smb_msg
;
203 struct socket
*csocket
= server
->ssocket
;
204 struct list_head
*tmp
;
205 struct cifsSesInfo
*ses
;
206 struct task_struct
*task_to_wake
= NULL
;
207 struct mid_q_entry
*mid_entry
;
211 allow_signal(SIGKILL
);
212 current
->flags
|= PF_MEMALLOC
;
213 server
->tsk
= current
; /* save process info to wake at shutdown */
214 cFYI(1, ("Demultiplex PID: %d", current
->pid
));
215 write_lock(&GlobalSMBSeslock
);
216 atomic_inc(&tcpSesAllocCount
);
217 length
= tcpSesAllocCount
.counter
;
218 write_unlock(&GlobalSMBSeslock
);
220 mempool_resize(cifs_req_poolp
,
221 length
+ cifs_min_rcv
,
225 while (server
->tcpStatus
!= CifsExiting
) {
226 if (smb_buffer
== NULL
)
227 smb_buffer
= cifs_buf_get();
229 memset(smb_buffer
, 0, sizeof (struct smb_hdr
));
231 if (smb_buffer
== NULL
) {
232 cERROR(1,("Can not get memory for SMB response"));
233 set_current_state(TASK_INTERRUPTIBLE
);
234 schedule_timeout(HZ
* 3); /* give system time to free memory */
237 iov
.iov_base
= smb_buffer
;
239 smb_msg
.msg_control
= NULL
;
240 smb_msg
.msg_controllen
= 0;
242 kernel_recvmsg(csocket
, &smb_msg
,
243 &iov
, 1, 4, 0 /* BB see socket.h flags */);
245 if(server
->tcpStatus
== CifsExiting
) {
247 } else if (server
->tcpStatus
== CifsNeedReconnect
) {
248 cFYI(1,("Reconnecting after server stopped responding"));
249 cifs_reconnect(server
);
250 cFYI(1,("call to reconnect done"));
251 csocket
= server
->ssocket
;
253 } else if ((length
== -ERESTARTSYS
) || (length
== -EAGAIN
)) {
254 set_current_state(TASK_INTERRUPTIBLE
);
255 schedule_timeout(1); /* minimum sleep to prevent looping
256 allowing socket to clear and app threads to set
257 tcpStatus CifsNeedReconnect if server hung */
259 } else if (length
<= 0) {
260 if(server
->tcpStatus
== CifsNew
) {
261 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
262 /* some servers kill tcp session rather than returning
263 smb negprot error in which case reconnecting here is
264 not going to help - return error to mount */
267 if(length
== -EINTR
) {
268 cFYI(1,("cifsd thread killed"));
271 cFYI(1,("Reconnecting after unexpected peek error %d",length
));
272 cifs_reconnect(server
);
273 csocket
= server
->ssocket
;
274 wake_up(&server
->response_q
);
276 } else if (length
> 3) {
277 pdu_length
= ntohl(smb_buffer
->smb_buf_length
);
278 /* Only read pdu_length after below checks for too short (due
279 to e.g. int overflow) and too long ie beyond end of buf */
280 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length
+4));
282 temp
= (char *) smb_buffer
;
283 if (temp
[0] == (char) RFC1002_SESSION_KEEP_ALIVE
) {
284 cFYI(0,("Received 4 byte keep alive packet"));
285 } else if (temp
[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE
) {
286 cFYI(1,("Good RFC 1002 session rsp"));
287 } else if (temp
[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE
) {
288 /* we get this from Windows 98 instead of error on SMB negprot response */
289 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp
[4]));
290 if(server
->tcpStatus
== CifsNew
) {
291 /* if nack on negprot (rather than
292 ret of smb negprot error) reconnecting
293 not going to help, ret error to mount */
296 /* give server a second to
297 clean up before reconnect attempt */
298 set_current_state(TASK_INTERRUPTIBLE
);
299 schedule_timeout(HZ
);
300 /* always try 445 first on reconnect
301 since we get NACK on some if we ever
302 connected to port 139 (the NACK is
303 since we do not begin with RFC1001
304 session initialize frame) */
305 server
->addr
.sockAddr
.sin_port
= htons(CIFS_PORT
);
306 cifs_reconnect(server
);
307 csocket
= server
->ssocket
;
308 wake_up(&server
->response_q
);
311 } else if (temp
[0] != (char) 0) {
312 cERROR(1,("Unknown RFC 1002 frame"));
313 cifs_dump_mem(" Received Data: ", temp
, length
);
314 cifs_reconnect(server
);
315 csocket
= server
->ssocket
;
318 if((pdu_length
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
- 4)
319 || (pdu_length
< sizeof (struct smb_hdr
) - 1 - 4)) {
321 ("Invalid size SMB length %d and pdu_length %d",
322 length
, pdu_length
+4));
323 cifs_reconnect(server
);
324 csocket
= server
->ssocket
;
325 wake_up(&server
->response_q
);
327 } else { /* length ok */
329 iov
.iov_base
= 4 + (char *)smb_buffer
;
330 iov
.iov_len
= pdu_length
;
332 total_read
< pdu_length
;
333 total_read
+= length
) {
334 length
= kernel_recvmsg(csocket
, &smb_msg
,
336 pdu_length
- total_read
, 0);
339 ("Zero length receive when expecting %d ",
340 pdu_length
- total_read
));
341 cifs_reconnect(server
);
342 csocket
= server
->ssocket
;
343 wake_up(&server
->response_q
);
347 length
+= 4; /* account for rfc1002 hdr */
350 dump_smb(smb_buffer
, length
);
352 (smb_buffer
, smb_buffer
->Mid
, total_read
+4)) {
353 cERROR(1, ("Bad SMB Received "));
358 spin_lock(&GlobalMid_Lock
);
359 list_for_each(tmp
, &server
->pending_mid_q
) {
360 mid_entry
= list_entry(tmp
, struct
364 if ((mid_entry
->mid
== smb_buffer
->Mid
)
365 && (mid_entry
->midState
==
366 MID_REQUEST_SUBMITTED
)
367 && (mid_entry
->command
==
368 smb_buffer
->Command
)) {
369 cFYI(1,("Found Mid 0x%x wake up"
371 task_to_wake
= mid_entry
->tsk
;
372 mid_entry
->resp_buf
=
374 mid_entry
->midState
=
375 MID_RESPONSE_RECEIVED
;
378 spin_unlock(&GlobalMid_Lock
);
380 smb_buffer
= NULL
; /* will be freed by users thread after he is done */
381 wake_up_process(task_to_wake
);
382 } else if (is_valid_oplock_break(smb_buffer
) == FALSE
) {
383 cERROR(1, ("No task to wake, unknown frame rcvd!"));
384 cifs_dump_mem("Received Data is: ",temp
,sizeof(struct smb_hdr
));
389 ("Frame less than four bytes received %d bytes long.",
391 cifs_reconnect(server
);
392 csocket
= server
->ssocket
;
393 wake_up(&server
->response_q
);
397 spin_lock(&GlobalMid_Lock
);
398 server
->tcpStatus
= CifsExiting
;
400 atomic_set(&server
->inFlight
, 0);
401 spin_unlock(&GlobalMid_Lock
);
402 /* Although there should not be any requests blocked on
403 this queue it can not hurt to be paranoid and try to wake up requests
404 that may haven been blocked when more than 50 at time were on the wire
405 to the same server - they now will see the session is in exit state
406 and get out of SendReceive. */
407 wake_up_all(&server
->request_q
);
408 /* give those requests time to exit */
409 set_current_state(TASK_INTERRUPTIBLE
);
410 schedule_timeout(HZ
/8);
412 if(server
->ssocket
) {
413 sock_release(csocket
);
414 server
->ssocket
= NULL
;
416 if (smb_buffer
) /* buffer usually freed in free_mid - need to free it on error or exit */
417 cifs_buf_release(smb_buffer
);
419 read_lock(&GlobalSMBSeslock
);
420 if (list_empty(&server
->pending_mid_q
)) {
421 /* loop through server session structures attached to this and mark them dead */
422 list_for_each(tmp
, &GlobalSMBSessionList
) {
424 list_entry(tmp
, struct cifsSesInfo
,
426 if (ses
->server
== server
) {
427 ses
->status
= CifsExiting
;
431 read_unlock(&GlobalSMBSeslock
);
433 spin_lock(&GlobalMid_Lock
);
434 list_for_each(tmp
, &server
->pending_mid_q
) {
435 mid_entry
= list_entry(tmp
, struct mid_q_entry
, qhead
);
436 if (mid_entry
->midState
== MID_REQUEST_SUBMITTED
) {
438 (" Clearing Mid 0x%x - waking up ",mid_entry
->mid
));
439 task_to_wake
= mid_entry
->tsk
;
441 wake_up_process(task_to_wake
);
445 spin_unlock(&GlobalMid_Lock
);
446 read_unlock(&GlobalSMBSeslock
);
447 set_current_state(TASK_INTERRUPTIBLE
);
448 /* 1/8th of sec is more than enough time for them to exit */
449 schedule_timeout(HZ
/8);
452 if (list_empty(&server
->pending_mid_q
)) {
453 /* mpx threads have not exited yet give them
454 at least the smb send timeout time for long ops */
455 cFYI(1, ("Wait for exit from demultiplex thread"));
456 set_current_state(TASK_INTERRUPTIBLE
);
457 schedule_timeout(46 * HZ
);
458 /* if threads still have not exited they are probably never
459 coming home not much else we can do but free the memory */
463 write_lock(&GlobalSMBSeslock
);
464 atomic_dec(&tcpSesAllocCount
);
465 length
= tcpSesAllocCount
.counter
;
466 write_unlock(&GlobalSMBSeslock
);
468 mempool_resize(cifs_req_poolp
,
469 length
+ cifs_min_rcv
,
473 set_current_state(TASK_INTERRUPTIBLE
);
474 schedule_timeout(HZ
/4);
479 cifs_kcalloc(size_t size
, unsigned int __nocast type
)
482 addr
= kmalloc(size
, type
);
484 memset(addr
, 0, size
);
489 cifs_parse_mount_options(char *options
, const char *devname
,struct smb_vol
*vol
)
493 unsigned int temp_len
, i
, j
;
499 memset(vol
->source_rfc1001_name
,0x20,15);
500 for(i
=0;i
< strnlen(system_utsname
.nodename
,15);i
++) {
501 /* does not have to be a perfect mapping since the field is
502 informational, only used for servers that do not support
503 port 445 and it can be overridden at mount time */
504 vol
->source_rfc1001_name
[i
] = toupper(system_utsname
.nodename
[i
]);
506 vol
->source_rfc1001_name
[15] = 0;
508 vol
->linux_uid
= current
->uid
; /* current->euid instead? */
509 vol
->linux_gid
= current
->gid
;
510 vol
->dir_mode
= S_IRWXUGO
;
511 /* 2767 perms indicate mandatory locking support */
512 vol
->file_mode
= S_IALLUGO
& ~(S_ISUID
| S_IXGRP
);
514 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
520 if(strncmp(options
,"sep=",4) == 0) {
521 if(options
[4] != 0) {
522 separator
[0] = options
[4];
525 cFYI(1,("Null separator not allowed"));
529 while ((data
= strsep(&options
, separator
)) != NULL
) {
532 if ((value
= strchr(data
, '=')) != NULL
)
535 if (strnicmp(data
, "user_xattr",10) == 0) {/*parse before user*/
537 } else if (strnicmp(data
, "nouser_xattr",12) == 0) {
539 } else if (strnicmp(data
, "user", 4) == 0) {
540 if (!value
|| !*value
) {
542 "CIFS: invalid or missing username\n");
543 return 1; /* needs_arg; */
545 if (strnlen(value
, 200) < 200) {
546 vol
->username
= value
;
548 printk(KERN_WARNING
"CIFS: username too long\n");
551 } else if (strnicmp(data
, "pass", 4) == 0) {
553 vol
->password
= NULL
;
555 } else if(value
[0] == 0) {
556 /* check if string begins with double comma
557 since that would mean the password really
558 does start with a comma, and would not
559 indicate an empty string */
560 if(value
[1] != separator
[0]) {
561 vol
->password
= NULL
;
565 temp_len
= strlen(value
);
566 /* removed password length check, NTLM passwords
567 can be arbitrarily long */
569 /* if comma in password, the string will be
570 prematurely null terminated. Commas in password are
571 specified across the cifs mount interface by a double
572 comma ie ,, and a comma used as in other cases ie ','
573 as a parameter delimiter/separator is single and due
574 to the strsep above is temporarily zeroed. */
576 /* NB: password legally can have multiple commas and
577 the only illegal character in a password is null */
579 if ((value
[temp_len
] == 0) && (value
[temp_len
+1] == separator
[0])) {
581 value
[temp_len
] = separator
[0];
582 temp_len
+=2; /* move after the second comma */
583 while(value
[temp_len
] != 0) {
584 if (value
[temp_len
] == separator
[0]) {
585 if (value
[temp_len
+1] == separator
[0]) {
586 temp_len
++; /* skip second comma */
588 /* single comma indicating start
595 if(value
[temp_len
] == 0) {
599 /* point option to start of next parm */
600 options
= value
+ temp_len
+ 1;
602 /* go from value to value + temp_len condensing
603 double commas to singles. Note that this ends up
604 allocating a few bytes too many, which is ok */
605 vol
->password
= cifs_kcalloc(temp_len
, GFP_KERNEL
);
606 for(i
=0,j
=0;i
<temp_len
;i
++,j
++) {
607 vol
->password
[j
] = value
[i
];
608 if(value
[i
] == separator
[0] && value
[i
+1] == separator
[0]) {
609 /* skip second comma */
613 vol
->password
[j
] = 0;
615 vol
->password
= cifs_kcalloc(temp_len
+ 1, GFP_KERNEL
);
616 strcpy(vol
->password
, value
);
618 } else if (strnicmp(data
, "ip", 2) == 0) {
619 if (!value
|| !*value
) {
621 } else if (strnlen(value
, 35) < 35) {
624 printk(KERN_WARNING
"CIFS: ip address too long\n");
627 } else if ((strnicmp(data
, "unc", 3) == 0)
628 || (strnicmp(data
, "target", 6) == 0)
629 || (strnicmp(data
, "path", 4) == 0)) {
630 if (!value
|| !*value
) {
632 "CIFS: invalid path to network resource\n");
633 return 1; /* needs_arg; */
635 if ((temp_len
= strnlen(value
, 300)) < 300) {
636 vol
->UNC
= kmalloc(temp_len
+1,GFP_KERNEL
);
639 strcpy(vol
->UNC
,value
);
640 if (strncmp(vol
->UNC
, "//", 2) == 0) {
643 } else if (strncmp(vol
->UNC
, "\\\\", 2) != 0) {
645 "CIFS: UNC Path does not begin with // or \\\\ \n");
649 printk(KERN_WARNING
"CIFS: UNC name too long\n");
652 } else if ((strnicmp(data
, "domain", 3) == 0)
653 || (strnicmp(data
, "workgroup", 5) == 0)) {
654 if (!value
|| !*value
) {
655 printk(KERN_WARNING
"CIFS: invalid domain name\n");
656 return 1; /* needs_arg; */
658 /* BB are there cases in which a comma can be valid in
659 a domain name and need special handling? */
660 if (strnlen(value
, 65) < 65) {
661 vol
->domainname
= value
;
662 cFYI(1, ("Domain name set"));
664 printk(KERN_WARNING
"CIFS: domain name too long\n");
667 } else if (strnicmp(data
, "iocharset", 9) == 0) {
668 if (!value
|| !*value
) {
669 printk(KERN_WARNING
"CIFS: invalid iocharset specified\n");
670 return 1; /* needs_arg; */
672 if (strnlen(value
, 65) < 65) {
673 if(strnicmp(value
,"default",7))
674 vol
->iocharset
= value
;
675 /* if iocharset not set load_nls_default used by caller */
676 cFYI(1, ("iocharset set to %s",value
));
678 printk(KERN_WARNING
"CIFS: iocharset name too long.\n");
681 } else if (strnicmp(data
, "uid", 3) == 0) {
682 if (value
&& *value
) {
684 simple_strtoul(value
, &value
, 0);
686 } else if (strnicmp(data
, "gid", 3) == 0) {
687 if (value
&& *value
) {
689 simple_strtoul(value
, &value
, 0);
691 } else if (strnicmp(data
, "file_mode", 4) == 0) {
692 if (value
&& *value
) {
694 simple_strtoul(value
, &value
, 0);
696 } else if (strnicmp(data
, "dir_mode", 4) == 0) {
697 if (value
&& *value
) {
699 simple_strtoul(value
, &value
, 0);
701 } else if (strnicmp(data
, "dirmode", 4) == 0) {
702 if (value
&& *value
) {
704 simple_strtoul(value
, &value
, 0);
706 } else if (strnicmp(data
, "port", 4) == 0) {
707 if (value
&& *value
) {
709 simple_strtoul(value
, &value
, 0);
711 } else if (strnicmp(data
, "rsize", 5) == 0) {
712 if (value
&& *value
) {
714 simple_strtoul(value
, &value
, 0);
716 } else if (strnicmp(data
, "wsize", 5) == 0) {
717 if (value
&& *value
) {
719 simple_strtoul(value
, &value
, 0);
721 } else if (strnicmp(data
, "sockopt", 5) == 0) {
722 if (value
&& *value
) {
724 simple_strtoul(value
, &value
, 0);
726 } else if (strnicmp(data
, "netbiosname", 4) == 0) {
727 if (!value
|| !*value
|| (*value
== ' ')) {
728 cFYI(1,("invalid (empty) netbiosname specified"));
730 memset(vol
->source_rfc1001_name
,0x20,15);
732 /* BB are there cases in which a comma can be
733 valid in this workstation netbios name (and need
734 special handling)? */
736 /* We do not uppercase netbiosname for user */
740 vol
->source_rfc1001_name
[i
] = value
[i
];
742 /* The string has 16th byte zero still from
743 set at top of the function */
744 if((i
==15) && (value
[i
] != 0))
745 printk(KERN_WARNING
"CIFS: netbiosname longer than 15 and was truncated.\n");
747 } else if (strnicmp(data
, "credentials", 4) == 0) {
749 } else if (strnicmp(data
, "version", 3) == 0) {
751 } else if (strnicmp(data
, "guest",5) == 0) {
753 } else if (strnicmp(data
, "rw", 2) == 0) {
755 } else if ((strnicmp(data
, "suid", 4) == 0) ||
756 (strnicmp(data
, "nosuid", 6) == 0) ||
757 (strnicmp(data
, "exec", 4) == 0) ||
758 (strnicmp(data
, "noexec", 6) == 0) ||
759 (strnicmp(data
, "nodev", 5) == 0) ||
760 (strnicmp(data
, "noauto", 6) == 0) ||
761 (strnicmp(data
, "dev", 3) == 0)) {
762 /* The mount tool or mount.cifs helper (if present)
763 uses these opts to set flags, and the flags are read
764 by the kernel vfs layer before we get here (ie
765 before read super) so there is no point trying to
766 parse these options again and set anything and it
767 is ok to just ignore them */
769 } else if (strnicmp(data
, "ro", 2) == 0) {
771 } else if (strnicmp(data
, "hard", 4) == 0) {
773 } else if (strnicmp(data
, "soft", 4) == 0) {
775 } else if (strnicmp(data
, "perm", 4) == 0) {
777 } else if (strnicmp(data
, "noperm", 6) == 0) {
779 } else if (strnicmp(data
, "mapchars", 8) == 0) {
781 } else if (strnicmp(data
, "nomapchars", 10) == 0) {
783 } else if (strnicmp(data
, "setuids", 7) == 0) {
785 } else if (strnicmp(data
, "nosetuids", 9) == 0) {
787 } else if (strnicmp(data
, "nohard", 6) == 0) {
789 } else if (strnicmp(data
, "nosoft", 6) == 0) {
791 } else if (strnicmp(data
, "nointr", 6) == 0) {
793 } else if (strnicmp(data
, "intr", 4) == 0) {
795 } else if (strnicmp(data
, "serverino",7) == 0) {
797 } else if (strnicmp(data
, "noserverino",9) == 0) {
799 } else if (strnicmp(data
, "acl",3) == 0) {
801 } else if (strnicmp(data
, "noacl",5) == 0) {
803 } else if (strnicmp(data
, "direct",6) == 0) {
805 } else if (strnicmp(data
, "forcedirectio",13) == 0) {
807 } else if (strnicmp(data
, "in6_addr",8) == 0) {
808 if (!value
|| !*value
) {
809 vol
->in6_addr
= NULL
;
810 } else if (strnlen(value
, 49) == 48) {
811 vol
->in6_addr
= value
;
813 printk(KERN_WARNING
"CIFS: ip v6 address not 48 characters long\n");
816 } else if (strnicmp(data
, "noac", 4) == 0) {
817 printk(KERN_WARNING
"CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
819 printk(KERN_WARNING
"CIFS: Unknown mount option %s\n",data
);
821 if (vol
->UNC
== NULL
) {
822 if(devname
== NULL
) {
823 printk(KERN_WARNING
"CIFS: Missing UNC name for mount target\n");
826 if ((temp_len
= strnlen(devname
, 300)) < 300) {
827 vol
->UNC
= kmalloc(temp_len
+1,GFP_KERNEL
);
830 strcpy(vol
->UNC
,devname
);
831 if (strncmp(vol
->UNC
, "//", 2) == 0) {
834 } else if (strncmp(vol
->UNC
, "\\\\", 2) != 0) {
835 printk(KERN_WARNING
"CIFS: UNC Path does not begin with // or \\\\ \n");
839 printk(KERN_WARNING
"CIFS: UNC name too long\n");
843 if(vol
->UNCip
== NULL
)
844 vol
->UNCip
= &vol
->UNC
[2];
849 static struct cifsSesInfo
*
850 cifs_find_tcp_session(struct in_addr
* target_ip_addr
,
851 struct in6_addr
*target_ip6_addr
,
852 char *userName
, struct TCP_Server_Info
**psrvTcp
)
854 struct list_head
*tmp
;
855 struct cifsSesInfo
*ses
;
857 read_lock(&GlobalSMBSeslock
);
859 list_for_each(tmp
, &GlobalSMBSessionList
) {
860 ses
= list_entry(tmp
, struct cifsSesInfo
, cifsSessionList
);
862 if((target_ip_addr
&&
863 (ses
->server
->addr
.sockAddr
.sin_addr
.s_addr
864 == target_ip_addr
->s_addr
)) || (target_ip6_addr
865 && memcmp(&ses
->server
->addr
.sockAddr6
.sin6_addr
,
866 target_ip6_addr
,sizeof(*target_ip6_addr
)))){
867 /* BB lock server and tcp session and increment use count here?? */
868 *psrvTcp
= ses
->server
; /* found a match on the TCP session */
869 /* BB check if reconnection needed */
871 (ses
->userName
, userName
,
872 MAX_USERNAME_SIZE
) == 0){
873 read_unlock(&GlobalSMBSeslock
);
874 return ses
; /* found exact match on both tcp and SMB sessions */
878 /* else tcp and smb sessions need reconnection */
880 read_unlock(&GlobalSMBSeslock
);
884 static struct cifsTconInfo
*
885 find_unc(__be32 new_target_ip_addr
, char *uncName
, char *userName
)
887 struct list_head
*tmp
;
888 struct cifsTconInfo
*tcon
;
890 read_lock(&GlobalSMBSeslock
);
891 list_for_each(tmp
, &GlobalTreeConnectionList
) {
892 cFYI(1, ("Next tcon - "));
893 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
895 if (tcon
->ses
->server
) {
897 (" old ip addr: %x == new ip %x ?",
898 tcon
->ses
->server
->addr
.sockAddr
.sin_addr
.
899 s_addr
, new_target_ip_addr
));
900 if (tcon
->ses
->server
->addr
.sockAddr
.sin_addr
.
901 s_addr
== new_target_ip_addr
) {
902 /* BB lock tcon and server and tcp session and increment use count here? */
903 /* found a match on the TCP session */
904 /* BB check if reconnection needed */
905 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
906 tcon
->treeName
, uncName
));
908 (tcon
->treeName
, uncName
,
909 MAX_TREE_SIZE
) == 0) {
911 ("Matched UNC, old user: %s == new: %s ?",
912 tcon
->treeName
, uncName
));
914 (tcon
->ses
->userName
,
916 MAX_USERNAME_SIZE
) == 0) {
917 read_unlock(&GlobalSMBSeslock
);
918 return tcon
;/* also matched user (smb session)*/
925 read_unlock(&GlobalSMBSeslock
);
930 connect_to_dfs_path(int xid
, struct cifsSesInfo
*pSesInfo
,
931 const char *old_path
, const struct nls_table
*nls_codepage
,
934 unsigned char *referrals
= NULL
;
935 unsigned int num_referrals
;
938 rc
= get_dfs_path(xid
, pSesInfo
,old_path
, nls_codepage
,
939 &num_referrals
, &referrals
, remap
);
941 /* BB Add in code to: if valid refrl, if not ip address contact
942 the helper that resolves tcp names, mount to it, try to
943 tcon to it unmount it if fail */
952 get_dfs_path(int xid
, struct cifsSesInfo
*pSesInfo
,
953 const char *old_path
, const struct nls_table
*nls_codepage
,
954 unsigned int *pnum_referrals
,
955 unsigned char ** preferrals
, int remap
)
962 if (pSesInfo
->ipc_tid
== 0) {
963 temp_unc
= kmalloc(2 /* for slashes */ +
964 strnlen(pSesInfo
->serverName
,SERVER_NAME_LEN_WITH_NULL
* 2)
965 + 1 + 4 /* slash IPC$ */ + 2,
967 if (temp_unc
== NULL
)
971 strcpy(temp_unc
+ 2, pSesInfo
->serverName
);
972 strcpy(temp_unc
+ 2 + strlen(pSesInfo
->serverName
), "\\IPC$");
973 rc
= CIFSTCon(xid
, pSesInfo
, temp_unc
, NULL
, nls_codepage
);
975 ("CIFS Tcon rc = %d ipc_tid = %d", rc
,pSesInfo
->ipc_tid
));
979 rc
= CIFSGetDFSRefer(xid
, pSesInfo
, old_path
, preferrals
,
980 pnum_referrals
, nls_codepage
, remap
);
985 /* See RFC1001 section 14 on representation of Netbios names */
986 static void rfc1002mangle(char * target
,char * source
, unsigned int length
)
990 for(i
=0,j
=0;i
<(length
);i
++) {
991 /* mask a nibble at a time and encode */
992 target
[j
] = 'A' + (0x0F & (source
[i
] >> 4));
993 target
[j
+1] = 'A' + (0x0F & source
[i
]);
1001 ipv4_connect(struct sockaddr_in
*psin_server
, struct socket
**csocket
,
1002 char * netbios_name
)
1006 __be16 orig_port
= 0;
1008 if(*csocket
== NULL
) {
1009 rc
= sock_create_kern(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, csocket
);
1011 cERROR(1, ("Error %d creating socket",rc
));
1015 /* BB other socket options to set KEEPALIVE, NODELAY? */
1016 cFYI(1,("Socket created"));
1017 (*csocket
)->sk
->sk_allocation
= GFP_NOFS
;
1021 psin_server
->sin_family
= AF_INET
;
1022 if(psin_server
->sin_port
) { /* user overrode default port */
1023 rc
= (*csocket
)->ops
->connect(*csocket
,
1024 (struct sockaddr
*) psin_server
,
1025 sizeof (struct sockaddr_in
),0);
1031 /* save original port so we can retry user specified port
1032 later if fall back ports fail this time */
1033 orig_port
= psin_server
->sin_port
;
1035 /* do not retry on the same port we just failed on */
1036 if(psin_server
->sin_port
!= htons(CIFS_PORT
)) {
1037 psin_server
->sin_port
= htons(CIFS_PORT
);
1039 rc
= (*csocket
)->ops
->connect(*csocket
,
1040 (struct sockaddr
*) psin_server
,
1041 sizeof (struct sockaddr_in
),0);
1047 psin_server
->sin_port
= htons(RFC1001_PORT
);
1048 rc
= (*csocket
)->ops
->connect(*csocket
, (struct sockaddr
*)
1049 psin_server
, sizeof (struct sockaddr_in
),0);
1054 /* give up here - unless we want to retry on different
1055 protocol families some day */
1058 psin_server
->sin_port
= orig_port
;
1059 cFYI(1,("Error %d connecting to server via ipv4",rc
));
1060 sock_release(*csocket
);
1064 /* Eventually check for other socket options to change from
1065 the default. sock_setsockopt not used because it expects
1066 user space buffer */
1067 (*csocket
)->sk
->sk_rcvtimeo
= 7 * HZ
;
1069 /* send RFC1001 sessinit */
1071 if(psin_server
->sin_port
== htons(RFC1001_PORT
)) {
1072 /* some servers require RFC1001 sessinit before sending
1073 negprot - BB check reconnection in case where second
1074 sessinit is sent but no second negprot */
1075 struct rfc1002_session_packet
* ses_init_buf
;
1076 struct smb_hdr
* smb_buf
;
1077 ses_init_buf
= cifs_kcalloc(sizeof(struct rfc1002_session_packet
), GFP_KERNEL
);
1079 ses_init_buf
->trailer
.session_req
.called_len
= 32;
1080 rfc1002mangle(ses_init_buf
->trailer
.session_req
.called_name
,
1081 DEFAULT_CIFS_CALLED_NAME
,16);
1082 ses_init_buf
->trailer
.session_req
.calling_len
= 32;
1083 /* calling name ends in null (byte 16) from old smb
1085 if(netbios_name
&& (netbios_name
[0] !=0)) {
1086 rfc1002mangle(ses_init_buf
->trailer
.session_req
.calling_name
,
1089 rfc1002mangle(ses_init_buf
->trailer
.session_req
.calling_name
,
1090 "LINUX_CIFS_CLNT",16);
1092 ses_init_buf
->trailer
.session_req
.scope1
= 0;
1093 ses_init_buf
->trailer
.session_req
.scope2
= 0;
1094 smb_buf
= (struct smb_hdr
*)ses_init_buf
;
1095 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1096 smb_buf
->smb_buf_length
= 0x81000044;
1097 rc
= smb_send(*csocket
, smb_buf
, 0x44,
1098 (struct sockaddr
*)psin_server
);
1099 kfree(ses_init_buf
);
1101 /* else the negprot may still work without this
1102 even though malloc failed */
1110 ipv6_connect(struct sockaddr_in6
*psin_server
, struct socket
**csocket
)
1114 __be16 orig_port
= 0;
1116 if(*csocket
== NULL
) {
1117 rc
= sock_create_kern(PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, csocket
);
1119 cERROR(1, ("Error %d creating ipv6 socket",rc
));
1123 /* BB other socket options to set KEEPALIVE, NODELAY? */
1124 cFYI(1,("ipv6 Socket created"));
1125 (*csocket
)->sk
->sk_allocation
= GFP_NOFS
;
1129 psin_server
->sin6_family
= AF_INET6
;
1131 if(psin_server
->sin6_port
) { /* user overrode default port */
1132 rc
= (*csocket
)->ops
->connect(*csocket
,
1133 (struct sockaddr
*) psin_server
,
1134 sizeof (struct sockaddr_in6
),0);
1140 /* save original port so we can retry user specified port
1141 later if fall back ports fail this time */
1143 orig_port
= psin_server
->sin6_port
;
1144 /* do not retry on the same port we just failed on */
1145 if(psin_server
->sin6_port
!= htons(CIFS_PORT
)) {
1146 psin_server
->sin6_port
= htons(CIFS_PORT
);
1148 rc
= (*csocket
)->ops
->connect(*csocket
,
1149 (struct sockaddr
*) psin_server
,
1150 sizeof (struct sockaddr_in6
),0);
1156 psin_server
->sin6_port
= htons(RFC1001_PORT
);
1157 rc
= (*csocket
)->ops
->connect(*csocket
, (struct sockaddr
*)
1158 psin_server
, sizeof (struct sockaddr_in6
),0);
1163 /* give up here - unless we want to retry on different
1164 protocol families some day */
1167 psin_server
->sin6_port
= orig_port
;
1168 cFYI(1,("Error %d connecting to server via ipv6",rc
));
1169 sock_release(*csocket
);
1173 /* Eventually check for other socket options to change from
1174 the default. sock_setsockopt not used because it expects
1175 user space buffer */
1176 (*csocket
)->sk
->sk_rcvtimeo
= 7 * HZ
;
1182 cifs_mount(struct super_block
*sb
, struct cifs_sb_info
*cifs_sb
,
1183 char *mount_data
, const char *devname
)
1187 int address_type
= AF_INET
;
1188 struct socket
*csocket
= NULL
;
1189 struct sockaddr_in sin_server
;
1190 struct sockaddr_in6 sin_server6
;
1191 struct smb_vol volume_info
;
1192 struct cifsSesInfo
*pSesInfo
= NULL
;
1193 struct cifsSesInfo
*existingCifsSes
= NULL
;
1194 struct cifsTconInfo
*tcon
= NULL
;
1195 struct TCP_Server_Info
*srvTcp
= NULL
;
1199 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1201 memset(&volume_info
,0,sizeof(struct smb_vol
));
1202 if (cifs_parse_mount_options(mount_data
, devname
, &volume_info
)) {
1204 kfree(volume_info
.UNC
);
1205 if(volume_info
.password
)
1206 kfree(volume_info
.password
);
1211 if (volume_info
.username
) {
1212 /* BB fixme parse for domain name here */
1213 cFYI(1, ("Username: %s ", volume_info
.username
));
1216 cifserror("No username specified ");
1217 /* In userspace mount helper we can get user name from alternate
1218 locations such as env variables and files on disk */
1220 kfree(volume_info
.UNC
);
1221 if(volume_info
.password
)
1222 kfree(volume_info
.password
);
1227 if (volume_info
.UNCip
&& volume_info
.UNC
) {
1228 rc
= cifs_inet_pton(AF_INET
, volume_info
.UNCip
,&sin_server
.sin_addr
.s_addr
);
1231 /* not ipv4 address, try ipv6 */
1232 rc
= cifs_inet_pton(AF_INET6
,volume_info
.UNCip
,&sin_server6
.sin6_addr
.in6_u
);
1234 address_type
= AF_INET6
;
1236 address_type
= AF_INET
;
1240 /* we failed translating address */
1242 kfree(volume_info
.UNC
);
1243 if(volume_info
.password
)
1244 kfree(volume_info
.password
);
1249 cFYI(1, ("UNC: %s ip: %s", volume_info
.UNC
, volume_info
.UNCip
));
1252 } else if (volume_info
.UNCip
){
1253 /* BB using ip addr as server name connect to the DFS root below */
1254 cERROR(1,("Connecting to DFS root not implemented yet"));
1256 kfree(volume_info
.UNC
);
1257 if(volume_info
.password
)
1258 kfree(volume_info
.password
);
1261 } else /* which servers DFS root would we conect to */ {
1263 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1265 kfree(volume_info
.UNC
);
1266 if(volume_info
.password
)
1267 kfree(volume_info
.password
);
1272 /* this is needed for ASCII cp to Unicode converts */
1273 if(volume_info
.iocharset
== NULL
) {
1274 cifs_sb
->local_nls
= load_nls_default();
1275 /* load_nls_default can not return null */
1277 cifs_sb
->local_nls
= load_nls(volume_info
.iocharset
);
1278 if(cifs_sb
->local_nls
== NULL
) {
1279 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info
.iocharset
));
1281 kfree(volume_info
.UNC
);
1282 if(volume_info
.password
)
1283 kfree(volume_info
.password
);
1289 if(address_type
== AF_INET
)
1290 existingCifsSes
= cifs_find_tcp_session(&sin_server
.sin_addr
,
1291 NULL
/* no ipv6 addr */,
1292 volume_info
.username
, &srvTcp
);
1293 else if(address_type
== AF_INET6
)
1294 existingCifsSes
= cifs_find_tcp_session(NULL
/* no ipv4 addr */,
1295 &sin_server6
.sin6_addr
,
1296 volume_info
.username
, &srvTcp
);
1299 kfree(volume_info
.UNC
);
1300 if(volume_info
.password
)
1301 kfree(volume_info
.password
);
1308 cFYI(1, ("Existing tcp session with server found "));
1309 } else { /* create socket */
1310 if(volume_info
.port
)
1311 sin_server
.sin_port
= htons(volume_info
.port
);
1313 sin_server
.sin_port
= 0;
1314 rc
= ipv4_connect(&sin_server
,&csocket
,volume_info
.source_rfc1001_name
);
1317 ("Error connecting to IPv4 socket. Aborting operation"));
1319 sock_release(csocket
);
1321 kfree(volume_info
.UNC
);
1322 if(volume_info
.password
)
1323 kfree(volume_info
.password
);
1328 srvTcp
= kmalloc(sizeof (struct TCP_Server_Info
), GFP_KERNEL
);
1329 if (srvTcp
== NULL
) {
1331 sock_release(csocket
);
1333 kfree(volume_info
.UNC
);
1334 if(volume_info
.password
)
1335 kfree(volume_info
.password
);
1339 memset(srvTcp
, 0, sizeof (struct TCP_Server_Info
));
1340 memcpy(&srvTcp
->addr
.sockAddr
, &sin_server
, sizeof (struct sockaddr_in
));
1341 atomic_set(&srvTcp
->inFlight
,0);
1342 /* BB Add code for ipv6 case too */
1343 srvTcp
->ssocket
= csocket
;
1344 srvTcp
->protocolType
= IPV4
;
1345 init_waitqueue_head(&srvTcp
->response_q
);
1346 init_waitqueue_head(&srvTcp
->request_q
);
1347 INIT_LIST_HEAD(&srvTcp
->pending_mid_q
);
1348 /* at this point we are the only ones with the pointer
1349 to the struct since the kernel thread not created yet
1350 so no need to spinlock this init of tcpStatus */
1351 srvTcp
->tcpStatus
= CifsNew
;
1352 init_MUTEX(&srvTcp
->tcpSem
);
1353 rc
= (int)kernel_thread((void *)(void *)cifs_demultiplex_thread
, srvTcp
,
1354 CLONE_FS
| CLONE_FILES
| CLONE_VM
);
1357 sock_release(csocket
);
1359 kfree(volume_info
.UNC
);
1360 if(volume_info
.password
)
1361 kfree(volume_info
.password
);
1366 memcpy(srvTcp
->workstation_RFC1001_name
, volume_info
.source_rfc1001_name
,16);
1367 srvTcp
->sequence_number
= 0;
1371 if (existingCifsSes
) {
1372 pSesInfo
= existingCifsSes
;
1373 cFYI(1, ("Existing smb sess found "));
1374 if(volume_info
.password
)
1375 kfree(volume_info
.password
);
1376 /* volume_info.UNC freed at end of function */
1378 cFYI(1, ("Existing smb sess not found "));
1379 pSesInfo
= sesInfoAlloc();
1380 if (pSesInfo
== NULL
)
1383 pSesInfo
->server
= srvTcp
;
1384 sprintf(pSesInfo
->serverName
, "%u.%u.%u.%u",
1385 NIPQUAD(sin_server
.sin_addr
.s_addr
));
1389 /* volume_info.password freed at unmount */
1390 if (volume_info
.password
)
1391 pSesInfo
->password
= volume_info
.password
;
1392 if (volume_info
.username
)
1393 strncpy(pSesInfo
->userName
,
1394 volume_info
.username
,MAX_USERNAME_SIZE
);
1395 if (volume_info
.domainname
)
1396 strncpy(pSesInfo
->domainName
,
1397 volume_info
.domainname
,MAX_USERNAME_SIZE
);
1398 pSesInfo
->linux_uid
= volume_info
.linux_uid
;
1399 down(&pSesInfo
->sesSem
);
1400 rc
= cifs_setup_session(xid
,pSesInfo
, cifs_sb
->local_nls
);
1401 up(&pSesInfo
->sesSem
);
1403 atomic_inc(&srvTcp
->socketUseCount
);
1405 if(volume_info
.password
)
1406 kfree(volume_info
.password
);
1409 /* search for existing tcon to this server share */
1411 if((volume_info
.rsize
) && (volume_info
.rsize
<= CIFSMaxBufSize
))
1412 cifs_sb
->rsize
= volume_info
.rsize
;
1414 cifs_sb
->rsize
= srvTcp
->maxBuf
- MAX_CIFS_HDR_SIZE
; /* default */
1415 if((volume_info
.wsize
) && (volume_info
.wsize
<= CIFSMaxBufSize
))
1416 cifs_sb
->wsize
= volume_info
.wsize
;
1418 cifs_sb
->wsize
= CIFSMaxBufSize
; /* default */
1419 if(cifs_sb
->rsize
< PAGE_CACHE_SIZE
) {
1420 cifs_sb
->rsize
= PAGE_CACHE_SIZE
;
1421 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1423 cifs_sb
->mnt_uid
= volume_info
.linux_uid
;
1424 cifs_sb
->mnt_gid
= volume_info
.linux_gid
;
1425 cifs_sb
->mnt_file_mode
= volume_info
.file_mode
;
1426 cifs_sb
->mnt_dir_mode
= volume_info
.dir_mode
;
1427 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb
->mnt_file_mode
,cifs_sb
->mnt_dir_mode
));
1429 if(volume_info
.noperm
)
1430 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_NO_PERM
;
1431 if(volume_info
.setuids
)
1432 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_SET_UID
;
1433 if(volume_info
.server_ino
)
1434 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_SERVER_INUM
;
1435 if(volume_info
.remap
)
1436 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_MAP_SPECIAL_CHR
;
1437 if(volume_info
.no_xattr
)
1438 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_NO_XATTR
;
1439 if(volume_info
.direct_io
) {
1440 cERROR(1,("mounting share using direct i/o"));
1441 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_DIRECT_IO
;
1445 find_unc(sin_server
.sin_addr
.s_addr
, volume_info
.UNC
,
1446 volume_info
.username
);
1448 cFYI(1, ("Found match on UNC path "));
1449 /* we can have only one retry value for a connection
1450 to a share so for resources mounted more than once
1451 to the same server share the last value passed in
1452 for the retry flag is used */
1453 tcon
->retry
= volume_info
.retry
;
1455 tcon
= tconInfoAlloc();
1459 /* check for null share name ie connect to dfs root */
1461 /* BB check if this works for exactly length three strings */
1462 if ((strchr(volume_info
.UNC
+ 3, '\\') == NULL
)
1463 && (strchr(volume_info
.UNC
+ 3, '/') ==
1465 rc
= connect_to_dfs_path(xid
, pSesInfo
,
1466 "", cifs_sb
->local_nls
,
1467 cifs_sb
->mnt_cifs_flags
&
1468 CIFS_MOUNT_MAP_SPECIAL_CHR
);
1470 kfree(volume_info
.UNC
);
1474 rc
= CIFSTCon(xid
, pSesInfo
,
1476 tcon
, cifs_sb
->local_nls
);
1477 cFYI(1, ("CIFS Tcon rc = %d", rc
));
1480 atomic_inc(&pSesInfo
->inUse
);
1481 tcon
->retry
= volume_info
.retry
;
1487 if (pSesInfo
->capabilities
& CAP_LARGE_FILES
) {
1488 sb
->s_maxbytes
= (u64
) 1 << 63;
1490 sb
->s_maxbytes
= (u64
) 1 << 31; /* 2 GB */
1493 sb
->s_time_gran
= 100;
1495 /* on error free sesinfo and tcon struct if needed */
1497 /* if session setup failed, use count is zero but
1498 we still need to free cifsd thread */
1499 if(atomic_read(&srvTcp
->socketUseCount
) == 0) {
1500 spin_lock(&GlobalMid_Lock
);
1501 srvTcp
->tcpStatus
= CifsExiting
;
1502 spin_unlock(&GlobalMid_Lock
);
1504 send_sig(SIGKILL
,srvTcp
->tsk
,1);
1506 /* If find_unc succeeded then rc == 0 so we can not end */
1507 if (tcon
) /* up accidently freeing someone elses tcon struct */
1509 if (existingCifsSes
== NULL
) {
1511 if ((pSesInfo
->server
) &&
1512 (pSesInfo
->status
== CifsGood
)) {
1514 temp_rc
= CIFSSMBLogoff(xid
, pSesInfo
);
1515 /* if the socketUseCount is now zero */
1516 if((temp_rc
== -ESHUTDOWN
) &&
1517 (pSesInfo
->server
->tsk
))
1518 send_sig(SIGKILL
,pSesInfo
->server
->tsk
,1);
1520 cFYI(1, ("No session or bad tcon"));
1521 sesInfoFree(pSesInfo
);
1522 /* pSesInfo = NULL; */
1526 atomic_inc(&tcon
->useCount
);
1527 cifs_sb
->tcon
= tcon
;
1528 tcon
->ses
= pSesInfo
;
1530 /* do not care if following two calls succeed - informational only */
1531 CIFSSMBQFSDeviceInfo(xid
, tcon
);
1532 CIFSSMBQFSAttributeInfo(xid
, tcon
);
1533 if (tcon
->ses
->capabilities
& CAP_UNIX
) {
1534 if(!CIFSSMBQFSUnixInfo(xid
, tcon
)) {
1535 if(!volume_info
.no_psx_acl
) {
1536 if(CIFS_UNIX_POSIX_ACL_CAP
&
1537 le64_to_cpu(tcon
->fsUnixInfo
.Capability
))
1538 cFYI(1,("server negotiated posix acl support"));
1539 sb
->s_flags
|= MS_POSIXACL
;
1545 /* volume_info.password is freed above when existing session found
1546 (in which case it is not needed anymore) but when new sesion is created
1547 the password ptr is put in the new session structure (in which case the
1548 password will be freed at unmount time) */
1550 kfree(volume_info
.UNC
);
1556 CIFSSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
1557 char session_key
[CIFS_SESSION_KEY_SIZE
],
1558 const struct nls_table
*nls_codepage
)
1560 struct smb_hdr
*smb_buffer
;
1561 struct smb_hdr
*smb_buffer_response
;
1562 SESSION_SETUP_ANDX
*pSMB
;
1563 SESSION_SETUP_ANDX
*pSMBr
;
1568 int remaining_words
= 0;
1569 int bytes_returned
= 0;
1574 cFYI(1, ("In sesssetup "));
1577 user
= ses
->userName
;
1578 domain
= ses
->domainName
;
1579 smb_buffer
= cifs_buf_get();
1580 if (smb_buffer
== NULL
) {
1583 smb_buffer_response
= smb_buffer
;
1584 pSMBr
= pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
1586 /* send SMBsessionSetup here */
1587 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
1588 NULL
/* no tCon exists yet */ , 13 /* wct */ );
1590 pSMB
->req_no_secext
.AndXCommand
= 0xFF;
1591 pSMB
->req_no_secext
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
1592 pSMB
->req_no_secext
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
1594 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
1595 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
1597 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
1598 CAP_LARGE_WRITE_X
| CAP_LARGE_READ_X
;
1599 if (ses
->capabilities
& CAP_UNICODE
) {
1600 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
1601 capabilities
|= CAP_UNICODE
;
1603 if (ses
->capabilities
& CAP_STATUS32
) {
1604 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
1605 capabilities
|= CAP_STATUS32
;
1607 if (ses
->capabilities
& CAP_DFS
) {
1608 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
1609 capabilities
|= CAP_DFS
;
1611 pSMB
->req_no_secext
.Capabilities
= cpu_to_le32(capabilities
);
1613 pSMB
->req_no_secext
.CaseInsensitivePasswordLength
=
1614 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
1616 pSMB
->req_no_secext
.CaseSensitivePasswordLength
=
1617 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
1618 bcc_ptr
= pByteArea(smb_buffer
);
1619 memcpy(bcc_ptr
, (char *) session_key
, CIFS_SESSION_KEY_SIZE
);
1620 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
1621 memcpy(bcc_ptr
, (char *) session_key
, CIFS_SESSION_KEY_SIZE
);
1622 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
1624 if (ses
->capabilities
& CAP_UNICODE
) {
1625 if ((long) bcc_ptr
% 2) { /* must be word aligned for Unicode */
1630 bytes_returned
= 0; /* skill null user */
1633 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 100,
1635 /* convert number of 16 bit words to bytes */
1636 bcc_ptr
+= 2 * bytes_returned
;
1637 bcc_ptr
+= 2; /* trailing null */
1640 cifs_strtoUCS((wchar_t *) bcc_ptr
,
1641 "CIFS_LINUX_DOM", 32, nls_codepage
);
1644 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
1646 bcc_ptr
+= 2 * bytes_returned
;
1649 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
1651 bcc_ptr
+= 2 * bytes_returned
;
1653 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
,
1655 bcc_ptr
+= 2 * bytes_returned
;
1658 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
1660 bcc_ptr
+= 2 * bytes_returned
;
1664 strncpy(bcc_ptr
, user
, 200);
1665 bcc_ptr
+= strnlen(user
, 200);
1669 if (domain
== NULL
) {
1670 strcpy(bcc_ptr
, "CIFS_LINUX_DOM");
1671 bcc_ptr
+= strlen("CIFS_LINUX_DOM") + 1;
1673 strncpy(bcc_ptr
, domain
, 64);
1674 bcc_ptr
+= strnlen(domain
, 64);
1678 strcpy(bcc_ptr
, "Linux version ");
1679 bcc_ptr
+= strlen("Linux version ");
1680 strcpy(bcc_ptr
, system_utsname
.release
);
1681 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
1682 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
1683 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
1685 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
1686 smb_buffer
->smb_buf_length
+= count
;
1687 pSMB
->req_no_secext
.ByteCount
= cpu_to_le16(count
);
1689 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
1690 &bytes_returned
, 1);
1692 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1693 } else if ((smb_buffer_response
->WordCount
== 3)
1694 || (smb_buffer_response
->WordCount
== 4)) {
1695 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
1696 __u16 blob_len
= le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
1697 if (action
& GUEST_LOGIN
)
1698 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1699 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format (le) */
1700 cFYI(1, ("UID = %d ", ses
->Suid
));
1701 /* response can have either 3 or 4 word count - Samba sends 3 */
1702 bcc_ptr
= pByteArea(smb_buffer_response
);
1703 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
1704 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
1705 && (blob_len
< pSMBr
->resp
.ByteCount
))) {
1706 if (pSMBr
->resp
.hdr
.WordCount
== 4)
1707 bcc_ptr
+= blob_len
;
1709 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
1710 if ((long) (bcc_ptr
) % 2) {
1712 (BCC(smb_buffer_response
) - 1) /2;
1713 bcc_ptr
++; /* Unicode strings must be word aligned */
1716 BCC(smb_buffer_response
) / 2;
1719 UniStrnlen((wchar_t *) bcc_ptr
,
1720 remaining_words
- 1);
1721 /* We look for obvious messed up bcc or strings in response so we do not go off
1722 the end since (at least) WIN2K and Windows XP have a major bug in not null
1723 terminating last Unicode string in response */
1724 ses
->serverOS
= cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
1725 cifs_strfromUCS_le(ses
->serverOS
,
1726 (wchar_t *)bcc_ptr
, len
,nls_codepage
);
1727 bcc_ptr
+= 2 * (len
+ 1);
1728 remaining_words
-= len
+ 1;
1729 ses
->serverOS
[2 * len
] = 0;
1730 ses
->serverOS
[1 + (2 * len
)] = 0;
1731 if (remaining_words
> 0) {
1732 len
= UniStrnlen((wchar_t *)bcc_ptr
,
1734 ses
->serverNOS
=cifs_kcalloc(2 * (len
+ 1),GFP_KERNEL
);
1735 cifs_strfromUCS_le(ses
->serverNOS
,
1736 (wchar_t *)bcc_ptr
,len
,nls_codepage
);
1737 bcc_ptr
+= 2 * (len
+ 1);
1738 ses
->serverNOS
[2 * len
] = 0;
1739 ses
->serverNOS
[1 + (2 * len
)] = 0;
1740 if(strncmp(ses
->serverNOS
,
1741 "NT LAN Manager 4",16) == 0) {
1742 cFYI(1,("NT4 server"));
1743 ses
->flags
|= CIFS_SES_NT4
;
1745 remaining_words
-= len
+ 1;
1746 if (remaining_words
> 0) {
1747 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
1748 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1750 cifs_kcalloc(2*(len
+1),GFP_KERNEL
);
1751 cifs_strfromUCS_le(ses
->serverDomain
,
1752 (wchar_t *)bcc_ptr
,len
,nls_codepage
);
1753 bcc_ptr
+= 2 * (len
+ 1);
1754 ses
->serverDomain
[2*len
] = 0;
1755 ses
->serverDomain
[1+(2*len
)] = 0;
1756 } /* else no more room so create dummy domain string */
1761 } else { /* no room so create dummy domain and NOS string */
1763 cifs_kcalloc(2, GFP_KERNEL
);
1765 cifs_kcalloc(2, GFP_KERNEL
);
1767 } else { /* ASCII */
1768 len
= strnlen(bcc_ptr
, 1024);
1769 if (((long) bcc_ptr
+ len
) - (long)
1770 pByteArea(smb_buffer_response
)
1771 <= BCC(smb_buffer_response
)) {
1772 ses
->serverOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1773 strncpy(ses
->serverOS
,bcc_ptr
, len
);
1776 bcc_ptr
[0] = 0; /* null terminate the string */
1779 len
= strnlen(bcc_ptr
, 1024);
1780 ses
->serverNOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1781 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
1786 len
= strnlen(bcc_ptr
, 1024);
1787 ses
->serverDomain
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1788 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
1794 ("Variable field of length %d extends beyond end of smb ",
1799 (" Security Blob Length extends beyond end of SMB"));
1803 (" Invalid Word count %d: ",
1804 smb_buffer_response
->WordCount
));
1809 cifs_buf_release(smb_buffer
);
1815 CIFSSpnegoSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
1816 char *SecurityBlob
,int SecurityBlobLength
,
1817 const struct nls_table
*nls_codepage
)
1819 struct smb_hdr
*smb_buffer
;
1820 struct smb_hdr
*smb_buffer_response
;
1821 SESSION_SETUP_ANDX
*pSMB
;
1822 SESSION_SETUP_ANDX
*pSMBr
;
1827 int remaining_words
= 0;
1828 int bytes_returned
= 0;
1833 cFYI(1, ("In spnego sesssetup "));
1836 user
= ses
->userName
;
1837 domain
= ses
->domainName
;
1839 smb_buffer
= cifs_buf_get();
1840 if (smb_buffer
== NULL
) {
1843 smb_buffer_response
= smb_buffer
;
1844 pSMBr
= pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
1846 /* send SMBsessionSetup here */
1847 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
1848 NULL
/* no tCon exists yet */ , 12 /* wct */ );
1849 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
1850 pSMB
->req
.AndXCommand
= 0xFF;
1851 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
1852 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
1854 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
1855 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
1857 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
1858 CAP_EXTENDED_SECURITY
;
1859 if (ses
->capabilities
& CAP_UNICODE
) {
1860 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
1861 capabilities
|= CAP_UNICODE
;
1863 if (ses
->capabilities
& CAP_STATUS32
) {
1864 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
1865 capabilities
|= CAP_STATUS32
;
1867 if (ses
->capabilities
& CAP_DFS
) {
1868 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
1869 capabilities
|= CAP_DFS
;
1871 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
1873 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
1874 bcc_ptr
= pByteArea(smb_buffer
);
1875 memcpy(bcc_ptr
, SecurityBlob
, SecurityBlobLength
);
1876 bcc_ptr
+= SecurityBlobLength
;
1878 if (ses
->capabilities
& CAP_UNICODE
) {
1879 if ((long) bcc_ptr
% 2) { /* must be word aligned for Unicode strings */
1884 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 100, nls_codepage
);
1885 bcc_ptr
+= 2 * bytes_returned
; /* convert num of 16 bit words to bytes */
1886 bcc_ptr
+= 2; /* trailing null */
1889 cifs_strtoUCS((wchar_t *) bcc_ptr
,
1890 "CIFS_LINUX_DOM", 32, nls_codepage
);
1893 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
1895 bcc_ptr
+= 2 * bytes_returned
;
1898 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
1900 bcc_ptr
+= 2 * bytes_returned
;
1902 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
1904 bcc_ptr
+= 2 * bytes_returned
;
1907 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
1909 bcc_ptr
+= 2 * bytes_returned
;
1912 strncpy(bcc_ptr
, user
, 200);
1913 bcc_ptr
+= strnlen(user
, 200);
1916 if (domain
== NULL
) {
1917 strcpy(bcc_ptr
, "CIFS_LINUX_DOM");
1918 bcc_ptr
+= strlen("CIFS_LINUX_DOM") + 1;
1920 strncpy(bcc_ptr
, domain
, 64);
1921 bcc_ptr
+= strnlen(domain
, 64);
1925 strcpy(bcc_ptr
, "Linux version ");
1926 bcc_ptr
+= strlen("Linux version ");
1927 strcpy(bcc_ptr
, system_utsname
.release
);
1928 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
1929 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
1930 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
1932 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
1933 smb_buffer
->smb_buf_length
+= count
;
1934 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
1936 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
1937 &bytes_returned
, 1);
1939 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1940 } else if ((smb_buffer_response
->WordCount
== 3)
1941 || (smb_buffer_response
->WordCount
== 4)) {
1942 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
1944 le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
1945 if (action
& GUEST_LOGIN
)
1946 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1948 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format (le) */
1949 cFYI(1, ("UID = %d ", ses
->Suid
));
1950 bcc_ptr
= pByteArea(smb_buffer_response
); /* response can have either 3 or 4 word count - Samba sends 3 */
1952 /* BB Fix below to make endian neutral !! */
1954 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
1955 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
1957 pSMBr
->resp
.ByteCount
))) {
1958 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
1962 ("Security Blob Length %d ",
1966 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
1967 if ((long) (bcc_ptr
) % 2) {
1969 (BCC(smb_buffer_response
)
1971 bcc_ptr
++; /* Unicode strings must be word aligned */
1975 (smb_buffer_response
) / 2;
1978 UniStrnlen((wchar_t *) bcc_ptr
,
1979 remaining_words
- 1);
1980 /* We look for obvious messed up bcc or strings in response so we do not go off
1981 the end since (at least) WIN2K and Windows XP have a major bug in not null
1982 terminating last Unicode string in response */
1984 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
1985 cifs_strfromUCS_le(ses
->serverOS
,
1989 bcc_ptr
+= 2 * (len
+ 1);
1990 remaining_words
-= len
+ 1;
1991 ses
->serverOS
[2 * len
] = 0;
1992 ses
->serverOS
[1 + (2 * len
)] = 0;
1993 if (remaining_words
> 0) {
1994 len
= UniStrnlen((wchar_t *)bcc_ptr
,
1998 cifs_kcalloc(2 * (len
+ 1),
2000 cifs_strfromUCS_le(ses
->serverNOS
,
2004 bcc_ptr
+= 2 * (len
+ 1);
2005 ses
->serverNOS
[2 * len
] = 0;
2006 ses
->serverNOS
[1 + (2 * len
)] = 0;
2007 remaining_words
-= len
+ 1;
2008 if (remaining_words
> 0) {
2009 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
2010 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2011 ses
->serverDomain
= cifs_kcalloc(2*(len
+1),GFP_KERNEL
);
2012 cifs_strfromUCS_le(ses
->serverDomain
,
2016 bcc_ptr
+= 2*(len
+1);
2017 ses
->serverDomain
[2*len
] = 0;
2018 ses
->serverDomain
[1+(2*len
)] = 0;
2019 } /* else no more room so create dummy domain string */
2022 cifs_kcalloc(2,GFP_KERNEL
);
2023 } else { /* no room so create dummy domain and NOS string */
2024 ses
->serverDomain
= cifs_kcalloc(2, GFP_KERNEL
);
2025 ses
->serverNOS
= cifs_kcalloc(2, GFP_KERNEL
);
2027 } else { /* ASCII */
2029 len
= strnlen(bcc_ptr
, 1024);
2030 if (((long) bcc_ptr
+ len
) - (long)
2031 pByteArea(smb_buffer_response
)
2032 <= BCC(smb_buffer_response
)) {
2033 ses
->serverOS
= cifs_kcalloc(len
+ 1, GFP_KERNEL
);
2034 strncpy(ses
->serverOS
, bcc_ptr
, len
);
2037 bcc_ptr
[0] = 0; /* null terminate the string */
2040 len
= strnlen(bcc_ptr
, 1024);
2041 ses
->serverNOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
2042 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2047 len
= strnlen(bcc_ptr
, 1024);
2048 ses
->serverDomain
= cifs_kcalloc(len
+ 1, GFP_KERNEL
);
2049 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2055 ("Variable field of length %d extends beyond end of smb ",
2060 (" Security Blob Length extends beyond end of SMB"));
2063 cERROR(1, ("No session structure passed in."));
2067 (" Invalid Word count %d: ",
2068 smb_buffer_response
->WordCount
));
2073 cifs_buf_release(smb_buffer
);
2079 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid
,
2080 struct cifsSesInfo
*ses
, int * pNTLMv2_flag
,
2081 const struct nls_table
*nls_codepage
)
2083 struct smb_hdr
*smb_buffer
;
2084 struct smb_hdr
*smb_buffer_response
;
2085 SESSION_SETUP_ANDX
*pSMB
;
2086 SESSION_SETUP_ANDX
*pSMBr
;
2090 int remaining_words
= 0;
2091 int bytes_returned
= 0;
2093 int SecurityBlobLength
= sizeof (NEGOTIATE_MESSAGE
);
2094 PNEGOTIATE_MESSAGE SecurityBlob
;
2095 PCHALLENGE_MESSAGE SecurityBlob2
;
2096 __u32 negotiate_flags
, capabilities
;
2099 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2102 domain
= ses
->domainName
;
2103 *pNTLMv2_flag
= FALSE
;
2104 smb_buffer
= cifs_buf_get();
2105 if (smb_buffer
== NULL
) {
2108 smb_buffer_response
= smb_buffer
;
2109 pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
2110 pSMBr
= (SESSION_SETUP_ANDX
*) smb_buffer_response
;
2112 /* send SMBsessionSetup here */
2113 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
2114 NULL
/* no tCon exists yet */ , 12 /* wct */ );
2115 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
2116 pSMB
->req
.hdr
.Flags
|= (SMBFLG_CASELESS
| SMBFLG_CANONICAL_PATH_FORMAT
);
2118 pSMB
->req
.AndXCommand
= 0xFF;
2119 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
2120 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
2122 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2123 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2125 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
2126 CAP_EXTENDED_SECURITY
;
2127 if (ses
->capabilities
& CAP_UNICODE
) {
2128 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2129 capabilities
|= CAP_UNICODE
;
2131 if (ses
->capabilities
& CAP_STATUS32
) {
2132 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2133 capabilities
|= CAP_STATUS32
;
2135 if (ses
->capabilities
& CAP_DFS
) {
2136 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2137 capabilities
|= CAP_DFS
;
2139 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
2141 bcc_ptr
= (char *) &pSMB
->req
.SecurityBlob
;
2142 SecurityBlob
= (PNEGOTIATE_MESSAGE
) bcc_ptr
;
2143 strncpy(SecurityBlob
->Signature
, NTLMSSP_SIGNATURE
, 8);
2144 SecurityBlob
->MessageType
= NtLmNegotiate
;
2146 NTLMSSP_NEGOTIATE_UNICODE
| NTLMSSP_NEGOTIATE_OEM
|
2147 NTLMSSP_REQUEST_TARGET
| NTLMSSP_NEGOTIATE_NTLM
| 0x80000000 |
2148 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128
;
2150 negotiate_flags
|= NTLMSSP_NEGOTIATE_SIGN
;
2152 negotiate_flags
|= NTLMSSP_NEGOTIATE_NTLMV2
;
2153 /* setup pointers to domain name and workstation name */
2154 bcc_ptr
+= SecurityBlobLength
;
2156 SecurityBlob
->WorkstationName
.Buffer
= 0;
2157 SecurityBlob
->WorkstationName
.Length
= 0;
2158 SecurityBlob
->WorkstationName
.MaximumLength
= 0;
2160 if (domain
== NULL
) {
2161 SecurityBlob
->DomainName
.Buffer
= 0;
2162 SecurityBlob
->DomainName
.Length
= 0;
2163 SecurityBlob
->DomainName
.MaximumLength
= 0;
2166 negotiate_flags
|= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED
;
2167 strncpy(bcc_ptr
, domain
, 63);
2168 len
= strnlen(domain
, 64);
2169 SecurityBlob
->DomainName
.MaximumLength
=
2171 SecurityBlob
->DomainName
.Buffer
=
2172 cpu_to_le32((long) &SecurityBlob
->
2174 (long) &SecurityBlob
->Signature
);
2176 SecurityBlobLength
+= len
;
2177 SecurityBlob
->DomainName
.Length
=
2180 if (ses
->capabilities
& CAP_UNICODE
) {
2181 if ((long) bcc_ptr
% 2) {
2187 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
2189 bcc_ptr
+= 2 * bytes_returned
;
2191 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
2193 bcc_ptr
+= 2 * bytes_returned
;
2194 bcc_ptr
+= 2; /* null terminate Linux version */
2196 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
2198 bcc_ptr
+= 2 * bytes_returned
;
2201 bcc_ptr
+= 2; /* null terminate network opsys string */
2204 bcc_ptr
+= 2; /* null domain */
2205 } else { /* ASCII */
2206 strcpy(bcc_ptr
, "Linux version ");
2207 bcc_ptr
+= strlen("Linux version ");
2208 strcpy(bcc_ptr
, system_utsname
.release
);
2209 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
2210 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
2211 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
2212 bcc_ptr
++; /* empty domain field */
2215 SecurityBlob
->NegotiateFlags
= cpu_to_le32(negotiate_flags
);
2216 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
2217 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
2218 smb_buffer
->smb_buf_length
+= count
;
2219 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
2221 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
2222 &bytes_returned
, 1);
2224 if (smb_buffer_response
->Status
.CifsError
==
2225 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED
))
2229 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2230 } else if ((smb_buffer_response
->WordCount
== 3)
2231 || (smb_buffer_response
->WordCount
== 4)) {
2232 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
2233 __u16 blob_len
= le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
2235 if (action
& GUEST_LOGIN
)
2236 cFYI(1, (" Guest login"));
2237 /* Do we want to set anything in SesInfo struct when guest login? */
2239 bcc_ptr
= pByteArea(smb_buffer_response
);
2240 /* response can have either 3 or 4 word count - Samba sends 3 */
2242 SecurityBlob2
= (PCHALLENGE_MESSAGE
) bcc_ptr
;
2243 if (SecurityBlob2
->MessageType
!= NtLmChallenge
) {
2245 ("Unexpected NTLMSSP message type received %d",
2246 SecurityBlob2
->MessageType
));
2248 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in le format */
2249 cFYI(1, ("UID = %d ", ses
->Suid
));
2250 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
2251 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
2253 pSMBr
->resp
.ByteCount
))) {
2255 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
2256 bcc_ptr
+= blob_len
;
2258 ("Security Blob Length %d ",
2262 cFYI(1, ("NTLMSSP Challenge rcvd "));
2264 memcpy(ses
->server
->cryptKey
,
2265 SecurityBlob2
->Challenge
,
2266 CIFS_CRYPTO_KEY_SIZE
);
2267 if(SecurityBlob2
->NegotiateFlags
& cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2
))
2268 *pNTLMv2_flag
= TRUE
;
2270 if((SecurityBlob2
->NegotiateFlags
&
2271 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN
))
2272 || (sign_CIFS_PDUs
> 1))
2273 ses
->server
->secMode
|=
2274 SECMODE_SIGN_REQUIRED
;
2275 if ((SecurityBlob2
->NegotiateFlags
&
2276 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN
)) && (sign_CIFS_PDUs
))
2277 ses
->server
->secMode
|=
2278 SECMODE_SIGN_ENABLED
;
2280 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2281 if ((long) (bcc_ptr
) % 2) {
2283 (BCC(smb_buffer_response
)
2285 bcc_ptr
++; /* Unicode strings must be word aligned */
2289 (smb_buffer_response
) / 2;
2292 UniStrnlen((wchar_t *) bcc_ptr
,
2293 remaining_words
- 1);
2294 /* We look for obvious messed up bcc or strings in response so we do not go off
2295 the end since (at least) WIN2K and Windows XP have a major bug in not null
2296 terminating last Unicode string in response */
2298 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
2299 cifs_strfromUCS_le(ses
->serverOS
,
2303 bcc_ptr
+= 2 * (len
+ 1);
2304 remaining_words
-= len
+ 1;
2305 ses
->serverOS
[2 * len
] = 0;
2306 ses
->serverOS
[1 + (2 * len
)] = 0;
2307 if (remaining_words
> 0) {
2308 len
= UniStrnlen((wchar_t *)
2313 cifs_kcalloc(2 * (len
+ 1),
2315 cifs_strfromUCS_le(ses
->
2321 bcc_ptr
+= 2 * (len
+ 1);
2322 ses
->serverNOS
[2 * len
] = 0;
2325 remaining_words
-= len
+ 1;
2326 if (remaining_words
> 0) {
2327 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
2328 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2353 } /* else no more room so create dummy domain string */
2358 } else { /* no room so create dummy domain and NOS string */
2360 cifs_kcalloc(2, GFP_KERNEL
);
2362 cifs_kcalloc(2, GFP_KERNEL
);
2364 } else { /* ASCII */
2365 len
= strnlen(bcc_ptr
, 1024);
2366 if (((long) bcc_ptr
+ len
) - (long)
2367 pByteArea(smb_buffer_response
)
2368 <= BCC(smb_buffer_response
)) {
2370 cifs_kcalloc(len
+ 1,
2372 strncpy(ses
->serverOS
,
2376 bcc_ptr
[0] = 0; /* null terminate string */
2379 len
= strnlen(bcc_ptr
, 1024);
2381 cifs_kcalloc(len
+ 1,
2383 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2388 len
= strnlen(bcc_ptr
, 1024);
2390 cifs_kcalloc(len
+ 1,
2392 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2398 ("Variable field of length %d extends beyond end of smb ",
2403 (" Security Blob Length extends beyond end of SMB"));
2406 cERROR(1, ("No session structure passed in."));
2410 (" Invalid Word count %d: ",
2411 smb_buffer_response
->WordCount
));
2416 cifs_buf_release(smb_buffer
);
2421 CIFSNTLMSSPAuthSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
2422 char *ntlm_session_key
, int ntlmv2_flag
,
2423 const struct nls_table
*nls_codepage
)
2425 struct smb_hdr
*smb_buffer
;
2426 struct smb_hdr
*smb_buffer_response
;
2427 SESSION_SETUP_ANDX
*pSMB
;
2428 SESSION_SETUP_ANDX
*pSMBr
;
2433 int remaining_words
= 0;
2434 int bytes_returned
= 0;
2436 int SecurityBlobLength
= sizeof (AUTHENTICATE_MESSAGE
);
2437 PAUTHENTICATE_MESSAGE SecurityBlob
;
2438 __u32 negotiate_flags
, capabilities
;
2441 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2444 user
= ses
->userName
;
2445 domain
= ses
->domainName
;
2446 smb_buffer
= cifs_buf_get();
2447 if (smb_buffer
== NULL
) {
2450 smb_buffer_response
= smb_buffer
;
2451 pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
2452 pSMBr
= (SESSION_SETUP_ANDX
*) smb_buffer_response
;
2454 /* send SMBsessionSetup here */
2455 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
2456 NULL
/* no tCon exists yet */ , 12 /* wct */ );
2457 pSMB
->req
.hdr
.Flags
|= (SMBFLG_CASELESS
| SMBFLG_CANONICAL_PATH_FORMAT
);
2458 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
2459 pSMB
->req
.AndXCommand
= 0xFF;
2460 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
2461 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
2463 pSMB
->req
.hdr
.Uid
= ses
->Suid
;
2465 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2466 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2468 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
2469 CAP_EXTENDED_SECURITY
;
2470 if (ses
->capabilities
& CAP_UNICODE
) {
2471 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2472 capabilities
|= CAP_UNICODE
;
2474 if (ses
->capabilities
& CAP_STATUS32
) {
2475 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2476 capabilities
|= CAP_STATUS32
;
2478 if (ses
->capabilities
& CAP_DFS
) {
2479 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2480 capabilities
|= CAP_DFS
;
2482 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
2484 bcc_ptr
= (char *) &pSMB
->req
.SecurityBlob
;
2485 SecurityBlob
= (PAUTHENTICATE_MESSAGE
) bcc_ptr
;
2486 strncpy(SecurityBlob
->Signature
, NTLMSSP_SIGNATURE
, 8);
2487 SecurityBlob
->MessageType
= NtLmAuthenticate
;
2488 bcc_ptr
+= SecurityBlobLength
;
2490 NTLMSSP_NEGOTIATE_UNICODE
| NTLMSSP_REQUEST_TARGET
|
2491 NTLMSSP_NEGOTIATE_NTLM
| NTLMSSP_NEGOTIATE_TARGET_INFO
|
2492 0x80000000 | NTLMSSP_NEGOTIATE_128
;
2494 negotiate_flags
|= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN
;
2496 negotiate_flags
|= NTLMSSP_NEGOTIATE_NTLMV2
;
2498 /* setup pointers to domain name and workstation name */
2500 SecurityBlob
->WorkstationName
.Buffer
= 0;
2501 SecurityBlob
->WorkstationName
.Length
= 0;
2502 SecurityBlob
->WorkstationName
.MaximumLength
= 0;
2503 SecurityBlob
->SessionKey
.Length
= 0;
2504 SecurityBlob
->SessionKey
.MaximumLength
= 0;
2505 SecurityBlob
->SessionKey
.Buffer
= 0;
2507 SecurityBlob
->LmChallengeResponse
.Length
= 0;
2508 SecurityBlob
->LmChallengeResponse
.MaximumLength
= 0;
2509 SecurityBlob
->LmChallengeResponse
.Buffer
= 0;
2511 SecurityBlob
->NtChallengeResponse
.Length
=
2512 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
2513 SecurityBlob
->NtChallengeResponse
.MaximumLength
=
2514 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
2515 memcpy(bcc_ptr
, ntlm_session_key
, CIFS_SESSION_KEY_SIZE
);
2516 SecurityBlob
->NtChallengeResponse
.Buffer
=
2517 cpu_to_le32(SecurityBlobLength
);
2518 SecurityBlobLength
+= CIFS_SESSION_KEY_SIZE
;
2519 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
2521 if (ses
->capabilities
& CAP_UNICODE
) {
2522 if (domain
== NULL
) {
2523 SecurityBlob
->DomainName
.Buffer
= 0;
2524 SecurityBlob
->DomainName
.Length
= 0;
2525 SecurityBlob
->DomainName
.MaximumLength
= 0;
2528 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
2531 SecurityBlob
->DomainName
.MaximumLength
=
2533 SecurityBlob
->DomainName
.Buffer
=
2534 cpu_to_le32(SecurityBlobLength
);
2536 SecurityBlobLength
+= len
;
2537 SecurityBlob
->DomainName
.Length
=
2541 SecurityBlob
->UserName
.Buffer
= 0;
2542 SecurityBlob
->UserName
.Length
= 0;
2543 SecurityBlob
->UserName
.MaximumLength
= 0;
2546 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 64,
2549 SecurityBlob
->UserName
.MaximumLength
=
2551 SecurityBlob
->UserName
.Buffer
=
2552 cpu_to_le32(SecurityBlobLength
);
2554 SecurityBlobLength
+= len
;
2555 SecurityBlob
->UserName
.Length
=
2559 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2560 SecurityBlob->WorkstationName.Length *= 2;
2561 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2562 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2563 bcc_ptr += SecurityBlob->WorkstationName.Length;
2564 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2565 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2567 if ((long) bcc_ptr
% 2) {
2572 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
2574 bcc_ptr
+= 2 * bytes_returned
;
2576 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
2578 bcc_ptr
+= 2 * bytes_returned
;
2579 bcc_ptr
+= 2; /* null term version string */
2581 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
2583 bcc_ptr
+= 2 * bytes_returned
;
2586 bcc_ptr
+= 2; /* null terminate network opsys string */
2589 bcc_ptr
+= 2; /* null domain */
2590 } else { /* ASCII */
2591 if (domain
== NULL
) {
2592 SecurityBlob
->DomainName
.Buffer
= 0;
2593 SecurityBlob
->DomainName
.Length
= 0;
2594 SecurityBlob
->DomainName
.MaximumLength
= 0;
2597 negotiate_flags
|= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED
;
2598 strncpy(bcc_ptr
, domain
, 63);
2599 len
= strnlen(domain
, 64);
2600 SecurityBlob
->DomainName
.MaximumLength
=
2602 SecurityBlob
->DomainName
.Buffer
=
2603 cpu_to_le32(SecurityBlobLength
);
2605 SecurityBlobLength
+= len
;
2606 SecurityBlob
->DomainName
.Length
= cpu_to_le16(len
);
2609 SecurityBlob
->UserName
.Buffer
= 0;
2610 SecurityBlob
->UserName
.Length
= 0;
2611 SecurityBlob
->UserName
.MaximumLength
= 0;
2614 strncpy(bcc_ptr
, user
, 63);
2615 len
= strnlen(user
, 64);
2616 SecurityBlob
->UserName
.MaximumLength
=
2618 SecurityBlob
->UserName
.Buffer
=
2619 cpu_to_le32(SecurityBlobLength
);
2621 SecurityBlobLength
+= len
;
2622 SecurityBlob
->UserName
.Length
= cpu_to_le16(len
);
2624 /* BB fill in our workstation name if known BB */
2626 strcpy(bcc_ptr
, "Linux version ");
2627 bcc_ptr
+= strlen("Linux version ");
2628 strcpy(bcc_ptr
, system_utsname
.release
);
2629 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
2630 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
2631 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
2632 bcc_ptr
++; /* null domain */
2635 SecurityBlob
->NegotiateFlags
= cpu_to_le32(negotiate_flags
);
2636 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
2637 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
2638 smb_buffer
->smb_buf_length
+= count
;
2639 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
2641 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
2642 &bytes_returned
, 1);
2644 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2645 } else if ((smb_buffer_response
->WordCount
== 3)
2646 || (smb_buffer_response
->WordCount
== 4)) {
2647 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
2649 le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
2650 if (action
& GUEST_LOGIN
)
2651 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2652 /* if(SecurityBlob2->MessageType != NtLm??){
2653 cFYI("Unexpected message type on auth response is %d "));
2657 ("Does UID on challenge %d match auth response UID %d ",
2658 ses
->Suid
, smb_buffer_response
->Uid
));
2659 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format */
2660 bcc_ptr
= pByteArea(smb_buffer_response
);
2661 /* response can have either 3 or 4 word count - Samba sends 3 */
2662 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
2663 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
2665 pSMBr
->resp
.ByteCount
))) {
2666 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
2670 ("Security Blob Length %d ",
2675 ("NTLMSSP response to Authenticate "));
2677 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2678 if ((long) (bcc_ptr
) % 2) {
2680 (BCC(smb_buffer_response
)
2682 bcc_ptr
++; /* Unicode strings must be word aligned */
2684 remaining_words
= BCC(smb_buffer_response
) / 2;
2687 UniStrnlen((wchar_t *) bcc_ptr
,remaining_words
- 1);
2688 /* We look for obvious messed up bcc or strings in response so we do not go off
2689 the end since (at least) WIN2K and Windows XP have a major bug in not null
2690 terminating last Unicode string in response */
2692 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
2693 cifs_strfromUCS_le(ses
->serverOS
,
2697 bcc_ptr
+= 2 * (len
+ 1);
2698 remaining_words
-= len
+ 1;
2699 ses
->serverOS
[2 * len
] = 0;
2700 ses
->serverOS
[1 + (2 * len
)] = 0;
2701 if (remaining_words
> 0) {
2702 len
= UniStrnlen((wchar_t *)
2707 cifs_kcalloc(2 * (len
+ 1),
2709 cifs_strfromUCS_le(ses
->
2715 bcc_ptr
+= 2 * (len
+ 1);
2716 ses
->serverNOS
[2 * len
] = 0;
2717 ses
->serverNOS
[1+(2*len
)] = 0;
2718 remaining_words
-= len
+ 1;
2719 if (remaining_words
> 0) {
2720 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
2721 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2746 } /* else no more room so create dummy domain string */
2748 ses
->serverDomain
= cifs_kcalloc(2,GFP_KERNEL
);
2749 } else { /* no room so create dummy domain and NOS string */
2750 ses
->serverDomain
= cifs_kcalloc(2, GFP_KERNEL
);
2751 ses
->serverNOS
= cifs_kcalloc(2, GFP_KERNEL
);
2753 } else { /* ASCII */
2754 len
= strnlen(bcc_ptr
, 1024);
2755 if (((long) bcc_ptr
+ len
) -
2756 (long) pByteArea(smb_buffer_response
)
2757 <= BCC(smb_buffer_response
)) {
2758 ses
->serverOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
2759 strncpy(ses
->serverOS
,bcc_ptr
, len
);
2762 bcc_ptr
[0] = 0; /* null terminate the string */
2765 len
= strnlen(bcc_ptr
, 1024);
2766 ses
->serverNOS
= cifs_kcalloc(len
+1,GFP_KERNEL
);
2767 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2772 len
= strnlen(bcc_ptr
, 1024);
2773 ses
->serverDomain
= cifs_kcalloc(len
+1,GFP_KERNEL
);
2774 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2780 ("Variable field of length %d extends beyond end of smb ",
2785 (" Security Blob Length extends beyond end of SMB"));
2788 cERROR(1, ("No session structure passed in."));
2792 (" Invalid Word count %d: ",
2793 smb_buffer_response
->WordCount
));
2798 cifs_buf_release(smb_buffer
);
2804 CIFSTCon(unsigned int xid
, struct cifsSesInfo
*ses
,
2805 const char *tree
, struct cifsTconInfo
*tcon
,
2806 const struct nls_table
*nls_codepage
)
2808 struct smb_hdr
*smb_buffer
;
2809 struct smb_hdr
*smb_buffer_response
;
2812 unsigned char *bcc_ptr
;
2820 smb_buffer
= cifs_buf_get();
2821 if (smb_buffer
== NULL
) {
2824 smb_buffer_response
= smb_buffer
;
2826 header_assemble(smb_buffer
, SMB_COM_TREE_CONNECT_ANDX
,
2827 NULL
/*no tid */ , 4 /*wct */ );
2828 smb_buffer
->Uid
= ses
->Suid
;
2829 pSMB
= (TCONX_REQ
*) smb_buffer
;
2830 pSMBr
= (TCONX_RSP
*) smb_buffer_response
;
2832 pSMB
->AndXCommand
= 0xFF;
2833 pSMB
->Flags
= cpu_to_le16(TCON_EXTENDED_SECINFO
);
2834 pSMB
->PasswordLength
= cpu_to_le16(1); /* minimum */
2835 bcc_ptr
= &pSMB
->Password
[0];
2836 bcc_ptr
++; /* skip password */
2838 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2839 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2841 if (ses
->capabilities
& CAP_STATUS32
) {
2842 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2844 if (ses
->capabilities
& CAP_DFS
) {
2845 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2847 if (ses
->capabilities
& CAP_UNICODE
) {
2848 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2850 cifs_strtoUCS((wchar_t *) bcc_ptr
, tree
, 100, nls_codepage
);
2851 bcc_ptr
+= 2 * length
; /* convert num of 16 bit words to bytes */
2852 bcc_ptr
+= 2; /* skip trailing null */
2853 } else { /* ASCII */
2855 strcpy(bcc_ptr
, tree
);
2856 bcc_ptr
+= strlen(tree
) + 1;
2858 strcpy(bcc_ptr
, "?????");
2859 bcc_ptr
+= strlen("?????");
2861 count
= bcc_ptr
- &pSMB
->Password
[0];
2862 pSMB
->hdr
.smb_buf_length
+= count
;
2863 pSMB
->ByteCount
= cpu_to_le16(count
);
2865 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
, &length
, 0);
2867 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2868 /* above now done in SendReceive */
2869 if ((rc
== 0) && (tcon
!= NULL
)) {
2870 tcon
->tidStatus
= CifsGood
;
2871 tcon
->tid
= smb_buffer_response
->Tid
;
2872 bcc_ptr
= pByteArea(smb_buffer_response
);
2873 length
= strnlen(bcc_ptr
, BCC(smb_buffer_response
) - 2);
2874 /* skip service field (NB: this field is always ASCII) */
2875 bcc_ptr
+= length
+ 1;
2876 strncpy(tcon
->treeName
, tree
, MAX_TREE_SIZE
);
2877 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2878 length
= UniStrnlen((wchar_t *) bcc_ptr
, 512);
2879 if ((bcc_ptr
+ (2 * length
)) -
2880 pByteArea(smb_buffer_response
) <=
2881 BCC(smb_buffer_response
)) {
2882 if(tcon
->nativeFileSystem
)
2883 kfree(tcon
->nativeFileSystem
);
2884 tcon
->nativeFileSystem
=
2885 cifs_kcalloc(length
+ 2, GFP_KERNEL
);
2886 cifs_strfromUCS_le(tcon
->nativeFileSystem
,
2887 (wchar_t *) bcc_ptr
,
2888 length
, nls_codepage
);
2889 bcc_ptr
+= 2 * length
;
2890 bcc_ptr
[0] = 0; /* null terminate the string */
2894 /* else do not bother copying these informational fields */
2896 length
= strnlen(bcc_ptr
, 1024);
2897 if ((bcc_ptr
+ length
) -
2898 pByteArea(smb_buffer_response
) <=
2899 BCC(smb_buffer_response
)) {
2900 if(tcon
->nativeFileSystem
)
2901 kfree(tcon
->nativeFileSystem
);
2902 tcon
->nativeFileSystem
=
2903 cifs_kcalloc(length
+ 1, GFP_KERNEL
);
2904 strncpy(tcon
->nativeFileSystem
, bcc_ptr
,
2907 /* else do not bother copying these informational fields */
2909 tcon
->Flags
= le16_to_cpu(pSMBr
->OptionalSupport
);
2910 cFYI(1, ("Tcon flags: 0x%x ", tcon
->Flags
));
2911 } else if ((rc
== 0) && tcon
== NULL
) {
2912 /* all we need to save for IPC$ connection */
2913 ses
->ipc_tid
= smb_buffer_response
->Tid
;
2917 cifs_buf_release(smb_buffer
);
2922 cifs_umount(struct super_block
*sb
, struct cifs_sb_info
*cifs_sb
)
2926 struct cifsSesInfo
*ses
= NULL
;
2927 struct task_struct
*cifsd_task
;
2931 if (cifs_sb
->tcon
) {
2932 ses
= cifs_sb
->tcon
->ses
; /* save ptr to ses before delete tcon!*/
2933 rc
= CIFSSMBTDis(xid
, cifs_sb
->tcon
);
2938 tconInfoFree(cifs_sb
->tcon
);
2939 if ((ses
) && (ses
->server
)) {
2940 /* save off task so we do not refer to ses later */
2941 cifsd_task
= ses
->server
->tsk
;
2942 cFYI(1, ("About to do SMBLogoff "));
2943 rc
= CIFSSMBLogoff(xid
, ses
);
2947 } else if (rc
== -ESHUTDOWN
) {
2948 cFYI(1,("Waking up socket by sending it signal"));
2950 send_sig(SIGKILL
,cifsd_task
,1);
2952 } /* else - we have an smb session
2953 left on this socket do not kill cifsd */
2955 cFYI(1, ("No session or bad tcon"));
2958 cifs_sb
->tcon
= NULL
;
2960 set_current_state(TASK_INTERRUPTIBLE
);
2961 schedule_timeout(HZ
/ 2);
2967 return rc
; /* BB check if we should always return zero here */
2970 int cifs_setup_session(unsigned int xid
, struct cifsSesInfo
*pSesInfo
,
2971 struct nls_table
* nls_info
)
2974 char ntlm_session_key
[CIFS_SESSION_KEY_SIZE
];
2975 int ntlmv2_flag
= FALSE
;
2978 /* what if server changes its buffer size after dropping the session? */
2979 if(pSesInfo
->server
->maxBuf
== 0) /* no need to send on reconnect */ {
2980 rc
= CIFSSMBNegotiate(xid
, pSesInfo
);
2981 if(rc
== -EAGAIN
) /* retry only once on 1st time connection */ {
2982 rc
= CIFSSMBNegotiate(xid
, pSesInfo
);
2987 spin_lock(&GlobalMid_Lock
);
2988 if(pSesInfo
->server
->tcpStatus
!= CifsExiting
)
2989 pSesInfo
->server
->tcpStatus
= CifsGood
;
2992 spin_unlock(&GlobalMid_Lock
);
2998 pSesInfo
->capabilities
= pSesInfo
->server
->capabilities
;
2999 if(linuxExtEnabled
== 0)
3000 pSesInfo
->capabilities
&= (~CAP_UNIX
);
3001 /* pSesInfo->sequence_number = 0;*/
3002 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3003 pSesInfo
->server
->secMode
,
3004 pSesInfo
->server
->capabilities
,
3005 pSesInfo
->server
->timeZone
));
3006 if (extended_security
3007 && (pSesInfo
->capabilities
& CAP_EXTENDED_SECURITY
)
3008 && (pSesInfo
->server
->secType
== NTLMSSP
)) {
3009 cFYI(1, ("New style sesssetup "));
3010 rc
= CIFSSpnegoSessSetup(xid
, pSesInfo
,
3011 NULL
/* security blob */,
3012 0 /* blob length */,
3014 } else if (extended_security
3015 && (pSesInfo
->capabilities
& CAP_EXTENDED_SECURITY
)
3016 && (pSesInfo
->server
->secType
== RawNTLMSSP
)) {
3017 cFYI(1, ("NTLMSSP sesssetup "));
3018 rc
= CIFSNTLMSSPNegotiateSessSetup(xid
,
3025 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3026 if(CalcNTLMv2_partial_mac_key(pSesInfo
,
3031 v2_response
= kmalloc(16 + 64 /* blob */, GFP_KERNEL
);
3033 CalcNTLMv2_response(pSesInfo
,v2_response
);
3035 cifs_calculate_ntlmv2_mac_key(
3036 pSesInfo->server->mac_signing_key,
3037 response, ntlm_session_key, */
3039 /* BB Put dummy sig in SessSetup PDU? */
3046 SMBNTencrypt(pSesInfo
->password
,
3047 pSesInfo
->server
->cryptKey
,
3051 cifs_calculate_mac_key(
3052 pSesInfo
->server
->mac_signing_key
,
3054 pSesInfo
->password
);
3056 /* for better security the weaker lanman hash not sent
3057 in AuthSessSetup so we no longer calculate it */
3059 rc
= CIFSNTLMSSPAuthSessSetup(xid
,
3065 } else { /* old style NTLM 0.12 session setup */
3066 SMBNTencrypt(pSesInfo
->password
,
3067 pSesInfo
->server
->cryptKey
,
3071 cifs_calculate_mac_key(
3072 pSesInfo
->server
->mac_signing_key
,
3073 ntlm_session_key
, pSesInfo
->password
);
3075 rc
= CIFSSessSetup(xid
, pSesInfo
,
3076 ntlm_session_key
, nls_info
);
3079 cERROR(1,("Send error in SessSetup = %d",rc
));
3081 cFYI(1,("CIFS Session Established successfully"));
3082 pSesInfo
->status
= CifsGood
;