[asterisk-commits] tilghman: branch group/manager_http_auth r188580 - in /team/group/manager_htt...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Apr 15 12:10:49 CDT 2009


Author: tilghman
Date: Wed Apr 15 12:10:44 2009
New Revision: 188580

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=188580
Log:
Convert digest function into using stringfields, as suggested by Mark Michelson

Modified:
    team/group/manager_http_auth/include/asterisk/http.h
    team/group/manager_http_auth/include/asterisk/utils.h
    team/group/manager_http_auth/main/manager.c
    team/group/manager_http_auth/main/utils.c

Modified: team/group/manager_http_auth/include/asterisk/http.h
URL: http://svn.digium.com/svn-view/asterisk/team/group/manager_http_auth/include/asterisk/http.h?view=diff&rev=188580&r1=188579&r2=188580
==============================================================================
--- team/group/manager_http_auth/include/asterisk/http.h (original)
+++ team/group/manager_http_auth/include/asterisk/http.h Wed Apr 15 12:10:44 2009
@@ -54,11 +54,11 @@
 
 /*! \brief HTTP Request methods known by Asterisk */
 enum ast_http_method {
-	AST_HTTP_UNKNOWN = 0,	/*!< Unknown response */
-	AST_HTTP_GET,
+	AST_HTTP_UNKNOWN = -1,   /*!< Unknown response */
+	AST_HTTP_GET = 0,
 	AST_HTTP_POST,
 	AST_HTTP_HEAD,
-	AST_HTTP_PUT		/*!< Not supported in Asterisk */
+	AST_HTTP_PUT,            /*!< Not supported in Asterisk */
 };
 
 struct ast_http_uri;

Modified: team/group/manager_http_auth/include/asterisk/utils.h
URL: http://svn.digium.com/svn-view/asterisk/team/group/manager_http_auth/include/asterisk/utils.h?view=diff&rev=188580&r1=188579&r2=188580
==============================================================================
--- team/group/manager_http_auth/include/asterisk/utils.h (original)
+++ team/group/manager_http_auth/include/asterisk/utils.h Wed Apr 15 12:10:44 2009
@@ -32,8 +32,9 @@
 #include "asterisk/time.h"
 #include "asterisk/logger.h"
 #include "asterisk/localtime.h"
-
-/*! 
+#include "asterisk/stringfields.h"
+
+/*!
 \note \verbatim
    Note:
    It is very important to use only unsigned variables to hold
@@ -649,16 +650,18 @@
 
 /* Definition for Digest authorization */
 struct ast_http_digest {
-	char username[80];
-	char nonce[32];
-	char uri[256];
-	char realm[256];
-	char domain[256];
-	char response[256];
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(username);
+		AST_STRING_FIELD(nonce);
+		AST_STRING_FIELD(uri);
+		AST_STRING_FIELD(realm);
+		AST_STRING_FIELD(domain);
+		AST_STRING_FIELD(response);
+		AST_STRING_FIELD(cnonce);
+		AST_STRING_FIELD(opaque);
+		AST_STRING_FIELD(nc);
+	);
 	int qop;		/* Flag set to 1, if we send/recv qop="quth" */
-	char cnonce[256];
-	char opaque[32];
-	char nc[32];
 };
 
 /*!

Modified: team/group/manager_http_auth/main/manager.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/manager_http_auth/main/manager.c?view=diff&rev=188580&r1=188579&r2=188580
==============================================================================
--- team/group/manager_http_auth/main/manager.c (original)
+++ team/group/manager_http_auth/main/manager.c Wed Apr 15 12:10:44 2009
@@ -22,7 +22,7 @@
  *
  * \author Mark Spencer <markster at digium.com>
  *
- * \extref OpenSSL http://www.openssl.org - for AMI/SSL 
+ * \extref OpenSSL http://www.openssl.org - for AMI/SSL
  *
  * At the moment this file contains a number of functions, namely:
  *
@@ -285,7 +285,7 @@
  * Event list management functions.
  * We assume that the event list always has at least one element,
  * and the delete code will not remove the last entry even if the
- * 
+ *
  */
 #if 0
 static time_t __deb(time_t start, const char *msg)
