summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth.c59
-rw-r--r--file.c48
-rw-r--r--uhttpd.h2
3 files changed, 88 insertions, 21 deletions
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);