aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c577
1 files changed, 182 insertions, 395 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479318d1..0e9ba0b9d71e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -49,8 +49,6 @@
49 49
50static DECLARE_COMPLETION(cifsd_complete); 50static DECLARE_COMPLETION(cifsd_complete);
51 51
52extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24); 53 unsigned char *p24);
56 54
@@ -70,6 +68,7 @@ struct smb_vol {
70 gid_t linux_gid; 68 gid_t linux_gid;
71 mode_t file_mode; 69 mode_t file_mode;
72 mode_t dir_mode; 70 mode_t dir_mode;
71 unsigned secFlg;
73 unsigned rw:1; 72 unsigned rw:1;
74 unsigned retry:1; 73 unsigned retry:1;
75 unsigned intr:1; 74 unsigned intr:1;
@@ -83,18 +82,14 @@ struct smb_vol {
83 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
84 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
85 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
86 unsigned krb5:1;
87 unsigned ntlm:1;
88 unsigned ntlmv2:1;
89 unsigned nullauth:1; /* attempt to authenticate with null user */ 85 unsigned nullauth:1; /* attempt to authenticate with null user */
90 unsigned sign:1;
91 unsigned seal:1; /* encrypt */
92 unsigned nocase; /* request case insensitive filenames */ 86 unsigned nocase; /* request case insensitive filenames */
93 unsigned nobrl; /* disable sending byte range locks to srv */ 87 unsigned nobrl; /* disable sending byte range locks to srv */
94 unsigned int rsize; 88 unsigned int rsize;
95 unsigned int wsize; 89 unsigned int wsize;
96 unsigned int sockopt; 90 unsigned int sockopt;
97 unsigned short int port; 91 unsigned short int port;
92 char * prepath;
98}; 93};
99 94
100static int ipv4_connect(struct sockaddr_in *psin_server, 95static int ipv4_connect(struct sockaddr_in *psin_server,
@@ -188,6 +183,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
188 183
189 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) 184 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
190 { 185 {
186 try_to_freeze();
191 if(server->protocolType == IPV6) { 187 if(server->protocolType == IPV6) {
192 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket); 188 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
193 } else { 189 } else {
@@ -369,21 +365,21 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
369 continue; 365 continue;
370 if (bigbuf == NULL) { 366 if (bigbuf == NULL) {
371 bigbuf = cifs_buf_get(); 367 bigbuf = cifs_buf_get();
372 if(bigbuf == NULL) { 368 if (!bigbuf) {
373 cERROR(1,("No memory for large SMB response")); 369 cERROR(1, ("No memory for large SMB response"));
374 msleep(3000); 370 msleep(3000);
375 /* retry will check if exiting */ 371 /* retry will check if exiting */
376 continue; 372 continue;
377 } 373 }
378 } else if(isLargeBuf) { 374 } else if (isLargeBuf) {
379 /* we are reusing a dirtry large buf, clear its start */ 375 /* we are reusing a dirty large buf, clear its start */
380 memset(bigbuf, 0, sizeof (struct smb_hdr)); 376 memset(bigbuf, 0, sizeof (struct smb_hdr));
381 } 377 }
382 378
383 if (smallbuf == NULL) { 379 if (smallbuf == NULL) {
384 smallbuf = cifs_small_buf_get(); 380 smallbuf = cifs_small_buf_get();
385 if(smallbuf == NULL) { 381 if (!smallbuf) {
386 cERROR(1,("No memory for SMB response")); 382 cERROR(1, ("No memory for SMB response"));
387 msleep(1000); 383 msleep(1000);
388 /* retry will check if exiting */ 384 /* retry will check if exiting */
389 continue; 385 continue;
@@ -403,12 +399,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
403 kernel_recvmsg(csocket, &smb_msg, 399 kernel_recvmsg(csocket, &smb_msg,
404 &iov, 1, 4, 0 /* BB see socket.h flags */); 400 &iov, 1, 4, 0 /* BB see socket.h flags */);
405 401
406 if(server->tcpStatus == CifsExiting) { 402 if (server->tcpStatus == CifsExiting) {
407 break; 403 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) { 404 } else if (server->tcpStatus == CifsNeedReconnect) {
409 cFYI(1,("Reconnect after server stopped responding")); 405 cFYI(1, ("Reconnect after server stopped responding"));
410 cifs_reconnect(server); 406 cifs_reconnect(server);
411 cFYI(1,("call to reconnect done")); 407 cFYI(1, ("call to reconnect done"));
412 csocket = server->ssocket; 408 csocket = server->ssocket;
413 continue; 409 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { 410 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
@@ -417,15 +413,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
417 tcpStatus CifsNeedReconnect if server hung */ 413 tcpStatus CifsNeedReconnect if server hung */
418 continue; 414 continue;
419 } else if (length <= 0) { 415 } else if (length <= 0) {
420 if(server->tcpStatus == CifsNew) { 416 if (server->tcpStatus == CifsNew) {
421 cFYI(1,("tcp session abend after SMBnegprot")); 417 cFYI(1, ("tcp session abend after SMBnegprot"));
422 /* some servers kill the TCP session rather than 418 /* some servers kill the TCP session rather than
423 returning an SMB negprot error, in which 419 returning an SMB negprot error, in which
424 case reconnecting here is not going to help, 420 case reconnecting here is not going to help,
425 and so simply return error to mount */ 421 and so simply return error to mount */
426 break; 422 break;
427 } 423 }
428 if(length == -EINTR) { 424 if (!try_to_freeze() && (length == -EINTR)) {
429 cFYI(1,("cifsd thread killed")); 425 cFYI(1,("cifsd thread killed"));
430 break; 426 break;
431 } 427 }
@@ -585,9 +581,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
585 /* merge response - fix up 1st*/ 581 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer, 582 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) { 583 mid_entry->resp_buf)) {
584 mid_entry->multiRsp = 1;
588 break; 585 break;
589 } else { 586 } else {
590 /* all parts received */ 587 /* all parts received */
588 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd; 589 goto multi_t2_fnd;
592 } 590 }
593 } else { 591 } else {
@@ -616,6 +614,10 @@ multi_t2_fnd:
616#ifdef CONFIG_CIFS_STATS2 614#ifdef CONFIG_CIFS_STATS2
617 mid_entry->when_received = jiffies; 615 mid_entry->when_received = jiffies;
618#endif 616#endif
617 /* so we do not time out requests to server
618 which is still responding (since server could
619 be busy but not dead) */
620 server->lstrp = jiffies;
619 break; 621 break;
620 } 622 }
621 } 623 }
@@ -632,9 +634,14 @@ multi_t2_fnd:
632 wake_up_process(task_to_wake); 634 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) 635 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) { 636 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd!")); 637 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer, 638 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr)); 639 sizeof(struct smb_hdr));
640#ifdef CONFIG_CIFS_DEBUG2
641 cifs_dump_detail(smb_buffer);
642 cifs_dump_mids(server);
643#endif /* CIFS_DEBUG2 */
644
638 } 645 }
639 } /* end while !EXITING */ 646 } /* end while !EXITING */
640 647
@@ -784,7 +791,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
784 791
785 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 792 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
786 vol->rw = TRUE; 793 vol->rw = TRUE;
787 vol->ntlm = TRUE;
788 /* default is always to request posix paths. */ 794 /* default is always to request posix paths. */
789 vol->posix_paths = 1; 795 vol->posix_paths = 1;
790 796
@@ -915,30 +921,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
915 cERROR(1,("no security value specified")); 921 cERROR(1,("no security value specified"));
916 continue; 922 continue;
917 } else if (strnicmp(value, "krb5i", 5) == 0) { 923 } else if (strnicmp(value, "krb5i", 5) == 0) {
918 vol->sign = 1; 924 vol->secFlg |= CIFSSEC_MAY_KRB5 |
919 vol->krb5 = 1; 925 CIFSSEC_MUST_SIGN;
920 } else if (strnicmp(value, "krb5p", 5) == 0) { 926 } else if (strnicmp(value, "krb5p", 5) == 0) {
921 /* vol->seal = 1; 927 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
922 vol->krb5 = 1; */ 928 CIFSSEC_MAY_KRB5; */
923 cERROR(1,("Krb5 cifs privacy not supported")); 929 cERROR(1,("Krb5 cifs privacy not supported"));
924 return 1; 930 return 1;
925 } else if (strnicmp(value, "krb5", 4) == 0) { 931 } else if (strnicmp(value, "krb5", 4) == 0) {
926 vol->krb5 = 1; 932 vol->secFlg |= CIFSSEC_MAY_KRB5;
927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 933 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
928 vol->ntlmv2 = 1; 934 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
929 vol->sign = 1; 935 CIFSSEC_MUST_SIGN;
930 } else if (strnicmp(value, "ntlmv2", 6) == 0) { 936 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
931 vol->ntlmv2 = 1; 937 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
932 } else if (strnicmp(value, "ntlmi", 5) == 0) { 938 } else if (strnicmp(value, "ntlmi", 5) == 0) {
933 vol->ntlm = 1; 939 vol->secFlg |= CIFSSEC_MAY_NTLM |
934 vol->sign = 1; 940 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlm", 4) == 0) { 941 } else if (strnicmp(value, "ntlm", 4) == 0) {
936 /* ntlm is default so can be turned off too */ 942 /* ntlm is default so can be turned off too */
937 vol->ntlm = 1; 943 vol->secFlg |= CIFSSEC_MAY_NTLM;
938 } else if (strnicmp(value, "nontlm", 6) == 0) { 944 } else if (strnicmp(value, "nontlm", 6) == 0) {
939 vol->ntlm = 0; 945 /* BB is there a better way to do this? */
946 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
947#ifdef CONFIG_CIFS_WEAK_PW_HASH
948 } else if (strnicmp(value, "lanman", 6) == 0) {
949 vol->secFlg |= CIFSSEC_MAY_LANMAN;
950#endif
940 } else if (strnicmp(value, "none", 4) == 0) { 951 } else if (strnicmp(value, "none", 4) == 0) {
941 vol->nullauth = 1; 952 vol->nullauth = 1;
942 } else { 953 } else {
943 cERROR(1,("bad security option: %s", value)); 954 cERROR(1,("bad security option: %s", value));
944 return 1; 955 return 1;
@@ -976,13 +987,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
976 } 987 }
977 /* BB are there cases in which a comma can be valid in 988 /* BB are there cases in which a comma can be valid in
978 a domain name and need special handling? */ 989 a domain name and need special handling? */
979 if (strnlen(value, 65) < 65) { 990 if (strnlen(value, 256) < 256) {
980 vol->domainname = value; 991 vol->domainname = value;
981 cFYI(1, ("Domain name set")); 992 cFYI(1, ("Domain name set"));
982 } else { 993 } else {
983 printk(KERN_WARNING "CIFS: domain name too long\n"); 994 printk(KERN_WARNING "CIFS: domain name too long\n");
984 return 1; 995 return 1;
985 } 996 }
997 } else if (strnicmp(data, "prefixpath", 10) == 0) {
998 if (!value || !*value) {
999 printk(KERN_WARNING
1000 "CIFS: invalid path prefix\n");
1001 return 1; /* needs_arg; */
1002 }
1003 if ((temp_len = strnlen(value, 1024)) < 1024) {
1004 if(value[0] != '/')
1005 temp_len++; /* missing leading slash */
1006 vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
1007 if(vol->prepath == NULL)
1008 return 1;
1009 if(value[0] != '/') {
1010 vol->prepath[0] = '/';
1011 strcpy(vol->prepath+1,value);
1012 } else
1013 strcpy(vol->prepath,value);
1014 cFYI(1,("prefix path %s",vol->prepath));
1015 } else {
1016 printk(KERN_WARNING "CIFS: prefix too long\n");
1017 return 1;
1018 }
986 } else if (strnicmp(data, "iocharset", 9) == 0) { 1019 } else if (strnicmp(data, "iocharset", 9) == 0) {
987 if (!value || !*value) { 1020 if (!value || !*value) {
988 printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); 1021 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
@@ -1168,6 +1201,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1168 vol->no_psx_acl = 0; 1201 vol->no_psx_acl = 0;
1169 } else if (strnicmp(data, "noacl",5) == 0) { 1202 } else if (strnicmp(data, "noacl",5) == 0) {
1170 vol->no_psx_acl = 1; 1203 vol->no_psx_acl = 1;
1204 } else if (strnicmp(data, "sign",4) == 0) {
1205 vol->secFlg |= CIFSSEC_MUST_SIGN;
1206/* } else if (strnicmp(data, "seal",4) == 0) {
1207 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1171 } else if (strnicmp(data, "direct",6) == 0) { 1208 } else if (strnicmp(data, "direct",6) == 0) {
1172 vol->direct_io = 1; 1209 vol->direct_io = 1;
1173 } else if (strnicmp(data, "forcedirectio",13) == 0) { 1210 } else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1257,33 +1294,35 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1257 1294
1258 read_lock(&GlobalSMBSeslock); 1295 read_lock(&GlobalSMBSeslock);
1259 list_for_each(tmp, &GlobalTreeConnectionList) { 1296 list_for_each(tmp, &GlobalTreeConnectionList) {
1260 cFYI(1, ("Next tcon - ")); 1297 cFYI(1, ("Next tcon"));
1261 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 1298 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1262 if (tcon->ses) { 1299 if (tcon->ses) {
1263 if (tcon->ses->server) { 1300 if (tcon->ses->server) {
1264 cFYI(1, 1301 cFYI(1,
1265 (" old ip addr: %x == new ip %x ?", 1302 ("old ip addr: %x == new ip %x ?",
1266 tcon->ses->server->addr.sockAddr.sin_addr. 1303 tcon->ses->server->addr.sockAddr.sin_addr.
1267 s_addr, new_target_ip_addr)); 1304 s_addr, new_target_ip_addr));
1268 if (tcon->ses->server->addr.sockAddr.sin_addr. 1305 if (tcon->ses->server->addr.sockAddr.sin_addr.
1269 s_addr == new_target_ip_addr) { 1306 s_addr == new_target_ip_addr) {
1270 /* BB lock tcon and server and tcp session and increment use count here? */ 1307 /* BB lock tcon, server and tcp session and increment use count here? */
1271 /* found a match on the TCP session */ 1308 /* found a match on the TCP session */
1272 /* BB check if reconnection needed */ 1309 /* BB check if reconnection needed */
1273 cFYI(1,("Matched ip, old UNC: %s == new: %s ?", 1310 cFYI(1,("IP match, old UNC: %s new: %s",
1274 tcon->treeName, uncName)); 1311 tcon->treeName, uncName));
1275 if (strncmp 1312 if (strncmp
1276 (tcon->treeName, uncName, 1313 (tcon->treeName, uncName,
1277 MAX_TREE_SIZE) == 0) { 1314 MAX_TREE_SIZE) == 0) {
1278 cFYI(1, 1315 cFYI(1,
1279 ("Matched UNC, old user: %s == new: %s ?", 1316 ("and old usr: %s new: %s",
1280 tcon->treeName, uncName)); 1317 tcon->treeName, uncName));
1281 if (strncmp 1318 if (strncmp
1282 (tcon->ses->userName, 1319 (tcon->ses->userName,
1283 userName, 1320 userName,
1284 MAX_USERNAME_SIZE) == 0) { 1321 MAX_USERNAME_SIZE) == 0) {
1285 read_unlock(&GlobalSMBSeslock); 1322 read_unlock(&GlobalSMBSeslock);
1286 return tcon;/* also matched user (smb session)*/ 1323 /* matched smb session
1324 (user name */
1325 return tcon;
1287 } 1326 }
1288 } 1327 }
1289 } 1328 }
@@ -1589,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1589 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { 1628 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1590 kfree(volume_info.UNC); 1629 kfree(volume_info.UNC);
1591 kfree(volume_info.password); 1630 kfree(volume_info.password);
1631 kfree(volume_info.prepath);
1592 FreeXid(xid); 1632 FreeXid(xid);
1593 return -EINVAL; 1633 return -EINVAL;
1594 } 1634 }
@@ -1603,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1603 locations such as env variables and files on disk */ 1643 locations such as env variables and files on disk */
1604 kfree(volume_info.UNC); 1644 kfree(volume_info.UNC);
1605 kfree(volume_info.password); 1645 kfree(volume_info.password);
1646 kfree(volume_info.prepath);
1606 FreeXid(xid); 1647 FreeXid(xid);
1607 return -EINVAL; 1648 return -EINVAL;
1608 } 1649 }
@@ -1623,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1623 /* we failed translating address */ 1664 /* we failed translating address */
1624 kfree(volume_info.UNC); 1665 kfree(volume_info.UNC);
1625 kfree(volume_info.password); 1666 kfree(volume_info.password);
1667 kfree(volume_info.prepath);
1626 FreeXid(xid); 1668 FreeXid(xid);
1627 return -EINVAL; 1669 return -EINVAL;
1628 } 1670 }
@@ -1635,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1635 cERROR(1,("Connecting to DFS root not implemented yet")); 1677 cERROR(1,("Connecting to DFS root not implemented yet"));
1636 kfree(volume_info.UNC); 1678 kfree(volume_info.UNC);
1637 kfree(volume_info.password); 1679 kfree(volume_info.password);
1680 kfree(volume_info.prepath);
1638 FreeXid(xid); 1681 FreeXid(xid);
1639 return -EINVAL; 1682 return -EINVAL;
1640 } else /* which servers DFS root would we conect to */ { 1683 } else /* which servers DFS root would we conect to */ {
@@ -1642,6 +1685,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1642 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); 1685 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1643 kfree(volume_info.UNC); 1686 kfree(volume_info.UNC);
1644 kfree(volume_info.password); 1687 kfree(volume_info.password);
1688 kfree(volume_info.prepath);
1645 FreeXid(xid); 1689 FreeXid(xid);
1646 return -EINVAL; 1690 return -EINVAL;
1647 } 1691 }
@@ -1656,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1656 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); 1700 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1657 kfree(volume_info.UNC); 1701 kfree(volume_info.UNC);
1658 kfree(volume_info.password); 1702 kfree(volume_info.password);
1703 kfree(volume_info.prepath);
1659 FreeXid(xid); 1704 FreeXid(xid);
1660 return -ELIBACC; 1705 return -ELIBACC;
1661 } 1706 }
@@ -1672,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1672 else { 1717 else {
1673 kfree(volume_info.UNC); 1718 kfree(volume_info.UNC);
1674 kfree(volume_info.password); 1719 kfree(volume_info.password);
1720 kfree(volume_info.prepath);
1675 FreeXid(xid); 1721 FreeXid(xid);
1676 return -EINVAL; 1722 return -EINVAL;
1677 } 1723 }
@@ -1694,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1694 sock_release(csocket); 1740 sock_release(csocket);
1695 kfree(volume_info.UNC); 1741 kfree(volume_info.UNC);
1696 kfree(volume_info.password); 1742 kfree(volume_info.password);
1743 kfree(volume_info.prepath);
1697 FreeXid(xid); 1744 FreeXid(xid);
1698 return rc; 1745 return rc;
1699 } 1746 }
@@ -1704,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1704 sock_release(csocket); 1751 sock_release(csocket);
1705 kfree(volume_info.UNC); 1752 kfree(volume_info.UNC);
1706 kfree(volume_info.password); 1753 kfree(volume_info.password);
1754 kfree(volume_info.prepath);
1707 FreeXid(xid); 1755 FreeXid(xid);
1708 return rc; 1756 return rc;
1709 } else { 1757 } else {
@@ -1728,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1728 sock_release(csocket); 1776 sock_release(csocket);
1729 kfree(volume_info.UNC); 1777 kfree(volume_info.UNC);
1730 kfree(volume_info.password); 1778 kfree(volume_info.password);
1779 kfree(volume_info.prepath);
1731 FreeXid(xid); 1780 FreeXid(xid);
1732 return rc; 1781 return rc;
1733 } 1782 }
@@ -1762,11 +1811,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1762 if (volume_info.username) 1811 if (volume_info.username)
1763 strncpy(pSesInfo->userName, 1812 strncpy(pSesInfo->userName,
1764 volume_info.username,MAX_USERNAME_SIZE); 1813 volume_info.username,MAX_USERNAME_SIZE);
1765 if (volume_info.domainname) 1814 if (volume_info.domainname) {
1766 strncpy(pSesInfo->domainName, 1815 int len = strlen(volume_info.domainname);
1767 volume_info.domainname,MAX_USERNAME_SIZE); 1816 pSesInfo->domainName =
1817 kmalloc(len + 1, GFP_KERNEL);
1818 if(pSesInfo->domainName)
1819 strcpy(pSesInfo->domainName,
1820 volume_info.domainname);
1821 }
1768 pSesInfo->linux_uid = volume_info.linux_uid; 1822 pSesInfo->linux_uid = volume_info.linux_uid;
1823 pSesInfo->overrideSecFlg = volume_info.secFlg;
1769 down(&pSesInfo->sesSem); 1824 down(&pSesInfo->sesSem);
1825 /* BB FIXME need to pass vol->secFlgs BB */
1770 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1826 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1771 up(&pSesInfo->sesSem); 1827 up(&pSesInfo->sesSem);
1772 if(!rc) 1828 if(!rc)
@@ -1808,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1808 /* Windows ME may prefer this */ 1864 /* Windows ME may prefer this */
1809 cFYI(1,("readsize set to minimum 2048")); 1865 cFYI(1,("readsize set to minimum 2048"));
1810 } 1866 }
1867 /* calculate prepath */
1868 cifs_sb->prepath = volume_info.prepath;
1869 if(cifs_sb->prepath) {
1870 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1871 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
1872 volume_info.prepath = NULL;
1873 } else
1874 cifs_sb->prepathlen = 0;
1811 cifs_sb->mnt_uid = volume_info.linux_uid; 1875 cifs_sb->mnt_uid = volume_info.linux_uid;
1812 cifs_sb->mnt_gid = volume_info.linux_gid; 1876 cifs_sb->mnt_gid = volume_info.linux_gid;
1813 cifs_sb->mnt_file_mode = volume_info.file_mode; 1877 cifs_sb->mnt_file_mode = volume_info.file_mode;
@@ -1953,7 +2017,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1953 } 2017 }
1954 2018
1955 cFYI(1,("Negotiate caps 0x%x",(int)cap)); 2019 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1956 2020#ifdef CONFIG_CIFS_DEBUG2
2021 if(cap & CIFS_UNIX_FCNTL_CAP)
2022 cFYI(1,("FCNTL cap"));
2023 if(cap & CIFS_UNIX_EXTATTR_CAP)
2024 cFYI(1,("EXTATTR cap"));
2025 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2026 cFYI(1,("POSIX path cap"));
2027 if(cap & CIFS_UNIX_XATTR_CAP)
2028 cFYI(1,("XATTR cap"));
2029 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
2030 cFYI(1,("POSIX ACL cap"));
2031#endif /* CIFS_DEBUG2 */
1957 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { 2032 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1958 cFYI(1,("setting capabilities failed")); 2033 cFYI(1,("setting capabilities failed"));
1959 } 2034 }
@@ -1974,13 +2049,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1974 the password ptr is put in the new session structure (in which case the 2049 the password ptr is put in the new session structure (in which case the
1975 password will be freed at unmount time) */ 2050 password will be freed at unmount time) */
1976 kfree(volume_info.UNC); 2051 kfree(volume_info.UNC);
2052 kfree(volume_info.prepath);
1977 FreeXid(xid); 2053 FreeXid(xid);
1978 return rc; 2054 return rc;
1979} 2055}
1980 2056
1981static int 2057static int
1982CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, 2058CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1983 char session_key[CIFS_SESSION_KEY_SIZE], 2059 char session_key[CIFS_SESS_KEY_SIZE],
1984 const struct nls_table *nls_codepage) 2060 const struct nls_table *nls_codepage)
1985{ 2061{
1986 struct smb_hdr *smb_buffer; 2062 struct smb_hdr *smb_buffer;
@@ -2038,15 +2114,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2038 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); 2114 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2039 2115
2040 pSMB->req_no_secext.CaseInsensitivePasswordLength = 2116 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2041 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2117 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2042 2118
2043 pSMB->req_no_secext.CaseSensitivePasswordLength = 2119 pSMB->req_no_secext.CaseSensitivePasswordLength =
2044 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2120 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2045 bcc_ptr = pByteArea(smb_buffer); 2121 bcc_ptr = pByteArea(smb_buffer);
2046 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2122 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2047 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2123 bcc_ptr += CIFS_SESS_KEY_SIZE;
2048 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); 2124 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2049 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2125 bcc_ptr += CIFS_SESS_KEY_SIZE;
2050 2126
2051 if (ses->capabilities & CAP_UNICODE) { 2127 if (ses->capabilities & CAP_UNICODE) {
2052 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ 2128 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -2054,7 +2130,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2054 bcc_ptr++; 2130 bcc_ptr++;
2055 } 2131 }
2056 if(user == NULL) 2132 if(user == NULL)
2057 bytes_returned = 0; /* skill null user */ 2133 bytes_returned = 0; /* skip null user */
2058 else 2134 else
2059 bytes_returned = 2135 bytes_returned =
2060 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, 2136 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2162,8 +2238,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2162 if (remaining_words > 0) { 2238 if (remaining_words > 0) {
2163 len = UniStrnlen((wchar_t *)bcc_ptr, 2239 len = UniStrnlen((wchar_t *)bcc_ptr,
2164 remaining_words-1); 2240 remaining_words-1);
2165 if(ses->serverNOS) 2241 kfree(ses->serverNOS);
2166 kfree(ses->serverNOS);
2167 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); 2242 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2168 if(ses->serverNOS == NULL) 2243 if(ses->serverNOS == NULL)
2169 goto sesssetup_nomem; 2244 goto sesssetup_nomem;
@@ -2203,12 +2278,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2203 /* if these kcallocs fail not much we 2278 /* if these kcallocs fail not much we
2204 can do, but better to not fail the 2279 can do, but better to not fail the
2205 sesssetup itself */ 2280 sesssetup itself */
2206 if(ses->serverDomain) 2281 kfree(ses->serverDomain);
2207 kfree(ses->serverDomain);
2208 ses->serverDomain = 2282 ses->serverDomain =
2209 kzalloc(2, GFP_KERNEL); 2283 kzalloc(2, GFP_KERNEL);
2210 if(ses->serverNOS) 2284 kfree(ses->serverNOS);
2211 kfree(ses->serverNOS);
2212 ses->serverNOS = 2285 ses->serverNOS =
2213 kzalloc(2, GFP_KERNEL); 2286 kzalloc(2, GFP_KERNEL);
2214 } 2287 }
@@ -2217,8 +2290,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2217 if (((long) bcc_ptr + len) - (long) 2290 if (((long) bcc_ptr + len) - (long)
2218 pByteArea(smb_buffer_response) 2291 pByteArea(smb_buffer_response)
2219 <= BCC(smb_buffer_response)) { 2292 <= BCC(smb_buffer_response)) {
2220 if(ses->serverOS) 2293 kfree(ses->serverOS);
2221 kfree(ses->serverOS);
2222 ses->serverOS = kzalloc(len + 1,GFP_KERNEL); 2294 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2223 if(ses->serverOS == NULL) 2295 if(ses->serverOS == NULL)
2224 goto sesssetup_nomem; 2296 goto sesssetup_nomem;
@@ -2229,8 +2301,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2229 bcc_ptr++; 2301 bcc_ptr++;
2230 2302
2231 len = strnlen(bcc_ptr, 1024); 2303 len = strnlen(bcc_ptr, 1024);
2232 if(ses->serverNOS) 2304 kfree(ses->serverNOS);
2233 kfree(ses->serverNOS);
2234 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); 2305 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2235 if(ses->serverNOS == NULL) 2306 if(ses->serverNOS == NULL)
2236 goto sesssetup_nomem; 2307 goto sesssetup_nomem;
@@ -2274,292 +2345,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings,
2274} 2345}
2275 2346
2276static int 2347static int
2277CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2278 char *SecurityBlob,int SecurityBlobLength,
2279 const struct nls_table *nls_codepage)
2280{
2281 struct smb_hdr *smb_buffer;
2282 struct smb_hdr *smb_buffer_response;
2283 SESSION_SETUP_ANDX *pSMB;
2284 SESSION_SETUP_ANDX *pSMBr;
2285 char *bcc_ptr;
2286 char *user;
2287 char *domain;
2288 int rc = 0;
2289 int remaining_words = 0;
2290 int bytes_returned = 0;
2291 int len;
2292 __u32 capabilities;
2293 __u16 count;
2294
2295 cFYI(1, ("In spnego sesssetup "));
2296 if(ses == NULL)
2297 return -EINVAL;
2298 user = ses->userName;
2299 domain = ses->domainName;
2300
2301 smb_buffer = cifs_buf_get();
2302 if (smb_buffer == NULL) {
2303 return -ENOMEM;
2304 }
2305 smb_buffer_response = smb_buffer;
2306 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2307
2308 /* send SMBsessionSetup here */
2309 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2310 NULL /* no tCon exists yet */ , 12 /* wct */ );
2311
2312 smb_buffer->Mid = GetNextMid(ses->server);
2313 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2314 pSMB->req.AndXCommand = 0xFF;
2315 if(ses->server->maxBuf > 64*1024)
2316 ses->server->maxBuf = (64*1023);
2317 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2318 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2319
2320 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2321 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2322
2323 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2324 CAP_EXTENDED_SECURITY;
2325 if (ses->capabilities & CAP_UNICODE) {
2326 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2327 capabilities |= CAP_UNICODE;
2328 }
2329 if (ses->capabilities & CAP_STATUS32) {
2330 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2331 capabilities |= CAP_STATUS32;
2332 }
2333 if (ses->capabilities & CAP_DFS) {
2334 smb_buffer->Flags2 |= SMBFLG2_DFS;
2335 capabilities |= CAP_DFS;
2336 }
2337 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2338
2339 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2340 bcc_ptr = pByteArea(smb_buffer);
2341 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2342 bcc_ptr += SecurityBlobLength;
2343
2344 if (ses->capabilities & CAP_UNICODE) {
2345 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2346 *bcc_ptr = 0;
2347 bcc_ptr++;
2348 }
2349 bytes_returned =
2350 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2351 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2352 bcc_ptr += 2; /* trailing null */
2353 if (domain == NULL)
2354 bytes_returned =
2355 cifs_strtoUCS((__le16 *) bcc_ptr,
2356 "CIFS_LINUX_DOM", 32, nls_codepage);
2357 else
2358 bytes_returned =
2359 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2360 nls_codepage);
2361 bcc_ptr += 2 * bytes_returned;
2362 bcc_ptr += 2;
2363 bytes_returned =
2364 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2365 32, nls_codepage);
2366 bcc_ptr += 2 * bytes_returned;
2367 bytes_returned =
2368 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2369 nls_codepage);
2370 bcc_ptr += 2 * bytes_returned;
2371 bcc_ptr += 2;
2372 bytes_returned =
2373 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2374 64, nls_codepage);
2375 bcc_ptr += 2 * bytes_returned;
2376 bcc_ptr += 2;
2377 } else {
2378 strncpy(bcc_ptr, user, 200);
2379 bcc_ptr += strnlen(user, 200);
2380 *bcc_ptr = 0;
2381 bcc_ptr++;
2382 if (domain == NULL) {
2383 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2384 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2385 } else {
2386 strncpy(bcc_ptr, domain, 64);
2387 bcc_ptr += strnlen(domain, 64);
2388 *bcc_ptr = 0;
2389 bcc_ptr++;
2390 }
2391 strcpy(bcc_ptr, "Linux version ");
2392 bcc_ptr += strlen("Linux version ");
2393 strcpy(bcc_ptr, system_utsname.release);
2394 bcc_ptr += strlen(system_utsname.release) + 1;
2395 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2396 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2397 }
2398 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2399 smb_buffer->smb_buf_length += count;
2400 pSMB->req.ByteCount = cpu_to_le16(count);
2401
2402 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2403 &bytes_returned, 1);
2404 if (rc) {
2405/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2406 } else if ((smb_buffer_response->WordCount == 3)
2407 || (smb_buffer_response->WordCount == 4)) {
2408 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2409 __u16 blob_len =
2410 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2411 if (action & GUEST_LOGIN)
2412 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2413 if (ses) {
2414 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2415 cFYI(1, ("UID = %d ", ses->Suid));
2416 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2417
2418 /* BB Fix below to make endian neutral !! */
2419
2420 if ((pSMBr->resp.hdr.WordCount == 3)
2421 || ((pSMBr->resp.hdr.WordCount == 4)
2422 && (blob_len <
2423 pSMBr->resp.ByteCount))) {
2424 if (pSMBr->resp.hdr.WordCount == 4) {
2425 bcc_ptr +=
2426 blob_len;
2427 cFYI(1,
2428 ("Security Blob Length %d ",
2429 blob_len));
2430 }
2431
2432 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2433 if ((long) (bcc_ptr) % 2) {
2434 remaining_words =
2435 (BCC(smb_buffer_response)
2436 - 1) / 2;
2437 bcc_ptr++; /* Unicode strings must be word aligned */
2438 } else {
2439 remaining_words =
2440 BCC
2441 (smb_buffer_response) / 2;
2442 }
2443 len =
2444 UniStrnlen((wchar_t *) bcc_ptr,
2445 remaining_words - 1);
2446/* We look for obvious messed up bcc or strings in response so we do not go off
2447 the end since (at least) WIN2K and Windows XP have a major bug in not null
2448 terminating last Unicode string in response */
2449 if(ses->serverOS)
2450 kfree(ses->serverOS);
2451 ses->serverOS =
2452 kzalloc(2 * (len + 1), GFP_KERNEL);
2453 cifs_strfromUCS_le(ses->serverOS,
2454 (__le16 *)
2455 bcc_ptr, len,
2456 nls_codepage);
2457 bcc_ptr += 2 * (len + 1);
2458 remaining_words -= len + 1;
2459 ses->serverOS[2 * len] = 0;
2460 ses->serverOS[1 + (2 * len)] = 0;
2461 if (remaining_words > 0) {
2462 len = UniStrnlen((wchar_t *)bcc_ptr,
2463 remaining_words
2464 - 1);
2465 if(ses->serverNOS)
2466 kfree(ses->serverNOS);
2467 ses->serverNOS =
2468 kzalloc(2 * (len + 1),
2469 GFP_KERNEL);
2470 cifs_strfromUCS_le(ses->serverNOS,
2471 (__le16 *)bcc_ptr,
2472 len,
2473 nls_codepage);
2474 bcc_ptr += 2 * (len + 1);
2475 ses->serverNOS[2 * len] = 0;
2476 ses->serverNOS[1 + (2 * len)] = 0;
2477 remaining_words -= len + 1;
2478 if (remaining_words > 0) {
2479 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2480 /* last string not null terminated (e.g.Windows XP/2000) */
2481 if(ses->serverDomain)
2482 kfree(ses->serverDomain);
2483 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2484 cifs_strfromUCS_le(ses->serverDomain,
2485 (__le16 *)bcc_ptr,
2486 len, nls_codepage);
2487 bcc_ptr += 2*(len+1);
2488 ses->serverDomain[2*len] = 0;
2489 ses->serverDomain[1+(2*len)] = 0;
2490 } /* else no more room so create dummy domain string */
2491 else {
2492 if(ses->serverDomain)
2493 kfree(ses->serverDomain);
2494 ses->serverDomain =
2495 kzalloc(2,GFP_KERNEL);
2496 }
2497 } else {/* no room use dummy domain&NOS */
2498 if(ses->serverDomain)
2499 kfree(ses->serverDomain);
2500 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2501 if(ses->serverNOS)
2502 kfree(ses->serverNOS);
2503 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2504 }
2505 } else { /* ASCII */
2506
2507 len = strnlen(bcc_ptr, 1024);
2508 if (((long) bcc_ptr + len) - (long)
2509 pByteArea(smb_buffer_response)
2510 <= BCC(smb_buffer_response)) {
2511 if(ses->serverOS)
2512 kfree(ses->serverOS);
2513 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2514 strncpy(ses->serverOS, bcc_ptr, len);
2515
2516 bcc_ptr += len;
2517 bcc_ptr[0] = 0; /* null terminate the string */
2518 bcc_ptr++;
2519
2520 len = strnlen(bcc_ptr, 1024);
2521 if(ses->serverNOS)
2522 kfree(ses->serverNOS);
2523 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2524 strncpy(ses->serverNOS, bcc_ptr, len);
2525 bcc_ptr += len;
2526 bcc_ptr[0] = 0;
2527 bcc_ptr++;
2528
2529 len = strnlen(bcc_ptr, 1024);
2530 if(ses->serverDomain)
2531 kfree(ses->serverDomain);
2532 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2533 strncpy(ses->serverDomain, bcc_ptr, len);
2534 bcc_ptr += len;
2535 bcc_ptr[0] = 0;
2536 bcc_ptr++;
2537 } else
2538 cFYI(1,
2539 ("Variable field of length %d extends beyond end of smb ",
2540 len));
2541 }
2542 } else {
2543 cERROR(1,
2544 (" Security Blob Length extends beyond end of SMB"));
2545 }
2546 } else {
2547 cERROR(1, ("No session structure passed in."));
2548 }
2549 } else {
2550 cERROR(1,
2551 (" Invalid Word count %d: ",
2552 smb_buffer_response->WordCount));
2553 rc = -EIO;
2554 }
2555
2556 if (smb_buffer)
2557 cifs_buf_release(smb_buffer);
2558
2559 return rc;
2560}
2561
2562static int
2563CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 2348CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2564 struct cifsSesInfo *ses, int * pNTLMv2_flag, 2349 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2565 const struct nls_table *nls_codepage) 2350 const struct nls_table *nls_codepage)
@@ -2635,8 +2420,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2635 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; 2420 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2636 if(sign_CIFS_PDUs) 2421 if(sign_CIFS_PDUs)
2637 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; 2422 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2638 if(ntlmv2_support) 2423/* if(ntlmv2_support)
2639 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; 2424 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2640 /* setup pointers to domain name and workstation name */ 2425 /* setup pointers to domain name and workstation name */
2641 bcc_ptr += SecurityBlobLength; 2426 bcc_ptr += SecurityBlobLength;
2642 2427
@@ -2783,8 +2568,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2783 bcc_ptr, 2568 bcc_ptr,
2784 remaining_words 2569 remaining_words
2785 - 1); 2570 - 1);
2786 if(ses->serverNOS) 2571 kfree(ses->serverNOS);
2787 kfree(ses->serverNOS);
2788 ses->serverNOS = 2572 ses->serverNOS =
2789 kzalloc(2 * (len + 1), 2573 kzalloc(2 * (len + 1),
2790 GFP_KERNEL); 2574 GFP_KERNEL);
@@ -2802,8 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2802 if (remaining_words > 0) { 2586 if (remaining_words > 0) {
2803 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2587 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2804 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2588 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2805 if(ses->serverDomain) 2589 kfree(ses->serverDomain);
2806 kfree(ses->serverDomain);
2807 ses->serverDomain = 2590 ses->serverDomain =
2808 kzalloc(2 * 2591 kzalloc(2 *
2809 (len + 2592 (len +
@@ -2822,19 +2605,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2822 = 0; 2605 = 0;
2823 } /* else no more room so create dummy domain string */ 2606 } /* else no more room so create dummy domain string */
2824 else { 2607 else {
2825 if(ses->serverDomain) 2608 kfree(ses->serverDomain);
2826 kfree(ses->serverDomain);
2827 ses->serverDomain = 2609 ses->serverDomain =
2828 kzalloc(2, 2610 kzalloc(2,
2829 GFP_KERNEL); 2611 GFP_KERNEL);
2830 } 2612 }
2831 } else { /* no room so create dummy domain and NOS string */ 2613 } else { /* no room so create dummy domain and NOS string */
2832 if(ses->serverDomain); 2614 kfree(ses->serverDomain);
2833 kfree(ses->serverDomain);
2834 ses->serverDomain = 2615 ses->serverDomain =
2835 kzalloc(2, GFP_KERNEL); 2616 kzalloc(2, GFP_KERNEL);
2836 if(ses->serverNOS) 2617 kfree(ses->serverNOS);
2837 kfree(ses->serverNOS);
2838 ses->serverNOS = 2618 ses->serverNOS =
2839 kzalloc(2, GFP_KERNEL); 2619 kzalloc(2, GFP_KERNEL);
2840 } 2620 }
@@ -2856,8 +2636,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2856 bcc_ptr++; 2636 bcc_ptr++;
2857 2637
2858 len = strnlen(bcc_ptr, 1024); 2638 len = strnlen(bcc_ptr, 1024);
2859 if(ses->serverNOS) 2639 kfree(ses->serverNOS);
2860 kfree(ses->serverNOS);
2861 ses->serverNOS = 2640 ses->serverNOS =
2862 kzalloc(len + 1, 2641 kzalloc(len + 1,
2863 GFP_KERNEL); 2642 GFP_KERNEL);
@@ -2867,8 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2867 bcc_ptr++; 2646 bcc_ptr++;
2868 2647
2869 len = strnlen(bcc_ptr, 1024); 2648 len = strnlen(bcc_ptr, 1024);
2870 if(ses->serverDomain) 2649 kfree(ses->serverDomain);
2871 kfree(ses->serverDomain);
2872 ses->serverDomain = 2650 ses->serverDomain =
2873 kzalloc(len + 1, 2651 kzalloc(len + 1,
2874 GFP_KERNEL); 2652 GFP_KERNEL);
@@ -2994,14 +2772,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2994 SecurityBlob->LmChallengeResponse.Buffer = 0; 2772 SecurityBlob->LmChallengeResponse.Buffer = 0;
2995 2773
2996 SecurityBlob->NtChallengeResponse.Length = 2774 SecurityBlob->NtChallengeResponse.Length =
2997 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2775 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2998 SecurityBlob->NtChallengeResponse.MaximumLength = 2776 SecurityBlob->NtChallengeResponse.MaximumLength =
2999 cpu_to_le16(CIFS_SESSION_KEY_SIZE); 2777 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3000 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); 2778 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3001 SecurityBlob->NtChallengeResponse.Buffer = 2779 SecurityBlob->NtChallengeResponse.Buffer =
3002 cpu_to_le32(SecurityBlobLength); 2780 cpu_to_le32(SecurityBlobLength);
3003 SecurityBlobLength += CIFS_SESSION_KEY_SIZE; 2781 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3004 bcc_ptr += CIFS_SESSION_KEY_SIZE; 2782 bcc_ptr += CIFS_SESS_KEY_SIZE;
3005 2783
3006 if (ses->capabilities & CAP_UNICODE) { 2784 if (ses->capabilities & CAP_UNICODE) {
3007 if (domain == NULL) { 2785 if (domain == NULL) {
@@ -3190,8 +2968,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3190 bcc_ptr, 2968 bcc_ptr,
3191 remaining_words 2969 remaining_words
3192 - 1); 2970 - 1);
3193 if(ses->serverNOS) 2971 kfree(ses->serverNOS);
3194 kfree(ses->serverNOS);
3195 ses->serverNOS = 2972 ses->serverNOS =
3196 kzalloc(2 * (len + 1), 2973 kzalloc(2 * (len + 1),
3197 GFP_KERNEL); 2974 GFP_KERNEL);
@@ -3244,8 +3021,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3244 if(ses->serverDomain) 3021 if(ses->serverDomain)
3245 kfree(ses->serverDomain); 3022 kfree(ses->serverDomain);
3246 ses->serverDomain = kzalloc(2, GFP_KERNEL); 3023 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3247 if(ses->serverNOS) 3024 kfree(ses->serverNOS);
3248 kfree(ses->serverNOS);
3249 ses->serverNOS = kzalloc(2, GFP_KERNEL); 3025 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3250 } 3026 }
3251 } else { /* ASCII */ 3027 } else { /* ASCII */
@@ -3263,8 +3039,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3263 bcc_ptr++; 3039 bcc_ptr++;
3264 3040
3265 len = strnlen(bcc_ptr, 1024); 3041 len = strnlen(bcc_ptr, 1024);
3266 if(ses->serverNOS) 3042 kfree(ses->serverNOS);
3267 kfree(ses->serverNOS);
3268 ses->serverNOS = kzalloc(len+1,GFP_KERNEL); 3043 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3269 strncpy(ses->serverNOS, bcc_ptr, len); 3044 strncpy(ses->serverNOS, bcc_ptr, len);
3270 bcc_ptr += len; 3045 bcc_ptr += len;
@@ -3340,22 +3115,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3340 bcc_ptr = &pSMB->Password[0]; 3115 bcc_ptr = &pSMB->Password[0];
3341 if((ses->server->secMode) & SECMODE_USER) { 3116 if((ses->server->secMode) & SECMODE_USER) {
3342 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ 3117 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3118 *bcc_ptr = 0; /* password is null byte */
3343 bcc_ptr++; /* skip password */ 3119 bcc_ptr++; /* skip password */
3120 /* already aligned so no need to do it below */
3344 } else { 3121 } else {
3345 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); 3122 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3346 /* BB FIXME add code to fail this if NTLMv2 or Kerberos 3123 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3347 specified as required (when that support is added to 3124 specified as required (when that support is added to
3348 the vfs in the future) as only NTLM or the much 3125 the vfs in the future) as only NTLM or the much
3349 weaker LANMAN (which we do not send) is accepted 3126 weaker LANMAN (which we do not send by default) is accepted
3350 by Samba (not sure whether other servers allow 3127 by Samba (not sure whether other servers allow
3351 NTLMv2 password here) */ 3128 NTLMv2 password here) */
3129#ifdef CONFIG_CIFS_WEAK_PW_HASH
3130 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3131 (ses->server->secType == LANMAN))
3132 calc_lanman_hash(ses, bcc_ptr);
3133 else
3134#endif /* CIFS_WEAK_PW_HASH */
3352 SMBNTencrypt(ses->password, 3135 SMBNTencrypt(ses->password,
3353 ses->server->cryptKey, 3136 ses->server->cryptKey,
3354 bcc_ptr); 3137 bcc_ptr);
3355 3138
3356 bcc_ptr += CIFS_SESSION_KEY_SIZE; 3139 bcc_ptr += CIFS_SESS_KEY_SIZE;
3357 *bcc_ptr = 0; 3140 if(ses->capabilities & CAP_UNICODE) {
3358 bcc_ptr++; /* align */ 3141 /* must align unicode strings */
3142 *bcc_ptr = 0; /* null byte password */
3143 bcc_ptr++;
3144 }
3359 } 3145 }
3360 3146
3361 if(ses->server->secMode & 3147 if(ses->server->secMode &
@@ -3429,7 +3215,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3429 } 3215 }
3430 /* else do not bother copying these informational fields */ 3216 /* else do not bother copying these informational fields */
3431 } 3217 }
3432 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); 3218 if(smb_buffer_response->WordCount == 3)
3219 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3220 else
3221 tcon->Flags = 0;
3433 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); 3222 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3434 } else if ((rc == 0) && tcon == NULL) { 3223 } else if ((rc == 0) && tcon == NULL) {
3435 /* all we need to save for IPC$ connection */ 3224 /* all we need to save for IPC$ connection */
@@ -3448,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3448 int xid; 3237 int xid;
3449 struct cifsSesInfo *ses = NULL; 3238 struct cifsSesInfo *ses = NULL;
3450 struct task_struct *cifsd_task; 3239 struct task_struct *cifsd_task;
3240 char * tmp;
3451 3241
3452 xid = GetXid(); 3242 xid = GetXid();
3453 3243
@@ -3481,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3481 } 3271 }
3482 3272
3483 cifs_sb->tcon = NULL; 3273 cifs_sb->tcon = NULL;
3274 tmp = cifs_sb->prepath;
3275 cifs_sb->prepathlen = 0;
3276 cifs_sb->prepath = NULL;
3277 kfree(tmp);
3484 if (ses) 3278 if (ses)
3485 schedule_timeout_interruptible(msecs_to_jiffies(500)); 3279 schedule_timeout_interruptible(msecs_to_jiffies(500));
3486 if (ses) 3280 if (ses)
@@ -3494,7 +3288,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3494 struct nls_table * nls_info) 3288 struct nls_table * nls_info)
3495{ 3289{
3496 int rc = 0; 3290 int rc = 0;
3497 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3291 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3498 int ntlmv2_flag = FALSE; 3292 int ntlmv2_flag = FALSE;
3499 int first_time = 0; 3293 int first_time = 0;
3500 3294
@@ -3526,20 +3320,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3526 pSesInfo->server->secMode, 3320 pSesInfo->server->secMode,
3527 pSesInfo->server->capabilities, 3321 pSesInfo->server->capabilities,
3528 pSesInfo->server->timeZone)); 3322 pSesInfo->server->timeZone));
3529#ifdef CONFIG_CIFS_EXPERIMENTAL 3323 if(experimEnabled < 2)
3530 if(experimEnabled > 1) 3324 rc = CIFS_SessSetup(xid, pSesInfo,
3531 rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, 3325 first_time, nls_info);
3532 &ntlmv2_flag, nls_info); 3326 else if (extended_security
3533 else
3534#endif
3535 if (extended_security
3536 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3327 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3537 && (pSesInfo->server->secType == NTLMSSP)) { 3328 && (pSesInfo->server->secType == NTLMSSP)) {
3538 cFYI(1, ("New style sesssetup")); 3329 rc = -EOPNOTSUPP;
3539 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3540 NULL /* security blob */,
3541 0 /* blob length */,
3542 nls_info);
3543 } else if (extended_security 3330 } else if (extended_security
3544 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3331 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3545 && (pSesInfo->server->secType == RawNTLMSSP)) { 3332 && (pSesInfo->server->secType == RawNTLMSSP)) {