summaryrefslogtreecommitdiff
path: root/src/user
diff options
context:
space:
mode:
authordzwdz2022-08-24 15:49:55 +0200
committerdzwdz2022-08-24 15:49:55 +0200
commita805325980aa434739ed1c0f62836296ef098be4 (patch)
treea51a099a7185bc4644b08a37535e06af6eb2338e /src/user
parent7944d21846ef288fee087159cb244897d5fff4ba (diff)
user/httpd
Diffstat (limited to 'src/user')
-rw-r--r--src/user/app/httpd/httpd.c80
-rw-r--r--src/user/app/netstack/fs.c12
2 files changed, 89 insertions, 3 deletions
diff --git a/src/user/app/httpd/httpd.c b/src/user/app/httpd/httpd.c
new file mode 100644
index 0000000..1aaebc5
--- /dev/null
+++ b/src/user/app/httpd/httpd.c
@@ -0,0 +1,80 @@
+/* garbage httpd, just to see if it works
+ * easily DoSable (like the rest of the network stack), vulnerable to path traversal, etc */
+#include <camellia/flags.h>
+#include <camellia/syscalls.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define eprintf(fmt, ...) fprintf(stderr, "httpd: "fmt"\n" __VA_OPT__(,) __VA_ARGS__)
+
+static void handle(FILE *c) {
+ char buf[2048];
+ fgets(buf, sizeof buf, c);
+ printf("%s", buf);
+
+ if (memcmp(buf, "GET /", 5) != 0) {
+ fprintf(c, "HTTP/1.1 400 Bad Request\r\n\r\n");
+ return;
+ }
+ char *path = buf + 4;
+ char *end = strchr(path, ' ');
+ if (end) *end = '\0';
+
+ handle_t h = _syscall_open(path, strlen(path), OPEN_RO);
+ if (h < 0) {
+ fprintf(c, "HTTP/1.1 404 Not Found\r\n\r\n");
+ return;
+ }
+ FILE *f = fdopen(h, "r");
+ if (!f) {
+ fprintf(c, "HTTP/1.1 500 Internal Server Error\r\n\r\n");
+ return;
+ }
+
+ if (path[strlen(path) - 1] != '/') {
+ /* regular file */
+ fprintf(c, "HTTP/1.1 200 OK\r\n");
+ fprintf(c, "\r\n");
+ for (;;) {
+ int len = fread(buf, 1, sizeof buf, f);
+ if (len <= 0) break;
+ fwrite(buf, 1, len, c);
+ }
+ } else {
+ /* directory listing */
+ fprintf(c, "HTTP/1.1 200 OK\r\n");
+ fprintf(c, "Content-Type: text/html; charset=UTF-8\r\n");
+ fprintf(c, "\r\n");
+ fprintf(c, "<h1>directory listing for %s</h1><hr><ul><li><a href=..>..</a></li>", path);
+ for (;;) {
+ int len = fread(buf, 1, sizeof buf, f);
+ if (len <= 0) break;
+ // TODO directory library
+ // based on find.c
+ for (int pos = 0; pos < len; ) {
+ if (buf[pos] == '\0') break;
+ const char *end = memchr(buf + pos, 0, len - pos);
+ if (!end) break;
+ fprintf(c, "<li><a href=\"%s\">%s</a></li>", buf + pos, buf + pos);
+ pos += end - (buf + pos) + 1;
+ }
+ }
+ }
+ fclose(f);
+}
+
+int main(int argc, char **argv) {
+ const char *path = (argc > 1) ? argv[1] : "/net/0.0.0.0/listen/tcp/80";
+ handle_t conn;
+ for (;;) {
+ conn = _syscall_open(path, strlen(path), 0);
+ if (conn < 0) {
+ eprintf("open('%s') failed, %d", path, conn);
+ return 1;
+ }
+ FILE *f = fdopen(conn, "a+");
+ handle(f);
+ fclose(f);
+ }
+}
diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c
index f4d9625..9f40ef8 100644
--- a/src/user/app/netstack/fs.c
+++ b/src/user/app/netstack/fs.c
@@ -12,6 +12,7 @@
*/
#include "proto.h"
#include "util.h"
+#include <camellia/flags.h>
#include <camellia/syscalls.h>
#include <errno.h>
#include <stdio.h>
@@ -58,7 +59,9 @@ static void tcp_recv_callback(void *arg) {
struct handle *h = arg;
char buf[1024];
if (h->reqh >= 0) {
- size_t len = tcpc_tryread(h->tcp.c, buf, sizeof buf);
+ if (h->tcp.readcap > sizeof buf)
+ h->tcp.readcap = sizeof buf;
+ size_t len = tcpc_tryread(h->tcp.c, buf, h->tcp.readcap);
if (len > 0) {
_syscall_fs_respond(h->reqh, buf, len, 0);
h->reqh = -1;
@@ -122,7 +125,7 @@ static void recv_enqueue(struct handle *h, handle_t reqh, size_t readcap) {
}
}
-static void fs_open(handle_t reqh, char *path) {
+static void fs_open(handle_t reqh, char *path, int flags) {
#define respond(buf, val) do{ _syscall_fs_respond(reqh, buf, val, 0); return; }while(0)
struct handle *h;
if (*path != '/') respond(NULL, -1);
@@ -140,6 +143,9 @@ static void fs_open(handle_t reqh, char *path) {
respond(h, 0);
}
+ /* everything below ends up sending packets */
+ if (flags & OPEN_RO) respond(NULL, -EACCES);
+
char *save;
const char *verb, *proto, *port_s;
@@ -241,7 +247,7 @@ void fs_thread(void *arg) { (void)arg;
case VFSOP_OPEN:
if (res.len < buflen) {
buf[res.len] = '\0';
- fs_open(reqh, buf);
+ fs_open(reqh, buf, res.flags);
} else {
_syscall_fs_respond(reqh, NULL, -1, 0);
}