/** Authenticate a request with @b Basic authentication scheme. * */ void auth_method_basic(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach) { char *userpass, buffer[128]; size_t n, upsize; char *pass; auth_passwd_t *apw; if (!as->as_realm) return; userpass = buffer, upsize = sizeof buffer; for (au = auth_mod_credentials(au, "Basic", NULL); au; au = auth_mod_credentials(au->au_next, "Basic", NULL)) { if (!au->au_params) continue; n = base64_d(userpass, upsize - 1, au->au_params[0]); if (n >= INT_MAX) continue; if (n >= upsize) { void *b = realloc(userpass == buffer ? NULL : userpass, upsize = n + 1); if (b == NULL) break; base64_d(userpass = b, upsize - 1, au->au_params[0]); } userpass[n] = 0; if (!(pass = strchr(userpass, ':'))) continue; *pass++ = '\0'; SU_DEBUG_5(("auth_method_basic: %s => %s:%s\n", au->au_params[0], userpass, pass)); if (!(apw = auth_mod_getpass(am, userpass, as->as_realm))) continue; if (strcmp(apw->apw_pass, pass)) continue; as->as_user = apw->apw_user; as->as_anonymous = apw == am->am_anon_user; as->as_ident = apw->apw_ident; as->as_match = (msg_header_t *)au; as->as_status = 0; /* Successful authentication! */ break; } if (userpass != buffer) free(userpass); if (au) return; if (auth_allow_check(am, as)) auth_challenge_basic(am, as, ach); }
/** Validate nonce parameter. * * @param am pointer to authentication module object * @param as authentication status structure [OUT] * @param ar decoded authentication response from client [IN] * @param now current time [IN] */ int auth_validate_digest_nonce(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, msg_time_t now) { struct nonce nonce[1] = {{ 0 }}; su_md5_t md5[1]; uint8_t hmac[sizeof nonce->digest]; unsigned expires; /* Check nonce */ if (!ar->ar_nonce) { SU_DEBUG_5(("auth_method_digest: no nonce\n")); return -1; } if (base64_d((void*)nonce, (sizeof nonce), ar->ar_nonce) != (sizeof nonce)) { SU_DEBUG_5(("auth_method_digest: too short nonce\n")); return -1; } /* Calculate HMAC over decoded nonce data */ auth_md5_hmac_init(am, md5); su_md5_update(md5, nonce, offsetof(struct nonce, digest)); auth_md5_hmac_digest(am, md5, hmac, sizeof hmac); if (memcmp(nonce->digest, hmac, sizeof nonce->digest)) { SU_DEBUG_5(("auth_method_digest: bad nonce\n")); return -1; } as->as_nonce_issued = nonce->issued; as->as_nextnonce = nonce->nextnonce != 0; expires = nonce->nextnonce ? am->am_next_exp : am->am_expires; if (nonce->issued > now || (expires && nonce->issued + expires < now)) { SU_DEBUG_5(("auth_method_digest: nonce expired %lu seconds ago " "(lifetime %u)\n", now - (nonce->issued + expires), expires)); as->as_stale = 1; } if (am->am_max_ncount && ar->ar_nc) { unsigned long nc = strtoul(ar->ar_nc, NULL, 10); if (nc == 0 || nc > am->am_max_ncount) { SU_DEBUG_5(("auth_method_digest: nonce used %s times, max %u\n", ar->ar_nc, am->am_max_ncount)); as->as_stale = 1; } } /* We should also check cnonce, nc... */ return 0; }