[svn-commits] mmichelson: branch mmichelson/authenticate r381053 - /team/mmichelson/authent...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 7 13:15:47 CST 2013


Author: mmichelson
Date: Thu Feb  7 13:15:44 2013
New Revision: 381053

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381053
Log:
Fix problem where the same challenge would be found during verification every time.

Keying a challenge solely on the nonce is bad. I need to key on both the nonce and
realm. This way, when a request comes in, I can look at the authentication headers
and find a challenge that has the nonce indicated as well as has the same realm as
the ast_sip_auth I'm currently interested in using for verification.

I changed the challenge to simply be a pair of realm and nonce. I don't store a
pool or auth_srv any more. I can simply create an auth_srv on the fly when I need
one. As long as I'm doing nonce verification, there's no need to store the
auth_srv, as far as I can tell. It wouldn't be terribly difficult to switch
back to storing it if I have to though.


Modified:
    team/mmichelson/authenticate/res/res_sip_authenticator_digest.c

Modified: team/mmichelson/authenticate/res/res_sip_authenticator_digest.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/authenticate/res/res_sip_authenticator_digest.c?view=diff&rev=381053&r1=381052&r2=381053
==============================================================================
--- team/mmichelson/authenticate/res/res_sip_authenticator_digest.c (original)
+++ team/mmichelson/authenticate/res/res_sip_authenticator_digest.c Thu Feb  7 13:15:44 2013
@@ -38,74 +38,55 @@
 struct ao2_container *challenges;
 
 struct challenge {
-	pj_pool_t *pool;
-	pjsip_auth_srv *auth_server;
-	struct ast_uuid *nonce;
+	char nonce[AST_UUID_STR_LEN];
+	const char *realm;
 };
 
 static int challenge_hash(const void *obj, int flags)
 {
 	const struct challenge *chall = obj;
-	const struct ast_uuid *nonce = flags & OBJ_KEY ? obj : chall->nonce;
-	char nonce_str[AST_UUID_STR_LEN];
-	ast_uuid_to_str(nonce, nonce_str, sizeof(nonce_str));
-
-	return ast_str_hash(nonce_str);
+	int hash = ast_str_hash(chall->nonce);
+	hash = ast_str_hash_add(chall->realm, hash);
+	return hash;
 }
 
 static int challenge_cmp(void *obj, void *arg, int flags)
 {
 	struct challenge *chall1 = obj;
 	struct challenge *chall2 = arg;
-	struct ast_uuid *nonce2 = flags & OBJ_KEY ? arg : chall2->nonce;
-
-	return ast_uuid_compare(chall1->nonce, nonce2);
+
+	return (!strcmp(chall1->nonce, chall2->nonce) && !strcmp(chall1->realm, chall2->realm)) ? CMP_MATCH : 0;
 }
 
 static void challenge_destructor(void *obj)
 {
 	struct challenge *chall = obj;
 
-	if (chall->pool) {
-		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), chall->pool);
-	}
-	ast_free(chall->auth_server);
-	ast_free(chall->nonce);
+	ast_free((char *) chall->realm);
 }
 
 static struct challenge *create_challenge(struct ast_sip_auth *auth)
 {
 	struct challenge *chall = ao2_alloc(sizeof(*chall), challenge_destructor);
-	pj_str_t realm;
+	struct ast_uuid *uuid;
 
 	if (!chall) {
 		return NULL;
 	}
 
-	chall->pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "auth", 128, 128);
-	if (!chall->pool) {
+	uuid = ast_uuid_generate();
+	if (!uuid) {
 		ao2_cleanup(chall);
 		return NULL;
 	}
-
-	chall->nonce = ast_uuid_generate();
-	if (!chall->nonce) {
+	ast_uuid_to_str(uuid, chall->nonce, sizeof(chall->nonce));
+
+	chall->realm = ast_strdup(auth->realm);
+	if (!chall->realm) {
 		ao2_cleanup(chall);
 		return NULL;
 	}
 
-	chall->auth_server = ast_calloc(1, sizeof(*chall->auth_server));
-	if (!chall->auth_server) {
-		ao2_cleanup(chall);
-		return NULL;
-	}
-
-	pj_cstr(&realm, auth->realm);
-	pjsip_auth_srv_init(chall->pool, chall->auth_server, &realm, digest_lookup, 0);
-	if (!ao2_link(challenges, chall)) {
-		ao2_cleanup(chall);
-		return NULL;
-	}
 	return chall;
 }
 
@@ -250,23 +231,19 @@
 	return PJ_SUCCESS;
 }
 
