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); } }
/** Create a new outbound object */ outbound_t * outbound_new(outbound_owner_t *owner, outbound_owner_vtable const *owner_methods, su_root_t *root, nta_agent_t *agent, char const *instance) { outbound_t *ob; if (!owner || !owner_methods || !root || !agent) return NULL; ob = su_home_clone((su_home_t *)owner, sizeof *ob); if (ob) { su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; su_guid_t guid[1]; ob->ob_owner = owner; ob->ob_oo = owner_methods; ob->ob_root = root; ob->ob_nta = agent; if (instance) ob->ob_instance = su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance); ob->ob_reg_id = 0; outbound_peer_info(ob, NULL); /* Generate a random cookie (used as Call-ID) for us */ su_md5_init(md5); su_guid_generate(guid); if (instance) su_md5_update(md5, (void *)instance, strlen(instance)); su_md5_update(md5, (void *)guid, sizeof guid); su_md5_digest(md5, digest); token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest); if (instance && !ob->ob_instance) su_home_unref(ob->ob_home), ob = NULL; } return ob; }
int test_md5(void) { BEGIN(); su_md5_t md5[1], md5i[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; char hexdigest[2 * SU_MD5_DIGEST_SIZE + 1]; struct { char *input; uint8_t digest[SU_MD5_DIGEST_SIZE]; } suite[] = { { (""), { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, { ("a"), { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, { ("abc"), { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, { ("message digest"), { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, { ("abcdefghijklmnopqrstuvwxyz"), { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, { "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }}; su_md5_init(md5); su_md5_update(md5, suite[0].input, 0); su_md5_digest(md5, digest); TEST_M(digest, suite[0].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_strupdate(md5, suite[1].input); su_md5_digest(md5, digest); TEST_M(digest, suite[1].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_iupdate(md5, suite[2].input, 3); su_md5_digest(md5, digest); TEST_M(digest, suite[2].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_striupdate(md5, suite[3].input); su_md5_digest(md5, digest); TEST_M(digest, suite[3].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_iupdate(md5, suite[4].input, 13); su_md5_striupdate(md5, suite[4].input + 13); su_md5_digest(md5, digest); TEST_M(digest, suite[4].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_update(md5, suite[5].input, 13); su_md5_strupdate(md5, suite[5].input + 13); su_md5_digest(md5, digest); TEST_M(digest, suite[5].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_update(md5, suite[6].input, 13); su_md5_strupdate(md5, suite[6].input + 13); su_md5_digest(md5, digest); TEST_M(digest, suite[6].digest, SU_MD5_DIGEST_SIZE); su_md5_deinit(md5); su_md5_init(md5); su_md5_str0update(md5, NULL); su_md5_hexdigest(md5, hexdigest); TEST_S(hexdigest, "93b885adfe0da089cdf634904fd59f71"); su_md5_deinit(md5); su_md5_init(md5); su_md5_stri0update(md5, NULL); su_md5_stri0update(md5, "ABBADABBADOO"); su_md5_hexdigest(md5, hexdigest); TEST_S(hexdigest, "101e6dd7cfabdb5c74f44b4c545c05cc"); su_md5_init(md5); su_md5_update(md5, "\0abbadabbadoo\0", 14); su_md5_hexdigest(md5, hexdigest); TEST_S(hexdigest, "101e6dd7cfabdb5c74f44b4c545c05cc"); su_md5_deinit(md5); /* Calculate md5 sum of 512 MB of zero */ if (getenv("EXPENSIVE_CHECKS")) { char zerokilo[1024] = { '\0' }; int i; su_md5_init(md5); su_md5_iupdate(md5, zerokilo, 19); for (i = 1; i < 512 * 1024; i++) su_md5_update(md5, zerokilo, 1024); *md5i = *md5; su_md5_update(md5, zerokilo, 1024 - 19); su_md5_hexdigest(md5, hexdigest); TEST_S(hexdigest, "aa559b4e3523a6c931f08f4df52d58f2"); su_md5_deinit(md5); su_md5_iupdate(md5i, zerokilo, 1024 - 19); su_md5_hexdigest(md5i, hexdigest); TEST_S(hexdigest, "aa559b4e3523a6c931f08f4df52d58f2"); } END(); }
/**Initialize an authentication module instance. * * The function auth_mod_init_default() initializes an authentication module * object used to authenticate the requests. * * @param am * @param base * @param root * @param tag,value,... tagged argument list * * @TAGS * AUTHTAG_REALM(), AUTHTAG_OPAQUE(), AUTHTAG_DB(), AUTHTAG_QOP(), * AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), AUTHTAG_NEXT_EXPIRES(), * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(), * AUTHTAG_FAKE(), AUTHTAG_ALLOW(), AUTHTAG_REMOTE(), and * AUTHTAG_MASTER_KEY(). * * @return 0 if successful * @return -1 upon an error */ int auth_init_default(auth_mod_t *am, auth_scheme_t *base, su_root_t *root, tag_type_t tag, tag_value_t value, ...) { int retval = 0; ta_list ta; char const *realm = NULL, *opaque = NULL, *db = NULL, *allows = NULL; char const *qop = NULL, *algorithm = NULL; unsigned expires = 60 * 60, next_expires = 5 * 60; unsigned max_ncount = 0; unsigned blacklist = 5; int forbidden = 0; int anonymous = 0; int fake = 0; url_string_t const *remote = NULL; char const *master_key = "fish"; char *s; ta_start(ta, tag, value); /* Authentication stuff */ tl_gets(ta_args(ta), AUTHTAG_REALM_REF(realm), AUTHTAG_OPAQUE_REF(opaque), AUTHTAG_DB_REF(db), AUTHTAG_QOP_REF(qop), AUTHTAG_ALGORITHM_REF(algorithm), AUTHTAG_EXPIRES_REF(expires), AUTHTAG_NEXT_EXPIRES_REF(next_expires), AUTHTAG_MAX_NCOUNT_REF(max_ncount), AUTHTAG_BLACKLIST_REF(blacklist), AUTHTAG_FORBIDDEN_REF(forbidden), AUTHTAG_ANONYMOUS_REF(anonymous), AUTHTAG_FAKE_REF(fake), AUTHTAG_ALLOW_REF(allows), AUTHTAG_REMOTE_REF(remote), AUTHTAG_MASTER_KEY_REF(master_key), TAG_NULL()); if (!realm) realm = "*"; if (!allows) allows = "ACK, BYE, CANCEL"; am->am_realm = su_strdup(am->am_home, realm); am->am_opaque = su_strdup(am->am_home, opaque); am->am_db = su_strdup(am->am_home, db); s = su_strdup(am->am_home, allows); if (s) msg_commalist_d(am->am_home, &s, &am->am_allow, NULL); am->am_expires = expires; am->am_next_exp = next_expires; am->am_max_ncount = max_ncount; am->am_blacklist = blacklist; am->am_forbidden = forbidden; am->am_anonymous = anonymous; am->am_fake = fake; am->am_remote = url_hdup(am->am_home, (url_t *)remote); am->am_algorithm = algorithm ? su_strdup(am->am_home, algorithm) : "MD5"; am->am_nextnonce = !algorithm || su_casematch(algorithm, "MD5"); if (next_expires == 0) am->am_nextnonce = 0; am->am_qop = su_strdup(am->am_home, qop); if (master_key) { su_md5_t md5[1]; su_md5_init(md5); su_md5_strupdate(md5, master_key); su_md5_strupdate(md5, "70P 53KR37"); su_md5_digest(md5, am->am_master_key); } auth_md5_hmac_key(am); /* Make sure that we have something that can be used to identify credentials */ if (am->am_opaque && strcmp(am->am_opaque, "*") == 0) { #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif char hostname[HOST_NAME_MAX + 1]; su_md5_t md5[1]; uint8_t hmac[6]; gethostname(hostname, sizeof hostname); auth_md5_hmac_init(am, md5); su_md5_strupdate(md5, hostname); su_md5_update(md5, ":", 1); if (am->am_remote) url_update(md5, am->am_remote); auth_md5_hmac_digest(am, md5, hmac, sizeof hmac); base64_e(hostname, sizeof hostname, hmac, sizeof hmac); am->am_opaque = su_strdup(am->am_home, hostname); if (!am->am_opaque) { retval = -1; SU_DEBUG_1(("%s: cannot create unique identifier\n", __func__)); } } if (retval < 0) ; else if (db) { retval = auth_readdb(am); if (retval == -1) { int err = errno; SU_DEBUG_1(("auth-module: %s: %s\n", am->am_db, strerror(err))); errno = err; } } else { retval = auth_htable_resize(am->am_home, am->am_users, 0); } ta_end(ta); return retval; }
static int nua_notify_client_init_etag(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { #if SU_HAVE_EXPERIMENTAL nua_handle_t *nh = cr->cr_owner; struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage); nua_server_request_t *sr; if (nu->nu_tag) su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL; nu->nu_no_body = 0; if (sip->sip_etag) { nu->nu_appl_etags = 1; nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string); } else if (!nu->nu_appl_etags && nu->nu_etags) { su_md5_t md5[1]; unsigned char digest[SU_MD5_DIGEST_SIZE]; sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() }; char token[2 * 16]; su_md5_init(md5); if (sip->sip_payload) *pl = *sip->sip_payload; if (pl->pl_len) su_md5_update(md5, pl->pl_data, pl->pl_len); su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len)); if (sip->sip_content_type) su_md5_striupdate(md5, sip->sip_content_type->c_type); su_md5_digest(md5, digest); token64_e(token, sizeof token, digest, sizeof digest); token[(sizeof token) - 1] = '\0'; nu->nu_tag = su_strdup(nh->nh_home, token); } if (!nu->nu_requested || !nu->nu_tag) return 0; /* Check if SUBSCRIBE had matching suppression */ for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe) break; if (sr) { sip_t const *sip = sr->sr_request.sip; sip_suppress_body_if_match_t *sbim; sip_suppress_notify_if_match_t *snim; if (cr->cr_usage->du_ready) { snim = sip_suppress_notify_if_match(sip); if (snim && su_casematch(snim->snim_tag, nu->nu_tag)) { if (nu->nu_requested > nu->nu_expires) nu->nu_expires = nu->nu_requested; nu->nu_requested = 0; return nua_client_return(cr, 202, "NOTIFY Suppressed", msg); } } sbim = sip_suppress_body_if_match(sip); if (sbim && su_casematch(sbim->sbim_tag, nu->nu_tag)) nu->nu_no_body = 1; } #endif return 0; }