|
@@ -49,8 +49,6 @@
|
|
|
|
|
|
static DECLARE_COMPLETION(cifsd_complete);
|
|
|
|
|
|
-extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
|
|
- unsigned char *p24);
|
|
|
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
|
|
|
unsigned char *p24);
|
|
|
|
|
@@ -70,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;
|
|
@@ -83,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;
|
|
@@ -369,21 +363,21 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|
|
continue;
|
|
|
if (bigbuf == NULL) {
|
|
|
bigbuf = cifs_buf_get();
|
|
|
- if(bigbuf == NULL) {
|
|
|
- cERROR(1,("No memory for large SMB response"));
|
|
|
+ if (!bigbuf) {
|
|
|
+ cERROR(1, ("No memory for large SMB response"));
|
|
|
msleep(3000);
|
|
|
/* retry will check if exiting */
|
|
|
continue;
|
|
|
}
|
|
|
- } else if(isLargeBuf) {
|
|
|
- /* we are reusing a dirtry large buf, clear its start */
|
|
|
+ } else if (isLargeBuf) {
|
|
|
+ /* we are reusing a dirty large buf, clear its start */
|
|
|
memset(bigbuf, 0, sizeof (struct smb_hdr));
|
|
|
}
|
|
|
|
|
|
if (smallbuf == NULL) {
|
|
|
smallbuf = cifs_small_buf_get();
|
|
|
- if(smallbuf == NULL) {
|
|
|
- cERROR(1,("No memory for SMB response"));
|
|
|
+ if (!smallbuf) {
|
|
|
+ cERROR(1, ("No memory for SMB response"));
|
|
|
msleep(1000);
|
|
|
/* retry will check if exiting */
|
|
|
continue;
|
|
@@ -403,12 +397,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|
|
kernel_recvmsg(csocket, &smb_msg,
|
|
|
&iov, 1, 4, 0 /* BB see socket.h flags */);
|
|
|
|
|
|
- if(server->tcpStatus == CifsExiting) {
|
|
|
+ if (server->tcpStatus == CifsExiting) {
|
|
|
break;
|
|
|
} else if (server->tcpStatus == CifsNeedReconnect) {
|
|
|
- cFYI(1,("Reconnect after server stopped responding"));
|
|
|
+ cFYI(1, ("Reconnect after server stopped responding"));
|
|
|
cifs_reconnect(server);
|
|
|
- cFYI(1,("call to reconnect done"));
|
|
|
+ cFYI(1, ("call to reconnect done"));
|
|
|
csocket = server->ssocket;
|
|
|
continue;
|
|
|
} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
|
|
@@ -417,15 +411,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|
|
tcpStatus CifsNeedReconnect if server hung */
|
|
|
continue;
|
|
|
} else if (length <= 0) {
|
|
|
- if(server->tcpStatus == CifsNew) {
|
|
|
- cFYI(1,("tcp session abend after SMBnegprot"));
|
|
|
+ if (server->tcpStatus == CifsNew) {
|
|
|
+ cFYI(1, ("tcp session abend after SMBnegprot"));
|
|
|
/* some servers kill the TCP session rather than
|
|
|
returning an SMB negprot error, in which
|
|
|
case reconnecting here is not going to help,
|
|
|
and so simply return error to mount */
|
|
|
break;
|
|
|
}
|
|
|
- if(length == -EINTR) {
|
|
|
+ if (!try_to_freeze() && (length == -EINTR)) {
|
|
|
cFYI(1,("cifsd thread killed"));
|
|
|
break;
|
|
|
}
|
|
@@ -585,9 +579,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|
|
/* merge response - fix up 1st*/
|
|
|
if(coalesce_t2(smb_buffer,
|
|
|
mid_entry->resp_buf)) {
|
|
|
+ mid_entry->multiRsp = 1;
|
|
|
break;
|
|
|
} else {
|
|
|
/* all parts received */
|
|
|
+ mid_entry->multiEnd = 1;
|
|
|
goto multi_t2_fnd;
|
|
|
}
|
|
|
} else {
|
|
@@ -632,9 +628,14 @@ multi_t2_fnd:
|
|
|
wake_up_process(task_to_wake);
|
|
|
} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
|
|
|
&& (isMultiRsp == FALSE)) {
|
|
|
- cERROR(1, ("No task to wake, unknown frame rcvd!"));
|
|
|
+ cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
|
|
|
cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
|
|
|
sizeof(struct smb_hdr));
|
|
|
+#ifdef CONFIG_CIFS_DEBUG2
|
|
|
+ cifs_dump_detail(smb_buffer);
|
|
|
+ cifs_dump_mids(server);
|
|
|
+#endif /* CIFS_DEBUG2 */
|
|
|
+
|
|
|
}
|
|
|
} /* end while !EXITING */
|
|
|
|
|
@@ -784,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;
|
|
|
|
|
@@ -915,30 +915,35 @@ 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;
|
|
|
+ vol->nullauth = 1;
|
|
|
} else {
|
|
|
cERROR(1,("bad security option: %s", value));
|
|
|
return 1;
|
|
@@ -976,7 +981,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
|
|
}
|
|
|
/* BB are there cases in which a comma can be valid in
|
|
|
a domain name and need special handling? */
|
|
|
- if (strnlen(value, 65) < 65) {
|
|
|
+ if (strnlen(value, 256) < 256) {
|
|
|
vol->domainname = value;
|
|
|
cFYI(1, ("Domain name set"));
|
|
|
} else {
|
|
@@ -1168,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
|
|
vol->no_psx_acl = 0;
|
|
|
} else if (strnicmp(data, "noacl",5) == 0) {
|
|
|
vol->no_psx_acl = 1;
|
|
|
+ } else if (strnicmp(data, "sign",4) == 0) {
|
|
|
+ vol->secFlg |= CIFSSEC_MUST_SIGN;
|
|
|
+/* } else if (strnicmp(data, "seal",4) == 0) {
|
|
|
+ vol->secFlg |= CIFSSEC_MUST_SEAL; */
|
|
|
} else if (strnicmp(data, "direct",6) == 0) {
|
|
|
vol->direct_io = 1;
|
|
|
} else if (strnicmp(data, "forcedirectio",13) == 0) {
|
|
@@ -1762,11 +1771,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
if (volume_info.username)
|
|
|
strncpy(pSesInfo->userName,
|
|
|
volume_info.username,MAX_USERNAME_SIZE);
|
|
|
- if (volume_info.domainname)
|
|
|
- strncpy(pSesInfo->domainName,
|
|
|
- volume_info.domainname,MAX_USERNAME_SIZE);
|
|
|
+ if (volume_info.domainname) {
|
|
|
+ int len = strlen(volume_info.domainname);
|
|
|
+ pSesInfo->domainName =
|
|
|
+ kmalloc(len + 1, GFP_KERNEL);
|
|
|
+ if(pSesInfo->domainName)
|
|
|
+ strcpy(pSesInfo->domainName,
|
|
|
+ volume_info.domainname);
|
|
|
+ }
|
|
|
pSesInfo->linux_uid = volume_info.linux_uid;
|
|
|
+ pSesInfo->overrideSecFlg = volume_info.secFlg;
|
|
|
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)
|
|
@@ -1980,7 +1996,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|
|
|
|
|
static int
|
|
|
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
- char session_key[CIFS_SESSION_KEY_SIZE],
|
|
|
+ char session_key[CIFS_SESS_KEY_SIZE],
|
|
|
const struct nls_table *nls_codepage)
|
|
|
{
|
|
|
struct smb_hdr *smb_buffer;
|
|
@@ -2038,15 +2054,15 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
|
|
|
|
|
|
pSMB->req_no_secext.CaseInsensitivePasswordLength =
|
|
|
- cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
|
|
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
|
|
|
|
|
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
|
|
- cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
|
|
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
|
|
bcc_ptr = pByteArea(smb_buffer);
|
|
|
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
|
|
|
- bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
|
|
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
|
|
|
- bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
|
|
+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
|
|
|
+ bcc_ptr += CIFS_SESS_KEY_SIZE;
|
|
|
+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
|
|
|
+ bcc_ptr += CIFS_SESS_KEY_SIZE;
|
|
|
|
|
|
if (ses->capabilities & CAP_UNICODE) {
|
|
|
if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
|
|
@@ -2054,7 +2070,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
bcc_ptr++;
|
|
|
}
|
|
|
if(user == NULL)
|
|
|
- bytes_returned = 0; /* skill null user */
|
|
|
+ bytes_returned = 0; /* skip null user */
|
|
|
else
|
|
|
bytes_returned =
|
|
|
cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
|
|
@@ -2162,8 +2178,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
if (remaining_words > 0) {
|
|
|
len = UniStrnlen((wchar_t *)bcc_ptr,
|
|
|
remaining_words-1);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
|
|
|
if(ses->serverNOS == NULL)
|
|
|
goto sesssetup_nomem;
|
|
@@ -2203,12 +2218,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
/* if these kcallocs fail not much we
|
|
|
can do, but better to not fail the
|
|
|
sesssetup itself */
|
|
|
- if(ses->serverDomain)
|
|
|
- kfree(ses->serverDomain);
|
|
|
+ kfree(ses->serverDomain);
|
|
|
ses->serverDomain =
|
|
|
kzalloc(2, GFP_KERNEL);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS =
|
|
|
kzalloc(2, GFP_KERNEL);
|
|
|
}
|
|
@@ -2217,8 +2230,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
if (((long) bcc_ptr + len) - (long)
|
|
|
pByteArea(smb_buffer_response)
|
|
|
<= BCC(smb_buffer_response)) {
|
|
|
- if(ses->serverOS)
|
|
|
- kfree(ses->serverOS);
|
|
|
+ kfree(ses->serverOS);
|
|
|
ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
|
|
|
if(ses->serverOS == NULL)
|
|
|
goto sesssetup_nomem;
|
|
@@ -2229,8 +2241,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
bcc_ptr++;
|
|
|
|
|
|
len = strnlen(bcc_ptr, 1024);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
|
|
|
if(ses->serverNOS == NULL)
|
|
|
goto sesssetup_nomem;
|
|
@@ -2273,292 +2284,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings,
|
|
|
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,
|
|
@@ -2635,8 +2360,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
|
|
|
if(sign_CIFS_PDUs)
|
|
|
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
|
- if(ntlmv2_support)
|
|
|
- negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
|
|
|
+/* if(ntlmv2_support)
|
|
|
+ negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
|
|
|
/* setup pointers to domain name and workstation name */
|
|
|
bcc_ptr += SecurityBlobLength;
|
|
|
|
|
@@ -2783,8 +2508,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
bcc_ptr,
|
|
|
remaining_words
|
|
|
- 1);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS =
|
|
|
kzalloc(2 * (len + 1),
|
|
|
GFP_KERNEL);
|
|
@@ -2802,8 +2526,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
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) */
|
|
|
- if(ses->serverDomain)
|
|
|
- kfree(ses->serverDomain);
|
|
|
+ kfree(ses->serverDomain);
|
|
|
ses->serverDomain =
|
|
|
kzalloc(2 *
|
|
|
(len +
|
|
@@ -2822,19 +2545,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
= 0;
|
|
|
} /* else no more room so create dummy domain string */
|
|
|
else {
|
|
|
- if(ses->serverDomain)
|
|
|
- kfree(ses->serverDomain);
|
|
|
+ kfree(ses->serverDomain);
|
|
|
ses->serverDomain =
|
|
|
kzalloc(2,
|
|
|
GFP_KERNEL);
|
|
|
}
|
|
|
} else { /* no room so create dummy domain and NOS string */
|
|
|
- if(ses->serverDomain);
|
|
|
- kfree(ses->serverDomain);
|
|
|
+ kfree(ses->serverDomain);
|
|
|
ses->serverDomain =
|
|
|
kzalloc(2, GFP_KERNEL);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS =
|
|
|
kzalloc(2, GFP_KERNEL);
|
|
|
}
|
|
@@ -2856,8 +2576,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
bcc_ptr++;
|
|
|
|
|
|
len = strnlen(bcc_ptr, 1024);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS =
|
|
|
kzalloc(len + 1,
|
|
|
GFP_KERNEL);
|
|
@@ -2867,8 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|
|
bcc_ptr++;
|
|
|
|
|
|
len = strnlen(bcc_ptr, 1024);
|
|
|
- if(ses->serverDomain)
|
|
|
- kfree(ses->serverDomain);
|
|
|
+ kfree(ses->serverDomain);
|
|
|
ses->serverDomain =
|
|
|
kzalloc(len + 1,
|
|
|
GFP_KERNEL);
|
|
@@ -2994,14 +2712,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
SecurityBlob->LmChallengeResponse.Buffer = 0;
|
|
|
|
|
|
SecurityBlob->NtChallengeResponse.Length =
|
|
|
- cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
|
|
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
|
|
SecurityBlob->NtChallengeResponse.MaximumLength =
|
|
|
- cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
|
|
- memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
|
|
|
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
|
|
+ memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
|
|
|
SecurityBlob->NtChallengeResponse.Buffer =
|
|
|
cpu_to_le32(SecurityBlobLength);
|
|
|
- SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
|
|
|
- bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
|
|
+ SecurityBlobLength += CIFS_SESS_KEY_SIZE;
|
|
|
+ bcc_ptr += CIFS_SESS_KEY_SIZE;
|
|
|
|
|
|
if (ses->capabilities & CAP_UNICODE) {
|
|
|
if (domain == NULL) {
|
|
@@ -3190,8 +2908,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
bcc_ptr,
|
|
|
remaining_words
|
|
|
- 1);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS =
|
|
|
kzalloc(2 * (len + 1),
|
|
|
GFP_KERNEL);
|
|
@@ -3244,8 +2961,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
if(ses->serverDomain)
|
|
|
kfree(ses->serverDomain);
|
|
|
ses->serverDomain = kzalloc(2, GFP_KERNEL);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS = kzalloc(2, GFP_KERNEL);
|
|
|
}
|
|
|
} else { /* ASCII */
|
|
@@ -3263,8 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
bcc_ptr++;
|
|
|
|
|
|
len = strnlen(bcc_ptr, 1024);
|
|
|
- if(ses->serverNOS)
|
|
|
- kfree(ses->serverNOS);
|
|
|
+ kfree(ses->serverNOS);
|
|
|
ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
|
|
|
strncpy(ses->serverNOS, bcc_ptr, len);
|
|
|
bcc_ptr += len;
|
|
@@ -3340,22 +3055,33 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
bcc_ptr = &pSMB->Password[0];
|
|
|
if((ses->server->secMode) & SECMODE_USER) {
|
|
|
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
|
|
|
+ *bcc_ptr = 0; /* password is null byte */
|
|
|
bcc_ptr++; /* skip password */
|
|
|
+ /* already aligned so no need to do it below */
|
|
|
} else {
|
|
|
- pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
|
|
+ pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
|
|
/* BB FIXME add code to fail this if NTLMv2 or Kerberos
|
|
|
specified as required (when that support is added to
|
|
|
the vfs in the future) as only NTLM or the much
|
|
|
- weaker LANMAN (which we do not send) is accepted
|
|
|
+ weaker LANMAN (which we do not send by default) is accepted
|
|
|
by Samba (not sure whether other servers allow
|
|
|
NTLMv2 password here) */
|
|
|
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
|
|
+ if((extended_security & CIFSSEC_MAY_LANMAN) &&
|
|
|
+ (ses->server->secType == LANMAN))
|
|
|
+ calc_lanman_hash(ses, bcc_ptr);
|
|
|
+ else
|
|
|
+#endif /* CIFS_WEAK_PW_HASH */
|
|
|
SMBNTencrypt(ses->password,
|
|
|
ses->server->cryptKey,
|
|
|
bcc_ptr);
|
|
|
|
|
|
- bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
|
|
- *bcc_ptr = 0;
|
|
|
- bcc_ptr++; /* align */
|
|
|
+ bcc_ptr += CIFS_SESS_KEY_SIZE;
|
|
|
+ if(ses->capabilities & CAP_UNICODE) {
|
|
|
+ /* must align unicode strings */
|
|
|
+ *bcc_ptr = 0; /* null byte password */
|
|
|
+ bcc_ptr++;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if(ses->server->secMode &
|
|
@@ -3429,7 +3155,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|
|
}
|
|
|
/* else do not bother copying these informational fields */
|
|
|
}
|
|
|
- tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
|
|
|
+ if(smb_buffer_response->WordCount == 3)
|
|
|
+ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
|
|
|
+ else
|
|
|
+ tcon->Flags = 0;
|
|
|
cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
|
|
|
} else if ((rc == 0) && tcon == NULL) {
|
|
|
/* all we need to save for IPC$ connection */
|
|
@@ -3494,7 +3223,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
|
|
struct nls_table * nls_info)
|
|
|
{
|
|
|
int rc = 0;
|
|
|
- char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
|
|
|
+ char ntlm_session_key[CIFS_SESS_KEY_SIZE];
|
|
|
int ntlmv2_flag = FALSE;
|
|
|
int first_time = 0;
|
|
|
|
|
@@ -3526,20 +3255,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)
|
|
|
- rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
|
|
|
- &ntlmv2_flag, nls_info);
|
|
|
- else
|
|
|
-#endif
|
|
|
- if (extended_security
|
|
|
+ if(experimEnabled < 2)
|
|
|
+ rc = CIFS_SessSetup(xid, pSesInfo,
|
|
|
+ first_time, nls_info);
|
|
|
+ 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)) {
|