auth_module.c

来自「sip协议栈」· C语言 代码 · 共 1,882 行 · 第 1/4 页

C
1,882
字号
  if (!(buffer = su_alloc(home, len + 2)) ||      fread(buffer, 1, len, f) != len) {    SU_DEBUG_1(("%s: unable to read file (%s)\n", __func__, strerror(errno)));    if (buffer)      su_free(home, buffer);    return -1;  }  if (add_trailing_lf) {    /* Make sure that the buffer has trailing newline */    if (len == 0 || buffer[len - 1] != '\n')      buffer[len++] = '\n';  }  buffer[len] = '\0';  *contents = buffer;  return len;}/* ====================================================================== *//* Helper functions *//** Check if request method is on always-allowed list. */int auth_allow_check(auth_mod_t *am, auth_status_t *as){  char const *method = as->as_method;  int i;  if (method && strcmp(method, "ACK") == 0) /* Hack */    return as->as_status = 0;  if (!method || !am->am_allow)    return 1;  for (i = 0; am->am_allow[i]; i++)    if (strcmp(am->am_allow[i], method) == 0)      return as->as_status = 0;  return 1;}/** Find a credential header with matching scheme and realm. */msg_auth_t *auth_mod_credentials(msg_auth_t *auth, 				 char const *scheme,				 char const *realm){  char const *arealm;  for (;auth; auth = auth->au_next) {    if (strcasecmp(auth->au_scheme, scheme))      continue;    if (!realm)      return auth;    arealm = msg_header_find_param(auth->au_common, "realm=");    if (!arealm)      continue;    if (arealm[0] == '"') {      /* Compare quoted arealm with unquoted realm */      int i, j;      for (i = 1, j = 0; arealm[i] != 0; i++, j++) {	if (arealm[i] == '"' && realm[j] == 0)	  return auth;	if (arealm[i] == '\\' && arealm[i + 1] != '\0')	  i++;	if (arealm[i] != realm[j])	  break;      }    } else {      if (strcmp(arealm, realm) == 0)	return auth;    }  }  return NULL;}/** Find a Digest credential header with matching realm and opaque. */msg_auth_t *auth_digest_credentials(msg_auth_t *auth, 				    char const *realm,				    char const *opaque){  char const *arealm, *aopaque;  for (;auth; auth = auth->au_next) {    if (strcasecmp(auth->au_scheme, "Digest"))      continue;    if (realm) {      int cmp = 1;      arealm = msg_header_find_param(auth->au_common, "realm=");      if (!arealm)	continue;      if (arealm[0] == '"') {	/* Compare quoted arealm with unquoted realm */	int i, j;	for (i = 1, j = 0, cmp = 1; arealm[i] != 0; i++, j++) {	  if (arealm[i] == '"' && realm[j] == 0) {	    cmp = 0;	    break;	  }	  if (arealm[i] == '\\' && arealm[i + 1] != '\0')	    i++;	  if (arealm[i] != realm[j])	    break;	}      }       else {	cmp = strcmp(arealm, realm);      }      if (cmp)	continue;    }    if (opaque) {      int cmp = 1;      aopaque = msg_header_find_param(auth->au_common, "opaque=");      if (!aopaque)	continue;      if (aopaque[0] == '"') {	/* Compare quoted aopaque with unquoted opaque */	int i, j;	for (i = 1, j = 0, cmp = 1; aopaque[i] != 0; i++, j++) {	  if (aopaque[i] == '"' && opaque[j] == 0) {	    cmp = 0;	    break;	  }	  if (aopaque[i] == '\\' && aopaque[i + 1] != '\0')	    i++;	  if (aopaque[i] != opaque[j])	    break;	}      } else {	cmp = strcmp(aopaque, opaque);      }      if (cmp)	continue;    }    return auth;  }  return NULL;}/** Generate nonce parameter. * * @param am pointer to authentication module object * @param buffer string buffer for nonce [OUT] * @param bsize size of buffer [IN] * @param nextnonce true if this is a "nextnonce" [IN] * @param now  current time [IN] */int auth_generate_digest_nonce(auth_mod_t *am, 			       char buffer[],			       size_t bsize,			       int nextnonce,			       msg_time_t now){  struct nonce nonce[1] = {{ 0 }};  su_md5_t md5[1];   am->am_count += 3730029547U;	/* 3730029547 is a prime */  nonce->issued = now;  nonce->count = am->am_count;  nonce->nextnonce = nextnonce != 0;    /* Calculate HMAC of nonce data */  auth_md5_hmac_init(am, md5);  su_md5_update(md5, nonce, offsetof(struct nonce, digest));  auth_md5_hmac_digest(am, md5, nonce->digest, sizeof nonce->digest);  return base64_e(buffer, bsize, nonce, sizeof(nonce));}/** Validate nonce parameter. * * @param am   pointer to authentication module object * @param as   authentication status structure [OUT] * @param ar   decoded authentication response from client [IN] * @param now  current time [IN] */int auth_validate_digest_nonce(auth_mod_t *am, 			       auth_status_t *as,			       auth_response_t *ar,			       msg_time_t now){  struct nonce nonce[1] = {{ 0 }};  su_md5_t md5[1];   uint8_t hmac[sizeof nonce->digest];  unsigned expires;  /* Check nonce */  if (!ar->ar_nonce) {    SU_DEBUG_5(("auth_method_digest: no nonce\n"));    return -1;  }  if (base64_d((void*)nonce, (sizeof nonce), ar->ar_nonce) != (sizeof nonce)) {    SU_DEBUG_5(("auth_method_digest: too short nonce\n"));    return -1;  }  /* Calculate HMAC over decoded nonce data */  auth_md5_hmac_init(am, md5);  su_md5_update(md5, nonce, offsetof(struct nonce, digest));  auth_md5_hmac_digest(am, md5, hmac, sizeof hmac);  if (memcmp(nonce->digest, hmac, sizeof nonce->digest)) {    SU_DEBUG_5(("auth_method_digest: bad nonce\n"));    return -1;  }  as->as_nonce_issued = nonce->issued;  as->as_nextnonce = nonce->nextnonce != 0;  expires = nonce->nextnonce ? am->am_next_exp : am->am_expires;  if (nonce->issued > now ||       (expires && nonce->issued + expires < now)) {    SU_DEBUG_5(("auth_method_digest: nonce expired %lu seconds ago "		"(lifetime %u)\n",		now - (nonce->issued + expires), expires));    as->as_stale = 1;  }  /* We should also check cnonce, nc... */  return 0;}#if HAVE_SOFIA_NTLM/** Find a NTLM credential header with matching realm and opaque. */msg_auth_t *auth_ntlm_credentials(msg_auth_t *auth, 				  char const *realm,				  char const *opaque,				  char const *gssapidata,				  char const *targetname){  char const *arealm, *aopaque, *agssapidata, *atargetname;  for (;auth; auth = auth->au_next) {    if (strcasecmp(auth->au_scheme, "NTLM"))      continue;    if (realm) {      int cmp = 1;      arealm = msg_header_find_param(auth->au_common, "realm=");      if (!arealm)	continue;      if (arealm[0] == '"') {	/* Compare quoted arealm with unquoted realm */	int i, j;	for (i = 1, j = 0, cmp = 1; arealm[i] != 0; i++, j++) {	  if (arealm[i] == '"' && realm[j] == 0) {	    cmp = 0;	    break;	  }	  if (arealm[i] == '\\' && arealm[i + 1] != '\0')	    i++;	  if (arealm[i] != realm[j])	    break;	}      }       else {	cmp = strcmp(arealm, realm);      }      if (cmp)	continue;    }    if (opaque) {      int cmp = 1;      aopaque = msg_header_find_param(auth->au_common, "opaque=");      if (!aopaque)	continue;      if (aopaque[0] == '"') {	/* Compare quoted aopaque with unquoted opaque */	int i, j;	for (i = 1, j = 0, cmp = 1; aopaque[i] != 0; i++, j++) {	  if (aopaque[i] == '"' && opaque[j] == 0) {	    cmp = 0;	    break;	  }	  if (aopaque[i] == '\\' && aopaque[i + 1] != '\0')	    i++;	  if (aopaque[i] != opaque[j])	    break;	}      } else {	cmp = strcmp(aopaque, opaque);      }      if (cmp)	continue;    }    if (gssapidata) {      int cmp = 1;      agssapidata = msg_header_find_param(auth->au_common, "gssapi-data=");      if (!agssapidata)	continue;      if (agssapidata[0] == '"') {	/* Compare quoted agssapi-data with unquoted gssapi-data */	int i, j;	for (i = 1, j = 0, cmp = 1; agssapidata[i] != 0; i++, j++) {	  if (agssapidata[i] == '"' && gssapidata[j] == 0) {	    cmp = 0;	    break;	  }	  if (agssapidata[i] == '\\' && agssapidata[i + 1] != '\0')	    i++;	  if (agssapidata[i] != gssapidata[j])	    break;	}      } else {	cmp = strcmp(agssapidata, gssapidata);      }      if (cmp)	continue;    }    if (targetname) {      int cmp = 1;      atargetname = msg_header_find_param(auth->au_common, "targetname=");      if (!atargetname)	continue;      if (atargetname[0] == '"') {	/* Compare quoted atargetname with unquoted targetname */	int i, j;	for (i = 1, j = 0, cmp = 1; atargetname[i] != 0; i++, j++) {	  if (atargetname[i] == '"' && targetname[j] == 0) {	    cmp = 0;	    break;	  }	  if (atargetname[i] == '\\' && atargetname[i + 1] != '\0')	    i++;	  if (atargetname[i] != targetname[j])	    break;	}      } else {	cmp = strcmp(atargetname, targetname);      }      if (cmp)	continue;    }    return auth;  }  return NULL;}#endif /* HAVE_SOFIA_NTLM *//* ====================================================================== *//* HMAC routines */staticvoid auth_md5_hmac_key(auth_mod_t *am){  int i;  uint8_t ipad[SU_MD5_DIGEST_SIZE];  uint8_t opad[SU_MD5_DIGEST_SIZE];  assert(SU_MD5_DIGEST_SIZE == sizeof am->am_master_key);  /* Derive HMAC ipad and opad from master key */  for (i = 0; i < sizeof am->am_master_key; i++) {    ipad[i] = am->am_master_key[i] ^ 0x36;    opad[i] = am->am_master_key[i] ^ 0x5C;  }  /* Pre-calculate sum of ipad */  su_md5_init(&am->am_hmac_ipad);  su_md5_update(&am->am_hmac_ipad, ipad, sizeof ipad);  /* Pre-calculate sum of opad */  su_md5_init(&am->am_hmac_opad);  su_md5_update(&am->am_hmac_opad, opad, sizeof opad);}void auth_md5_hmac_init(auth_mod_t *am, struct su_md5_t *imd5){  *imd5 = am->am_hmac_ipad;}void auth_md5_hmac_digest(auth_mod_t *am, struct su_md5_t *imd5, 			  void *hmac, size_t size){  uint8_t digest[SU_MD5_DIGEST_SIZE];  su_md5_t omd5[1];  /* inner sum */  su_md5_digest(imd5, digest);  *omd5 = am->am_hmac_opad;  su_md5_update(omd5, digest, sizeof *digest);  /* outer sum */  if (size == sizeof digest) {    su_md5_digest(omd5, hmac);	  }  else {    su_md5_digest(omd5, digest);    if (size > sizeof digest) {      memset((char *)hmac + (sizeof digest), 0, size - sizeof digest);      size = sizeof digest;    }    memcpy(hmac, digest, size);  }}/* ====================================================================== *//* Compatibility interface */void auth_mod_check_client(auth_mod_t *am,			   auth_status_t *as,			   msg_auth_t *credentials,			   auth_challenger_t const *ach){  auth_mod_method(am, as, credentials, ach);}void auth_mod_challenge_client(auth_mod_t *am,			       auth_status_t *as,			       auth_challenger_t const *ach){  auth_mod_challenge(am, as, ach);}

⌨️ 快捷键说明

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