aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/sess.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2010-08-20 16:42:26 -0400
committerSteve French <sfrench@us.ibm.com>2010-08-20 16:42:26 -0400
commit9fbc590860e75785bdaf8b83e48fabfe4d4f7d58 (patch)
treedccc154927cf1e12c702537b5bc028158b938e21 /fs/cifs/sess.c
parentbf4f12113812ac5be76c5590c6f50c8346f784a4 (diff)
[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>
Diffstat (limited to 'fs/cifs/sess.c')
-rw-r--r--fs/cifs/sess.c118
1 files changed, 89 insertions, 29 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7db5dd..41fc5328120d 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, 383static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
384 struct cifsSesInfo *ses) 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 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; 389 CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
387 390
388 if (blob_len < sizeof(CHALLENGE_MESSAGE)) { 391 if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
@@ -405,6 +408,18 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
405 /* BB spec says that if AvId field of MsvAvTimestamp is populated then 408 /* BB spec says that if AvId field of MsvAvTimestamp is populated then
406 we must set the MIC field of the AUTHENTICATE_MESSAGE */ 409 we must set the MIC field of the AUTHENTICATE_MESSAGE */
407 410
411 tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
412 tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
413 ses->server->tilen = tilen;
414 if (tilen) {
415 ses->server->tiblob = kmalloc(tilen, GFP_KERNEL);
416 if (!ses->server->tiblob) {
417 cERROR(1, "Challenge target info allocation failure");
418 return -ENOMEM;
419 }
420 memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen);
421 }
422
408 return 0; 423 return 0;
409} 424}
410 425
@@ -451,10 +466,12 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
451 struct cifsSesInfo *ses, 466 struct cifsSesInfo *ses,
452 const struct nls_table *nls_cp, bool first) 467 const struct nls_table *nls_cp, bool first)
453{ 468{
469 int rc;
470 unsigned int size;
454 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; 471 AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
455 __u32 flags; 472 __u32 flags;
456 unsigned char *tmp; 473 unsigned char *tmp;
457 char ntlm_session_key[CIFS_SESS_KEY_SIZE]; 474 struct ntlmv2_resp ntlmv2_response = {};
458 475
459 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 476 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
460 sec_blob->MessageType = NtLmAuthenticate; 477 sec_blob->MessageType = NtLmAuthenticate;
@@ -477,19 +494,25 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
477 sec_blob->LmChallengeResponse.Length = 0; 494 sec_blob->LmChallengeResponse.Length = 0;
478 sec_blob->LmChallengeResponse.MaximumLength = 0; 495 sec_blob->LmChallengeResponse.MaximumLength = 0;
479 496
480 /* calculate session key, BB what about adding similar ntlmv2 path? */
481 SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
482 if (first)
483 cifs_calculate_mac_key(&ses->server->mac_signing_key,
484 ntlm_session_key, ses->password);
485
486 memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
487 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); 497 sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
488 sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); 498 rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
489 sec_blob->NtChallengeResponse.MaximumLength = 499 if (rc) {
490 cpu_to_le16(CIFS_SESS_KEY_SIZE); 500 cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc);
501 goto setup_ntlmv2_ret;
502 }
503 size = sizeof(struct ntlmv2_resp);
504 memcpy(tmp, (char *)&ntlmv2_response, size);
505 tmp += size;
506 if (ses->server->tilen > 0) {
507 memcpy(tmp, ses->server->tiblob, ses->server->tilen);
508 tmp += ses->server->tilen;
509 } else
510 ses->server->tilen = 0;
491 511
492 tmp += CIFS_SESS_KEY_SIZE; 512 sec_blob->NtChallengeResponse.Length = cpu_to_le16(size +
513 ses->server->tilen);
514 sec_blob->NtChallengeResponse.MaximumLength =
515 cpu_to_le16(size + ses->server->tilen);
493 516
494 if (ses->domainName == NULL) { 517 if (ses->domainName == NULL) {
495 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 518 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +524,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
501 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, 524 len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
502 MAX_USERNAME_SIZE, nls_cp); 525 MAX_USERNAME_SIZE, nls_cp);
503 len *= 2; /* unicode is 2 bytes each */ 526 len *= 2; /* unicode is 2 bytes each */
504 len += 2; /* trailing null */
505 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); 527 sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
506 sec_blob->DomainName.Length = cpu_to_le16(len); 528 sec_blob->DomainName.Length = cpu_to_le16(len);
507 sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 529 sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +540,6 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
518 len = cifs_strtoUCS((__le16 *)tmp, ses->userName, 540 len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
519 MAX_USERNAME_SIZE, nls_cp); 541 MAX_USERNAME_SIZE, nls_cp);
520 len *= 2; /* unicode is 2 bytes each */ 542 len *= 2; /* unicode is 2 bytes each */
521 len += 2; /* trailing null */
522 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); 543 sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
523 sec_blob->UserName.Length = cpu_to_le16(len); 544 sec_blob->UserName.Length = cpu_to_le16(len);
524 sec_blob->UserName.MaximumLength = cpu_to_le16(len); 545 sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -530,9 +551,26 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
530 sec_blob->WorkstationName.MaximumLength = 0; 551 sec_blob->WorkstationName.MaximumLength = 0;
531 tmp += 2; 552 tmp += 2;
532 553
533 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 554 if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
534 sec_blob->SessionKey.Length = 0; 555 !calc_seckey(ses->server)) {
535 sec_blob->SessionKey.MaximumLength = 0; 556 memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE);
557 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
558 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
559 sec_blob->SessionKey.MaximumLength =
560 cpu_to_le16(CIFS_CPHTXT_SIZE);
561 tmp += CIFS_CPHTXT_SIZE;
562 } else {
563 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
564 sec_blob->SessionKey.Length = 0;
565 sec_blob->SessionKey.MaximumLength = 0;
566 }
567
568 ses->server->sequence_number = 0;
569
570setup_ntlmv2_ret:
571 if (ses->server->tilen > 0)
572 kfree(ses->server->tiblob);
573
536 return tmp - pbuffer; 574 return tmp - pbuffer;
537} 575}
538 576
@@ -546,15 +584,14 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
546 return; 584 return;
547} 585}
548 586
549static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, 587static int setup_ntlmssp_auth_req(char *ntlmsspblob,
550 struct cifsSesInfo *ses, 588 struct cifsSesInfo *ses,
551 const struct nls_table *nls, bool first_time) 589 const struct nls_table *nls, bool first_time)
552{ 590{
553 int bloblen; 591 int bloblen;
554 592
555 bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, 593 bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls,
556 first_time); 594 first_time);
557 pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
558 595
559 return bloblen; 596 return bloblen;
560} 597}
@@ -580,6 +617,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
580 struct key *spnego_key = NULL; 617 struct key *spnego_key = NULL;
581 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 618 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
582 bool first_time; 619 bool first_time;
620 char *ntlmsspblob;
583 621
584 if (ses == NULL) 622 if (ses == NULL)
585 return -EINVAL; 623 return -EINVAL;
@@ -690,7 +728,7 @@ ssetup_ntlmssp_authenticate:
690 728
691 if (first_time) /* should this be moved into common code 729 if (first_time) /* should this be moved into common code
692 with similar ntlmv2 path? */ 730 with similar ntlmv2 path? */
693 cifs_calculate_mac_key(&ses->server->mac_signing_key, 731 cifs_calculate_session_key(&ses->server->session_key,
694 ntlm_session_key, ses->password); 732 ntlm_session_key, ses->password);
695 /* copy session key */ 733 /* copy session key */
696 734
@@ -729,12 +767,21 @@ ssetup_ntlmssp_authenticate:
729 cpu_to_le16(sizeof(struct ntlmv2_resp)); 767 cpu_to_le16(sizeof(struct ntlmv2_resp));
730 768
731 /* calculate session key */ 769 /* calculate session key */
732 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); 770 rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
771 if (rc) {
772 kfree(v2_sess_key);
773 goto ssetup_exit;
774 }
733 /* FIXME: calculate MAC key */ 775 /* FIXME: calculate MAC key */
734 memcpy(bcc_ptr, (char *)v2_sess_key, 776 memcpy(bcc_ptr, (char *)v2_sess_key,
735 sizeof(struct ntlmv2_resp)); 777 sizeof(struct ntlmv2_resp));
736 bcc_ptr += sizeof(struct ntlmv2_resp); 778 bcc_ptr += sizeof(struct ntlmv2_resp);
737 kfree(v2_sess_key); 779 kfree(v2_sess_key);
780 if (ses->server->tilen > 0) {
781 memcpy(bcc_ptr, ses->server->tiblob,
782 ses->server->tilen);
783 bcc_ptr += ses->server->tilen;
784 }
738 if (ses->capabilities & CAP_UNICODE) { 785 if (ses->capabilities & CAP_UNICODE) {
739 if (iov[0].iov_len % 2) { 786 if (iov[0].iov_len % 2) {
740 *bcc_ptr = 0; 787 *bcc_ptr = 0;
@@ -765,15 +812,15 @@ ssetup_ntlmssp_authenticate:
765 } 812 }
766 /* bail out if key is too long */ 813 /* bail out if key is too long */
767 if (msg->sesskey_len > 814 if (msg->sesskey_len >
768 sizeof(ses->server->mac_signing_key.data.krb5)) { 815 sizeof(ses->server->session_key.data.krb5)) {
769 cERROR(1, "Kerberos signing key too long (%u bytes)", 816 cERROR(1, "Kerberos signing key too long (%u bytes)",
770 msg->sesskey_len); 817 msg->sesskey_len);
771 rc = -EOVERFLOW; 818 rc = -EOVERFLOW;
772 goto ssetup_exit; 819 goto ssetup_exit;
773 } 820 }
774 if (first_time) { 821 if (first_time) {
775 ses->server->mac_signing_key.len = msg->sesskey_len; 822 ses->server->session_key.len = msg->sesskey_len;
776 memcpy(ses->server->mac_signing_key.data.krb5, 823 memcpy(ses->server->session_key.data.krb5,
777 msg->data, msg->sesskey_len); 824 msg->data, msg->sesskey_len);
778 } 825 }
779 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 826 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -815,12 +862,26 @@ ssetup_ntlmssp_authenticate:
815 if (phase == NtLmNegotiate) { 862 if (phase == NtLmNegotiate) {
816 setup_ntlmssp_neg_req(pSMB, ses); 863 setup_ntlmssp_neg_req(pSMB, ses);
817 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 864 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
865 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
818 } else if (phase == NtLmAuthenticate) { 866 } else if (phase == NtLmAuthenticate) {
819 int blob_len; 867 int blob_len;
820 blob_len = setup_ntlmssp_auth_req(pSMB, ses, 868 ntlmsspblob = kmalloc(5 *
821 nls_cp, 869 sizeof(struct _AUTHENTICATE_MESSAGE),
822 first_time); 870 GFP_KERNEL);
871 if (!ntlmsspblob) {
872 cERROR(1, "Can't allocate NTLMSSP");
873 rc = -ENOMEM;
874 goto ssetup_exit;
875 }
876
877 blob_len = setup_ntlmssp_auth_req(ntlmsspblob,
878 ses,
879 nls_cp,
880 first_time);
823 iov[1].iov_len = blob_len; 881 iov[1].iov_len = blob_len;
882 iov[1].iov_base = ntlmsspblob;
883 pSMB->req.SecurityBlobLength =
884 cpu_to_le16(blob_len);
824 /* Make sure that we tell the server that we 885 /* Make sure that we tell the server that we
825 are using the uid that it just gave us back 886 are using the uid that it just gave us back
826 on the response (challenge) */ 887 on the response (challenge) */
@@ -830,7 +891,6 @@ ssetup_ntlmssp_authenticate:
830 rc = -ENOSYS; 891 rc = -ENOSYS;
831 goto ssetup_exit; 892 goto ssetup_exit;
832 } 893 }
833 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 /* unicode strings must be word aligned */ 894 /* unicode strings must be word aligned */
835 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 895 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
836 *bcc_ptr = 0; 896 *bcc_ptr = 0;