@@ -601,7 +601,7 @@
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show command";
-		e->usage = 
+		e->usage =
 			"Usage: manager show command <actionname>\n"
 			"	Shows the detailed description for a specific Asterisk manager interface command.\n";
 		return NULL;
@@ -647,9 +647,9 @@
 		e->usage = "Usage: manager set debug [on|off]\n	Show, enable, disable debugging of the manager code.\n";
 		return NULL;
 	case CLI_GENERATE:
-		return NULL;	
-	}
-	
+		return NULL;
+	}
+
 	if (a->argc == 3) {
 		ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
 	} else if (a->argc == 4) {
@@ -675,7 +675,7 @@
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show user";
-		e->usage = 
+		e->usage =
 			" Usage: manager show user <user>\n"
 			"        Display all information related to the manager user specified.\n";
 		return NULL;
@@ -736,7 +736,7 @@
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show users";
-		e->usage = 
+		e->usage =
 			"Usage: manager show users\n"
 			"       Prints a listing of all managers that are currently configured on that\n"
 			" system.\n";
@@ -781,13 +781,13 @@
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show commands";
-		e->usage = 
+		e->usage =
 			"Usage: manager show commands\n"
 			"	Prints a listing of all the available Asterisk manager interface commands.\n";
 		return NULL;
 	case CLI_GENERATE:
-		return NULL;	
-	}	
+		return NULL;
+	}
 	authority = ast_str_alloca(80);
 	ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
 	ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
@@ -809,17 +809,17 @@
 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
 	int count = 0;
 	struct ao2_iterator i;
-	
+
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show connected";
-		e->usage = 
+		e->usage =
 			"Usage: manager show connected\n"
 			"	Prints a listing of the users that are currently connected to the\n"
 			"Asterisk manager interface.\n";
 		return NULL;
 	case CLI_GENERATE:
-		return NULL;	
+		return NULL;
 	}
 
 	ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
@@ -846,7 +846,7 @@
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "manager show eventq";
-		e->usage = 
+		e->usage =
 			"Usage: manager show eventq\n"
 			"	Prints a listing of all events pending in the Asterisk manger\n"
 			"event queue.\n";
@@ -1191,7 +1191,7 @@
 				error = 0;
 			}
 		} else {
-			ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n", 
+			ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
 				S_OR(s->session->challenge, ""));
 		}
 	} else if (password && user->secret && !strcmp(password, user->secret)) {
@@ -1205,14 +1205,14 @@
 	}
 
 	/* auth complete */
-	
+
 	ast_copy_string(s->session->username, username, sizeof(s->session->username));
 	s->session->readperm = user->readperm;
 	s->session->writeperm = user->writeperm;
 	s->session->writetimeout = user->writetimeout;
 	s->session->sessionstart = time(NULL);
 	set_eventmask(s, astman_get_header(m, "Events"));
-	
+
 	AST_RWLIST_UNLOCK(&users);
 	return 0;
 }
@@ -1320,7 +1320,7 @@
 }
 
 
-	
+
 
 /*! The amount of space in out must be at least ( 2 * strlen(in) + 1 ) */
 static void json_escape(char *out, const char *in)
@@ -1443,7 +1443,7 @@
 			object = 1;
 			value++;
 		}
-	
+
 		snprintf(hdr, sizeof(hdr), "Match-%06d", x);
 		match = astman_get_header(m, hdr);
 
@@ -1516,7 +1516,7 @@
 				break;
 			}
 			if (!(category = ast_category_get(cfg, cat))) {
-				result = UNKNOWN_CATEGORY;	
+				result = UNKNOWN_CATEGORY;
 				break;
 			}
 			if (!(v = ast_variable_new(var, value, dfn))) {
@@ -2009,7 +2009,7 @@
 	return 0;
 }
 
-static char mandescr_status[] = 
+static char mandescr_status[] =
 "Description: Lists channel status along with requested channel vars.\n"
 "Variables: (Names marked with * are required)\n"
 "	*Channel: Name of the channel to query for status\n"
@@ -2017,7 +2017,7 @@
 "	ActionID: Optional ID for this transaction\n"
 "Will return the status information of each channel along with the\n"
 "value for the specified channel variables.\n";
- 
+
 
 /*! \brief Manager "status" command to show channels */
 /* Needs documentation... */
