Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bfe01ef authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS/SMB3 updates from Steve French:
 "Includes support for a critical SMB3 security feature: per-share
  encryption from Pavel, and a cleanup from Jean Delvare.

  Will have another cifs/smb3 merge next week"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Allow to switch on encryption with seal mount option
  CIFS: Add capability to decrypt big read responses
  CIFS: Decrypt and process small encrypted packets
  CIFS: Add copy into pages callback for a read operation
  CIFS: Add mid handle callback
  CIFS: Add transform header handling callbacks
  CIFS: Encrypt SMB3 requests before sending
  CIFS: Enable encryption during session setup phase
  CIFS: Add capability to transform requests before sending
  CIFS: Separate RFC1001 length processing for SMB2 read
  CIFS: Separate SMB2 sync header processing
  CIFS: Send RFC1001 length in a separate iov
  CIFS: Make send_cancel take rqst as argument
  CIFS: Make SendReceive2() takes resp iov
  CIFS: Separate SMB2 header structure
  CIFS: Fix splice read for non-cached files
  cifs: Add soft dependencies
  cifs: Only select the required crypto modules
  cifs: Simplify SMB2 and SMB311 dependencies
parents cab7076a ae6f8dd4
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -9,8 +9,6 @@ config CIFS
	select CRYPTO_ARC4
	select CRYPTO_ECB
	select CRYPTO_DES
	select CRYPTO_SHA256
	select CRYPTO_CMAC
	help
	  This is the client VFS module for the Common Internet File System
	  (CIFS) protocol which is the successor to the Server Message Block
@@ -169,11 +167,15 @@ config CIFS_NFSD_EXPORT

config CIFS_SMB2
	bool "SMB2 and SMB3 network file system support"
	depends on CIFS && INET
	select NLS
	depends on CIFS
	select KEYS
	select FSCACHE
	select DNS_RESOLVER
	select CRYPTO_AES
	select CRYPTO_SHA256
	select CRYPTO_CMAC
	select CRYPTO_AEAD2
	select CRYPTO_CCM

	help
	  This enables support for the Server Message Block version 2
@@ -194,7 +196,7 @@ config CIFS_SMB2

config CIFS_SMB311
	bool "SMB3.1.1 network file system support (Experimental)"
	depends on CIFS_SMB2 && INET
	depends on CIFS_SMB2

	help
	  This enables experimental support for the newest, SMB3.1.1, dialect.
+34 −17
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/random.h>
#include <linux/highmem.h>
#include <crypto/skcipher.h>
#include <crypto/aead.h>

