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 */
78 unsigned short int port
;
81 static int ipv4_connect(struct sockaddr_in
*psin_server
,
82 struct socket
**csocket
,
84 static int ipv6_connect(struct sockaddr_in6
*psin_server
,
85 struct socket
**csocket
);
89 * cifs tcp session reconnection
91 * mark tcp session as reconnecting so temporarily locked
92 * mark all smb sessions as reconnecting for tcp session
93 * reconnect tcp session
94 * wake up waiters on reconnection? - (not needed currently)
98 cifs_reconnect(struct TCP_Server_Info
*server
)
101 struct list_head
*tmp
;
102 struct cifsSesInfo
*ses
;
103 struct cifsTconInfo
*tcon
;
104 struct mid_q_entry
* mid_entry
;
106 spin_lock(&GlobalMid_Lock
);
107 if(server
->tcpStatus
== CifsExiting
) {
108 /* the demux thread will exit normally
109 next time through the loop */
110 spin_unlock(&GlobalMid_Lock
);
113 server
->tcpStatus
= CifsNeedReconnect
;
114 spin_unlock(&GlobalMid_Lock
);
117 cFYI(1, ("Reconnecting tcp session "));
119 /* before reconnecting the tcp session, mark the smb session (uid)
120 and the tid bad so they are not used until reconnected */
121 read_lock(&GlobalSMBSeslock
);
122 list_for_each(tmp
, &GlobalSMBSessionList
) {
123 ses
= list_entry(tmp
, struct cifsSesInfo
, cifsSessionList
);
125 if (ses
->server
== server
) {
126 ses
->status
= CifsNeedReconnect
;
130 /* else tcp and smb sessions need reconnection */
132 list_for_each(tmp
, &GlobalTreeConnectionList
) {
133 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
134 if((tcon
) && (tcon
->ses
) && (tcon
->ses
->server
== server
)) {
135 tcon
->tidStatus
= CifsNeedReconnect
;
138 read_unlock(&GlobalSMBSeslock
);
139 /* do not want to be sending data on a socket we are freeing */
140 down(&server
->tcpSem
);
141 if(server
->ssocket
) {
142 cFYI(1,("State: 0x%x Flags: 0x%lx", server
->ssocket
->state
,
143 server
->ssocket
->flags
));
144 server
->ssocket
->ops
->shutdown(server
->ssocket
,SEND_SHUTDOWN
);
145 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server
->ssocket
->state
,
146 server
->ssocket
->flags
));
147 sock_release(server
->ssocket
);
148 server
->ssocket
= NULL
;
151 spin_lock(&GlobalMid_Lock
);
152 list_for_each(tmp
, &server
->pending_mid_q
) {
153 mid_entry
= list_entry(tmp
, struct
157 if(mid_entry
->midState
== MID_REQUEST_SUBMITTED
) {
158 /* Mark other intransit requests as needing retry so
159 we do not immediately mark the session bad again
160 (ie after we reconnect below) as they timeout too */
161 mid_entry
->midState
= MID_RETRY_NEEDED
;
165 spin_unlock(&GlobalMid_Lock
);
168 while ((server
->tcpStatus
!= CifsExiting
) && (server
->tcpStatus
!= CifsGood
))
170 if(server
->protocolType
== IPV6
) {
171 rc
= ipv6_connect(&server
->addr
.sockAddr6
,&server
->ssocket
);
173 rc
= ipv4_connect(&server
->addr
.sockAddr
,
175 server
->workstation_RFC1001_name
);
178 set_current_state(TASK_INTERRUPTIBLE
);
179 schedule_timeout(3 * HZ
);
181 atomic_inc(&tcpSesReconnectCount
);
182 spin_lock(&GlobalMid_Lock
);
183 if(server
->tcpStatus
!= CifsExiting
)
184 server
->tcpStatus
= CifsGood
;
185 spin_unlock(&GlobalMid_Lock
);
186 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server
->response_q
);
194 cifs_demultiplex_thread(struct TCP_Server_Info
*server
)
197 unsigned int pdu_length
, total_read
;
198 struct smb_hdr
*smb_buffer
= NULL
;
199 struct msghdr smb_msg
;
201 struct socket
*csocket
= server
->ssocket
;
202 struct list_head
*tmp
;
203 struct cifsSesInfo
*ses
;
204 struct task_struct
*task_to_wake
= NULL
;
205 struct mid_q_entry
*mid_entry
;
209 allow_signal(SIGKILL
);
210 current
->flags
|= PF_MEMALLOC
;
211 server
->tsk
= current
; /* save process info to wake at shutdown */
212 cFYI(1, ("Demultiplex PID: %d", current
->pid
));
213 write_lock(&GlobalSMBSeslock
);
214 atomic_inc(&tcpSesAllocCount
);
215 length
= tcpSesAllocCount
.counter
;
216 write_unlock(&GlobalSMBSeslock
);
218 mempool_resize(cifs_req_poolp
,
219 length
+ cifs_min_rcv
,
223 while (server
->tcpStatus
!= CifsExiting
) {
224 if (smb_buffer
== NULL
)
225 smb_buffer
= cifs_buf_get();
227 memset(smb_buffer
, 0, sizeof (struct smb_hdr
));
229 if (smb_buffer
== NULL
) {
230 cERROR(1,("Can not get memory for SMB response"));
231 set_current_state(TASK_INTERRUPTIBLE
);
232 schedule_timeout(HZ
* 3); /* give system time to free memory */
235 iov
.iov_base
= smb_buffer
;
237 smb_msg
.msg_control
= NULL
;
238 smb_msg
.msg_controllen
= 0;
240 kernel_recvmsg(csocket
, &smb_msg
,
241 &iov
, 1, 4, 0 /* BB see socket.h flags */);
243 if(server
->tcpStatus
== CifsExiting
) {
245 } else if (server
->tcpStatus
== CifsNeedReconnect
) {
246 cFYI(1,("Reconnecting after server stopped responding"));
247 cifs_reconnect(server
);
248 cFYI(1,("call to reconnect done"));
249 csocket
= server
->ssocket
;
251 } else if ((length
== -ERESTARTSYS
) || (length
== -EAGAIN
)) {
252 set_current_state(TASK_INTERRUPTIBLE
);
253 schedule_timeout(1); /* minimum sleep to prevent looping
254 allowing socket to clear and app threads to set
255 tcpStatus CifsNeedReconnect if server hung */
257 } else if (length
<= 0) {
258 if(server
->tcpStatus
== CifsNew
) {
259 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
260 /* some servers kill tcp session rather than returning
261 smb negprot error in which case reconnecting here is
262 not going to help - return error to mount */
265 if(length
== -EINTR
) {
266 cFYI(1,("cifsd thread killed"));
269 cFYI(1,("Reconnecting after unexpected peek error %d",length
));
270 cifs_reconnect(server
);
271 csocket
= server
->ssocket
;
272 wake_up(&server
->response_q
);
274 } else if (length
> 3) {
275 pdu_length
= ntohl(smb_buffer
->smb_buf_length
);
276 /* Only read pdu_length after below checks for too short (due
277 to e.g. int overflow) and too long ie beyond end of buf */
278 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length
+4));
280 temp
= (char *) smb_buffer
;
281 if (temp
[0] == (char) RFC1002_SESSION_KEEP_ALIVE
) {
282 cFYI(0,("Received 4 byte keep alive packet"));
283 } else if (temp
[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE
) {
284 cFYI(1,("Good RFC 1002 session rsp"));
285 } else if (temp
[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE
) {
286 /* we get this from Windows 98 instead of error on SMB negprot response */
287 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp
[4]));
288 if(server
->tcpStatus
== CifsNew
) {
289 /* if nack on negprot (rather than
290 ret of smb negprot error) reconnecting
291 not going to help, ret error to mount */
294 /* give server a second to
295 clean up before reconnect attempt */
296 set_current_state(TASK_INTERRUPTIBLE
);
297 schedule_timeout(HZ
);
298 /* always try 445 first on reconnect
299 since we get NACK on some if we ever
300 connected to port 139 (the NACK is
301 since we do not begin with RFC1001
302 session initialize frame) */
303 server
->addr
.sockAddr
.sin_port
= htons(CIFS_PORT
);
304 cifs_reconnect(server
);
305 csocket
= server
->ssocket
;
306 wake_up(&server
->response_q
);
309 } else if (temp
[0] != (char) 0) {
310 cERROR(1,("Unknown RFC 1002 frame"));
311 cifs_dump_mem(" Received Data: ", temp
, length
);
312 cifs_reconnect(server
);
313 csocket
= server
->ssocket
;
316 if((pdu_length
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
- 4)
317 || (pdu_length
< sizeof (struct smb_hdr
) - 1 - 4)) {
319 ("Invalid size SMB length %d and pdu_length %d",
320 length
, pdu_length
+4));
321 cifs_reconnect(server
);
322 csocket
= server
->ssocket
;
323 wake_up(&server
->response_q
);
325 } else { /* length ok */
327 iov
.iov_base
= 4 + (char *)smb_buffer
;
328 iov
.iov_len
= pdu_length
;
330 total_read
< pdu_length
;
331 total_read
+= length
) {
332 length
= kernel_recvmsg(csocket
, &smb_msg
,
334 pdu_length
- total_read
, 0);
337 ("Zero length receive when expecting %d ",
338 pdu_length
- total_read
));
339 cifs_reconnect(server
);
340 csocket
= server
->ssocket
;
341 wake_up(&server
->response_q
);
345 length
+= 4; /* account for rfc1002 hdr */
348 dump_smb(smb_buffer
, length
);
350 (smb_buffer
, smb_buffer
->Mid
, total_read
+4)) {
351 cERROR(1, ("Bad SMB Received "));
356 spin_lock(&GlobalMid_Lock
);
357 list_for_each(tmp
, &server
->pending_mid_q
) {
358 mid_entry
= list_entry(tmp
, struct
362 if ((mid_entry
->mid
== smb_buffer
->Mid
) && (mid_entry
->midState
== MID_REQUEST_SUBMITTED
)) {
364 (" Mid 0x%x matched - waking up ",mid_entry
->mid
));
365 task_to_wake
= mid_entry
->tsk
;
366 mid_entry
->resp_buf
=
368 mid_entry
->midState
=
369 MID_RESPONSE_RECEIVED
;
372 spin_unlock(&GlobalMid_Lock
);
374 smb_buffer
= NULL
; /* will be freed by users thread after he is done */
375 wake_up_process(task_to_wake
);
376 } else if (is_valid_oplock_break(smb_buffer
) == FALSE
) {
377 cERROR(1, ("No task to wake, unknown frame rcvd!"));
378 cifs_dump_mem("Received Data is: ",temp
,sizeof(struct smb_hdr
));
383 ("Frame less than four bytes received %d bytes long.",
385 cifs_reconnect(server
);
386 csocket
= server
->ssocket
;
387 wake_up(&server
->response_q
);
391 spin_lock(&GlobalMid_Lock
);
392 server
->tcpStatus
= CifsExiting
;
394 atomic_set(&server
->inFlight
, 0);
395 spin_unlock(&GlobalMid_Lock
);
396 /* Although there should not be any requests blocked on
397 this queue it can not hurt to be paranoid and try to wake up requests
398 that may haven been blocked when more than 50 at time were on the wire
399 to the same server - they now will see the session is in exit state
400 and get out of SendReceive. */
401 wake_up_all(&server
->request_q
);
402 /* give those requests time to exit */
403 set_current_state(TASK_INTERRUPTIBLE
);
404 schedule_timeout(HZ
/8);
406 if(server
->ssocket
) {
407 sock_release(csocket
);
408 server
->ssocket
= NULL
;
410 if (smb_buffer
) /* buffer usually freed in free_mid - need to free it on error or exit */
411 cifs_buf_release(smb_buffer
);
413 read_lock(&GlobalSMBSeslock
);
414 if (list_empty(&server
->pending_mid_q
)) {
415 /* loop through server session structures attached to this and mark them dead */
416 list_for_each(tmp
, &GlobalSMBSessionList
) {
418 list_entry(tmp
, struct cifsSesInfo
,
420 if (ses
->server
== server
) {
421 ses
->status
= CifsExiting
;
425 read_unlock(&GlobalSMBSeslock
);
427 spin_lock(&GlobalMid_Lock
);
428 list_for_each(tmp
, &server
->pending_mid_q
) {
429 mid_entry
= list_entry(tmp
, struct mid_q_entry
, qhead
);
430 if (mid_entry
->midState
== MID_REQUEST_SUBMITTED
) {
432 (" Clearing Mid 0x%x - waking up ",mid_entry
->mid
));
433 task_to_wake
= mid_entry
->tsk
;
435 wake_up_process(task_to_wake
);
439 spin_unlock(&GlobalMid_Lock
);
440 read_unlock(&GlobalSMBSeslock
);
441 set_current_state(TASK_INTERRUPTIBLE
);
442 /* 1/8th of sec is more than enough time for them to exit */
443 schedule_timeout(HZ
/8);
446 if (list_empty(&server
->pending_mid_q
)) {
447 /* mpx threads have not exited yet give them
448 at least the smb send timeout time for long ops */
449 cFYI(1, ("Wait for exit from demultiplex thread"));
450 set_current_state(TASK_INTERRUPTIBLE
);
451 schedule_timeout(46 * HZ
);
452 /* if threads still have not exited they are probably never
453 coming home not much else we can do but free the memory */
457 write_lock(&GlobalSMBSeslock
);
458 atomic_dec(&tcpSesAllocCount
);
459 length
= tcpSesAllocCount
.counter
;
460 write_unlock(&GlobalSMBSeslock
);
462 mempool_resize(cifs_req_poolp
,
463 length
+ cifs_min_rcv
,
467 set_current_state(TASK_INTERRUPTIBLE
);
468 schedule_timeout(HZ
/4);
473 cifs_kcalloc(size_t size
, unsigned int __nocast type
)
476 addr
= kmalloc(size
, type
);
478 memset(addr
, 0, size
);
483 cifs_parse_mount_options(char *options
, const char *devname
,struct smb_vol
*vol
)
487 unsigned int temp_len
, i
, j
;
493 memset(vol
->source_rfc1001_name
,0x20,15);
494 for(i
=0;i
< strnlen(system_utsname
.nodename
,15);i
++) {
495 /* does not have to be a perfect mapping since the field is
496 informational, only used for servers that do not support
497 port 445 and it can be overridden at mount time */
498 vol
->source_rfc1001_name
[i
] = toupper(system_utsname
.nodename
[i
]);
500 vol
->source_rfc1001_name
[15] = 0;
502 vol
->linux_uid
= current
->uid
; /* current->euid instead? */
503 vol
->linux_gid
= current
->gid
;
504 vol
->dir_mode
= S_IRWXUGO
;
505 /* 2767 perms indicate mandatory locking support */
506 vol
->file_mode
= S_IALLUGO
& ~(S_ISUID
| S_IXGRP
);
508 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
514 if(strncmp(options
,"sep=",4) == 0) {
515 if(options
[4] != 0) {
516 separator
[0] = options
[4];
519 cFYI(1,("Null separator not allowed"));
523 while ((data
= strsep(&options
, separator
)) != NULL
) {
526 if ((value
= strchr(data
, '=')) != NULL
)
529 if (strnicmp(data
, "user_xattr",10) == 0) {/*parse before user*/
531 } else if (strnicmp(data
, "nouser_xattr",12) == 0) {
533 } else if (strnicmp(data
, "user", 4) == 0) {
534 if (!value
|| !*value
) {
536 "CIFS: invalid or missing username\n");
537 return 1; /* needs_arg; */
539 if (strnlen(value
, 200) < 200) {
540 vol
->username
= value
;
542 printk(KERN_WARNING
"CIFS: username too long\n");
545 } else if (strnicmp(data
, "pass", 4) == 0) {
547 vol
->password
= NULL
;
549 } else if(value
[0] == 0) {
550 /* check if string begins with double comma
551 since that would mean the password really
552 does start with a comma, and would not
553 indicate an empty string */
554 if(value
[1] != separator
[0]) {
555 vol
->password
= NULL
;
559 temp_len
= strlen(value
);
560 /* removed password length check, NTLM passwords
561 can be arbitrarily long */
563 /* if comma in password, the string will be
564 prematurely null terminated. Commas in password are
565 specified across the cifs mount interface by a double
566 comma ie ,, and a comma used as in other cases ie ','
567 as a parameter delimiter/separator is single and due
568 to the strsep above is temporarily zeroed. */
570 /* NB: password legally can have multiple commas and
571 the only illegal character in a password is null */
573 if ((value
[temp_len
] == 0) && (value
[temp_len
+1] == separator
[0])) {
575 value
[temp_len
] = separator
[0];
576 temp_len
+=2; /* move after the second comma */
577 while(value
[temp_len
] != 0) {
578 if (value
[temp_len
] == separator
[0]) {
579 if (value
[temp_len
+1] == separator
[0]) {
580 temp_len
++; /* skip second comma */
582 /* single comma indicating start
589 if(value
[temp_len
] == 0) {
593 /* point option to start of next parm */
594 options
= value
+ temp_len
+ 1;
596 /* go from value to value + temp_len condensing
597 double commas to singles. Note that this ends up
598 allocating a few bytes too many, which is ok */
599 vol
->password
= cifs_kcalloc(temp_len
, GFP_KERNEL
);
600 for(i
=0,j
=0;i
<temp_len
;i
++,j
++) {
601 vol
->password
[j
] = value
[i
];
602 if(value
[i
] == separator
[0] && value
[i
+1] == separator
[0]) {
603 /* skip second comma */
607 vol
->password
[j
] = 0;
609 vol
->password
= cifs_kcalloc(temp_len
+ 1, GFP_KERNEL
);
610 strcpy(vol
->password
, value
);
612 } else if (strnicmp(data
, "ip", 2) == 0) {
613 if (!value
|| !*value
) {
615 } else if (strnlen(value
, 35) < 35) {
618 printk(KERN_WARNING
"CIFS: ip address too long\n");
621 } else if ((strnicmp(data
, "unc", 3) == 0)
622 || (strnicmp(data
, "target", 6) == 0)
623 || (strnicmp(data
, "path", 4) == 0)) {
624 if (!value
|| !*value
) {
626 "CIFS: invalid path to network resource\n");
627 return 1; /* needs_arg; */
629 if ((temp_len
= strnlen(value
, 300)) < 300) {
630 vol
->UNC
= kmalloc(temp_len
+1,GFP_KERNEL
);
633 strcpy(vol
->UNC
,value
);
634 if (strncmp(vol
->UNC
, "//", 2) == 0) {
637 } else if (strncmp(vol
->UNC
, "\\\\", 2) != 0) {
639 "CIFS: UNC Path does not begin with // or \\\\ \n");
643 printk(KERN_WARNING
"CIFS: UNC name too long\n");
646 } else if ((strnicmp(data
, "domain", 3) == 0)
647 || (strnicmp(data
, "workgroup", 5) == 0)) {
648 if (!value
|| !*value
) {
649 printk(KERN_WARNING
"CIFS: invalid domain name\n");
650 return 1; /* needs_arg; */
652 /* BB are there cases in which a comma can be valid in
653 a domain name and need special handling? */
654 if (strnlen(value
, 65) < 65) {
655 vol
->domainname
= value
;
656 cFYI(1, ("Domain name set"));
658 printk(KERN_WARNING
"CIFS: domain name too long\n");
661 } else if (strnicmp(data
, "iocharset", 9) == 0) {
662 if (!value
|| !*value
) {
663 printk(KERN_WARNING
"CIFS: invalid iocharset specified\n");
664 return 1; /* needs_arg; */
666 if (strnlen(value
, 65) < 65) {
667 if(strnicmp(value
,"default",7))
668 vol
->iocharset
= value
;
669 /* if iocharset not set load_nls_default used by caller */
670 cFYI(1, ("iocharset set to %s",value
));
672 printk(KERN_WARNING
"CIFS: iocharset name too long.\n");
675 } else if (strnicmp(data
, "uid", 3) == 0) {
676 if (value
&& *value
) {
678 simple_strtoul(value
, &value
, 0);
680 } else if (strnicmp(data
, "gid", 3) == 0) {
681 if (value
&& *value
) {
683 simple_strtoul(value
, &value
, 0);
685 } else if (strnicmp(data
, "file_mode", 4) == 0) {
686 if (value
&& *value
) {
688 simple_strtoul(value
, &value
, 0);
690 } else if (strnicmp(data
, "dir_mode", 4) == 0) {
691 if (value
&& *value
) {
693 simple_strtoul(value
, &value
, 0);
695 } else if (strnicmp(data
, "dirmode", 4) == 0) {
696 if (value
&& *value
) {
698 simple_strtoul(value
, &value
, 0);
700 } else if (strnicmp(data
, "port", 4) == 0) {
701 if (value
&& *value
) {
703 simple_strtoul(value
, &value
, 0);
705 } else if (strnicmp(data
, "rsize", 5) == 0) {
706 if (value
&& *value
) {
708 simple_strtoul(value
, &value
, 0);
710 } else if (strnicmp(data
, "wsize", 5) == 0) {
711 if (value
&& *value
) {
713 simple_strtoul(value
, &value
, 0);
715 } else if (strnicmp(data
, "sockopt", 5) == 0) {
716 if (value
&& *value
) {
718 simple_strtoul(value
, &value
, 0);
720 } else if (strnicmp(data
, "netbiosname", 4) == 0) {
721 if (!value
|| !*value
|| (*value
== ' ')) {
722 cFYI(1,("invalid (empty) netbiosname specified"));
724 memset(vol
->source_rfc1001_name
,0x20,15);
726 /* BB are there cases in which a comma can be
727 valid in this workstation netbios name (and need
728 special handling)? */
730 /* We do not uppercase netbiosname for user */
734 vol
->source_rfc1001_name
[i
] = value
[i
];
736 /* The string has 16th byte zero still from
737 set at top of the function */
738 if((i
==15) && (value
[i
] != 0))
739 printk(KERN_WARNING
"CIFS: netbiosname longer than 15 and was truncated.\n");
741 } else if (strnicmp(data
, "credentials", 4) == 0) {
743 } else if (strnicmp(data
, "version", 3) == 0) {
745 } else if (strnicmp(data
, "guest",5) == 0) {
747 } else if (strnicmp(data
, "rw", 2) == 0) {
749 } else if ((strnicmp(data
, "suid", 4) == 0) ||
750 (strnicmp(data
, "nosuid", 6) == 0) ||
751 (strnicmp(data
, "exec", 4) == 0) ||
752 (strnicmp(data
, "noexec", 6) == 0) ||
753 (strnicmp(data
, "nodev", 5) == 0) ||
754 (strnicmp(data
, "noauto", 6) == 0) ||
755 (strnicmp(data
, "dev", 3) == 0)) {
756 /* The mount tool or mount.cifs helper (if present)
757 uses these opts to set flags, and the flags are read
758 by the kernel vfs layer before we get here (ie
759 before read super) so there is no point trying to
760 parse these options again and set anything and it
761 is ok to just ignore them */
763 } else if (strnicmp(data
, "ro", 2) == 0) {
765 } else if (strnicmp(data
, "hard", 4) == 0) {
767 } else if (strnicmp(data
, "soft", 4) == 0) {
769 } else if (strnicmp(data
, "perm", 4) == 0) {
771 } else if (strnicmp(data
, "noperm", 6) == 0) {
773 } else if (strnicmp(data
, "setuids", 7) == 0) {
775 } else if (strnicmp(data
, "nosetuids", 9) == 0) {
777 } else if (strnicmp(data
, "nohard", 6) == 0) {
779 } else if (strnicmp(data
, "nosoft", 6) == 0) {
781 } else if (strnicmp(data
, "nointr", 6) == 0) {
783 } else if (strnicmp(data
, "intr", 4) == 0) {
785 } else if (strnicmp(data
, "serverino",7) == 0) {
787 } else if (strnicmp(data
, "noserverino",9) == 0) {
789 } else if (strnicmp(data
, "acl",3) == 0) {
791 } else if (strnicmp(data
, "noacl",5) == 0) {
793 } else if (strnicmp(data
, "direct",6) == 0) {
795 } else if (strnicmp(data
, "forcedirectio",13) == 0) {
797 } else if (strnicmp(data
, "in6_addr",8) == 0) {
798 if (!value
|| !*value
) {
799 vol
->in6_addr
= NULL
;
800 } else if (strnlen(value
, 49) == 48) {
801 vol
->in6_addr
= value
;
803 printk(KERN_WARNING
"CIFS: ip v6 address not 48 characters long\n");
806 } else if (strnicmp(data
, "noac", 4) == 0) {
807 printk(KERN_WARNING
"CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
809 printk(KERN_WARNING
"CIFS: Unknown mount option %s\n",data
);
811 if (vol
->UNC
== NULL
) {
812 if(devname
== NULL
) {
813 printk(KERN_WARNING
"CIFS: Missing UNC name for mount target\n");
816 if ((temp_len
= strnlen(devname
, 300)) < 300) {
817 vol
->UNC
= kmalloc(temp_len
+1,GFP_KERNEL
);
820 strcpy(vol
->UNC
,devname
);
821 if (strncmp(vol
->UNC
, "//", 2) == 0) {
824 } else if (strncmp(vol
->UNC
, "\\\\", 2) != 0) {
825 printk(KERN_WARNING
"CIFS: UNC Path does not begin with // or \\\\ \n");
829 printk(KERN_WARNING
"CIFS: UNC name too long\n");
833 if(vol
->UNCip
== NULL
)
834 vol
->UNCip
= &vol
->UNC
[2];
839 static struct cifsSesInfo
*
840 cifs_find_tcp_session(struct in_addr
* target_ip_addr
,
841 struct in6_addr
*target_ip6_addr
,
842 char *userName
, struct TCP_Server_Info
**psrvTcp
)
844 struct list_head
*tmp
;
845 struct cifsSesInfo
*ses
;
847 read_lock(&GlobalSMBSeslock
);
849 list_for_each(tmp
, &GlobalSMBSessionList
) {
850 ses
= list_entry(tmp
, struct cifsSesInfo
, cifsSessionList
);
852 if((target_ip_addr
&&
853 (ses
->server
->addr
.sockAddr
.sin_addr
.s_addr
854 == target_ip_addr
->s_addr
)) || (target_ip6_addr
855 && memcmp(&ses
->server
->addr
.sockAddr6
.sin6_addr
,
856 target_ip6_addr
,sizeof(*target_ip6_addr
)))){
857 /* BB lock server and tcp session and increment use count here?? */
858 *psrvTcp
= ses
->server
; /* found a match on the TCP session */
859 /* BB check if reconnection needed */
861 (ses
->userName
, userName
,
862 MAX_USERNAME_SIZE
) == 0){
863 read_unlock(&GlobalSMBSeslock
);
864 return ses
; /* found exact match on both tcp and SMB sessions */
868 /* else tcp and smb sessions need reconnection */
870 read_unlock(&GlobalSMBSeslock
);
874 static struct cifsTconInfo
*
875 find_unc(__be32 new_target_ip_addr
, char *uncName
, char *userName
)
877 struct list_head
*tmp
;
878 struct cifsTconInfo
*tcon
;
880 read_lock(&GlobalSMBSeslock
);
881 list_for_each(tmp
, &GlobalTreeConnectionList
) {
882 cFYI(1, ("Next tcon - "));
883 tcon
= list_entry(tmp
, struct cifsTconInfo
, cifsConnectionList
);
885 if (tcon
->ses
->server
) {
887 (" old ip addr: %x == new ip %x ?",
888 tcon
->ses
->server
->addr
.sockAddr
.sin_addr
.
889 s_addr
, new_target_ip_addr
));
890 if (tcon
->ses
->server
->addr
.sockAddr
.sin_addr
.
891 s_addr
== new_target_ip_addr
) {
892 /* BB lock tcon and server and tcp session and increment use count here? */
893 /* found a match on the TCP session */
894 /* BB check if reconnection needed */
895 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
896 tcon
->treeName
, uncName
));
898 (tcon
->treeName
, uncName
,
899 MAX_TREE_SIZE
) == 0) {
901 ("Matched UNC, old user: %s == new: %s ?",
902 tcon
->treeName
, uncName
));
904 (tcon
->ses
->userName
,
906 MAX_USERNAME_SIZE
) == 0) {
907 read_unlock(&GlobalSMBSeslock
);
908 return tcon
;/* also matched user (smb session)*/
915 read_unlock(&GlobalSMBSeslock
);
920 connect_to_dfs_path(int xid
, struct cifsSesInfo
*pSesInfo
,
921 const char *old_path
, const struct nls_table
*nls_codepage
)
923 unsigned char *referrals
= NULL
;
924 unsigned int num_referrals
;
927 rc
= get_dfs_path(xid
, pSesInfo
,old_path
, nls_codepage
,
928 &num_referrals
, &referrals
);
930 /* BB Add in code to: if valid refrl, if not ip address contact
931 the helper that resolves tcp names, mount to it, try to
932 tcon to it unmount it if fail */
941 get_dfs_path(int xid
, struct cifsSesInfo
*pSesInfo
,
942 const char *old_path
, const struct nls_table
*nls_codepage
,
943 unsigned int *pnum_referrals
, unsigned char ** preferrals
)
950 if (pSesInfo
->ipc_tid
== 0) {
951 temp_unc
= kmalloc(2 /* for slashes */ +
952 strnlen(pSesInfo
->serverName
,SERVER_NAME_LEN_WITH_NULL
* 2)
953 + 1 + 4 /* slash IPC$ */ + 2,
955 if (temp_unc
== NULL
)
959 strcpy(temp_unc
+ 2, pSesInfo
->serverName
);
960 strcpy(temp_unc
+ 2 + strlen(pSesInfo
->serverName
), "\\IPC$");
961 rc
= CIFSTCon(xid
, pSesInfo
, temp_unc
, NULL
, nls_codepage
);
963 ("CIFS Tcon rc = %d ipc_tid = %d", rc
,pSesInfo
->ipc_tid
));
967 rc
= CIFSGetDFSRefer(xid
, pSesInfo
, old_path
, preferrals
,
968 pnum_referrals
, nls_codepage
);
973 /* See RFC1001 section 14 on representation of Netbios names */
974 static void rfc1002mangle(char * target
,char * source
, unsigned int length
)
978 for(i
=0,j
=0;i
<(length
);i
++) {
979 /* mask a nibble at a time and encode */
980 target
[j
] = 'A' + (0x0F & (source
[i
] >> 4));
981 target
[j
+1] = 'A' + (0x0F & source
[i
]);
989 ipv4_connect(struct sockaddr_in
*psin_server
, struct socket
**csocket
,
994 __be16 orig_port
= 0;
996 if(*csocket
== NULL
) {
997 rc
= sock_create_kern(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, csocket
);
999 cERROR(1, ("Error %d creating socket",rc
));
1003 /* BB other socket options to set KEEPALIVE, NODELAY? */
1004 cFYI(1,("Socket created"));
1005 (*csocket
)->sk
->sk_allocation
= GFP_NOFS
;
1009 psin_server
->sin_family
= AF_INET
;
1010 if(psin_server
->sin_port
) { /* user overrode default port */
1011 rc
= (*csocket
)->ops
->connect(*csocket
,
1012 (struct sockaddr
*) psin_server
,
1013 sizeof (struct sockaddr_in
),0);
1019 /* save original port so we can retry user specified port
1020 later if fall back ports fail this time */
1021 orig_port
= psin_server
->sin_port
;
1023 /* do not retry on the same port we just failed on */
1024 if(psin_server
->sin_port
!= htons(CIFS_PORT
)) {
1025 psin_server
->sin_port
= htons(CIFS_PORT
);
1027 rc
= (*csocket
)->ops
->connect(*csocket
,
1028 (struct sockaddr
*) psin_server
,
1029 sizeof (struct sockaddr_in
),0);
1035 psin_server
->sin_port
= htons(RFC1001_PORT
);
1036 rc
= (*csocket
)->ops
->connect(*csocket
, (struct sockaddr
*)
1037 psin_server
, sizeof (struct sockaddr_in
),0);
1042 /* give up here - unless we want to retry on different
1043 protocol families some day */
1046 psin_server
->sin_port
= orig_port
;
1047 cFYI(1,("Error %d connecting to server via ipv4",rc
));
1048 sock_release(*csocket
);
1052 /* Eventually check for other socket options to change from
1053 the default. sock_setsockopt not used because it expects
1054 user space buffer */
1055 (*csocket
)->sk
->sk_rcvtimeo
= 7 * HZ
;
1057 /* send RFC1001 sessinit */
1059 if(psin_server
->sin_port
== htons(RFC1001_PORT
)) {
1060 /* some servers require RFC1001 sessinit before sending
1061 negprot - BB check reconnection in case where second
1062 sessinit is sent but no second negprot */
1063 struct rfc1002_session_packet
* ses_init_buf
;
1064 struct smb_hdr
* smb_buf
;
1065 ses_init_buf
= cifs_kcalloc(sizeof(struct rfc1002_session_packet
), GFP_KERNEL
);
1067 ses_init_buf
->trailer
.session_req
.called_len
= 32;
1068 rfc1002mangle(ses_init_buf
->trailer
.session_req
.called_name
,
1069 DEFAULT_CIFS_CALLED_NAME
,16);
1070 ses_init_buf
->trailer
.session_req
.calling_len
= 32;
1071 /* calling name ends in null (byte 16) from old smb
1073 if(netbios_name
&& (netbios_name
[0] !=0)) {
1074 rfc1002mangle(ses_init_buf
->trailer
.session_req
.calling_name
,
1077 rfc1002mangle(ses_init_buf
->trailer
.session_req
.calling_name
,
1078 "LINUX_CIFS_CLNT",16);
1080 ses_init_buf
->trailer
.session_req
.scope1
= 0;
1081 ses_init_buf
->trailer
.session_req
.scope2
= 0;
1082 smb_buf
= (struct smb_hdr
*)ses_init_buf
;
1083 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1084 smb_buf
->smb_buf_length
= 0x81000044;
1085 rc
= smb_send(*csocket
, smb_buf
, 0x44,
1086 (struct sockaddr
*)psin_server
);
1087 kfree(ses_init_buf
);
1089 /* else the negprot may still work without this
1090 even though malloc failed */
1098 ipv6_connect(struct sockaddr_in6
*psin_server
, struct socket
**csocket
)
1102 __be16 orig_port
= 0;
1104 if(*csocket
== NULL
) {
1105 rc
= sock_create_kern(PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, csocket
);
1107 cERROR(1, ("Error %d creating ipv6 socket",rc
));
1111 /* BB other socket options to set KEEPALIVE, NODELAY? */
1112 cFYI(1,("ipv6 Socket created"));
1113 (*csocket
)->sk
->sk_allocation
= GFP_NOFS
;
1117 psin_server
->sin6_family
= AF_INET6
;
1119 if(psin_server
->sin6_port
) { /* user overrode default port */
1120 rc
= (*csocket
)->ops
->connect(*csocket
,
1121 (struct sockaddr
*) psin_server
,
1122 sizeof (struct sockaddr_in6
),0);
1128 /* save original port so we can retry user specified port
1129 later if fall back ports fail this time */
1131 orig_port
= psin_server
->sin6_port
;
1132 /* do not retry on the same port we just failed on */
1133 if(psin_server
->sin6_port
!= htons(CIFS_PORT
)) {
1134 psin_server
->sin6_port
= htons(CIFS_PORT
);
1136 rc
= (*csocket
)->ops
->connect(*csocket
,
1137 (struct sockaddr
*) psin_server
,
1138 sizeof (struct sockaddr_in6
),0);
1144 psin_server
->sin6_port
= htons(RFC1001_PORT
);
1145 rc
= (*csocket
)->ops
->connect(*csocket
, (struct sockaddr
*)
1146 psin_server
, sizeof (struct sockaddr_in6
),0);
1151 /* give up here - unless we want to retry on different
1152 protocol families some day */
1155 psin_server
->sin6_port
= orig_port
;
1156 cFYI(1,("Error %d connecting to server via ipv6",rc
));
1157 sock_release(*csocket
);
1161 /* Eventually check for other socket options to change from
1162 the default. sock_setsockopt not used because it expects
1163 user space buffer */
1164 (*csocket
)->sk
->sk_rcvtimeo
= 7 * HZ
;
1170 cifs_mount(struct super_block
*sb
, struct cifs_sb_info
*cifs_sb
,
1171 char *mount_data
, const char *devname
)
1175 int address_type
= AF_INET
;
1176 struct socket
*csocket
= NULL
;
1177 struct sockaddr_in sin_server
;
1178 struct sockaddr_in6 sin_server6
;
1179 struct smb_vol volume_info
;
1180 struct cifsSesInfo
*pSesInfo
= NULL
;
1181 struct cifsSesInfo
*existingCifsSes
= NULL
;
1182 struct cifsTconInfo
*tcon
= NULL
;
1183 struct TCP_Server_Info
*srvTcp
= NULL
;
1187 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1189 memset(&volume_info
,0,sizeof(struct smb_vol
));
1190 if (cifs_parse_mount_options(mount_data
, devname
, &volume_info
)) {
1192 kfree(volume_info
.UNC
);
1193 if(volume_info
.password
)
1194 kfree(volume_info
.password
);
1199 if (volume_info
.username
) {
1200 /* BB fixme parse for domain name here */
1201 cFYI(1, ("Username: %s ", volume_info
.username
));
1204 cifserror("No username specified ");
1205 /* In userspace mount helper we can get user name from alternate
1206 locations such as env variables and files on disk */
1208 kfree(volume_info
.UNC
);
1209 if(volume_info
.password
)
1210 kfree(volume_info
.password
);
1215 if (volume_info
.UNCip
&& volume_info
.UNC
) {
1216 rc
= cifs_inet_pton(AF_INET
, volume_info
.UNCip
,&sin_server
.sin_addr
.s_addr
);
1219 /* not ipv4 address, try ipv6 */
1220 rc
= cifs_inet_pton(AF_INET6
,volume_info
.UNCip
,&sin_server6
.sin6_addr
.in6_u
);
1222 address_type
= AF_INET6
;
1224 address_type
= AF_INET
;
1228 /* we failed translating address */
1230 kfree(volume_info
.UNC
);
1231 if(volume_info
.password
)
1232 kfree(volume_info
.password
);
1237 cFYI(1, ("UNC: %s ip: %s", volume_info
.UNC
, volume_info
.UNCip
));
1240 } else if (volume_info
.UNCip
){
1241 /* BB using ip addr as server name connect to the DFS root below */
1242 cERROR(1,("Connecting to DFS root not implemented yet"));
1244 kfree(volume_info
.UNC
);
1245 if(volume_info
.password
)
1246 kfree(volume_info
.password
);
1249 } else /* which servers DFS root would we conect to */ {
1251 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1253 kfree(volume_info
.UNC
);
1254 if(volume_info
.password
)
1255 kfree(volume_info
.password
);
1260 /* this is needed for ASCII cp to Unicode converts */
1261 if(volume_info
.iocharset
== NULL
) {
1262 cifs_sb
->local_nls
= load_nls_default();
1263 /* load_nls_default can not return null */
1265 cifs_sb
->local_nls
= load_nls(volume_info
.iocharset
);
1266 if(cifs_sb
->local_nls
== NULL
) {
1267 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info
.iocharset
));
1269 kfree(volume_info
.UNC
);
1270 if(volume_info
.password
)
1271 kfree(volume_info
.password
);
1277 if(address_type
== AF_INET
)
1278 existingCifsSes
= cifs_find_tcp_session(&sin_server
.sin_addr
,
1279 NULL
/* no ipv6 addr */,
1280 volume_info
.username
, &srvTcp
);
1281 else if(address_type
== AF_INET6
)
1282 existingCifsSes
= cifs_find_tcp_session(NULL
/* no ipv4 addr */,
1283 &sin_server6
.sin6_addr
,
1284 volume_info
.username
, &srvTcp
);
1287 kfree(volume_info
.UNC
);
1288 if(volume_info
.password
)
1289 kfree(volume_info
.password
);
1296 cFYI(1, ("Existing tcp session with server found "));
1297 } else { /* create socket */
1298 if(volume_info
.port
)
1299 sin_server
.sin_port
= htons(volume_info
.port
);
1301 sin_server
.sin_port
= 0;
1302 rc
= ipv4_connect(&sin_server
,&csocket
,volume_info
.source_rfc1001_name
);
1305 ("Error connecting to IPv4 socket. Aborting operation"));
1307 sock_release(csocket
);
1309 kfree(volume_info
.UNC
);
1310 if(volume_info
.password
)
1311 kfree(volume_info
.password
);
1316 srvTcp
= kmalloc(sizeof (struct TCP_Server_Info
), GFP_KERNEL
);
1317 if (srvTcp
== NULL
) {
1319 sock_release(csocket
);
1321 kfree(volume_info
.UNC
);
1322 if(volume_info
.password
)
1323 kfree(volume_info
.password
);
1327 memset(srvTcp
, 0, sizeof (struct TCP_Server_Info
));
1328 memcpy(&srvTcp
->addr
.sockAddr
, &sin_server
, sizeof (struct sockaddr_in
));
1329 atomic_set(&srvTcp
->inFlight
,0);
1330 /* BB Add code for ipv6 case too */
1331 srvTcp
->ssocket
= csocket
;
1332 srvTcp
->protocolType
= IPV4
;
1333 init_waitqueue_head(&srvTcp
->response_q
);
1334 init_waitqueue_head(&srvTcp
->request_q
);
1335 INIT_LIST_HEAD(&srvTcp
->pending_mid_q
);
1336 /* at this point we are the only ones with the pointer
1337 to the struct since the kernel thread not created yet
1338 so no need to spinlock this init of tcpStatus */
1339 srvTcp
->tcpStatus
= CifsNew
;
1340 init_MUTEX(&srvTcp
->tcpSem
);
1341 rc
= (int)kernel_thread((void *)(void *)cifs_demultiplex_thread
, srvTcp
,
1342 CLONE_FS
| CLONE_FILES
| CLONE_VM
);
1345 sock_release(csocket
);
1347 kfree(volume_info
.UNC
);
1348 if(volume_info
.password
)
1349 kfree(volume_info
.password
);
1354 memcpy(srvTcp
->workstation_RFC1001_name
, volume_info
.source_rfc1001_name
,16);
1358 if (existingCifsSes
) {
1359 pSesInfo
= existingCifsSes
;
1360 cFYI(1, ("Existing smb sess found "));
1361 if(volume_info
.password
)
1362 kfree(volume_info
.password
);
1363 /* volume_info.UNC freed at end of function */
1365 cFYI(1, ("Existing smb sess not found "));
1366 pSesInfo
= sesInfoAlloc();
1367 if (pSesInfo
== NULL
)
1370 pSesInfo
->server
= srvTcp
;
1371 sprintf(pSesInfo
->serverName
, "%u.%u.%u.%u",
1372 NIPQUAD(sin_server
.sin_addr
.s_addr
));
1376 /* volume_info.password freed at unmount */
1377 if (volume_info
.password
)
1378 pSesInfo
->password
= volume_info
.password
;
1379 if (volume_info
.username
)
1380 strncpy(pSesInfo
->userName
,
1381 volume_info
.username
,MAX_USERNAME_SIZE
);
1382 if (volume_info
.domainname
)
1383 strncpy(pSesInfo
->domainName
,
1384 volume_info
.domainname
,MAX_USERNAME_SIZE
);
1385 pSesInfo
->linux_uid
= volume_info
.linux_uid
;
1386 down(&pSesInfo
->sesSem
);
1387 rc
= cifs_setup_session(xid
,pSesInfo
, cifs_sb
->local_nls
);
1388 up(&pSesInfo
->sesSem
);
1390 atomic_inc(&srvTcp
->socketUseCount
);
1392 if(volume_info
.password
)
1393 kfree(volume_info
.password
);
1396 /* search for existing tcon to this server share */
1398 if((volume_info
.rsize
) && (volume_info
.rsize
<= CIFSMaxBufSize
))
1399 cifs_sb
->rsize
= volume_info
.rsize
;
1401 cifs_sb
->rsize
= srvTcp
->maxBuf
- MAX_CIFS_HDR_SIZE
; /* default */
1402 if((volume_info
.wsize
) && (volume_info
.wsize
<= CIFSMaxBufSize
))
1403 cifs_sb
->wsize
= volume_info
.wsize
;
1405 cifs_sb
->wsize
= CIFSMaxBufSize
; /* default */
1406 if(cifs_sb
->rsize
< PAGE_CACHE_SIZE
) {
1407 cifs_sb
->rsize
= PAGE_CACHE_SIZE
;
1408 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1410 cifs_sb
->mnt_uid
= volume_info
.linux_uid
;
1411 cifs_sb
->mnt_gid
= volume_info
.linux_gid
;
1412 cifs_sb
->mnt_file_mode
= volume_info
.file_mode
;
1413 cifs_sb
->mnt_dir_mode
= volume_info
.dir_mode
;
1414 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb
->mnt_file_mode
,cifs_sb
->mnt_dir_mode
));
1416 if(volume_info
.noperm
)
1417 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_NO_PERM
;
1418 if(volume_info
.setuids
)
1419 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_SET_UID
;
1420 if(volume_info
.server_ino
)
1421 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_SERVER_INUM
;
1422 if(volume_info
.no_xattr
)
1423 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_NO_XATTR
;
1424 if(volume_info
.direct_io
) {
1425 cERROR(1,("mounting share using direct i/o"));
1426 cifs_sb
->mnt_cifs_flags
|= CIFS_MOUNT_DIRECT_IO
;
1430 find_unc(sin_server
.sin_addr
.s_addr
, volume_info
.UNC
,
1431 volume_info
.username
);
1433 cFYI(1, ("Found match on UNC path "));
1434 /* we can have only one retry value for a connection
1435 to a share so for resources mounted more than once
1436 to the same server share the last value passed in
1437 for the retry flag is used */
1438 tcon
->retry
= volume_info
.retry
;
1440 tcon
= tconInfoAlloc();
1444 /* check for null share name ie connect to dfs root */
1446 /* BB check if this works for exactly length three strings */
1447 if ((strchr(volume_info
.UNC
+ 3, '\\') == NULL
)
1448 && (strchr(volume_info
.UNC
+ 3, '/') ==
1450 rc
= connect_to_dfs_path(xid
,
1456 kfree(volume_info
.UNC
);
1460 rc
= CIFSTCon(xid
, pSesInfo
,
1462 tcon
, cifs_sb
->local_nls
);
1463 cFYI(1, ("CIFS Tcon rc = %d", rc
));
1466 atomic_inc(&pSesInfo
->inUse
);
1467 tcon
->retry
= volume_info
.retry
;
1473 if (pSesInfo
->capabilities
& CAP_LARGE_FILES
) {
1474 sb
->s_maxbytes
= (u64
) 1 << 63;
1476 sb
->s_maxbytes
= (u64
) 1 << 31; /* 2 GB */
1479 sb
->s_time_gran
= 100;
1481 /* on error free sesinfo and tcon struct if needed */
1483 /* if session setup failed, use count is zero but
1484 we still need to free cifsd thread */
1485 if(atomic_read(&srvTcp
->socketUseCount
) == 0) {
1486 spin_lock(&GlobalMid_Lock
);
1487 srvTcp
->tcpStatus
= CifsExiting
;
1488 spin_unlock(&GlobalMid_Lock
);
1490 send_sig(SIGKILL
,srvTcp
->tsk
,1);
1492 /* If find_unc succeeded then rc == 0 so we can not end */
1493 if (tcon
) /* up accidently freeing someone elses tcon struct */
1495 if (existingCifsSes
== NULL
) {
1497 if ((pSesInfo
->server
) &&
1498 (pSesInfo
->status
== CifsGood
)) {
1500 temp_rc
= CIFSSMBLogoff(xid
, pSesInfo
);
1501 /* if the socketUseCount is now zero */
1502 if((temp_rc
== -ESHUTDOWN
) &&
1503 (pSesInfo
->server
->tsk
))
1504 send_sig(SIGKILL
,pSesInfo
->server
->tsk
,1);
1506 cFYI(1, ("No session or bad tcon"));
1507 sesInfoFree(pSesInfo
);
1508 /* pSesInfo = NULL; */
1512 atomic_inc(&tcon
->useCount
);
1513 cifs_sb
->tcon
= tcon
;
1514 tcon
->ses
= pSesInfo
;
1516 /* do not care if following two calls succeed - informational only */
1517 CIFSSMBQFSDeviceInfo(xid
, tcon
, cifs_sb
->local_nls
);
1518 CIFSSMBQFSAttributeInfo(xid
, tcon
, cifs_sb
->local_nls
);
1519 if (tcon
->ses
->capabilities
& CAP_UNIX
) {
1520 if(!CIFSSMBQFSUnixInfo(xid
, tcon
, cifs_sb
->local_nls
)) {
1521 if(!volume_info
.no_psx_acl
) {
1522 if(CIFS_UNIX_POSIX_ACL_CAP
&
1523 le64_to_cpu(tcon
->fsUnixInfo
.Capability
))
1524 cFYI(1,("server negotiated posix acl support"));
1525 sb
->s_flags
|= MS_POSIXACL
;
1531 /* volume_info.password is freed above when existing session found
1532 (in which case it is not needed anymore) but when new sesion is created
1533 the password ptr is put in the new session structure (in which case the
1534 password will be freed at unmount time) */
1536 kfree(volume_info
.UNC
);
1542 CIFSSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
1543 char session_key
[CIFS_SESSION_KEY_SIZE
],
1544 const struct nls_table
*nls_codepage
)
1546 struct smb_hdr
*smb_buffer
;
1547 struct smb_hdr
*smb_buffer_response
;
1548 SESSION_SETUP_ANDX
*pSMB
;
1549 SESSION_SETUP_ANDX
*pSMBr
;
1554 int remaining_words
= 0;
1555 int bytes_returned
= 0;
1560 cFYI(1, ("In sesssetup "));
1563 user
= ses
->userName
;
1564 domain
= ses
->domainName
;
1565 smb_buffer
= cifs_buf_get();
1566 if (smb_buffer
== NULL
) {
1569 smb_buffer_response
= smb_buffer
;
1570 pSMBr
= pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
1572 /* send SMBsessionSetup here */
1573 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
1574 NULL
/* no tCon exists yet */ , 13 /* wct */ );
1576 pSMB
->req_no_secext
.AndXCommand
= 0xFF;
1577 pSMB
->req_no_secext
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
1578 pSMB
->req_no_secext
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
1580 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
1581 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
1583 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
1584 CAP_LARGE_WRITE_X
| CAP_LARGE_READ_X
;
1585 if (ses
->capabilities
& CAP_UNICODE
) {
1586 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
1587 capabilities
|= CAP_UNICODE
;
1589 if (ses
->capabilities
& CAP_STATUS32
) {
1590 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
1591 capabilities
|= CAP_STATUS32
;
1593 if (ses
->capabilities
& CAP_DFS
) {
1594 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
1595 capabilities
|= CAP_DFS
;
1597 pSMB
->req_no_secext
.Capabilities
= cpu_to_le32(capabilities
);
1599 pSMB
->req_no_secext
.CaseInsensitivePasswordLength
=
1600 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
1602 pSMB
->req_no_secext
.CaseSensitivePasswordLength
=
1603 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
1604 bcc_ptr
= pByteArea(smb_buffer
);
1605 memcpy(bcc_ptr
, (char *) session_key
, CIFS_SESSION_KEY_SIZE
);
1606 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
1607 memcpy(bcc_ptr
, (char *) session_key
, CIFS_SESSION_KEY_SIZE
);
1608 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
1610 if (ses
->capabilities
& CAP_UNICODE
) {
1611 if ((long) bcc_ptr
% 2) { /* must be word aligned for Unicode */
1616 bytes_returned
= 0; /* skill null user */
1619 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 100,
1621 /* convert number of 16 bit words to bytes */
1622 bcc_ptr
+= 2 * bytes_returned
;
1623 bcc_ptr
+= 2; /* trailing null */
1626 cifs_strtoUCS((wchar_t *) bcc_ptr
,
1627 "CIFS_LINUX_DOM", 32, nls_codepage
);
1630 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
1632 bcc_ptr
+= 2 * bytes_returned
;
1635 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
1637 bcc_ptr
+= 2 * bytes_returned
;
1639 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
,
1641 bcc_ptr
+= 2 * bytes_returned
;
1644 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
1646 bcc_ptr
+= 2 * bytes_returned
;
1650 strncpy(bcc_ptr
, user
, 200);
1651 bcc_ptr
+= strnlen(user
, 200);
1655 if (domain
== NULL
) {
1656 strcpy(bcc_ptr
, "CIFS_LINUX_DOM");
1657 bcc_ptr
+= strlen("CIFS_LINUX_DOM") + 1;
1659 strncpy(bcc_ptr
, domain
, 64);
1660 bcc_ptr
+= strnlen(domain
, 64);
1664 strcpy(bcc_ptr
, "Linux version ");
1665 bcc_ptr
+= strlen("Linux version ");
1666 strcpy(bcc_ptr
, system_utsname
.release
);
1667 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
1668 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
1669 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
1671 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
1672 smb_buffer
->smb_buf_length
+= count
;
1673 pSMB
->req_no_secext
.ByteCount
= cpu_to_le16(count
);
1675 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
1676 &bytes_returned
, 1);
1678 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1679 } else if ((smb_buffer_response
->WordCount
== 3)
1680 || (smb_buffer_response
->WordCount
== 4)) {
1681 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
1682 __u16 blob_len
= le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
1683 if (action
& GUEST_LOGIN
)
1684 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1685 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format (le) */
1686 cFYI(1, ("UID = %d ", ses
->Suid
));
1687 /* response can have either 3 or 4 word count - Samba sends 3 */
1688 bcc_ptr
= pByteArea(smb_buffer_response
);
1689 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
1690 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
1691 && (blob_len
< pSMBr
->resp
.ByteCount
))) {
1692 if (pSMBr
->resp
.hdr
.WordCount
== 4)
1693 bcc_ptr
+= blob_len
;
1695 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
1696 if ((long) (bcc_ptr
) % 2) {
1698 (BCC(smb_buffer_response
) - 1) /2;
1699 bcc_ptr
++; /* Unicode strings must be word aligned */
1702 BCC(smb_buffer_response
) / 2;
1705 UniStrnlen((wchar_t *) bcc_ptr
,
1706 remaining_words
- 1);
1707 /* We look for obvious messed up bcc or strings in response so we do not go off
1708 the end since (at least) WIN2K and Windows XP have a major bug in not null
1709 terminating last Unicode string in response */
1710 ses
->serverOS
= cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
1711 cifs_strfromUCS_le(ses
->serverOS
,
1712 (wchar_t *)bcc_ptr
, len
,nls_codepage
);
1713 bcc_ptr
+= 2 * (len
+ 1);
1714 remaining_words
-= len
+ 1;
1715 ses
->serverOS
[2 * len
] = 0;
1716 ses
->serverOS
[1 + (2 * len
)] = 0;
1717 if (remaining_words
> 0) {
1718 len
= UniStrnlen((wchar_t *)bcc_ptr
,
1720 ses
->serverNOS
=cifs_kcalloc(2 * (len
+ 1),GFP_KERNEL
);
1721 cifs_strfromUCS_le(ses
->serverNOS
,
1722 (wchar_t *)bcc_ptr
,len
,nls_codepage
);
1723 bcc_ptr
+= 2 * (len
+ 1);
1724 ses
->serverNOS
[2 * len
] = 0;
1725 ses
->serverNOS
[1 + (2 * len
)] = 0;
1726 if(strncmp(ses
->serverNOS
,
1727 "NT LAN Manager 4",16) == 0) {
1728 cFYI(1,("NT4 server"));
1729 ses
->flags
|= CIFS_SES_NT4
;
1731 remaining_words
-= len
+ 1;
1732 if (remaining_words
> 0) {
1733 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
1734 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1736 cifs_kcalloc(2*(len
+1),GFP_KERNEL
);
1737 cifs_strfromUCS_le(ses
->serverDomain
,
1738 (wchar_t *)bcc_ptr
,len
,nls_codepage
);
1739 bcc_ptr
+= 2 * (len
+ 1);
1740 ses
->serverDomain
[2*len
] = 0;
1741 ses
->serverDomain
[1+(2*len
)] = 0;
1742 } /* else no more room so create dummy domain string */
1747 } else { /* no room so create dummy domain and NOS string */
1749 cifs_kcalloc(2, GFP_KERNEL
);
1751 cifs_kcalloc(2, GFP_KERNEL
);
1753 } else { /* ASCII */
1754 len
= strnlen(bcc_ptr
, 1024);
1755 if (((long) bcc_ptr
+ len
) - (long)
1756 pByteArea(smb_buffer_response
)
1757 <= BCC(smb_buffer_response
)) {
1758 ses
->serverOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1759 strncpy(ses
->serverOS
,bcc_ptr
, len
);
1762 bcc_ptr
[0] = 0; /* null terminate the string */
1765 len
= strnlen(bcc_ptr
, 1024);
1766 ses
->serverNOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1767 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
1772 len
= strnlen(bcc_ptr
, 1024);
1773 ses
->serverDomain
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
1774 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
1780 ("Variable field of length %d extends beyond end of smb ",
1785 (" Security Blob Length extends beyond end of SMB"));
1789 (" Invalid Word count %d: ",
1790 smb_buffer_response
->WordCount
));
1795 cifs_buf_release(smb_buffer
);
1801 CIFSSpnegoSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
1802 char *SecurityBlob
,int SecurityBlobLength
,
1803 const struct nls_table
*nls_codepage
)
1805 struct smb_hdr
*smb_buffer
;
1806 struct smb_hdr
*smb_buffer_response
;
1807 SESSION_SETUP_ANDX
*pSMB
;
1808 SESSION_SETUP_ANDX
*pSMBr
;
1813 int remaining_words
= 0;
1814 int bytes_returned
= 0;
1819 cFYI(1, ("In spnego sesssetup "));
1822 user
= ses
->userName
;
1823 domain
= ses
->domainName
;
1825 smb_buffer
= cifs_buf_get();
1826 if (smb_buffer
== NULL
) {
1829 smb_buffer_response
= smb_buffer
;
1830 pSMBr
= pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
1832 /* send SMBsessionSetup here */
1833 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
1834 NULL
/* no tCon exists yet */ , 12 /* wct */ );
1835 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
1836 pSMB
->req
.AndXCommand
= 0xFF;
1837 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
1838 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
1840 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
1841 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
1843 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
1844 CAP_EXTENDED_SECURITY
;
1845 if (ses
->capabilities
& CAP_UNICODE
) {
1846 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
1847 capabilities
|= CAP_UNICODE
;
1849 if (ses
->capabilities
& CAP_STATUS32
) {
1850 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
1851 capabilities
|= CAP_STATUS32
;
1853 if (ses
->capabilities
& CAP_DFS
) {
1854 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
1855 capabilities
|= CAP_DFS
;
1857 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
1859 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
1860 bcc_ptr
= pByteArea(smb_buffer
);
1861 memcpy(bcc_ptr
, SecurityBlob
, SecurityBlobLength
);
1862 bcc_ptr
+= SecurityBlobLength
;
1864 if (ses
->capabilities
& CAP_UNICODE
) {
1865 if ((long) bcc_ptr
% 2) { /* must be word aligned for Unicode strings */
1870 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 100, nls_codepage
);
1871 bcc_ptr
+= 2 * bytes_returned
; /* convert num of 16 bit words to bytes */
1872 bcc_ptr
+= 2; /* trailing null */
1875 cifs_strtoUCS((wchar_t *) bcc_ptr
,
1876 "CIFS_LINUX_DOM", 32, nls_codepage
);
1879 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
1881 bcc_ptr
+= 2 * bytes_returned
;
1884 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
1886 bcc_ptr
+= 2 * bytes_returned
;
1888 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
1890 bcc_ptr
+= 2 * bytes_returned
;
1893 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
1895 bcc_ptr
+= 2 * bytes_returned
;
1898 strncpy(bcc_ptr
, user
, 200);
1899 bcc_ptr
+= strnlen(user
, 200);
1902 if (domain
== NULL
) {
1903 strcpy(bcc_ptr
, "CIFS_LINUX_DOM");
1904 bcc_ptr
+= strlen("CIFS_LINUX_DOM") + 1;
1906 strncpy(bcc_ptr
, domain
, 64);
1907 bcc_ptr
+= strnlen(domain
, 64);
1911 strcpy(bcc_ptr
, "Linux version ");
1912 bcc_ptr
+= strlen("Linux version ");
1913 strcpy(bcc_ptr
, system_utsname
.release
);
1914 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
1915 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
1916 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
1918 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
1919 smb_buffer
->smb_buf_length
+= count
;
1920 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
1922 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
1923 &bytes_returned
, 1);
1925 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1926 } else if ((smb_buffer_response
->WordCount
== 3)
1927 || (smb_buffer_response
->WordCount
== 4)) {
1928 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
1930 le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
1931 if (action
& GUEST_LOGIN
)
1932 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1934 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format (le) */
1935 cFYI(1, ("UID = %d ", ses
->Suid
));
1936 bcc_ptr
= pByteArea(smb_buffer_response
); /* response can have either 3 or 4 word count - Samba sends 3 */
1938 /* BB Fix below to make endian neutral !! */
1940 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
1941 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
1943 pSMBr
->resp
.ByteCount
))) {
1944 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
1948 ("Security Blob Length %d ",
1952 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
1953 if ((long) (bcc_ptr
) % 2) {
1955 (BCC(smb_buffer_response
)
1957 bcc_ptr
++; /* Unicode strings must be word aligned */
1961 (smb_buffer_response
) / 2;
1964 UniStrnlen((wchar_t *) bcc_ptr
,
1965 remaining_words
- 1);
1966 /* We look for obvious messed up bcc or strings in response so we do not go off
1967 the end since (at least) WIN2K and Windows XP have a major bug in not null
1968 terminating last Unicode string in response */
1970 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
1971 cifs_strfromUCS_le(ses
->serverOS
,
1975 bcc_ptr
+= 2 * (len
+ 1);
1976 remaining_words
-= len
+ 1;
1977 ses
->serverOS
[2 * len
] = 0;
1978 ses
->serverOS
[1 + (2 * len
)] = 0;
1979 if (remaining_words
> 0) {
1980 len
= UniStrnlen((wchar_t *)bcc_ptr
,
1984 cifs_kcalloc(2 * (len
+ 1),
1986 cifs_strfromUCS_le(ses
->serverNOS
,
1990 bcc_ptr
+= 2 * (len
+ 1);
1991 ses
->serverNOS
[2 * len
] = 0;
1992 ses
->serverNOS
[1 + (2 * len
)] = 0;
1993 remaining_words
-= len
+ 1;
1994 if (remaining_words
> 0) {
1995 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
1996 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1997 ses
->serverDomain
= cifs_kcalloc(2*(len
+1),GFP_KERNEL
);
1998 cifs_strfromUCS_le(ses
->serverDomain
,
2002 bcc_ptr
+= 2*(len
+1);
2003 ses
->serverDomain
[2*len
] = 0;
2004 ses
->serverDomain
[1+(2*len
)] = 0;
2005 } /* else no more room so create dummy domain string */
2008 cifs_kcalloc(2,GFP_KERNEL
);
2009 } else { /* no room so create dummy domain and NOS string */
2010 ses
->serverDomain
= cifs_kcalloc(2, GFP_KERNEL
);
2011 ses
->serverNOS
= cifs_kcalloc(2, GFP_KERNEL
);
2013 } else { /* ASCII */
2015 len
= strnlen(bcc_ptr
, 1024);
2016 if (((long) bcc_ptr
+ len
) - (long)
2017 pByteArea(smb_buffer_response
)
2018 <= BCC(smb_buffer_response
)) {
2019 ses
->serverOS
= cifs_kcalloc(len
+ 1, GFP_KERNEL
);
2020 strncpy(ses
->serverOS
, bcc_ptr
, len
);
2023 bcc_ptr
[0] = 0; /* null terminate the string */
2026 len
= strnlen(bcc_ptr
, 1024);
2027 ses
->serverNOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
2028 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2033 len
= strnlen(bcc_ptr
, 1024);
2034 ses
->serverDomain
= cifs_kcalloc(len
+ 1, GFP_KERNEL
);
2035 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2041 ("Variable field of length %d extends beyond end of smb ",
2046 (" Security Blob Length extends beyond end of SMB"));
2049 cERROR(1, ("No session structure passed in."));
2053 (" Invalid Word count %d: ",
2054 smb_buffer_response
->WordCount
));
2059 cifs_buf_release(smb_buffer
);
2065 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid
,
2066 struct cifsSesInfo
*ses
, int * pNTLMv2_flag
,
2067 const struct nls_table
*nls_codepage
)
2069 struct smb_hdr
*smb_buffer
;
2070 struct smb_hdr
*smb_buffer_response
;
2071 SESSION_SETUP_ANDX
*pSMB
;
2072 SESSION_SETUP_ANDX
*pSMBr
;
2076 int remaining_words
= 0;
2077 int bytes_returned
= 0;
2079 int SecurityBlobLength
= sizeof (NEGOTIATE_MESSAGE
);
2080 PNEGOTIATE_MESSAGE SecurityBlob
;
2081 PCHALLENGE_MESSAGE SecurityBlob2
;
2082 __u32 negotiate_flags
, capabilities
;
2085 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2088 domain
= ses
->domainName
;
2089 *pNTLMv2_flag
= FALSE
;
2090 smb_buffer
= cifs_buf_get();
2091 if (smb_buffer
== NULL
) {
2094 smb_buffer_response
= smb_buffer
;
2095 pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
2096 pSMBr
= (SESSION_SETUP_ANDX
*) smb_buffer_response
;
2098 /* send SMBsessionSetup here */
2099 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
2100 NULL
/* no tCon exists yet */ , 12 /* wct */ );
2101 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
2102 pSMB
->req
.hdr
.Flags
|= (SMBFLG_CASELESS
| SMBFLG_CANONICAL_PATH_FORMAT
);
2104 pSMB
->req
.AndXCommand
= 0xFF;
2105 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
2106 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
2108 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2109 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2111 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
2112 CAP_EXTENDED_SECURITY
;
2113 if (ses
->capabilities
& CAP_UNICODE
) {
2114 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2115 capabilities
|= CAP_UNICODE
;
2117 if (ses
->capabilities
& CAP_STATUS32
) {
2118 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2119 capabilities
|= CAP_STATUS32
;
2121 if (ses
->capabilities
& CAP_DFS
) {
2122 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2123 capabilities
|= CAP_DFS
;
2125 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
2127 bcc_ptr
= (char *) &pSMB
->req
.SecurityBlob
;
2128 SecurityBlob
= (PNEGOTIATE_MESSAGE
) bcc_ptr
;
2129 strncpy(SecurityBlob
->Signature
, NTLMSSP_SIGNATURE
, 8);
2130 SecurityBlob
->MessageType
= NtLmNegotiate
;
2132 NTLMSSP_NEGOTIATE_UNICODE
| NTLMSSP_NEGOTIATE_OEM
|
2133 NTLMSSP_REQUEST_TARGET
| NTLMSSP_NEGOTIATE_NTLM
| 0x80000000 |
2134 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128
;
2136 negotiate_flags
|= NTLMSSP_NEGOTIATE_SIGN
;
2138 negotiate_flags
|= NTLMSSP_NEGOTIATE_NTLMV2
;
2139 /* setup pointers to domain name and workstation name */
2140 bcc_ptr
+= SecurityBlobLength
;
2142 SecurityBlob
->WorkstationName
.Buffer
= 0;
2143 SecurityBlob
->WorkstationName
.Length
= 0;
2144 SecurityBlob
->WorkstationName
.MaximumLength
= 0;
2146 if (domain
== NULL
) {
2147 SecurityBlob
->DomainName
.Buffer
= 0;
2148 SecurityBlob
->DomainName
.Length
= 0;
2149 SecurityBlob
->DomainName
.MaximumLength
= 0;
2152 negotiate_flags
|= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED
;
2153 strncpy(bcc_ptr
, domain
, 63);
2154 len
= strnlen(domain
, 64);
2155 SecurityBlob
->DomainName
.MaximumLength
=
2157 SecurityBlob
->DomainName
.Buffer
=
2158 cpu_to_le32((long) &SecurityBlob
->
2160 (long) &SecurityBlob
->Signature
);
2162 SecurityBlobLength
+= len
;
2163 SecurityBlob
->DomainName
.Length
=
2166 if (ses
->capabilities
& CAP_UNICODE
) {
2167 if ((long) bcc_ptr
% 2) {
2173 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
2175 bcc_ptr
+= 2 * bytes_returned
;
2177 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
2179 bcc_ptr
+= 2 * bytes_returned
;
2180 bcc_ptr
+= 2; /* null terminate Linux version */
2182 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
2184 bcc_ptr
+= 2 * bytes_returned
;
2187 bcc_ptr
+= 2; /* null terminate network opsys string */
2190 bcc_ptr
+= 2; /* null domain */
2191 } else { /* ASCII */
2192 strcpy(bcc_ptr
, "Linux version ");
2193 bcc_ptr
+= strlen("Linux version ");
2194 strcpy(bcc_ptr
, system_utsname
.release
);
2195 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
2196 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
2197 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
2198 bcc_ptr
++; /* empty domain field */
2201 SecurityBlob
->NegotiateFlags
= cpu_to_le32(negotiate_flags
);
2202 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
2203 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
2204 smb_buffer
->smb_buf_length
+= count
;
2205 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
2207 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
2208 &bytes_returned
, 1);
2210 if (smb_buffer_response
->Status
.CifsError
==
2211 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED
))
2215 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2216 } else if ((smb_buffer_response
->WordCount
== 3)
2217 || (smb_buffer_response
->WordCount
== 4)) {
2218 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
2219 __u16 blob_len
= le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
2221 if (action
& GUEST_LOGIN
)
2222 cFYI(1, (" Guest login"));
2223 /* Do we want to set anything in SesInfo struct when guest login? */
2225 bcc_ptr
= pByteArea(smb_buffer_response
);
2226 /* response can have either 3 or 4 word count - Samba sends 3 */
2228 SecurityBlob2
= (PCHALLENGE_MESSAGE
) bcc_ptr
;
2229 if (SecurityBlob2
->MessageType
!= NtLmChallenge
) {
2231 ("Unexpected NTLMSSP message type received %d",
2232 SecurityBlob2
->MessageType
));
2234 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in le format */
2235 cFYI(1, ("UID = %d ", ses
->Suid
));
2236 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
2237 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
2239 pSMBr
->resp
.ByteCount
))) {
2241 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
2242 bcc_ptr
+= blob_len
;
2244 ("Security Blob Length %d ",
2248 cFYI(1, ("NTLMSSP Challenge rcvd "));
2250 memcpy(ses
->server
->cryptKey
,
2251 SecurityBlob2
->Challenge
,
2252 CIFS_CRYPTO_KEY_SIZE
);
2253 if(SecurityBlob2
->NegotiateFlags
& cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2
))
2254 *pNTLMv2_flag
= TRUE
;
2256 if((SecurityBlob2
->NegotiateFlags
&
2257 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN
))
2258 || (sign_CIFS_PDUs
> 1))
2259 ses
->server
->secMode
|=
2260 SECMODE_SIGN_REQUIRED
;
2261 if ((SecurityBlob2
->NegotiateFlags
&
2262 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN
)) && (sign_CIFS_PDUs
))
2263 ses
->server
->secMode
|=
2264 SECMODE_SIGN_ENABLED
;
2266 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2267 if ((long) (bcc_ptr
) % 2) {
2269 (BCC(smb_buffer_response
)
2271 bcc_ptr
++; /* Unicode strings must be word aligned */
2275 (smb_buffer_response
) / 2;
2278 UniStrnlen((wchar_t *) bcc_ptr
,
2279 remaining_words
- 1);
2280 /* We look for obvious messed up bcc or strings in response so we do not go off
2281 the end since (at least) WIN2K and Windows XP have a major bug in not null
2282 terminating last Unicode string in response */
2284 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
2285 cifs_strfromUCS_le(ses
->serverOS
,
2289 bcc_ptr
+= 2 * (len
+ 1);
2290 remaining_words
-= len
+ 1;
2291 ses
->serverOS
[2 * len
] = 0;
2292 ses
->serverOS
[1 + (2 * len
)] = 0;
2293 if (remaining_words
> 0) {
2294 len
= UniStrnlen((wchar_t *)
2299 cifs_kcalloc(2 * (len
+ 1),
2301 cifs_strfromUCS_le(ses
->
2307 bcc_ptr
+= 2 * (len
+ 1);
2308 ses
->serverNOS
[2 * len
] = 0;
2311 remaining_words
-= len
+ 1;
2312 if (remaining_words
> 0) {
2313 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
2314 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2339 } /* else no more room so create dummy domain string */
2344 } else { /* no room so create dummy domain and NOS string */
2346 cifs_kcalloc(2, GFP_KERNEL
);
2348 cifs_kcalloc(2, GFP_KERNEL
);
2350 } else { /* ASCII */
2351 len
= strnlen(bcc_ptr
, 1024);
2352 if (((long) bcc_ptr
+ len
) - (long)
2353 pByteArea(smb_buffer_response
)
2354 <= BCC(smb_buffer_response
)) {
2356 cifs_kcalloc(len
+ 1,
2358 strncpy(ses
->serverOS
,
2362 bcc_ptr
[0] = 0; /* null terminate string */
2365 len
= strnlen(bcc_ptr
, 1024);
2367 cifs_kcalloc(len
+ 1,
2369 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2374 len
= strnlen(bcc_ptr
, 1024);
2376 cifs_kcalloc(len
+ 1,
2378 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2384 ("Variable field of length %d extends beyond end of smb ",
2389 (" Security Blob Length extends beyond end of SMB"));
2392 cERROR(1, ("No session structure passed in."));
2396 (" Invalid Word count %d: ",
2397 smb_buffer_response
->WordCount
));
2402 cifs_buf_release(smb_buffer
);
2407 CIFSNTLMSSPAuthSessSetup(unsigned int xid
, struct cifsSesInfo
*ses
,
2408 char *ntlm_session_key
, int ntlmv2_flag
,
2409 const struct nls_table
*nls_codepage
)
2411 struct smb_hdr
*smb_buffer
;
2412 struct smb_hdr
*smb_buffer_response
;
2413 SESSION_SETUP_ANDX
*pSMB
;
2414 SESSION_SETUP_ANDX
*pSMBr
;
2419 int remaining_words
= 0;
2420 int bytes_returned
= 0;
2422 int SecurityBlobLength
= sizeof (AUTHENTICATE_MESSAGE
);
2423 PAUTHENTICATE_MESSAGE SecurityBlob
;
2424 __u32 negotiate_flags
, capabilities
;
2427 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2430 user
= ses
->userName
;
2431 domain
= ses
->domainName
;
2432 smb_buffer
= cifs_buf_get();
2433 if (smb_buffer
== NULL
) {
2436 smb_buffer_response
= smb_buffer
;
2437 pSMB
= (SESSION_SETUP_ANDX
*) smb_buffer
;
2438 pSMBr
= (SESSION_SETUP_ANDX
*) smb_buffer_response
;
2440 /* send SMBsessionSetup here */
2441 header_assemble(smb_buffer
, SMB_COM_SESSION_SETUP_ANDX
,
2442 NULL
/* no tCon exists yet */ , 12 /* wct */ );
2443 pSMB
->req
.hdr
.Flags
|= (SMBFLG_CASELESS
| SMBFLG_CANONICAL_PATH_FORMAT
);
2444 pSMB
->req
.hdr
.Flags2
|= SMBFLG2_EXT_SEC
;
2445 pSMB
->req
.AndXCommand
= 0xFF;
2446 pSMB
->req
.MaxBufferSize
= cpu_to_le16(ses
->server
->maxBuf
);
2447 pSMB
->req
.MaxMpxCount
= cpu_to_le16(ses
->server
->maxReq
);
2449 pSMB
->req
.hdr
.Uid
= ses
->Suid
;
2451 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2452 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2454 capabilities
= CAP_LARGE_FILES
| CAP_NT_SMBS
| CAP_LEVEL_II_OPLOCKS
|
2455 CAP_EXTENDED_SECURITY
;
2456 if (ses
->capabilities
& CAP_UNICODE
) {
2457 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2458 capabilities
|= CAP_UNICODE
;
2460 if (ses
->capabilities
& CAP_STATUS32
) {
2461 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2462 capabilities
|= CAP_STATUS32
;
2464 if (ses
->capabilities
& CAP_DFS
) {
2465 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2466 capabilities
|= CAP_DFS
;
2468 pSMB
->req
.Capabilities
= cpu_to_le32(capabilities
);
2470 bcc_ptr
= (char *) &pSMB
->req
.SecurityBlob
;
2471 SecurityBlob
= (PAUTHENTICATE_MESSAGE
) bcc_ptr
;
2472 strncpy(SecurityBlob
->Signature
, NTLMSSP_SIGNATURE
, 8);
2473 SecurityBlob
->MessageType
= NtLmAuthenticate
;
2474 bcc_ptr
+= SecurityBlobLength
;
2476 NTLMSSP_NEGOTIATE_UNICODE
| NTLMSSP_REQUEST_TARGET
|
2477 NTLMSSP_NEGOTIATE_NTLM
| NTLMSSP_NEGOTIATE_TARGET_INFO
|
2478 0x80000000 | NTLMSSP_NEGOTIATE_128
;
2480 negotiate_flags
|= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN
;
2482 negotiate_flags
|= NTLMSSP_NEGOTIATE_NTLMV2
;
2484 /* setup pointers to domain name and workstation name */
2486 SecurityBlob
->WorkstationName
.Buffer
= 0;
2487 SecurityBlob
->WorkstationName
.Length
= 0;
2488 SecurityBlob
->WorkstationName
.MaximumLength
= 0;
2489 SecurityBlob
->SessionKey
.Length
= 0;
2490 SecurityBlob
->SessionKey
.MaximumLength
= 0;
2491 SecurityBlob
->SessionKey
.Buffer
= 0;
2493 SecurityBlob
->LmChallengeResponse
.Length
= 0;
2494 SecurityBlob
->LmChallengeResponse
.MaximumLength
= 0;
2495 SecurityBlob
->LmChallengeResponse
.Buffer
= 0;
2497 SecurityBlob
->NtChallengeResponse
.Length
=
2498 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
2499 SecurityBlob
->NtChallengeResponse
.MaximumLength
=
2500 cpu_to_le16(CIFS_SESSION_KEY_SIZE
);
2501 memcpy(bcc_ptr
, ntlm_session_key
, CIFS_SESSION_KEY_SIZE
);
2502 SecurityBlob
->NtChallengeResponse
.Buffer
=
2503 cpu_to_le32(SecurityBlobLength
);
2504 SecurityBlobLength
+= CIFS_SESSION_KEY_SIZE
;
2505 bcc_ptr
+= CIFS_SESSION_KEY_SIZE
;
2507 if (ses
->capabilities
& CAP_UNICODE
) {
2508 if (domain
== NULL
) {
2509 SecurityBlob
->DomainName
.Buffer
= 0;
2510 SecurityBlob
->DomainName
.Length
= 0;
2511 SecurityBlob
->DomainName
.MaximumLength
= 0;
2514 cifs_strtoUCS((wchar_t *) bcc_ptr
, domain
, 64,
2517 SecurityBlob
->DomainName
.MaximumLength
=
2519 SecurityBlob
->DomainName
.Buffer
=
2520 cpu_to_le32(SecurityBlobLength
);
2522 SecurityBlobLength
+= len
;
2523 SecurityBlob
->DomainName
.Length
=
2527 SecurityBlob
->UserName
.Buffer
= 0;
2528 SecurityBlob
->UserName
.Length
= 0;
2529 SecurityBlob
->UserName
.MaximumLength
= 0;
2532 cifs_strtoUCS((wchar_t *) bcc_ptr
, user
, 64,
2535 SecurityBlob
->UserName
.MaximumLength
=
2537 SecurityBlob
->UserName
.Buffer
=
2538 cpu_to_le32(SecurityBlobLength
);
2540 SecurityBlobLength
+= len
;
2541 SecurityBlob
->UserName
.Length
=
2545 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2546 SecurityBlob->WorkstationName.Length *= 2;
2547 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2548 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2549 bcc_ptr += SecurityBlob->WorkstationName.Length;
2550 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2551 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2553 if ((long) bcc_ptr
% 2) {
2558 cifs_strtoUCS((wchar_t *) bcc_ptr
, "Linux version ",
2560 bcc_ptr
+= 2 * bytes_returned
;
2562 cifs_strtoUCS((wchar_t *) bcc_ptr
, system_utsname
.release
, 32,
2564 bcc_ptr
+= 2 * bytes_returned
;
2565 bcc_ptr
+= 2; /* null term version string */
2567 cifs_strtoUCS((wchar_t *) bcc_ptr
, CIFS_NETWORK_OPSYS
,
2569 bcc_ptr
+= 2 * bytes_returned
;
2572 bcc_ptr
+= 2; /* null terminate network opsys string */
2575 bcc_ptr
+= 2; /* null domain */
2576 } else { /* ASCII */
2577 if (domain
== NULL
) {
2578 SecurityBlob
->DomainName
.Buffer
= 0;
2579 SecurityBlob
->DomainName
.Length
= 0;
2580 SecurityBlob
->DomainName
.MaximumLength
= 0;
2583 negotiate_flags
|= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED
;
2584 strncpy(bcc_ptr
, domain
, 63);
2585 len
= strnlen(domain
, 64);
2586 SecurityBlob
->DomainName
.MaximumLength
=
2588 SecurityBlob
->DomainName
.Buffer
=
2589 cpu_to_le32(SecurityBlobLength
);
2591 SecurityBlobLength
+= len
;
2592 SecurityBlob
->DomainName
.Length
= cpu_to_le16(len
);
2595 SecurityBlob
->UserName
.Buffer
= 0;
2596 SecurityBlob
->UserName
.Length
= 0;
2597 SecurityBlob
->UserName
.MaximumLength
= 0;
2600 strncpy(bcc_ptr
, user
, 63);
2601 len
= strnlen(user
, 64);
2602 SecurityBlob
->UserName
.MaximumLength
=
2604 SecurityBlob
->UserName
.Buffer
=
2605 cpu_to_le32(SecurityBlobLength
);
2607 SecurityBlobLength
+= len
;
2608 SecurityBlob
->UserName
.Length
= cpu_to_le16(len
);
2610 /* BB fill in our workstation name if known BB */
2612 strcpy(bcc_ptr
, "Linux version ");
2613 bcc_ptr
+= strlen("Linux version ");
2614 strcpy(bcc_ptr
, system_utsname
.release
);
2615 bcc_ptr
+= strlen(system_utsname
.release
) + 1;
2616 strcpy(bcc_ptr
, CIFS_NETWORK_OPSYS
);
2617 bcc_ptr
+= strlen(CIFS_NETWORK_OPSYS
) + 1;
2618 bcc_ptr
++; /* null domain */
2621 SecurityBlob
->NegotiateFlags
= cpu_to_le32(negotiate_flags
);
2622 pSMB
->req
.SecurityBlobLength
= cpu_to_le16(SecurityBlobLength
);
2623 count
= (long) bcc_ptr
- (long) pByteArea(smb_buffer
);
2624 smb_buffer
->smb_buf_length
+= count
;
2625 pSMB
->req
.ByteCount
= cpu_to_le16(count
);
2627 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
,
2628 &bytes_returned
, 1);
2630 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2631 } else if ((smb_buffer_response
->WordCount
== 3)
2632 || (smb_buffer_response
->WordCount
== 4)) {
2633 __u16 action
= le16_to_cpu(pSMBr
->resp
.Action
);
2635 le16_to_cpu(pSMBr
->resp
.SecurityBlobLength
);
2636 if (action
& GUEST_LOGIN
)
2637 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2638 /* if(SecurityBlob2->MessageType != NtLm??){
2639 cFYI("Unexpected message type on auth response is %d "));
2643 ("Does UID on challenge %d match auth response UID %d ",
2644 ses
->Suid
, smb_buffer_response
->Uid
));
2645 ses
->Suid
= smb_buffer_response
->Uid
; /* UID left in wire format */
2646 bcc_ptr
= pByteArea(smb_buffer_response
);
2647 /* response can have either 3 or 4 word count - Samba sends 3 */
2648 if ((pSMBr
->resp
.hdr
.WordCount
== 3)
2649 || ((pSMBr
->resp
.hdr
.WordCount
== 4)
2651 pSMBr
->resp
.ByteCount
))) {
2652 if (pSMBr
->resp
.hdr
.WordCount
== 4) {
2656 ("Security Blob Length %d ",
2661 ("NTLMSSP response to Authenticate "));
2663 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2664 if ((long) (bcc_ptr
) % 2) {
2666 (BCC(smb_buffer_response
)
2668 bcc_ptr
++; /* Unicode strings must be word aligned */
2670 remaining_words
= BCC(smb_buffer_response
) / 2;
2673 UniStrnlen((wchar_t *) bcc_ptr
,remaining_words
- 1);
2674 /* We look for obvious messed up bcc or strings in response so we do not go off
2675 the end since (at least) WIN2K and Windows XP have a major bug in not null
2676 terminating last Unicode string in response */
2678 cifs_kcalloc(2 * (len
+ 1), GFP_KERNEL
);
2679 cifs_strfromUCS_le(ses
->serverOS
,
2683 bcc_ptr
+= 2 * (len
+ 1);
2684 remaining_words
-= len
+ 1;
2685 ses
->serverOS
[2 * len
] = 0;
2686 ses
->serverOS
[1 + (2 * len
)] = 0;
2687 if (remaining_words
> 0) {
2688 len
= UniStrnlen((wchar_t *)
2693 cifs_kcalloc(2 * (len
+ 1),
2695 cifs_strfromUCS_le(ses
->
2701 bcc_ptr
+= 2 * (len
+ 1);
2702 ses
->serverNOS
[2 * len
] = 0;
2703 ses
->serverNOS
[1+(2*len
)] = 0;
2704 remaining_words
-= len
+ 1;
2705 if (remaining_words
> 0) {
2706 len
= UniStrnlen((wchar_t *) bcc_ptr
, remaining_words
);
2707 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2732 } /* else no more room so create dummy domain string */
2734 ses
->serverDomain
= cifs_kcalloc(2,GFP_KERNEL
);
2735 } else { /* no room so create dummy domain and NOS string */
2736 ses
->serverDomain
= cifs_kcalloc(2, GFP_KERNEL
);
2737 ses
->serverNOS
= cifs_kcalloc(2, GFP_KERNEL
);
2739 } else { /* ASCII */
2740 len
= strnlen(bcc_ptr
, 1024);
2741 if (((long) bcc_ptr
+ len
) -
2742 (long) pByteArea(smb_buffer_response
)
2743 <= BCC(smb_buffer_response
)) {
2744 ses
->serverOS
= cifs_kcalloc(len
+ 1,GFP_KERNEL
);
2745 strncpy(ses
->serverOS
,bcc_ptr
, len
);
2748 bcc_ptr
[0] = 0; /* null terminate the string */
2751 len
= strnlen(bcc_ptr
, 1024);
2752 ses
->serverNOS
= cifs_kcalloc(len
+1,GFP_KERNEL
);
2753 strncpy(ses
->serverNOS
, bcc_ptr
, len
);
2758 len
= strnlen(bcc_ptr
, 1024);
2759 ses
->serverDomain
= cifs_kcalloc(len
+1,GFP_KERNEL
);
2760 strncpy(ses
->serverDomain
, bcc_ptr
, len
);
2766 ("Variable field of length %d extends beyond end of smb ",
2771 (" Security Blob Length extends beyond end of SMB"));
2774 cERROR(1, ("No session structure passed in."));
2778 (" Invalid Word count %d: ",
2779 smb_buffer_response
->WordCount
));
2784 cifs_buf_release(smb_buffer
);
2790 CIFSTCon(unsigned int xid
, struct cifsSesInfo
*ses
,
2791 const char *tree
, struct cifsTconInfo
*tcon
,
2792 const struct nls_table
*nls_codepage
)
2794 struct smb_hdr
*smb_buffer
;
2795 struct smb_hdr
*smb_buffer_response
;
2798 unsigned char *bcc_ptr
;
2806 smb_buffer
= cifs_buf_get();
2807 if (smb_buffer
== NULL
) {
2810 smb_buffer_response
= smb_buffer
;
2812 header_assemble(smb_buffer
, SMB_COM_TREE_CONNECT_ANDX
,
2813 NULL
/*no tid */ , 4 /*wct */ );
2814 smb_buffer
->Uid
= ses
->Suid
;
2815 pSMB
= (TCONX_REQ
*) smb_buffer
;
2816 pSMBr
= (TCONX_RSP
*) smb_buffer_response
;
2818 pSMB
->AndXCommand
= 0xFF;
2819 pSMB
->Flags
= cpu_to_le16(TCON_EXTENDED_SECINFO
);
2820 pSMB
->PasswordLength
= cpu_to_le16(1); /* minimum */
2821 bcc_ptr
= &pSMB
->Password
[0];
2822 bcc_ptr
++; /* skip password */
2824 if(ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
| SECMODE_SIGN_ENABLED
))
2825 smb_buffer
->Flags2
|= SMBFLG2_SECURITY_SIGNATURE
;
2827 if (ses
->capabilities
& CAP_STATUS32
) {
2828 smb_buffer
->Flags2
|= SMBFLG2_ERR_STATUS
;
2830 if (ses
->capabilities
& CAP_DFS
) {
2831 smb_buffer
->Flags2
|= SMBFLG2_DFS
;
2833 if (ses
->capabilities
& CAP_UNICODE
) {
2834 smb_buffer
->Flags2
|= SMBFLG2_UNICODE
;
2836 cifs_strtoUCS((wchar_t *) bcc_ptr
, tree
, 100, nls_codepage
);
2837 bcc_ptr
+= 2 * length
; /* convert num of 16 bit words to bytes */
2838 bcc_ptr
+= 2; /* skip trailing null */
2839 } else { /* ASCII */
2841 strcpy(bcc_ptr
, tree
);
2842 bcc_ptr
+= strlen(tree
) + 1;
2844 strcpy(bcc_ptr
, "?????");
2845 bcc_ptr
+= strlen("?????");
2847 count
= bcc_ptr
- &pSMB
->Password
[0];
2848 pSMB
->hdr
.smb_buf_length
+= count
;
2849 pSMB
->ByteCount
= cpu_to_le16(count
);
2851 rc
= SendReceive(xid
, ses
, smb_buffer
, smb_buffer_response
, &length
, 0);
2853 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2854 /* above now done in SendReceive */
2855 if ((rc
== 0) && (tcon
!= NULL
)) {
2856 tcon
->tidStatus
= CifsGood
;
2857 tcon
->tid
= smb_buffer_response
->Tid
;
2858 bcc_ptr
= pByteArea(smb_buffer_response
);
2859 length
= strnlen(bcc_ptr
, BCC(smb_buffer_response
) - 2);
2860 /* skip service field (NB: this field is always ASCII) */
2861 bcc_ptr
+= length
+ 1;
2862 strncpy(tcon
->treeName
, tree
, MAX_TREE_SIZE
);
2863 if (smb_buffer
->Flags2
& SMBFLG2_UNICODE
) {
2864 length
= UniStrnlen((wchar_t *) bcc_ptr
, 512);
2865 if ((bcc_ptr
+ (2 * length
)) -
2866 pByteArea(smb_buffer_response
) <=
2867 BCC(smb_buffer_response
)) {
2868 if(tcon
->nativeFileSystem
)
2869 kfree(tcon
->nativeFileSystem
);
2870 tcon
->nativeFileSystem
=
2871 cifs_kcalloc(length
+ 2, GFP_KERNEL
);
2872 cifs_strfromUCS_le(tcon
->nativeFileSystem
,
2873 (wchar_t *) bcc_ptr
,
2874 length
, nls_codepage
);
2875 bcc_ptr
+= 2 * length
;
2876 bcc_ptr
[0] = 0; /* null terminate the string */
2880 /* else do not bother copying these informational fields */
2882 length
= strnlen(bcc_ptr
, 1024);
2883 if ((bcc_ptr
+ length
) -
2884 pByteArea(smb_buffer_response
) <=
2885 BCC(smb_buffer_response
)) {
2886 if(tcon
->nativeFileSystem
)
2887 kfree(tcon
->nativeFileSystem
);
2888 tcon
->nativeFileSystem
=
2889 cifs_kcalloc(length
+ 1, GFP_KERNEL
);
2890 strncpy(tcon
->nativeFileSystem
, bcc_ptr
,
2893 /* else do not bother copying these informational fields */
2895 tcon
->Flags
= le16_to_cpu(pSMBr
->OptionalSupport
);
2896 cFYI(1, ("Tcon flags: 0x%x ", tcon
->Flags
));
2897 } else if ((rc
== 0) && tcon
== NULL
) {
2898 /* all we need to save for IPC$ connection */
2899 ses
->ipc_tid
= smb_buffer_response
->Tid
;
2903 cifs_buf_release(smb_buffer
);
2908 cifs_umount(struct super_block
*sb
, struct cifs_sb_info
*cifs_sb
)
2912 struct cifsSesInfo
*ses
= NULL
;
2913 struct task_struct
*cifsd_task
;
2917 if (cifs_sb
->tcon
) {
2918 ses
= cifs_sb
->tcon
->ses
; /* save ptr to ses before delete tcon!*/
2919 rc
= CIFSSMBTDis(xid
, cifs_sb
->tcon
);
2924 tconInfoFree(cifs_sb
->tcon
);
2925 if ((ses
) && (ses
->server
)) {
2926 /* save off task so we do not refer to ses later */
2927 cifsd_task
= ses
->server
->tsk
;
2928 cFYI(1, ("About to do SMBLogoff "));
2929 rc
= CIFSSMBLogoff(xid
, ses
);
2933 } else if (rc
== -ESHUTDOWN
) {
2934 cFYI(1,("Waking up socket by sending it signal"));
2936 send_sig(SIGKILL
,cifsd_task
,1);
2938 } /* else - we have an smb session
2939 left on this socket do not kill cifsd */
2941 cFYI(1, ("No session or bad tcon"));
2944 cifs_sb
->tcon
= NULL
;
2946 set_current_state(TASK_INTERRUPTIBLE
);
2947 schedule_timeout(HZ
/ 2);
2953 return rc
; /* BB check if we should always return zero here */
2956 int cifs_setup_session(unsigned int xid
, struct cifsSesInfo
*pSesInfo
,
2957 struct nls_table
* nls_info
)
2960 char ntlm_session_key
[CIFS_SESSION_KEY_SIZE
];
2961 int ntlmv2_flag
= FALSE
;
2963 /* what if server changes its buffer size after dropping the session? */
2964 if(pSesInfo
->server
->maxBuf
== 0) /* no need to send on reconnect */ {
2965 rc
= CIFSSMBNegotiate(xid
, pSesInfo
);
2966 if(rc
== -EAGAIN
) /* retry only once on 1st time connection */ {
2967 rc
= CIFSSMBNegotiate(xid
, pSesInfo
);
2972 spin_lock(&GlobalMid_Lock
);
2973 if(pSesInfo
->server
->tcpStatus
!= CifsExiting
)
2974 pSesInfo
->server
->tcpStatus
= CifsGood
;
2977 spin_unlock(&GlobalMid_Lock
);
2982 pSesInfo
->capabilities
= pSesInfo
->server
->capabilities
;
2983 if(linuxExtEnabled
== 0)
2984 pSesInfo
->capabilities
&= (~CAP_UNIX
);
2985 pSesInfo
->sequence_number
= 0;
2986 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2987 pSesInfo
->server
->secMode
,
2988 pSesInfo
->server
->capabilities
,
2989 pSesInfo
->server
->timeZone
));
2990 if (extended_security
2991 && (pSesInfo
->capabilities
& CAP_EXTENDED_SECURITY
)
2992 && (pSesInfo
->server
->secType
== NTLMSSP
)) {
2993 cFYI(1, ("New style sesssetup "));
2994 rc
= CIFSSpnegoSessSetup(xid
, pSesInfo
,
2995 NULL
/* security blob */,
2996 0 /* blob length */,
2998 } else if (extended_security
2999 && (pSesInfo
->capabilities
& CAP_EXTENDED_SECURITY
)
3000 && (pSesInfo
->server
->secType
== RawNTLMSSP
)) {
3001 cFYI(1, ("NTLMSSP sesssetup "));
3002 rc
= CIFSNTLMSSPNegotiateSessSetup(xid
,
3009 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3010 if(CalcNTLMv2_partial_mac_key(pSesInfo
,
3015 v2_response
= kmalloc(16 + 64 /* blob */, GFP_KERNEL
);
3017 CalcNTLMv2_response(pSesInfo
,v2_response
);
3018 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
3020 /* BB Put dummy sig in SessSetup PDU? */
3027 SMBNTencrypt(pSesInfo
->password
,
3028 pSesInfo
->server
->cryptKey
,
3031 cifs_calculate_mac_key(pSesInfo
->mac_signing_key
,
3033 pSesInfo
->password
);
3035 /* for better security the weaker lanman hash not sent
3036 in AuthSessSetup so we no longer calculate it */
3038 rc
= CIFSNTLMSSPAuthSessSetup(xid
,
3044 } else { /* old style NTLM 0.12 session setup */
3045 SMBNTencrypt(pSesInfo
->password
,
3046 pSesInfo
->server
->cryptKey
,
3049 cifs_calculate_mac_key(pSesInfo
->mac_signing_key
,
3050 ntlm_session_key
, pSesInfo
->password
);
3051 rc
= CIFSSessSetup(xid
, pSesInfo
,
3052 ntlm_session_key
, nls_info
);
3055 cERROR(1,("Send error in SessSetup = %d",rc
));
3057 cFYI(1,("CIFS Session Established successfully"));
3058 pSesInfo
->status
= CifsGood
;