X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Fcifs%2Fsess.c;h=bbdda99dce610364b71b5218cb061b3dfc577cd9;hb=239fd45938f9ddf64f120e0260c7b76eb73bd5a7;hp=1fe9461c6dca4f97d70f3790dddd789bc0e2d3ff;hpb=9312f6754d4b2d3ce27c21b16fb92923ce92a411;p=powerpc.git diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 1fe9461c6d..bbdda99dce 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -33,8 +33,6 @@ extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); -#ifdef CONFIG_CIFS_EXPERIMENTAL - static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) { __u32 capabilities = 0; @@ -85,14 +83,16 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, /* BB FIXME add check that strings total less than 335 or will need to send them as arrays */ - /* align unicode strings, must be word aligned */ - if ((long) bcc_ptr % 2) { + /* unicode strings, must be word aligned before the call */ +/* if ((long) bcc_ptr % 2) { *bcc_ptr = 0; bcc_ptr++; - } + } */ /* copy user */ if(ses->userName == NULL) { - /* BB what about null user mounts - check that we do this BB */ + /* null user mount */ + *bcc_ptr = 0; + *(bcc_ptr+1) = 0; } else { /* 300 should be long enough for any conceivable user name */ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, 300, nls_cp); @@ -100,10 +100,13 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null termination */ /* copy domain */ - if(ses->domainName == NULL) - bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, - "CIFS_LINUX_DOM", 32, nls_cp); - else + if(ses->domainName == NULL) { + /* Sending null domain better than using a bogus domain name (as + we did briefly in 2.6.18) since server will use its default */ + *bcc_ptr = 0; + *(bcc_ptr+1) = 0; + bytes_ret = 0; + } else bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, 256, nls_cp); bcc_ptr += 2 * bytes_ret; @@ -113,7 +116,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, nls_cp); bcc_ptr += 2 * bytes_ret; - bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, 32, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* trailing null */ @@ -140,19 +143,17 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, strncpy(bcc_ptr, ses->userName, 300); } /* BB improve check for overflow */ - bcc_ptr += strnlen(ses->userName, 200); + bcc_ptr += strnlen(ses->userName, 300); *bcc_ptr = 0; bcc_ptr++; /* account for null termination */ /* copy domain */ - if(ses->domainName == NULL) { - strcpy(bcc_ptr, "CIFS_LINUX_DOM"); - bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */ - } else { + if(ses->domainName != NULL) { strncpy(bcc_ptr, ses->domainName, 256); bcc_ptr += strnlen(ses->domainName, 256); - } + } /* else we will send a null domain name + so the server will default to its own domain */ *bcc_ptr = 0; bcc_ptr++; @@ -160,8 +161,8 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, strcpy(bcc_ptr, "Linux version "); bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, system_utsname.release); - bcc_ptr += strlen(system_utsname.release) + 1; + strcpy(bcc_ptr, init_utsname()->release); + bcc_ptr += strlen(init_utsname()->release) + 1; strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; @@ -270,6 +271,10 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo ses->serverOS = kzalloc(len + 1, GFP_KERNEL); if(ses->serverOS) strncpy(ses->serverOS, bcc_ptr, len); + if(strncmp(ses->serverOS, "OS/2",4) == 0) { + cFYI(1,("OS/2 server")); + ses->flags |= CIFS_SES_OS2; + } bcc_ptr += len + 1; bleft -= len + 1; @@ -292,16 +297,11 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo if(len > bleft) return rc; - if(ses->serverDomain) - kfree(ses->serverDomain); - - ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); - if(ses->serverOS) - strncpy(ses->serverOS, bcc_ptr, len); - - bcc_ptr += len + 1; - bleft -= len + 1; - + /* No domain field in LANMAN case. Domain is + returned by old servers in the SMB negprot response */ + /* BB For newer servers which do not support Unicode, + but thus do return domain here we could add parsing + for it later, but it is not very important */ cFYI(1,("ascii: bytes left %d",bleft)); return rc; @@ -315,20 +315,22 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, int wct; struct smb_hdr *smb_buf; char *bcc_ptr; + char *str_area; SESSION_SETUP_ANDX *pSMB; __u32 capabilities; int count; int resp_buf_type = 0; - struct kvec iov[1]; + struct kvec iov[2]; enum securityEnum type; __u16 action; int bytes_remaining; - cFYI(1,("new sess setup")); if(ses == NULL) return -EINVAL; type = ses->server->secType; + + cFYI(1,("sess setup type %d",type)); if(type == LANMAN) { #ifndef CONFIG_CIFS_WEAK_PW_HASH /* LANMAN and plaintext are less secure and off by default. @@ -353,7 +355,20 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, pSMB = (SESSION_SETUP_ANDX *)smb_buf; capabilities = cifs_ssetup_hdr(ses, pSMB); - bcc_ptr = pByteArea(smb_buf); + + /* we will send the SMB in two pieces, + a fixed length beginning part, and a + second part which will include the strings + and rest of bcc area, in order to avoid having + to do a large buffer 17K allocation */ + iov[0].iov_base = (char *)pSMB; + iov[0].iov_len = smb_buf->smb_buf_length + 4; + + /* 2000 big enough to fit max user, domain, NOS name etc. */ + str_area = kmalloc(2000, GFP_KERNEL); + bcc_ptr = str_area; + + ses->flags &= ~CIFS_SES_LANMAN; if(type == LANMAN) { #ifdef CONFIG_CIFS_WEAK_PW_HASH @@ -361,16 +376,16 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* no capabilities flags in old lanman negotiation */ - pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; + pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); /* BB calculate hash with password */ /* and copy into bcc */ calc_lanman_hash(ses, lnm_session_key); - -#ifdef CONFIG_CIFS_DEBUG2 + ses->flags |= CIFS_SES_LANMAN; +/* #ifdef CONFIG_CIFS_DEBUG2 cifs_dump_mem("cryptkey: ",ses->server->cryptKey, CIFS_SESS_KEY_SIZE); -#endif +#endif */ memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); bcc_ptr += CIFS_SESS_KEY_SIZE; @@ -379,7 +394,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, changed to do higher than lanman dialect and we reconnected would we ever calc signing_key? */ - cERROR(1,("Negotiating LANMAN setting up strings")); + cFYI(1,("Negotiating LANMAN setting up strings")); /* Unicode not allowed for LANMAN dialects */ ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); #endif @@ -398,7 +413,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, if(first_time) /* should this be moved into common code with similar ntlmv2 path? */ - cifs_calculate_mac_key( ses->server->mac_signing_key, + cifs_calculate_mac_key(ses->server->mac_signing_key, ntlm_session_key, ses->password); /* copy session key */ @@ -406,12 +421,21 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, bcc_ptr += CIFS_SESS_KEY_SIZE; memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); bcc_ptr += CIFS_SESS_KEY_SIZE; - if(ses->capabilities & CAP_UNICODE) + if(ses->capabilities & CAP_UNICODE) { + /* unicode strings must be word aligned */ + if (iov[0].iov_len % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - else + } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); } else if (type == NTLMv2) { - char * v2_sess_key = kmalloc(V2_SESS_KEY_SIZE, GFP_KERNEL); + char * v2_sess_key = + kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL); + + /* BB FIXME change all users of v2_sess_key to + struct ntlmv2_resp */ if(v2_sess_key == NULL) { cifs_small_buf_release(smb_buf); @@ -425,10 +449,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* cpu_to_le16(LM2_SESS_KEY_SIZE); */ pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(V2_SESS_KEY_SIZE); + cpu_to_le16(sizeof(struct ntlmv2_resp)); /* calculate session key */ - CalcNTLMv2_response(ses, v2_sess_key); + setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); if(first_time) /* should this be moved into common code with similar ntlmv2 path? */ /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, @@ -438,11 +462,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); bcc_ptr += LM2_SESS_KEY_SIZE; */ - memcpy(bcc_ptr, (char *)v2_sess_key, V2_SESS_KEY_SIZE); - bcc_ptr += V2_SESS_KEY_SIZE; - if(ses->capabilities & CAP_UNICODE) + memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); + bcc_ptr += sizeof(struct ntlmv2_resp); + kfree(v2_sess_key); + if(ses->capabilities & CAP_UNICODE) { + if(iov[0].iov_len % 2) { + *bcc_ptr = 0; + } bcc_ptr++; unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - else + } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); } else /* NTLMSSP or SPNEGO */ { pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; @@ -451,23 +479,14 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* BB set password lengths */ } - count = (long) bcc_ptr - (long) pByteArea(smb_buf); + count = (long) bcc_ptr - (long) str_area; smb_buf->smb_buf_length += count; - /* if we switch to small buffers, count will need to be fewer - than 383 (strings less than 335 bytes) */ - BCC_LE(smb_buf) = cpu_to_le16(count); - - /* BB FIXME check for other non ntlm code paths */ - - /* BB check is this too big for a small smb? */ - - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = smb_buf->smb_buf_length + 4; - - rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0); + iov[1].iov_base = str_area; + iov[1].iov_len = count; + rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0); /* SMB request buf freed in SendReceive2 */ cFYI(1,("ssetup rc from sendrecv2 is %d",rc)); @@ -484,7 +503,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, } action = le16_to_cpu(pSMB->resp.Action); if (action & GUEST_LOGIN) - cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */ + cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ cFYI(1, ("UID = %d ", ses->Suid)); /* response can have either 3 or 4 word count - Samba sends 3 */ @@ -512,6 +531,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp); ssetup_exit: + kfree(str_area); if(resp_buf_type == CIFS_SMALL_BUFFER) { cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base)); cifs_small_buf_release(iov[0].iov_base); @@ -520,4 +540,3 @@ ssetup_exit: return rc; } -#endif /* CONFIG_CIFS_EXPERIMENTAL */