@@ -2184,13 +2184,13 @@
 
 	res = ast_sendtext(c, textmsg);
 	ast_channel_unlock(c);
-	
+
 	if (res > 0) {
 		astman_send_ack(s, m, "Success");
 	} else {
 		astman_send_error(s, m, "Failure");
 	}
-	
+
 	return res;
 }
 
@@ -2303,7 +2303,7 @@
 	struct ast_call_feature *atxfer_feature = NULL;
 	char *feature_code = NULL;
 
-	if (ast_strlen_zero(name)) { 
+	if (ast_strlen_zero(name)) {
 		astman_send_error(s, m, "No channel specified");
 		return 0;
 	}
@@ -2476,7 +2476,7 @@
 	}
 
 	if (!chan) {
-		snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);	
+		snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
 	}
 	/* Tell the manager what happened with the channel */
 	manager_event(EVENT_FLAG_CALL, "OriginateResponse",
@@ -2489,8 +2489,8 @@
 		"Uniqueid: %s\r\n"
 		"CallerIDNum: %s\r\n"
 		"CallerIDName: %s\r\n",
-		in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success", 
-		chan ? chan->name : requested_channel, in->context, in->exten, reason, 
+		in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
+		chan ? chan->name : requested_channel, in->context, in->exten, reason,
 		chan ? chan->uniqueid : "<null>",
 		S_OR(in->cid_num, "<unknown>"),
 		S_OR(in->cid_name, "<unknown>")
@@ -2862,14 +2862,14 @@
 			"CoreMaxLoadAvg: %f\r\n"
 			"CoreRunUser: %s\r\n"
 			"CoreRunGroup: %s\r\n"
-			"CoreMaxFilehandles: %d\r\n" 
+			"CoreMaxFilehandles: %d\r\n"
 			"CoreRealTimeEnabled: %s\r\n"
 			"CoreCDRenabled: %s\r\n"
 			"CoreHTTPenabled: %s\r\n"
 			"\r\n",
 			idText,
 			AMI_VERSION,
-			ast_get_version(), 
+			ast_get_version(),
 			ast_config_AST_SYSTEM_NAME,
 			option_maxcalls,
 			option_maxload,
@@ -2948,7 +2948,7 @@
 "Variables:\n"
 "          ActionID: Optional Action id for message matching.\n";
 
-/*! \brief  Manager command "CoreShowChannels" - List currently defined channels 
+/*! \brief  Manager command "CoreShowChannels" - List currently defined channels
  *          and some information about them. */
 static int action_coreshowchannels(struct mansession *s, const struct message *m)
 {
@@ -2964,7 +2964,7 @@
 		actionidtext[0] = '\0';
 	}
 
-	astman_send_listack(s, m, "Channels will follow", "start");	
+	astman_send_listack(s, m, "Channels will follow", "start");
 
 	while ((c = ast_channel_walk_locked(c)) != NULL) {
 		struct ast_channel *bc = ast_bridged_channel(c);
@@ -3011,7 +3011,7 @@
 	return 0;
 }
 
-static char mandescr_modulecheck[] = 
+static char mandescr_modulecheck[] =
 "Description: Checks if Asterisk module is loaded\n"
 "Variables: \n"
 "  ActionID: <id>          Action ID for this transaction. Will be returned.\n"
@@ -3064,7 +3064,7 @@
 	return 0;
 }
 
-static char mandescr_moduleload[] = 
+static char mandescr_moduleload[] =
 "Description: Loads, unloads or reloads an Asterisk module in a running system.\n"
 "Variables: \n"
 "  ActionID: <id>          Action ID for this transaction. Will be returned.\n"
@@ -3116,7 +3116,7 @@
 			ast_module_reload(NULL);	/* Reload all modules */
 			astman_send_ack(s, m, "All modules reloaded");
 		}
-	} else 
+	} else
 		astman_send_error(s, m, "Incomplete ModuleLoad action.");
 	return 0;
 }
@@ -3682,12 +3682,12 @@
 
 /*!
  * locate an http session in the list.
- * The search keys (nonce) and (username) is value from received 
+ * The search keys (nonce) and (username) is value from received
  * "Authorization" http header.
  * As well as in find_session() function, the value of the nonce can't be zero.
  * (0 meansi, that the session used for AMI socket connection).
  * Flag (stale) is set, if client used valid, but old, nonce value.
- * 
+ *
  */
 static struct mansession_session *find_session_by_nonce(const char *username, unsigned long nonce, int *stale)
 {
@@ -3716,7 +3716,7 @@
 	return session;
 }
 
