[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