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.c206
1 files changed, 114 insertions, 92 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index c7d13866..26f972b8 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -1,6 +1,7 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 Copyright (C) 2010, 2011, 2012, 2015, 2018 Daniel Pittman and Christian Grothoff 3 Copyright (C) 2010, 2011, 2012, 2015, 2018 Daniel Pittman and Christian Grothoff
4 Copyright (C) 2014-2022 Evgeny Grin (Karlson2k)
4 5
5 This library is free software; you can redistribute it and/or 6 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 7 modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,7 @@
22 * @author Amr Ali 23 * @author Amr Ali
23 * @author Matthieu Speder 24 * @author Matthieu Speder
24 * @author Christian Grothoff (RFC 7616 support) 25 * @author Christian Grothoff (RFC 7616 support)
26 * @author Karlson2k (Evgeny Grin)
25 */ 27 */
26#include "platform.h" 28#include "platform.h"
27#include "mhd_limits.h" 29#include "mhd_limits.h"
@@ -153,63 +155,6 @@
153 */ 155 */
154#define _MHD_SESS_TOKEN "-sess" 156#define _MHD_SESS_TOKEN "-sess"
155 157
156
157/**
158 * The result of digest authentication of the client.
159 */
160enum MHD_DigestAuthResult
161{
162 /**
163 * Authentication OK
164 */
165 MHD_DAUTH_OK = 1,
166
167 /**
168 * General error, like "out of memory"
169 */
170 MHD_DAUTH_ERROR = 0,
171
172 /**
173 * No "Authorization" header or wrong format of the header.
174 */
175 MHD_DAUTH_WRONG_HEADER = -1,
176
177 /**
178 * Wrong 'username'.
179 */
180 MHD_DAUTH_WRONG_USERNAME = -2,
181
182 /**
183 * Wrong 'realm'.
184 */
185 MHD_DAUTH_WRONG_REALM = -3,
186
187 /**
188 * Wrong 'URI' (or URI parameters).
189 */
190 MHD_DAUTH_WRONG_URI = -4,
191
192 /* The different form of naming is intentionally used for the results below,
193 * as they are more important */
194
195 /**
196 * The 'nonce' is too old. Suggest the client to retry with the same
197 * username and password to get the fresh 'nonce'.
198 * The validity of the 'nonce' may not be checked.
199 */
200 MHD_DAUTH_NONCE_STALE = -16,
201
202 /**
203 * The 'nonce' is wrong. May indicate an attack attempt.
204 */
205 MHD_DAUTH_NONCE_WRONG = -32,
206
207 /**
208 * The 'response' is wrong. May indicate an attack attempt.
209 */
210 MHD_DAUTH_RESPONSE_WRONG = -33,
211};
212
213/** 158/**
214 * The result of nonce-nc map array check. 159 * The result of nonce-nc map array check.
215 */ 160 */
@@ -1586,7 +1531,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1586 * Authenticates the authorization header sent by the client. 1531 * Authenticates the authorization header sent by the client.
1587 * Uses #MHD_DIGEST_ALG_MD5 (for now, for backwards-compatibility). 1532 * Uses #MHD_DIGEST_ALG_MD5 (for now, for backwards-compatibility).
1588 * Note that this MAY change to #MHD_DIGEST_ALG_AUTO in the future. 1533 * Note that this MAY change to #MHD_DIGEST_ALG_AUTO in the future.
1589 * If you want to be sure you get MD5, use #MHD_digest_auth_check2 1534 * If you want to be sure you get MD5, use #MHD_digest_auth_check2()
1590 * and specify MD5 explicitly. 1535 * and specify MD5 explicitly.
1591 * 1536 *
1592 * @param connection The MHD connection structure 1537 * @param connection The MHD connection structure
@@ -1597,6 +1542,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1597 * invalid in seconds 1542 * invalid in seconds
1598 * @return #MHD_YES if authenticated, #MHD_NO if not, 1543 * @return #MHD_YES if authenticated, #MHD_NO if not,
1599 * #MHD_INVALID_NONCE if nonce is invalid or stale 1544 * #MHD_INVALID_NONCE if nonce is invalid or stale
1545 * @deprecated use MHD_digest_auth_check3()
1600 * @ingroup authentication 1546 * @ingroup authentication
1601 */ 1547 */
1602_MHD_EXTERN int 1548_MHD_EXTERN int
@@ -1667,6 +1613,86 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1667/** 1613/**
1668 * Authenticates the authorization header sent by the client. 1614 * Authenticates the authorization header sent by the client.
1669 * 1615 *
1616 * @param connection the MHD connection structure
1617 * @param realm the realm to be used for authorization of the client
1618 * @param username the username needs to be authenticated
1619 * @param password the password used in the authentication
1620 * @param nonce_timeout the nonce validity duration in seconds
1621 * @param algo the digest algorithms allowed for verification
1622 * @return #MHD_DAUTH_OK if authenticated,
1623 * the error code otherwise
1624 * @note Available since #MHD_VERSION 0x00097513
1625 * @ingroup authentication
1626 */
1627_MHD_EXTERN enum MHD_DigestAuthResult
1628MHD_digest_auth_check3 (struct MHD_Connection *connection,
1629 const char *realm,
1630 const char *username,
1631 const char *password,
1632 unsigned int nonce_timeout,
1633 enum MHD_DigestAuthAlgorithm algo)
1634{
1635 SETUP_DA (algo, da);
1636
1637 mhd_assert (NULL != password);
1638 if (0 == da.digest_size)
1639 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
1640
1641 return digest_auth_check_all (connection,
1642 &da,
1643 realm,
1644 username,
1645 password,
1646 NULL,
1647 nonce_timeout);
1648}
1649
1650
1651/**
1652 * Authenticates the authorization header sent by the client.
1653 *
1654 * @param connection the MHD connection structure
1655 * @param realm the realm to be used for authorization of the client
1656 * @param username the username needs to be authenticated
1657 * @param digest the pointer to the binary digest for the precalculated hash
1658 * value "username:realm:password" with specified @a algo
1659 * @param digest_size the number of bytes in @a digest (the size must match
1660 * @a algo!)
1661 * @param nonce_timeout the nonce validity duration in seconds
1662 * @param algo digest algorithms allowed for verification
1663 * @return #MHD_DAUTH_OK if authenticated,
1664 * the error code otherwise
1665 * @note Available since #MHD_VERSION 0x00097513
1666 * @ingroup authentication
1667 */
1668_MHD_EXTERN enum MHD_DigestAuthResult
1669MHD_digest_auth_check_digest3 (struct MHD_Connection *connection,
1670 const char *realm,
1671 const char *username,
1672 const uint8_t *digest,
1673 size_t digest_size,
1674 unsigned int nonce_timeout,
1675 enum MHD_DigestAuthAlgorithm algo)
1676{
1677 SETUP_DA (algo, da);
1678
1679 mhd_assert (NULL != digest);
1680 if ((da.digest_size != digest_size) || (0 == digest_size))
1681 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */
1682
1683 return digest_auth_check_all (connection,
1684 &da,
1685 realm,
1686 username,
1687 NULL,
1688 digest,
1689 nonce_timeout);
1690}
1691
1692
1693/**
1694 * Authenticates the authorization header sent by the client.
1695 *
1670 * @param connection The MHD connection structure 1696 * @param connection The MHD connection structure
1671 * @param realm The realm presented to the client 1697 * @param realm The realm presented to the client
1672 * @param username The username needs to be authenticated 1698 * @param username The username needs to be authenticated
@@ -1676,6 +1702,8 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1676 * @param algo digest algorithms allowed for verification 1702 * @param algo digest algorithms allowed for verification
1677 * @return #MHD_YES if authenticated, #MHD_NO if not, 1703 * @return #MHD_YES if authenticated, #MHD_NO if not,
1678 * #MHD_INVALID_NONCE if nonce is invalid or stale 1704 * #MHD_INVALID_NONCE if nonce is invalid or stale
1705 * @note Available since #MHD_VERSION 0x00096200
1706 * @deprecated use MHD_digest_auth_check3()
1679 * @ingroup authentication 1707 * @ingroup authentication
1680 */ 1708 */
1681_MHD_EXTERN int 1709_MHD_EXTERN int
@@ -1687,18 +1715,12 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
1687 enum MHD_DigestAuthAlgorithm algo) 1715 enum MHD_DigestAuthAlgorithm algo)
1688{ 1716{
1689 enum MHD_DigestAuthResult res; 1717 enum MHD_DigestAuthResult res;
1690 SETUP_DA (algo, da); 1718 res = MHD_digest_auth_check3 (connection,
1691 1719 realm,
1692 mhd_assert (NULL != password); 1720 username,
1693 if (0 == da.digest_size) 1721 password,
1694 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */ 1722 nonce_timeout,
1695 res = digest_auth_check_all (connection, 1723 algo);
1696 &da,
1697 realm,
1698 username,
1699 password,
1700 NULL,
1701 nonce_timeout);
1702 if (MHD_DAUTH_OK == res) 1724 if (MHD_DAUTH_OK == res)
1703 return MHD_YES; 1725 return MHD_YES;
1704 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res)) 1726 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
@@ -1716,13 +1738,15 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
1716 * @param username The username needs to be authenticated 1738 * @param username The username needs to be authenticated
1717 * @param digest An `unsigned char *' pointer to the binary MD5 sum 1739 * @param digest An `unsigned char *' pointer to the binary MD5 sum
1718 * for the precalculated hash value "username:realm:password" 1740 * for the precalculated hash value "username:realm:password"
1719 * of #MHD_MD5_DIGEST_SIZE bytes 1741 * of @a digest_size bytes
1720 * @param digest_size number of bytes in @a digest 1742 * @param digest_size number of bytes in @a digest (size must match @a algo!)
1721 * @param nonce_timeout The amount of time for a nonce to be 1743 * @param nonce_timeout The amount of time for a nonce to be
1722 * invalid in seconds 1744 * invalid in seconds
1723 * @param algo digest algorithms allowed for verification 1745 * @param algo digest algorithms allowed for verification
1724 * @return #MHD_YES if authenticated, #MHD_NO if not, 1746 * @return #MHD_YES if authenticated, #MHD_NO if not,
1725 * #MHD_INVALID_NONCE if nonce is invalid or stale 1747 * #MHD_INVALID_NONCE if nonce is invalid or stale
1748 * @note Available since #MHD_VERSION 0x00096200
1749 * @deprecated use MHD_digest_auth_check_digest3()
1726 * @ingroup authentication 1750 * @ingroup authentication
1727 */ 1751 */
1728_MHD_EXTERN int 1752_MHD_EXTERN int
@@ -1735,18 +1759,14 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1735 enum MHD_DigestAuthAlgorithm algo) 1759 enum MHD_DigestAuthAlgorithm algo)
1736{ 1760{
1737 enum MHD_DigestAuthResult res; 1761 enum MHD_DigestAuthResult res;
1738 SETUP_DA (algo, da);
1739 1762
1740 mhd_assert (NULL != digest); 1763 res = MHD_digest_auth_check_digest3 (connection,
1741 if ((da.digest_size != digest_size) || (0 == digest_size)) 1764 realm,
1742 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */ 1765 username,
1743 res = digest_auth_check_all (connection, 1766 digest,
1744 &da, 1767 digest_size,
1745 realm, 1768 nonce_timeout,
1746 username, 1769 algo);
1747 NULL,
1748 digest,
1749 nonce_timeout);
1750 if (MHD_DAUTH_OK == res) 1770 if (MHD_DAUTH_OK == res)
1751 return MHD_YES; 1771 return MHD_YES;
1752 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res)) 1772 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
@@ -1756,20 +1776,22 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1756 1776
1757 1777
1758/** 1778/**
1759 * Authenticates the authorization header sent by the client. 1779 * Authenticates the authorization header sent by the client
1760 * Uses #MHD_DIGEST_ALG_MD5 (required, as @a digest is of fixed 1780 * Uses #MHD_DIGEST_ALG_MD5 (required, as @a digest is of fixed
1761 * size). 1781 * size).
1762 * 1782 *
1763 * @param connection The MHD connection structure 1783 * @param connection The MHD connection structure
1764 * @param realm The realm presented to the client 1784 * @param realm The realm presented to the client
1765 * @param username The username needs to be authenticated 1785 * @param username The username needs to be authenticated
1766 * @param digest An `unsigned char *' pointer to the binary digest 1786 * @param digest An `unsigned char *' pointer to the binary hash
1767 * for the precalculated hash value "username:realm:password" 1787 * for the precalculated hash value "username:realm:password";
1768 * of @a digest_size bytes 1788 * length must be #MHD_MD5_DIGEST_SIZE bytes
1769 * @param nonce_timeout The amount of time for a nonce to be 1789 * @param nonce_timeout The amount of time for a nonce to be
1770 * invalid in seconds 1790 * invalid in seconds
1771 * @return #MHD_YES if authenticated, #MHD_NO if not, 1791 * @return #MHD_YES if authenticated, #MHD_NO if not,
1772 * #MHD_INVALID_NONCE if nonce is invalid or stale 1792 * #MHD_INVALID_NONCE if nonce is invalid or stale
1793 * @note Available since #MHD_VERSION 0x00096000
1794 * @deprecated use #MHD_digest_auth_check_digest3()
1773 * @ingroup authentication 1795 * @ingroup authentication
1774 */ 1796 */
1775_MHD_EXTERN int 1797_MHD_EXTERN int
@@ -1798,8 +1820,8 @@ MHD_digest_auth_check_digest (struct MHD_Connection *connection,
1798 * @param response reply to send; should contain the "access denied" 1820 * @param response reply to send; should contain the "access denied"
1799 * body; note that this function will set the "WWW Authenticate" 1821 * body; note that this function will set the "WWW Authenticate"
1800 * header and that the caller should not do this; the NULL is tolerated 1822 * header and that the caller should not do this; the NULL is tolerated
1801 * @param signal_stale #MHD_YES if the nonce is invalid to add 1823 * @param signal_stale #MHD_YES if the nonce is stale to add
1802 * 'stale=true' to the authentication header 1824 * 'stale=true' to the authentication header
1803 * @param algo digest algorithm to use 1825 * @param algo digest algorithm to use
1804 * @return #MHD_YES on success, #MHD_NO otherwise 1826 * @return #MHD_YES on success, #MHD_NO otherwise
1805 * @note Available since #MHD_VERSION 0x00096200 1827 * @note Available since #MHD_VERSION 0x00096200
@@ -1928,9 +1950,9 @@ MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
1928 * @param opaque string to user for opaque value 1950 * @param opaque string to user for opaque value
1929 * @param response reply to send; should contain the "access denied" 1951 * @param response reply to send; should contain the "access denied"
1930 * body; note that this function will set the "WWW Authenticate" 1952 * body; note that this function will set the "WWW Authenticate"
1931 * header and that the caller should not do this 1953 * header and that the caller should not do this; the NULL is tolerated
1932 * @param signal_stale #MHD_YES if the nonce is invalid to add 1954 * @param signal_stale #MHD_YES if the nonce is stale to add
1933 * 'stale=true' to the authentication header 1955 * 'stale=true' to the authentication header
1934 * @return #MHD_YES on success, #MHD_NO otherwise 1956 * @return #MHD_YES on success, #MHD_NO otherwise
1935 * @ingroup authentication 1957 * @ingroup authentication
1936 * @deprecated use MHD_queue_auth_fail_response2() 1958 * @deprecated use MHD_queue_auth_fail_response2()