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.c172
1 files changed, 124 insertions, 48 deletions
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index a92d99ed..d870902e 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -147,6 +147,63 @@
147 */ 147 */
148#define _MHD_SESS_TOKEN "-sess" 148#define _MHD_SESS_TOKEN "-sess"
149 149
150
151/**
152 * The result of digest authentication of the client.
153 */
154enum MHD_DigestAuthResult
155{
156 /**
157 * Authentication OK
158 */
159 MHD_DAUTH_OK = 1,
160
161 /**
162 * General error, like "out of memory"
163 */
164 MHD_DAUTH_ERROR = 0,
165
166 /**
167 * No "Authorization" header or wrong format of the header.
168 */
169 MHD_DAUTH_WRONG_HEADER = -1,
170
171 /**
172 * Wrong 'username'.
173 */
174 MHD_DAUTH_WRONG_USERNAME = -2,
175
176 /**
177 * Wrong 'realm'.
178 */
179 MHD_DAUTH_WRONG_REALM = -3,
180
181 /**
182 * Wrong 'URI' (or URI parameters).
183 */
184 MHD_DAUTH_WRONG_URI = -4,
185
186 /* The different form of naming is intentionally used for the results below,
187 * as they are more important */
188
189 /**
190 * The 'nonce' is too old. Suggest the client to retry with the same
191 * username and password to get the fresh 'nonce'.
192 * The validity of the 'nonce' may not be checked.
193 */
194 MHD_DAUTH_NONCE_STALE = -16,
195
196 /**
197 * The 'nonce' is wrong. May indicate an attack attempt.
198 */
199 MHD_DAUTH_NONCE_WRONG = -32,
200
201 /**
202 * The 'response' is wrong. May indicate an attack attempt.
203 */
204 MHD_DAUTH_RESPONSE_WRONG = -33,
205};
206
150/** 207/**
151 * Context passed to functions that need to calculate 208 * Context passed to functions that need to calculate
152 * a digest but are orthogonal to the specific 209 * a digest but are orthogonal to the specific
@@ -1129,11 +1186,11 @@ check_argument_match (struct MHD_Connection *connection,
1129 * (must contain "da->digest_size" bytes or be NULL) 1186 * (must contain "da->digest_size" bytes or be NULL)
1130 * @param nonce_timeout The amount of time for a nonce to be 1187 * @param nonce_timeout The amount of time for a nonce to be
1131 * invalid in seconds 1188 * invalid in seconds
1132 * @return #MHD_YES if authenticated, #MHD_NO if not, 1189 * @return #MHD_DAUTH_OK if authenticated,
1133 * #MHD_INVALID_NONCE if nonce is invalid 1190 * error code otherwise.
1134 * @ingroup authentication 1191 * @ingroup authentication
1135 */ 1192 */
1136static int 1193static enum MHD_DigestAuthResult
1137digest_auth_check_all (struct MHD_Connection *connection, 1194digest_auth_check_all (struct MHD_Connection *connection,
1138 struct DigestAlgorithm *da, 1195 struct DigestAlgorithm *da,
1139 const char *realm, 1196 const char *realm,
@@ -1169,14 +1226,15 @@ digest_auth_check_all (struct MHD_Connection *connection,
1169 MHD_HTTP_HEADER_AUTHORIZATION), 1226 MHD_HTTP_HEADER_AUTHORIZATION),
1170 &header, 1227 &header,
1171 NULL)) 1228 NULL))
1172 return MHD_NO; 1229 return MHD_DAUTH_WRONG_HEADER;
1173 if (0 != strncmp (header, 1230 if (0 != strncmp (header,
1174 _BASE, 1231 _BASE,
1175 MHD_STATICSTR_LEN_ (_BASE))) 1232 MHD_STATICSTR_LEN_ (_BASE)))
1176 return MHD_NO; 1233 return MHD_DAUTH_WRONG_HEADER;
1177 header += MHD_STATICSTR_LEN_ (_BASE); 1234 header += MHD_STATICSTR_LEN_ (_BASE);
1178 left = strlen (header); 1235 left = strlen (header);
1179 1236
1237 if (1)
1180 { 1238 {
1181 char un[MAX_USERNAME_LENGTH]; 1239 char un[MAX_USERNAME_LENGTH];
1182 1240
@@ -1184,13 +1242,15 @@ digest_auth_check_all (struct MHD_Connection *connection,
1184 sizeof (un), 1242 sizeof (un),
1185 header, 1243 header,
1186 "username"); 1244 "username");
1187 if ( (0 == len) || 1245 if (0 == len)
1188 (0 != strcmp (username, 1246 return MHD_DAUTH_WRONG_HEADER;
1189 un)) ) 1247 if (0 != strcmp (username,
1190 return MHD_NO; 1248 un))
1249 return MHD_DAUTH_WRONG_USERNAME;
1191 left -= strlen ("username") + len; 1250 left -= strlen ("username") + len;
1192 } 1251 }
1193 1252
1253 if (1)
1194 { 1254 {
1195 char r[MAX_REALM_LENGTH]; 1255 char r[MAX_REALM_LENGTH];
1196 1256
@@ -1198,10 +1258,11 @@ digest_auth_check_all (struct MHD_Connection *connection,
1198 sizeof (r), 1258 sizeof (r),
1199 header, 1259 header,
1200 "realm"); 1260 "realm");
1201 if ( (0 == len) || 1261 if (0 == len)
1202 (0 != strcmp (realm, 1262 return MHD_DAUTH_WRONG_HEADER;
1203 r)) ) 1263 if (0 != strcmp (realm,
1204 return MHD_NO; 1264 r))
1265 return MHD_DAUTH_WRONG_REALM;
1205 left -= strlen ("realm") + len; 1266 left -= strlen ("realm") + len;
1206 } 1267 }
1207 1268
@@ -1209,7 +1270,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1209 sizeof (nonce), 1270 sizeof (nonce),
1210 header, 1271 header,
1211 "nonce"))) 1272 "nonce")))
1212 return MHD_NO; 1273 return MHD_DAUTH_WRONG_HEADER;
1213 nonce_len = len; 1274 nonce_len = len;
1214 left -= strlen ("nonce") + len; 1275 left -= strlen ("nonce") + len;
1215 if (left > 32 * 1024) 1276 if (left > 32 * 1024)
@@ -1221,7 +1282,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1221 #MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large 1282 #MHD_OPTION_CONNECTION_MEMORY_LIMIT might be very large
1222 and would thus permit sending a >32k authorization 1283 and would thus permit sending a >32k authorization
1223 header value. */ 1284 header value. */
1224 return MHD_NO; 1285 return MHD_DAUTH_WRONG_HEADER;
1225 } 1286 }
1226 if (! get_nonce_timestamp (nonce, nonce_len, &nonce_time)) 1287 if (! get_nonce_timestamp (nonce, nonce_len, &nonce_time))
1227 { 1288 {
@@ -1229,7 +1290,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1229 MHD_DLOG (daemon, 1290 MHD_DLOG (daemon,
1230 _ ("Authentication failed, invalid timestamp format.\n")); 1291 _ ("Authentication failed, invalid timestamp format.\n"));
1231#endif 1292#endif
1232 return MHD_NO; 1293 return MHD_DAUTH_WRONG_HEADER;
1233 } 1294 }
1234 1295
1235 t = MHD_monotonic_msec_counter (); 1296 t = MHD_monotonic_msec_counter ();
@@ -1241,7 +1302,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1241 if (TRIM_TO_TIMESTAMP (t - nonce_time) > (nonce_timeout * 1000)) 1302 if (TRIM_TO_TIMESTAMP (t - nonce_time) > (nonce_timeout * 1000))
1242 { 1303 {
1243 /* too old */ 1304 /* too old */
1244 return MHD_INVALID_NONCE; 1305 return MHD_DAUTH_NONCE_STALE;
1245 } 1306 }
1246 1307
1247 calculate_nonce (nonce_time, 1308 calculate_nonce (nonce_time,
@@ -1264,7 +1325,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1264 if (0 != strcmp (nonce, 1325 if (0 != strcmp (nonce,
1265 noncehashexp)) 1326 noncehashexp))
1266 { 1327 {
1267 return MHD_INVALID_NONCE; 1328 return MHD_DAUTH_NONCE_WRONG;
1268 } 1329 }
1269 if ( (0 == lookup_sub_value (cnonce, 1330 if ( (0 == lookup_sub_value (cnonce,
1270 sizeof (cnonce), 1331 sizeof (cnonce),
@@ -1291,7 +1352,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1291 MHD_DLOG (daemon, 1352 MHD_DLOG (daemon,
1292 _ ("Authentication failed, invalid format.\n")); 1353 _ ("Authentication failed, invalid format.\n"));
1293#endif 1354#endif
1294 return MHD_NO; 1355 return MHD_DAUTH_WRONG_HEADER;
1295 } 1356 }
1296 if (len != MHD_strx_to_uint64_n_ (nc, 1357 if (len != MHD_strx_to_uint64_n_ (nc,
1297 len, 1358 len,
@@ -1301,7 +1362,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1301 MHD_DLOG (daemon, 1362 MHD_DLOG (daemon,
1302 _ ("Authentication failed, invalid nc format.\n")); 1363 _ ("Authentication failed, invalid nc format.\n"));
1303#endif 1364#endif
1304 return MHD_NO; /* invalid nonce format */ 1365 return MHD_DAUTH_WRONG_HEADER; /* invalid nonce format */
1305 } 1366 }
1306 if (0 == nci) 1367 if (0 == nci)
1307 { 1368 {
@@ -1309,7 +1370,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1309 MHD_DLOG (daemon, 1370 MHD_DLOG (daemon,
1310 _ ("Authentication failed, invalid 'nc' value.\n")); 1371 _ ("Authentication failed, invalid 'nc' value.\n"));
1311#endif 1372#endif
1312 return MHD_NO; /* invalid nc value */ 1373 return MHD_DAUTH_WRONG_HEADER; /* invalid nc value */
1313 } 1374 }
1314 1375
1315 /* 1376 /*
@@ -1322,9 +1383,10 @@ digest_auth_check_all (struct MHD_Connection *connection,
1322 nonce_len, 1383 nonce_len,
1323 nci)) 1384 nci))
1324 { 1385 {
1325 return MHD_NO; 1386 return MHD_DAUTH_NONCE_STALE;
1326 } 1387 }
1327 1388
1389 if (1)
1328 { 1390 {
1329 char *uri; 1391 char *uri;
1330 1392
@@ -1335,7 +1397,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1335 MHD_DLOG (daemon, 1397 MHD_DLOG (daemon,
1336 _ ("Failed to allocate memory for auth header processing.\n")); 1398 _ ("Failed to allocate memory for auth header processing.\n"));
1337#endif /* HAVE_MESSAGES */ 1399#endif /* HAVE_MESSAGES */
1338 return MHD_NO; 1400 return MHD_DAUTH_ERROR;
1339 } 1401 }
1340 if (0 == lookup_sub_value (uri, 1402 if (0 == lookup_sub_value (uri,
1341 left + 1, 1403 left + 1,
@@ -1343,7 +1405,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1343 "uri")) 1405 "uri"))
1344 { 1406 {
1345 free (uri); 1407 free (uri);
1346 return MHD_NO; 1408 return MHD_DAUTH_WRONG_HEADER;
1347 } 1409 }
1348 if (NULL != digest) 1410 if (NULL != digest)
1349 { 1411 {
@@ -1396,9 +1458,10 @@ digest_auth_check_all (struct MHD_Connection *connection,
1396 _ ("Authentication failed, URI does not match.\n")); 1458 _ ("Authentication failed, URI does not match.\n"));
1397#endif 1459#endif
1398 free (uri); 1460 free (uri);
1399 return MHD_NO; 1461 return MHD_DAUTH_WRONG_URI;
1400 } 1462 }
1401 1463
1464 if (1)
1402 { 1465 {
1403 const char *args = qmark; 1466 const char *args = qmark;
1404 1467
@@ -1415,15 +1478,15 @@ digest_auth_check_all (struct MHD_Connection *connection,
1415 _ ("Authentication failed, arguments do not match.\n")); 1478 _ ("Authentication failed, arguments do not match.\n"));
1416#endif 1479#endif
1417 free (uri); 1480 free (uri);
1418 return MHD_NO; 1481 return MHD_DAUTH_WRONG_URI;
1419 } 1482 }
1420 } 1483 }
1421 free (uri); 1484 free (uri);
1422 return (0 == strcmp (response,
1423 da->sessionkey))
1424 ? MHD_YES
1425 : MHD_NO;
1426 } 1485 }
1486 return (0 == strcmp (response,
1487 da->sessionkey))
1488 ? MHD_DAUTH_OK
1489 : MHD_DAUTH_RESPONSE_WRONG;
1427} 1490}
1428 1491
1429 1492
@@ -1441,7 +1504,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
1441 * @param nonce_timeout The amount of time for a nonce to be 1504 * @param nonce_timeout The amount of time for a nonce to be
1442 * invalid in seconds 1505 * invalid in seconds
1443 * @return #MHD_YES if authenticated, #MHD_NO if not, 1506 * @return #MHD_YES if authenticated, #MHD_NO if not,
1444 * #MHD_INVALID_NONCE if nonce is invalid 1507 * #MHD_INVALID_NONCE if nonce is invalid or stale
1445 * @ingroup authentication 1508 * @ingroup authentication
1446 */ 1509 */
1447_MHD_EXTERN int 1510_MHD_EXTERN int
@@ -1520,7 +1583,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
1520 * invalid in seconds 1583 * invalid in seconds
1521 * @param algo digest algorithms allowed for verification 1584 * @param algo digest algorithms allowed for verification
1522 * @return #MHD_YES if authenticated, #MHD_NO if not, 1585 * @return #MHD_YES if authenticated, #MHD_NO if not,
1523 * #MHD_INVALID_NONCE if nonce is invalid 1586 * #MHD_INVALID_NONCE if nonce is invalid or stale
1524 * @ingroup authentication 1587 * @ingroup authentication
1525 */ 1588 */
1526_MHD_EXTERN int 1589_MHD_EXTERN int
@@ -1531,18 +1594,25 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
1531 unsigned int nonce_timeout, 1594 unsigned int nonce_timeout,
1532 enum MHD_DigestAuthAlgorithm algo) 1595 enum MHD_DigestAuthAlgorithm algo)
1533{ 1596{
1597 enum MHD_DigestAuthResult res;
1534 SETUP_DA (algo, da); 1598 SETUP_DA (algo, da);
1535 1599
1536 mhd_assert (NULL != password); 1600 mhd_assert (NULL != password);
1537 if (0 == da.digest_size) 1601 if (0 == da.digest_size)
1538 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */ 1602 MHD_PANIC (_ ("Wrong algo value.\n")); /* API violation! */
1539 return digest_auth_check_all (connection, 1603 res = digest_auth_check_all (connection,
1540 &da, 1604 &da,
1541 realm, 1605 realm,
1542 username, 1606 username,
1543 password, 1607 password,
1544 NULL, 1608 NULL,
1545 nonce_timeout); 1609 nonce_timeout);
1610 if (MHD_DAUTH_OK == res)
1611 return MHD_YES;
1612 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
1613 return MHD_INVALID_NONCE;
1614 return MHD_NO;
1615
1546} 1616}
1547 1617
1548 1618
@@ -1560,7 +1630,7 @@ MHD_digest_auth_check2 (struct MHD_Connection *connection,
1560 * invalid in seconds 1630 * invalid in seconds
1561 * @param algo digest algorithms allowed for verification 1631 * @param algo digest algorithms allowed for verification
1562 * @return #MHD_YES if authenticated, #MHD_NO if not, 1632 * @return #MHD_YES if authenticated, #MHD_NO if not,
1563 * #MHD_INVALID_NONCE if nonce is invalid 1633 * #MHD_INVALID_NONCE if nonce is invalid or stale
1564 * @ingroup authentication 1634 * @ingroup authentication
1565 */ 1635 */
1566_MHD_EXTERN int 1636_MHD_EXTERN int
@@ -1572,18 +1642,24 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1572 unsigned int nonce_timeout, 1642 unsigned int nonce_timeout,
1573 enum MHD_DigestAuthAlgorithm algo) 1643 enum MHD_DigestAuthAlgorithm algo)
1574{ 1644{
1645 enum MHD_DigestAuthResult res;
1575 SETUP_DA (algo, da); 1646 SETUP_DA (algo, da);
1576 1647
1577 mhd_assert (NULL != digest); 1648 mhd_assert (NULL != digest);
1578 if ((da.digest_size != digest_size) || (0 == digest_size)) 1649 if ((da.digest_size != digest_size) || (0 == digest_size))
1579 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */ 1650 MHD_PANIC (_ ("Digest size mismatch.\n")); /* API violation! */
1580 return digest_auth_check_all (connection, 1651 res = digest_auth_check_all (connection,
1581 &da, 1652 &da,
1582 realm, 1653 realm,
1583 username, 1654 username,
1584 NULL, 1655 NULL,
1585 digest, 1656 digest,
1586 nonce_timeout); 1657 nonce_timeout);
1658 if (MHD_DAUTH_OK == res)
1659 return MHD_YES;
1660 else if ((MHD_DAUTH_NONCE_STALE == res) || (MHD_DAUTH_NONCE_WRONG == res))
1661 return MHD_INVALID_NONCE;
1662 return MHD_NO;
1587} 1663}
1588 1664
1589 1665
@@ -1601,7 +1677,7 @@ MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
1601 * @param nonce_timeout The amount of time for a nonce to be 1677 * @param nonce_timeout The amount of time for a nonce to be
1602 * invalid in seconds 1678 * invalid in seconds
1603 * @return #MHD_YES if authenticated, #MHD_NO if not, 1679 * @return #MHD_YES if authenticated, #MHD_NO if not,
1604 * #MHD_INVALID_NONCE if nonce is invalid 1680 * #MHD_INVALID_NONCE if nonce is invalid or stale
1605 * @ingroup authentication 1681 * @ingroup authentication
1606 */ 1682 */
1607_MHD_EXTERN int 1683_MHD_EXTERN int