diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 498 |
1 files changed, 110 insertions, 388 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bae1479318d1..876eb9ef85fe 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,12 +82,7 @@ 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; |
@@ -369,21 +363,21 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
369 | continue; | 363 | continue; |
370 | if (bigbuf == NULL) { | 364 | if (bigbuf == NULL) { |
371 | bigbuf = cifs_buf_get(); | 365 | bigbuf = cifs_buf_get(); |
372 | if(bigbuf == NULL) { | 366 | if (!bigbuf) { |
373 | cERROR(1,("No memory for large SMB response")); | 367 | cERROR(1, ("No memory for large SMB response")); |
374 | msleep(3000); | 368 | msleep(3000); |
375 | /* retry will check if exiting */ | 369 | /* retry will check if exiting */ |
376 | continue; | 370 | continue; |
377 | } | 371 | } |
378 | } else if(isLargeBuf) { | 372 | } else if (isLargeBuf) { |
379 | /* we are reusing a dirtry large buf, clear its start */ | 373 | /* we are reusing a dirty large buf, clear its start */ |
380 | memset(bigbuf, 0, sizeof (struct smb_hdr)); | 374 | memset(bigbuf, 0, sizeof (struct smb_hdr)); |
381 | } | 375 | } |
382 | 376 | ||
383 | if (smallbuf == NULL) { | 377 | if (smallbuf == NULL) { |
384 | smallbuf = cifs_small_buf_get(); | 378 | smallbuf = cifs_small_buf_get(); |
385 | if(smallbuf == NULL) { | 379 | if (!smallbuf) { |
386 | cERROR(1,("No memory for SMB response")); | 380 | cERROR(1, ("No memory for SMB response")); |
387 | msleep(1000); | 381 | msleep(1000); |
388 | /* retry will check if exiting */ | 382 | /* retry will check if exiting */ |
389 | continue; | 383 | continue; |
@@ -403,12 +397,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
403 | kernel_recvmsg(csocket, &smb_msg, | 397 | kernel_recvmsg(csocket, &smb_msg, |
404 | &iov, 1, 4, 0 /* BB see socket.h flags */); | 398 | &iov, 1, 4, 0 /* BB see socket.h flags */); |
405 | 399 | ||
406 | if(server->tcpStatus == CifsExiting) { | 400 | if (server->tcpStatus == CifsExiting) { |
407 | break; | 401 | break; |
408 | } else if (server->tcpStatus == CifsNeedReconnect) { | 402 | } else if (server->tcpStatus == CifsNeedReconnect) { |
409 | cFYI(1,("Reconnect after server stopped responding")); | 403 | cFYI(1, ("Reconnect after server stopped responding")); |
410 | cifs_reconnect(server); | 404 | cifs_reconnect(server); |
411 | cFYI(1,("call to reconnect done")); | 405 | cFYI(1, ("call to reconnect done")); |
412 | csocket = server->ssocket; | 406 | csocket = server->ssocket; |
413 | continue; | 407 | continue; |
414 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { | 408 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { |
@@ -417,15 +411,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
417 | tcpStatus CifsNeedReconnect if server hung */ | 411 | tcpStatus CifsNeedReconnect if server hung */ |
418 | continue; | 412 | continue; |
419 | } else if (length <= 0) { | 413 | } else if (length <= 0) { |
420 | if(server->tcpStatus == CifsNew) { | 414 | if (server->tcpStatus == CifsNew) { |
421 | cFYI(1,("tcp session abend after SMBnegprot")); | 415 | cFYI(1, ("tcp session abend after SMBnegprot")); |
422 | /* some servers kill the TCP session rather than | 416 | /* some servers kill the TCP session rather than |
423 | returning an SMB negprot error, in which | 417 | returning an SMB negprot error, in which |
424 | case reconnecting here is not going to help, | 418 | case reconnecting here is not going to help, |
425 | and so simply return error to mount */ | 419 | and so simply return error to mount */ |
426 | break; | 420 | break; |
427 | } | 421 | } |
428 | if(length == -EINTR) { | 422 | if (!try_to_freeze() && (length == -EINTR)) { |
429 | cFYI(1,("cifsd thread killed")); | 423 | cFYI(1,("cifsd thread killed")); |
430 | break; | 424 | break; |
431 | } | 425 | } |
@@ -585,9 +579,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
585 | /* merge response - fix up 1st*/ | 579 | /* merge response - fix up 1st*/ |
586 | if(coalesce_t2(smb_buffer, | 580 | if(coalesce_t2(smb_buffer, |
587 | mid_entry->resp_buf)) { | 581 | mid_entry->resp_buf)) { |
582 | mid_entry->multiRsp = 1; | ||
588 | break; | 583 | break; |
589 | } else { | 584 | } else { |
590 | /* all parts received */ | 585 | /* all parts received */ |
586 | mid_entry->multiEnd = 1; | ||
591 | goto multi_t2_fnd; | 587 | goto multi_t2_fnd; |
592 | } | 588 | } |
593 | } else { | 589 | } else { |
@@ -632,9 +628,14 @@ multi_t2_fnd: | |||
632 | wake_up_process(task_to_wake); | 628 | wake_up_process(task_to_wake); |
633 | } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) | 629 | } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) |
634 | && (isMultiRsp == FALSE)) { | 630 | && (isMultiRsp == FALSE)) { |
635 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 631 | cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter)); |
636 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, | 632 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, |
637 | sizeof(struct smb_hdr)); | 633 | sizeof(struct smb_hdr)); |
634 | #ifdef CONFIG_CIFS_DEBUG2 | ||
635 | cifs_dump_detail(smb_buffer); | ||
636 | cifs_dump_mids(server); | ||
637 | #endif /* CIFS_DEBUG2 */ | ||
638 | |||
638 | } | 639 | } |
639 | } /* end while !EXITING */ | 640 | } /* end while !EXITING */ |
640 | 641 | ||
@@ -784,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
784 | 785 | ||
785 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 786 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
786 | vol->rw = TRUE; | 787 | vol->rw = TRUE; |
787 | vol->ntlm = TRUE; | ||
788 | /* default is always to request posix paths. */ | 788 | /* default is always to request posix paths. */ |
789 | vol->posix_paths = 1; | 789 | vol->posix_paths = 1; |
790 | 790 | ||
@@ -915,30 +915,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
915 | cERROR(1,("no security value specified")); | 915 | cERROR(1,("no security value specified")); |
916 | continue; | 916 | continue; |
917 | } else if (strnicmp(value, "krb5i", 5) == 0) { | 917 | } else if (strnicmp(value, "krb5i", 5) == 0) { |
918 | vol->sign = 1; | 918 | vol->secFlg |= CIFSSEC_MAY_KRB5 | |
919 | vol->krb5 = 1; | 919 | CIFSSEC_MUST_SIGN; |
920 | } else if (strnicmp(value, "krb5p", 5) == 0) { | 920 | } else if (strnicmp(value, "krb5p", 5) == 0) { |
921 | /* vol->seal = 1; | 921 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | |
922 | vol->krb5 = 1; */ | 922 | CIFSSEC_MAY_KRB5; */ |
923 | cERROR(1,("Krb5 cifs privacy not supported")); | 923 | cERROR(1,("Krb5 cifs privacy not supported")); |
924 | return 1; | 924 | return 1; |
925 | } else if (strnicmp(value, "krb5", 4) == 0) { | 925 | } else if (strnicmp(value, "krb5", 4) == 0) { |
926 | vol->krb5 = 1; | 926 | vol->secFlg |= CIFSSEC_MAY_KRB5; |
927 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { | 927 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { |
928 | vol->ntlmv2 = 1; | 928 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | |
929 | vol->sign = 1; | 929 | CIFSSEC_MUST_SIGN; |
930 | } else if (strnicmp(value, "ntlmv2", 6) == 0) { | 930 | } else if (strnicmp(value, "ntlmv2", 6) == 0) { |
931 | vol->ntlmv2 = 1; | 931 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; |
932 | } else if (strnicmp(value, "ntlmi", 5) == 0) { | 932 | } else if (strnicmp(value, "ntlmi", 5) == 0) { |
933 | vol->ntlm = 1; | 933 | vol->secFlg |= CIFSSEC_MAY_NTLM | |
934 | vol->sign = 1; | 934 | CIFSSEC_MUST_SIGN; |
935 | } else if (strnicmp(value, "ntlm", 4) == 0) { | 935 | } else if (strnicmp(value, "ntlm", 4) == 0) { |
936 | /* ntlm is default so can be turned off too */ | 936 | /* ntlm is default so can be turned off too */ |
937 | vol->ntlm = 1; | 937 | vol->secFlg |= CIFSSEC_MAY_NTLM; |
938 | } else if (strnicmp(value, "nontlm", 6) == 0) { | 938 | } else if (strnicmp(value, "nontlm", 6) == 0) { |
939 | vol->ntlm = 0; | 939 | /* BB is there a better way to do this? */ |
940 | vol->secFlg |= CIFSSEC_MAY_NTLMV2; | ||
941 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
942 | } else if (strnicmp(value, "lanman", 6) == 0) { | ||
943 | vol->secFlg |= CIFSSEC_MAY_LANMAN; | ||
944 | #endif | ||
940 | } else if (strnicmp(value, "none", 4) == 0) { | 945 | } else if (strnicmp(value, "none", 4) == 0) { |
941 | vol->nullauth = 1; | 946 | vol->nullauth = 1; |
942 | } else { | 947 | } else { |
943 | cERROR(1,("bad security option: %s", value)); | 948 | cERROR(1,("bad security option: %s", value)); |
944 | return 1; | 949 | return 1; |
@@ -976,7 +981,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
976 | } | 981 | } |
977 | /* BB are there cases in which a comma can be valid in | 982 | /* BB are there cases in which a comma can be valid in |
978 | a domain name and need special handling? */ | 983 | a domain name and need special handling? */ |
979 | if (strnlen(value, 65) < 65) { | 984 | if (strnlen(value, 256) < 256) { |
980 | vol->domainname = value; | 985 | vol->domainname = value; |
981 | cFYI(1, ("Domain name set")); | 986 | cFYI(1, ("Domain name set")); |
982 | } else { | 987 | } else { |
@@ -1168,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1168 | vol->no_psx_acl = 0; | 1173 | vol->no_psx_acl = 0; |
1169 | } else if (strnicmp(data, "noacl",5) == 0) { | 1174 | } else if (strnicmp(data, "noacl",5) == 0) { |
1170 | vol->no_psx_acl = 1; | 1175 | vol->no_psx_acl = 1; |
1176 | } else if (strnicmp(data, "sign",4) == 0) { | ||
1177 | vol->secFlg |= CIFSSEC_MUST_SIGN; | ||
1178 | /* } else if (strnicmp(data, "seal",4) == 0) { | ||
1179 | vol->secFlg |= CIFSSEC_MUST_SEAL; */ | ||
1171 | } else if (strnicmp(data, "direct",6) == 0) { | 1180 | } else if (strnicmp(data, "direct",6) == 0) { |
1172 | vol->direct_io = 1; | 1181 | vol->direct_io = 1; |
1173 | } else if (strnicmp(data, "forcedirectio",13) == 0) { | 1182 | } else if (strnicmp(data, "forcedirectio",13) == 0) { |
@@ -1762,11 +1771,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1762 | if (volume_info.username) | 1771 | if (volume_info.username) |
1763 | strncpy(pSesInfo->userName, | 1772 | strncpy(pSesInfo->userName, |
1764 | volume_info.username,MAX_USERNAME_SIZE); | 1773 | volume_info.username,MAX_USERNAME_SIZE); |
1765 | if (volume_info.domainname) | 1774 | if (volume_info.domainname) { |
1766 | strncpy(pSesInfo->domainName, | 1775 | int len = strlen(volume_info.domainname); |
1767 | volume_info.domainname,MAX_USERNAME_SIZE); | 1776 | pSesInfo->domainName = |
1777 | kmalloc(len + 1, GFP_KERNEL); | ||
1778 | if(pSesInfo->domainName) | ||
1779 | strcpy(pSesInfo->domainName, | ||
1780 | volume_info.domainname); | ||
1781 | } | ||
1768 | pSesInfo->linux_uid = volume_info.linux_uid; | 1782 | pSesInfo->linux_uid = volume_info.linux_uid; |
1783 | pSesInfo->overrideSecFlg = volume_info.secFlg; | ||
1769 | down(&pSesInfo->sesSem); | 1784 | down(&pSesInfo->sesSem); |
1785 | /* BB FIXME need to pass vol->secFlgs BB */ | ||
1770 | rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); | 1786 | rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); |
1771 | up(&pSesInfo->sesSem); | 1787 | up(&pSesInfo->sesSem); |
1772 | if(!rc) | 1788 | if(!rc) |
@@ -1980,7 +1996,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1980 | 1996 | ||
1981 | static int | 1997 | static int |
1982 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 1998 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, |
1983 | char session_key[CIFS_SESSION_KEY_SIZE], | 1999 | char session_key[CIFS_SESS_KEY_SIZE], |
1984 | const struct nls_table *nls_codepage) | 2000 | const struct nls_table *nls_codepage) |
1985 | { | 2001 | { |
1986 | struct smb_hdr *smb_buffer; | 2002 | struct smb_hdr *smb_buffer; |
@@ -2038,15 +2054,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2038 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 2054 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
2039 | 2055 | ||
2040 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | 2056 | pSMB->req_no_secext.CaseInsensitivePasswordLength = |
2041 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2057 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2042 | 2058 | ||
2043 | pSMB->req_no_secext.CaseSensitivePasswordLength = | 2059 | pSMB->req_no_secext.CaseSensitivePasswordLength = |
2044 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2060 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2045 | bcc_ptr = pByteArea(smb_buffer); | 2061 | bcc_ptr = pByteArea(smb_buffer); |
2046 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2062 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2047 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2063 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2048 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); | 2064 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); |
2049 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2065 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
2050 | 2066 | ||
2051 | if (ses->capabilities & CAP_UNICODE) { | 2067 | if (ses->capabilities & CAP_UNICODE) { |
2052 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ | 2068 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ |
@@ -2054,7 +2070,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2054 | bcc_ptr++; | 2070 | bcc_ptr++; |
2055 | } | 2071 | } |
2056 | if(user == NULL) | 2072 | if(user == NULL) |
2057 | bytes_returned = 0; /* skill null user */ | 2073 | bytes_returned = 0; /* skip null user */ |
2058 | else | 2074 | else |
2059 | bytes_returned = | 2075 | bytes_returned = |
2060 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, | 2076 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, |
@@ -2162,8 +2178,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2162 | if (remaining_words > 0) { | 2178 | if (remaining_words > 0) { |
2163 | len = UniStrnlen((wchar_t *)bcc_ptr, | 2179 | len = UniStrnlen((wchar_t *)bcc_ptr, |
2164 | remaining_words-1); | 2180 | remaining_words-1); |
2165 | if(ses->serverNOS) | 2181 | kfree(ses->serverNOS); |
2166 | kfree(ses->serverNOS); | ||
2167 | ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); | 2182 | ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); |
2168 | if(ses->serverNOS == NULL) | 2183 | if(ses->serverNOS == NULL) |
2169 | goto sesssetup_nomem; | 2184 | goto sesssetup_nomem; |
@@ -2203,12 +2218,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2203 | /* if these kcallocs fail not much we | 2218 | /* if these kcallocs fail not much we |
2204 | can do, but better to not fail the | 2219 | can do, but better to not fail the |
2205 | sesssetup itself */ | 2220 | sesssetup itself */ |
2206 | if(ses->serverDomain) | 2221 | kfree(ses->serverDomain); |
2207 | kfree(ses->serverDomain); | ||
2208 | ses->serverDomain = | 2222 | ses->serverDomain = |
2209 | kzalloc(2, GFP_KERNEL); | 2223 | kzalloc(2, GFP_KERNEL); |
2210 | if(ses->serverNOS) | 2224 | kfree(ses->serverNOS); |
2211 | kfree(ses->serverNOS); | ||
2212 | ses->serverNOS = | 2225 | ses->serverNOS = |
2213 | kzalloc(2, GFP_KERNEL); | 2226 | kzalloc(2, GFP_KERNEL); |
2214 | } | 2227 | } |
@@ -2217,8 +2230,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2217 | if (((long) bcc_ptr + len) - (long) | 2230 | if (((long) bcc_ptr + len) - (long) |
2218 | pByteArea(smb_buffer_response) | 2231 | pByteArea(smb_buffer_response) |
2219 | <= BCC(smb_buffer_response)) { | 2232 | <= BCC(smb_buffer_response)) { |
2220 | if(ses->serverOS) | 2233 | kfree(ses->serverOS); |
2221 | kfree(ses->serverOS); | ||
2222 | ses->serverOS = kzalloc(len + 1,GFP_KERNEL); | 2234 | ses->serverOS = kzalloc(len + 1,GFP_KERNEL); |
2223 | if(ses->serverOS == NULL) | 2235 | if(ses->serverOS == NULL) |
2224 | goto sesssetup_nomem; | 2236 | goto sesssetup_nomem; |
@@ -2229,8 +2241,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2229 | bcc_ptr++; | 2241 | bcc_ptr++; |
2230 | 2242 | ||
2231 | len = strnlen(bcc_ptr, 1024); | 2243 | len = strnlen(bcc_ptr, 1024); |
2232 | if(ses->serverNOS) | 2244 | kfree(ses->serverNOS); |
2233 | kfree(ses->serverNOS); | ||
2234 | ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); | 2245 | ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); |
2235 | if(ses->serverNOS == NULL) | 2246 | if(ses->serverNOS == NULL) |
2236 | goto sesssetup_nomem; | 2247 | goto sesssetup_nomem; |
@@ -2274,292 +2285,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings, | |||
2274 | } | 2285 | } |
2275 | 2286 | ||
2276 | static int | 2287 | 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, | 2288 | CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, |
2564 | struct cifsSesInfo *ses, int * pNTLMv2_flag, | 2289 | struct cifsSesInfo *ses, int * pNTLMv2_flag, |
2565 | const struct nls_table *nls_codepage) | 2290 | const struct nls_table *nls_codepage) |
@@ -2635,8 +2360,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2635 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; | 2360 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; |
2636 | if(sign_CIFS_PDUs) | 2361 | if(sign_CIFS_PDUs) |
2637 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; | 2362 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; |
2638 | if(ntlmv2_support) | 2363 | /* if(ntlmv2_support) |
2639 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; | 2364 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/ |
2640 | /* setup pointers to domain name and workstation name */ | 2365 | /* setup pointers to domain name and workstation name */ |
2641 | bcc_ptr += SecurityBlobLength; | 2366 | bcc_ptr += SecurityBlobLength; |
2642 | 2367 | ||
@@ -2783,8 +2508,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2783 | bcc_ptr, | 2508 | bcc_ptr, |
2784 | remaining_words | 2509 | remaining_words |
2785 | - 1); | 2510 | - 1); |
2786 | if(ses->serverNOS) | 2511 | kfree(ses->serverNOS); |
2787 | kfree(ses->serverNOS); | ||
2788 | ses->serverNOS = | 2512 | ses->serverNOS = |
2789 | kzalloc(2 * (len + 1), | 2513 | kzalloc(2 * (len + 1), |
2790 | GFP_KERNEL); | 2514 | GFP_KERNEL); |
@@ -2802,8 +2526,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2802 | if (remaining_words > 0) { | 2526 | if (remaining_words > 0) { |
2803 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | 2527 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); |
2804 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ | 2528 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ |
2805 | if(ses->serverDomain) | 2529 | kfree(ses->serverDomain); |
2806 | kfree(ses->serverDomain); | ||
2807 | ses->serverDomain = | 2530 | ses->serverDomain = |
2808 | kzalloc(2 * | 2531 | kzalloc(2 * |
2809 | (len + | 2532 | (len + |
@@ -2822,19 +2545,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2822 | = 0; | 2545 | = 0; |
2823 | } /* else no more room so create dummy domain string */ | 2546 | } /* else no more room so create dummy domain string */ |
2824 | else { | 2547 | else { |
2825 | if(ses->serverDomain) | 2548 | kfree(ses->serverDomain); |
2826 | kfree(ses->serverDomain); | ||
2827 | ses->serverDomain = | 2549 | ses->serverDomain = |
2828 | kzalloc(2, | 2550 | kzalloc(2, |
2829 | GFP_KERNEL); | 2551 | GFP_KERNEL); |
2830 | } | 2552 | } |
2831 | } else { /* no room so create dummy domain and NOS string */ | 2553 | } else { /* no room so create dummy domain and NOS string */ |
2832 | if(ses->serverDomain); | 2554 | kfree(ses->serverDomain); |
2833 | kfree(ses->serverDomain); | ||
2834 | ses->serverDomain = | 2555 | ses->serverDomain = |
2835 | kzalloc(2, GFP_KERNEL); | 2556 | kzalloc(2, GFP_KERNEL); |
2836 | if(ses->serverNOS) | 2557 | kfree(ses->serverNOS); |
2837 | kfree(ses->serverNOS); | ||
2838 | ses->serverNOS = | 2558 | ses->serverNOS = |
2839 | kzalloc(2, GFP_KERNEL); | 2559 | kzalloc(2, GFP_KERNEL); |
2840 | } | 2560 | } |
@@ -2856,8 +2576,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2856 | bcc_ptr++; | 2576 | bcc_ptr++; |
2857 | 2577 | ||
2858 | len = strnlen(bcc_ptr, 1024); | 2578 | len = strnlen(bcc_ptr, 1024); |
2859 | if(ses->serverNOS) | 2579 | kfree(ses->serverNOS); |
2860 | kfree(ses->serverNOS); | ||
2861 | ses->serverNOS = | 2580 | ses->serverNOS = |
2862 | kzalloc(len + 1, | 2581 | kzalloc(len + 1, |
2863 | GFP_KERNEL); | 2582 | GFP_KERNEL); |
@@ -2867,8 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2867 | bcc_ptr++; | 2586 | bcc_ptr++; |
2868 | 2587 | ||
2869 | len = strnlen(bcc_ptr, 1024); | 2588 | len = strnlen(bcc_ptr, 1024); |
2870 | if(ses->serverDomain) | 2589 | kfree(ses->serverDomain); |
2871 | kfree(ses->serverDomain); | ||
2872 | ses->serverDomain = | 2590 | ses->serverDomain = |
2873 | kzalloc(len + 1, | 2591 | kzalloc(len + 1, |
2874 | GFP_KERNEL); | 2592 | GFP_KERNEL); |
@@ -2994,14 +2712,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2994 | SecurityBlob->LmChallengeResponse.Buffer = 0; | 2712 | SecurityBlob->LmChallengeResponse.Buffer = 0; |
2995 | 2713 | ||
2996 | SecurityBlob->NtChallengeResponse.Length = | 2714 | SecurityBlob->NtChallengeResponse.Length = |
2997 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2715 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
2998 | SecurityBlob->NtChallengeResponse.MaximumLength = | 2716 | SecurityBlob->NtChallengeResponse.MaximumLength = |
2999 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 2717 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3000 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE); | 2718 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); |
3001 | SecurityBlob->NtChallengeResponse.Buffer = | 2719 | SecurityBlob->NtChallengeResponse.Buffer = |
3002 | cpu_to_le32(SecurityBlobLength); | 2720 | cpu_to_le32(SecurityBlobLength); |
3003 | SecurityBlobLength += CIFS_SESSION_KEY_SIZE; | 2721 | SecurityBlobLength += CIFS_SESS_KEY_SIZE; |
3004 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 2722 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3005 | 2723 | ||
3006 | if (ses->capabilities & CAP_UNICODE) { | 2724 | if (ses->capabilities & CAP_UNICODE) { |
3007 | if (domain == NULL) { | 2725 | if (domain == NULL) { |
@@ -3190,8 +2908,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3190 | bcc_ptr, | 2908 | bcc_ptr, |
3191 | remaining_words | 2909 | remaining_words |
3192 | - 1); | 2910 | - 1); |
3193 | if(ses->serverNOS) | 2911 | kfree(ses->serverNOS); |
3194 | kfree(ses->serverNOS); | ||
3195 | ses->serverNOS = | 2912 | ses->serverNOS = |
3196 | kzalloc(2 * (len + 1), | 2913 | kzalloc(2 * (len + 1), |
3197 | GFP_KERNEL); | 2914 | GFP_KERNEL); |
@@ -3244,8 +2961,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3244 | if(ses->serverDomain) | 2961 | if(ses->serverDomain) |
3245 | kfree(ses->serverDomain); | 2962 | kfree(ses->serverDomain); |
3246 | ses->serverDomain = kzalloc(2, GFP_KERNEL); | 2963 | ses->serverDomain = kzalloc(2, GFP_KERNEL); |
3247 | if(ses->serverNOS) | 2964 | kfree(ses->serverNOS); |
3248 | kfree(ses->serverNOS); | ||
3249 | ses->serverNOS = kzalloc(2, GFP_KERNEL); | 2965 | ses->serverNOS = kzalloc(2, GFP_KERNEL); |
3250 | } | 2966 | } |
3251 | } else { /* ASCII */ | 2967 | } else { /* ASCII */ |
@@ -3263,8 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3263 | bcc_ptr++; | 2979 | bcc_ptr++; |
3264 | 2980 | ||
3265 | len = strnlen(bcc_ptr, 1024); | 2981 | len = strnlen(bcc_ptr, 1024); |
3266 | if(ses->serverNOS) | 2982 | kfree(ses->serverNOS); |
3267 | kfree(ses->serverNOS); | ||
3268 | ses->serverNOS = kzalloc(len+1,GFP_KERNEL); | 2983 | ses->serverNOS = kzalloc(len+1,GFP_KERNEL); |
3269 | strncpy(ses->serverNOS, bcc_ptr, len); | 2984 | strncpy(ses->serverNOS, bcc_ptr, len); |
3270 | bcc_ptr += len; | 2985 | bcc_ptr += len; |
@@ -3340,22 +3055,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3340 | bcc_ptr = &pSMB->Password[0]; | 3055 | bcc_ptr = &pSMB->Password[0]; |
3341 | if((ses->server->secMode) & SECMODE_USER) { | 3056 | if((ses->server->secMode) & SECMODE_USER) { |
3342 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | 3057 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ |
3058 | *bcc_ptr = 0; /* password is null byte */ | ||
3343 | bcc_ptr++; /* skip password */ | 3059 | bcc_ptr++; /* skip password */ |
3060 | /* already aligned so no need to do it below */ | ||
3344 | } else { | 3061 | } else { |
3345 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE); | 3062 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); |
3346 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | 3063 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos |
3347 | specified as required (when that support is added to | 3064 | specified as required (when that support is added to |
3348 | the vfs in the future) as only NTLM or the much | 3065 | the vfs in the future) as only NTLM or the much |
3349 | weaker LANMAN (which we do not send) is accepted | 3066 | weaker LANMAN (which we do not send by default) is accepted |
3350 | by Samba (not sure whether other servers allow | 3067 | by Samba (not sure whether other servers allow |
3351 | NTLMv2 password here) */ | 3068 | NTLMv2 password here) */ |
3069 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
3070 | if((extended_security & CIFSSEC_MAY_LANMAN) && | ||
3071 | (ses->server->secType == LANMAN)) | ||
3072 | calc_lanman_hash(ses, bcc_ptr); | ||
3073 | else | ||
3074 | #endif /* CIFS_WEAK_PW_HASH */ | ||
3352 | SMBNTencrypt(ses->password, | 3075 | SMBNTencrypt(ses->password, |
3353 | ses->server->cryptKey, | 3076 | ses->server->cryptKey, |
3354 | bcc_ptr); | 3077 | bcc_ptr); |
3355 | 3078 | ||
3356 | bcc_ptr += CIFS_SESSION_KEY_SIZE; | 3079 | bcc_ptr += CIFS_SESS_KEY_SIZE; |
3357 | *bcc_ptr = 0; | 3080 | if(ses->capabilities & CAP_UNICODE) { |
3358 | bcc_ptr++; /* align */ | 3081 | /* must align unicode strings */ |
3082 | *bcc_ptr = 0; /* null byte password */ | ||
3083 | bcc_ptr++; | ||
3084 | } | ||
3359 | } | 3085 | } |
3360 | 3086 | ||
3361 | if(ses->server->secMode & | 3087 | if(ses->server->secMode & |
@@ -3429,7 +3155,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3429 | } | 3155 | } |
3430 | /* else do not bother copying these informational fields */ | 3156 | /* else do not bother copying these informational fields */ |
3431 | } | 3157 | } |
3432 | tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); | 3158 | if(smb_buffer_response->WordCount == 3) |
3159 | tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); | ||
3160 | else | ||
3161 | tcon->Flags = 0; | ||
3433 | cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); | 3162 | cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); |
3434 | } else if ((rc == 0) && tcon == NULL) { | 3163 | } else if ((rc == 0) && tcon == NULL) { |
3435 | /* all we need to save for IPC$ connection */ | 3164 | /* all we need to save for IPC$ connection */ |
@@ -3494,7 +3223,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3494 | struct nls_table * nls_info) | 3223 | struct nls_table * nls_info) |
3495 | { | 3224 | { |
3496 | int rc = 0; | 3225 | int rc = 0; |
3497 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; | 3226 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
3498 | int ntlmv2_flag = FALSE; | 3227 | int ntlmv2_flag = FALSE; |
3499 | int first_time = 0; | 3228 | int first_time = 0; |
3500 | 3229 | ||
@@ -3526,20 +3255,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3526 | pSesInfo->server->secMode, | 3255 | pSesInfo->server->secMode, |
3527 | pSesInfo->server->capabilities, | 3256 | pSesInfo->server->capabilities, |
3528 | pSesInfo->server->timeZone)); | 3257 | pSesInfo->server->timeZone)); |
3529 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 3258 | if(experimEnabled < 2) |
3530 | if(experimEnabled > 1) | 3259 | rc = CIFS_SessSetup(xid, pSesInfo, |
3531 | rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */, | 3260 | first_time, nls_info); |
3532 | &ntlmv2_flag, nls_info); | 3261 | else if (extended_security |
3533 | else | ||
3534 | #endif | ||
3535 | if (extended_security | ||
3536 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3262 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3537 | && (pSesInfo->server->secType == NTLMSSP)) { | 3263 | && (pSesInfo->server->secType == NTLMSSP)) { |
3538 | cFYI(1, ("New style sesssetup")); | 3264 | rc = -EOPNOTSUPP; |
3539 | rc = CIFSSpnegoSessSetup(xid, pSesInfo, | ||
3540 | NULL /* security blob */, | ||
3541 | 0 /* blob length */, | ||
3542 | nls_info); | ||
3543 | } else if (extended_security | 3265 | } else if (extended_security |
3544 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3266 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3545 | && (pSesInfo->server->secType == RawNTLMSSP)) { | 3267 | && (pSesInfo->server->secType == RawNTLMSSP)) { |