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

📄 auth_client.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (!ca->ca_user || !ca->ca_pass || !ca->ca_credential_class)      return 0;    if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)      return 0;  }  return 1;}/**Authorize a request. * * The function auc_authorization() is used to add correct authentication * headers to a request. The authentication headers will contain the * credentials generated by the list of authenticators. * * @param[in,out] auc_list  list of authenticators  * @param[out] msg          message to be authenticated * @param[out] pub          headers of the message * @param[in] method        request method * @param[in] url           request URI * @param[in] body          message body (NULL if empty) *  * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */int auc_authorization(auth_client_t **auc_list, msg_t *msg, msg_pub_t *pub,		      char const *method, 		      url_t const *url, 		      msg_payload_t const *body){  auth_client_t *ca;  msg_mclass_t const *mc = msg_mclass(msg);  if (auc_list == NULL || msg == NULL)    return -1;  if (!auc_has_authorization(auc_list))    return 0;  if (pub == NULL)    pub = msg_object(msg);  /* Remove existing credentials */  for (ca = *auc_list; ca; ca = ca->ca_next) {    msg_header_t **hh = msg_hclass_offset(mc, pub, ca->ca_credential_class);    while (hh && *hh)      msg_header_remove(msg, pub, *hh);  }  /* Insert new credentials */  for (; *auc_list; auc_list = &(*auc_list)->ca_next) {    su_home_t *home = msg_home(msg);    msg_header_t *h = NULL;    ca = *auc_list;    if (!ca->ca_auc)      continue;    if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0)      return -1;    if (h == NULL)      continue;    if (msg_header_insert(msg, pub, h) < 0)      return -1;  }  return 1;}/**Generate headers authorizing a request. * * The function auc_authorization_headers() is used to generate * authentication headers for a request. The list of authentication headers * will contain the credentials generated by the list of authenticators. * * @param[in] auc_list      list of authenticators  * @param[in] home          memory home used to allocate headers * @param[in] method        request method * @param[in] url           request URI * @param[in] body          message body (NULL if empty) * @param[out] return_headers  authorization headers return value *  * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */int auc_authorization_headers(auth_client_t **auc_list, 			      su_home_t *home,			      char const *method, 			      url_t const *url, 			      msg_payload_t const *body,			      msg_header_t **return_headers){  auth_client_t *ca;  /* Make sure every challenge has credentials */  if (!auc_has_authorization(auc_list))    return 0;  /* Create new credential headers */  for (; *auc_list; auc_list = &(*auc_list)->ca_next) {    msg_header_t *h = NULL;    ca = *auc_list;    if (!ca->ca_auc)      continue;    if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0)      return -1;    *return_headers = h;    while (*return_headers)      return_headers = &(*return_headers)->sh_next;  }  return 1;}/* ---------------------------------------------------------------------- *//* Basic scheme */static int auc_basic_authorization(auth_client_t *ca,				   su_home_t *h,				   char const *method, 				   url_t const *url, 				   msg_payload_t const *body,				   msg_header_t **);static const auth_client_plugin_t ca_basic_plugin = {   /* auc_plugin_size: */ sizeof ca_basic_plugin,  /* auc_size: */        sizeof (auth_client_t),  /* auc_name: */       "Basic",  /* auc_challenge: */   NULL,  /* auc_authorize: */   auc_basic_authorization,  /* auc_info: */        NULL,  /* auc_clear: */       ca_clear_credentials};/**Create a basic authorization header. * * The function auc_basic_authorization() creates a basic authorization * header from username @a user and password @a pass. The authorization * header type is determined by @a hc - it can be sip_authorization_class, * sip_proxy_authorization_class, http_authorization_class, or * http_proxy_authorization_class, for instance. * * @param home memory home used to allocate memory for the new header * @param hc   header class for the header to be created * @param user user name * @param pass password *  * @return * The function auc_basic_authorization() returns a pointer to newly created  * authorization header, or NULL upon an error. */int auc_basic_authorization(auth_client_t *ca, 			    su_home_t *home,			    char const *method, 			    url_t const *url, 			    msg_payload_t const *body,			    msg_header_t **return_headers){  msg_hclass_t *hc = ca->ca_credential_class;  char const *user = ca->ca_user;  char const *pass = ca->ca_pass;  size_t ulen, plen, uplen, b64len, basiclen;  char *basic, *base64, *userpass;  char buffer[71];  if (user == NULL || pass == NULL)    return -1;  if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)    return 0;  ulen = strlen(user), plen = strlen(pass), uplen = ulen + 1 + plen;  b64len = BASE64_SIZE(uplen);  basiclen = strlen("Basic ") + b64len;  if (sizeof(buffer) > basiclen + 1)    basic = buffer;  else    basic = malloc(basiclen + 1);  if (basic == NULL)    return -1;  /*   * Basic authentication consists of username and password separated by   * colon and then base64 encoded.   */  strcpy(basic, "Basic ");  base64 = basic + strlen("Basic ");  userpass = base64 + b64len - uplen;  memcpy(userpass, user, ulen);  userpass[ulen] = ':';  memcpy(userpass + ulen + 1, pass, plen);  userpass[uplen] = '\0';    base64_e(base64, b64len + 1, userpass, uplen);  base64[b64len] = '\0';  *return_headers = msg_header_make(home, hc, basic);  if (buffer != basic)    free(basic);  return *return_headers ? 0 : -1;}/* ---------------------------------------------------------------------- *//* Digest scheme */typedef struct auth_digest_client_s{  auth_client_t cda_client;  int           cda_ncount;  char const   *cda_cnonce;  auth_challenge_t cda_ac[1];} auth_digest_client_t;static int auc_digest_challenge(auth_client_t *ca, 				msg_auth_t const *ch);static int auc_digest_authorization(auth_client_t *ca, 				    su_home_t *h,				    char const *method, 				    url_t const *url, 				    msg_payload_t const *body,				    msg_header_t **);static int auc_digest_info(auth_client_t *ca, 			   msg_auth_info_t const *info);static const auth_client_plugin_t ca_digest_plugin = {   /* auc_plugin_size: */ sizeof ca_digest_plugin,  /* auc_size: */        sizeof (auth_digest_client_t),  /* auc_name: */       "Digest",   /* auc_challenge: */   auc_digest_challenge,  /* auc_authorize: */   auc_digest_authorization,  /* auc_info: */        auc_digest_info,  /* auc_clear: */       ca_clear_credentials};/** Store a digest authorization challenge. * * @retval 2 if credentials need to be (re)sent * @retval 1 if challenge was updated * @retval -1 upon an error */static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch){  su_home_t *home = ca->ca_home;  auth_digest_client_t *cda = (auth_digest_client_t *)ca;  auth_challenge_t ac[1] = {{ sizeof ac }};  int stale;  if (auth_digest_challenge_get(home, ac, ch->au_params) < 0)    goto error;  /* Check that we can handle the challenge */  if (!ac->ac_md5 && !ac->ac_md5sess)    goto error;  if (ac->ac_qop && !ac->ac_auth && !ac->ac_auth_int)    goto error;  stale = ac->ac_stale || cda->cda_ac->ac_nonce == NULL;  if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale)) {    su_guid_t guid[1];    char *cnonce;    size_t b64len = BASE64_MINSIZE(sizeof(guid)) + 1;    if (cda->cda_cnonce != NULL)      /* Free the old one if we are updating after stale=true */      su_free(home, (void *)cda->cda_cnonce);    su_guid_generate(guid);    cda->cda_cnonce = cnonce = su_alloc(home, b64len);    base64_e(cnonce, b64len, guid, sizeof(guid));    cda->cda_ncount = 0;  }  auth_digest_challenge_free_params(home, cda->cda_ac);  *cda->cda_ac = *ac;  return stale ? 2 : 1; error:  auth_digest_challenge_free_params(home, ac);  return -1;}static int auc_digest_info(auth_client_t *ca,			   msg_auth_info_t const *info){  auth_digest_client_t *cda = (auth_digest_client_t *)ca;  su_home_t *home = ca->ca_home;  char const *nextnonce = NULL;  issize_t n;  n = auth_get_params(home, info->ai_params,		      "nextnonce=", &nextnonce,		      NULL);  if (n <= 0)    return n;  cda->cda_ac->ac_nonce = nextnonce;  return 1;}/**Create a digest authorization header. * * Creates a digest authorization header from username @a user and password * @a pass, client nonce @a cnonce, client nonce count @a nc, request method * @a method, request URI @a uri and message body @a data. The authorization * header type is determined by @a hc - it can be either * sip_authorization_class or sip_proxy_authorization_class, as well as * http_authorization_class or http_proxy_authorization_class. * * @retval 1 when authorization headers has been created   * @retval 0 when there is no credentials * @retval -1 upon an error */staticint auc_digest_authorization(auth_client_t *ca, 			     su_home_t *home,			     char const *method, 			     url_t const *url, 			     msg_payload_t const *body,			     msg_header_t **return_headers){  auth_digest_client_t *cda = (auth_digest_client_t *)ca;  msg_hclass_t *hc = ca->ca_credential_class;  char const *user = ca->ca_user;  char const *pass = ca->ca_pass;  auth_challenge_t const *ac = cda->cda_ac;  char const *cnonce = cda->cda_cnonce;  unsigned nc = ++cda->cda_ncount;  char *uri = url_as_string(home, url);  void const *data = body ? body->pl_data : "";  usize_t dlen = body ? body->pl_len : 0;  msg_header_t *h;  auth_hexmd5_t sessionkey, response;  auth_response_t ar[1] = {{ 0 }};  char ncount[17];  if (!user || !pass || (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear))    return 0;  ar->ar_size = sizeof(ar);  ar->ar_username = user;  ar->ar_realm = ac->ac_realm;  ar->ar_nonce = ac->ac_nonce;  ar->ar_algorithm = NULL;  ar->ar_md5 = ac->ac_md5;  ar->ar_md5sess = ac->ac_md5sess;  ar->ar_opaque = ac->ac_opaque;  ar->ar_qop = NULL;  ar->ar_auth = ac->ac_auth;  ar->ar_auth_int = ac->ac_auth_int;  ar->ar_uri = uri;  /* If there is no qop, we MUST NOT include cnonce or nc */  if (!ar->ar_auth && !ar->ar_auth_int)    cnonce = NULL;  if (cnonce) {    snprintf(ncount, sizeof(ncount), "%08x", nc);    ar->ar_cnonce = cnonce;    ar->ar_nc = ncount;  }  auth_digest_sessionkey(ar, sessionkey, pass);  auth_digest_response(ar, response, sessionkey, method, data, dlen);  h = msg_header_format(home, hc, 			"Digest "			"username=\"%s\", "			"realm=\"%s\", "			"nonce=\"%s"			"%s%s"			"%s%s"			"%s%s, "			"uri=\"%s\", "			"response=\"%s\""			"%s%s"			"%s%s",			ar->ar_username, 			ar->ar_realm,			ar->ar_nonce,			cnonce ? "\",  cnonce=\"" : "", 			cnonce ? cnonce : "",			ar->ar_opaque ? "\",  opaque=\"" : "", 			ar->ar_opaque ? ar->ar_opaque : "",			ar->ar_algorithm ? "\", algorithm=" : "",			ar->ar_algorithm ? ar->ar_algorithm : "",			ar->ar_uri,			response,			ar->ar_auth || ar->ar_auth_int ? ", qop=" : "", 			ar->ar_auth_int ? "auth-int" : 			(ar->ar_auth ? "auth" : ""),			cnonce ? ", nc=" : "", 			cnonce ? ncount : "");  su_free(home, uri);  if (!h)    return -1;  *return_headers = h;  return 0;}/* ---------------------------------------------------------------------- */#define MAX_AUC 20static auth_client_plugin_t const *ca_plugins[MAX_AUC] = {  &ca_digest_plugin, &ca_basic_plugin, NULL};/** Register an authentication client plugin */int auc_register_plugin(auth_client_plugin_t const *plugin){  int i;  if (plugin == NULL ||      plugin->auc_name == NULL ||      plugin->auc_authorize == NULL)    return errno = EFAULT, -1;  if (plugin->auc_size < (int) sizeof (auth_client_t))    return errno = EINVAL, -1;  for (i = 0; i < MAX_AUC; i++) {    if (ca_plugins[i] == NULL || 	strcmp(plugin->auc_name, ca_plugins[i]->auc_name) == 0) {      ca_plugins[i] = plugin;      return 0;    }  }  return errno = ENOMEM, -1;}/** Allocate an (possibly extended) auth_client_t structure. */staticauth_client_t *ca_create(su_home_t *home,			 char const *scheme,			 char const *realm){  auth_client_plugin_t const *auc = NULL;  auth_client_t *ca;  size_t aucsize = (sizeof *ca), realmlen, size;  char *s;  int i;  if (scheme == NULL || realm == NULL)    return (void)(errno = EFAULT), NULL;  realmlen = strlen(realm) + 1;  for (i = 0; i < MAX_AUC; i++) {    auc = ca_plugins[i];    if (!auc || strcasecmp(auc->auc_name, scheme) == 0)      break;  }  /* XXX - should report error if the auth scheme is not known? */  aucsize = auc ? (size_t)auc->auc_size : (sizeof *ca);  size = aucsize + realmlen;  if (!auc)    size += strlen(scheme) + 1;  ca = su_home_clone(home, (isize_t)size);  if (!ca)    return ca;  s = (char *)ca + aucsize;  ca->ca_auc = auc;  ca->ca_realm = strcpy(s, realm);  ca->ca_scheme = auc ? auc->auc_name : strcpy(s + realmlen, scheme);  return ca;}void ca_destroy(su_home_t *home, auth_client_t *ca){  su_free(home, ca);}#if HAVE_SOFIA_SIP#include <sofia-sip/sip.h>/**Authorize a SIP request. * * The function auc_authorize() is used to add correct authentication * headers to a SIP request. The authentication headers will contain the * credentials generated by the list of authenticators. * * @param[in,out] auc_list  list of authenticators  * @param[in,out] msg       message to be authenticated * @param[in,out] sip       sip headers of the message *  * @retval 1 when successful * @retval 0 when there is not enough credentials * @retval -1 upon an error */int auc_authorize(auth_client_t **auc_list, msg_t *msg, sip_t *sip){  sip_request_t *rq = sip ? sip->sip_request : NULL;  if (!rq)    return 0;  return auc_authorization(auc_list, msg, (msg_pub_t *)sip, 			   rq->rq_method_name, 			   /*			     RFC 3261 defines the protection domain based			     only on realm, so we do not bother get a			     correct URI to auth module.			   */			   rq->rq_url, 			   sip->sip_payload);}#endif

⌨️ 快捷键说明

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