[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(&copy, "/");
+	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", &timestamp_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