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 + -
显示快捷键?