auth_module.c
来自「sip协议栈」· C语言 代码 · 共 1,882 行 · 第 1/4 页
C
1,882 行
auth_ntlm_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL; if (ar->ar_md5sess) auth_ntlm_a1sess(ar, a1buf, a1), a1 = a1buf;#else 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;#endif /* XXX - replace with auth_ntlm_response */ #if 0 auth_ntlm_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen);#else auth_digest_response(ar, response, a1, as->as_method, as->as_body, as->as_bodylen);#endif 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_ntlm(am, as, ach); as->as_blacklist = am->am_blacklist; } SU_DEBUG_5(("auth_method_ntlm: 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_ntlm(am, as, ach); if (am->am_challenge) auth_challenge_ntlm(am, as, ach); SU_DEBUG_7(("auth_method_ntlm: successful authentication\n")); as->as_status = 0; /* Successful authentication! */ as->as_phrase = "";}/** Construct a challenge header for @b Ntlm authentication scheme. */void auth_challenge_ntlm(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach){ char const *u, *d; char nonce[AUTH_NTLM_NONCE_LEN];#if 0 auth_generate_ntlm_nonce(am, nonce, sizeof nonce, 0, msg_now());#else auth_generate_digest_nonce(am, nonce, sizeof nonce, 0, msg_now());#endif u = as->as_uri; d = as->as_pdomain; as->as_response = msg_header_format(as->as_home, ach->ach_header, "Ntlm" " 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 Ntlm authentication scheme. */void auth_info_ntlm(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_NTLM_NONCE_LEN]; /* XXX - replace */#if 0 auth_generate_ntlm_nonce(am, nonce, sizeof nonce, 1, msg_now());#else auth_generate_digest_nonce(am, nonce, sizeof nonce, 1, msg_now());#endif as->as_info = msg_header_format(as->as_home, ach->ach_info, "nextnonce=\"%s\"", nonce); }}#endif /* HAVE_SOFIA_NTLM *//* ====================================================================== *//* Password database */static inline voidauth_htable_append_local(auth_htable_t *pr, auth_passwd_t *apw);/** Get an passwd entry for user. */auth_passwd_t *auth_mod_getpass(auth_mod_t *am, char const *user, char const *realm){ auth_passwd_t *apw, **slot; unsigned index; if (am == NULL || user == NULL) return NULL; index = msg_hash_string(user); for (slot = auth_htable_hash(am->am_users, index); (apw = *slot); slot = auth_htable_next(am->am_users, slot)) { if (index != apw->apw_index) continue; if (strcmp(user, apw->apw_user)) continue; if (realm && apw->apw_realm[0] && strcmp(realm, apw->apw_realm)) continue; break; /* Found it */ } return apw;}/** Add a password entry. */auth_passwd_t *auth_mod_addpass(auth_mod_t *am, char const *user, char const *realm){ auth_passwd_t *apw, **slot; unsigned index; if (am == NULL || user == NULL) return NULL; index = msg_hash_string(user); for (slot = auth_htable_hash(am->am_users, index); (apw = *slot); slot = auth_htable_next(am->am_users, slot)) { if (index != apw->apw_index) continue; if (strcmp(user, apw->apw_user)) continue; if (realm && strcmp(realm, apw->apw_realm)) continue; break; /* Found it */ } if (realm == NULL) realm = ""; if (!apw) { size_t ulen = strlen(user) + 1, rlen = strlen(realm) + 1; apw = su_alloc(am->am_home, sizeof *apw + ulen + rlen); if (apw) { memset(apw, 0, sizeof *apw); apw->apw_index = index; apw->apw_user = memcpy((char *)(apw + 1), user, ulen); apw->apw_realm = memcpy((char *)apw->apw_user + ulen, realm, rlen); if (!auth_htable_is_full(am->am_users)) { *slot = apw, am->am_users->aht_used++; } else { if (auth_htable_resize(am->am_home, am->am_users, 0) < 0) su_free(am->am_home, apw), apw = NULL; else auth_htable_append(am->am_users, apw); } } } return apw;}static int readfile(su_home_t *, FILE *, void **contents, int add_trailing_lf);static int auth_readdb_internal(auth_mod_t *am, int always);/** Read authentication database */int auth_readdb(auth_mod_t *am){ return auth_readdb_internal(am, 1);}/** Read authentication database only when needed */int auth_readdb_if_needed(auth_mod_t *am){ struct stat st[1]; if (!am->am_stat || !am->am_db) return 0; if (stat(am->am_db, st) != -1 && st->st_dev == am->am_stat->st_dev && st->st_ino == am->am_stat->st_ino && st->st_size == am->am_stat->st_size && memcmp(&st->st_mtime, &am->am_stat->st_mtime, (sizeof st->st_mtime)) == 0) return 0; /* Nothing has changed or passwd file is removed */ return auth_readdb_internal(am, 0);}#if HAVE_FLOCK#include <sys/file.h>#endif#define auth_apw_local auth_readdb_internal/** Read authentication database */staticint auth_readdb_internal(auth_mod_t *am, int always){ FILE *f; char *data, *s; size_t len, i, n, N; auth_passwd_t *apw; if (!am->am_stat) am->am_stat = su_zalloc(am->am_home, sizeof (*am->am_stat)); f = fopen(am->am_db, "rb"); if (f) { void *buffer = NULL; auth_passwd_t *fresh = NULL;#if HAVE_FLOCK int locked; /* Obtain shared lock on the database file */ if (flock(fileno(f), LOCK_SH | (always ? 0 : LOCK_NB)) == 0) { locked = 1; } else { locked = 0; if (errno == ENOLCK) { ; } else if (errno == EWOULDBLOCK) { SU_DEBUG_3(("auth(%s): user file \"%s\" is busy, trying again later\n", am->am_scheme->asch_method, am->am_db)); fclose(f); return always ? -1 : 0; } else { SU_DEBUG_3(("auth(%s): flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return always ? -1 : 0; } } #endif if (am->am_stat) stat(am->am_db, am->am_stat); /* too bad if this fails */ len = readfile(am->am_home, f, &buffer, 1);#if HAVE_FLOCK /* Release shared lock on the database file */ if (locked && flock(fileno(f), LOCK_UN) == -1) { SU_DEBUG_0(("auth(%s): un-flock(\"%s\"): %s (%u)\n", am->am_scheme->asch_method, am->am_db, strerror(errno), errno)); fclose(f); return -1; }#endif fclose(f); if (len < 0) return -1; /* Count number of entries in new buffer */ for (i = am->am_anonymous, s = data = buffer; s < data + len; s += n + strspn(s + n, "\r\n")) { n = strcspn(s, "\r\n"); if (*s != '#' && *s != '\n' && *s != '\r') i++; } N = i, i = 0; if (N > 0) { if (auth_htable_resize(am->am_home, am->am_users, N) < 0 || !(fresh = su_zalloc(am->am_home, sizeof(*fresh) * N))) { su_free(am->am_home, buffer); return -1; } } if (am->am_anonymous) { assert(i < N); apw = fresh + i++; apw->apw_index = msg_hash_string("anonymous"); apw->apw_user = "anonymous"; apw->apw_pass = ""; apw->apw_realm = ""; am->am_anon_user = apw; if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } for (data = buffer, s = data; s < data + len && i < N; s += n + strspn(s + n, "\r\n")) { char *user, *pass, *realm; n = strcspn(s, "\r\n"); if (*s == '#') continue; user = s; s[n++] = '\0'; if (!(pass = strchr(user, ':'))) continue; *pass++ = '\0'; if (!*user) continue; if (!(realm = strchr(pass, ':'))) realm = ""; else *realm++ = '\0'; if (!*pass) continue; apw = fresh + i++; apw->apw_index = msg_hash_string(user); apw->apw_user = user; /* Check for htdigest format */ if (span_hexdigit(realm) == 32 && realm[32] == '\0') { apw->apw_realm = pass; apw->apw_hash = realm; } else { apw->apw_pass = pass; apw->apw_realm = realm; } if (auth_htable_is_full(am->am_users)) auth_htable_resize(am->am_home, am->am_users, 0); auth_htable_append_local(am->am_users, apw); } assert(i <= N); N = i; /* Remove from hash those entries that were read from old passwd file */ for (i = 0; i < am->am_local_count; i++) { if (am->am_locals[i].apw_type == auth_apw_local) auth_htable_remove(am->am_users, &am->am_locals[i]); } if (am->am_locals) su_free(am->am_home, am->am_locals); /* Free old entries */ if (am->am_buffer) su_free(am->am_home, am->am_buffer); /* Free old passwd file contents */ SU_DEBUG_5(("auth(%s): read %u entries from \"%s\"\n", am->am_scheme->asch_method, (unsigned)N, am->am_db)); am->am_locals = fresh; am->am_local_count = N; am->am_buffer = buffer; return 0; } return -1;}/** Append to hash, remove existing user */static inline voidauth_htable_append_local(auth_htable_t *aht, auth_passwd_t *apw) { auth_passwd_t **slot; apw->apw_type = auth_apw_local; /* Append to hash */ for (slot = auth_htable_hash(aht, apw->apw_index); *slot; slot = auth_htable_next(aht, slot)) { if (strcmp((*slot)->apw_user, apw->apw_user) == 0) { if ((*slot)->apw_type == auth_apw_local) { (*slot)->apw_type = NULL; assert(aht->aht_used > 0); aht->aht_used--; apw->apw_extended = (*slot)->apw_extended; *slot = NULL; break; } else { /* We insert local before external entry */ auth_passwd_t *swap = apw; apw = *slot; *slot = swap; } } } aht->aht_used++; assert(aht->aht_used <= aht->aht_size); *slot = apw;}int readfile(su_home_t *home, FILE *f, void **contents, int add_trailing_lf){ /* Read in whole (binary!) file */ char *buffer = NULL; long size; int len = -1; /* Read whole file in */ if (fseek(f, 0, SEEK_END) < 0 || (size = ftell(f)) < 0 || fseek(f, 0, SEEK_SET) < 0 || (long)(len = size) != size) { SU_DEBUG_1(("%s: unable to determine file size (%s)\n", __func__, strerror(errno))); return -1; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?