X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcifs%2Fconnect.c;h=e548bb3cf2e3df20c93156bf531924a520d11233;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=bb6b0f3b2fb205621e217363bdc95e7e51360cfb;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bb6b0f3b2..e548bb3cf 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -64,11 +64,11 @@ struct smb_vol { gid_t linux_gid; mode_t file_mode; mode_t dir_mode; - int rw:1; - int retry:1; - int intr:1; - int setuids:1; - int noperm:1; + unsigned rw:1; + unsigned retry:1; + unsigned intr:1; + unsigned setuids:1; + unsigned noperm:1; unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -313,7 +313,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) connected to port 139 (the NACK is since we do not begin with RFC1001 session initialize frame) */ - server->addr.sockAddr.sin_port = CIFS_PORT; + server->addr.sockAddr.sin_port = htons(CIFS_PORT); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); @@ -814,19 +814,23 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol } static struct cifsSesInfo * -cifs_find_tcp_session(__u32 new_target_ip_addr, +cifs_find_tcp_session(struct in_addr * target_ip_addr, + struct in6_addr *target_ip6_addr, char *userName, struct TCP_Server_Info **psrvTcp) { struct list_head *tmp; struct cifsSesInfo *ses; - *psrvTcp = NULL; read_lock(&GlobalSMBSeslock); + list_for_each(tmp, &GlobalSMBSessionList) { ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); if (ses->server) { - if (ses->server->addr.sockAddr.sin_addr.s_addr == - new_target_ip_addr) { + if((target_ip_addr && + (ses->server->addr.sockAddr.sin_addr.s_addr + == target_ip_addr->s_addr)) || (target_ip6_addr + && memcmp(&ses->server->addr.sockAddr6.sin6_addr, + target_ip6_addr,sizeof(*target_ip6_addr)))){ /* BB lock server and tcp session and increment use count here?? */ *psrvTcp = ses->server; /* found a match on the TCP session */ /* BB check if reconnection needed */ @@ -845,7 +849,7 @@ cifs_find_tcp_session(__u32 new_target_ip_addr, } static struct cifsTconInfo * -find_unc(__u32 new_target_ip_addr, char *uncName, char *userName) +find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) { struct list_head *tmp; struct cifsTconInfo *tcon; @@ -964,7 +968,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, { int rc = 0; int connected = 0; - unsigned short int orig_port = 0; + __be16 orig_port = 0; if(*csocket == NULL) { rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket); @@ -1029,7 +1033,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, /* send RFC1001 sessinit */ - if(psin_server->sin_port == htons(139)) { + if(psin_server->sin_port == htons(RFC1001_PORT)) { /* some servers require RFC1001 sessinit before sending negprot - BB check reconnection in case where second sessinit is sent but no second negprot */ @@ -1072,6 +1076,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) { int rc = 0; int connected = 0; + __be16 orig_port = 0; if(*csocket == NULL) { rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket); @@ -1097,6 +1102,10 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) } if(!connected) { + /* save original port so we can retry user specified port + later if fall back ports fail this time */ + + orig_port = psin_server->sin6_port; /* do not retry on the same port we just failed on */ if(psin_server->sin6_port != htons(CIFS_PORT)) { psin_server->sin6_port = htons(CIFS_PORT); @@ -1119,6 +1128,8 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) /* give up here - unless we want to retry on different protocol families some day */ if (!connected) { + if(orig_port) + psin_server->sin6_port = orig_port; cFYI(1,("Error %d connecting to server via ipv6",rc)); sock_release(*csocket); *csocket = NULL; @@ -1138,6 +1149,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, { int rc = 0; int xid; + int address_type = AF_INET; struct socket *csocket = NULL; struct sockaddr_in sin_server; struct sockaddr_in6 sin_server6; @@ -1179,12 +1191,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (volume_info.UNCip && volume_info.UNC) { rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr); - if(rc == 0) { + if(rc <= 0) { /* not ipv4 address, try ipv6 */ rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); - } + if(rc > 0) + address_type = AF_INET6; + } else { + address_type = AF_INET; + } - if(rc != 1) { + if(rc <= 0) { /* we failed translating address */ if(volume_info.UNC) kfree(volume_info.UNC); @@ -1234,9 +1250,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } } - existingCifsSes = - cifs_find_tcp_session(sin_server.sin_addr.s_addr, - volume_info.username, &srvTcp); + if(address_type == AF_INET) + existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr, + NULL /* no ipv6 addr */, + volume_info.username, &srvTcp); + else if(address_type == AF_INET6) + existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, + &sin_server6.sin6_addr, + volume_info.username, &srvTcp); + else { + if(volume_info.UNC) + kfree(volume_info.UNC); + if(volume_info.password) + kfree(volume_info.password); + FreeXid(xid); + return -EINVAL; + } + + if (srvTcp) { cFYI(1, ("Existing tcp session with server found ")); } else { /* create socket */ @@ -1283,8 +1314,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, so no need to spinlock this init of tcpStatus */ srvTcp->tcpStatus = CifsNew; init_MUTEX(&srvTcp->tcpSem); - kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp, + rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp, CLONE_FS | CLONE_FILES | CLONE_VM); + if(rc < 0) { + rc = -ENOMEM; + sock_release(csocket); + if(volume_info.UNC) + kfree(volume_info.UNC); + if(volume_info.password) + kfree(volume_info.password); + FreeXid(xid); + return rc; + } else + rc = 0; memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); } } @@ -1464,15 +1506,20 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; - char *user = ses->userName; - char *domain = ses->domainName; + char *user; + char *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; + __u32 capabilities; + __u16 count; cFYI(1, ("In sesssetup ")); - + if(ses == NULL) + return -EINVAL; + user = ses->userName; + domain = ses->domainName; smb_buffer = cifs_buf_get(); if (smb_buffer == 0) { return -ENOMEM; @@ -1491,22 +1538,20 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - pSMB->req_no_secext.Capabilities = - CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS; + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; - pSMB->req_no_secext.Capabilities |= CAP_UNICODE; + capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - pSMB->req_no_secext.Capabilities |= CAP_STATUS32; + capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; - pSMB->req_no_secext.Capabilities |= CAP_DFS; + capabilities |= CAP_DFS; } - pSMB->req_no_secext.Capabilities = - cpu_to_le32(pSMB->req_no_secext.Capabilities); + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); /* pSMB->req_no_secext.CaseInsensitivePasswordLength = CIFS_SESSION_KEY_SIZE; */ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; @@ -1578,9 +1623,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; } - BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += BCC(smb_buffer); - BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); + count = (long) bcc_ptr - (long) pByteArea(smb_buffer); + smb_buffer->smb_buf_length += count; + pSMB->req_no_secext.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &bytes_returned, 1); @@ -1588,114 +1633,106 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ } else if ((smb_buffer_response->WordCount == 3) || (smb_buffer_response->WordCount == 4)) { - pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); - if (pSMBr->resp.Action & GUEST_LOGIN) + __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")); /* do we want to mark SesInfo struct ? */ - if (ses) { - ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */ - cFYI(1, ("UID = %d ", ses->Suid)); + ses->Suid = smb_buffer_response->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 */ - bcc_ptr = pByteArea(smb_buffer_response); - if ((pSMBr->resp.hdr.WordCount == 3) - || ((pSMBr->resp.hdr.WordCount == 4) - && (pSMBr->resp.SecurityBlobLength < - pSMBr->resp.ByteCount))) { - if (pSMBr->resp.hdr.WordCount == 4) - bcc_ptr += - pSMBr->resp.SecurityBlobLength; - - 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); + bcc_ptr = pByteArea(smb_buffer_response); + 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; + + 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); + 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; - 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); + 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) + 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); + 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++; + 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->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")); + 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, ("No session structure passed in.")); + cERROR(1, + (" Security Blob Length extends beyond end of SMB")); } } else { cERROR(1, @@ -1720,14 +1757,20 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; - char *user = ses->userName; - char *domain = ses->domainName; + 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) { @@ -1747,22 +1790,21 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - pSMB->req.Capabilities = - CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_EXTENDED_SECURITY; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; - pSMB->req.Capabilities |= CAP_UNICODE; + capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - pSMB->req.Capabilities |= CAP_STATUS32; + capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; - pSMB->req.Capabilities |= CAP_DFS; + capabilities |= CAP_DFS; } - pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); + pSMB->req.Capabilities = cpu_to_le32(capabilities); pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); bcc_ptr = pByteArea(smb_buffer); @@ -1823,9 +1865,9 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; } - BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += BCC(smb_buffer); - BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); + 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); @@ -1833,10 +1875,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* 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)) { - pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); - pSMBr->resp.SecurityBlobLength = + __u16 action = le16_to_cpu(pSMBr->resp.Action); + __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); - if (pSMBr->resp.Action & GUEST_LOGIN) + 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) */ @@ -1847,14 +1889,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) - && (pSMBr->resp.SecurityBlobLength < + && (blob_len < pSMBr->resp.ByteCount))) { if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += - pSMBr->resp.SecurityBlobLength; + blob_len; cFYI(1, ("Security Blob Length %d ", - pSMBr->resp.SecurityBlobLength)); + blob_len)); } if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { @@ -1979,7 +2021,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; - char *domain = ses->domainName; + char *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; @@ -1987,8 +2029,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 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) { @@ -2011,35 +2058,34 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - pSMB->req.Capabilities = - CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_EXTENDED_SECURITY; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; - pSMB->req.Capabilities |= CAP_UNICODE; + capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - pSMB->req.Capabilities |= CAP_STATUS32; + capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; - pSMB->req.Capabilities |= CAP_DFS; + capabilities |= CAP_DFS; } - pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); + 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; - SecurityBlob->NegotiateFlags = + 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) - SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; + negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; if(ntlmv2_support) - SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; + negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; /* setup pointers to domain name and workstation name */ bcc_ptr += SecurityBlobLength; @@ -2052,20 +2098,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { - SecurityBlob->NegotiateFlags |= - NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; + __u16 len; + negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; strncpy(bcc_ptr, domain, 63); - SecurityBlob->DomainName.Length = strnlen(domain, 64); + len = strnlen(domain, 64); SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(SecurityBlob->DomainName.Length); + cpu_to_le16(len); SecurityBlob->DomainName.Buffer = cpu_to_le32((long) &SecurityBlob-> DomainString - (long) &SecurityBlob->Signature); - bcc_ptr += SecurityBlob->DomainName.Length; - SecurityBlobLength += SecurityBlob->DomainName.Length; + bcc_ptr += len; + SecurityBlobLength += len; SecurityBlob->DomainName.Length = - cpu_to_le16(SecurityBlob->DomainName.Length); + cpu_to_le16(len); } if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { @@ -2102,28 +2148,27 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, bcc_ptr++; /* empty domain field */ *bcc_ptr = 0; } - SecurityBlob->NegotiateFlags = - cpu_to_le32(SecurityBlob->NegotiateFlags); + SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); - BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += BCC(smb_buffer); - BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); + 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 (smb_buffer_response->Status.CifsError == - (NT_STATUS_MORE_PROCESSING_REQUIRED)) + cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) rc = 0; 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)) { - pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); - pSMBr->resp.SecurityBlobLength = - le16_to_cpu(pSMBr->resp.SecurityBlobLength); - if (pSMBr->resp.Action & GUEST_LOGIN) + __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")); /* Do we want to set anything in SesInfo struct when guest login? */ @@ -2140,14 +2185,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, cFYI(1, ("UID = %d ", ses->Suid)); if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) - && (pSMBr->resp.SecurityBlobLength < + && (blob_len < pSMBr->resp.ByteCount))) { + if (pSMBr->resp.hdr.WordCount == 4) { - bcc_ptr += - pSMBr->resp.SecurityBlobLength; + bcc_ptr += blob_len; cFYI(1, ("Security Blob Length %d ", - pSMBr->resp.SecurityBlobLength)); + blob_len)); } cFYI(1, ("NTLMSSP Challenge rcvd ")); @@ -2155,16 +2200,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, memcpy(ses->server->cryptKey, SecurityBlob2->Challenge, CIFS_CRYPTO_KEY_SIZE); - if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2) + if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) *pNTLMv2_flag = TRUE; if((SecurityBlob2->NegotiateFlags & - NTLMSSP_NEGOTIATE_ALWAYS_SIGN) + cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) || (sign_CIFS_PDUs > 1)) ses->server->secMode |= SECMODE_SIGN_REQUIRED; if ((SecurityBlob2->NegotiateFlags & - NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs)) + cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs)) ses->server->secMode |= SECMODE_SIGN_ENABLED; @@ -2308,7 +2353,6 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, return rc; } - static int CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *ntlm_session_key, int ntlmv2_flag, @@ -2319,17 +2363,22 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB; SESSION_SETUP_ANDX *pSMBr; char *bcc_ptr; - char *user = ses->userName; - char *domain = ses->domainName; + char *user; + char *domain; int rc = 0; int remaining_words = 0; int bytes_returned = 0; int len; int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); PAUTHENTICATE_MESSAGE SecurityBlob; + __u32 negotiate_flags, capabilities; + __u16 count; cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); - + if(ses == NULL) + return -EINVAL; + user = ses->userName; + domain = ses->domainName; smb_buffer = cifs_buf_get(); if (smb_buffer == 0) { return -ENOMEM; @@ -2352,36 +2401,35 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - pSMB->req.Capabilities = - CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_EXTENDED_SECURITY; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; - pSMB->req.Capabilities |= CAP_UNICODE; + capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - pSMB->req.Capabilities |= CAP_STATUS32; + capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { smb_buffer->Flags2 |= SMBFLG2_DFS; - pSMB->req.Capabilities |= CAP_DFS; + capabilities |= CAP_DFS; } - pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities); + pSMB->req.Capabilities = cpu_to_le32(capabilities); bcc_ptr = (char *) &pSMB->req.SecurityBlob; SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); SecurityBlob->MessageType = NtLmAuthenticate; bcc_ptr += SecurityBlobLength; - SecurityBlob->NegotiateFlags = + negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | 0x80000000 | NTLMSSP_NEGOTIATE_128; if(sign_CIFS_PDUs) - SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; + negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; if(ntlmv2_flag) - SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2; + negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; /* setup pointers to domain name and workstation name */ @@ -2412,36 +2460,36 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { - SecurityBlob->DomainName.Length = + __u16 len = cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64, nls_codepage); - SecurityBlob->DomainName.Length *= 2; + len *= 2; SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(SecurityBlob->DomainName.Length); + cpu_to_le16(len); SecurityBlob->DomainName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += SecurityBlob->DomainName.Length; - SecurityBlobLength += SecurityBlob->DomainName.Length; + bcc_ptr += len; + SecurityBlobLength += len; SecurityBlob->DomainName.Length = - cpu_to_le16(SecurityBlob->DomainName.Length); + cpu_to_le16(len); } if (user == NULL) { SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.MaximumLength = 0; } else { - SecurityBlob->UserName.Length = + __u16 len = cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64, nls_codepage); - SecurityBlob->UserName.Length *= 2; + len *= 2; SecurityBlob->UserName.MaximumLength = - cpu_to_le16(SecurityBlob->UserName.Length); + cpu_to_le16(len); SecurityBlob->UserName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += SecurityBlob->UserName.Length; - SecurityBlobLength += SecurityBlob->UserName.Length; + bcc_ptr += len; + SecurityBlobLength += len; SecurityBlob->UserName.Length = - cpu_to_le16(SecurityBlob->UserName.Length); + cpu_to_le16(len); } /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage); @@ -2481,34 +2529,33 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.MaximumLength = 0; } else { - SecurityBlob->NegotiateFlags |= - NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; + __u16 len; + negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; strncpy(bcc_ptr, domain, 63); - SecurityBlob->DomainName.Length = strnlen(domain, 64); + len = strnlen(domain, 64); SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(SecurityBlob->DomainName.Length); + cpu_to_le16(len); SecurityBlob->DomainName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += SecurityBlob->DomainName.Length; - SecurityBlobLength += SecurityBlob->DomainName.Length; - SecurityBlob->DomainName.Length = - cpu_to_le16(SecurityBlob->DomainName.Length); + bcc_ptr += len; + SecurityBlobLength += len; + SecurityBlob->DomainName.Length = cpu_to_le16(len); } if (user == NULL) { SecurityBlob->UserName.Buffer = 0; SecurityBlob->UserName.Length = 0; SecurityBlob->UserName.MaximumLength = 0; } else { + __u16 len; strncpy(bcc_ptr, user, 63); - SecurityBlob->UserName.Length = strnlen(user, 64); + len = strnlen(user, 64); SecurityBlob->UserName.MaximumLength = - cpu_to_le16(SecurityBlob->UserName.Length); + cpu_to_le16(len); SecurityBlob->UserName.Buffer = cpu_to_le32(SecurityBlobLength); - bcc_ptr += SecurityBlob->UserName.Length; - SecurityBlobLength += SecurityBlob->UserName.Length; - SecurityBlob->UserName.Length = - cpu_to_le16(SecurityBlob->UserName.Length); + bcc_ptr += len; + SecurityBlobLength += len; + SecurityBlob->UserName.Length = cpu_to_le16(len); } /* BB fill in our workstation name if known BB */ @@ -2521,12 +2568,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr++; /* null domain */ *bcc_ptr = 0; } - SecurityBlob->NegotiateFlags = - cpu_to_le32(SecurityBlob->NegotiateFlags); + SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); - BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += BCC(smb_buffer); - BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); + 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); @@ -2534,10 +2580,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* 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)) { - pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action); - pSMBr->resp.SecurityBlobLength = + __u16 action = le16_to_cpu(pSMBr->resp.Action); + __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); - if (pSMBr->resp.Action & GUEST_LOGIN) + if (action & GUEST_LOGIN) cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */ /* if(SecurityBlob2->MessageType != NtLm??){ cFYI("Unexpected message type on auth response is %d ")); @@ -2551,14 +2597,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* response can have either 3 or 4 word count - Samba sends 3 */ if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) - && (pSMBr->resp.SecurityBlobLength < + && (blob_len < pSMBr->resp.ByteCount))) { if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += - pSMBr->resp.SecurityBlobLength; + blob_len; cFYI(1, ("Security Blob Length %d ", - pSMBr->resp.SecurityBlobLength)); + blob_len)); } cFYI(1, @@ -2699,9 +2745,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, struct smb_hdr *smb_buffer_response; TCONX_REQ *pSMB; TCONX_RSP *pSMBr; - char *bcc_ptr; + unsigned char *bcc_ptr; int rc = 0; int length; + __u16 count; if (ses == NULL) return -EIO; @@ -2721,7 +2768,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, pSMB->AndXCommand = 0xFF; pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ - bcc_ptr = &(pSMB->Password[0]); + bcc_ptr = &pSMB->Password[0]; bcc_ptr++; /* skip password */ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) @@ -2747,16 +2794,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, strcpy(bcc_ptr, "?????"); bcc_ptr += strlen("?????"); bcc_ptr += 1; - BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += BCC(smb_buffer); - BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer)); + count = bcc_ptr - &pSMB->Password[0]; + pSMB->hdr.smb_buf_length += count; + pSMB->ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ /* above now done in SendReceive */ if ((rc == 0) && (tcon != NULL)) { - tcon->tidStatus = CifsGood; + tcon->tidStatus = CifsGood; tcon->tid = smb_buffer_response->Tid; bcc_ptr = pByteArea(smb_buffer_response); length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); @@ -2765,8 +2812,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, strncpy(tcon->treeName, tree, MAX_TREE_SIZE); if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { length = UniStrnlen((wchar_t *) bcc_ptr, 512); - if (((long) bcc_ptr + (2 * length)) - - (long) pByteArea(smb_buffer_response) <= + if ((bcc_ptr + (2 * length)) - + pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { if(tcon->nativeFileSystem) kfree(tcon->nativeFileSystem); @@ -2783,8 +2830,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, /* else do not bother copying these informational fields */ } else { length = strnlen(bcc_ptr, 1024); - if (((long) bcc_ptr + length) - - (long) pByteArea(smb_buffer_response) <= + if ((bcc_ptr + length) - + pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { if(tcon->nativeFileSystem) kfree(tcon->nativeFileSystem);