Skip to content

Commit 2bfe01e

Browse files
committed
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
2 parents cab7076 + ae6f8dd commit 2bfe01e

File tree

19 files changed

+1582
-479
lines changed

19 files changed

+1582
-479
lines changed

fs/cifs/Kconfig

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ config CIFS
99
select CRYPTO_ARC4
1010
select CRYPTO_ECB
1111
select CRYPTO_DES
12-
select CRYPTO_SHA256
13-
select CRYPTO_CMAC
1412
help
1513
This is the client VFS module for the Common Internet File System
1614
(CIFS) protocol which is the successor to the Server Message Block
@@ -169,11 +167,15 @@ config CIFS_NFSD_EXPORT
169167

170168
config CIFS_SMB2
171169
bool "SMB2 and SMB3 network file system support"
172-
depends on CIFS && INET
173-
select NLS
170+
depends on CIFS
174171
select KEYS
175172
select FSCACHE
176173
select DNS_RESOLVER
174+
select CRYPTO_AES
175+
select CRYPTO_SHA256
176+
select CRYPTO_CMAC
177+
select CRYPTO_AEAD2
178+
select CRYPTO_CCM
177179

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

195197
config CIFS_SMB311
196198
bool "SMB3.1.1 network file system support (Experimental)"
197-
depends on CIFS_SMB2 && INET
199+
depends on CIFS_SMB2
198200

199201
help
200202
This enables experimental support for the newest, SMB3.1.1, dialect.

fs/cifs/cifsencrypt.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/random.h>
3535
#include <linux/highmem.h>
3636
#include <crypto/skcipher.h>
37+
#include <crypto/aead.h>
3738

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

