[CIFS] Fix allocation of buffers for new session setup routine to allow
longer user and domain names and allow passing sec options on mount Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
124a27fe32
commit
750d1151a6
6 changed files with 58 additions and 36 deletions
|
@ -7,7 +7,8 @@ so we can do search (ls etc.) to OS/2. Do not send NTCreateX
|
|||
or recent levels of FindFirst unless server says it supports NT SMBs
|
||||
(instead use legacy equivalents from LANMAN dialect). Fix to allow
|
||||
NTLMv2 authentication support (now can use stronger password hashing
|
||||
on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004)
|
||||
on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
|
||||
Allow override of global cifs security flags on mount via "sec=" option(s).
|
||||
|
||||
Version 1.43
|
||||
------------
|
||||
|
|
|
@ -443,7 +443,10 @@ A partial list of the supported mount options follows:
|
|||
SFU does). In the future the bottom 9 bits of the mode
|
||||
mode also will be emulated using queries of the security
|
||||
descriptor (ACL).
|
||||
sec Security mode. Allowed values are:
|
||||
sign Must use packet signing (helps avoid unwanted data modification
|
||||
by intermediate systems in the route). Note that signing
|
||||
does not work with lanman or plaintext authentication.
|
||||
sec Security mode. Allowed values are:
|
||||
none attempt to connection as a null user (no name)
|
||||
krb5 Use Kerberos version 5 authentication
|
||||
krb5i Use Kerberos authentication and packet signing
|
||||
|
|
|
@ -186,6 +186,7 @@ struct cifsSesInfo {
|
|||
struct TCP_Server_Info *server; /* pointer to server info */
|
||||
atomic_t inUse; /* # of mounts (tree connections) on this ses */
|
||||
enum statusEnum status;
|
||||
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
||||
__u16 ipc_tid; /* special tid for connection to IPC share */
|
||||
__u16 flags;
|
||||
char *serverOS; /* name of operating system underlying server */
|
||||
|
|
|
@ -396,6 +396,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
int i;
|
||||
struct TCP_Server_Info * server;
|
||||
u16 count;
|
||||
unsigned int secFlags;
|
||||
|
||||
if(ses->server)
|
||||
server = ses->server;
|
||||
|
@ -407,9 +408,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
(void **) &pSMB, (void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* if any of auth flags (ie not sign or seal) are overriden use them */
|
||||
if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
|
||||
secFlags = ses->overrideSecFlg;
|
||||
else /* if override flags set only sign/seal OR them with global auth */
|
||||
secFlags = extended_security | ses->overrideSecFlg;
|
||||
|
||||
pSMB->hdr.Mid = GetNextMid(server);
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||
if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
||||
if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||
|
||||
count = 0;
|
||||
|
@ -439,8 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
&& (pSMBr->DialectIndex == LANMAN_PROT)) {
|
||||
struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
|
||||
|
||||
if((extended_security & CIFSSEC_MAY_LANMAN) ||
|
||||
(extended_security & CIFSSEC_MAY_PLNTXT))
|
||||
if((secFlags & CIFSSEC_MAY_LANMAN) ||
|
||||
(secFlags & CIFSSEC_MAY_PLNTXT))
|
||||
server->secType = LANMAN;
|
||||
else {
|
||||
cERROR(1, ("mount failed weak security disabled"
|
||||
|
@ -498,12 +506,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
|
||||
if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0)
|
||||
if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
|
||||
#endif /* CIFS_WEAK_PW_HASH */
|
||||
cERROR(1,("Server requests plain text password"
|
||||
" but client support disabled"));
|
||||
|
||||
if(extended_security & CIFSSEC_MUST_NTLMV2)
|
||||
if(secFlags & CIFSSEC_MUST_NTLMV2)
|
||||
server->secType = NTLMv2;
|
||||
else
|
||||
server->secType = NTLM;
|
||||
|
|
|
@ -915,32 +915,32 @@ 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->secFlg = CIFSSEC_MAY_KRB5 |
|
||||
vol->secFlg |= CIFSSEC_MAY_KRB5 |
|
||||
CIFSSEC_MUST_SIGN;
|
||||
} else if (strnicmp(value, "krb5p", 5) == 0) {
|
||||
/* vol->secFlg = CIFSSEC_MUST_SEAL |
|
||||
/* 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->secFlg = CIFSSEC_MAY_KRB5;
|
||||
vol->secFlg |= CIFSSEC_MAY_KRB5;
|
||||
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
|
||||
vol->secFlg = CIFSSEC_MAY_NTLMV2 |
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
|
||||
CIFSSEC_MUST_SIGN;
|
||||
} else if (strnicmp(value, "ntlmv2", 6) == 0) {
|
||||
vol->secFlg = CIFSSEC_MAY_NTLMV2;
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLMV2;
|
||||
} else if (strnicmp(value, "ntlmi", 5) == 0) {
|
||||
vol->secFlg = CIFSSEC_MAY_NTLM |
|
||||
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->secFlg = CIFSSEC_MAY_NTLM;
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLM;
|
||||
} else if (strnicmp(value, "nontlm", 6) == 0) {
|
||||
/* BB is there a better way to do this? */
|
||||
vol->secFlg = CIFSSEC_MAY_NTLMV2;
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLMV2;
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
} else if (strnicmp(value, "lanman", 6) == 0) {
|
||||
vol->secFlg = CIFSSEC_MAY_LANMAN;
|
||||
vol->secFlg |= CIFSSEC_MAY_LANMAN;
|
||||
#endif
|
||||
} else if (strnicmp(value, "none", 4) == 0) {
|
||||
vol->nullauth = 1;
|
||||
|
@ -1173,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) {
|
||||
|
@ -1776,6 +1780,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
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);
|
||||
|
|
|
@ -138,7 +138,7 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||
strncpy(bcc_ptr, ses->userName, 300);
|
||||
}
|
||||
/* BB improve check for overflow */
|
||||
bcc_ptr += strnlen(ses->userName, 200);
|
||||
bcc_ptr += strnlen(ses->userName, 300);
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++; /* account for null termination */
|
||||
|
||||
|
@ -313,11 +313,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
int wct;
|
||||
struct smb_hdr *smb_buf;
|
||||
char *bcc_ptr;
|
||||
char *str_area;
|
||||
SESSION_SETUP_ANDX *pSMB;
|
||||
__u32 capabilities;
|
||||
int count;
|
||||
int resp_buf_type = 0;
|
||||
struct kvec iov[2]; /* BB split variable length info into 2nd iovec */
|
||||
struct kvec iov[2];
|
||||
enum securityEnum type;
|
||||
__u16 action;
|
||||
int bytes_remaining;
|
||||
|
@ -351,7 +352,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
pSMB = (SESSION_SETUP_ANDX *)smb_buf;
|
||||
|
||||
capabilities = cifs_ssetup_hdr(ses, pSMB);
|
||||
bcc_ptr = pByteArea(smb_buf);
|
||||
|
||||
/* we will send the SMB in two pieces,
|
||||
a fixed length beginning part, and a
|
||||
second part which will include the strings
|
||||
and rest of bcc area, in order to avoid having
|
||||
to do a large buffer 17K allocation */
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = smb_buf->smb_buf_length + 4;
|
||||
|
||||
/* 2000 big enough to fit max user, domain, NOS name etc. */
|
||||
str_area = kmalloc(2000, GFP_KERNEL);
|
||||
bcc_ptr = str_area;
|
||||
|
||||
if(type == LANMAN) {
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
|
@ -365,10 +377,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
|
||||
calc_lanman_hash(ses, lnm_session_key);
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
/* #ifdef CONFIG_CIFS_DEBUG2
|
||||
cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
|
||||
CIFS_SESS_KEY_SIZE);
|
||||
#endif
|
||||
#endif */
|
||||
memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
|
||||
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||
|
||||
|
@ -377,7 +389,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
changed to do higher than lanman dialect and
|
||||
we reconnected would we ever calc signing_key? */
|
||||
|
||||
cERROR(1,("Negotiating LANMAN setting up strings"));
|
||||
cFYI(1,("Negotiating LANMAN setting up strings"));
|
||||
/* Unicode not allowed for LANMAN dialects */
|
||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
#endif
|
||||
|
@ -396,7 +408,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
|
||||
if(first_time) /* should this be moved into common code
|
||||
with similar ntlmv2 path? */
|
||||
cifs_calculate_mac_key( ses->server->mac_signing_key,
|
||||
cifs_calculate_mac_key(ses->server->mac_signing_key,
|
||||
ntlm_session_key, ses->password);
|
||||
/* copy session key */
|
||||
|
||||
|
@ -454,23 +466,14 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
/* BB set password lengths */
|
||||
}
|
||||
|
||||
count = (long) bcc_ptr - (long) pByteArea(smb_buf);
|
||||
count = (long) bcc_ptr - (long) str_area;
|
||||
smb_buf->smb_buf_length += count;
|
||||
|
||||
/* if we switch to small buffers, count will need to be fewer
|
||||
than 383 (strings less than 335 bytes) */
|
||||
|
||||
BCC_LE(smb_buf) = cpu_to_le16(count);
|
||||
|
||||
|
||||
/* BB FIXME check for other non ntlm code paths */
|
||||
|
||||
/* BB check is this too big for a small smb? */
|
||||
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = smb_buf->smb_buf_length + 4;
|
||||
|
||||
rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
|
||||
iov[1].iov_base = str_area;
|
||||
iov[1].iov_len = count;
|
||||
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
|
||||
/* SMB request buf freed in SendReceive2 */
|
||||
|
||||
cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
|
||||
|
@ -515,6 +518,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
|
||||
|
||||
ssetup_exit:
|
||||
kfree(str_area);
|
||||
if(resp_buf_type == CIFS_SMALL_BUFFER) {
|
||||
cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
|
||||
cifs_small_buf_release(iov[0].iov_base);
|
||||
|
|
Loading…
Reference in a new issue