mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
Support HTTP digest authentication for the http manager interface.
(closes issue #10961) Reported by: ys Patches: digest_auth_r148468_v5.diff uploaded by ys (license 281) SVN branch http://svn.digium.com/svn/asterisk/team/group/manager_http_auth Tested by: ys, twilson, tilghman Review: http://reviewboard.digium.com/r/223/ Reviewed by: tilghman,russellb,mmichelson git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190349 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
120
main/utils.c
120
main/utils.c
@@ -1839,6 +1839,126 @@ int ast_utils_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*\brief Parse digest authorization header.
|
||||
*\return Returns -1 if we have no auth or something wrong with digest.
|
||||
*\note This function may be used for Digest request and responce header.
|
||||
* request arg is set to nonzero, if we parse Digest Request.
|
||||
* pedantic arg can be set to nonzero if we need to do addition Digest check.
|
||||
*/
|
||||
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];
|
||||
struct ast_str *str = ast_str_create(16);
|
||||
|
||||
if (ast_strlen_zero(digest) || !d || !str) {
|
||||
ast_free(str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 ");
|
||||
|
||||
/* lookup for keys/value pair */
|
||||
while (*c && *(c = ast_skip_blanks(c))) {
|
||||
/* find key */
|
||||
i = 0;
|
||||
while (*c && *c != '=' && *c != ',' && !isspace(*c)) {
|
||||
key[i++] = *c++;
|
||||
}
|
||||
key[i] = '\0';
|
||||
c = ast_skip_blanks(c);
|
||||
if (*c == '=') {
|
||||
c = ast_skip_blanks(++c);
|
||||
i = 0;
|
||||
if (*c == '\"') {
|
||||
/* in quotes. Skip first and look for last */
|
||||
c++;
|
||||
while (*c && *c != '\"') {
|
||||
if (*c == '\\' && c[1] != '\0') { /* unescape chars */
|
||||
c++;
|
||||
}
|
||||
val[i++] = *c++;
|
||||
}
|
||||
} else {
|
||||
/* token */
|
||||
while (*c && *c != ',' && !isspace(*c)) {
|
||||
val[i++] = *c++;
|
||||
}
|
||||
}
|
||||
val[i] = '\0';
|
||||
}
|
||||
|
||||
while (*c && *c != ',') {
|
||||
c++;
|
||||
}
|
||||
if (*c) {
|
||||
c++;
|
||||
}
|
||||
|
||||
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")) {
|
||||
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")) {
|
||||
unsigned long u;
|
||||
if (sscanf(val, "%lx", &u) != 1) {
|
||||
ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", val);
|
||||
return -1;
|
||||
}
|
||||
ast_string_field_set(d, nc, val);
|
||||
}
|
||||
}
|
||||
ast_free(str);
|
||||
|
||||
/* Digest checkout */
|
||||
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 (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __AST_DEBUG_MALLOC
|
||||
int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
|
||||
{
|
||||
|
Reference in New Issue
Block a user