[asterisk-commits] mmichelson: branch mmichelson/authenticate r381036 - in /team/mmichelson/auth...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Feb 7 11:47:45 CST 2013


Author: mmichelson
Date: Thu Feb  7 11:47:42 2013
New Revision: 381036

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381036
Log:
First measure in storing authentication challenges instead of being stateless.

We now generate a nonce for each authentication challenge and store the challenge
in a container. The container is keyed off the nonce. This way, when a request comes
in, we can first find if we have a challenge with that nonce and then move on to
verification.

What needs to be added now is a destruction mechanism for authentication challenges.
This includes destroying challenges as requests with credentials arrive as well as
timing out authentication challenges that receive no answers.

This code is untested. It will be tested once further improvements are made.


Modified:
    team/mmichelson/authenticate/include/asterisk/sorcery.h
    team/mmichelson/authenticate/res/res_sip/sip_configuration.c
    team/mmichelson/authenticate/res/res_sip_authenticator_digest.c

Modified: team/mmichelson/authenticate/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/authenticate/include/asterisk/sorcery.h?view=diff&rev=381036&r1=381035&r2=381036
==============================================================================
--- team/mmichelson/authenticate/include/asterisk/sorcery.h (original)
+++ team/mmichelson/authenticate/include/asterisk/sorcery.h Thu Feb  7 11:47:42 2013
@@ -146,6 +146,9 @@
 /*!
  * \brief A callback function for when an object set is successfully applied to an object
  *
+ * \note On a failure return, the state of the object is left undefined. It is a bad
+ * idea to try to use this object.
+ *
  * \param sorcery Sorcery structure in use
  * \param obj The object itself
  * \retval 0 Success

Modified: team/mmichelson/authenticate/res/res_sip/sip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/authenticate/res/res_sip/sip_configuration.c?view=diff&rev=381036&r1=381035&r2=381036
==============================================================================
--- team/mmichelson/authenticate/res/res_sip/sip_configuration.c (original)
+++ team/mmichelson/authenticate/res/res_sip/sip_configuration.c Thu Feb  7 11:47:42 2013
@@ -322,7 +322,7 @@
 		ao2_cleanup(endpoint);
 		return NULL;
 	}
-	if (!(endpoint->sip_auths = ao2_container_alloc_list(0,
+	if (!(endpoint->sip_auths = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
 					AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, NULL, auth_cmp))) {
 		ao2_cleanup(endpoint);
 		return NULL;

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=381036&r1=381035&r2=381036
==============================================================================
--- team/mmichelson/authenticate/res/res_sip_authenticator_digest.c (original)
+++ team/mmichelson/authenticate/res/res_sip_authenticator_digest.c Thu Feb  7 11:47:42 2013
@@ -29,6 +29,85 @@
 	<depend>res_sip</depend>
 	<support_level>core</support_level>
  ***/
+
+#define CHALLENGE_BUCKETS 83
+
+static pj_status_t digest_lookup(pj_pool_t *pool, const pj_str_t *realm,
+		const pj_str_t *acc_name, pjsip_cred_info *info);
+
+struct ao2_container *challenges;
+
+struct challenge {
+	pj_pool_t *pool;
+	pjsip_auth_srv *auth_server;
+	struct ast_uuid *nonce;
+};
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+static struct challenge *create_challenge(struct ast_sip_auth *auth)
+{
+	struct challenge *chall = ao2_alloc(sizeof(*chall), challenge_destructor);
+	pj_str_t realm;
+
+	if (!chall) {
+		return NULL;
+	}
+
+	chall->pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "auth", 128, 128);
+	if (!chall->pool) {
+		ao2_cleanup(chall);
+		return NULL;
+	}
+
+	chall->nonce = ast_uuid_generate();
+	if (!chall->nonce) {
+		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;
+}
 
 /*!
  * \brief Determine if authentication is required
@@ -171,40 +250,55 @@
 	return PJ_SUCCESS;
 }
 
-/*!
- * \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);
+static struct challenge *find_challenge(pjsip_rx_data *rdata)
+{
+	struct pjsip_authorization_hdr *auth_hdr = (pjsip_authorization_hdr *) &rdata->msg_info.msg->hdr;
+	struct challenge *chall = NULL;
+
+	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);
+		if (chall) {
+			break;
+		}
+	}
+
+	return chall;
 }
 
 /*!
  * \brief astobj2 callback for verifying incoming credentials
  *
  * \param obj The ast_sip_auth to check against
- * \param arg The pre-made response. Used only for its pool
- * \param data The incoming request
+ * \param arg The incoming request
  * \return CMP_MATCH on successful authentication
  * \return 0 on failed authentication
  */
