Loading fs/cifs/README +2 −0 Original line number Diff line number Diff line Loading @@ -453,6 +453,8 @@ sec Security mode. Allowed values are: server requires signing also can be the default) ntlmv2 Use NTLMv2 password hashing ntlmv2i Use NTLMv2 password hashing with packet signing lanman (if configured in kernel config) use older lanman hash The mount.cifs mount helper also accepts a few mount options before -o including: Loading fs/cifs/cifsproto.h +1 −1 Original line number Diff line number Diff line Loading @@ -68,10 +68,10 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , extern int small_smb_init_no_tc(const int smb_cmd, const int wct, struct cifsSesInfo *ses, void ** request_buf); #endif extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int stage, const struct nls_table *nls_cp); #endif extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); Loading fs/cifs/connect.c +23 −315 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ struct smb_vol { gid_t linux_gid; mode_t file_mode; mode_t dir_mode; unsigned secFlg; unsigned rw:1; unsigned retry:1; unsigned intr:1; Loading @@ -81,12 +82,7 @@ struct smb_vol { unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ unsigned sfu_emul:1; unsigned krb5:1; unsigned ntlm:1; unsigned ntlmv2:1; unsigned nullauth:1; /* attempt to authenticate with null user */ unsigned sign:1; unsigned seal:1; /* encrypt */ unsigned nocase; /* request case insensitive filenames */ unsigned nobrl; /* disable sending byte range locks to srv */ unsigned int rsize; Loading Loading @@ -789,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ vol->rw = TRUE; vol->ntlm = TRUE; /* default is always to request posix paths. */ vol->posix_paths = 1; Loading Loading @@ -920,28 +915,33 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) cERROR(1,("no security value specified")); continue; } else if (strnicmp(value, "krb5i", 5) == 0) { vol->sign = 1; vol->krb5 = 1; vol->secFlg = CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "krb5p", 5) == 0) { /* vol->seal = 1; vol->krb5 = 1; */ /* vol->secFlg = CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ cERROR(1,("Krb5 cifs privacy not supported")); return 1; } else if (strnicmp(value, "krb5", 4) == 0) { vol->krb5 = 1; vol->secFlg = CIFSSEC_MAY_KRB5; } else if (strnicmp(value, "ntlmv2i", 7) == 0) { vol->ntlmv2 = 1; vol->sign = 1; vol->secFlg = CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "ntlmv2", 6) == 0) { vol->ntlmv2 = 1; vol->secFlg = CIFSSEC_MAY_NTLMV2; } else if (strnicmp(value, "ntlmi", 5) == 0) { vol->ntlm = 1; vol->sign = 1; vol->secFlg = CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "ntlm", 4) == 0) { /* ntlm is default so can be turned off too */ vol->ntlm = 1; vol->secFlg = CIFSSEC_MAY_NTLM; } else if (strnicmp(value, "nontlm", 6) == 0) { vol->ntlm = 0; /* BB is there a better way to do this? */ vol->secFlg = CIFSSEC_MAY_NTLMV2; #ifdef CONFIG_CIFS_WEAK_PW_HASH } else if (strnicmp(value, "lanman", 6) == 0) { vol->secFlg = CIFSSEC_MAY_LANMAN; #endif } else if (strnicmp(value, "none", 4) == 0) { vol->nullauth = 1; } else { Loading Loading @@ -1777,6 +1777,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } pSesInfo->linux_uid = volume_info.linux_uid; down(&pSesInfo->sesSem); /* BB FIXME need to pass vol->secFlgs BB */ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); up(&pSesInfo->sesSem); if(!rc) Loading Loading @@ -2283,292 +2284,6 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, return rc; } static int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *SecurityBlob,int SecurityBlobLength, const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer_response; SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; char *user; char *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; __u32 capabilities; __u16 count; cFYI(1, ("In spnego sesssetup ")); if(ses == NULL) return -EINVAL; user = ses->userName; domain = ses->domainName; smb_buffer = cifs_buf_get(); if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; if(ses->server->maxBuf > 64*1024) ses->server->maxBuf = (64*1023); pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_EXTENDED_SECURITY; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; capabilities |= CAP_DFS; } pSMB->req.Capabilities = cpu_to_le32(capabilities); pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); bcc_ptr = pByteArea(smb_buffer); memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength); bcc_ptr += SecurityBlobLength; if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */ *bcc_ptr = 0; bcc_ptr++; } bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage); bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */ bcc_ptr += 2; /* trailing null */ if (domain == NULL) bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, "CIFS_LINUX_DOM", 32, nls_codepage); else bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 64, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; } else { strncpy(bcc_ptr, user, 200); bcc_ptr += strnlen(user, 200); *bcc_ptr = 0; bcc_ptr++; if (domain == NULL) { strcpy(bcc_ptr, "CIFS_LINUX_DOM"); bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; } else { strncpy(bcc_ptr, domain, 64); bcc_ptr += strnlen(domain, 64); *bcc_ptr = 0; bcc_ptr++; } 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, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; } count = (long) bcc_ptr - (long) pByteArea(smb_buffer); smb_buffer->smb_buf_length += count; pSMB->req.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &bytes_returned, 1); if (rc) { /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ } else if ((smb_buffer_response->WordCount == 3) || (smb_buffer_response->WordCount == 4)) { __u16 action = le16_to_cpu(pSMBr->resp.Action); __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); if (action & GUEST_LOGIN) cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ if (ses) { ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ cFYI(1, ("UID = %d ", ses->Suid)); bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */ /* BB Fix below to make endian neutral !! */ if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) && (blob_len < pSMBr->resp.ByteCount))) { if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += blob_len; cFYI(1, ("Security Blob Length %d ", blob_len)); } if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { if ((long) (bcc_ptr) % 2) { remaining_words = (BCC(smb_buffer_response) - 1) / 2; bcc_ptr++; /* Unicode strings must be word aligned */ } else { remaining_words = BCC (smb_buffer_response) / 2; } len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words - 1); /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ if(ses->serverOS) kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (__le16 *) bcc_ptr, len, nls_codepage); bcc_ptr += 2 * (len + 1); remaining_words -= len + 1; ses->serverOS[2 * len] = 0; ses->serverOS[1 + (2 * len)] = 0; if (remaining_words > 0) { len = UniStrnlen((wchar_t *)bcc_ptr, remaining_words - 1); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverNOS, (__le16 *)bcc_ptr, len, nls_codepage); bcc_ptr += 2 * (len + 1); ses->serverNOS[2 * len] = 0; ses->serverNOS[1 + (2 * len)] = 0; remaining_words -= len + 1; if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string not null terminated (e.g.Windows XP/2000) */ if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); cifs_strfromUCS_le(ses->serverDomain, (__le16 *)bcc_ptr, len, nls_codepage); bcc_ptr += 2*(len+1); ses->serverDomain[2*len] = 0; ses->serverDomain[1+(2*len)] = 0; } /* else no more room so create dummy domain string */ else { if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2,GFP_KERNEL); } } else {/* no room use dummy domain&NOS */ if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { if(ses->serverOS) kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; /* null terminate the string */ bcc_ptr++; len = strnlen(bcc_ptr, 1024); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; } else cFYI(1, ("Variable field of length %d extends beyond end of smb ", len)); } } else { cERROR(1, (" Security Blob Length extends beyond end of SMB")); } } else { cERROR(1, ("No session structure passed in.")); } } else { cERROR(1, (" Invalid Word count %d: ", smb_buffer_response->WordCount)); rc = -EIO; } if (smb_buffer) cifs_buf_release(smb_buffer); return rc; } static int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, struct cifsSesInfo *ses, int * pNTLMv2_flag, Loading Loading @@ -3550,20 +3265,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, pSesInfo->server->secMode, pSesInfo->server->capabilities, pSesInfo->server->timeZone)); #ifdef CONFIG_CIFS_EXPERIMENTAL if(experimEnabled > 1) if(experimEnabled < 2) rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); else #endif if (extended_security else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == NTLMSSP)) { cFYI(1, ("New style sesssetup")); rc = CIFSSpnegoSessSetup(xid, pSesInfo, NULL /* security blob */, 0 /* blob length */, nls_info); rc = -EOPNOTSUPP; } else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == RawNTLMSSP)) { Loading fs/cifs/sess.c +2 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -319,7 +317,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, __u32 capabilities; int count; int resp_buf_type = 0; struct kvec iov[1]; struct kvec iov[2]; /* BB split variable length info into 2nd iovec */ enum securityEnum type; __u16 action; int bytes_remaining; Loading Loading @@ -525,4 +523,3 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, return rc; } #endif /* CONFIG_CIFS_EXPERIMENTAL */ Loading
fs/cifs/README +2 −0 Original line number Diff line number Diff line Loading @@ -453,6 +453,8 @@ sec Security mode. Allowed values are: server requires signing also can be the default) ntlmv2 Use NTLMv2 password hashing ntlmv2i Use NTLMv2 password hashing with packet signing lanman (if configured in kernel config) use older lanman hash The mount.cifs mount helper also accepts a few mount options before -o including: Loading
fs/cifs/cifsproto.h +1 −1 Original line number Diff line number Diff line Loading @@ -68,10 +68,10 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , extern int small_smb_init_no_tc(const int smb_cmd, const int wct, struct cifsSesInfo *ses, void ** request_buf); #endif extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int stage, const struct nls_table *nls_cp); #endif extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); Loading
fs/cifs/connect.c +23 −315 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ struct smb_vol { gid_t linux_gid; mode_t file_mode; mode_t dir_mode; unsigned secFlg; unsigned rw:1; unsigned retry:1; unsigned intr:1; Loading @@ -81,12 +82,7 @@ struct smb_vol { unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ unsigned sfu_emul:1; unsigned krb5:1; unsigned ntlm:1; unsigned ntlmv2:1; unsigned nullauth:1; /* attempt to authenticate with null user */ unsigned sign:1; unsigned seal:1; /* encrypt */ unsigned nocase; /* request case insensitive filenames */ unsigned nobrl; /* disable sending byte range locks to srv */ unsigned int rsize; Loading Loading @@ -789,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ vol->rw = TRUE; vol->ntlm = TRUE; /* default is always to request posix paths. */ vol->posix_paths = 1; Loading Loading @@ -920,28 +915,33 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) cERROR(1,("no security value specified")); continue; } else if (strnicmp(value, "krb5i", 5) == 0) { vol->sign = 1; vol->krb5 = 1; vol->secFlg = CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "krb5p", 5) == 0) { /* vol->seal = 1; vol->krb5 = 1; */ /* vol->secFlg = CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ cERROR(1,("Krb5 cifs privacy not supported")); return 1; } else if (strnicmp(value, "krb5", 4) == 0) { vol->krb5 = 1; vol->secFlg = CIFSSEC_MAY_KRB5; } else if (strnicmp(value, "ntlmv2i", 7) == 0) { vol->ntlmv2 = 1; vol->sign = 1; vol->secFlg = CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "ntlmv2", 6) == 0) { vol->ntlmv2 = 1; vol->secFlg = CIFSSEC_MAY_NTLMV2; } else if (strnicmp(value, "ntlmi", 5) == 0) { vol->ntlm = 1; vol->sign = 1; vol->secFlg = CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; } else if (strnicmp(value, "ntlm", 4) == 0) { /* ntlm is default so can be turned off too */ vol->ntlm = 1; vol->secFlg = CIFSSEC_MAY_NTLM; } else if (strnicmp(value, "nontlm", 6) == 0) { vol->ntlm = 0; /* BB is there a better way to do this? */ vol->secFlg = CIFSSEC_MAY_NTLMV2; #ifdef CONFIG_CIFS_WEAK_PW_HASH } else if (strnicmp(value, "lanman", 6) == 0) { vol->secFlg = CIFSSEC_MAY_LANMAN; #endif } else if (strnicmp(value, "none", 4) == 0) { vol->nullauth = 1; } else { Loading Loading @@ -1777,6 +1777,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } pSesInfo->linux_uid = volume_info.linux_uid; down(&pSesInfo->sesSem); /* BB FIXME need to pass vol->secFlgs BB */ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); up(&pSesInfo->sesSem); if(!rc) Loading Loading @@ -2283,292 +2284,6 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, return rc; } static int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *SecurityBlob,int SecurityBlobLength, const struct nls_table *nls_codepage) { struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer_response; SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; char *user; char *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; __u32 capabilities; __u16 count; cFYI(1, ("In spnego sesssetup ")); if(ses == NULL) return -EINVAL; user = ses->userName; domain = ses->domainName; smb_buffer = cifs_buf_get(); if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; if(ses->server->maxBuf > 64*1024) ses->server->maxBuf = (64*1023); pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_EXTENDED_SECURITY; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; capabilities |= CAP_DFS; } pSMB->req.Capabilities = cpu_to_le32(capabilities); pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); bcc_ptr = pByteArea(smb_buffer); memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength); bcc_ptr += SecurityBlobLength; if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */ *bcc_ptr = 0; bcc_ptr++; } bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage); bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */ bcc_ptr += 2; /* trailing null */ if (domain == NULL) bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, "CIFS_LINUX_DOM", 32, nls_codepage); else bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 64, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; } else { strncpy(bcc_ptr, user, 200); bcc_ptr += strnlen(user, 200); *bcc_ptr = 0; bcc_ptr++; if (domain == NULL) { strcpy(bcc_ptr, "CIFS_LINUX_DOM"); bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; } else { strncpy(bcc_ptr, domain, 64); bcc_ptr += strnlen(domain, 64); *bcc_ptr = 0; bcc_ptr++; } 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, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; } count = (long) bcc_ptr - (long) pByteArea(smb_buffer); smb_buffer->smb_buf_length += count; pSMB->req.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &bytes_returned, 1); if (rc) { /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ } else if ((smb_buffer_response->WordCount == 3) || (smb_buffer_response->WordCount == 4)) { __u16 action = le16_to_cpu(pSMBr->resp.Action); __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); if (action & GUEST_LOGIN) cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ if (ses) { ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ cFYI(1, ("UID = %d ", ses->Suid)); bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */ /* BB Fix below to make endian neutral !! */ if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) && (blob_len < pSMBr->resp.ByteCount))) { if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += blob_len; cFYI(1, ("Security Blob Length %d ", blob_len)); } if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { if ((long) (bcc_ptr) % 2) { remaining_words = (BCC(smb_buffer_response) - 1) / 2; bcc_ptr++; /* Unicode strings must be word aligned */ } else { remaining_words = BCC (smb_buffer_response) / 2; } len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words - 1); /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ if(ses->serverOS) kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (__le16 *) bcc_ptr, len, nls_codepage); bcc_ptr += 2 * (len + 1); remaining_words -= len + 1; ses->serverOS[2 * len] = 0; ses->serverOS[1 + (2 * len)] = 0; if (remaining_words > 0) { len = UniStrnlen((wchar_t *)bcc_ptr, remaining_words - 1); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverNOS, (__le16 *)bcc_ptr, len, nls_codepage); bcc_ptr += 2 * (len + 1); ses->serverNOS[2 * len] = 0; ses->serverNOS[1 + (2 * len)] = 0; remaining_words -= len + 1; if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string not null terminated (e.g.Windows XP/2000) */ if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); cifs_strfromUCS_le(ses->serverDomain, (__le16 *)bcc_ptr, len, nls_codepage); bcc_ptr += 2*(len+1); ses->serverDomain[2*len] = 0; ses->serverDomain[1+(2*len)] = 0; } /* else no more room so create dummy domain string */ else { if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2,GFP_KERNEL); } } else {/* no room use dummy domain&NOS */ if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { if(ses->serverOS) kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; /* null terminate the string */ bcc_ptr++; len = strnlen(bcc_ptr, 1024); if(ses->serverNOS) kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); if(ses->serverDomain) kfree(ses->serverDomain); ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; } else cFYI(1, ("Variable field of length %d extends beyond end of smb ", len)); } } else { cERROR(1, (" Security Blob Length extends beyond end of SMB")); } } else { cERROR(1, ("No session structure passed in.")); } } else { cERROR(1, (" Invalid Word count %d: ", smb_buffer_response->WordCount)); rc = -EIO; } if (smb_buffer) cifs_buf_release(smb_buffer); return rc; } static int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, struct cifsSesInfo *ses, int * pNTLMv2_flag, Loading Loading @@ -3550,20 +3265,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, pSesInfo->server->secMode, pSesInfo->server->capabilities, pSesInfo->server->timeZone)); #ifdef CONFIG_CIFS_EXPERIMENTAL if(experimEnabled > 1) if(experimEnabled < 2) rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); else #endif if (extended_security else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == NTLMSSP)) { cFYI(1, ("New style sesssetup")); rc = CIFSSpnegoSessSetup(xid, pSesInfo, NULL /* security blob */, 0 /* blob length */, nls_info); rc = -EOPNOTSUPP; } else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == RawNTLMSSP)) { Loading
fs/cifs/sess.c +2 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -319,7 +317,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, __u32 capabilities; int count; int resp_buf_type = 0; struct kvec iov[1]; struct kvec iov[2]; /* BB split variable length info into 2nd iovec */ enum securityEnum type; __u16 action; int bytes_remaining; Loading Loading @@ -525,4 +523,3 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, return rc; } #endif /* CONFIG_CIFS_EXPERIMENTAL */