📄 connect.c
字号:
strncpy(ses->serverOS,bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; /* null terminate the string */ bcc_ptr++; len = strnlen(bcc_ptr, 1024); ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); ses->serverDomain = cifs_kcalloc(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, (" Invalid Word count %d: ", smb_buffer_response->WordCount)); rc = -EIO; } if (smb_buffer) cifs_buf_release(smb_buffer); return rc;}static intCIFSSpnegoSessSetup(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 == 0) { 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 */ ); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; 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((wchar_t *) 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((wchar_t *) bcc_ptr, "CIFS_LINUX_DOM", 32, nls_codepage); else bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; bytes_returned = cifs_strtoUCS((wchar_t *) 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, UTS_RELEASE); bcc_ptr += strlen(UTS_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 */ ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (wchar_t *) 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); ses->serverNOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverNOS, (wchar_t *)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 is not always null terminated (for e.g. for Windows XP & 2000) */ ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); cifs_strfromUCS_le(ses->serverDomain, (wchar_t *)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 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); } else { /* no room so create dummy domain and NOS string */ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { ses->serverOS = cifs_kcalloc(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); ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); ses->serverDomain = cifs_kcalloc(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 intCIFSNTLMSSPNegotiateSessSetup(unsigned int xid, struct cifsSesInfo *ses, int * pNTLMv2_flag, 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 *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); PNEGOTIATE_MESSAGE SecurityBlob; PCHALLENGE_MESSAGE SecurityBlob2; __u32 negotiate_flags, capabilities; __u16 count; cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); if(ses == NULL) return -EINVAL; domain = ses->domainName; *pNTLMv2_flag = FALSE; smb_buffer = cifs_buf_get(); if (smb_buffer == 0) { return -ENOMEM; } smb_buffer_response = smb_buffer; pSMB = (SESSION_SETUP_ANDX *) smb_buffer; pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); pSMB->req.AndXCommand = 0xFF; 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); bcc_ptr = (char *) &pSMB->req.SecurityBlob; SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr; strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); SecurityBlob->MessageType = NtLmNegotiate; negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; if(sign_CIFS_PDUs) negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; if(ntlmv2_support) negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; /* setup pointers to domain name and workstation name */ bcc_ptr += SecurityBlobLength; SecurityBlob->WorkstationName.Buffer = 0; SecurityBlob->WorkstationName.Length = 0; SecurityBlob->WorkstationName.MaximumLength = 0; if (domain == NULL) { SecurityBlob->DomainName.Buffer = 0; SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { __u16 len; negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; strncpy(bcc_ptr, domain, 63); len = strnlen(domain, 64); SecurityBlob->DomainName.MaximumLength = cpu_to_le16(len); SecurityBlob->DomainName.Buffer = cpu_to_le32((long) &SecurityBlob-> DomainString - (long) &SecurityBlob->Signature); bcc_ptr += len; SecurityBlobLength += len; SecurityBlob->DomainName.Length = cpu_to_le16(len); } if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { *bcc_ptr = 0; bcc_ptr++; } bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ", 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32, nls_codepage); bcc_ptr += 2 * bytes_returned; bcc_ptr += 2; /* null terminate Linux version */ bytes_returned = cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -