[CIFS] Fix ntlmv2 auth with ntlmssp

Make ntlmv2 as an authentication mechanism within ntlmssp
instead of ntlmv1.
Parse type 2 response in ntlmssp negotiation to pluck
AV pairs and use them to calculate ntlmv2 response token.
Also, assign domain name from the sever response in type 2
packet of ntlmssp and use that (netbios) domain name in
calculation of response.

Enable cifs/smb signing using rc4 and md5.

Changed name of the structure mac_key to session_key to reflect
the type of key it holds.

Use kernel crypto_shash_* APIs instead of the equivalent cifs functions.

Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Steve French <sfrench@us.ibm.com>

+452 -172
+2
fs/cifs/Kconfig
··· 2 2 tristate "CIFS support (advanced network filesystem, SMBFS successor)" 3 3 depends on INET 4 4 select NLS 5 + select CRYPTO_MD5 6 + select CRYPTO_ARC4 5 7 help 6 8 This is the client VFS module for the Common Internet File System 7 9 (CIFS) protocol which is the successor to the Server Message Block
+3 -3
fs/cifs/asn1.c
··· 597 597 if (compare_oid(oid, oidlen, MSKRB5_OID, 598 598 MSKRB5_OID_LEN)) 599 599 server->sec_mskerberos = true; 600 - else if (compare_oid(oid, oidlen, KRB5U2U_OID, 600 + if (compare_oid(oid, oidlen, KRB5U2U_OID, 601 601 KRB5U2U_OID_LEN)) 602 602 server->sec_kerberosu2u = true; 603 - else if (compare_oid(oid, oidlen, KRB5_OID, 603 + if (compare_oid(oid, oidlen, KRB5_OID, 604 604 KRB5_OID_LEN)) 605 605 server->sec_kerberos = true; 606 - else if (compare_oid(oid, oidlen, NTLMSSP_OID, 606 + if (compare_oid(oid, oidlen, NTLMSSP_OID, 607 607 NTLMSSP_OID_LEN)) 608 608 server->sec_ntlmssp = true; 609 609
+294 -122
fs/cifs/cifsencrypt.c
··· 27 27 #include "md5.h" 28 28 #include "cifs_unicode.h" 29 29 #include "cifsproto.h" 30 + #include "ntlmssp.h" 30 31 #include <linux/ctype.h> 31 32 #include <linux/random.h> 32 33 ··· 43 42 unsigned char *p24); 44 43 45 44 static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 46 - const struct mac_key *key, char *signature) 45 + struct TCP_Server_Info *server, char *signature) 47 46 { 48 - struct MD5Context context; 47 + int rc = 0; 48 + struct { 49 + struct shash_desc shash; 50 + char ctx[crypto_shash_descsize(server->ntlmssp.md5)]; 51 + } sdesc; 49 52 50 - if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) 53 + if (cifs_pdu == NULL || server == NULL || signature == NULL) 51 54 return -EINVAL; 52 55 53 - cifs_MD5_init(&context); 54 - cifs_MD5_update(&context, (char *)&key->data, key->len); 55 - cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 56 + sdesc.shash.tfm = server->ntlmssp.md5; 57 + sdesc.shash.flags = 0x0; 56 58 57 - cifs_MD5_final(signature, &context); 59 + rc = crypto_shash_init(&sdesc.shash); 60 + if (rc) { 61 + cERROR(1, "could not initialize master crypto API hmacmd5\n"); 62 + return rc; 63 + } 64 + 65 + if (server->secType == RawNTLMSSP) 66 + crypto_shash_update(&sdesc.shash, 67 + server->session_key.data.ntlmv2.key, 68 + CIFS_NTLMV2_SESSKEY_SIZE); 69 + else 70 + crypto_shash_update(&sdesc.shash, 71 + (char *)&server->session_key.data, 72 + server->session_key.len); 73 + 74 + crypto_shash_update(&sdesc.shash, 75 + cifs_pdu->Protocol, cifs_pdu->smb_buf_length); 76 + 77 + rc = crypto_shash_final(&sdesc.shash, signature); 78 + 58 79 return 0; 59 80 } 81 + 60 82 61 83 int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 62 84 __u32 *pexpected_response_sequence_number) ··· 102 78 server->sequence_number++; 103 79 spin_unlock(&GlobalMid_Lock); 104 80 105 - rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, 106 - smb_signature); 81 + rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); 107 82 if (rc) 108 83 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 109 84 else ··· 112 89 } 113 90 114 91 static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 115 - const struct mac_key *key, char *signature) 92 + struct TCP_Server_Info *server, char *signature) 116 93 { 117 - struct MD5Context context; 118 94 int i; 95 + int rc = 0; 96 + struct { 97 + struct shash_desc shash; 98 + char ctx[crypto_shash_descsize(server->ntlmssp.md5)]; 99 + } sdesc; 119 100 120 - if ((iov == NULL) || (signature == NULL) || (key == NULL)) 101 + if (iov == NULL || server == NULL || signature == NULL) 121 102 return -EINVAL; 122 103 123 - cifs_MD5_init(&context); 124 - cifs_MD5_update(&context, (char *)&key->data, key->len); 104 + sdesc.shash.tfm = server->ntlmssp.md5; 105 + sdesc.shash.flags = 0x0; 106 + 107 + rc = crypto_shash_init(&sdesc.shash); 108 + if (rc) { 109 + cERROR(1, "could not initialize master crypto API hmacmd5\n"); 110 + return rc; 111 + } 112 + 113 + if (server->secType == RawNTLMSSP) 114 + crypto_shash_update(&sdesc.shash, 115 + server->session_key.data.ntlmv2.key, 116 + CIFS_NTLMV2_SESSKEY_SIZE); 117 + else 118 + crypto_shash_update(&sdesc.shash, 119 + (char *)&server->session_key.data, 120 + server->session_key.len); 121 + 125 122 for (i = 0; i < n_vec; i++) { 126 123 if (iov[i].iov_len == 0) 127 124 continue; ··· 154 111 if (i == 0) { 155 112 if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ 156 113 break; /* nothing to sign or corrupt header */ 157 - cifs_MD5_update(&context, iov[0].iov_base+4, 158 - iov[0].iov_len-4); 114 + crypto_shash_update(&sdesc.shash, 115 + iov[i].iov_base + 4, iov[i].iov_len - 4); 159 116 } else 160 - cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); 117 + crypto_shash_update(&sdesc.shash, 118 + iov[i].iov_base, iov[i].iov_len); 161 119 } 162 120 163 - cifs_MD5_final(signature, &context); 121 + rc = crypto_shash_final(&sdesc.shash, signature); 164 122 165 123 return 0; 166 124 } 167 - 168 125 169 126 int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 170 127 __u32 *pexpected_response_sequence_number) ··· 188 145 server->sequence_number++; 189 146 spin_unlock(&GlobalMid_Lock); 190 147 191 - rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, 192 - smb_signature); 148 + rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); 193 149 if (rc) 194 150 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 195 151 else ··· 198 156 } 199 157 200 158 int cifs_verify_signature(struct smb_hdr *cifs_pdu, 201 - const struct mac_key *mac_key, 159 + struct TCP_Server_Info *server, 202 160 __u32 expected_sequence_number) 203 161 { 204 - unsigned int rc; 162 + int rc; 205 163 char server_response_sig[8]; 206 164 char what_we_think_sig_should_be[20]; 207 165 208 - if ((cifs_pdu == NULL) || (mac_key == NULL)) 166 + if (cifs_pdu == NULL || server == NULL) 209 167 return -EINVAL; 210 168 211 169 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) ··· 234 192 cpu_to_le32(expected_sequence_number); 235 193 cifs_pdu->Signature.Sequence.Reserved = 0; 236 194 237 - rc = cifs_calculate_signature(cifs_pdu, mac_key, 195 + rc = cifs_calculate_signature(cifs_pdu, server, 238 196 what_we_think_sig_should_be); 239 197 240 198 if (rc) ··· 251 209 } 252 210 253 211 /* We fill in key by putting in 40 byte array which was allocated by caller */ 254 - int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 212 + int cifs_calculate_session_key(struct session_key *key, const char *rn, 255 213 const char *password) 256 214 { 257 215 char temp_key[16]; ··· 262 220 mdfour(key->data.ntlm, temp_key, 16); 263 221 memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE); 264 222 key->len = 40; 265 - return 0; 266 - } 267 - 268 - int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses, 269 - const struct nls_table *nls_info) 270 - { 271 - char temp_hash[16]; 272 - struct HMACMD5Context ctx; 273 - char *ucase_buf; 274 - __le16 *unicode_buf; 275 - unsigned int i, user_name_len, dom_name_len; 276 - 277 - if (ses == NULL) 278 - return -EINVAL; 279 - 280 - E_md4hash(ses->password, temp_hash); 281 - 282 - hmac_md5_init_limK_to_64(temp_hash, 16, &ctx); 283 - user_name_len = strlen(ses->userName); 284 - if (user_name_len > MAX_USERNAME_SIZE) 285 - return -EINVAL; 286 - if (ses->domainName == NULL) 287 - return -EINVAL; /* BB should we use CIFS_LINUX_DOM */ 288 - dom_name_len = strlen(ses->domainName); 289 - if (dom_name_len > MAX_USERNAME_SIZE) 290 - return -EINVAL; 291 - 292 - ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL); 293 - if (ucase_buf == NULL) 294 - return -ENOMEM; 295 - unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL); 296 - if (unicode_buf == NULL) { 297 - kfree(ucase_buf); 298 - return -ENOMEM; 299 - } 300 - 301 - for (i = 0; i < user_name_len; i++) 302 - ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]]; 303 - ucase_buf[i] = 0; 304 - user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, 305 - MAX_USERNAME_SIZE*2, nls_info); 306 - unicode_buf[user_name_len] = 0; 307 - user_name_len++; 308 - 309 - for (i = 0; i < dom_name_len; i++) 310 - ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]]; 311 - ucase_buf[i] = 0; 312 - dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, 313 - MAX_USERNAME_SIZE*2, nls_info); 314 - 315 - unicode_buf[user_name_len + dom_name_len] = 0; 316 - hmac_md5_update((const unsigned char *) unicode_buf, 317 - (user_name_len+dom_name_len)*2, &ctx); 318 - 319 - hmac_md5_final(ses->server->ntlmv2_hash, &ctx); 320 - kfree(ucase_buf); 321 - kfree(unicode_buf); 322 223 return 0; 323 224 } 324 225 ··· 309 324 { 310 325 int rc = 0; 311 326 int len; 312 - char nt_hash[16]; 313 - struct HMACMD5Context *pctxt; 327 + char nt_hash[CIFS_NTHASH_SIZE]; 314 328 wchar_t *user; 315 329 wchar_t *domain; 316 - 317 - pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 318 - 319 - if (pctxt == NULL) 320 - return -ENOMEM; 330 + wchar_t *server; 331 + struct { 332 + struct shash_desc shash; 333 + char ctx[crypto_shash_descsize(ses->server->ntlmssp.hmacmd5)]; 334 + } sdesc; 321 335 322 336 /* calculate md4 hash of password */ 323 337 E_md4hash(ses->password, nt_hash); 324 338 325 - /* convert Domainname to unicode and uppercase */ 326 - hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); 339 + sdesc.shash.tfm = ses->server->ntlmssp.hmacmd5; 340 + sdesc.shash.flags = 0x0; 341 + 342 + crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, 343 + CIFS_NTHASH_SIZE); 344 + 345 + rc = crypto_shash_init(&sdesc.shash); 346 + if (rc) { 347 + cERROR(1, "could not initialize master crypto API hmacmd5\n"); 348 + return rc; 349 + } 327 350 328 351 /* convert ses->userName to unicode and uppercase */ 329 352 len = strlen(ses->userName); ··· 340 347 goto calc_exit_2; 341 348 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); 342 349 UniStrupr(user); 343 - hmac_md5_update((char *)user, 2*len, pctxt); 350 + 351 + crypto_shash_update(&sdesc.shash, (char *)user, 2 * len); 344 352 345 353 /* convert ses->domainName to unicode and uppercase */ 346 354 if (ses->domainName) { ··· 357 363 Maybe converting the domain name earlier makes sense */ 358 364 /* UniStrupr(domain); */ 359 365 360 - hmac_md5_update((char *)domain, 2*len, pctxt); 366 + crypto_shash_update(&sdesc.shash, (char *)domain, 2 * len); 361 367 362 368 kfree(domain); 369 + } else if (ses->serverName) { 370 + len = strlen(ses->serverName); 371 + 372 + server = kmalloc(2 + (len * 2), GFP_KERNEL); 373 + if (server == NULL) 374 + goto calc_exit_1; 375 + len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, 376 + nls_cp); 377 + /* the following line was removed since it didn't work well 378 + with lower cased domain name that passed as an option. 379 + Maybe converting the domain name earlier makes sense */ 380 + /* UniStrupr(domain); */ 381 + 382 + crypto_shash_update(&sdesc.shash, (char *)server, 2 * len); 383 + 384 + kfree(server); 363 385 } 364 386 calc_exit_1: 365 387 kfree(user); 366 388 calc_exit_2: 367 389 /* BB FIXME what about bytes 24 through 40 of the signing key? 368 390 compare with the NTLM example */ 369 - hmac_md5_final(ses->server->ntlmv2_hash, pctxt); 391 + rc = crypto_shash_final(&sdesc.shash, ses->server->ntlmv2_hash); 370 392 371 - kfree(pctxt); 372 393 return rc; 373 394 } 374 395 375 - void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 376 - const struct nls_table *nls_cp) 396 + static int 397 + find_domain_name(struct cifsSesInfo *ses) 398 + { 399 + int rc = 0; 400 + unsigned int attrsize; 401 + unsigned int type; 402 + unsigned char *blobptr; 403 + struct ntlmssp2_name *attrptr; 404 + 405 + if (ses->server->tiblob) { 406 + blobptr = ses->server->tiblob; 407 + attrptr = (struct ntlmssp2_name *) blobptr; 408 + 409 + while ((type = attrptr->type) != 0) { 410 + blobptr += 2; /* advance attr type */ 411 + attrsize = attrptr->length; 412 + blobptr += 2; /* advance attr size */ 413 + if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { 414 + if (!ses->domainName) { 415 + ses->domainName = 416 + kmalloc(attrptr->length + 1, 417 + GFP_KERNEL); 418 + if (!ses->domainName) 419 + return -ENOMEM; 420 + cifs_from_ucs2(ses->domainName, 421 + (__le16 *)blobptr, 422 + attrptr->length, 423 + attrptr->length, 424 + load_nls_default(), false); 425 + } 426 + } 427 + blobptr += attrsize; /* advance attr value */ 428 + attrptr = (struct ntlmssp2_name *) blobptr; 429 + } 430 + } else { 431 + ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); 432 + ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); 433 + if (!ses->server->tiblob) { 434 + ses->server->tilen = 0; 435 + cERROR(1, "Challenge target info allocation failure"); 436 + return -ENOMEM; 437 + } 438 + memset(ses->server->tiblob, 0x0, ses->server->tilen); 439 + attrptr = (struct ntlmssp2_name *) ses->server->tiblob; 440 + attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); 441 + } 442 + 443 + return rc; 444 + } 445 + 446 + static int 447 + CalcNTLMv2_response(const struct TCP_Server_Info *server, 448 + char *v2_session_response) 377 449 { 378 450 int rc; 451 + struct { 452 + struct shash_desc shash; 453 + char ctx[crypto_shash_descsize(server->ntlmssp.hmacmd5)]; 454 + } sdesc; 455 + 456 + sdesc.shash.tfm = server->ntlmssp.hmacmd5; 457 + sdesc.shash.flags = 0x0; 458 + 459 + crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, 460 + CIFS_HMAC_MD5_HASH_SIZE); 461 + 462 + rc = crypto_shash_init(&sdesc.shash); 463 + if (rc) { 464 + cERROR(1, "could not initialize master crypto API hmacmd5\n"); 465 + return rc; 466 + } 467 + 468 + memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, 469 + server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); 470 + crypto_shash_update(&sdesc.shash, 471 + v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, 472 + sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); 473 + 474 + if (server->tilen) 475 + crypto_shash_update(&sdesc.shash, 476 + server->tiblob, server->tilen); 477 + 478 + rc = crypto_shash_final(&sdesc.shash, v2_session_response); 479 + 480 + return rc; 481 + } 482 + 483 + int 484 + setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 485 + const struct nls_table *nls_cp) 486 + { 487 + int rc = 0; 379 488 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; 380 - struct HMACMD5Context context; 489 + struct { 490 + struct shash_desc shash; 491 + char ctx[crypto_shash_descsize(ses->server->ntlmssp.hmacmd5)]; 492 + } sdesc; 381 493 382 494 buf->blob_signature = cpu_to_le32(0x00000101); 383 495 buf->reserved = 0; 384 496 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 385 497 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 386 498 buf->reserved2 = 0; 387 - buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); 388 - buf->names[0].length = 0; 389 - buf->names[1].type = 0; 390 - buf->names[1].length = 0; 499 + 500 + if (!ses->domainName) { 501 + rc = find_domain_name(ses); 502 + if (rc) { 503 + cERROR(1, "could not get domain/server name rc %d", rc); 504 + return rc; 505 + } 506 + } 391 507 392 508 /* calculate buf->ntlmv2_hash */ 393 509 rc = calc_ntlmv2_hash(ses, nls_cp); 394 - if (rc) 510 + if (rc) { 395 511 cERROR(1, "could not get v2 hash rc %d", rc); 396 - CalcNTLMv2_response(ses, resp_buf); 512 + return rc; 513 + } 514 + rc = CalcNTLMv2_response(ses->server, resp_buf); 515 + if (rc) { 516 + cERROR(1, "could not get v2 hash rc %d", rc); 517 + return rc; 518 + } 397 519 398 - /* now calculate the MAC key for NTLMv2 */ 399 - hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 400 - hmac_md5_update(resp_buf, 16, &context); 401 - hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); 520 + crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, 521 + ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); 402 522 403 - memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, 404 - sizeof(struct ntlmv2_resp)); 405 - ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); 523 + sdesc.shash.tfm = ses->server->ntlmssp.hmacmd5; 524 + sdesc.shash.flags = 0x0; 525 + 526 + rc = crypto_shash_init(&sdesc.shash); 527 + if (rc) { 528 + cERROR(1, "could not initialize master crypto API hmacmd5\n"); 529 + return rc; 530 + } 531 + 532 + crypto_shash_update(&sdesc.shash, resp_buf, CIFS_HMAC_MD5_HASH_SIZE); 533 + 534 + rc = crypto_shash_final(&sdesc.shash, 535 + ses->server->session_key.data.ntlmv2.key); 536 + 537 + memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, 538 + sizeof(struct ntlmv2_resp)); 539 + ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); 540 + 541 + return rc; 406 542 } 407 543 408 - void CalcNTLMv2_response(const struct cifsSesInfo *ses, 409 - char *v2_session_response) 544 + int 545 + calc_seckey(struct TCP_Server_Info *server) 410 546 { 411 - struct HMACMD5Context context; 412 - /* rest of v2 struct already generated */ 413 - memcpy(v2_session_response + 8, ses->server->cryptKey, 8); 414 - hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 547 + int rc; 548 + unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; 549 + struct crypto_blkcipher *tfm_arc4; 550 + struct scatterlist sgin, sgout; 551 + struct blkcipher_desc desc; 415 552 416 - hmac_md5_update(v2_session_response+8, 417 - sizeof(struct ntlmv2_resp) - 8, &context); 553 + get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); 418 554 419 - hmac_md5_final(v2_session_response, &context); 420 - /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ 555 + tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 556 + 0, CRYPTO_ALG_ASYNC); 557 + if (!tfm_arc4 || IS_ERR(tfm_arc4)) { 558 + cERROR(1, "could not allocate " "master crypto API arc4\n"); 559 + return 1; 560 + } 561 + 562 + crypto_blkcipher_setkey(tfm_arc4, 563 + server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); 564 + sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); 565 + sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); 566 + rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); 567 + 568 + if (!rc) 569 + memcpy(server->session_key.data.ntlmv2.key, 570 + sec_key, CIFS_NTLMV2_SESSKEY_SIZE); 571 + 572 + crypto_free_blkcipher(tfm_arc4); 573 + 574 + return 0; 575 + } 576 + 577 + void 578 + cifs_crypto_shash_release(struct TCP_Server_Info *server) 579 + { 580 + if (server->ntlmssp.md5) 581 + crypto_free_shash(server->ntlmssp.md5); 582 + 583 + if (server->ntlmssp.hmacmd5) 584 + crypto_free_shash(server->ntlmssp.hmacmd5); 585 + } 586 + 587 + int 588 + cifs_crypto_shash_allocate(struct TCP_Server_Info *server) 589 + { 590 + server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); 591 + if (!server->ntlmssp.hmacmd5 || 592 + IS_ERR(server->ntlmssp.hmacmd5)) { 593 + cERROR(1, "could not allocate master crypto API hmacmd5\n"); 594 + return 1; 595 + } 596 + 597 + server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); 598 + if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { 599 + crypto_free_shash(server->ntlmssp.hmacmd5); 600 + cERROR(1, "could not allocate master crypto API md5\n"); 601 + return 1; 602 + } 603 + 604 + return 0; 421 605 }
+16 -2
fs/cifs/cifsglob.h
··· 25 25 #include <linux/workqueue.h> 26 26 #include "cifs_fs_sb.h" 27 27 #include "cifsacl.h" 28 + #include <crypto/internal/hash.h> 29 + #include <linux/scatterlist.h> 30 + 28 31 /* 29 32 * The sizes of various internal tables and strings 30 33 */ ··· 100 97 /* Netbios frames protocol not supported at this time */ 101 98 }; 102 99 103 - struct mac_key { 100 + struct session_key { 104 101 unsigned int len; 105 102 union { 106 103 char ntlm[CIFS_SESS_KEY_SIZE + 16]; ··· 121 118 struct cifs_sid gsid; 122 119 struct cifs_ntace *ntaces; 123 120 struct cifs_ace *aces; 121 + }; 122 + 123 + struct ntlmssp_auth { 124 + __u32 client_flags; 125 + __u32 server_flags; 126 + unsigned char ciphertext[CIFS_CPHTXT_SIZE]; 127 + struct crypto_shash *hmacmd5; 128 + struct crypto_shash *md5; 124 129 }; 125 130 126 131 /* ··· 193 182 /* 16th byte of RFC1001 workstation name is always null */ 194 183 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 195 184 __u32 sequence_number; /* needed for CIFS PDU signature */ 196 - struct mac_key mac_signing_key; 185 + struct session_key session_key; 197 186 char ntlmv2_hash[16]; 198 187 unsigned long lstrp; /* when we got last response from this server */ 199 188 u16 dialect; /* dialect index that server chose */ 200 189 /* extended security flavors that server supports */ 190 + unsigned int tilen; /* length of the target info blob */ 191 + unsigned char *tiblob; /* target info blob in challenge response */ 192 + struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */ 201 193 bool sec_kerberos; /* supports plain Kerberos */ 202 194 bool sec_mskerberos; /* supports legacy MS Kerberos */ 203 195 bool sec_kerberosu2u; /* supports U2U Kerberos */
+6 -1
fs/cifs/cifspdu.h
··· 134 134 * Size of the session key (crypto key encrypted with the password 135 135 */ 136 136 #define CIFS_SESS_KEY_SIZE (24) 137 + #define CIFS_CLIENT_CHALLENGE_SIZE (8) 138 + #define CIFS_SERVER_CHALLENGE_SIZE (8) 139 + #define CIFS_HMAC_MD5_HASH_SIZE (16) 140 + #define CIFS_CPHTXT_SIZE (16) 141 + #define CIFS_NTLMV2_SESSKEY_SIZE (16) 142 + #define CIFS_NTHASH_SIZE (16) 137 143 138 144 /* 139 145 * Maximum user name length ··· 669 663 __le64 time; 670 664 __u64 client_chal; /* random */ 671 665 __u32 reserved2; 672 - struct ntlmssp2_name names[2]; 673 666 /* array of name entries could follow ending in minimum 4 byte struct */ 674 667 } __attribute__((packed)); 675 668
+6 -6
fs/cifs/cifsproto.h
··· 361 361 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, 362 362 __u32 *); 363 363 extern int cifs_verify_signature(struct smb_hdr *, 364 - const struct mac_key *mac_key, 364 + struct TCP_Server_Info *server, 365 365 __u32 expected_sequence_number); 366 - extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 366 + extern int cifs_calculate_session_key(struct session_key *key, const char *rn, 367 367 const char *pass); 368 - extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, 369 - const struct nls_table *); 370 - extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); 371 - extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 368 + extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 372 369 const struct nls_table *); 370 + extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); 371 + extern void cifs_crypto_shash_release(struct TCP_Server_Info *); 372 + extern int calc_seckey(struct TCP_Server_Info *); 373 373 #ifdef CONFIG_CIFS_WEAK_PW_HASH 374 374 extern void calc_lanman_hash(const char *password, const char *cryptkey, 375 375 bool encrypt, char *lnm_session_key);
+8 -5
fs/cifs/cifssmb.c
··· 604 604 else 605 605 rc = -EINVAL; 606 606 607 - if (server->sec_kerberos || server->sec_mskerberos) 608 - server->secType = Kerberos; 609 - else if (server->sec_ntlmssp) 610 - server->secType = RawNTLMSSP; 611 - else 607 + if (server->secType == Kerberos) { 608 + if (!server->sec_kerberos && 609 + !server->sec_mskerberos) 610 + rc = -EOPNOTSUPP; 611 + } else if (server->secType == RawNTLMSSP) { 612 + if (!server->sec_ntlmssp) 613 + rc = -EOPNOTSUPP; 614 + } else 612 615 rc = -EOPNOTSUPP; 613 616 } 614 617 } else
+12 -1
fs/cifs/connect.c
··· 1707 1707 CIFSSMBLogoff(xid, ses); 1708 1708 _FreeXid(xid); 1709 1709 } 1710 + cifs_crypto_shash_release(server); 1710 1711 sesInfoFree(ses); 1711 1712 cifs_put_tcp_session(server); 1712 1713 } ··· 1787 1786 ses->linux_uid = volume_info->linux_uid; 1788 1787 ses->overrideSecFlg = volume_info->secFlg; 1789 1788 1789 + rc = cifs_crypto_shash_allocate(server); 1790 + if (rc) { 1791 + cERROR(1, "could not setup hash structures rc %d", rc); 1792 + goto get_ses_fail; 1793 + } 1794 + server->tilen = 0; 1795 + server->tiblob = NULL; 1796 + 1790 1797 mutex_lock(&ses->session_mutex); 1791 1798 rc = cifs_negotiate_protocol(xid, ses); 1792 1799 if (!rc) 1793 1800 rc = cifs_setup_session(xid, ses, volume_info->local_nls); 1794 1801 mutex_unlock(&ses->session_mutex); 1795 - if (rc) 1802 + if (rc) { 1803 + cifs_crypto_shash_release(ses->server); 1796 1804 goto get_ses_fail; 1805 + } 1797 1806 1798 1807 /* success, put it on the list */ 1799 1808 write_lock(&cifs_tcp_ses_lock);
+13
fs/cifs/ntlmssp.h
··· 61 61 #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 62 62 #define NTLMSSP_NEGOTIATE_56 0x80000000 63 63 64 + /* Define AV Pair Field IDs */ 65 + #define NTLMSSP_AV_EOL 0 66 + #define NTLMSSP_AV_NB_COMPUTER_NAME 1 67 + #define NTLMSSP_AV_NB_DOMAIN_NAME 2 68 + #define NTLMSSP_AV_DNS_COMPUTER_NAME 3 69 + #define NTLMSSP_AV_DNS_DOMAIN_NAME 4 70 + #define NTLMSSP_AV_DNS_TREE_NAME 5 71 + #define NTLMSSP_AV_FLAGS 6 72 + #define NTLMSSP_AV_TIMESTAMP 7 73 + #define NTLMSSP_AV_RESTRICTION 8 74 + #define NTLMSSP_AV_TARGET_NAME 9 75 + #define NTLMSSP_AV_CHANNEL_BINDINGS 10 76 + 64 77 /* Although typedefs are not commonly used for structure definitions */ 65 78 /* in the Linux kernel, in this particular case they are useful */ 66 79 /* to more closely match the standards document for NTLMSSP from */
+89 -29
fs/cifs/sess.c
··· 383 383 static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, 384 384 struct cifsSesInfo *ses) 385 385 { 386 + unsigned int tioffset; /* challeng message target info area */ 387 + unsigned int tilen; /* challeng message target info area length */ 388 + 386 389 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; 387 390 388 391 if (blob_len < sizeof(CHALLENGE_MESSAGE)) { ··· 407 404 /* In particular we can examine sign flags */ 408 405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then 409 406 we must set the MIC field of the AUTHENTICATE_MESSAGE */ 407 + 408 + tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); 409 + tilen = cpu_to_le16(pblob->TargetInfoArray.Length); 410 + ses->server->tilen = tilen; 411 + if (tilen) { 412 + ses->server->tiblob = kmalloc(tilen, GFP_KERNEL); 413 + if (!ses->server->tiblob) { 414 + cERROR(1, "Challenge target info allocation failure"); 415 + return -ENOMEM; 416 + } 417 + memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen); 418 + } 410 419 411 420 return 0; 412 421 } ··· 466 451 struct cifsSesInfo *ses, 467 452 const struct nls_table *nls_cp, bool first) 468 453 { 454 + int rc; 455 + unsigned int size; 469 456 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 470 457 __u32 flags; 471 458 unsigned char *tmp; 472 - char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 459 + struct ntlmv2_resp ntlmv2_response = {}; 473 460 474 461 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 475 462 sec_blob->MessageType = NtLmAuthenticate; ··· 494 477 sec_blob->LmChallengeResponse.Length = 0; 495 478 sec_blob->LmChallengeResponse.MaximumLength = 0; 496 479 497 - /* calculate session key, BB what about adding similar ntlmv2 path? */ 498 - SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); 499 - if (first) 500 - cifs_calculate_mac_key(&ses->server->mac_signing_key, 501 - ntlm_session_key, ses->password); 502 - 503 - memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); 504 480 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 505 - sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 506 - sec_blob->NtChallengeResponse.MaximumLength = 507 - cpu_to_le16(CIFS_SESS_KEY_SIZE); 481 + rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); 482 + if (rc) { 483 + cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); 484 + goto setup_ntlmv2_ret; 485 + } 486 + size = sizeof(struct ntlmv2_resp); 487 + memcpy(tmp, (char *)&ntlmv2_response, size); 488 + tmp += size; 489 + if (ses->server->tilen > 0) { 490 + memcpy(tmp, ses->server->tiblob, ses->server->tilen); 491 + tmp += ses->server->tilen; 492 + } else 493 + ses->server->tilen = 0; 508 494 509 - tmp += CIFS_SESS_KEY_SIZE; 495 + sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + 496 + ses->server->tilen); 497 + sec_blob->NtChallengeResponse.MaximumLength = 498 + cpu_to_le16(size + ses->server->tilen); 510 499 511 500 if (ses->domainName == NULL) { 512 501 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); ··· 524 501 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 525 502 MAX_USERNAME_SIZE, nls_cp); 526 503 len *= 2; /* unicode is 2 bytes each */ 527 - len += 2; /* trailing null */ 528 504 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 529 505 sec_blob->DomainName.Length = cpu_to_le16(len); 530 506 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); ··· 540 518 len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 541 519 MAX_USERNAME_SIZE, nls_cp); 542 520 len *= 2; /* unicode is 2 bytes each */ 543 - len += 2; /* trailing null */ 544 521 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 545 522 sec_blob->UserName.Length = cpu_to_le16(len); 546 523 sec_blob->UserName.MaximumLength = cpu_to_le16(len); ··· 551 530 sec_blob->WorkstationName.MaximumLength = 0; 552 531 tmp += 2; 553 532 554 - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 555 - sec_blob->SessionKey.Length = 0; 556 - sec_blob->SessionKey.MaximumLength = 0; 533 + if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && 534 + !calc_seckey(ses->server)) { 535 + memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); 536 + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 537 + sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); 538 + sec_blob->SessionKey.MaximumLength = 539 + cpu_to_le16(CIFS_CPHTXT_SIZE); 540 + tmp += CIFS_CPHTXT_SIZE; 541 + } else { 542 + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 543 + sec_blob->SessionKey.Length = 0; 544 + sec_blob->SessionKey.MaximumLength = 0; 545 + } 546 + 547 + ses->server->sequence_number = 0; 548 + 549 + setup_ntlmv2_ret: 550 + if (ses->server->tilen > 0) 551 + kfree(ses->server->tiblob); 552 + 557 553 return tmp - pbuffer; 558 554 } 559 555 ··· 584 546 return; 585 547 } 586 548 587 - static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, 549 + static int setup_ntlmssp_auth_req(char *ntlmsspblob, 588 550 struct cifsSesInfo *ses, 589 551 const struct nls_table *nls, bool first_time) 590 552 { 591 553 int bloblen; 592 554 593 - bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, 555 + bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, 594 556 first_time); 595 - pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); 596 557 597 558 return bloblen; 598 559 } ··· 617 580 struct key *spnego_key = NULL; 618 581 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 619 582 bool first_time; 583 + char *ntlmsspblob; 620 584 621 585 if (ses == NULL) 622 586 return -EINVAL; ··· 728 690 729 691 if (first_time) /* should this be moved into common code 730 692 with similar ntlmv2 path? */ 731 - cifs_calculate_mac_key(&ses->server->mac_signing_key, 693 + cifs_calculate_session_key(&ses->server->session_key, 732 694 ntlm_session_key, ses->password); 733 695 /* copy session key */ 734 696 ··· 767 729 cpu_to_le16(sizeof(struct ntlmv2_resp)); 768 730 769 731 /* calculate session key */ 770 - setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 732 + rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 733 + if (rc) { 734 + kfree(v2_sess_key); 735 + goto ssetup_exit; 736 + } 771 737 /* FIXME: calculate MAC key */ 772 738 memcpy(bcc_ptr, (char *)v2_sess_key, 773 739 sizeof(struct ntlmv2_resp)); 774 740 bcc_ptr += sizeof(struct ntlmv2_resp); 775 741 kfree(v2_sess_key); 742 + if (ses->server->tilen > 0) { 743 + memcpy(bcc_ptr, ses->server->tiblob, 744 + ses->server->tilen); 745 + bcc_ptr += ses->server->tilen; 746 + } 776 747 if (ses->capabilities & CAP_UNICODE) { 777 748 if (iov[0].iov_len % 2) { 778 749 *bcc_ptr = 0; ··· 812 765 } 813 766 /* bail out if key is too long */ 814 767 if (msg->sesskey_len > 815 - sizeof(ses->server->mac_signing_key.data.krb5)) { 768 + sizeof(ses->server->session_key.data.krb5)) { 816 769 cERROR(1, "Kerberos signing key too long (%u bytes)", 817 770 msg->sesskey_len); 818 771 rc = -EOVERFLOW; 819 772 goto ssetup_exit; 820 773 } 821 774 if (first_time) { 822 - ses->server->mac_signing_key.len = msg->sesskey_len; 823 - memcpy(ses->server->mac_signing_key.data.krb5, 775 + ses->server->session_key.len = msg->sesskey_len; 776 + memcpy(ses->server->session_key.data.krb5, 824 777 msg->data, msg->sesskey_len); 825 778 } 826 779 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; ··· 862 815 if (phase == NtLmNegotiate) { 863 816 setup_ntlmssp_neg_req(pSMB, ses); 864 817 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 818 + iov[1].iov_base = &pSMB->req.SecurityBlob[0]; 865 819 } else if (phase == NtLmAuthenticate) { 866 820 int blob_len; 867 - blob_len = setup_ntlmssp_auth_req(pSMB, ses, 868 - nls_cp, 869 - first_time); 821 + ntlmsspblob = kmalloc(5 * 822 + sizeof(struct _AUTHENTICATE_MESSAGE), 823 + GFP_KERNEL); 824 + if (!ntlmsspblob) { 825 + cERROR(1, "Can't allocate NTLMSSP"); 826 + rc = -ENOMEM; 827 + goto ssetup_exit; 828 + } 829 + 830 + blob_len = setup_ntlmssp_auth_req(ntlmsspblob, 831 + ses, 832 + nls_cp, 833 + first_time); 870 834 iov[1].iov_len = blob_len; 835 + iov[1].iov_base = ntlmsspblob; 836 + pSMB->req.SecurityBlobLength = 837 + cpu_to_le16(blob_len); 871 838 /* Make sure that we tell the server that we 872 839 are using the uid that it just gave us back 873 840 on the response (challenge) */ ··· 891 830 rc = -ENOSYS; 892 831 goto ssetup_exit; 893 832 } 894 - iov[1].iov_base = &pSMB->req.SecurityBlob[0]; 895 833 /* unicode strings must be word aligned */ 896 834 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 897 835 *bcc_ptr = 0;
+3 -3
fs/cifs/transport.c
··· 543 543 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 544 544 SECMODE_SIGN_ENABLED))) { 545 545 rc = cifs_verify_signature(midQ->resp_buf, 546 - &ses->server->mac_signing_key, 546 + ses->server, 547 547 midQ->sequence_number+1); 548 548 if (rc) { 549 549 cERROR(1, "Unexpected SMB signature"); ··· 731 731 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 732 732 SECMODE_SIGN_ENABLED))) { 733 733 rc = cifs_verify_signature(out_buf, 734 - &ses->server->mac_signing_key, 734 + ses->server, 735 735 midQ->sequence_number+1); 736 736 if (rc) { 737 737 cERROR(1, "Unexpected SMB signature"); ··· 981 981 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 982 982 SECMODE_SIGN_ENABLED))) { 983 983 rc = cifs_verify_signature(out_buf, 984 - &ses->server->mac_signing_key, 984 + ses->server, 985 985 midQ->sequence_number+1); 986 986 if (rc) { 987 987 cERROR(1, "Unexpected SMB signature");