-int astman_is_authed(uint32_t ident) 
+int astman_is_authed(uint32_t ident)
 {
 	int authed;
 	struct mansession_session *session;
@@ -3803,7 +3803,7 @@
 				break;
 			}
 		}
-			
+
 		if ( (mode & 2) && !isalnum(*src)) {
 			*dst++ = '_';
 			space--;
@@ -3881,7 +3881,7 @@
  *
  * General: the unformatted text is used as a value of
  * XML output:  to be completed
- * 
+ *
  * \verbatim
  *   Each section is within <response type="object" id="xxx">
  *   where xxx is taken from ajaxdest variable or defaults to unknown
@@ -3922,7 +3922,7 @@
 			objtype = "generic";
 		}
 	}
-	
+
 	/* we want to stop when we find an empty line */
 	while (in && *in) {
 		val = strsep(&in, "\r\n");	/* mark start and end of line */
@@ -3931,14 +3931,14 @@
 		}
 		ast_trim_blanks(val);
 		ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
-		if (ast_strlen_zero(val)) { 
+		if (ast_strlen_zero(val)) {
 			/* empty line */
 			if (in_data) {
 				/* close data in Opaque mode */
 				ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
 				in_data = 0;
 			}
-			
+
 			if (inobj) {
 				/* close block */
 				ast_str_append(out, 0, xml ? " /></response>\n" :
@@ -3958,14 +3958,14 @@
 			vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
 			inobj = 1;
 		}
-		
+
 		if (in_data) {
 			/* Process data field in Opaque mode */
 			xml_copy_escape(out, val, 0);   /* data field */
 			ast_str_append(out, 0, xml ? "\n" : "<br>\n");
 			continue;
 		}
-			
+
 		/* We expect "Name: value" line here */
 		var = strsep(&val, ":");
 		if (val) {
@@ -3990,7 +3990,7 @@
 			vc->count = 1;
 			ao2_link(vco, vc);
 		}
-		
+
 		xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */
 		if (vc->count > 1) {
 			ast_str_append(out, 0, "-%d", vc->count);
@@ -4254,7 +4254,7 @@
 
 	time_t time_now = time(NULL);
 	unsigned long nonce = 0, nc;
-	struct ast_http_digest d;
+	struct ast_http_digest d = { NULL, };
 	struct ast_manager_user *user = NULL;
 	int stale = 0;
 	char resp_hash[256]="";
@@ -4269,7 +4269,7 @@
 		ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
 		return -1;
 	}
-	
+
 	/* Find "Authorization: " header */
 	for (v = headers; v; v = v->next) {
 		if (!strcasecmp(v->name, "Authorization")) {
@@ -4280,8 +4280,13 @@
 	if (!v || ast_strlen_zero(v->value)) {
 		goto out_401; /* Authorization Header not present - send auth request */
 	}
-	
+
 	/* Digest found - parse */
+	if (ast_string_field_init(&d, 128)) {
+		ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
+		return -1;
+	}
+
 	if (ast_parse_digest(v->value, &d, 0, 1)) {
 		/* Error in Digest - send new one */
 		nonce = 0;
@@ -4292,7 +4297,7 @@
 		nonce = 0;
 		goto out_401;
 	}
-	
+
 	AST_RWLIST_WRLOCK(&users);
 	user = get_manager_by_name_locked(d.username);
 	if(!user) {
@@ -4309,7 +4314,7 @@
 		ast_http_error(ser, 403, "Permission denied", "Permission denied\n");
 		return -1;
 	}
-	
+
 	/* --- We have auth, so check it */
 
 	/* compute the expected response to compare with what we received */
@@ -4321,9 +4326,9 @@
 		/* XXX Now request method are hardcoded in A2 */
 		snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri);
 		ast_md5_hash(a2_hash, a2);
-		
+
 		if (d.qop) {
-			/* RFC 2617 */	
+			/* RFC 2617 */
 			snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash);
 		}  else {
 			/* RFC 2069 */
@@ -4331,7 +4336,7 @@
 		}
 		ast_md5_hash(resp_hash, resp);
 	}
-	
+
 	if (!d.nonce  || strncasecmp(d.response, resp_hash, strlen(resp_hash))) {
 		/* Something was wrong, so give the client to try with a new challenge */
 		AST_RWLIST_UNLOCK(&users);
@@ -4387,20 +4392,16 @@
 
 	} else if (stale) {
 		/*
-		 * Session found, but nonce is staled.
+		 * Session found, but nonce is stale.
 		 *
-		 * It may be caused if old request (w/old nonce) arrived.
-		 * 
-		 * Or, if http request with lower nonce_count value
-		 * arrive after request w/higher nonce counter and
-		 * new auth request was beed send before.
-		 * 
-		 * This may be as the result of http proxy usage 
-		 * (separate delay or multipath) or in situation,
-		 * if page are refreshed to fast (found in Firefox).
+		 * This could be because an old request (w/old nonce) arrived.
 		 *
-		 * In this situation reask the auth information with
-		 * actual nonce value.
+		 * This may be as the result of http proxy usage (separate delay or
+		 * multipath) or in a situation where a page was refreshed too quickly
+		 * (seen in Firefox).
+		 *
+		 * In this situation, we repeat the 401 auth with the current nonce
+		 * value.
 		 */
 		nonce = session->managerid;
 		ao2_unlock(session);
@@ -4410,14 +4411,11 @@
 		sscanf(d.nc, "%lx", &nc);
 		if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) {
 			/*
-			 * Nonce time expired (> 2 minutes)
-			 * or something wrong with nonce counter.
+			 * Nonce time expired (> 2 minutes) or something wrong with nonce
+			 * counter.
 			 *
-			 * Create new nonce key, put him in managerid field
-			 * in manager session struct and resend Digest auth
-			 * request.
-			 * Save expired nonce value in s->oldnonce field for
-			 * stale checking...
+			 * Create new nonce key and resend Digest auth request. Old nonce
+			 * is saved for stale checking...
 			 */
 			session->nc = 0; /* Reset nonce counter */
 			session->oldnonce = session->managerid;
@@ -4473,7 +4471,7 @@
 	}
 
 	if (s.f) {
-		result_size = ftell(s.f); /* Calculate aprox. size of result */
+		result_size = ftell(s.f); /* Calculate approx. size of result */
 	}
 
 	http_header = ast_str_create(80);
@@ -4527,21 +4525,18 @@
 	} else if (format == FORMAT_HTML) {
 		ast_str_append(&out, 0, "</table></form></body></html>\r\n");
 	}
-	
+
 	ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
 	http_header = out = NULL;
-		
+
 auth_callback_out:
-	/* Clear resource and unlock manager session */
+	/* Clear resources and unlock manager session */
 	if (method == AST_HTTP_POST && params) {
 		ast_variables_destroy(params);
 	}
-	if (http_header) {
-		ast_free(http_header);
-	}
-	if (out) {
-		ast_free(out);
-	}
+
+	ast_free(http_header);
+	ast_free(out);
 
 	ao2_lock(session);
 	if (session->f) {
@@ -4555,14 +4550,16 @@
 		ast_debug(1, "Need destroy, doing it now!\n");
 		session_destroy(session);
 	}
+	ast_string_field_free_memory(&d);
 	return 0;
-	
+
 out_401:
 	if (!nonce) {
 		nonce = ast_random();
 	}
-	
+
 	ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL);
