diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-04-23 20:36:35 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-04-23 20:36:35 +0000 |
commit | 23d5f93d74c885df5a8feee25229d68576b394d3 (patch) | |
tree | a9289da90accc4137203d99a5205aae4d8ed7edb /main/utils.c | |
parent | c052997dcc8db29dd063ab6eeb2bfa3be1f4ae96 (diff) |
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: http://svn.digium.com/svn/asterisk/trunk@190349 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/utils.c')
-rw-r--r-- | main/utils.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/main/utils.c b/main/utils.c index 60da56250..57ea0566d 100644 --- a/main/utils.c +++ b/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, ...) { |