From 3ea978c60ee03dba2cb883ba18d3b334cfbf6cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 20 Sep 2021 22:07:51 +0200 Subject: Implement login --- Makefile | 2 +- README | 10 +++---- cforum.c | 2 +- cforum.h | 5 ++-- ctl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- db.c | 3 ++- t/front.t | 1 + 7 files changed, 91 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 6890d52..f6f78ac 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ db: sqlite3 db "CREATE TABLE settings(key, value, PRIMARY KEY (key));" sqlite3 db "INSERT INTO settings values('name', 'C Forum');" sqlite3 db "CREATE TABLE users(name, full, hash NOT NULL, salt NOT NULL, created INT NOT NULL, PRIMARY KEY (name));" - sqlite3 db "INSERT INTO users values('john', 'John Ankarström', '$$2b$$10$$...v8J996R...KGui.D3H.4K7ZLj0/fl9LcenV71fja/drdObqxZK', '$$2b$$10$$...v8J996R...KGui.D3H.', 1462134896);" + sqlite3 db "INSERT INTO users values('john', 'John Ankarström', '\$$2b\$$10\$$...v8J996R...KGui.D3H.4K7ZLj0/fl9LcenV71fja/drdObqxZK', '\$$2b\$$10\$$...v8J996R...KGui.D3H.', 1462134896);" sqlite3 db "CREATE TABLE posts(parent INT, user INT NOT NULL, created INT NOT NULL, edited INT, subject NOT NULL, text NOT NULL, FOREIGN KEY (user) REFERENCES users(oid));" sqlite3 db "INSERT INTO posts values(NULL, 1, 1462137896, NULL, 'Hello World!', 'This is the first post.');" sqlite3 db "INSERT INTO posts values(1, 1, 1462138896, NULL, 'Re: Hello World!', 'This is the second post!');" diff --git a/README b/README index 6f2e572..e84f8a4 100644 --- a/README +++ b/README @@ -9,11 +9,11 @@ It is also rather small: wc -l *.c *.h crypt/*.c crypt/*.h */*.t */*.lex 97 cforum.c - 316 ctl.c - 305 db.c + 381 ctl.c + 306 db.c 11 err.c 144 query.c - 100 cforum.h + 101 cforum.h 907 crypt/crypt_blowfish.c 124 crypt/crypt_gensalt.c 551 crypt/wrapper.c @@ -23,11 +23,11 @@ It is also rather small: 43 crypt/ow-crypt.h 3 t/err.t 1 t/foot.t - 29 t/front.t + 30 t/front.t 15 t/head.t 18 t/login.t 38 t/newuser.t 28 t/post.t 12 t/user.t 95 mktpl/mktpl.lex - 2918 total + 2986 total diff --git a/cforum.c b/cforum.c index c3b0b26..b536827 100644 --- a/cforum.c +++ b/cforum.c @@ -87,7 +87,7 @@ main(int argc, char *argv[]) if(strcmp(v, "att") == 0) newatt(); else if(strcmp(v, "post") == 0) newpost(); else if(strcmp(v, "user") == 0) newuser(); - else if(strcmp(v, "session") == 0) login(); + else if(strcmp(v, "session") == 0) newsession(); else showfront(); /* TODO */ }else showfront(); diff --git a/cforum.h b/cforum.h index a7572e2..7d7dc60 100644 --- a/cforum.h +++ b/cforum.h @@ -49,9 +49,9 @@ struct site{ /***** Functions *****/ /* ctl.c */ -void login(void); void newatt(void); void newpost(void); +void newsession(void); void newuser(void); void showatt(int); void showfront(void); @@ -86,8 +86,9 @@ int urldecode(char *, int); /* Maximum allowed Content-Length for various forms. */ #define MAXATTDATA 4096 -#define MAXUSERDATA 512 #define MAXPOSTDATA 4096 +#define MAXSESSIONDATA 512 +#define MAXUSERDATA 512 /* Maximum size of user information, incl. NUL. */ #define MAXUSERNAME 40 diff --git a/ctl.c b/ctl.c index cd90f4f..9583c44 100644 --- a/ctl.c +++ b/ctl.c @@ -37,19 +37,6 @@ printhtml(char *s) } } -void -login() -{ - char *hlite, msg[MAXMSG], *name; - char title[] = "Log In"; - - *msg = 0; - hlite = name = NULL; - - printf("Content-Type: text/html\n\n"); - #include "t/login.tc" -} - /* * The `new' functions provide a way to add a new attachment/post/user. * On GET, they show a form. On POST, they insert the posted information @@ -63,6 +50,84 @@ void newpost() {} +void +newsession() +{ + char *hlite, msg[MAXMSG], *p, *v; + char *name, *pass, *remember; + char title[] = "Log In"; + struct user *user; + sqlite3_stmt *stmt; + + *msg = 0; + hlite = name = pass = remember = NULL; + + if(query.method == GET){ + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" + return; + } + + if(query.length > MAXSESSIONDATA){ + snprintf(msg, MAXMSG, "Input exceeded server limitations"); + printf("Status: 431 Request Header Fields Too Large\n"); + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" + return; + } + + while(p = nextparam(POST, NULL, MAXSESSIONDATA)){ + if(!(v = split(p))) continue; + + if(!name && strcmp(p, "name") == 0) + name = strdup(v); + else if(!pass && strcmp(p, "pass") == 0) + pass = strdup(v); + else if(!remember && strcmp(p, "remember") == 0) + remember = strdup(v); + else + continue; + } + + if(!name || !*name){ + snprintf(msg, MAXMSG, "Username may not be empty"); + printf("Status: 400 Bad Request\n"); + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" + return; + } + + if(sqlite3_prepare(db, "SELECT oid, * from users WHERE name = ?", + -1, &stmt, 0) != SQLITE_OK) + goto fail; + + if(sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC) != SQLITE_OK) + goto dberr; + + if(!(user = getuser(stmt))) + goto fail; + + if(!haspass(user, pass)) + goto fail; + + printf("Content-Type: text/plain\n\n"); + printf("Success!\n"); + return; + +dberr: + snprintf(msg, MAXMSG, "Could not retrieve user: %s", + sqlite3_errmsg(db)); + printf("Status: 500 Internal Server Errror\n"); + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" + return; +fail: + snprintf(msg, MAXMSG, "Invalid username or password"); + printf("Status: 400 Bad Request\n"); + printf("Content-Type: text/html\n\n"); + #include "t/login.tc" +} + void newuser() { diff --git a/db.c b/db.c index 30c255b..4b1b234 100644 --- a/db.c +++ b/db.c @@ -271,7 +271,8 @@ nextuser(sqlite3_stmt *stmt) user->name = strdupn(sqlite3_column_text(stmt, 1)); user->full = strdupn(sqlite3_column_text(stmt, 2)); user->hash = strdupn(sqlite3_column_text(stmt, 3)); - user->created = sqlite3_column_int(stmt, 4); + user->salt = strdupn(sqlite3_column_text(stmt, 4)); + user->created = sqlite3_column_int(stmt, 5); return user; } diff --git a/t/front.t b/t/front.t index 2662be2..4f94a9b 100644 --- a/t/front.t +++ b/t/front.t @@ -2,6 +2,7 @@

<%= site.name %>

Latest posts

-- cgit v1.2.3