[linux-cifs-client] [PATCH 5/5] [CIFS] have CIFS_SessSetup build correct SPNEGO SessionSetup request

Q (Igor Mammedov) qwerty0987654321 at mail.ru
Fri Nov 16 14:21:05 GMT 2007


Looks ok for me.

Jeff Layton wrote:
> 
> Good catch. How about this patch instead?
> 
> From 3fd419aee87260b2f349fa092766fcb535cf7f53 Mon Sep 17 00:00:00 2001
> From: Jeff Layton <jlayton at redhat.com>
> Date: Fri, 16 Nov 2007 08:44:45 -0500
> Subject: [PATCH 5/5] [CIFS] have CIFS_SessSetup build correct SPNEGO SessionSetup request
> 
> Have CIFS_SessSetup call cifs_get_spnego_key when Kerberos is
> negotiated. Use the info in the key payload to build a session
> setup request packet.
> 
> Signed-off-by: Jeff Layton <jlayton at redhat.com>
> ---
>  fs/cifs/cifsglob.h |    1 +
>  fs/cifs/sess.c     |   66 ++++++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 60 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 3525082..1fde219 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -110,6 +110,7 @@ struct mac_key {
>  	unsigned int len;
>  	union {
>  		char ntlm[CIFS_SESS_KEY_SIZE + 16];
> +		char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */
>  		struct {
>  			char key[16];
>  			struct ntlmv2_resp resp;
> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
> index ed01ef3..192b154 100644
> --- a/fs/cifs/sess.c
> +++ b/fs/cifs/sess.c
> @@ -29,6 +29,7 @@
>  #include "ntlmssp.h"
>  #include "nterr.h"
>  #include <linux/utsname.h>
> +#include "cifs_spnego.h"
>  
>  extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
>  			 unsigned char *p24);
> @@ -341,10 +342,11 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
>  	__u32 capabilities;
>  	int count;
>  	int resp_buf_type = 0;
> -	struct kvec iov[2];
> +	struct kvec iov[3];
>  	enum securityEnum type;
>  	__u16 action;
>  	int bytes_remaining;
> +	struct key *spnego_key = NULL;
>  
>  	if (ses == NULL)
>  		return -EINVAL;
> @@ -395,6 +397,9 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
>  
>  	ses->flags &= ~CIFS_SES_LANMAN;
>  
> +	iov[1].iov_base = NULL;
> +	iov[1].iov_len = 0;
> +
>  	if (type == LANMAN) {
>  #ifdef CONFIG_CIFS_WEAK_PW_HASH
>  		char lnm_session_key[CIFS_SESS_KEY_SIZE];
> @@ -499,21 +504,66 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
>  			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
>  		} else
>  			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
> -	} else /* NTLMSSP or SPNEGO */ {
> +	} else if (type == Kerberos) {
> +#ifdef CONFIG_CIFS_UPCALL
> +		struct cifs_spnego_msg *msg;
> +		spnego_key = cifs_get_spnego_key(ses);
> +		if (IS_ERR(spnego_key)) {
> +			rc = PTR_ERR(spnego_key);
> +			spnego_key = NULL;
> +			goto ssetup_exit;
> +		}
> +
> +		msg = spnego_key->payload.data;
> +		/* bail out if key is too long */
> +		if (msg->sesskey_len >
> +		    sizeof(ses->server->mac_signing_key.data.krb5)) {
> +			cERROR(1,("Kerberos signing key too long (%u bytes)",
> +				msg->sesskey_len));
> +			rc = -EOVERFLOW;
> +			goto ssetup_exit;
> +		}
> +		ses->server->mac_signing_key.len = msg->sesskey_len;
> +		memcpy(ses->server->mac_signing_key.data.krb5, msg->data,
> +			msg->sesskey_len);
>  		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
>  		capabilities |= CAP_EXTENDED_SECURITY;
>  		pSMB->req.Capabilities = cpu_to_le32(capabilities);
> -		/* BB set password lengths */
> +		iov[1].iov_base = msg->data + msg->sesskey_len;
> +		iov[1].iov_len = msg->secblob_len;
> +		pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len);
> +
> +		if (ses->capabilities & CAP_UNICODE) {
> +			/* unicode strings must be word aligned */
> +			if (iov[0].iov_len % 2) {
> +				*bcc_ptr = 0;
> +				bcc_ptr++;
> +			}
> +			unicode_oslm_strings(&bcc_ptr, nls_cp);
> +			unicode_domain_string(&bcc_ptr, ses, nls_cp);
> +		} else
> +		/* BB: is this right? */
> +		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
> +#else /* ! CONFIG_CIFS_UPCALL */
> +		cERROR(1,("Kerberos negotiated, but upcall support disabled!"));
> +		rc = -ENOSYS;
> +		goto ssetup_exit;
> +#endif /* CONFIG_CIFS_UPCALL */
> +	} else {
> +		cERROR(1,("secType %d not supported!", type));
> +		rc = -ENOSYS;
> +		goto ssetup_exit;
>  	}
>  
> -	count = (long) bcc_ptr - (long) str_area;
> +	iov[2].iov_base = str_area;
> +	iov[2].iov_len = (long) bcc_ptr - (long) str_area;
> +
> +	count = iov[1].iov_len + iov[2].iov_len;
>  	smb_buf->smb_buf_length += count;
>  
>  	BCC_LE(smb_buf) = cpu_to_le16(count);
>  
> -	iov[1].iov_base = str_area;
> -	iov[1].iov_len = count;
> -	rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
> +	rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
>  			  CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
>  	/* SMB request buf freed in SendReceive2 */
>  
> @@ -560,6 +610,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
>  					 ses, nls_cp);
>  
>  ssetup_exit:
> +	if (spnego_key)
> +		key_put(spnego_key);
>  	kfree(str_area);
>  	if (resp_buf_type == CIFS_SMALL_BUFFER) {
>  		cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));


-- 

Best regards,

-------------------------
Igor Mammedov,
niallain "at" gmail.com






More information about the linux-cifs-client mailing list