static int
cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
@@ -75,24 +76,20 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
	struct kvec *iov = rqst->rq_iov;
	int n_vec = rqst->rq_nvec;

	for (i = 0; i < n_vec; i++) {
	if (n_vec < 2 || iov[0].iov_len != 4)
		return -EIO;

	for (i = 1; i < n_vec; i++) {
		if (iov[i].iov_len == 0)
			continue;
		if (iov[i].iov_base == NULL) {
			cifs_dbg(VFS, "null iovec entry\n");
			return -EIO;
		}
		/* The first entry includes a length field (which does not get
		   signed that occupies the first 4 bytes before the header */
		if (i == 0) {
			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
		if (i == 1 && iov[1].iov_len <= 4)
			break; /* nothing to sign or corrupt header */
			rc = crypto_shash_update(shash,
				iov[i].iov_base + 4, iov[i].iov_len - 4);
		} else {
		rc = crypto_shash_update(shash,
					 iov[i].iov_base, iov[i].iov_len);
		}
		if (rc) {
			cifs_dbg(VFS, "%s: Could not update with payload\n",
				 __func__);
@@ -168,6 +165,10 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
	char smb_signature[20];
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;

	if (rqst->rq_iov[0].iov_len != 4 ||
	    rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
		return -EIO;

	if ((cifs_pdu == NULL) || (server == NULL))
		return -EINVAL;

@@ -209,12 +210,14 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
		  __u32 *pexpected_response_sequence_number)
{
	struct kvec iov;
	struct kvec iov[2];

	iov.iov_base = cifs_pdu;
	iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
	iov[0].iov_base = cifs_pdu;
	iov[0].iov_len = 4;
	iov[1].iov_base = (char *)cifs_pdu + 4;
	iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);

	return cifs_sign_smbv(&iov, 1, server,
	return cifs_sign_smbv(iov, 2, server,
			      pexpected_response_sequence_number);
}

@@ -227,6 +230,10 @@ int cifs_verify_signature(struct smb_rqst *rqst,
	char what_we_think_sig_should_be[20];
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;

	if (rqst->rq_iov[0].iov_len != 4 ||
	    rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
		return -EIO;

	if (cifs_pdu == NULL || server == NULL)
		return -EINVAL;

@@ -868,7 +875,7 @@ calc_seckey(struct cifs_ses *ses)
}

void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
cifs_crypto_secmech_release(struct TCP_Server_Info *server)
{
	if (server->secmech.cmacaes) {
		crypto_free_shash(server->secmech.cmacaes);
@@ -890,6 +897,16 @@ cifs_crypto_shash_release(struct TCP_Server_Info *server)
		server->secmech.hmacmd5 = NULL;
	}

	if (server->secmech.ccmaesencrypt) {
		crypto_free_aead(server->secmech.ccmaesencrypt);
		server->secmech.ccmaesencrypt = NULL;
	}

	if (server->secmech.ccmaesdecrypt) {
		crypto_free_aead(server->secmech.ccmaesdecrypt);
		server->secmech.ccmaesdecrypt = NULL;
	}

	kfree(server->secmech.sdesccmacaes);
	server->secmech.sdesccmacaes = NULL;
	kfree(server->secmech.sdeschmacsha256);
+14 −0
Original line number Diff line number Diff line
@@ -1365,5 +1365,19 @@ MODULE_DESCRIPTION
    ("VFS to access servers complying with the SNIA CIFS Specification "
     "e.g. Samba and Windows");
MODULE_VERSION(CIFS_VERSION);
MODULE_SOFTDEP("pre: arc4");
MODULE_SOFTDEP("pre: des");
MODULE_SOFTDEP("pre: ecb");
MODULE_SOFTDEP("pre: hmac");
MODULE_SOFTDEP("pre: md4");
MODULE_SOFTDEP("pre: md5");
MODULE_SOFTDEP("pre: nls");
#ifdef CONFIG_CIFS_SMB2
MODULE_SOFTDEP("pre: aes");
MODULE_SOFTDEP("pre: cmac");
MODULE_SOFTDEP("pre: sha256");
MODULE_SOFTDEP("pre: aead2");
MODULE_SOFTDEP("pre: ccm");
#endif /* CONFIG_CIFS_SMB2 */
module_init(init_cifs)
module_exit(exit_cifs)
+26 −2
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ struct cifs_secmech {
	struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
	struct sdesc *sdeschmacsha256;  /* ctxt to generate smb2 signature */
	struct sdesc *sdesccmacaes;  /* ctxt to generate smb3 signature */
	struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */
	struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */
};

/* per smb session structure/fields */
@@ -208,7 +210,7 @@ struct cifsInodeInfo;
struct cifs_open_parms;

struct smb_version_operations {
	int (*send_cancel)(struct TCP_Server_Info *, void *,
	int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *,
			   struct mid_q_entry *);
	bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *);
	/* setup request: allocate mid, sign message */
@@ -433,6 +435,14 @@ struct smb_version_operations {
	bool (*dir_needs_close)(struct cifsFileInfo *);
	long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
			  loff_t);
	/* init transform request - used for encryption for now */
	int (*init_transform_rq)(struct TCP_Server_Info *, struct smb_rqst *,
				 struct smb_rqst *);
	/* free transform request */
	void (*free_transform_rq)(struct smb_rqst *);
	int (*is_transform_hdr)(void *buf);
	int (*receive_transform)(struct TCP_Server_Info *,
				 struct mid_q_entry **);
};

struct smb_version_values {
@@ -1119,7 +1129,10 @@ struct cifs_readdata {
	int (*read_into_pages)(struct TCP_Server_Info *server,
				struct cifs_readdata *rdata,
				unsigned int len);
	struct kvec			iov;
	int (*copy_into_pages)(struct TCP_Server_Info *server,
				struct cifs_readdata *rdata,
				struct iov_iter *iter);
	struct kvec			iov[2];
	unsigned int			pagesz;
	unsigned int			tailsz;
	unsigned int			credits;
@@ -1302,6 +1315,13 @@ typedef int (mid_receive_t)(struct TCP_Server_Info *server,
 */
typedef void (mid_callback_t)(struct mid_q_entry *mid);

/*
 * This is the protopyte for mid handle function. This is called once the mid
 * has been recognized after decryption of the message.
 */
typedef int (mid_handle_t)(struct TCP_Server_Info *server,
			    struct mid_q_entry *mid);

/* one of these for every pending CIFS request to the server */
struct mid_q_entry {
	struct list_head qhead;	/* mids waiting on reply from this server */
@@ -1316,6 +1336,7 @@ struct mid_q_entry {
#endif
	mid_receive_t *receive; /* call receive callback */
	mid_callback_t *callback; /* call completion callback */
	mid_handle_t *handle; /* call handle mid callback */
	void *callback_data;	  /* general purpose pointer for callback */
	void *resp_buf;		/* pointer to received SMB header */
	int mid_state;	/* wish this were enum but can not pass to wait_event */
@@ -1323,6 +1344,7 @@ struct mid_q_entry {
	bool large_buf:1;	/* if valid response, is pointer to large buf */
	bool multiRsp:1;	/* multiple trans2 responses for one request  */
	bool multiEnd:1;	/* both received */
	bool decrypted:1;	/* decrypted entry */
};

/*	Make code in transport.c a little cleaner by moving
@@ -1475,7 +1497,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define   CIFS_OBREAK_OP   0x0100    /* oplock break request */
#define   CIFS_NEG_OP      0x0200    /* negotiate request */
#define   CIFS_OP_MASK     0x0380    /* mask request type */

#define   CIFS_HAS_CREDITS 0x0400    /* already has credits */
#define   CIFS_TRANSFORM_REQ 0x0800    /* transform request before sending */

/* Security Flags: indicate type of session setup needed */
#define   CIFSSEC_MAY_SIGN	0x00001
+10 −3
Original line number Diff line number Diff line
@@ -75,10 +75,16 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
extern void cifs_delete_mid(struct mid_q_entry *mid);
extern void cifs_wake_up_task(struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server,
				struct mid_q_entry *mid);
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
extern int cifs_call_async(struct TCP_Server_Info *server,
			struct smb_rqst *rqst,
			mid_receive_t *receive, mid_callback_t *callback,
			void *cbdata, const int flags);
			mid_handle_t *handle, void *cbdata, const int flags);
extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
			  struct smb_rqst *rqst, int *resp_buf_type,
			  const int flags, struct kvec *resp_iov);
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
			struct smb_hdr * /* input */ ,
			struct smb_hdr * /* out */ ,
@@ -96,7 +102,8 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server,
				 unsigned int *credits);
extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
			struct kvec *, int /* nvec to send */,
			int * /* type of buf returned */ , const int flags);
			int * /* type of buf returned */, const int flags,
			struct kvec * /* resp vec */);
extern int SendReceiveBlockingLock(const unsigned int xid,
			struct cifs_tcon *ptcon,
			struct smb_hdr *in_buf ,
@@ -441,7 +448,7 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
			const struct nls_table *);
extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
extern int calc_seckey(struct cifs_ses *);
extern int generate_smb30signingkey(struct cifs_ses *);
extern int generate_smb311signingkey(struct cifs_ses *);
Loading