diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-01-02 14:47:12 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2013-01-02 14:47:12 +0100 |
commit | 76f5d84671a258274b0b647d234431ad70b4553e (patch) | |
tree | 353f16cc576f23bd559a2390dd505eb0b4eba6a5 | |
parent | d0aab7b1fc7c94c3d6d41990e7615be85b58e640 (diff) |
add auth support
-rw-r--r-- | auth.c | 59 | ||||
-rw-r--r-- | file.c | 48 | ||||
-rw-r--r-- | uhttpd.h | 2 |
3 files changed, 88 insertions, 21 deletions
@@ -66,3 +66,62 @@ void uh_auth_add(const char *path, const char *user, const char *pass) new->pass = strcpy(dest_pass, new_pass); list_add(&new->list, &auth_realms); } + +bool uh_auth_check(struct client *cl, struct path_info *pi) +{ + struct http_request *req = &cl->request; + struct auth_realm *realm; + bool user_match = false; + char *user = NULL; + char *pass = NULL; + int plen; + + if (pi->auth && !strncasecmp(pi->auth, "Basic ", 6)) { + const char *auth = pi->auth + 6; + + uh_b64decode(uh_buf, sizeof(uh_buf), auth, strlen(auth)); + pass = strchr(uh_buf, ':'); + if (pass) { + user = uh_buf; + *pass++ = 0; + } + } + + req->realm = NULL; + plen = strlen(pi->name); + list_for_each_entry(realm, &auth_realms, list) { + int rlen = strlen(realm->path); + + if (plen < rlen) + continue; + + if (strncasecmp(pi->name, realm->path, rlen) != 0) + continue; + + req->realm = realm; + if (!user) + break; + + if (strcmp(user, realm->user) != 0) + continue; + + user_match = true; + break; + } + + if (!req->realm) + return true; + + if (user_match && !strcmp(crypt(pass, realm->pass), realm->pass)) + return true; + + uh_http_header(cl, 401, "Authorization Required"); + ustream_printf(cl->us, + "WWW-Authenticate: Basic realm=\"%s\"\r\n" + "Content-Type: text/plain\r\n\r\n", + conf.realm); + uh_chunk_printf(cl, "Authorization Required\n"); + uh_request_done(cl); + + return false; +} @@ -40,6 +40,7 @@ struct index_file { }; enum file_hdr { + HDR_AUTHORIZATION, HDR_IF_MODIFIED_SINCE, HDR_IF_UNMODIFIED_SINCE, HDR_IF_MATCH, @@ -578,22 +579,11 @@ static void uh_file_data(struct client *cl, struct path_info *pi, int fd) file_write_cb(cl); } -static void uh_file_request(struct client *cl, const char *url, struct path_info *pi) +static void uh_file_request(struct client *cl, const char *url, + struct path_info *pi, struct blob_attr **tb) { - static const struct blobmsg_policy hdr_policy[__HDR_MAX] = { - [HDR_IF_MODIFIED_SINCE] = { "if-modified-since", BLOBMSG_TYPE_STRING }, - [HDR_IF_UNMODIFIED_SINCE] = { "if-unmodified-since", BLOBMSG_TYPE_STRING }, - [HDR_IF_MATCH] = { "if-match", BLOBMSG_TYPE_STRING }, - [HDR_IF_NONE_MATCH] = { "if-none-match", BLOBMSG_TYPE_STRING }, - [HDR_IF_RANGE] = { "if-range", BLOBMSG_TYPE_STRING }, - }; - struct blob_attr *tb[__HDR_MAX]; int fd; - blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head)); - - cl->dispatch.file.hdr = tb; - if (!(pi->stat.st_mode & S_IROTH)) goto error; @@ -602,24 +592,24 @@ static void uh_file_request(struct client *cl, const char *url, struct path_info if (fd < 0) goto error; + cl->dispatch.file.hdr = tb; uh_file_data(cl, pi, fd); - } else if ((pi->stat.st_mode & S_IFDIR)) { + cl->dispatch.file.hdr = NULL; + return; + } + + if ((pi->stat.st_mode & S_IFDIR)) { if (conf.no_dirlists) goto error; uh_file_dirlist(cl, pi); - } else { - goto error; + return; } - cl->dispatch.file.hdr = NULL; - return; - error: uh_client_error(cl, 403, "Forbidden", "You don't have permission to access %s on this server.", url); - cl->dispatch.file.hdr = NULL; } void uh_dispatch_add(struct dispatch_handler *d) @@ -653,7 +643,16 @@ dispatch_find(const char *url, struct path_info *pi) static bool __handle_file_request(struct client *cl, const char *url) { + static const struct blobmsg_policy hdr_policy[__HDR_MAX] = { + [HDR_AUTHORIZATION] = { "authorization", BLOBMSG_TYPE_STRING }, + [HDR_IF_MODIFIED_SINCE] = { "if-modified-since", BLOBMSG_TYPE_STRING }, + [HDR_IF_UNMODIFIED_SINCE] = { "if-unmodified-since", BLOBMSG_TYPE_STRING }, + [HDR_IF_MATCH] = { "if-match", BLOBMSG_TYPE_STRING }, + [HDR_IF_NONE_MATCH] = { "if-none-match", BLOBMSG_TYPE_STRING }, + [HDR_IF_RANGE] = { "if-range", BLOBMSG_TYPE_STRING }, + }; struct dispatch_handler *d; + struct blob_attr *tb[__HDR_MAX]; struct path_info *pi; pi = uh_path_lookup(cl, url); @@ -663,11 +662,18 @@ static bool __handle_file_request(struct client *cl, const char *url) if (pi->redirected) return true; + blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head)); + if (tb[HDR_AUTHORIZATION]) + pi->auth = blobmsg_data(tb[HDR_AUTHORIZATION]); + + if (!uh_auth_check(cl, pi)) + return true; + d = dispatch_find(url, pi); if (d) d->handle_request(cl, url, pi); else - uh_file_request(cl, url, pi); + uh_file_request(cl, url, pi, tb); return true; } @@ -103,6 +103,7 @@ struct path_info { const char *name; const char *info; const char *query; + const char *auth; bool redirected; struct stat stat; const struct interpreter *ip; @@ -213,6 +214,7 @@ uh_client_error(struct client *cl, int code, const char *summary, const char *fm void uh_handle_request(struct client *cl); void uh_auth_add(const char *path, const char *user, const char *pass); +bool uh_auth_check(struct client *cl, struct path_info *pi); void uh_close_listen_fds(void); void uh_close_fds(void); |