78-
for (i = 0; i < n_vec; i++) {
79+
if (n_vec < 2 || iov[0].iov_len != 4)
80+
return -EIO;
81+
82+
for (i = 1; i < n_vec; i++) {
7983
if (iov[i].iov_len == 0)
8084
continue;
8185
if (iov[i].iov_base == NULL) {
8286
cifs_dbg(VFS, "null iovec entry\n");
8387
return -EIO;
8488
}
85-
/* The first entry includes a length field (which does not get
86-
signed that occupies the first 4 bytes before the header */
87-
if (i == 0) {
88-
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
89-
break; /* nothing to sign or corrupt header */
90-
rc = crypto_shash_update(shash,
91-
iov[i].iov_base + 4, iov[i].iov_len - 4);
92-
} else {
93-
rc = crypto_shash_update(shash,
94-
iov[i].iov_base, iov[i].iov_len);
95-
}
89+
if (i == 1 && iov[1].iov_len <= 4)
90+
break; /* nothing to sign or corrupt header */
91+
rc = crypto_shash_update(shash,
92+
iov[i].iov_base, iov[i].iov_len);
9693
if (rc) {
9794
cifs_dbg(VFS, "%s: Could not update with payload\n",
9895
__func__);
@@ -168,6 +165,10 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
168165
char smb_signature[20];
169166
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
170167

168+
if (rqst->rq_iov[0].iov_len != 4 ||
169+
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
170+
return -EIO;
171+
171172
if ((cifs_pdu == NULL) || (server == NULL))
172173
return -EINVAL;
173174

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

214-
iov.iov_base = cifs_pdu;
215-
iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
215+
iov[0].iov_base = cifs_pdu;
216+
iov[0].iov_len = 4;
217+
iov[1].iov_base = (char *)cifs_pdu + 4;
218+
iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
216219

217-
return cifs_sign_smbv(&iov, 1, server,
220+
return cifs_sign_smbv(iov, 2, server,
218221
pexpected_response_sequence_number);
219222
}
220223

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

233+
if (rqst->rq_iov[0].iov_len != 4 ||
234+
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
235+
return -EIO;
236+
230237
if (cifs_pdu == NULL || server == NULL)
231238
return -EINVAL;
232239

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

870877
void
871-
cifs_crypto_shash_release(struct TCP_Server_Info *server)
878+
cifs_crypto_secmech_release(struct TCP_Server_Info *server)
872879
{
873880
if (server->secmech.cmacaes) {
874881
crypto_free_shash(server->secmech.cmacaes);
@@ -890,6 +897,16 @@ cifs_crypto_shash_release(struct TCP_Server_Info *server)
890897
server->secmech.hmacmd5 = NULL;
891898
}
892899

900+
if (server->secmech.ccmaesencrypt) {
901+
crypto_free_aead(server->secmech.ccmaesencrypt);
902+
server->secmech.ccmaesencrypt = NULL;
903+
}
904+
905+
if (server->secmech.ccmaesdecrypt) {
906+
crypto_free_aead(server->secmech.ccmaesdecrypt);
907+
server->secmech.ccmaesdecrypt = NULL;
908+
}
909+
893910
kfree(server->secmech.sdesccmacaes);
894911
server->secmech.sdesccmacaes = NULL;
895912
kfree(server->secmech.sdeschmacsha256);

fs/cifs/cifsfs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,5 +1365,19 @@ MODULE_DESCRIPTION
13651365
("VFS to access servers complying with the SNIA CIFS Specification "
13661366
"e.g. Samba and Windows");
13671367
MODULE_VERSION(CIFS_VERSION);
1368+
MODULE_SOFTDEP("pre: arc4");
1369+
MODULE_SOFTDEP("pre: des");
1370+
MODULE_SOFTDEP("pre: ecb");
1371+
MODULE_SOFTDEP("pre: hmac");
1372+
MODULE_SOFTDEP("pre: md4");
1373+
MODULE_SOFTDEP("pre: md5");
1374+
MODULE_SOFTDEP("pre: nls");
1375+
#ifdef CONFIG_CIFS_SMB2
1376+
MODULE_SOFTDEP("pre: aes");
1377+
MODULE_SOFTDEP("pre: cmac");
1378+
MODULE_SOFTDEP("pre: sha256");
1379+
MODULE_SOFTDEP("pre: aead2");
1380+
MODULE_SOFTDEP("pre: ccm");
1381+
#endif /* CONFIG_CIFS_SMB2 */
13681382
module_init(init_cifs)
13691383
module_exit(exit_cifs)

fs/cifs/cifsglob.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ struct cifs_secmech {
136136
struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
137137
struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */
138138
struct sdesc *sdesccmacaes; /* ctxt to generate smb3 signature */
139+
struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */
140+
struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */
139141
};
140142

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

210212
struct smb_version_operations {
211-
int (*send_cancel)(struct TCP_Server_Info *, void *,
213+
int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *,
212214
struct mid_q_entry *);
213215
bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *);
214216
/* setup request: allocate mid, sign message */
@@ -433,6 +435,14 @@ struct smb_version_operations {
433435
bool (*dir_needs_close)(struct cifsFileInfo *);
434436
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
435437
loff_t);
438+
/* init transform request - used for encryption for now */
439+
int (*init_transform_rq)(struct TCP_Server_Info *, struct smb_rqst *,
440+
struct smb_rqst *);
441+
/* free transform request */
442+
void (*free_transform_rq)(struct smb_rqst *);
443+
int (*is_transform_hdr)(void *buf);
444+
int (*receive_transform)(struct TCP_Server_Info *,
445+
struct mid_q_entry **);
436446
};
437447

438448
struct smb_version_values {
@@ -1119,7 +1129,10 @@ struct cifs_readdata {
11191129
int (*read_into_pages)(struct TCP_Server_Info *server,
11201130
struct cifs_readdata *rdata,
11211131
unsigned int len);
1122-
struct kvec iov;
1132+
int (*copy_into_pages)(struct TCP_Server_Info *server,
1133+
struct cifs_readdata *rdata,
1134+
struct iov_iter *iter);
1135+
struct kvec iov[2];
11231136
unsigned int pagesz;
11241137
unsigned int tailsz;
11251138
unsigned int credits;
@@ -1302,6 +1315,13 @@ typedef int (mid_receive_t)(struct TCP_Server_Info *server,
13021315
*/
13031316
typedef void (mid_callback_t)(struct mid_q_entry *mid);
13041317

1318+
/*
1319+
* This is the protopyte for mid handle function. This is called once the mid
1320+
* has been recognized after decryption of the message.
1321+
*/
1322+
typedef int (mid_handle_t)(struct TCP_Server_Info *server,
1323+
struct mid_q_entry *mid);
1324+
13051325
/* one of these for every pending CIFS request to the server */
13061326
struct mid_q_entry {
13071327
struct list_head qhead; /* mids waiting on reply from this server */
@@ -1316,13 +1336,15 @@ struct mid_q_entry {
13161336
#endif
13171337
mid_receive_t *receive; /* call receive callback */
13181338
mid_callback_t *callback; /* call completion callback */
1339+
mid_handle_t *handle; /* call handle mid callback */
13191340
void *callback_data; /* general purpose pointer for callback */
13201341
void *resp_buf; /* pointer to received SMB header */
13211342
int mid_state; /* wish this were enum but can not pass to wait_event */
13221343
__le16 command; /* smb command code */
13231344
bool large_buf:1; /* if valid response, is pointer to large buf */
13241345
bool multiRsp:1; /* multiple trans2 responses for one request */
13251346
bool multiEnd:1; /* both received */
1347+
bool decrypted:1; /* decrypted entry */
13261348
};
13271349

13281350
/* 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,
14751497
#define CIFS_OBREAK_OP 0x0100 /* oplock break request */
14761498
#define CIFS_NEG_OP 0x0200 /* negotiate request */
14771499
#define CIFS_OP_MASK 0x0380 /* mask request type */
1500+
14781501
#define CIFS_HAS_CREDITS 0x0400 /* already has credits */
1502+
#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
14791503

14801504
/* Security Flags: indicate type of session setup needed */
14811505
#define CIFSSEC_MAY_SIGN 0x00001

fs/cifs/cifsproto.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,16 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
7575
extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
7676
extern void cifs_delete_mid(struct mid_q_entry *mid);
7777
extern void cifs_wake_up_task(struct mid_q_entry *mid);
78+
extern int cifs_handle_standard(struct TCP_Server_Info *server,
79+
struct mid_q_entry *mid);
80+
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
7881
extern int cifs_call_async(struct TCP_Server_Info *server,
7982
struct smb_rqst *rqst,
8083
mid_receive_t *receive, mid_callback_t *callback,
81-
void *cbdata, const int flags);
84+
mid_handle_t *handle, void *cbdata, const int flags);
85+
extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
86+
struct smb_rqst *rqst, int *resp_buf_type,
87+
const int flags, struct kvec *resp_iov);
8288
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
8389
struct smb_hdr * /* input */ ,
8490
struct smb_hdr * /* out */ ,
@@ -96,7 +102,8 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server,
96102
unsigned int *credits);
97103
extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
98104
struct kvec *, int /* nvec to send */,
99-
int * /* type of buf returned */ , const int flags);
105+
int * /* type of buf returned */, const int flags,
106+
struct kvec * /* resp vec */);
100107
extern int SendReceiveBlockingLock(const unsigned int xid,
101108
struct cifs_tcon *ptcon,
102109
struct smb_hdr *in_buf ,
@@ -441,7 +448,7 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
441448
const struct nls_table *);
442449
extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
443450
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
444-
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
451+
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
445452
extern int calc_seckey(struct cifs_ses *);
446453
extern int generate_smb30signingkey(struct cifs_ses *);
447454
extern int generate_smb311signingkey(struct cifs_ses *);

0 commit comments

Comments
 (0)