| 1370 | } |
| 1371 | |
| 1372 | static int check_nc(const request_rec *r, const digest_header_rec *resp, |
| 1373 | const digest_config_rec *conf) |
| 1374 | { |
| 1375 | unsigned long nc; |
| 1376 | const char *snc = resp->nonce_count; |
| 1377 | char *endptr; |
| 1378 | |
| 1379 | if (conf->check_nc && !client_shm) { |
| 1380 | /* Shouldn't happen, but just in case... */ |
| 1381 | ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01771) |
| 1382 | "cannot check nonce count without shared memory"); |
| 1383 | return OK; |
| 1384 | } |
| 1385 | |
| 1386 | if (!conf->check_nc || !client_shm) { |
| 1387 | return OK; |
| 1388 | } |
| 1389 | |
| 1390 | if (!apr_is_empty_array(conf->qop_list) && |
| 1391 | !ap_cstr_casecmp(*(const char **)(conf->qop_list->elts), "none")) { |
| 1392 | /* qop is none, client must not send a nonce count */ |
| 1393 | if (snc != NULL) { |
| 1394 | ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01772) |
| 1395 | "invalid nc %s received - no nonce count allowed when qop=none", |
| 1396 | snc); |
| 1397 | return !OK; |
| 1398 | } |
| 1399 | /* qop is none, cannot check nonce count */ |
| 1400 | return OK; |
| 1401 | } |
| 1402 | |
| 1403 | nc = strtol(snc, &endptr, 16); |
| 1404 | if (endptr < (snc+strlen(snc)) && !apr_isspace(*endptr)) { |
| 1405 | ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01773) |
| 1406 | "invalid nc %s received - not a number", snc); |
| 1407 | return !OK; |
| 1408 | } |
| 1409 | |
| 1410 | if (!resp->client) { |
| 1411 | return !OK; |
| 1412 | } |
| 1413 | |
| 1414 | if (nc != resp->client->nonce_count) { |
| 1415 | ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01774) |
| 1416 | "Warning, possible replay attack: nonce-count " |
| 1417 | "check failed: %lu != %lu", nc, |
| 1418 | resp->client->nonce_count); |
| 1419 | return !OK; |
| 1420 | } |
| 1421 | |
| 1422 | return OK; |
| 1423 | } |
| 1424 | |
| 1425 | static int check_nonce(request_rec *r, digest_header_rec *resp, |
| 1426 | const digest_config_rec *conf) |
no test coverage detected