+	ast_string_field_free_memory(&d);
 	return 0;
 }
 
@@ -4665,7 +4662,7 @@
 static struct ast_tcptls_session_args ami_desc = {
 	.accept_fd = -1,
 	.master = AST_PTHREADT_NULL,
-	.tls_cfg = NULL, 
+	.tls_cfg = NULL,
 	.poll_timeout = 5000,	/* wake up every 5 seconds */
 	.periodic_fn = purge_old_stuff,
 	.name = "AMI server",
@@ -4676,7 +4673,7 @@
 static struct ast_tcptls_session_args amis_desc = {
 	.accept_fd = -1,
 	.master = AST_PTHREADT_NULL,
-	.tls_cfg = &ami_tls_cfg, 
+	.tls_cfg = &ami_tls_cfg,
 	.poll_timeout = -1,	/* the other does the periodic cleanup */
 	.name = "AMI TLS server",
 	.accept_fn = ast_tcptls_server_root,	/* thread doing the accept() */
@@ -4800,7 +4797,7 @@
 				ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
 				memset(&ami_desc.local_address.sin_addr, 0, sizeof(ami_desc.local_address.sin_addr));
 			}
-		} else if (!strcasecmp(var->name, "allowmultiplelogin")) { 
+		} else if (!strcasecmp(var->name, "allowmultiplelogin")) {
 			allowmultiplelogin = ast_true(val);
 		} else if (!strcasecmp(var->name, "displayconnects")) {
 			displayconnects = ast_true(val);
@@ -4813,7 +4810,7 @@
 		} else {
 			ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
 				var->name, val);
