aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorShirish Pargaonkar <shirishpargaonkar@gmail.com>2010-10-28 10:53:07 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-28 21:47:33 -0400
commitd3686d54c7902a303bd65d751226aa1647319863 (patch)
treeb4acd7dfc6c5ec2f254608a2f0ef11ef274861b8 /fs/cifs
parentd3ba50b17aa7a391bb5b3dcd8d6ba7a02c4f031c (diff)
cifs: Cleanup and thus reduce smb session structure and fields used during authentication
Removed following fields from smb session structure cryptkey, ntlmv2_hash, tilen, tiblob and ntlmssp_auth structure is allocated dynamically only if the auth mech in NTLMSSP. response field within a session_key structure is used to initially store the target info (either plucked from type 2 challenge packet in case of NTLMSSP or fabricated in case of NTLMv2 without extended security) and then to store Message Authentication Key (mak) (session key + client response). Server challenge or cryptkey needed during a NTLMSSP authentication is now part of ntlmssp_auth structure which gets allocated and freed once authenticaiton process is done. Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsencrypt.c53
-rw-r--r--fs/cifs/cifsglob.h9
-rw-r--r--fs/cifs/connect.c11
-rw-r--r--fs/cifs/sess.c29
4 files changed, 55 insertions, 47 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index ef95a272f73d..f856732161ab 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -328,15 +328,15 @@ build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
328 * two times the unicode length of a server name + 328 * two times the unicode length of a server name +
329 * size of a timestamp (which is 8 bytes). 329 * size of a timestamp (which is 8 bytes).
330 */ 330 */
331 ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8; 331 ses->auth_key.len = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
332 ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL); 332 ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
333 if (!ses->tiblob) { 333 if (!ses->auth_key.response) {
334 ses->tilen = 0; 334 ses->auth_key.len = 0;
335 cERROR(1, "Challenge target info allocation failure"); 335 cERROR(1, "Challenge target info allocation failure");
336 return -ENOMEM; 336 return -ENOMEM;
337 } 337 }
338 338
339 blobptr = ses->tiblob; 339 blobptr = ses->auth_key.response;
340 attrptr = (struct ntlmssp2_name *) blobptr; 340 attrptr = (struct ntlmssp2_name *) blobptr;
341 341
342 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); 342 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
@@ -400,11 +400,11 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
400 unsigned char *blobend; 400 unsigned char *blobend;
401 struct ntlmssp2_name *attrptr; 401 struct ntlmssp2_name *attrptr;
402 402
403 if (!ses->tilen || !ses->tiblob) 403 if (!ses->auth_key.len || !ses->auth_key.response)
404 return 0; 404 return 0;
405 405
406 blobptr = ses->tiblob; 406 blobptr = ses->auth_key.response;
407 blobend = ses->tiblob + ses->tilen; 407 blobend = blobptr + ses->auth_key.len;
408 408
409 while (blobptr + onesize < blobend) { 409 while (blobptr + onesize < blobend) {
410 attrptr = (struct ntlmssp2_name *) blobptr; 410 attrptr = (struct ntlmssp2_name *) blobptr;
@@ -436,7 +436,7 @@ find_domain_name(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
436 return 0; 436 return 0;
437} 437}
438 438
439static int calc_ntlmv2_hash(struct cifsSesInfo *ses, 439static int calc_ntlmv2_hash(struct cifsSesInfo *ses, char *ntlmv2_hash,
440 const struct nls_table *nls_cp) 440 const struct nls_table *nls_cp)
441{ 441{
442 int rc = 0; 442 int rc = 0;
@@ -509,7 +509,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
509 } 509 }
510 510
511 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, 511 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
512 ses->ntlmv2_hash); 512 ntlmv2_hash);
513 513
514calc_exit_1: 514calc_exit_1:
515 kfree(user); 515 kfree(user);
@@ -518,7 +518,7 @@ calc_exit_2:
518} 518}
519 519
520static int 520static int
521CalcNTLMv2_response(const struct cifsSesInfo *ses) 521CalcNTLMv2_response(const struct cifsSesInfo *ses, char *ntlmv2_hash)
522{ 522{
523 int rc; 523 int rc;
524 unsigned int offset = CIFS_SESS_KEY_SIZE + 8; 524 unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
@@ -529,7 +529,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses)
529 } 529 }
530 530
531 crypto_shash_setkey(ses->server->secmech.hmacmd5, 531 crypto_shash_setkey(ses->server->secmech.hmacmd5,
532 ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); 532 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
533 533
534 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); 534 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
535 if (rc) { 535 if (rc) {
@@ -539,7 +539,7 @@ CalcNTLMv2_response(const struct cifsSesInfo *ses)
539 539
540 if (ses->server->secType == RawNTLMSSP) 540 if (ses->server->secType == RawNTLMSSP)
541 memcpy(ses->auth_key.response + offset, 541 memcpy(ses->auth_key.response + offset,
542 ses->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 542 ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
543 else 543 else
544 memcpy(ses->auth_key.response + offset, 544 memcpy(ses->auth_key.response + offset,
545 ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 545 ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
@@ -558,7 +558,10 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
558{ 558{
559 int rc; 559 int rc;
560 int baselen; 560 int baselen;
561 unsigned int tilen;
561 struct ntlmv2_resp *buf; 562 struct ntlmv2_resp *buf;
563 char ntlmv2_hash[16];
564 unsigned char *tiblob = NULL; /* target info blob */
562 565
563 if (ses->server->secType == RawNTLMSSP) { 566 if (ses->server->secType == RawNTLMSSP) {
564 if (!ses->domainName) { 567 if (!ses->domainName) {
@@ -572,18 +575,22 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
572 rc = build_avpair_blob(ses, nls_cp); 575 rc = build_avpair_blob(ses, nls_cp);
573 if (rc) { 576 if (rc) {
574 cERROR(1, "error %d building av pair blob", rc); 577 cERROR(1, "error %d building av pair blob", rc);
575 return rc; 578 goto setup_ntlmv2_rsp_ret;
576 } 579 }
577 } 580 }
578 581
579 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); 582 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
580 ses->auth_key.len = baselen + ses->tilen; 583 tilen = ses->auth_key.len;
581 ses->auth_key.response = kmalloc(ses->auth_key.len, GFP_KERNEL); 584 tiblob = ses->auth_key.response;
585
586 ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
582 if (!ses->auth_key.response) { 587 if (!ses->auth_key.response) {
583 rc = ENOMEM; 588 rc = ENOMEM;
589 ses->auth_key.len = 0;
584 cERROR(1, "%s: Can't allocate auth blob", __func__); 590 cERROR(1, "%s: Can't allocate auth blob", __func__);
585 goto setup_ntlmv2_rsp_ret; 591 goto setup_ntlmv2_rsp_ret;
586 } 592 }
593 ses->auth_key.len += baselen;
587 594
588 buf = (struct ntlmv2_resp *) 595 buf = (struct ntlmv2_resp *)
589 (ses->auth_key.response + CIFS_SESS_KEY_SIZE); 596 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
@@ -593,17 +600,17 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
593 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 600 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
594 buf->reserved2 = 0; 601 buf->reserved2 = 0;
595 602
596 memcpy(ses->auth_key.response + baselen, ses->tiblob, ses->tilen); 603 memcpy(ses->auth_key.response + baselen, tiblob, tilen);
597 604
598 /* calculate ntlmv2_hash */ 605 /* calculate ntlmv2_hash */
599 rc = calc_ntlmv2_hash(ses, nls_cp); 606 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
600 if (rc) { 607 if (rc) {
601 cERROR(1, "could not get v2 hash rc %d", rc); 608 cERROR(1, "could not get v2 hash rc %d", rc);
602 goto setup_ntlmv2_rsp_ret; 609 goto setup_ntlmv2_rsp_ret;
603 } 610 }
604 611
605 /* calculate first part of the client response (CR1) */ 612 /* calculate first part of the client response (CR1) */
606 rc = CalcNTLMv2_response(ses); 613 rc = CalcNTLMv2_response(ses, ntlmv2_hash);
607 if (rc) { 614 if (rc) {
608 cERROR(1, "Could not calculate CR1 rc: %d", rc); 615 cERROR(1, "Could not calculate CR1 rc: %d", rc);
609 goto setup_ntlmv2_rsp_ret; 616 goto setup_ntlmv2_rsp_ret;
@@ -611,7 +618,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
611 618
612 /* now calculate the session key for NTLMv2 */ 619 /* now calculate the session key for NTLMv2 */
613 crypto_shash_setkey(ses->server->secmech.hmacmd5, 620 crypto_shash_setkey(ses->server->secmech.hmacmd5,
614 ses->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); 621 ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
615 622
616 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); 623 rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
617 if (rc) { 624 if (rc) {
@@ -627,9 +634,7 @@ setup_ntlmv2_rsp(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
627 ses->auth_key.response); 634 ses->auth_key.response);
628 635
629setup_ntlmv2_rsp_ret: 636setup_ntlmv2_rsp_ret:
630 kfree(ses->tiblob); 637 kfree(tiblob);
631 ses->tiblob = NULL;
632 ses->tilen = 0;
633 638
634 return rc; 639 return rc;
635} 640}
@@ -657,7 +662,7 @@ calc_seckey(struct cifsSesInfo *ses)
657 CIFS_SESS_KEY_SIZE); 662 CIFS_SESS_KEY_SIZE);
658 663
659 sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); 664 sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
660 sg_init_one(&sgout, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); 665 sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
661 666
662 rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); 667 rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
663 if (rc) { 668 if (rc) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b73695176467..f259e4d7612d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -119,11 +119,12 @@ struct cifs_secmech {
119 struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ 119 struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
120}; 120};
121 121
122/* per smb connection structure/fields */ 122/* per smb session structure/fields */
123struct ntlmssp_auth { 123struct ntlmssp_auth {
124 __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */ 124 __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */
125 __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */ 125 __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */
126 unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */ 126 unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */
127 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
127}; 128};
128 129
129struct cifs_cred { 130struct cifs_cred {
@@ -241,12 +242,8 @@ struct cifsSesInfo {
241 char userName[MAX_USERNAME_SIZE + 1]; 242 char userName[MAX_USERNAME_SIZE + 1];
242 char *domainName; 243 char *domainName;
243 char *password; 244 char *password;
244 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
245 struct session_key auth_key; 245 struct session_key auth_key;
246 char ntlmv2_hash[16]; 246 struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
247 unsigned int tilen; /* length of the target info blob */
248 unsigned char *tiblob; /* target info blob in challenge response */
249 struct ntlmssp_auth ntlmssp; /* ciphertext, flags */
250 bool need_reconnect:1; /* connection reset, uid now invalid */ 247 bool need_reconnect:1; /* connection reset, uid now invalid */
251}; 248};
252/* no more than one of the following three session flags may be set */ 249/* no more than one of the following three session flags may be set */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4d8004ce5834..9eb327defa1d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1818,8 +1818,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1818 if (ses == NULL) 1818 if (ses == NULL)
1819 goto get_ses_fail; 1819 goto get_ses_fail;
1820 1820
1821 ses->tilen = 0;
1822 ses->tiblob = NULL;
1823 /* new SMB session uses our server ref */ 1821 /* new SMB session uses our server ref */
1824 ses->server = server; 1822 ses->server = server;
1825 if (server->addr.sockAddr6.sin6_family == AF_INET6) 1823 if (server->addr.sockAddr6.sin6_family == AF_INET6)
@@ -1840,10 +1838,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1840 goto get_ses_fail; 1838 goto get_ses_fail;
1841 } 1839 }
1842 if (volume_info->domainname) { 1840 if (volume_info->domainname) {
1843 int len = strlen(volume_info->domainname); 1841 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
1844 ses->domainName = kmalloc(len + 1, GFP_KERNEL); 1842 if (!ses->domainName)
1845 if (ses->domainName) 1843 goto get_ses_fail;
1846 strcpy(ses->domainName, volume_info->domainname);
1847 } 1844 }
1848 ses->cred_uid = volume_info->cred_uid; 1845 ses->cred_uid = volume_info->cred_uid;
1849 ses->linux_uid = volume_info->linux_uid; 1846 ses->linux_uid = volume_info->linux_uid;
@@ -3213,6 +3210,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
3213 kfree(ses->auth_key.response); 3210 kfree(ses->auth_key.response);
3214 ses->auth_key.response = NULL; 3211 ses->auth_key.response = NULL;
3215 ses->auth_key.len = 0; 3212 ses->auth_key.len = 0;
3213 kfree(ses->ntlmssp);
3214 ses->ntlmssp = NULL;
3216 3215
3217 return rc; 3216 return rc;
3218} 3217}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index f74c5a88dd4c..7b01d3f6eed6 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -399,23 +399,22 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
399 return -EINVAL; 399 return -EINVAL;
400 } 400 }
401 401
402 memcpy(ses->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); 402 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
403 /* BB we could decode pblob->NegotiateFlags; some may be useful */ 403 /* BB we could decode pblob->NegotiateFlags; some may be useful */
404 /* In particular we can examine sign flags */ 404 /* In particular we can examine sign flags */
405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then 405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
406 we must set the MIC field of the AUTHENTICATE_MESSAGE */ 406 we must set the MIC field of the AUTHENTICATE_MESSAGE */
407 ses->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); 407 ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
408 tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); 408 tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
409 tilen = cpu_to_le16(pblob->TargetInfoArray.Length); 409 tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
410 ses->tilen = tilen; 410 if (tilen) {
411 if (ses->tilen) { 411 ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
412 ses->tiblob = kmalloc(tilen, GFP_KERNEL); 412 if (!ses->auth_key.response) {
413 if (!ses->tiblob) {
414 cERROR(1, "Challenge target info allocation failure"); 413 cERROR(1, "Challenge target info allocation failure");
415 ses->tilen = 0;
416 return -ENOMEM; 414 return -ENOMEM;
417 } 415 }
418 memcpy(ses->tiblob, bcc_ptr + tioffset, ses->tilen); 416 memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen);
417 ses->auth_key.len = tilen;
419 } 418 }
420 419
421 return 0; 420 return 0;
@@ -545,9 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
545 sec_blob->WorkstationName.MaximumLength = 0; 544 sec_blob->WorkstationName.MaximumLength = 0;
546 tmp += 2; 545 tmp += 2;
547 546
548 if ((ses->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && 547 if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
549 !calc_seckey(ses)) { 548 !calc_seckey(ses)) {
550 memcpy(tmp, ses->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); 549 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
551 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 550 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
552 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); 551 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
553 sec_blob->SessionKey.MaximumLength = 552 sec_blob->SessionKey.MaximumLength =
@@ -601,8 +600,16 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
601 return -EINVAL; 600 return -EINVAL;
602 601
603 type = ses->server->secType; 602 type = ses->server->secType;
604
605 cFYI(1, "sess setup type %d", type); 603 cFYI(1, "sess setup type %d", type);
604 if (type == RawNTLMSSP) {
605 /* if memory allocation is successful, caller of this function
606 * frees it.
607 */
608 ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
609 if (!ses->ntlmssp)
610 return -ENOMEM;
611 }
612
606ssetup_ntlmssp_authenticate: 613ssetup_ntlmssp_authenticate:
607 if (phase == NtLmChallenge) 614 if (phase == NtLmChallenge)
608 phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ 615 phase = NtLmAuthenticate; /* if ntlmssp, now final phase */