-static int verify(void *obj, void *arg, void *data, int flags)
-{
+static int verify(void *obj, void *arg, int flags)
+{
+	RAII_VAR(struct challenge *, chall, NULL, ao2_cleanup);
 	struct ast_sip_auth *auth = obj;
-	pjsip_tx_data *tdata = arg;
-	pjsip_rx_data *rdata = data;
-	pjsip_auth_srv auth_server;
+	pjsip_rx_data *rdata = arg;
 	pj_status_t authed;
 	int response_code;
 
-	setup_auth_srv(tdata->pool, &auth_server, auth);
+	chall = find_challenge(rdata);
+	if (!chall) {
+		return 0;
+	}
 
 	store_auth(auth);
 
-	authed = pjsip_auth_srv_verify(&auth_server, rdata, &response_code);
+	authed = pjsip_auth_srv_verify(chall->auth_server, rdata, &response_code);
 
 	remove_auth();
 
@@ -221,14 +315,22 @@
 static int challenge(void *obj, void *arg, int flags)
 {
 	struct ast_sip_auth *auth = obj;
+	RAII_VAR(struct challenge *, chall, NULL, ao2_cleanup);
 	pjsip_tx_data *tdata = arg;
-	pjsip_auth_srv auth_server;
 	pj_str_t qop;
+	pj_str_t pj_nonce;
+	char nonce[AST_UUID_STR_LEN];
+
+	chall = create_challenge(auth);
+	if (!chall) {
+		return 0;
+	}
+
+	ast_uuid_to_str(chall->nonce, nonce, sizeof(nonce));
+
+	pj_cstr(&pj_nonce, nonce);
 	pj_cstr(&qop, "auth");
-
-	setup_auth_srv(tdata->pool, &auth_server, auth);
-
-	pjsip_auth_srv_challenge(&auth_server, &qop, NULL, NULL, PJ_FALSE, tdata);
+	pjsip_auth_srv_challenge(chall->auth_server, &qop, &pj_nonce, NULL, PJ_FALSE, tdata);
 	return 0;
 }
 
@@ -246,7 +348,7 @@
 {
 	struct ast_sip_auth *auth;
 
-	auth = ao2_callback_data(endpoint->sip_auths, 0, verify, tdata, rdata);
+	auth = ao2_callback(endpoint->sip_auths, 0, verify, rdata);
 	if (auth) {
 		ao2_ref(auth, -1);
 		return AST_SIP_AUTHENTICATION_SUCCESS;
@@ -263,7 +365,12 @@
 
 static int load_module(void)
 {
+	challenges = ao2_container_alloc(CHALLENGE_BUCKETS, challenge_hash, challenge_cmp);
+	if (!challenges) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
 	if (ast_sip_register_authenticator(&digest_authenticator)) {
+		ao2_cleanup(challenges);
 		return AST_MODULE_LOAD_DECLINE;
 	}
 	return AST_MODULE_LOAD_SUCCESS;
@@ -271,6 +378,7 @@
 
 static int unload_module(void)
 {
+	ao2_cleanup(challenges);
 	ast_sip_unregister_authenticator(&digest_authenticator);
 	return 0;
 }




More information about the asterisk-commits mailing list