[asterisk-commits] mmichelson: branch mmichelson/authenticate r381064 - /team/mmichelson/authent...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Feb 7 18:22:07 CST 2013
Author: mmichelson
Date: Thu Feb 7 18:22:04 2013
New Revision: 381064
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381064
Log:
Several improvements
* Add doxygen to explain nonce logic a bit
* Fix memory leak during entity ID generation
* Add timestamp checks to further make nonce checking more tight.
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=381064&r1=381063&r2=381064
==============================================================================
--- team/mmichelson/authenticate/res/res_sip_authenticator_digest.c (original)
+++ team/mmichelson/authenticate/res/res_sip_authenticator_digest.c Thu Feb 7 18:22:04 2013
@@ -174,6 +174,22 @@
return PJ_SUCCESS;
}
+/*!
+ * \brief Calculate a nonce
+ *
+ * We use this in order to create authentication challenges. We also use this in order
+ * to verify that an incoming request with credentials could be in response to one
+ * of our challenges.
+ *
+ * The nonce is calculated from a timestamp, the source IP address, the source port, a
+ * unique ID for us, and the realm. This helps to ensure that the incoming request
+ * is from the same source that the nonce was calculated for. Including the realm
+ * ensures that multiple challenges to the same request have different nonces.
+ *
+ * \param A UNIX timestamp expressed as a string
+ * \param rdata The incoming request
+ * \param realm The realm for which authentication should occur
+ */
static int build_nonce(struct ast_str **nonce, char *timestamp, pjsip_rx_data *rdata, const char *realm)
{
struct ast_str *str = ast_str_create(64);
@@ -190,16 +206,39 @@
return 0;
}
+/*!
+ * \brief Ensure that a nonce on an incoming request is sane.
+ *
+ * The nonce in an incoming Authorization header needs to pass some scrutiny in order
+ * for us to consider accepting it. What we do is re-build a nonce based on request
+ * data and a realm and see if it matches the nonce they sent us.
+ * \param candidate The nonce on an incoming request
+ * \param rdata The incoming request
+ * \param realm The realm for which we want to authenticate
+ * \retval 0 Nonce does not pass validity checks
+ * \retval 1 Nonce passes validity check
+ */
static int check_nonce(const char *candidate, pjsip_rx_data *rdata, const char *realm)
{
char *copy = ast_strdupa(candidate);
char *timestamp = strsep(©, "/");
+ static const int AUTH_TOLERANCE = 32;
+ int timestamp_int;
+ time_t now = time(NULL);
struct ast_str *calculated = ast_str_create(64);
if (!copy) {
/* Clearly a bad nonce! */
return 0;
}
+ if (sscanf(timestamp, "%30d", ×tamp_int) != 1) {
+ return 0;
+ }
+
+ if ((int) now - timestamp_int > AUTH_TOLERANCE) {
+ return 0;
+ }
+
build_nonce(&calculated, timestamp, rdata, realm);
ast_debug(3, "Calculated nonce %s. Actual nonce is %s\n", ast_str_buffer(calculated), candidate);
if (strcmp(ast_str_buffer(calculated), candidate)) {
@@ -215,10 +254,8 @@
char nonce[64];
while ((auth_hdr = (pjsip_authorization_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, auth_hdr->next))) {
- /* Let's do a nonce check! */
ast_copy_pj_str(nonce, &auth_hdr->credential.digest.nonce, sizeof(nonce));
if (check_nonce(nonce, rdata, auth->realm) && !pj_strcmp2(&auth_hdr->credential.digest.realm, auth->realm)) {
- /* Sane nonce found! */
challenge_found = 1;
break;
}
@@ -340,6 +377,7 @@
return -1;
}
ast_uuid_to_str(uu, entity_id, sizeof(entity_id));
+ ast_free(uu);
return 0;
}
More information about the asterisk-commits
mailing list