-		}	
+		}
 	}
 
 	if (manager_enabled) {
@@ -4826,7 +4823,6 @@
 		amis_desc.local_address.sin_family = AF_INET;
 	}
 
-	
 	AST_RWLIST_WRLOCK(&users);
 
 	/* First, get users from users.conf */
@@ -4839,7 +4835,7 @@
 			if (!strcasecmp(cat, "general")) {
 				continue;
 			}
-			
+
 			hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
 			if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
 				const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
@@ -4847,7 +4843,7 @@
 				const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
 				const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
 				const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
-				
+
 				/* Look for an existing entry,
 				 * if none found - create one and add it to the list
 				 */
@@ -4982,7 +4978,7 @@
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
 		if (user->keep) {	/* valid record. clear flag for the next round */
 			user->keep = 0;
-			
+
 			/* Calculate A1 for Digest auth */
 			snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret);
 			ast_md5_hash(a1_hash,a1);
@@ -5019,7 +5015,7 @@
 			ast_http_uri_link(&rawmanuri);
 			ast_http_uri_link(&manageruri);
 			ast_http_uri_link(&managerxmluri);
-			
+
 			ast_http_uri_link(&arawmanuri);
 			ast_http_uri_link(&amanageruri);
 			ast_http_uri_link(&amanagerxmluri);
