mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	cifs: send workstation name during ntlmssp session setup
During the ntlmssp session setup (authenticate phases) send the client workstation info. This can make debugging easier on servers. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
		
							parent
							
								
									c9f1c19cf7
								
							
						
					
					
						commit
						49bd49f983
					
				
					 8 changed files with 170 additions and 85 deletions
				
			
		| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
#include <linux/slab.h>
 | 
					#include <linux/slab.h>
 | 
				
			||||||
#include <linux/mempool.h>
 | 
					#include <linux/mempool.h>
 | 
				
			||||||
#include <linux/workqueue.h>
 | 
					#include <linux/workqueue.h>
 | 
				
			||||||
 | 
					#include <linux/utsname.h>
 | 
				
			||||||
#include "cifs_fs_sb.h"
 | 
					#include "cifs_fs_sb.h"
 | 
				
			||||||
#include "cifsacl.h"
 | 
					#include "cifsacl.h"
 | 
				
			||||||
#include <crypto/internal/hash.h>
 | 
					#include <crypto/internal/hash.h>
 | 
				
			||||||
| 
						 | 
					@ -99,6 +100,8 @@
 | 
				
			||||||
#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
 | 
					#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CIFS_MAX_WORKSTATION_LEN  (__NEW_UTS_LEN + 1)  /* reasonable max for client */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * CIFS vfs client Status information (based on what we know.)
 | 
					 * CIFS vfs client Status information (based on what we know.)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -909,6 +912,7 @@ struct cifs_ses {
 | 
				
			||||||
				   and after mount option parsing we fill it */
 | 
									   and after mount option parsing we fill it */
 | 
				
			||||||
	char *domainName;
 | 
						char *domainName;
 | 
				
			||||||
	char *password;
 | 
						char *password;
 | 
				
			||||||
 | 
						char *workstation_name;
 | 
				
			||||||
	struct session_key auth_key;
 | 
						struct session_key auth_key;
 | 
				
			||||||
	struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
 | 
						struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
 | 
				
			||||||
	enum securityEnum sectype; /* what security flavor was specified? */
 | 
						enum securityEnum sectype; /* what security flavor was specified? */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1948,6 +1948,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
 | 
				
			||||||
		if (!ses->domainName)
 | 
							if (!ses->domainName)
 | 
				
			||||||
			goto get_ses_fail;
 | 
								goto get_ses_fail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (ctx->workstation_name) {
 | 
				
			||||||
 | 
							ses->workstation_name = kstrdup(ctx->workstation_name,
 | 
				
			||||||
 | 
											GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!ses->workstation_name)
 | 
				
			||||||
 | 
								goto get_ses_fail;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (ctx->domainauto)
 | 
						if (ctx->domainauto)
 | 
				
			||||||
		ses->domainAuto = ctx->domainauto;
 | 
							ses->domainAuto = ctx->domainauto;
 | 
				
			||||||
	ses->cred_uid = ctx->cred_uid;
 | 
						ses->cred_uid = ctx->cred_uid;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -309,6 +309,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
 | 
				
			||||||
	new_ctx->username = NULL;
 | 
						new_ctx->username = NULL;
 | 
				
			||||||
	new_ctx->password = NULL;
 | 
						new_ctx->password = NULL;
 | 
				
			||||||
	new_ctx->domainname = NULL;
 | 
						new_ctx->domainname = NULL;
 | 
				
			||||||
 | 
						new_ctx->workstation_name = NULL;
 | 
				
			||||||
	new_ctx->UNC = NULL;
 | 
						new_ctx->UNC = NULL;
 | 
				
			||||||
	new_ctx->source = NULL;
 | 
						new_ctx->source = NULL;
 | 
				
			||||||
	new_ctx->iocharset = NULL;
 | 
						new_ctx->iocharset = NULL;
 | 
				
			||||||
| 
						 | 
					@ -323,6 +324,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
 | 
				
			||||||
	DUP_CTX_STR(UNC);
 | 
						DUP_CTX_STR(UNC);
 | 
				
			||||||
	DUP_CTX_STR(source);
 | 
						DUP_CTX_STR(source);
 | 
				
			||||||
	DUP_CTX_STR(domainname);
 | 
						DUP_CTX_STR(domainname);
 | 
				
			||||||
 | 
						DUP_CTX_STR(workstation_name);
 | 
				
			||||||
	DUP_CTX_STR(nodename);
 | 
						DUP_CTX_STR(nodename);
 | 
				
			||||||
	DUP_CTX_STR(iocharset);
 | 
						DUP_CTX_STR(iocharset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -720,6 +722,11 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
 | 
				
			||||||
		cifs_errorf(fc, "can not change domainname during remount\n");
 | 
							cifs_errorf(fc, "can not change domainname during remount\n");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (new_ctx->workstation_name &&
 | 
				
			||||||
 | 
						    (!old_ctx->workstation_name || strcmp(new_ctx->workstation_name, old_ctx->workstation_name))) {
 | 
				
			||||||
 | 
							cifs_errorf(fc, "can not change workstation_name during remount\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (new_ctx->nodename &&
 | 
						if (new_ctx->nodename &&
 | 
				
			||||||
	    (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
 | 
						    (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
 | 
				
			||||||
		cifs_errorf(fc, "can not change nodename during remount\n");
 | 
							cifs_errorf(fc, "can not change nodename during remount\n");
 | 
				
			||||||
| 
						 | 
					@ -753,7 +760,8 @@ static int smb3_reconfigure(struct fs_context *fc)
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We can not change UNC/username/password/domainname/nodename/iocharset
 | 
						 * We can not change UNC/username/password/domainname/
 | 
				
			||||||
 | 
						 * workstation_name/nodename/iocharset
 | 
				
			||||||
	 * during reconnect so ignore what we have in the new context and
 | 
						 * during reconnect so ignore what we have in the new context and
 | 
				
			||||||
	 * just use what we already have in cifs_sb->ctx.
 | 
						 * just use what we already have in cifs_sb->ctx.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -762,6 +770,7 @@ static int smb3_reconfigure(struct fs_context *fc)
 | 
				
			||||||
	STEAL_STRING(cifs_sb, ctx, username);
 | 
						STEAL_STRING(cifs_sb, ctx, username);
 | 
				
			||||||
	STEAL_STRING(cifs_sb, ctx, password);
 | 
						STEAL_STRING(cifs_sb, ctx, password);
 | 
				
			||||||
	STEAL_STRING(cifs_sb, ctx, domainname);
 | 
						STEAL_STRING(cifs_sb, ctx, domainname);
 | 
				
			||||||
 | 
						STEAL_STRING(cifs_sb, ctx, workstation_name);
 | 
				
			||||||
	STEAL_STRING(cifs_sb, ctx, nodename);
 | 
						STEAL_STRING(cifs_sb, ctx, nodename);
 | 
				
			||||||
	STEAL_STRING(cifs_sb, ctx, iocharset);
 | 
						STEAL_STRING(cifs_sb, ctx, iocharset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1414,13 +1423,22 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int smb3_init_fs_context(struct fs_context *fc)
 | 
					int smb3_init_fs_context(struct fs_context *fc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
	struct smb3_fs_context *ctx;
 | 
						struct smb3_fs_context *ctx;
 | 
				
			||||||
	char *nodename = utsname()->nodename;
 | 
						char *nodename = utsname()->nodename;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
 | 
						ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
 | 
				
			||||||
	if (unlikely(!ctx))
 | 
						if (unlikely(!ctx)) {
 | 
				
			||||||
		return -ENOMEM;
 | 
							rc = -ENOMEM;
 | 
				
			||||||
 | 
							goto err_exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx->workstation_name = kstrdup(nodename, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (unlikely(!ctx->workstation_name)) {
 | 
				
			||||||
 | 
							rc = -ENOMEM;
 | 
				
			||||||
 | 
							goto err_exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * does not have to be perfect mapping since field is
 | 
						 * does not have to be perfect mapping since field is
 | 
				
			||||||
| 
						 | 
					@ -1493,6 +1511,14 @@ int smb3_init_fs_context(struct fs_context *fc)
 | 
				
			||||||
	fc->fs_private = ctx;
 | 
						fc->fs_private = ctx;
 | 
				
			||||||
	fc->ops = &smb3_fs_context_ops;
 | 
						fc->ops = &smb3_fs_context_ops;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_exit:
 | 
				
			||||||
 | 
						if (ctx) {
 | 
				
			||||||
 | 
							kfree(ctx->workstation_name);
 | 
				
			||||||
 | 
							kfree(ctx);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -1518,6 +1544,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
 | 
				
			||||||
	ctx->source = NULL;
 | 
						ctx->source = NULL;
 | 
				
			||||||
	kfree(ctx->domainname);
 | 
						kfree(ctx->domainname);
 | 
				
			||||||
	ctx->domainname = NULL;
 | 
						ctx->domainname = NULL;
 | 
				
			||||||
 | 
						kfree(ctx->workstation_name);
 | 
				
			||||||
 | 
						ctx->workstation_name = NULL;
 | 
				
			||||||
	kfree(ctx->nodename);
 | 
						kfree(ctx->nodename);
 | 
				
			||||||
	ctx->nodename = NULL;
 | 
						ctx->nodename = NULL;
 | 
				
			||||||
	kfree(ctx->iocharset);
 | 
						kfree(ctx->iocharset);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,6 +170,7 @@ struct smb3_fs_context {
 | 
				
			||||||
	char *server_hostname;
 | 
						char *server_hostname;
 | 
				
			||||||
	char *UNC;
 | 
						char *UNC;
 | 
				
			||||||
	char *nodename;
 | 
						char *nodename;
 | 
				
			||||||
 | 
						char *workstation_name;
 | 
				
			||||||
	char *iocharset;  /* local code page for mapping to and from Unicode */
 | 
						char *iocharset;  /* local code page for mapping to and from Unicode */
 | 
				
			||||||
	char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
 | 
						char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
 | 
				
			||||||
	char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
 | 
						char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,6 +94,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
 | 
				
			||||||
	kfree_sensitive(buf_to_free->password);
 | 
						kfree_sensitive(buf_to_free->password);
 | 
				
			||||||
	kfree(buf_to_free->user_name);
 | 
						kfree(buf_to_free->user_name);
 | 
				
			||||||
	kfree(buf_to_free->domainName);
 | 
						kfree(buf_to_free->domainName);
 | 
				
			||||||
 | 
						kfree(buf_to_free->workstation_name);
 | 
				
			||||||
	kfree_sensitive(buf_to_free->auth_key.response);
 | 
						kfree_sensitive(buf_to_free->auth_key.response);
 | 
				
			||||||
	kfree(buf_to_free->iface_list);
 | 
						kfree(buf_to_free->iface_list);
 | 
				
			||||||
	kfree_sensitive(buf_to_free);
 | 
						kfree_sensitive(buf_to_free);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,9 @@ typedef struct _AUTHENTICATE_MESSAGE {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
 | 
					int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
 | 
				
			||||||
void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
 | 
					int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
 | 
				
			||||||
 | 
									 struct cifs_ses *ses,
 | 
				
			||||||
 | 
									 const struct nls_table *nls_cp);
 | 
				
			||||||
int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
 | 
					int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
 | 
				
			||||||
			struct cifs_ses *ses,
 | 
								struct cifs_ses *ses,
 | 
				
			||||||
			const struct nls_table *nls_cp);
 | 
								const struct nls_table *nls_cp);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										188
									
								
								fs/cifs/sess.c
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								fs/cifs/sess.c
									
									
									
									
									
								
							| 
						 | 
					@ -599,18 +599,85 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int sz = base_size + ses->auth_key.len
 | 
				
			||||||
 | 
							- CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ses->domainName)
 | 
				
			||||||
 | 
							sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							sz += sizeof(__le16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ses->user_name)
 | 
				
			||||||
 | 
							sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							sz += sizeof(__le16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sz += sizeof(__le16) * strnlen(ses->workstation_name, CIFS_MAX_WORKSTATION_LEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sz;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
 | 
				
			||||||
 | 
											 char *str_value,
 | 
				
			||||||
 | 
											 int str_length,
 | 
				
			||||||
 | 
											 unsigned char *pstart,
 | 
				
			||||||
 | 
											 unsigned char **pcur,
 | 
				
			||||||
 | 
											 const struct nls_table *nls_cp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char *tmp = pstart;
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pbuf)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pcur)
 | 
				
			||||||
 | 
							pcur = &tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!str_value) {
 | 
				
			||||||
 | 
							pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
 | 
				
			||||||
 | 
							pbuf->Length = 0;
 | 
				
			||||||
 | 
							pbuf->MaximumLength = 0;
 | 
				
			||||||
 | 
							*pcur += sizeof(__le16);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							len = cifs_strtoUTF16((__le16 *)*pcur,
 | 
				
			||||||
 | 
									      str_value,
 | 
				
			||||||
 | 
									      str_length,
 | 
				
			||||||
 | 
									      nls_cp);
 | 
				
			||||||
 | 
							len *= sizeof(__le16);
 | 
				
			||||||
 | 
							pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
 | 
				
			||||||
 | 
							pbuf->Length = cpu_to_le16(len);
 | 
				
			||||||
 | 
							pbuf->MaximumLength = cpu_to_le16(len);
 | 
				
			||||||
 | 
							*pcur += len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* BB Move to ntlmssp.c eventually */
 | 
					/* BB Move to ntlmssp.c eventually */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* We do not malloc the blob, it is passed in pbuffer, because
 | 
					int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
 | 
				
			||||||
   it is fixed size, and small, making this approach cleaner */
 | 
									 u16 *buflen,
 | 
				
			||||||
void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
 | 
									 struct cifs_ses *ses,
 | 
				
			||||||
					 struct cifs_ses *ses)
 | 
									 const struct nls_table *nls_cp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
	struct TCP_Server_Info *server = cifs_ses_server(ses);
 | 
						struct TCP_Server_Info *server = cifs_ses_server(ses);
 | 
				
			||||||
	NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
 | 
						NEGOTIATE_MESSAGE *sec_blob;
 | 
				
			||||||
	__u32 flags;
 | 
						__u32 flags;
 | 
				
			||||||
 | 
						unsigned char *tmp;
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
 | 
						len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
 | 
				
			||||||
 | 
						*pbuffer = kmalloc(len, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!*pbuffer) {
 | 
				
			||||||
 | 
							rc = -ENOMEM;
 | 
				
			||||||
 | 
							cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
 | 
				
			||||||
 | 
							*buflen = 0;
 | 
				
			||||||
 | 
							goto setup_ntlm_neg_ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
 | 
				
			||||||
	memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
 | 
						memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
 | 
				
			||||||
	sec_blob->MessageType = NtLmNegotiate;
 | 
						sec_blob->MessageType = NtLmNegotiate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -624,34 +691,25 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
 | 
				
			||||||
	if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
 | 
						if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
 | 
				
			||||||
		flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
 | 
							flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE);
 | 
				
			||||||
	sec_blob->NegotiateFlags = cpu_to_le32(flags);
 | 
						sec_blob->NegotiateFlags = cpu_to_le32(flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec_blob->WorkstationName.BufferOffset = 0;
 | 
						/* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
 | 
				
			||||||
	sec_blob->WorkstationName.Length = 0;
 | 
						cifs_security_buffer_from_str(&sec_blob->DomainName,
 | 
				
			||||||
	sec_blob->WorkstationName.MaximumLength = 0;
 | 
									      NULL,
 | 
				
			||||||
 | 
									      CIFS_MAX_DOMAINNAME_LEN,
 | 
				
			||||||
 | 
									      *pbuffer, &tmp,
 | 
				
			||||||
 | 
									      nls_cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
 | 
						cifs_security_buffer_from_str(&sec_blob->WorkstationName,
 | 
				
			||||||
	sec_blob->DomainName.BufferOffset = 0;
 | 
									      NULL,
 | 
				
			||||||
	sec_blob->DomainName.Length = 0;
 | 
									      CIFS_MAX_WORKSTATION_LEN,
 | 
				
			||||||
	sec_blob->DomainName.MaximumLength = 0;
 | 
									      *pbuffer, &tmp,
 | 
				
			||||||
}
 | 
									      nls_cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int size_of_ntlmssp_blob(struct cifs_ses *ses)
 | 
						*buflen = tmp - *pbuffer;
 | 
				
			||||||
{
 | 
					setup_ntlm_neg_ret:
 | 
				
			||||||
	int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
 | 
						return rc;
 | 
				
			||||||
		- CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ses->domainName)
 | 
					 | 
				
			||||||
		sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		sz += 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ses->user_name)
 | 
					 | 
				
			||||||
		sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		sz += 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sz;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
					int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
| 
						 | 
					@ -663,6 +721,7 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
	AUTHENTICATE_MESSAGE *sec_blob;
 | 
						AUTHENTICATE_MESSAGE *sec_blob;
 | 
				
			||||||
	__u32 flags;
 | 
						__u32 flags;
 | 
				
			||||||
	unsigned char *tmp;
 | 
						unsigned char *tmp;
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = setup_ntlmv2_rsp(ses, nls_cp);
 | 
						rc = setup_ntlmv2_rsp(ses, nls_cp);
 | 
				
			||||||
	if (rc) {
 | 
						if (rc) {
 | 
				
			||||||
| 
						 | 
					@ -670,7 +729,9 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
		*buflen = 0;
 | 
							*buflen = 0;
 | 
				
			||||||
		goto setup_ntlmv2_ret;
 | 
							goto setup_ntlmv2_ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	*pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
 | 
					
 | 
				
			||||||
 | 
						len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
 | 
				
			||||||
 | 
						*pbuffer = kmalloc(len, GFP_KERNEL);
 | 
				
			||||||
	if (!*pbuffer) {
 | 
						if (!*pbuffer) {
 | 
				
			||||||
		rc = -ENOMEM;
 | 
							rc = -ENOMEM;
 | 
				
			||||||
		cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
 | 
							cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
 | 
				
			||||||
| 
						 | 
					@ -686,7 +747,7 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
		NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
 | 
							NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
 | 
				
			||||||
		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
 | 
							NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
 | 
				
			||||||
		NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
 | 
							NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
 | 
				
			||||||
		NTLMSSP_NEGOTIATE_SEAL;
 | 
							NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
 | 
				
			||||||
	if (ses->server->sign)
 | 
						if (ses->server->sign)
 | 
				
			||||||
		flags |= NTLMSSP_NEGOTIATE_SIGN;
 | 
							flags |= NTLMSSP_NEGOTIATE_SIGN;
 | 
				
			||||||
	if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
 | 
						if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
 | 
				
			||||||
| 
						 | 
					@ -719,42 +780,23 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
		sec_blob->NtChallengeResponse.MaximumLength = 0;
 | 
							sec_blob->NtChallengeResponse.MaximumLength = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ses->domainName == NULL) {
 | 
						cifs_security_buffer_from_str(&sec_blob->DomainName,
 | 
				
			||||||
		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 | 
									      ses->domainName,
 | 
				
			||||||
		sec_blob->DomainName.Length = 0;
 | 
									      CIFS_MAX_DOMAINNAME_LEN,
 | 
				
			||||||
		sec_blob->DomainName.MaximumLength = 0;
 | 
									      *pbuffer, &tmp,
 | 
				
			||||||
		tmp += 2;
 | 
									      nls_cp);
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		int len;
 | 
					 | 
				
			||||||
		len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
 | 
					 | 
				
			||||||
				      CIFS_MAX_DOMAINNAME_LEN, nls_cp);
 | 
					 | 
				
			||||||
		len *= 2; /* unicode is 2 bytes each */
 | 
					 | 
				
			||||||
		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 | 
					 | 
				
			||||||
		sec_blob->DomainName.Length = cpu_to_le16(len);
 | 
					 | 
				
			||||||
		sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
 | 
					 | 
				
			||||||
		tmp += len;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ses->user_name == NULL) {
 | 
						cifs_security_buffer_from_str(&sec_blob->UserName,
 | 
				
			||||||
		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 | 
									      ses->user_name,
 | 
				
			||||||
		sec_blob->UserName.Length = 0;
 | 
									      CIFS_MAX_USERNAME_LEN,
 | 
				
			||||||
		sec_blob->UserName.MaximumLength = 0;
 | 
									      *pbuffer, &tmp,
 | 
				
			||||||
		tmp += 2;
 | 
									      nls_cp);
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		int len;
 | 
					 | 
				
			||||||
		len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
 | 
					 | 
				
			||||||
				      CIFS_MAX_USERNAME_LEN, nls_cp);
 | 
					 | 
				
			||||||
		len *= 2; /* unicode is 2 bytes each */
 | 
					 | 
				
			||||||
		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 | 
					 | 
				
			||||||
		sec_blob->UserName.Length = cpu_to_le16(len);
 | 
					 | 
				
			||||||
		sec_blob->UserName.MaximumLength = cpu_to_le16(len);
 | 
					 | 
				
			||||||
		tmp += len;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
 | 
						cifs_security_buffer_from_str(&sec_blob->WorkstationName,
 | 
				
			||||||
	sec_blob->WorkstationName.Length = 0;
 | 
									      ses->workstation_name,
 | 
				
			||||||
	sec_blob->WorkstationName.MaximumLength = 0;
 | 
									      CIFS_MAX_WORKSTATION_LEN,
 | 
				
			||||||
	tmp += 2;
 | 
									      *pbuffer, &tmp,
 | 
				
			||||||
 | 
									      nls_cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
 | 
						if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
 | 
				
			||||||
		(ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
 | 
							(ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
 | 
				
			||||||
| 
						 | 
					@ -1230,6 +1272,7 @@ sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
 | 
				
			||||||
	struct cifs_ses *ses = sess_data->ses;
 | 
						struct cifs_ses *ses = sess_data->ses;
 | 
				
			||||||
	__u16 bytes_remaining;
 | 
						__u16 bytes_remaining;
 | 
				
			||||||
	char *bcc_ptr;
 | 
						char *bcc_ptr;
 | 
				
			||||||
 | 
						unsigned char *ntlmsspblob = NULL;
 | 
				
			||||||
	u16 blob_len;
 | 
						u16 blob_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
 | 
						cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
 | 
				
			||||||
| 
						 | 
					@ -1253,10 +1296,15 @@ sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
 | 
				
			||||||
	pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
 | 
						pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Build security blob before we assemble the request */
 | 
						/* Build security blob before we assemble the request */
 | 
				
			||||||
	build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses);
 | 
						rc = build_ntlmssp_negotiate_blob(&ntlmsspblob,
 | 
				
			||||||
	sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
 | 
									     &blob_len, ses,
 | 
				
			||||||
	sess_data->iov[1].iov_base = pSMB->req.SecurityBlob;
 | 
									     sess_data->nls_cp);
 | 
				
			||||||
	pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
 | 
						if (rc)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess_data->iov[1].iov_len = blob_len;
 | 
				
			||||||
 | 
						sess_data->iov[1].iov_base = ntlmsspblob;
 | 
				
			||||||
 | 
						pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
 | 
						rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1456,7 +1456,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
	struct cifs_ses *ses = sess_data->ses;
 | 
						struct cifs_ses *ses = sess_data->ses;
 | 
				
			||||||
	struct smb2_sess_setup_rsp *rsp = NULL;
 | 
						struct smb2_sess_setup_rsp *rsp = NULL;
 | 
				
			||||||
	char *ntlmssp_blob = NULL;
 | 
						unsigned char *ntlmssp_blob = NULL;
 | 
				
			||||||
	bool use_spnego = false; /* else use raw ntlmssp */
 | 
						bool use_spnego = false; /* else use raw ntlmssp */
 | 
				
			||||||
	u16 blob_length = 0;
 | 
						u16 blob_length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1475,22 +1475,17 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto out_err;
 | 
							goto out_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
 | 
						rc = build_ntlmssp_negotiate_blob(&ntlmssp_blob,
 | 
				
			||||||
			       GFP_KERNEL);
 | 
										  &blob_length, ses,
 | 
				
			||||||
	if (ntlmssp_blob == NULL) {
 | 
										  sess_data->nls_cp);
 | 
				
			||||||
		rc = -ENOMEM;
 | 
						if (rc)
 | 
				
			||||||
		goto out;
 | 
							goto out_err;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
 | 
					 | 
				
			||||||
	if (use_spnego) {
 | 
						if (use_spnego) {
 | 
				
			||||||
		/* BB eventually need to add this */
 | 
							/* BB eventually need to add this */
 | 
				
			||||||
		cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
 | 
							cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
 | 
				
			||||||
		rc = -EOPNOTSUPP;
 | 
							rc = -EOPNOTSUPP;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
 | 
					 | 
				
			||||||
		/* with raw NTLMSSP we don't encapsulate in SPNEGO */
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sess_data->iov[1].iov_base = ntlmssp_blob;
 | 
						sess_data->iov[1].iov_base = ntlmssp_blob;
 | 
				
			||||||
	sess_data->iov[1].iov_len = blob_length;
 | 
						sess_data->iov[1].iov_len = blob_length;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue