summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorTilghman Lesher <tilghman@meg.abyt.es>2009-04-23 20:36:35 +0000
committerTilghman Lesher <tilghman@meg.abyt.es>2009-04-23 20:36:35 +0000
commitce6ebaef9712ef2f5d4cd6a717f13906f70364b7 (patch)
treea9289da90accc4137203d99a5205aae4d8ed7edb /res
parent80b8d3437717ec52af9eed3988ec07b7d6a5793b (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.c88
-rw-r--r--res/res_phoneprov.c91
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__,
};