auth_module.c
来自「sip协议栈」· C语言 代码 · 共 1,882 行 · 第 1/4 页
C
1,882 行
auth_init_default, /* asch_init */ auth_method_basic_x, /* asch_check */ auth_challenge_basic, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }};/**Authenticate a request with @b Basic authentication. * * This function reads user database before authentication, if needed. */staticvoid auth_method_basic_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach){ if (am) { auth_readdb_if_needed(am); auth_method_basic(am, as, au, ach); }}/** 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[80]; int n; char *pass; auth_passwd_t *apw; if (!as->as_realm) return; for (au = auth_mod_credentials(au, "Basic", NULL); au; au = auth_mod_credentials(au->au_next, "Basic", NULL)) { if (!au->au_params) continue; if ((n = base64_d(userpass, sizeof(userpass) - 1, au->au_params[0])) < 0) continue; 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_match = (msg_header_t *)au; as->as_status = 0; /* Successful authentication! */ return; } if (auth_allow_check(am, as)) auth_challenge_basic(am, as, ach);}/** Construct a challenge header for @b Basic authentication scheme. */void auth_challenge_basic(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach){ as->as_status = ach->ach_status; as->as_phrase = ach->ach_phrase; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Basic realm=\"%s\"", as->as_realm);}/* ====================================================================== *//* Digest authentication scheme */static void auth_method_digest_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach);auth_scheme_t auth_scheme_digest[1] = {{ "Digest", /* asch_method */ sizeof (auth_mod_t), /* asch_size */ auth_init_default, /* asch_init */ auth_method_digest_x, /* asch_check */ auth_challenge_digest, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }};struct nonce { msg_time_t issued; uint32_t count; uint16_t nextnonce; uint8_t digest[6];};#define AUTH_DIGEST_NONCE_LEN (BASE64_SIZE(sizeof (struct nonce)) + 1)/** Authenticate a request with @b Digest authentication scheme. * * This function reads user database before authentication, if needed. */staticvoid auth_method_digest_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach){ if (am) { auth_readdb_if_needed(am); auth_method_digest(am, as, au, ach); }}/** Authenticate a request with @b Digest authentication scheme. */void auth_method_digest(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach){ as->as_allow = as->as_allow || auth_allow_check(am, as) == 0; if (as->as_realm) au = auth_digest_credentials(au, as->as_realm, am->am_opaque); else au = NULL; if (as->as_allow) { SU_DEBUG_5(("%s: allow unauthenticated %s\n", __func__, as->as_method)); as->as_status = 0, as->as_phrase = NULL; as->as_match = (msg_header_t *)au; return; } if (au) { auth_response_t ar[1] = {{ sizeof(ar) }}; auth_digest_response_get(as->as_home, ar, au->au_params); as->as_match = (msg_header_t *)au; auth_check_digest(am, as, ar, ach); } else { /* There was no matching credentials, send challenge */ SU_DEBUG_5(("%s: no credentials matched\n", __func__)); auth_challenge_digest(am, as, ach); }}/** Check digest authentication */void auth_check_digest(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach){ char const *a1; auth_hexmd5_t a1buf, response; auth_passwd_t *apw; char const *phrase; msg_time_t now = msg_now(); if (am == NULL || as == NULL || ar == NULL || ach == NULL) { if (as) { as->as_status = 500, as->as_phrase = "Internal Server Error"; as->as_response = NULL; } return; } phrase = "Bad authorization";#define PA "Authorization missing " if ((!ar->ar_username && (phrase = PA "username")) || (!ar->ar_nonce && (phrase = PA "nonce")) || (!ar->ar_uri && (phrase = PA "URI")) || (!ar->ar_response && (phrase = PA "response")) || /* (!ar->ar_opaque && (phrase = PA "opaque")) || */ /* Check for qop */ (ar->ar_qop && ((ar->ar_auth && strcasecmp(ar->ar_qop, "auth") && strcasecmp(ar->ar_qop, "\"auth\"")) || (ar->ar_auth_int && strcasecmp(ar->ar_qop, "auth-int") && strcasecmp(ar->ar_qop, "\"auth-int\""))) && (phrase = PA "has invalid qop"))) { assert(phrase); SU_DEBUG_5(("auth_method_digest: 400 %s\n", phrase)); as->as_status = 400, as->as_phrase = phrase; as->as_response = NULL; return; } if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_digest_nonce(am, as, ar, now) < 0) { as->as_blacklist = am->am_blacklist; auth_challenge_digest(am, as, ach); return; } if (as->as_stale) { auth_challenge_digest(am, as, ach); return; } apw = auth_mod_getpass(am, ar->ar_username, ar->ar_realm); if (apw && apw->apw_hash) a1 = apw->apw_hash; else if (apw && apw->apw_pass) auth_digest_a1(ar, a1buf, apw->apw_pass), a1 = a1buf; else auth_digest_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL; if (ar->ar_md5sess) auth_digest_a1sess(ar, a1buf, a1), a1 = a1buf; auth_digest_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen); if (!apw || strcmp(response, ar->ar_response)) { if (am->am_forbidden) { as->as_status = 403, as->as_phrase = "Forbidden"; as->as_blacklist = am->am_blacklist; as->as_response = NULL; } else { auth_challenge_digest(am, as, ach); as->as_blacklist = am->am_blacklist; } SU_DEBUG_5(("auth_method_digest: response did not match\n")); return; } assert(apw); as->as_user = apw->apw_user; as->as_anonymous = apw == am->am_anon_user; if (am->am_nextnonce || am->am_mutual) auth_info_digest(am, as, ach); if (am->am_challenge) auth_challenge_digest(am, as, ach); SU_DEBUG_7(("auth_method_digest: successful authentication\n")); as->as_status = 0; /* Successful authentication! */ as->as_phrase = "";}/** Construct a challenge header for @b Digest authentication scheme. */void auth_challenge_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach){ char const *u, *d; char nonce[AUTH_DIGEST_NONCE_LEN]; auth_generate_digest_nonce(am, nonce, sizeof nonce, 0, msg_now()); u = as->as_uri; d = as->as_pdomain; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Digest" " realm=\"%s\"," "%s%s%s" "%s%s%s" " nonce=\"%s\"," "%s%s%s" "%s" /* stale */ " algorithm=%s" "%s%s%s", as->as_realm, u ? " uri=\"" : "", u ? u : "", u ? "\"," : "", d ? " domain=\"" : "", d ? d : "", d ? "\"," : "", nonce, am->am_opaque ? " opaque=\"" : "", am->am_opaque ? am->am_opaque : "", am->am_opaque ? "\"," : "", as->as_stale ? " stale=true," : "", am->am_algorithm, am->am_qop ? ", qop=\"" : "", am->am_qop ? am->am_qop : "", am->am_qop ? "\"" : ""); if (!as->as_response) as->as_status = 500, as->as_phrase = auth_internal_server_error; else as->as_status = ach->ach_status, as->as_phrase = ach->ach_phrase;}/** Construct a info header for @b Digest authentication scheme. */void auth_info_digest(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach){ if (!ach->ach_info) return; if (am->am_nextnonce) { char nonce[AUTH_DIGEST_NONCE_LEN]; auth_generate_digest_nonce(am, nonce, sizeof nonce, 1, msg_now()); as->as_info = msg_header_format(as->as_home, ach->ach_info, "nextnonce=\"%s\"", nonce); }}#if HAVE_SOFIA_NTLM/* ====================================================================== *//* NTLM authentication scheme */static void auth_method_ntlm_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach);auth_scheme_t auth_scheme_ntlm[1] = {{ "NTLM", /* asch_method */ sizeof (auth_mod_t), /* asch_size */ auth_init_default, /* asch_init */ auth_method_ntlm_x, /* asch_check */ auth_challenge_ntlm, /* asch_challenge */ auth_cancel_default, /* asch_cancel */ auth_destroy_default /* asch_destroy */ }};#define AUTH_NTLM_NONCE_LEN (BASE64_SIZE(sizeof (struct nonce)) + 1)/** Authenticate a request with @b Ntlm authentication scheme. * * This function reads user database before authentication, if needed. */staticvoid auth_method_ntlm_x(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach){ if (am) { auth_readdb_if_needed(am); auth_method_ntlm(am, as, au, ach); }}/** Authenticate a request with @b Ntlm authentication scheme. */void auth_method_ntlm(auth_mod_t *am, auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach){ as->as_allow = as->as_allow || auth_allow_check(am, as) == 0; if (as->as_realm) au = auth_ntlm_credentials(au, as->as_realm, am->am_opaque, am->am_gssapi_data, am->am_targetname); else au = NULL; if (as->as_allow) { SU_DEBUG_5(("%s: allow unauthenticated %s\n", __func__, as->as_method)); as->as_status = 0, as->as_phrase = NULL; as->as_match = (msg_header_t *)au; return; } if (au) { auth_response_t ar[1] = {{ sizeof(ar) }}; auth_ntlm_response_get(as->as_home, ar, au->au_params); as->as_match = (msg_header_t *)au; auth_check_ntlm(am, as, ar, ach); } else { /* There was no matching credentials, send challenge */ SU_DEBUG_5(("%s: no credentials matched\n", __func__)); auth_challenge_ntlm(am, as, ach); }}/** Check ntlm authentication */void auth_check_ntlm(auth_mod_t *am, auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach){ char const *a1; auth_hexmd5_t a1buf, response; auth_passwd_t *apw; char const *phrase; msg_time_t now = msg_now(); if (am == NULL || as == NULL || ar == NULL || ach == NULL) { if (as) { as->as_status = 500, as->as_phrase = "Internal Server Error"; as->as_response = NULL; } return; } phrase = "Bad authorization";#define PA "Authorization missing " if ((!ar->ar_username && (phrase = PA "username")) || (!ar->ar_nonce && (phrase = PA "nonce")) || (!ar->ar_uri && (phrase = PA "URI")) || (!ar->ar_response && (phrase = PA "response")) || /* (!ar->ar_opaque && (phrase = PA "opaque")) || */ /* Check for qop */ (ar->ar_qop && ((ar->ar_auth && strcasecmp(ar->ar_qop, "auth") && strcasecmp(ar->ar_qop, "\"auth\"")) || (ar->ar_auth_int && strcasecmp(ar->ar_qop, "auth-int") && strcasecmp(ar->ar_qop, "\"auth-int\""))) && (phrase = PA "has invalid qop"))) { assert(phrase); SU_DEBUG_5(("auth_method_ntlm: 400 %s\n", phrase)); as->as_status = 400, as->as_phrase = phrase; as->as_response = NULL; return; } /* XXX - replace */#if 0 if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_ntlm_nonce(am, as, ar, now) < 0) {#else if (as->as_nonce_issued == 0 /* Already validated nonce */ && auth_validate_digest_nonce(am, as, ar, now) < 0) {#endif as->as_blacklist = am->am_blacklist; auth_challenge_ntlm(am, as, ach); return; } if (as->as_stale) { auth_challenge_ntlm(am, as, ach); return; } apw = auth_mod_getpass(am, ar->ar_username, ar->ar_realm);#if 0 if (apw && apw->apw_hash) a1 = apw->apw_hash; else if (apw && apw->apw_pass) auth_ntlm_a1(ar, a1buf, apw->apw_pass), a1 = a1buf; else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?