diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/vfs_dir.c | 6 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 9 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 20 | ||||
| -rw-r--r-- | fs/aio.c | 3 | ||||
| -rw-r--r-- | fs/cifs/Kconfig | 2 | ||||
| -rw-r--r-- | fs/cifs/asn1.c | 6 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.c | 418 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 25 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 7 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 13 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 13 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 71 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 30 | ||||
| -rw-r--r-- | fs/cifs/netmisc.c | 22 | ||||
| -rw-r--r-- | fs/cifs/ntlmssp.h | 13 | ||||
| -rw-r--r-- | fs/cifs/sess.c | 132 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 6 | ||||
| -rw-r--r-- | fs/nfs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/nfs/client.c | 2 | ||||
| -rw-r--r-- | fs/nfs/file.c | 4 | ||||
| -rw-r--r-- | fs/nfs/super.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/Kconfig | 1 | 
22 files changed, 205 insertions, 607 deletions
| diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 16c8a2a98c1b..899f168fd19c 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -292,9 +292,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)  	fid = filp->private_data;  	P9_DPRINTK(P9_DEBUG_VFS, -			"inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); +			"v9fs_dir_release: inode: %p filp: %p fid: %d\n", +			inode, filp, fid ? fid->fid : -1);  	filemap_write_and_wait(inode->i_mapping); -	p9_client_clunk(fid); +	if (fid) +		p9_client_clunk(fid);  	return 0;  } diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c7c23eab9440..9e670d527646 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -730,7 +730,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,  		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);  		goto error;  	} -	dentry->d_op = &v9fs_cached_dentry_operations; +	if (v9ses->cache) +		dentry->d_op = &v9fs_cached_dentry_operations; +	else +		dentry->d_op = &v9fs_dentry_operations;  	d_instantiate(dentry, inode);  	err = v9fs_fid_add(dentry, fid);  	if (err < 0) @@ -1128,6 +1131,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,  	v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);  		generic_fillattr(dentry->d_inode, stat); +	p9stat_free(st);  	kfree(st);  	return 0;  } @@ -1489,6 +1493,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)  	retval = strnlen(buffer, buflen);  done: +	p9stat_free(st);  	kfree(st);  	return retval;  } @@ -1942,7 +1947,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {  	.unlink = v9fs_vfs_unlink,  	.mkdir = v9fs_vfs_mkdir,  	.rmdir = v9fs_vfs_rmdir, -	.mknod = v9fs_vfs_mknod_dotl, +	.mknod = v9fs_vfs_mknod,  	.rename = v9fs_vfs_rename,  	.getattr = v9fs_vfs_getattr,  	.setattr = v9fs_vfs_setattr, diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index f9311077de68..1d12ba0ed3db 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -122,6 +122,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,  	fid = v9fs_session_init(v9ses, dev_name, data);  	if (IS_ERR(fid)) {  		retval = PTR_ERR(fid); +		/* +		 * we need to call session_close to tear down some +		 * of the data structure setup by session_init +		 */  		goto close_session;  	} @@ -144,7 +148,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,  		retval = -ENOMEM;  		goto release_sb;  	} -  	sb->s_root = root;  	if (v9fs_proto_dotl(v9ses)) { @@ -152,7 +155,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,  		st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);  		if (IS_ERR(st)) {  			retval = PTR_ERR(st); -			goto clunk_fid; +			goto release_sb;  		}  		v9fs_stat2inode_dotl(st, root->d_inode); @@ -162,7 +165,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,  		st = p9_client_stat(fid);  		if (IS_ERR(st)) {  			retval = PTR_ERR(st); -			goto clunk_fid; +			goto release_sb;  		}  		root->d_inode->i_ino = v9fs_qid2ino(&st->qid); @@ -174,19 +177,24 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,  	v9fs_fid_add(root, fid); -P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); +	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");  	simple_set_mnt(mnt, sb);  	return 0;  clunk_fid:  	p9_client_clunk(fid); -  close_session:  	v9fs_session_close(v9ses);  	kfree(v9ses);  	return retval; -  release_sb: +	/* +	 * we will do the session_close and root dentry release +	 * in the below call. But we need to clunk fid, because we haven't +	 * attached the fid to dentry so it won't get clunked +	 * automatically. +	 */ +	p9_client_clunk(fid);  	deactivate_locked_super(sb);  	return retval;  } @@ -1659,6 +1659,9 @@ long do_io_submit(aio_context_t ctx_id, long nr,  	if (unlikely(nr < 0))  		return -EINVAL; +	if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) +		nr = LONG_MAX/sizeof(*iocbpp); +  	if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))  		return -EFAULT; diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0da1debd499d..917b7d449bb2 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -2,8 +2,6 @@ config CIFS  	tristate "CIFS support (advanced network filesystem, SMBFS successor)"  	depends on INET  	select NLS -	select CRYPTO_MD5 -	select CRYPTO_ARC4  	help  	  This is the client VFS module for the Common Internet File System  	  (CIFS) protocol which is the successor to the Server Message Block diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 21f0fbd86989..cfd1ce34e0bc 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,  				if (compare_oid(oid, oidlen, MSKRB5_OID,  						MSKRB5_OID_LEN))  					server->sec_mskerberos = true; -				if (compare_oid(oid, oidlen, KRB5U2U_OID, +				else if (compare_oid(oid, oidlen, KRB5U2U_OID,  						     KRB5U2U_OID_LEN))  					server->sec_kerberosu2u = true; -				if (compare_oid(oid, oidlen, KRB5_OID, +				else if (compare_oid(oid, oidlen, KRB5_OID,  						     KRB5_OID_LEN))  					server->sec_kerberos = true; -				if (compare_oid(oid, oidlen, NTLMSSP_OID, +				else if (compare_oid(oid, oidlen, NTLMSSP_OID,  						     NTLMSSP_OID_LEN))  					server->sec_ntlmssp = true; diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 709f2296bdb4..35042d8f7338 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -27,7 +27,6 @@  #include "md5.h"  #include "cifs_unicode.h"  #include "cifsproto.h" -#include "ntlmssp.h"  #include <linux/ctype.h>  #include <linux/random.h> @@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,  		       unsigned char *p24);  static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, -			struct TCP_Server_Info *server, char *signature) +				    const struct mac_key *key, char *signature)  { -	int rc; +	struct	MD5Context context; -	if (cifs_pdu == NULL || server == NULL || signature == NULL) +	if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))  		return -EINVAL; -	if (!server->ntlmssp.sdescmd5) { -		cERROR(1, -			"cifs_calculate_signature: can't generate signature\n"); -		return -1; -	} - -	rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); -	if (rc) { -		cERROR(1, "cifs_calculate_signature: oould not init md5\n"); -		return rc; -	} - -	if (server->secType == RawNTLMSSP) -		crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -			server->session_key.data.ntlmv2.key, -			CIFS_NTLMV2_SESSKEY_SIZE); -	else -		crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -			(char *)&server->session_key.data, -			server->session_key.len); - -	crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -			cifs_pdu->Protocol, cifs_pdu->smb_buf_length); +	cifs_MD5_init(&context); +	cifs_MD5_update(&context, (char *)&key->data, key->len); +	cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); -	rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); - -	return rc; +	cifs_MD5_final(signature, &context); +	return 0;  } -  int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,  		  __u32 *pexpected_response_sequence_number)  { @@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,  	server->sequence_number++;  	spin_unlock(&GlobalMid_Lock); -	rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); +	rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, +				      smb_signature);  	if (rc)  		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);  	else @@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,  }  static int cifs_calc_signature2(const struct kvec *iov, int n_vec, -			struct TCP_Server_Info *server, char *signature) +				const struct mac_key *key, char *signature)  { +	struct  MD5Context context;  	int i; -	int rc; -	if (iov == NULL || server == NULL || signature == NULL) +	if ((iov == NULL) || (signature == NULL) || (key == NULL))  		return -EINVAL; -	if (!server->ntlmssp.sdescmd5) { -		cERROR(1, "cifs_calc_signature2: can't generate signature\n"); -		return -1; -	} - -	rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); -	if (rc) { -		cERROR(1, "cifs_calc_signature2: oould not init md5\n"); -		return rc; -	} - -	if (server->secType == RawNTLMSSP) -		crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -			server->session_key.data.ntlmv2.key, -			CIFS_NTLMV2_SESSKEY_SIZE); -	else -		crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -			(char *)&server->session_key.data, -			server->session_key.len); - +	cifs_MD5_init(&context); +	cifs_MD5_update(&context, (char *)&key->data, key->len);  	for (i = 0; i < n_vec; i++) {  		if (iov[i].iov_len == 0)  			continue;  		if (iov[i].iov_base == NULL) { -			cERROR(1, "cifs_calc_signature2: null iovec entry"); +			cERROR(1, "null iovec entry");  			return -EIO;  		}  		/* The first entry includes a length field (which does not get @@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,  		if (i == 0) {  			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */  				break; /* nothing to sign or corrupt header */ -			crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -				iov[i].iov_base + 4, iov[i].iov_len - 4); +			cifs_MD5_update(&context, iov[0].iov_base+4, +				  iov[0].iov_len-4);  		} else -			crypto_shash_update(&server->ntlmssp.sdescmd5->shash, -				iov[i].iov_base, iov[i].iov_len); +			cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len);  	} -	rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); +	cifs_MD5_final(signature, &context); -	return rc; +	return 0;  } +  int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,  		   __u32 *pexpected_response_sequence_number)  { @@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,  	server->sequence_number++;  	spin_unlock(&GlobalMid_Lock); -	rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); +	rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, +				      smb_signature);  	if (rc)  		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);  	else @@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,  }  int cifs_verify_signature(struct smb_hdr *cifs_pdu, -			  struct TCP_Server_Info *server, +			  const struct mac_key *mac_key,  			  __u32 expected_sequence_number)  { -	int rc; +	unsigned int rc;  	char server_response_sig[8];  	char what_we_think_sig_should_be[20]; -	if (cifs_pdu == NULL || server == NULL) +	if ((cifs_pdu == NULL) || (mac_key == NULL))  		return -EINVAL;  	if (cifs_pdu->Command == SMB_COM_NEGOTIATE) @@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,  					cpu_to_le32(expected_sequence_number);  	cifs_pdu->Signature.Sequence.Reserved = 0; -	rc = cifs_calculate_signature(cifs_pdu, server, +	rc = cifs_calculate_signature(cifs_pdu, mac_key,  		what_we_think_sig_should_be);  	if (rc) @@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,  }  /* We fill in key by putting in 40 byte array which was allocated by caller */ -int cifs_calculate_session_key(struct session_key *key, const char *rn, +int cifs_calculate_mac_key(struct mac_key *key, const char *rn,  			   const char *password)  {  	char temp_key[16]; @@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,  {  	int rc = 0;  	int len; -	char nt_hash[CIFS_NTHASH_SIZE]; +	char nt_hash[16]; +	struct HMACMD5Context *pctxt;  	wchar_t *user;  	wchar_t *domain; -	wchar_t *server; -	if (!ses->server->ntlmssp.sdeschmacmd5) { -		cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); -		return -1; -	} +	pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); + +	if (pctxt == NULL) +		return -ENOMEM;  	/* calculate md4 hash of password */  	E_md4hash(ses->password, nt_hash); -	crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, -				CIFS_NTHASH_SIZE); - -	rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); -	if (rc) { -		cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); -		return rc; -	} +	/* convert Domainname to unicode and uppercase */ +	hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);  	/* convert ses->userName to unicode and uppercase */  	len = strlen(ses->userName);  	user = kmalloc(2 + (len * 2), GFP_KERNEL); -	if (user == NULL) { -		cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); -		rc = -ENOMEM; +	if (user == NULL)  		goto calc_exit_2; -	}  	len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);  	UniStrupr(user); - -	crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, -				(char *)user, 2 * len); +	hmac_md5_update((char *)user, 2*len, pctxt);  	/* convert ses->domainName to unicode and uppercase */  	if (ses->domainName) {  		len = strlen(ses->domainName);  		domain = kmalloc(2 + (len * 2), GFP_KERNEL); -		if (domain == NULL) { -			cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); -			rc = -ENOMEM; +		if (domain == NULL)  			goto calc_exit_1; -		}  		len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,  					nls_cp);  		/* the following line was removed since it didn't work well @@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,  		   Maybe converting the domain name earlier makes sense */  		/* UniStrupr(domain); */ -		crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, -					(char *)domain, 2 * len); +		hmac_md5_update((char *)domain, 2*len, pctxt);  		kfree(domain); -	} else if (ses->serverName) { -		len = strlen(ses->serverName); - -		server = kmalloc(2 + (len * 2), GFP_KERNEL); -		if (server == NULL) { -			cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); -			rc = -ENOMEM; -			goto calc_exit_1; -		} -		len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, -					nls_cp); -		/* the following line was removed since it didn't work well -		   with lower cased domain name that passed as an option. -		   Maybe converting the domain name earlier makes sense */ -		/* UniStrupr(domain); */ - -		crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, -					(char *)server, 2 * len); - -		kfree(server);  	} - -	rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, -					ses->server->ntlmv2_hash); -  calc_exit_1:  	kfree(user);  calc_exit_2:  	/* BB FIXME what about bytes 24 through 40 of the signing key?  	   compare with the NTLM example */ +	hmac_md5_final(ses->server->ntlmv2_hash, pctxt); +	kfree(pctxt);  	return rc;  } -static int -find_domain_name(struct cifsSesInfo *ses) -{ -	int rc = 0; -	unsigned int attrsize; -	unsigned int type; -	unsigned char *blobptr; -	struct ntlmssp2_name *attrptr; - -	if (ses->server->tiblob) { -		blobptr = ses->server->tiblob; -		attrptr = (struct ntlmssp2_name *) blobptr; - -		while ((type = attrptr->type) != 0) { -			blobptr += 2; /* advance attr type */ -			attrsize = attrptr->length; -			blobptr += 2; /* advance attr size */ -			if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { -				if (!ses->domainName) { -					ses->domainName = -						kmalloc(attrptr->length + 1, -								GFP_KERNEL); -					if (!ses->domainName) -							return -ENOMEM; -					cifs_from_ucs2(ses->domainName, -						(__le16 *)blobptr, -						attrptr->length, -						attrptr->length, -						load_nls_default(), false); -				} -			} -			blobptr += attrsize; /* advance attr  value */ -			attrptr = (struct ntlmssp2_name *) blobptr; -		} -	} else { -		ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); -		ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); -		if (!ses->server->tiblob) { -			ses->server->tilen = 0; -			cERROR(1, "Challenge target info allocation failure"); -			return -ENOMEM; -		} -		memset(ses->server->tiblob, 0x0, ses->server->tilen); -		attrptr = (struct ntlmssp2_name *) ses->server->tiblob; -		attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); -	} - -	return rc; -} - -static int -CalcNTLMv2_response(const struct TCP_Server_Info *server, -			 char *v2_session_response) -{ -	int rc; - -	if (!server->ntlmssp.sdeschmacmd5) { -		cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); -		return -1; -	} - -	crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, -		CIFS_HMAC_MD5_HASH_SIZE); - -	rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash); -	if (rc) { -		cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); -		return rc; -	} - -	memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, -		server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); -	crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, -		v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, -		sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); - -	if (server->tilen) -		crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, -					server->tiblob, server->tilen); - -	rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash, -					v2_session_response); - -	return rc; -} - -int -setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, +void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,  		      const struct nls_table *nls_cp)  { -	int rc = 0; +	int rc;  	struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; +	struct HMACMD5Context context;  	buf->blob_signature = cpu_to_le32(0x00000101);  	buf->reserved = 0;  	buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));  	get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));  	buf->reserved2 = 0; - -	if (!ses->domainName) { -		rc = find_domain_name(ses); -		if (rc) { -			cERROR(1, "could not get domain/server name rc %d", rc); -			return rc; -		} -	} +	buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); +	buf->names[0].length = 0; +	buf->names[1].type = 0; +	buf->names[1].length = 0;  	/* calculate buf->ntlmv2_hash */  	rc = calc_ntlmv2_hash(ses, nls_cp); -	if (rc) { -		cERROR(1, "could not get v2 hash rc %d", rc); -		return rc; -	} -	rc = CalcNTLMv2_response(ses->server, resp_buf); -	if (rc) { +	if (rc)  		cERROR(1, "could not get v2 hash rc %d", rc); -		return rc; -	} - -	if (!ses->server->ntlmssp.sdeschmacmd5) { -		cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); -		return -1; -	} - -	crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, -			ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); +	CalcNTLMv2_response(ses, resp_buf); -	rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); -	if (rc) { -		cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); -		return rc; -	} +	/* now calculate the MAC key for NTLMv2 */ +	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); +	hmac_md5_update(resp_buf, 16, &context); +	hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); -	crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, -				resp_buf, CIFS_HMAC_MD5_HASH_SIZE); - -	rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, -		ses->server->session_key.data.ntlmv2.key); - -	memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, -			sizeof(struct ntlmv2_resp)); -	ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); - -	return rc; +	memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, +	       sizeof(struct ntlmv2_resp)); +	ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);  } -int -calc_seckey(struct TCP_Server_Info *server) -{ -	int rc; -	unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; -	struct crypto_blkcipher *tfm_arc4; -	struct scatterlist sgin, sgout; -	struct blkcipher_desc desc; - -	get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - -	tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", -						0, CRYPTO_ALG_ASYNC); -	if (!tfm_arc4 || IS_ERR(tfm_arc4)) { -		cERROR(1, "could not allocate " "master crypto API arc4\n"); -		return 1; -	} - -	desc.tfm = tfm_arc4; - -	crypto_blkcipher_setkey(tfm_arc4, -		server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); -	sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); -	sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); -	rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); - -	if (!rc) -		memcpy(server->session_key.data.ntlmv2.key, -				sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - -	crypto_free_blkcipher(tfm_arc4); - -	return 0; -} - -void -cifs_crypto_shash_release(struct TCP_Server_Info *server) -{ -	if (server->ntlmssp.md5) -		crypto_free_shash(server->ntlmssp.md5); - -	if (server->ntlmssp.hmacmd5) -		crypto_free_shash(server->ntlmssp.hmacmd5); - -	kfree(server->ntlmssp.sdeschmacmd5); - -	kfree(server->ntlmssp.sdescmd5); -} - -int -cifs_crypto_shash_allocate(struct TCP_Server_Info *server) +void CalcNTLMv2_response(const struct cifsSesInfo *ses, +			 char *v2_session_response)  { -	int rc; -	unsigned int size; - -	server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); -	if (!server->ntlmssp.hmacmd5 || -			IS_ERR(server->ntlmssp.hmacmd5)) { -		cERROR(1, "could not allocate crypto hmacmd5\n"); -		return 1; -	} - -	server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); -	if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { -		cERROR(1, "could not allocate crypto md5\n"); -		rc = 1; -		goto cifs_crypto_shash_allocate_ret1; -	} - -	size = sizeof(struct shash_desc) + -			crypto_shash_descsize(server->ntlmssp.hmacmd5); -	server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); -	if (!server->ntlmssp.sdeschmacmd5) { -		cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); -		rc = -ENOMEM; -		goto cifs_crypto_shash_allocate_ret2; -	} -	server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5; -	server->ntlmssp.sdeschmacmd5->shash.flags = 0x0; +	struct HMACMD5Context context; +	/* rest of v2 struct already generated */ +	memcpy(v2_session_response + 8, ses->server->cryptKey, 8); +	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); +	hmac_md5_update(v2_session_response+8, +			sizeof(struct ntlmv2_resp) - 8, &context); -	size = sizeof(struct shash_desc) + -			crypto_shash_descsize(server->ntlmssp.md5); -	server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL); -	if (!server->ntlmssp.sdescmd5) { -		cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); -		rc = -ENOMEM; -		goto cifs_crypto_shash_allocate_ret3; -	} -	server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5; -	server->ntlmssp.sdescmd5->shash.flags = 0x0; - -	return 0; - -cifs_crypto_shash_allocate_ret3: -	kfree(server->ntlmssp.sdeschmacmd5); - -cifs_crypto_shash_allocate_ret2: -	crypto_free_shash(server->ntlmssp.md5); - -cifs_crypto_shash_allocate_ret1: -	crypto_free_shash(server->ntlmssp.hmacmd5); - -	return rc; +	hmac_md5_final(v2_session_response, &context); +/*	cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */  } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c9d0cfc086eb..0cdfb8c32ac6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -25,9 +25,6 @@  #include <linux/workqueue.h>  #include "cifs_fs_sb.h"  #include "cifsacl.h" -#include <crypto/internal/hash.h> -#include <linux/scatterlist.h> -  /*   * The sizes of various internal tables and strings   */ @@ -100,7 +97,7 @@ enum protocolEnum {  	/* Netbios frames protocol not supported at this time */  }; -struct session_key { +struct mac_key {  	unsigned int len;  	union {  		char ntlm[CIFS_SESS_KEY_SIZE + 16]; @@ -123,21 +120,6 @@ struct cifs_cred {  	struct cifs_ace *aces;  }; -struct sdesc { -	struct shash_desc shash; -	char ctx[]; -}; - -struct ntlmssp_auth { -	__u32 client_flags; -	__u32 server_flags; -	unsigned char ciphertext[CIFS_CPHTXT_SIZE]; -	struct crypto_shash *hmacmd5; -	struct crypto_shash *md5; -	struct sdesc *sdeschmacmd5; -	struct sdesc *sdescmd5; -}; -  /*   *****************************************************************   * Except the CIFS PDUs themselves all the @@ -200,14 +182,11 @@ struct TCP_Server_Info {  	/* 16th byte of RFC1001 workstation name is always null */  	char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];  	__u32 sequence_number; /* needed for CIFS PDU signature */ -	struct session_key session_key; +	struct mac_key mac_signing_key;  	char ntlmv2_hash[16];  	unsigned long lstrp; /* when we got last response from this server */  	u16 dialect; /* dialect index that server chose */  	/* extended security flavors that server supports */ -	unsigned int tilen; /* length of the target info blob */ -	unsigned char *tiblob; /* target info blob in challenge response */ -	struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */  	bool	sec_kerberos;		/* supports plain Kerberos */  	bool	sec_mskerberos;		/* supports legacy MS Kerberos */  	bool	sec_kerberosu2u;	/* supports U2U Kerberos */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 320e0fd0ba7b..14d036d8db11 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -134,12 +134,6 @@   * Size of the session key (crypto key encrypted with the password   */  #define CIFS_SESS_KEY_SIZE (24) -#define CIFS_CLIENT_CHALLENGE_SIZE (8) -#define CIFS_SERVER_CHALLENGE_SIZE (8) -#define CIFS_HMAC_MD5_HASH_SIZE (16) -#define CIFS_CPHTXT_SIZE (16) -#define CIFS_NTLMV2_SESSKEY_SIZE (16) -#define CIFS_NTHASH_SIZE (16)  /*   * Maximum user name length @@ -669,6 +663,7 @@ struct ntlmv2_resp {  	__le64  time;  	__u64  client_chal; /* random */  	__u32  reserved2; +	struct ntlmssp2_name names[2];  	/* array of name entries could follow ending in minimum 4 byte struct */  } __attribute__((packed)); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1378d9133844..1d60c655e3e0 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);  extern int decode_negTokenInit(unsigned char *security_blob, int length,  			struct TCP_Server_Info *server);  extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); +extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);  extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, -				unsigned short int port); +				const unsigned short int port);  extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);  extern void header_assemble(struct smb_hdr *, char /* command */ ,  			    const struct cifsTconInfo *, int /* length of @@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);  extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,  			  __u32 *);  extern int cifs_verify_signature(struct smb_hdr *, -				 struct TCP_Server_Info *server, +				 const struct mac_key *mac_key,  				__u32 expected_sequence_number); -extern int cifs_calculate_session_key(struct session_key *key, const char *rn, +extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,  				 const char *pass); -extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, +extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); +extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,  			     const struct nls_table *); -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); -extern void cifs_crypto_shash_release(struct TCP_Server_Info *); -extern int calc_seckey(struct TCP_Server_Info *);  #ifdef CONFIG_CIFS_WEAK_PW_HASH  extern void calc_lanman_hash(const char *password, const char *cryptkey,  				bool encrypt, char *lnm_session_key); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4bda920d1f75..c65c3419dd37 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -604,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)  			else  				rc = -EINVAL; -			if (server->secType == Kerberos) { -				if (!server->sec_kerberos && -						!server->sec_mskerberos) -					rc = -EOPNOTSUPP; -			} else if (server->secType == RawNTLMSSP) { -				if (!server->sec_ntlmssp) -					rc = -EOPNOTSUPP; -			} else +			if (server->sec_kerberos || server->sec_mskerberos) +				server->secType = Kerberos; +			else if (server->sec_ntlmssp) +				server->secType = RawNTLMSSP; +			else  				rc = -EOPNOTSUPP;  		}  	} else diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec0ea4a43bdb..67dad54fbfa1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -400,7 +400,9 @@ incomplete_rcv:  			cFYI(1, "call to reconnect done");  			csocket = server->ssocket;  			continue; -		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { +		} else if (length == -ERESTARTSYS || +			   length == -EAGAIN || +			   length == -EINTR) {  			msleep(1); /* minimum sleep to prevent looping  				allowing socket to clear and app threads to set  				tcpStatus CifsNeedReconnect if server hung */ @@ -414,18 +416,6 @@ incomplete_rcv:  			} else  				continue;  		} else if (length <= 0) { -			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 (!try_to_freeze() && (length == -EINTR)) { -				cFYI(1, "cifsd thread killed"); -				break; -			}  			cFYI(1, "Reconnect after unexpected peek error %d",  				length);  			cifs_reconnect(server); @@ -466,27 +456,19 @@ incomplete_rcv:  			   an error on SMB negprot response */  			cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",  				pdu_length); -			if (server->tcpStatus == CifsNew) { -				/* if nack on negprot (rather than -				ret of smb negprot error) reconnecting -				not going to help, ret error to mount */ -				break; -			} else { -				/* give server a second to -				clean up before reconnect attempt */ -				msleep(1000); -				/* always try 445 first on reconnect -				since we get NACK on some if we ever -				connected to port 139 (the NACK is -				since we do not begin with RFC1001 -				session initialize frame) */ -				server->addr.sockAddr.sin_port = -					htons(CIFS_PORT); -				cifs_reconnect(server); -				csocket = server->ssocket; -				wake_up(&server->response_q); -				continue; -			} +			/* give server a second to clean up  */ +			msleep(1000); +			/* always try 445 first on reconnect since we get NACK +			 * on some if we ever connected to port 139 (the NACK +			 * is since we do not begin with RFC1001 session +			 * initialize frame) +			 */ +			cifs_set_port((struct sockaddr *) +					&server->addr.sockAddr, CIFS_PORT); +			cifs_reconnect(server); +			csocket = server->ssocket; +			wake_up(&server->response_q); +			continue;  		} else if (temp != (char) 0) {  			cERROR(1, "Unknown RFC 1002 frame");  			cifs_dump_mem(" Received Data: ", (char *)smb_buffer, @@ -522,8 +504,7 @@ incomplete_rcv:  		     total_read += length) {  			length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,  						pdu_length - total_read, 0); -			if ((server->tcpStatus == CifsExiting) || -			    (length == -EINTR)) { +			if (server->tcpStatus == CifsExiting) {  				/* then will exit */  				reconnect = 2;  				break; @@ -534,8 +515,9 @@ incomplete_rcv:  				/* Now we will reread sock */  				reconnect = 1;  				break; -			} else if ((length == -ERESTARTSYS) || -				   (length == -EAGAIN)) { +			} else if (length == -ERESTARTSYS || +				   length == -EAGAIN || +				   length == -EINTR) {  				msleep(1); /* minimum sleep to prevent looping,  					      allowing socket to clear and app  					      threads to set tcpStatus @@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)  		CIFSSMBLogoff(xid, ses);  		_FreeXid(xid);  	} -	cifs_crypto_shash_release(server);  	sesInfoFree(ses);  	cifs_put_tcp_session(server);  } @@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)  	ses->linux_uid = volume_info->linux_uid;  	ses->overrideSecFlg = volume_info->secFlg; -	rc = cifs_crypto_shash_allocate(server); -	if (rc) { -		cERROR(1, "could not setup hash structures rc %d", rc); -		goto get_ses_fail; -	} -	server->tilen = 0; -	server->tiblob = NULL; -  	mutex_lock(&ses->session_mutex);  	rc = cifs_negotiate_protocol(xid, ses);  	if (!rc)  		rc = cifs_setup_session(xid, ses, volume_info->local_nls);  	mutex_unlock(&ses->session_mutex); -	if (rc) { -		cifs_crypto_shash_release(ses->server); +	if (rc)  		goto get_ses_fail; -	}  	/* success, put it on the list */  	write_lock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86a164f08a74..93f77d438d3c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1462,29 +1462,18 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,  {  	char *fromName = NULL;  	char *toName = NULL; -	struct cifs_sb_info *cifs_sb_source; -	struct cifs_sb_info *cifs_sb_target; +	struct cifs_sb_info *cifs_sb;  	struct cifsTconInfo *tcon;  	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;  	FILE_UNIX_BASIC_INFO *info_buf_target;  	int xid, rc, tmprc; -	cifs_sb_target = CIFS_SB(target_dir->i_sb); -	cifs_sb_source = CIFS_SB(source_dir->i_sb); -	tcon = cifs_sb_source->tcon; +	cifs_sb = CIFS_SB(source_dir->i_sb); +	tcon = cifs_sb->tcon;  	xid = GetXid();  	/* -	 * BB: this might be allowed if same server, but different share. -	 * Consider adding support for this -	 */ -	if (tcon != cifs_sb_target->tcon) { -		rc = -EXDEV; -		goto cifs_rename_exit; -	} - -	/*  	 * we already have the rename sem so we do not need to  	 * grab it again here to protect the path integrity  	 */ @@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,  		info_buf_target = info_buf_source + 1;  		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,  					info_buf_source, -					cifs_sb_source->local_nls, -					cifs_sb_source->mnt_cifs_flags & +					cifs_sb->local_nls, +					cifs_sb->mnt_cifs_flags &  					CIFS_MOUNT_MAP_SPECIAL_CHR);  		if (tmprc != 0)  			goto unlink_target; -		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, -					toName, info_buf_target, -					cifs_sb_target->local_nls, -					/* remap based on source sb */ -					cifs_sb_source->mnt_cifs_flags & +		tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, +					info_buf_target, +					cifs_sb->local_nls, +					cifs_sb->mnt_cifs_flags &  					CIFS_MOUNT_MAP_SPECIAL_CHR);  		if (tmprc == 0 && (info_buf_source->UniqueId == diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f97851119e6c..9aad47a2d62f 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len)  }  int -cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, -		   const unsigned short int port) +cifs_set_port(struct sockaddr *addr, const unsigned short int port)  { -	if (!cifs_convert_address(dst, src, len)) -		return 0; - -	switch (dst->sa_family) { +	switch (addr->sa_family) {  	case AF_INET: -		((struct sockaddr_in *)dst)->sin_port = htons(port); +		((struct sockaddr_in *)addr)->sin_port = htons(port);  		break;  	case AF_INET6: -		((struct sockaddr_in6 *)dst)->sin6_port = htons(port); +		((struct sockaddr_in6 *)addr)->sin6_port = htons(port);  		break;  	default:  		return 0;  	} -  	return 1;  } +int +cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, +		   const unsigned short int port) +{ +	if (!cifs_convert_address(dst, src, len)) +		return 0; +	return cifs_set_port(dst, port); +} +  /*****************************************************************************  convert a NT status code to a dos class/code   *****************************************************************************/ diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 1db0f0746a5b..49c9a4e75319 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -61,19 +61,6 @@  #define NTLMSSP_NEGOTIATE_KEY_XCH   0x40000000  #define NTLMSSP_NEGOTIATE_56        0x80000000 -/* Define AV Pair Field IDs */ -#define NTLMSSP_AV_EOL			0 -#define NTLMSSP_AV_NB_COMPUTER_NAME	1 -#define NTLMSSP_AV_NB_DOMAIN_NAME	2 -#define NTLMSSP_AV_DNS_COMPUTER_NAME	3 -#define NTLMSSP_AV_DNS_DOMAIN_NAME	4 -#define NTLMSSP_AV_DNS_TREE_NAME	5 -#define NTLMSSP_AV_FLAGS		6 -#define NTLMSSP_AV_TIMESTAMP		7 -#define NTLMSSP_AV_RESTRICTION		8 -#define NTLMSSP_AV_TARGET_NAME		9 -#define NTLMSSP_AV_CHANNEL_BINDINGS	10 -  /* Although typedefs are not commonly used for structure definitions */  /* in the Linux kernel, in this particular case they are useful      */  /* to more closely match the standards document for NTLMSSP from     */ diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 795095f4eac6..0a57cb7db5dd 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -383,9 +383,6 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,  static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,  				    struct cifsSesInfo *ses)  { -	unsigned int tioffset; /* challeng message target info area */ -	unsigned int tilen; /* challeng message target info area length  */ -  	CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;  	if (blob_len < sizeof(CHALLENGE_MESSAGE)) { @@ -408,20 +405,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,  	/* BB spec says that if AvId field of MsvAvTimestamp is populated then  		we must set the MIC field of the AUTHENTICATE_MESSAGE */ -	ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); - -	tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); -	tilen = cpu_to_le16(pblob->TargetInfoArray.Length); -	ses->server->tilen = tilen; -	if (tilen) { -		ses->server->tiblob = kmalloc(tilen, GFP_KERNEL); -		if (!ses->server->tiblob) { -			cERROR(1, "Challenge target info allocation failure"); -			return -ENOMEM; -		} -		memcpy(ses->server->tiblob,  bcc_ptr + tioffset, tilen); -	} -  	return 0;  } @@ -442,13 +425,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,  	/* BB is NTLMV2 session security format easier to use here? */  	flags = NTLMSSP_NEGOTIATE_56 |	NTLMSSP_REQUEST_TARGET |  		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | -		NTLMSSP_NEGOTIATE_NTLM; +		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;  	if (ses->server->secMode & -	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { -		flags |= NTLMSSP_NEGOTIATE_SIGN | -			NTLMSSP_NEGOTIATE_KEY_XCH | -			NTLMSSP_NEGOTIATE_EXTENDED_SEC; -	} +	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) +		flags |= NTLMSSP_NEGOTIATE_SIGN; +	if (ses->server->secMode & SECMODE_SIGN_REQUIRED) +		flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;  	sec_blob->NegotiateFlags |= cpu_to_le32(flags); @@ -469,12 +451,10 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,  				   struct cifsSesInfo *ses,  				   const struct nls_table *nls_cp, bool first)  { -	int rc; -	unsigned int size;  	AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;  	__u32 flags;  	unsigned char *tmp; -	struct ntlmv2_resp ntlmv2_response = {}; +	char ntlm_session_key[CIFS_SESS_KEY_SIZE];  	memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);  	sec_blob->MessageType = NtLmAuthenticate; @@ -497,25 +477,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,  	sec_blob->LmChallengeResponse.Length = 0;  	sec_blob->LmChallengeResponse.MaximumLength = 0; -	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); -	rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); -	if (rc) { -		cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); -		goto setup_ntlmv2_ret; -	} -	size =  sizeof(struct ntlmv2_resp); -	memcpy(tmp, (char *)&ntlmv2_response, size); -	tmp += size; -	if (ses->server->tilen > 0) { -		memcpy(tmp, ses->server->tiblob, ses->server->tilen); -		tmp += ses->server->tilen; -	} else -		ses->server->tilen = 0; +	/* calculate session key,  BB what about adding similar ntlmv2 path? */ +	SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); +	if (first) +		cifs_calculate_mac_key(&ses->server->mac_signing_key, +				       ntlm_session_key, ses->password); -	sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + -				ses->server->tilen); +	memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); +	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); +	sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);  	sec_blob->NtChallengeResponse.MaximumLength = -		cpu_to_le16(size + ses->server->tilen); +				cpu_to_le16(CIFS_SESS_KEY_SIZE); + +	tmp += CIFS_SESS_KEY_SIZE;  	if (ses->domainName == NULL) {  		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); @@ -527,6 +501,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,  		len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,  				    MAX_USERNAME_SIZE, nls_cp);  		len *= 2; /* unicode is 2 bytes each */ +		len += 2; /* trailing null */  		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); @@ -543,6 +518,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,  		len = cifs_strtoUCS((__le16 *)tmp, ses->userName,  				    MAX_USERNAME_SIZE, nls_cp);  		len *= 2; /* unicode is 2 bytes each */ +		len += 2; /* trailing null */  		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); @@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,  	sec_blob->WorkstationName.MaximumLength = 0;  	tmp += 2; -	if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && -			!calc_seckey(ses->server)) { -		memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); -		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); -		sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); -		sec_blob->SessionKey.MaximumLength = -			cpu_to_le16(CIFS_CPHTXT_SIZE); -		tmp += CIFS_CPHTXT_SIZE; -	} else { -		sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); -		sec_blob->SessionKey.Length = 0; -		sec_blob->SessionKey.MaximumLength = 0; -	} - -	ses->server->sequence_number = 0; - -setup_ntlmv2_ret: -	if (ses->server->tilen > 0) -		kfree(ses->server->tiblob); - +	sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); +	sec_blob->SessionKey.Length = 0; +	sec_blob->SessionKey.MaximumLength = 0;  	return tmp - pbuffer;  } @@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,  	return;  } -static int setup_ntlmssp_auth_req(char *ntlmsspblob, +static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,  				  struct cifsSesInfo *ses,  				  const struct nls_table *nls, bool first_time)  {  	int bloblen; -	bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, +	bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,  					  first_time); +	pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);  	return bloblen;  } @@ -730,7 +690,7 @@ ssetup_ntlmssp_authenticate:  		if (first_time) /* should this be moved into common code  				  with similar ntlmv2 path? */ -			cifs_calculate_session_key(&ses->server->session_key, +			cifs_calculate_mac_key(&ses->server->mac_signing_key,  				ntlm_session_key, ses->password);  		/* copy session key */ @@ -769,21 +729,12 @@ ssetup_ntlmssp_authenticate:  			cpu_to_le16(sizeof(struct ntlmv2_resp));  		/* calculate session key */ -		rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); -		if (rc) { -			kfree(v2_sess_key); -			goto ssetup_exit; -		} +		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);  		/* FIXME: calculate MAC key */  		memcpy(bcc_ptr, (char *)v2_sess_key,  		       sizeof(struct ntlmv2_resp));  		bcc_ptr += sizeof(struct ntlmv2_resp);  		kfree(v2_sess_key); -		if (ses->server->tilen > 0) { -			memcpy(bcc_ptr, ses->server->tiblob, -				ses->server->tilen); -			bcc_ptr += ses->server->tilen; -		}  		if (ses->capabilities & CAP_UNICODE) {  			if (iov[0].iov_len % 2) {  				*bcc_ptr = 0; @@ -814,15 +765,15 @@ ssetup_ntlmssp_authenticate:  		}  		/* bail out if key is too long */  		if (msg->sesskey_len > -		    sizeof(ses->server->session_key.data.krb5)) { +		    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;  		}  		if (first_time) { -			ses->server->session_key.len = msg->sesskey_len; -			memcpy(ses->server->session_key.data.krb5, +			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; @@ -864,28 +815,12 @@ ssetup_ntlmssp_authenticate:  			if (phase == NtLmNegotiate) {  				setup_ntlmssp_neg_req(pSMB, ses);  				iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); -				iov[1].iov_base = &pSMB->req.SecurityBlob[0];  			} else if (phase == NtLmAuthenticate) {  				int blob_len; -				char *ntlmsspblob; - -				ntlmsspblob = kmalloc(5 * -					sizeof(struct _AUTHENTICATE_MESSAGE), -					GFP_KERNEL); -				if (!ntlmsspblob) { -					cERROR(1, "Can't allocate NTLMSSP"); -					rc = -ENOMEM; -					goto ssetup_exit; -				} - -				blob_len = setup_ntlmssp_auth_req(ntlmsspblob, -								ses, -								nls_cp, -								first_time); +				blob_len = setup_ntlmssp_auth_req(pSMB, ses, +								  nls_cp, +								  first_time);  				iov[1].iov_len = blob_len; -				iov[1].iov_base = ntlmsspblob; -				pSMB->req.SecurityBlobLength = -					cpu_to_le16(blob_len);  				/* Make sure that we tell the server that we  				   are using the uid that it just gave us back  				   on the response (challenge) */ @@ -895,6 +830,7 @@ ssetup_ntlmssp_authenticate:  				rc = -ENOSYS;  				goto ssetup_exit;  			} +			iov[1].iov_base = &pSMB->req.SecurityBlob[0];  			/* unicode strings must be word aligned */  			if ((iov[0].iov_len + iov[1].iov_len) % 2) {  				*bcc_ptr = 0; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index e0588cdf4cc5..82f78c4d6978 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,  		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |  					     SECMODE_SIGN_ENABLED))) {  			rc = cifs_verify_signature(midQ->resp_buf, -						ses->server, +						&ses->server->mac_signing_key,  						midQ->sequence_number+1);  			if (rc) {  				cERROR(1, "Unexpected SMB signature"); @@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,  		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |  					     SECMODE_SIGN_ENABLED))) {  			rc = cifs_verify_signature(out_buf, -						ses->server, +						&ses->server->mac_signing_key,  						midQ->sequence_number+1);  			if (rc) {  				cERROR(1, "Unexpected SMB signature"); @@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,  	    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |  				     SECMODE_SIGN_ENABLED))) {  		rc = cifs_verify_signature(out_buf, -					   ses->server, +					   &ses->server->mac_signing_key,  					   midQ->sequence_number+1);  		if (rc) {  			cERROR(1, "Unexpected SMB signature"); diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad49d731..f7e13db613cb 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -63,6 +63,7 @@ config NFS_V3_ACL  config NFS_V4  	bool "NFS client support for NFS version 4"  	depends on NFS_FS +	select SUNRPC_GSS  	help  	  This option enables support for version 4 of the NFS protocol  	  (RFC 3530) in the kernel's NFS client. diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2adb212..e7340729af89 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,  	    sin1->sin6_scope_id != sin2->sin6_scope_id)  		return 0; -	return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); +	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);  }  #else	/* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */  static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6201da..05bf3c0dc751 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)  		default:  			BUG();  	} -	if (res < 0) -		dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" -			" - error %d!\n", -				__func__, res);  	return res;  } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e4706b..f4cbf0c306c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)  		goto out_err;  	error = server->nfs_client->rpc_ops->statfs(server, fh, &res); +	if (unlikely(error == -ESTALE)) { +		struct dentry *pd_dentry; +		pd_dentry = dget_parent(dentry); +		if (pd_dentry != NULL) { +			nfs_zap_caches(pd_dentry->d_inode); +			dput(pd_dentry); +		} +	}  	nfs_free_fattr(res.fattr);  	if (error < 0)  		goto out_err; diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f523aef..4264377552e2 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -69,6 +69,7 @@ config NFSD_V4  	depends on NFSD && PROC_FS && EXPERIMENTAL  	select NFSD_V3  	select FS_POSIX_ACL +	select SUNRPC_GSS  	help  	  This option enables support in your system's NFS server for  	  version 4 of the NFS protocol (RFC 3530). | 
