Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

Prepare for encryption support (first part). Add decryption and encryption key generation. Thanks to Metze for helping with this.

Reviewed-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <steve.french@primarydata.com>

authored by

Steve French and committed by
Steve French
373512ec 882137c4

+156 -33
+6 -2
fs/cifs/cifsglob.h
··· 227 227 void (*print_stats)(struct seq_file *m, struct cifs_tcon *); 228 228 void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *); 229 229 /* verify the message */ 230 - int (*check_message)(char *, unsigned int); 230 + int (*check_message)(char *, unsigned int, struct TCP_Server_Info *); 231 231 bool (*is_oplock_break)(char *, struct TCP_Server_Info *); 232 232 void (*downgrade_oplock)(struct TCP_Server_Info *, 233 233 struct cifsInodeInfo *, bool); ··· 630 630 #ifdef CONFIG_CIFS_SMB2 631 631 unsigned int max_read; 632 632 unsigned int max_write; 633 + __u8 preauth_hash[512]; 633 634 #endif /* CONFIG_CIFS_SMB2 */ 634 635 unsigned long echo_interval; 635 636 }; ··· 814 813 bool need_reconnect:1; /* connection reset, uid now invalid */ 815 814 #ifdef CONFIG_CIFS_SMB2 816 815 __u16 session_flags; 817 - char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */ 816 + __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; 817 + __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; 818 + __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; 819 + __u8 preauth_hash[512]; 818 820 #endif /* CONFIG_CIFS_SMB2 */ 819 821 }; 820 822
+3 -2
fs/cifs/cifsproto.h
··· 102 102 struct smb_hdr *out_buf, 103 103 int *bytes_returned); 104 104 extern int cifs_reconnect(struct TCP_Server_Info *server); 105 - extern int checkSMB(char *buf, unsigned int length); 105 + extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr); 106 106 extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); 107 107 extern bool backup_cred(struct cifs_sb_info *); 108 108 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); ··· 439 439 extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); 440 440 extern void cifs_crypto_shash_release(struct TCP_Server_Info *); 441 441 extern int calc_seckey(struct cifs_ses *); 442 - extern int generate_smb3signingkey(struct cifs_ses *); 442 + extern int generate_smb30signingkey(struct cifs_ses *); 443 + extern int generate_smb311signingkey(struct cifs_ses *); 443 444 444 445 #ifdef CONFIG_CIFS_WEAK_PW_HASH 445 446 extern int calc_lanman_hash(const char *password, const char *cryptkey,
+1 -1
fs/cifs/connect.c
··· 831 831 * 48 bytes is enough to display the header and a little bit 832 832 * into the payload for debugging purposes. 833 833 */ 834 - length = server->ops->check_message(buf, server->total_read); 834 + length = server->ops->check_message(buf, server->total_read, server); 835 835 if (length != 0) 836 836 cifs_dump_mem("Bad SMB: ", buf, 837 837 min_t(unsigned int, server->total_read, 48));
+1 -1
fs/cifs/misc.c
··· 310 310 } 311 311 312 312 int 313 - checkSMB(char *buf, unsigned int total_read) 313 + checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) 314 314 { 315 315 struct smb_hdr *smb = (struct smb_hdr *)buf; 316 316 __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
+30 -6
fs/cifs/smb2misc.c
··· 38 38 * Make sure that this really is an SMB, that it is a response, 39 39 * and that the message ids match. 40 40 */ 41 - if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && 41 + if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) && 42 42 (mid == wire_mid)) { 43 43 if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) 44 44 return 0; ··· 50 50 cifs_dbg(VFS, "Received Request not response\n"); 51 51 } 52 52 } else { /* bad signature or mid */ 53 - if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) 53 + if (hdr->ProtocolId != SMB2_PROTO_NUMBER) 54 54 cifs_dbg(VFS, "Bad protocol string signature header %x\n", 55 - *(unsigned int *) hdr->ProtocolId); 55 + le32_to_cpu(hdr->ProtocolId)); 56 56 if (mid != wire_mid) 57 57 cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", 58 58 mid, wire_mid); ··· 93 93 }; 94 94 95 95 int 96 - smb2_check_message(char *buf, unsigned int length) 96 + smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) 97 97 { 98 98 struct smb2_hdr *hdr = (struct smb2_hdr *)buf; 99 99 struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; 100 - __u64 mid = le64_to_cpu(hdr->MessageId); 100 + __u64 mid; 101 101 __u32 len = get_rfc1002_length(buf); 102 102 __u32 clc_len; /* calculated length */ 103 103 int command; ··· 111 111 * ie Validate the wct via smb2_struct_sizes table above 112 112 */ 113 113 114 + if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { 115 + struct smb2_transform_hdr *thdr = 116 + (struct smb2_transform_hdr *)buf; 117 + struct cifs_ses *ses = NULL; 118 + struct list_head *tmp; 119 + 120 + /* decrypt frame now that it is completely read in */ 121 + spin_lock(&cifs_tcp_ses_lock); 122 + list_for_each(tmp, &srvr->smb_ses_list) { 123 + ses = list_entry(tmp, struct cifs_ses, smb_ses_list); 124 + if (ses->Suid == thdr->SessionId) 125 + break; 126 + 127 + ses = NULL; 128 + } 129 + spin_unlock(&cifs_tcp_ses_lock); 130 + if (ses == NULL) { 131 + cifs_dbg(VFS, "no decryption - session id not found\n"); 132 + return 1; 133 + } 134 + } 135 + 136 + 137 + mid = le64_to_cpu(hdr->MessageId); 114 138 if (length < sizeof(struct smb2_pdu)) { 115 139 if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { 116 140 pdu->StructureSize2 = 0; ··· 346 322 347 323 /* return pointer to beginning of data area, ie offset from SMB start */ 348 324 if ((*off != 0) && (*len != 0)) 349 - return (char *)(&hdr->ProtocolId[0]) + *off; 325 + return (char *)(&hdr->ProtocolId) + *off; 350 326 else 351 327 return NULL; 352 328 }
+9 -4
fs/cifs/smb2ops.c
··· 182 182 struct smb2_hdr *hdr = (struct smb2_hdr *)buf; 183 183 __u64 wire_mid = le64_to_cpu(hdr->MessageId); 184 184 185 + if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { 186 + cifs_dbg(VFS, "encrypted frame parsing not supported yet"); 187 + return NULL; 188 + } 189 + 185 190 spin_lock(&GlobalMid_Lock); 186 191 list_for_each_entry(mid, &server->pending_mid_q, qhead) { 187 192 if ((mid->mid == wire_mid) && ··· 1697 1692 .get_lease_key = smb2_get_lease_key, 1698 1693 .set_lease_key = smb2_set_lease_key, 1699 1694 .new_lease_key = smb2_new_lease_key, 1700 - .generate_signingkey = generate_smb3signingkey, 1695 + .generate_signingkey = generate_smb30signingkey, 1701 1696 .calc_signature = smb3_calc_signature, 1702 1697 .set_integrity = smb3_set_integrity, 1703 1698 .is_read_op = smb21_is_read_op, ··· 1784 1779 .get_lease_key = smb2_get_lease_key, 1785 1780 .set_lease_key = smb2_set_lease_key, 1786 1781 .new_lease_key = smb2_new_lease_key, 1787 - .generate_signingkey = generate_smb3signingkey, 1782 + .generate_signingkey = generate_smb311signingkey, 1788 1783 .calc_signature = smb3_calc_signature, 1789 1784 .set_integrity = smb3_set_integrity, 1790 1785 .is_read_op = smb21_is_read_op, ··· 1843 1838 struct smb_version_values smb30_values = { 1844 1839 .version_string = SMB30_VERSION_STRING, 1845 1840 .protocol_id = SMB30_PROT_ID, 1846 - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, 1841 + .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION, 1847 1842 .large_lock_type = 0, 1848 1843 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, 1849 1844 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, ··· 1863 1858 struct smb_version_values smb302_values = { 1864 1859 .version_string = SMB302_VERSION_STRING, 1865 1860 .protocol_id = SMB302_PROT_ID, 1866 - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, 1861 + .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION, 1867 1862 .large_lock_type = 0, 1868 1863 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, 1869 1864 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
+4 -6
fs/cifs/smb2pdu.c
··· 97 97 hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr) 98 98 - 4 /* RFC 1001 length field itself not counted */); 99 99 100 - hdr->ProtocolId[0] = 0xFE; 101 - hdr->ProtocolId[1] = 'S'; 102 - hdr->ProtocolId[2] = 'M'; 103 - hdr->ProtocolId[3] = 'B'; 100 + hdr->ProtocolId = SMB2_PROTO_NUMBER; 104 101 hdr->StructureSize = cpu_to_le16(64); 105 102 hdr->Command = smb2_cmd; 106 103 hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */ ··· 1570 1573 goto ioctl_exit; 1571 1574 } 1572 1575 1573 - memcpy(*out_data, rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), 1576 + memcpy(*out_data, 1577 + (char *)&rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), 1574 1578 *plen); 1575 1579 ioctl_exit: 1576 1580 free_rsp_buf(resp_buftype, rsp); ··· 2091 2093 } 2092 2094 2093 2095 if (*buf) { 2094 - memcpy(*buf, (char *)rsp->hdr.ProtocolId + rsp->DataOffset, 2096 + memcpy(*buf, (char *)&rsp->hdr.ProtocolId + rsp->DataOffset, 2095 2097 *nbytes); 2096 2098 free_rsp_buf(resp_buftype, iov[0].iov_base); 2097 2099 } else if (resp_buftype != CIFS_NO_BUFFER) {
+4 -4
fs/cifs/smb2pdu.h
··· 86 86 #define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ 87 87 88 88 #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) 89 + #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) 89 90 90 91 /* 91 92 * SMB2 Header Definition ··· 103 102 __be32 smb2_buf_length; /* big endian on wire */ 104 103 /* length is only two or three bytes - with 105 104 one or two byte type preceding it that MBZ */ 106 - __u8 ProtocolId[4]; /* 0xFE 'S' 'M' 'B' */ 105 + __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ 107 106 __le16 StructureSize; /* 64 */ 108 107 __le16 CreditCharge; /* MBZ */ 109 108 __le32 Status; /* Error from server */ ··· 129 128 one or two byte type preceding it that MBZ */ 130 129 __u8 ProtocolId[4]; /* 0xFD 'S' 'M' 'B' */ 131 130 __u8 Signature[16]; 132 - __u8 Nonce[11]; 133 - __u8 Reserved[5]; 131 + __u8 Nonce[16]; 134 132 __le32 OriginalMessageSize; 135 133 __u16 Reserved1; 136 - __le16 EncryptionAlgorithm; 134 + __le16 Flags; /* EncryptionAlgorithm */ 137 135 __u64 SessionId; 138 136 } __packed; 139 137
+2 -1
fs/cifs/smb2proto.h
··· 34 34 ***************************************************************** 35 35 */ 36 36 extern int map_smb2_to_linux_error(char *buf, bool log_err); 37 - extern int smb2_check_message(char *buf, unsigned int length); 37 + extern int smb2_check_message(char *buf, unsigned int length, 38 + struct TCP_Server_Info *server); 38 39 extern unsigned int smb2_calc_size(void *buf); 39 40 extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr); 40 41 extern __le16 *cifs_convert_path_to_utf16(const char *from,
+96 -6
fs/cifs/smb2transport.c
··· 222 222 return rc; 223 223 } 224 224 225 - int 226 - generate_smb3signingkey(struct cifs_ses *ses) 225 + static int generate_key(struct cifs_ses *ses, struct kvec label, 226 + struct kvec context, __u8 *key, unsigned int key_size) 227 227 { 228 228 unsigned char zero = 0x0; 229 229 __u8 i[4] = {0, 0, 0, 1}; ··· 233 233 unsigned char *hashptr = prfhash; 234 234 235 235 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); 236 - memset(ses->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); 236 + memset(key, 0x0, key_size); 237 237 238 238 rc = smb3_crypto_shash_allocate(ses->server); 239 239 if (rc) { ··· 262 262 } 263 263 264 264 rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, 265 - "SMB2AESCMAC", 12); 265 + label.iov_base, label.iov_len); 266 266 if (rc) { 267 267 cifs_dbg(VFS, "%s: Could not update with label\n", __func__); 268 268 goto smb3signkey_ret; ··· 276 276 } 277 277 278 278 rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, 279 - "SmbSign", 8); 279 + context.iov_base, context.iov_len); 280 280 if (rc) { 281 281 cifs_dbg(VFS, "%s: Could not update with context\n", __func__); 282 282 goto smb3signkey_ret; ··· 296 296 goto smb3signkey_ret; 297 297 } 298 298 299 - memcpy(ses->smb3signingkey, hashptr, SMB3_SIGNKEY_SIZE); 299 + memcpy(key, hashptr, key_size); 300 300 301 301 smb3signkey_ret: 302 302 return rc; 303 + } 304 + 305 + struct derivation { 306 + struct kvec label; 307 + struct kvec context; 308 + }; 309 + 310 + struct derivation_triplet { 311 + struct derivation signing; 312 + struct derivation encryption; 313 + struct derivation decryption; 314 + }; 315 + 316 + static int 317 + generate_smb3signingkey(struct cifs_ses *ses, 318 + const struct derivation_triplet *ptriplet) 319 + { 320 + int rc; 321 + 322 + rc = generate_key(ses, ptriplet->signing.label, 323 + ptriplet->signing.context, ses->smb3signingkey, 324 + SMB3_SIGN_KEY_SIZE); 325 + if (rc) 326 + return rc; 327 + 328 + rc = generate_key(ses, ptriplet->encryption.label, 329 + ptriplet->encryption.context, ses->smb3encryptionkey, 330 + SMB3_SIGN_KEY_SIZE); 331 + if (rc) 332 + return rc; 333 + 334 + return generate_key(ses, ptriplet->decryption.label, 335 + ptriplet->decryption.context, 336 + ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE); 337 + } 338 + 339 + int 340 + generate_smb30signingkey(struct cifs_ses *ses) 341 + 342 + { 343 + struct derivation_triplet triplet; 344 + struct derivation *d; 345 + 346 + d = &triplet.signing; 347 + d->label.iov_base = "SMB2AESCMAC"; 348 + d->label.iov_len = 12; 349 + d->context.iov_base = "SmbSign"; 350 + d->context.iov_len = 8; 351 + 352 + d = &triplet.encryption; 353 + d->label.iov_base = "SMB2AESCCM"; 354 + d->label.iov_len = 11; 355 + d->context.iov_base = "ServerIn "; 356 + d->context.iov_len = 10; 357 + 358 + d = &triplet.decryption; 359 + d->label.iov_base = "SMB2AESCCM"; 360 + d->label.iov_len = 11; 361 + d->context.iov_base = "ServerOut"; 362 + d->context.iov_len = 10; 363 + 364 + return generate_smb3signingkey(ses, &triplet); 365 + } 366 + 367 + int 368 + generate_smb311signingkey(struct cifs_ses *ses) 369 + 370 + { 371 + struct derivation_triplet triplet; 372 + struct derivation *d; 373 + 374 + d = &triplet.signing; 375 + d->label.iov_base = "SMB2AESCMAC"; 376 + d->label.iov_len = 12; 377 + d->context.iov_base = "SmbSign"; 378 + d->context.iov_len = 8; 379 + 380 + d = &triplet.encryption; 381 + d->label.iov_base = "SMB2AESCCM"; 382 + d->label.iov_len = 11; 383 + d->context.iov_base = "ServerIn "; 384 + d->context.iov_len = 10; 385 + 386 + d = &triplet.decryption; 387 + d->label.iov_base = "SMB2AESCCM"; 388 + d->label.iov_len = 11; 389 + d->context.iov_base = "ServerOut"; 390 + d->context.iov_len = 10; 391 + 392 + return generate_smb3signingkey(ses, &triplet); 303 393 } 304 394 305 395 int