diff options
author | John Ankarström <john@ankarstrom.se> | 2021-09-20 22:07:51 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2021-09-20 22:07:51 +0200 |
commit | 3ea978c60ee03dba2cb883ba18d3b334cfbf6cd0 (patch) | |
tree | 6a3de0d664f261f7ae1ab57d35e7d2f37acc673b | |
parent | fd9e2f7245212f2b652652f4669648260e59f9e9 (diff) | |
download | cforum-3ea978c60ee03dba2cb883ba18d3b334cfbf6cd0.tar.gz |
Implement login
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README | 10 | ||||
-rw-r--r-- | cforum.c | 2 | ||||
-rw-r--r-- | cforum.h | 5 | ||||
-rw-r--r-- | ctl.c | 91 | ||||
-rw-r--r-- | db.c | 3 | ||||
-rw-r--r-- | t/front.t | 1 |
7 files changed, 91 insertions, 23 deletions
@@ -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!');" @@ -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 @@ -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(); @@ -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 @@ -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 @@ -64,6 +51,84 @@ 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() { char *captcha, *confirm, *name, *full, *pass; @@ -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; } @@ -2,6 +2,7 @@ <h1><%= site.name %></h1> <ul> <li><a href="?new=user">Sign up</a></li> + <li><a href="?new=session">Log in</a></li> </ul> <h3>Latest posts</h3> <table border="1"> |