[asterisk-commits] mmichelson: branch mmichelson/authenticate r381053 - /team/mmichelson/authent...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list