@@ -5076,7 +5072,7 @@
 struct ast_datastore *astman_datastore_find(struct mansession *s, const struct ast_datastore_info *info, const char *uid)
 {
 	struct ast_datastore *datastore = NULL;
-	
+
 	if (info == NULL)
 		return NULL;
 

Modified: team/group/manager_http_auth/main/utils.c
URL: http://svn.digium.com/svn-view/asterisk/team/group/manager_http_auth/main/utils.c?view=diff&rev=188580&r1=188579&r2=188580
==============================================================================
--- team/group/manager_http_auth/main/utils.c (original)
+++ team/group/manager_http_auth/main/utils.c Wed Apr 15 12:10:44 2009
@@ -1850,30 +1850,31 @@
 int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
 	int i;
 	char *c, key[512], val[512], tmp[512];
-
-	if(ast_strlen_zero(digest) || d == NULL)
+	struct ast_str *str = ast_str_create(16);
+
+	if (ast_strlen_zero(digest) || !d || !str) {
+		ast_free(str);
 		return -1;
-
-	ast_copy_string(tmp, digest, sizeof(tmp));
-
-	c = ast_skip_blanks(tmp);
-	
+	}
+
+	ast_str_set(&str, 0, "%s", digest);
+
+	c = ast_skip_blanks(ast_str_buffer(str));
+
 	if (strncasecmp(tmp, "Digest ", strlen("Digest "))) {
 		ast_log(LOG_WARNING, "Missing Digest.\n");
+		ast_free(str);
 		return -1;
 	}
 	c += strlen("Digest ");
 
-	/* clear digest data */
-	memset(d, 0, sizeof(struct ast_http_digest));
-
 	/* lookup for keys/value pair */
-        while (*c && *(c = ast_skip_blanks(c))) {
-
+	while (*c && *(c = ast_skip_blanks(c))) {
 		/* find key */
 		i = 0;
-		while (*c && *c != '=' && *c != ',' && !isspace(*c) )
+		while (*c && *c != '=' && *c != ',' && !isspace(*c)) {
 			key[i++] = *c++;
+		}
 		key[i] = '\0';
 		c = ast_skip_blanks(c);
 		if (*c == '=') {
@@ -1883,68 +1884,78 @@
 				/* in quotes. Skip first and look for last */
 				c++;
 				while (*c && *c != '\"') {
-					if (*c == '\\' && c[1] != '\0') /* unescape chars */
+					if (*c == '\\' && c[1] != '\0') { /* unescape chars */
 						c++;
+					}
 					val[i++] = *c++;
 				}
 			} else {
 				/* token */
-				while (*c && *c != ',' && !isspace(*c) )
+				while (*c && *c != ',' && !isspace(*c)) {
 					val[i++] = *c++;
+				}
 			}
 			val[i] = '\0';
 		}
 
-		while (*c && *c != ',')
+		while (*c && *c != ',') {
 			c++;
-		if (*c)
+		}
+		if (*c) {
 			c++;
-
-		if (!strcasecmp(key, "username"))
-			strncpy(d->username, val, sizeof(d->username)-1);
-		else if (!strcasecmp(key, "realm"))
-			strncpy(d->realm, val, sizeof(d->realm)-1);
-		else if (!strcasecmp(key, "nonce"))
-			strncpy(d->nonce, val, sizeof(d->nonce)-1);
-		else if (!strcasecmp(key, "uri"))
-			strncpy(d->uri, val, sizeof(d->uri)-1);
-		else if (!strcasecmp(key, "domain"))
-			strncpy(d->domain, val, sizeof(d->domain)-1);
-		else if (!strcasecmp(key, "response"))
-			strncpy(d->response, val, sizeof(d->response)-1);
-		else if (!strcasecmp(key, "algorithm")) {
+		}
+
+		if (!strcasecmp(key, "username")) {
+			ast_string_field_set(d, username, val);
+		} else if (!strcasecmp(key, "realm")) {
+			ast_string_field_set(d, realm, val);
+		} else if (!strcasecmp(key, "nonce")) {
+			ast_string_field_set(d, nonce, val);
+		} else if (!strcasecmp(key, "uri")) {
+			ast_string_field_set(d, uri, val);
+		} else if (!strcasecmp(key, "domain")) {
+			ast_string_field_set(d, domain, val);
+		} else if (!strcasecmp(key, "response")) {
+			ast_string_field_set(d, response, val);
+		} else if (!strcasecmp(key, "algorithm")) {
 			if (strcasecmp(val, "MD5")) {
 				ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", val);
 				return -1;
 			}
-		} else if (!strcasecmp(key, "cnonce"))
-			strncpy(d->cnonce, val, sizeof(d->cnonce)-1);
-		else if (!strcasecmp(key, "opaque"))
-			strncpy(d->opaque, val, sizeof(d->opaque)-1);
-		else if (!strcasecmp(key, "qop") && !strcasecmp(val, "auth"))
+		} else if (!strcasecmp(key, "cnonce")) {
+			ast_string_field_set(d, cnonce, val);
+		} else if (!strcasecmp(key, "opaque")) {
+			ast_string_field_set(d, opaque, val);
+		} else if (!strcasecmp(key, "qop") && !strcasecmp(val, "auth")) {
 			d->qop = 1;
-		else if (!strcasecmp(key, "nc")) {
+		} else if (!strcasecmp(key, "nc")) {
 			unsigned long u;
 			if (sscanf(val, "%lx", &u) != 1) {
 				ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", val);
 				return -1;
 			}
-			strncpy(d->nc, val, sizeof(d->nc)-1);
-		}
-	}
+			ast_string_field_set(d, nc, val);
+		}
+	}
+	ast_free(str);
+
 	/* Digest checkout */
-	if (!*d->realm || !*d->nonce)
-		return -1; /* "realm" and "nonce" MUST be always exist */
+	if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
+		/* "realm" and "nonce" MUST be always exist */
+		return -1;
+	}
 
 	if (!request) {
 		/* Additional check for Digest response */
-		if (!*d->username || !*d->uri || !*d->response)
+		if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
 			return -1;
-		
-		if(pedantic && d->qop && (!*d->cnonce || !*d->nc))
+		}
+
+		if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
 			return -1;
-	}
-	
+		}
+	}
+
 	return 0;
 }
 




More information about the asterisk-commits mailing list