⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth_module.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
		       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 < 0 || 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);}/** 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_MINSIZE(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);  }}/** Verify 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_response = NULL;      as->as_blacklist = am->am_blacklist;    }    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;  as->as_ident = apw->apw_ident;  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);  }}/* ====================================================================== *//* Password database */su_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 hash;  if (am == NULL || user == NULL)    return NULL;  hash = msg_hash_string(user);  for (slot = auth_htable_hash(am->am_users, hash);       (apw = *slot);       slot = auth_htable_next(am->am_users, slot)) {    if (hash != 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;    size_t size = sizeof *apw + ulen + rlen;    apw = su_alloc(am->am_home, size);    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 ssize_t 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)    /* Nothing has changed or passwd file is removed */    return 0;  return auth_readdb_internal(am, 0);}#if HAVE_FLOCK#include <sys/file.h>#endif/* This is just a magic value */#define auth_apw_local ((void *)(intptr_t)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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -