diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 577 |
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 | ||
| 50 | static DECLARE_COMPLETION(cifsd_complete); | 50 | static DECLARE_COMPLETION(cifsd_complete); |
| 51 | 51 | ||
| 52 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | ||
| 53 | unsigned char *p24); | ||
| 54 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 52 | extern 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 | ||
| 100 | static int ipv4_connect(struct sockaddr_in *psin_server, | 95 | static 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 | ||
| 1981 | static int | 2057 | static int |
| 1982 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 2058 | CIFSSessSetup(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 | ||
| 2276 | static int | 2347 | static int |
| 2277 | CIFSSpnegoSessSetup(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 | |||
| 2562 | static int | ||
| 2563 | CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | 2348 | CIFSNTLMSSPNegotiateSessSetup(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)) { |
