Skip to content

Commit

Permalink
move sectype to the cifs_ses instead of TCP_Server_Info
Browse files Browse the repository at this point in the history
Now that we track what sort of NEGOTIATE response was received, stop
mandating that every session on a socket use the same type of auth.

Push that decision out into the session setup code, and make the sectype
a per-session property. This should allow us to mix multiple sectypes on
a socket as long as they are compatible with the NEGOTIATE response.

With this too, we can now eliminate the ses->secFlg field since that
info is redundant and harder to work with than a securityEnum.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
  • Loading branch information
Jeff Layton authored and Steve French committed Jun 24, 2013
1 parent 38d77c5 commit 3f61822
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 180 deletions.
4 changes: 2 additions & 2 deletions fs/cifs/cifsencrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
return rc;
}

if (ses->server->secType == RawNTLMSSP)
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
memcpy(ses->auth_key.response + offset,
ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
else
Expand Down Expand Up @@ -567,7 +567,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
char ntlmv2_hash[16];
unsigned char *tiblob = NULL; /* target info blob */

if (ses->server->secType == RawNTLMSSP) {
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
if (!ses->domainName) {
rc = find_domain_name(ses, nls_cp);
if (rc) {
Expand Down
2 changes: 0 additions & 2 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ struct smb_vol {
kgid_t backupgid;
umode_t file_mode;
umode_t dir_mode;
unsigned secFlg;
enum securityEnum sectype; /* sectype requested via mnt opts */
bool sign; /* was signing requested via mnt opts? */
bool retry:1;
Expand Down Expand Up @@ -519,7 +518,6 @@ struct TCP_Server_Info {
bool echoes:1; /* enable echoes */
#endif
u16 dialect; /* dialect index that server chose */
enum securityEnum secType;
bool oplocks:1; /* enable oplocks */
unsigned int maxReq; /* Clients should submit no more */
/* than maxReq distinct unanswered SMBs to the server when using */
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifs_ses *ses,
void **request_buf);
extern enum securityEnum select_sectype(struct TCP_Server_Info *server,
enum securityEnum requested);
extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
const struct nls_table *nls_cp);
extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
Expand Down
92 changes: 20 additions & 72 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,12 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
}

static int
decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
{
int rc = 0;
u16 count;
char *guid = pSMBr->u.extended_response.GUID;
struct TCP_Server_Info *server = ses->server;

count = get_bcc(&pSMBr->hdr);
if (count < SMB1_CLIENT_GUID_SIZE)
Expand All @@ -391,27 +392,13 @@ decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
}

if (count == SMB1_CLIENT_GUID_SIZE) {
server->secType = RawNTLMSSP;
server->sec_ntlmssp = true;
} else {
count -= SMB1_CLIENT_GUID_SIZE;
rc = decode_negTokenInit(
pSMBr->u.extended_response.SecurityBlob, count, server);
if (rc != 1)
return -EINVAL;

/* Make sure server supports what we want to use */
switch(server->secType) {
case Kerberos:
if (!server->sec_kerberos && !server->sec_mskerberos)
return -EOPNOTSUPP;
break;
case RawNTLMSSP:
if (!server->sec_ntlmssp)
return -EOPNOTSUPP;
break;
default:
return -EOPNOTSUPP;
}
}

return 0;
Expand Down Expand Up @@ -462,21 +449,14 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)

#ifdef CONFIG_CIFS_WEAK_PW_HASH
static int
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
unsigned int secFlags)
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
{
__s16 tmp;
struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;

if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
return -EOPNOTSUPP;

if ((secFlags & CIFSSEC_MAY_LANMAN) || (secFlags & CIFSSEC_MAY_PLNTXT))
server->secType = LANMAN;
else {
cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n");
return -EOPNOTSUPP;
}
server->sec_mode = le16_to_cpu(rsp->SecurityMode);
server->maxReq = min_t(unsigned int,
le16_to_cpu(rsp->MaxMpxCount),
Expand Down Expand Up @@ -542,26 +522,28 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
}
#else
static inline int
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
unsigned int secFlags)
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
{
cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
return -EOPNOTSUPP;
}
#endif

static bool
should_set_ext_sec_flag(unsigned int secFlags)
should_set_ext_sec_flag(enum securityEnum sectype)
{
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
return true;
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5)
return true;
else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
return true;
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP)
switch (sectype) {
case RawNTLMSSP:
case Kerberos:
return true;
return false;
case Unspecified:
if (global_secflags &
(CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
return true;
/* Fallthrough */
default:
return false;
}
}

int
Expand All @@ -574,7 +556,6 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
int i;
struct TCP_Server_Info *server = ses->server;
u16 count;
unsigned int secFlags;

if (!server) {
WARN(1, "%s: server is NULL!\n", __func__);
Expand All @@ -586,18 +567,10 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
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; /* BB FIXME fix sign flags? */
else /* if override flags set only sign/seal OR them with global auth */
secFlags = global_secflags | ses->overrideSecFlg;

cifs_dbg(FYI, "secFlags 0x%x\n", secFlags);

pSMB->hdr.Mid = get_next_mid(server);
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);

if (should_set_ext_sec_flag(secFlags)) {
if (should_set_ext_sec_flag(ses->sectype)) {
cifs_dbg(FYI, "Requesting extended security.");
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
Expand Down Expand Up @@ -627,7 +600,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
goto neg_err_exit;
} else if (pSMBr->hdr.WordCount == 13) {
server->negflavor = CIFS_NEGFLAVOR_LANMAN;
rc = decode_lanman_negprot_rsp(server, pSMBr, secFlags);
rc = decode_lanman_negprot_rsp(server, pSMBr);
goto signing_check;
} else if (pSMBr->hdr.WordCount != 17) {
/* unknown wct */
Expand All @@ -640,31 +613,6 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
if ((server->sec_mode & SECMODE_USER) == 0)
cifs_dbg(FYI, "share mode security\n");

if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
#ifdef CONFIG_CIFS_WEAK_PW_HASH
if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
#endif /* CIFS_WEAK_PW_HASH */
cifs_dbg(VFS, "Server requests plain text password but client support disabled\n");

if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
server->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_NTLM)
server->secType = NTLM;
else if (secFlags & CIFSSEC_MAY_NTLMV2)
server->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_KRB5)
server->secType = Kerberos;
else if (secFlags & CIFSSEC_MAY_NTLMSSP)
server->secType = RawNTLMSSP;
else if (secFlags & CIFSSEC_MAY_LANMAN)
server->secType = LANMAN;
else {
rc = -EOPNOTSUPP;
cifs_dbg(VFS, "Invalid security type\n");
goto neg_err_exit;
}
/* else ... any others ...? */

/* one byte, so no need to convert this or EncryptionKeyLen from
little endian */
server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
Expand All @@ -686,7 +634,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
server->capabilities & CAP_EXTENDED_SECURITY) &&
(pSMBr->EncryptionKeyLength == 0)) {
server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
rc = decode_ext_sec_blob(server, pSMBr);
rc = decode_ext_sec_blob(ses, pSMBr);
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
rc = -EIO; /* no crypt key only if plain text pwd */
} else {
Expand Down
Loading

0 comments on commit 3f61822

Please sign in to comment.