aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/digestauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/digestauth.c')
-rw-r--r--src/microhttpd/digestauth.c207
1 files changed, 105 insertions, 102 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 9c3fe8c5..4cc7f61b 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 Copyright (C) 2010, 2011, 2012 Daniel Pittman and Christian Grothoff 3 Copyright (C) 2010, 2011, 2012, 2015 Daniel Pittman and Christian Grothoff
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
@@ -472,8 +472,8 @@ test_header (struct MHD_Connection *connection,
472 * 472 *
473 * @param connection connections with headers to compare against 473 * @param connection connections with headers to compare against
474 * @param args argument URI string (after "?" in URI) 474 * @param args argument URI string (after "?" in URI)
475 * @return MHD_YES if the arguments match, 475 * @return #MHD_YES if the arguments match,
476 * MHD_NO if not 476 * #MHD_NO if not
477 */ 477 */
478static int 478static int
479check_argument_match (struct MHD_Connection *connection, 479check_argument_match (struct MHD_Connection *connection,
@@ -632,10 +632,83 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
632 header value. */ 632 header value. */
633 return MHD_NO; 633 return MHD_NO;
634 } 634 }
635 /* 8 = 4 hexadecimal numbers for the timestamp */
636 nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16);
637 t = (uint32_t) MHD_monotonic_time();
638 /*
639 * First level vetting for the nonce validity: if the timestamp
640 * attached to the nonce exceeds `nonce_timeout', then the nonce is
641 * invalid.
642 */
643 if ( (t > nonce_time + nonce_timeout) ||
644 (nonce_time + nonce_timeout < nonce_time) )
645 {
646 /* too old */
647 return MHD_INVALID_NONCE;
648 }
649
650 calculate_nonce (nonce_time,
651 connection->method,
652 connection->daemon->digest_auth_random,
653 connection->daemon->digest_auth_rand_size,
654 connection->url,
655 realm,
656 noncehashexp);
657 /*
658 * Second level vetting for the nonce validity
659 * if the timestamp attached to the nonce is valid
660 * and possibly fabricated (in case of an attack)
661 * the attacker must also know the random seed to be
662 * able to generate a "sane" nonce, which if he does
663 * not, the nonce fabrication process going to be
664 * very hard to achieve.
665 */
666
667 if (0 != strcmp (nonce, noncehashexp))
668 {
669 return MHD_INVALID_NONCE;
670 }
671 if ( (0 == lookup_sub_value (cnonce,
672 sizeof (cnonce),
673 header, "cnonce")) ||
674 (0 == lookup_sub_value (qop, sizeof (qop), header, "qop")) ||
675 ( (0 != strcmp (qop, "auth")) &&
676 (0 != strcmp (qop, "")) ) ||
677 (0 == lookup_sub_value (nc, sizeof (nc), header, "nc")) ||
678 (0 == lookup_sub_value (response, sizeof (response), header, "response")) )
679 {
680#if HAVE_MESSAGES
681 MHD_DLOG (connection->daemon,
682 "Authentication failed, invalid format.\n");
683#endif
684 return MHD_NO;
685 }
686 nci = strtoul (nc, &end, 16);
687 if ( ('\0' != *end) ||
688 ( (LONG_MAX == nci) &&
689 (ERANGE == errno) ) )
690 {
691#if HAVE_MESSAGES
692 MHD_DLOG (connection->daemon,
693 "Authentication failed, invalid format.\n");
694#endif
695 return MHD_NO; /* invalid nonce format */
696 }
697 /*
698 * Checking if that combination of nonce and nc is sound
699 * and not a replay attack attempt. Also adds the nonce
700 * to the nonce-nc map if it does not exist there.
701 */
702
703 if (MHD_YES != check_nonce_nc (connection, nonce, nci))
704 {
705 return MHD_NO;
706 }
707
635 { 708 {
636 char *uri; 709 char *uri;
637 710
638 uri = malloc(left + 1); 711 uri = malloc (left + 1);
639 if (NULL == uri) 712 if (NULL == uri)
640 { 713 {
641#if HAVE_MESSAGES 714#if HAVE_MESSAGES
@@ -648,24 +721,31 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
648 left + 1, 721 left + 1,
649 header, "uri")) 722 header, "uri"))
650 { 723 {
651 free(uri); 724 free (uri);
652 return MHD_NO; 725 return MHD_NO;
653 } 726 }
654 727
655 /* 8 = 4 hexadecimal numbers for the timestamp */ 728 digest_calc_ha1("md5",
656 nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16); 729 username,
657 t = (uint32_t) MHD_monotonic_time(); 730 realm,
658 /* 731 password,
659 * First level vetting for the nonce validity: if the timestamp 732 nonce,
660 * attached to the nonce exceeds `nonce_timeout', then the nonce is 733 cnonce,
661 * invalid. 734 ha1);
662 */ 735 digest_calc_response (ha1,
663 if ( (t > nonce_time + nonce_timeout) || 736 nonce,
664 (nonce_time + nonce_timeout < nonce_time) ) 737 nc,
665 { 738 cnonce,
666 free(uri); 739 qop,
667 return MHD_INVALID_NONCE; 740 connection->method,
668 } 741 uri,
742 hentity,
743 respexp);
744
745 /* Need to unescape URI before comparing with connection->url */
746 connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
747 connection,
748 uri);
669 if (0 != strncmp (uri, 749 if (0 != strncmp (uri,
670 connection->url, 750 connection->url,
671 strlen (connection->url))) 751 strlen (connection->url)))
@@ -674,9 +754,10 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
674 MHD_DLOG (connection->daemon, 754 MHD_DLOG (connection->daemon,
675 "Authentication failed, URI does not match.\n"); 755 "Authentication failed, URI does not match.\n");
676#endif 756#endif
677 free(uri); 757 free (uri);
678 return MHD_NO; 758 return MHD_NO;
679 } 759 }
760
680 { 761 {
681 const char *args = strchr (uri, '?'); 762 const char *args = strchr (uri, '?');
682 763
@@ -692,89 +773,11 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
692 MHD_DLOG (connection->daemon, 773 MHD_DLOG (connection->daemon,
693 "Authentication failed, arguments do not match.\n"); 774 "Authentication failed, arguments do not match.\n");
694#endif 775#endif
695 free(uri); 776 free (uri);
696 return MHD_NO; 777 return MHD_NO;
697 } 778 }
698 } 779 }
699 calculate_nonce (nonce_time, 780 free (uri);
700 connection->method,
701 connection->daemon->digest_auth_random,
702 connection->daemon->digest_auth_rand_size,
703 connection->url,
704 realm,
705 noncehashexp);
706 /*
707 * Second level vetting for the nonce validity
708 * if the timestamp attached to the nonce is valid
709 * and possibly fabricated (in case of an attack)
710 * the attacker must also know the random seed to be
711 * able to generate a "sane" nonce, which if he does
712 * not, the nonce fabrication process going to be
713 * very hard to achieve.
714 */
715
716 if (0 != strcmp (nonce, noncehashexp))
717 {
718 free(uri);
719 return MHD_INVALID_NONCE;
720 }
721 if ( (0 == lookup_sub_value (cnonce,
722 sizeof (cnonce),
723 header, "cnonce")) ||
724 (0 == lookup_sub_value (qop, sizeof (qop), header, "qop")) ||
725 ( (0 != strcmp (qop, "auth")) &&
726 (0 != strcmp (qop, "")) ) ||
727 (0 == lookup_sub_value (nc, sizeof (nc), header, "nc")) ||
728 (0 == lookup_sub_value (response, sizeof (response), header, "response")) )
729 {
730#if HAVE_MESSAGES
731 MHD_DLOG (connection->daemon,
732 "Authentication failed, invalid format.\n");
733#endif
734 free(uri);
735 return MHD_NO;
736 }
737 nci = strtoul (nc, &end, 16);
738 if ( ('\0' != *end) ||
739 ( (LONG_MAX == nci) &&
740 (ERANGE == errno) ) )
741 {
742#if HAVE_MESSAGES
743 MHD_DLOG (connection->daemon,
744 "Authentication failed, invalid format.\n");
745#endif
746 free(uri);
747 return MHD_NO; /* invalid nonce format */
748 }
749 /*
750 * Checking if that combination of nonce and nc is sound
751 * and not a replay attack attempt. Also adds the nonce
752 * to the nonce-nc map if it does not exist there.
753 */
754
755 if (MHD_YES != check_nonce_nc (connection, nonce, nci))
756 {
757 free(uri);
758 return MHD_NO;
759 }
760
761 digest_calc_ha1("md5",
762 username,
763 realm,
764 password,
765 nonce,
766 cnonce,
767 ha1);
768 digest_calc_response (ha1,
769 nonce,
770 nc,
771 cnonce,
772 qop,
773 connection->method,
774 uri,
775 hentity,
776 respexp);
777 free(uri);
778 return (0 == strcmp(response, respexp)) 781 return (0 == strcmp(response, respexp))
779 ? MHD_YES 782 ? MHD_YES
780 : MHD_NO; 783 : MHD_NO;
@@ -835,7 +838,7 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection,
835 : ""); 838 : "");
836 { 839 {
837 char *header; 840 char *header;
838 841
839 header = malloc(hlen + 1); 842 header = malloc(hlen + 1);
840 if (NULL == header) 843 if (NULL == header)
841 { 844 {