diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2009-04-23 20:36:35 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2009-04-23 20:36:35 +0000 |
commit | ce6ebaef9712ef2f5d4cd6a717f13906f70364b7 (patch) | |
tree | a9289da90accc4137203d99a5205aae4d8ed7edb /res | |
parent | 80b8d3437717ec52af9eed3988ec07b7d6a5793b (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: https://origsvn.digium.com/svn/asterisk/trunk@190349 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res')
-rw-r--r-- | res/res_http_post.c | 88 | ||||
-rw-r--r-- | res/res_phoneprov.c | 91 |
2 files changed, 74 insertions, 105 deletions
diff --git a/res/res_http_post.c b/res/res_http_post.c index 9c8e06de5..74e249b33 100644 --- a/res/res_http_post.c +++ b/res/res_http_post.c @@ -156,7 +156,6 @@ static int process_message(GMimeMessage *message, const char *post_dir) return cbinfo.count; } - /* Find a sequence of bytes within a binary array. */ static int find_sequence(char * inbuf, int inlen, char * matchbuf, int matchlen) { @@ -292,10 +291,9 @@ static int readmimefile(FILE * fin, FILE * fout, char * boundary, int contentlen return 0; } - -static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength) +static int http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers) { - struct ast_variable *var; + struct ast_variable *var, *cookies; unsigned long ident = 0; FILE *f; int content_len = 0; @@ -304,41 +302,45 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se int message_count = 0; char * boundary_marker = NULL; - if (!urih) { - return ast_http_error((*status = 400), - (*title = ast_strdup("Missing URI handle")), - NULL, "There was an error parsing the request"); + if (method != AST_HTTP_POST) { + ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); + return -1; } - for (var = vars; var; var = var->next) { - if (strcasecmp(var->name, "mansession_id")) { - continue; - } + if (!astman_is_authed(ast_http_manid_from_vars(headers))) { + ast_http_error(ser, 403, "Access Denied", "Sorry, I cannot let you do that, Dave."); + return -1; + } - if (sscanf(var->value, "%lx", &ident) != 1) { - return ast_http_error((*status = 400), - (*title = ast_strdup("Bad Request")), - NULL, "The was an error parsing the request."); - } + if (!urih) { + ast_http_error(ser, 400, "Missing URI handle", "There was an error parsing the request"); + return -1; + } - if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) { - return ast_http_error((*status = 401), - (*title = ast_strdup("Unauthorized")), - NULL, "You are not authorized to make this request."); + cookies = ast_http_get_cookies(headers); + for (var = cookies; var; var = var->next) { + if (!strcasecmp(var->name, "mansession_id")) { + sscanf(var->value, "%lx", &ident); + break; } - - break; + } + if (cookies) { + ast_variables_destroy(cookies); } - if (!var) { - return ast_http_error((*status = 401), - (*title = ast_strdup("Unauthorized")), - NULL, "You are not authorized to make this request."); + if (ident == 0) { + ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request."); + return -1; + } + if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) { + ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request."); + return -1; } if (!(f = tmpfile())) { ast_log(LOG_ERROR, "Could not create temp file.\n"); - return NULL; + ast_http_error(ser, 500, "Internal server error", "Could not create temp file."); + return -1; } for (var = headers; var; var = var->next) { @@ -348,8 +350,8 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se if ((sscanf(var->value, "%u", &content_len)) != 1) { ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n"); fclose(f); - - return NULL; + ast_http_error(ser, 500, "Internal server error", "Invalid Content-Length in POST request!"); + return -1; } ast_debug(1, "Got a Content-Length of %d\n", content_len); } else if (!strcasecmp(var->name, "Content-Type")) { @@ -367,15 +369,15 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se ast_log(LOG_DEBUG, "Cannot find boundary marker in POST request.\n"); } fclose(f); - - return NULL; + + return -1; } if (fseek(f, SEEK_SET, 0)) { ast_log(LOG_ERROR, "Failed to seek temp file back to beginning.\n"); fclose(f); - - return NULL; + ast_http_error(ser, 500, "Internal server error", "Failed to seek temp file back to beginning."); + return -1; } post_dir = urih->data; @@ -385,24 +387,20 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se if (!message) { ast_log(LOG_ERROR, "Error parsing MIME data\n"); - return ast_http_error((*status = 400), - (*title = ast_strdup("Bad Request")), - NULL, "The was an error parsing the request."); + ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request."); + return -1; } if (!(message_count = process_message(message, ast_str_buffer(post_dir)))) { ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n"); g_object_unref(message); - return ast_http_error((*status = 400), - (*title = ast_strdup("Bad Request")), - NULL, "The was an error parsing the request."); + ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request."); + return -1; } - g_object_unref(message); - return ast_http_error((*status = 200), - (*title = ast_strdup("OK")), - NULL, "File successfully uploaded."); + ast_http_error(ser, 200, "OK", "File successfully uploaded."); + return 0; } static int __ast_http_post_load(int reload) @@ -450,8 +448,6 @@ static int __ast_http_post_load(int reload) ast_str_set(&ds, 0, "%s/%s", prefix, v->value); urih->data = ds; urih->has_subtree = 0; - urih->supports_get = 0; - urih->supports_post = 1; urih->callback = http_post_callback; urih->key = __FILE__; urih->mallocd = urih->dmallocd = 1; diff --git a/res/res_phoneprov.c b/res/res_phoneprov.c index cbd1eaaa0..2a5d24af7 100644 --- a/res/res_phoneprov.c +++ b/res/res_phoneprov.c @@ -155,19 +155,6 @@ static struct ao2_container *profiles; static struct ao2_container *http_routes; static struct ao2_container *users; -/*! \brief Extensions whose mime types we think we know */ -static struct { - char *ext; - char *mtype; -} mimetypes[] = { - { "png", "image/png" }, - { "xml", "text/xml" }, - { "jpg", "image/jpeg" }, - { "js", "application/x-javascript" }, - { "wav", "audio/x-wav" }, - { "mp3", "audio/mpeg" }, -}; - static char global_server[80] = ""; /*!< Server to substitute into templates */ static char global_serverport[6] = ""; /*!< Server port to substitute into templates */ static char global_default_profile[80] = ""; /*!< Default profile to use if one isn't specified */ @@ -176,22 +163,6 @@ static char global_default_profile[80] = ""; /*!< Default profile to use if one static struct varshead global_variables; static ast_mutex_t globals_lock; -/*! \brief Return mime type based on extension */ -static char *ftype2mtype(const char *ftype) -{ - int x; - - if (ast_strlen_zero(ftype)) - return NULL; - - for (x = 0;x < ARRAY_LEN(mimetypes);x++) { - if (!strcasecmp(ftype, mimetypes[x].ext)) - return mimetypes[x].mtype; - } - - return NULL; -} - /* iface is the interface (e.g. eth0); address is the return value */ static int lookup_iface(const char *iface, struct in_addr *address) { @@ -398,20 +369,24 @@ static void set_timezone_variables(struct varshead *headp, const char *zone) } /*! \brief Callback that is executed everytime an http request is received by this module */ -static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength) +static int phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers) { struct http_route *route; struct http_route search_route = { .uri = uri, }; - struct ast_str *result = ast_str_create(512); + struct ast_str *result; char path[PATH_MAX]; char *file = NULL; int len; int fd; char buf[256]; - struct timeval now = ast_tvnow(); - struct ast_tm tm; + struct ast_str *http_header; + + if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) { + ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); + return -1; + } if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) { goto out404; @@ -434,15 +409,9 @@ static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *se goto out500; } - ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT")); - fprintf(ser->f, "HTTP/1.1 200 OK\r\n" - "Server: Asterisk/%s\r\n" - "Date: %s\r\n" - "Connection: close\r\n" - "Cache-Control: no-cache, no-store\r\n" - "Content-Length: %d\r\n" - "Content-Type: %s\r\n\r\n", - ast_get_version(), buf, len, route->file->mime_type); + http_header = ast_str_create(80); + ast_str_set(&http_header, 0, "Content-type: %s\r\n", + route->file->mime_type); while ((len = read(fd, buf, sizeof(buf))) > 0) { if (fwrite(buf, 1, len, ser->f) != len) { @@ -455,9 +424,10 @@ static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *se } } + ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0); close(fd); route = unref_route(route); - return NULL; + return 0; } else { /* Dynamic file */ int bufsize; char *tmp; @@ -516,33 +486,36 @@ static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *se ast_free(file); } - ast_str_append(&result, 0, - "Content-Type: %s\r\n" - "Content-length: %d\r\n" - "\r\n" - "%s", route->file->mime_type, (int) strlen(tmp), tmp); + ast_str_set(&http_header, 0, "Content-type: %s\r\n", + route->file->mime_type); + if (!(result = ast_str_create(512))) { + ast_log(LOG_ERROR, "Could not create result string!\n"); + if (tmp) { + ast_free(tmp); + } + goto out500; + } + ast_str_append(&result, 0, "%s", tmp); + + ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0); if (tmp) { ast_free(tmp); } route = unref_route(route); - return result; + return 0; } out404: - *status = 404; - *title = strdup("Not Found"); - *contentlength = 0; - return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); + ast_http_error(ser, 404, "Not Found", "Nothing to see here. Move along."); + return -1; out500: route = unref_route(route); - *status = 500; - *title = strdup("Internal Server Error"); - *contentlength = 0; - return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); + ast_http_error(ser, 500, "Internal Error", "An internal error has occured."); + return -1; } /*! \brief Build a route structure and add it to the list of available http routes @@ -656,7 +629,8 @@ static void build_profile(const char *name, struct ast_variable *v) * 3) Default mime type specified in profile * 4) text/plain */ - ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, (S_OR(S_OR(ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); + ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, + (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); if (!strcasecmp(v->name, "static_file")) { ast_string_field_set(pp_file, format, args.filename); @@ -1233,7 +1207,6 @@ static struct ast_http_uri phoneprovuri = { .description = "Asterisk HTTP Phone Provisioning Tool", .uri = "phoneprov", .has_subtree = 1, - .supports_get = 1, .data = NULL, .key = __FILE__, }; |