From: Felix Fietkau Date: Wed, 2 Jan 2013 13:47:12 +0000 (+0100) Subject: add auth support X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuhttpd.git;a=commitdiff_plain;h=76f5d84671a258274b0b647d234431ad70b4553e add auth support --- diff --git a/auth.c b/auth.c index 05bec66..c27488f 100644 --- a/auth.c +++ b/auth.c @@ -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; +} diff --git a/file.c b/file.c index 4a10eaa..62c8ee7 100644 --- a/file.c +++ b/file.c @@ -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; } diff --git a/uhttpd.h b/uhttpd.h index e1d061f..cb56fcd 100644 --- a/uhttpd.h +++ b/uhttpd.h @@ -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);