From 9ffc5197fb90f2014fbe30026c6064827ff98008 Mon Sep 17 00:00:00 2001 From: Nicolas Favre-Felix Date: Sat, 22 Jan 2011 22:21:47 +0100 Subject: [PATCH] Fix ACLs --- acl.c | 14 ++++++-------- acl.h | 6 +++--- cmd.c | 6 ++---- http.c | 20 +++++++++++++++++++- http.h | 6 ++++++ server.c | 6 +----- 6 files changed, 37 insertions(+), 21 deletions(-) diff --git a/acl.c b/acl.c index 34db0bf..6eeeb3c 100644 --- a/acl.c +++ b/acl.c @@ -1,6 +1,7 @@ #include "acl.h" #include "cmd.h" #include "conf.h" +#include "http.h" #include #include @@ -8,11 +9,11 @@ #include int -acl_match_client(struct acl *a, struct evhttp_request *rq, in_addr_t *ip) { +acl_match_client(struct acl *a, struct http_client *client, in_addr_t *ip) { /* check HTTP Basic Auth */ const char *auth; - auth = evhttp_find_header(rq->input_headers, "Authorization"); + auth = client->header_authorization.s; if(auth && a->http_basic_auth && strncasecmp(auth, "Basic ", 6) == 0) { /* sent auth */ if(strcmp(auth + 6, a->http_basic_auth) != 0) { /* wrong */ return 0; @@ -31,7 +32,7 @@ acl_match_client(struct acl *a, struct evhttp_request *rq, in_addr_t *ip) { } int -acl_allow_command(struct cmd *cmd, struct conf *cfg, struct evhttp_request *rq) { +acl_allow_command(struct cmd *cmd, struct conf *cfg, struct http_client *client) { char *always_off[] = {"MULTI", "EXEC", "WATCH", "DISCARD"}; @@ -39,8 +40,6 @@ acl_allow_command(struct cmd *cmd, struct conf *cfg, struct evhttp_request *rq) int authorized = 1; struct acl *a; - char *client_ip; - u_short client_port; in_addr_t client_addr; const char *cmd_name = cmd->argv[0]; @@ -54,13 +53,12 @@ acl_allow_command(struct cmd *cmd, struct conf *cfg, struct evhttp_request *rq) } /* find client's address */ - evhttp_connection_get_peer(rq->evcon, &client_ip, &client_port); - client_addr = ntohl(inet_addr(client_ip)); + client_addr = ntohl(client->addr); /* go through permissions */ for(a = cfg->perms; a; a = a->next) { - if(!acl_match_client(a, rq, &client_addr)) continue; /* match client */ + if(!acl_match_client(a, client, &client_addr)) continue; /* match client */ /* go through authorized commands */ for(i = 0; i < a->enabled.count; ++i) { diff --git a/acl.h b/acl.h index f8770da..2b68b93 100644 --- a/acl.h +++ b/acl.h @@ -3,7 +3,7 @@ #include -struct evhttp_request; +struct http_client; struct cmd; struct conf; @@ -31,9 +31,9 @@ struct acl { }; int -acl_match_client(struct acl *a, struct evhttp_request *rq, in_addr_t *ip); +acl_match_client(struct acl *a, struct http_client *client, in_addr_t *ip); int -acl_allow_command(struct cmd *cmd, struct conf *cfg, struct evhttp_request *rq); +acl_allow_command(struct cmd *cmd, struct conf *cfg, struct http_client *client); #endif diff --git a/cmd.c b/cmd.c index e671f97..32ffa3d 100644 --- a/cmd.c +++ b/cmd.c @@ -131,12 +131,10 @@ cmd_run(struct server *s, struct http_client *client, cmd->argv_len[0] = cmd_len; - /* FIXME: check that the client is able to run this command */ - /* - if(!acl_allow_command(cmd, s->cfg, rq)) { + /* check that the client is able to run this command */ + if(!acl_allow_command(cmd, s->cfg, client)) { return -1; } - */ /* FIXME:check if we have to split the connection */ /* diff --git a/http.c b/http.c index 4f64031..fd16722 100644 --- a/http.c +++ b/http.c @@ -77,6 +77,9 @@ http_client_cleanup(struct http_client *c) { free(c->header_if_none_match.s); memset(&c->header_if_none_match, 0, sizeof(str_t)); + free(c->header_authorization.s); + memset(&c->header_authorization, 0, sizeof(str_t)); + free(c->out_content_type.s); memset(&c->out_content_type, 0, sizeof(str_t)); @@ -256,12 +259,23 @@ http_on_complete(http_parser *p) { default: slog(c->s, WEBDIS_DEBUG, "405"); - /* evhttp_send_reply(rq, 405, "Method Not Allowed", NULL); */ + http_send_error(c, 405, "Method Not Allowed"); return 0; } + + if(ret < 0) { + http_send_error(c, 403, "Forbidden"); + } + return ret; } +void +http_send_error(struct http_client *c, short code, const char *msg) { + + http_send_reply(c, code, msg, NULL, 0); +} + void http_send_reply(struct http_client *c, short code, const char *msg, const char *body, size_t body_len) { @@ -345,6 +359,10 @@ http_on_header_value(http_parser *p, const char *at, size_t length) { c->header_if_none_match.s = calloc(length+1, 1); memcpy(c->header_if_none_match.s, at, length); c->header_if_none_match.sz = length; + } else if(strncmp("Authorization", c->last_header_name.s, c->last_header_name.sz) == 0) { + c->header_authorization.s = calloc(length+1, 1); + memcpy(c->header_authorization.s, at, length); + c->header_authorization.sz = length; } free(c->last_header_name.s); diff --git a/http.h b/http.h index cd5434b..7256cfc 100644 --- a/http.h +++ b/http.h @@ -2,6 +2,7 @@ #define HTTP_H #include +#include #include "http-parser/http_parser.h" typedef struct { @@ -13,6 +14,7 @@ struct http_client { /* socket and server reference */ int fd; + in_addr_t addr; struct event ev; struct server *s; int executing; @@ -31,6 +33,7 @@ struct http_client { str_t body; str_t header_connection; str_t header_if_none_match; + str_t header_authorization; /* response headers */ str_t out_content_type; @@ -92,6 +95,9 @@ void http_send_reply(struct http_client *c, short code, const char *msg, const char *body, size_t body_len); +void +http_send_error(struct http_client *c, short code, const char *msg); + /* HTTP response */ void http_response_init(struct http_response *r, int code, const char *msg); diff --git a/server.c b/server.c index ee10088..091b97c 100644 --- a/server.c +++ b/server.c @@ -169,6 +169,7 @@ on_possible_accept(int fd, short event, void *ctx) { client_fd = accept(fd, (struct sockaddr*)&addr, &addr_sz); c = http_client_new(client_fd, s); + c->addr = addr.sin_addr.s_addr; http_client_serve(c); } @@ -189,11 +190,6 @@ server_start(struct server *s) { event_base_set(s->base, &s->ev); event_add(&s->ev, NULL); - /* - evhttp_set_cb(s->http, "/crossdomain.xml", on_flash_request, s); - evhttp_set_gencb(s->http, on_request, s); - */ - /* drop privileges */ slog(s, WEBDIS_INFO, "Dropping Privileges"); setuid(s->cfg->user);