-static struct challenge *find_challenge(pjsip_rx_data *rdata)
+static struct challenge *find_challenge(pjsip_rx_data *rdata, struct ast_sip_auth *auth)
 {
 	struct pjsip_authorization_hdr *auth_hdr = (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
 	struct challenge *chall = NULL;
+	struct challenge finder;
+
+	finder.realm = auth->realm;
 
 	for (auth_hdr = (pjsip_authorization_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, auth_hdr->next);
 			auth_hdr != (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
 			auth_hdr = (pjsip_authorization_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,  auth_hdr->next)) {
-		char nonce[AST_UUID_STR_LEN];
-		struct ast_uuid *uuid;
-		ast_copy_pj_str(nonce, &auth_hdr->credential.digest.nonce, sizeof(nonce));
-		uuid = ast_str_to_uuid(nonce);
-		if (!uuid) {
-			continue;
-		}
-		chall = ao2_find(challenges, uuid, OBJ_KEY);
-		ast_free(uuid);
+		ast_copy_pj_str(finder.nonce, &auth_hdr->credential.digest.nonce, sizeof(finder.nonce));
+		chall = ao2_find(challenges, &finder, OBJ_POINTER);
 		if (chall) {
 			break;
 		}
@@ -276,29 +253,45 @@
 }
 
 /*!
+ * \brief Common code for initializing a pjsip_auth_srv
+ */
+static void setup_auth_srv(pj_pool_t *pool, pjsip_auth_srv *auth_server, struct ast_sip_auth *auth)
+{
+	pj_str_t realm;
+	pj_cstr(&realm, auth->realm);
+
+	pjsip_auth_srv_init(pool, auth_server, &realm, digest_lookup, 0);
+}
+
+/*!
  * \brief astobj2 callback for verifying incoming credentials
  *
  * \param obj The ast_sip_auth to check against
  * \param arg The incoming request
+ * \param data A pool to use for the auth server
  * \return CMP_MATCH on successful authentication
  * \return 0 on failed authentication
  */
-static int verify(void *obj, void *arg, int flags)
+static int verify(void *obj, void *arg, void *data, int flags)
 {
 	RAII_VAR(struct challenge *, chall, NULL, ao2_cleanup);
 	struct ast_sip_auth *auth = obj;
+	pj_pool_t *pool = data;
 	pjsip_rx_data *rdata = arg;
 	pj_status_t authed;
 	int response_code;
-
-	chall = find_challenge(rdata);
+	pjsip_auth_srv auth_server;
+
+	chall = find_challenge(rdata, auth);
 	if (!chall) {
 		return 0;
 	}
 
+	setup_auth_srv(pool, &auth_server, auth);
+
 	store_auth(auth);
 
-	authed = pjsip_auth_srv_verify(chall->auth_server, rdata, &response_code);
+	authed = pjsip_auth_srv_verify(&auth_server, rdata, &response_code);
 
 	remove_auth();
 
@@ -318,19 +311,19 @@
 	RAII_VAR(struct challenge *, chall, NULL, ao2_cleanup);
 	pjsip_tx_data *tdata = arg;
 	pj_str_t qop;
-	pj_str_t pj_nonce;
-	char nonce[AST_UUID_STR_LEN];
+	pj_str_t nonce;
+	pjsip_auth_srv auth_server;
 
 	chall = create_challenge(auth);
 	if (!chall) {
 		return 0;
 	}
 
-	ast_uuid_to_str(chall->nonce, nonce, sizeof(nonce));
-
-	pj_cstr(&pj_nonce, nonce);
+	setup_auth_srv(tdata->pool, &auth_server, auth);
+
+	pj_cstr(&nonce, chall->nonce);
 	pj_cstr(&qop, "auth");
-	pjsip_auth_srv_challenge(chall->auth_server, &qop, &pj_nonce, NULL, PJ_FALSE, tdata);
+	pjsip_auth_srv_challenge(&auth_server, &qop, &nonce, NULL, PJ_FALSE, tdata);
 	return 0;
 }
 
@@ -348,7 +341,7 @@
 {
 	struct ast_sip_auth *auth;
 
-	auth = ao2_callback(endpoint->sip_auths, 0, verify, rdata);
+	auth = ao2_callback_data(endpoint->sip_auths, 0, verify, rdata, tdata->pool);
 	if (auth) {
 		ao2_ref(auth, -1);
 		return AST_SIP_AUTHENTICATION_SUCCESS;




More information about the svn-commits mailing list