jcs
/subtext
/amendments
/14
user+session: Implement user authentication
jcs made amendment 14 over 2 years ago
--- session.c Fri Dec 3 10:07:56 2021
+++ session.c Mon Dec 6 10:01:19 2021
@@ -21,6 +21,7 @@
#include "subtext.h"
#include "session.h"
+#include "user.h"
#include "uthread.h"
#include "util.h"
@@ -29,6 +30,7 @@ short nsessions = 0;
char session_tbuf[512];
void session_run(struct uthread *uthread, void *arg);
+short session_login(struct session *s);
struct session *
session_create(char *node, struct node_funcs *node_funcs)
@@ -53,6 +55,25 @@ session_create(char *node, struct node_funcs *node_fun
return session;
}
+void
+session_run(struct uthread *uthread, void *arg)
+{
+ struct session *s = (struct session *)arg;
+
+ session_output(s, "\r\n"
+ "Welcome to %s (%s)\r\n"
+ "\r\n", db->config.name, s->node);
+
+ if (session_login(s) == AUTH_USER_OK)
+ session_output(s, "Welcome, %s\r\n", s->user->username);
+ else
+ session_output(s, "Thanks for playing\r\n");
+
+ for (;;) {
+ uthread_yield();
+ }
+}
+
short
session_output(struct session *session, const char *format, ...)
{
@@ -73,7 +94,6 @@ session_output(struct session *session, const char *fo
memcpy(session->obuf + session->obuflen, session_tbuf, len);
session->obuflen += len;
session->node_funcs->output(session);
- uthread_yield();
return len;
}
@@ -83,7 +103,6 @@ session_output_char(struct session *session, const cha
{
session->obuf[session->obuflen++] = c;
session->node_funcs->output(session);
- uthread_yield();
return 1;
}
@@ -110,7 +129,7 @@ session_input_char(struct session *session)
}
char *
-session_field_input(struct session *session, unsigned short len)
+session_field_input(struct session *session, unsigned short len, char mask)
{
short ilen = 0, ipos = 0, lastlen = 0;
char *field;
@@ -158,7 +177,7 @@ session_field_input(struct session *session, unsigned
ipos++;
ilen++;
field[ipos] = '\0';
- session_output_char(session, c);
+ session_output_char(session, mask ? mask : c);
}
}
@@ -166,22 +185,55 @@ session_field_input(struct session *session, unsigned
return NULL;
}
-void
-session_run(struct uthread *uthread, void *arg)
+short
+session_login(struct session *s)
{
- struct session *s = (struct session *)arg;
- char *line;
+ struct user *user;
+ char junk[SHA256_DIGEST_STRING_LENGTH];
+ char *username;
+ char *password;
+ short n;
+ size_t len;
+
+ for (n = 1; n <= 3; n++) {
+ session_output(s, "login: ");
+ username = session_field_input(s, 32, 0);
+ session_output(s, "\r\n");
- session_output(s, "\r\n"
- "Welcome to %s (%s)\r\n"
- "\r\n", db->config.name, s->node);
+ if (strcmp(username, "guest") == 0) {
+ /* TODO */
+ } else if (strcmp(username, "signup") == 0 ||
+ strcmp(username, "new") == 0) {
+ /* TODO */
+ } else {
+ user = user_find(db, username);
+ }
+
+ session_output(s, "Password: ");
+ password = session_field_input(s, 64, '*');
+ session_output(s, "\r\n");
- session_output(s, "login: ");
- line = session_field_input(s, 50);
- session_output(s, "\r\nHi, %s\r\n", line);
- free(line);
-
- for (;;) {
- uthread_yield();
+ if (user) {
+ if (user_authenticate(db, user, password) == AUTH_USER_OK)
+ s->user = user;
+ } else
+ /* kill some time */
+ SHA256Data((const u_int8_t *)password, strlen(password), junk);
+
+ len = strlen(username);
+ memset(username, 0, len);
+ free(username);
+
+ len = strlen(password);
+ memset(password, 0, len);
+ free(password);
+
+ if (s->user)
+ return AUTH_USER_OK;
+
+ uthread_sleep(60);
+ session_output(s, "Login incorrect\r\n");
}
-}
+
+ return AUTH_USER_FAILED;
+}
--- session.h Tue Nov 30 13:23:40 2021
+++ session.h Sun Dec 5 16:50:30 2021
@@ -47,6 +47,7 @@ struct session {
void *cookie;
struct node_funcs *node_funcs;
struct uthread *uthread;
+ struct user *user;
};
extern struct session **sessions;
@@ -57,6 +58,7 @@ void session_idle(struct session *session);
char session_input_char(struct session *session);
short session_output(struct session *session, const char *format, ...);
short session_output_char(struct session *session, const char c);
-char *session_field_input(struct session *session, unsigned short len);
+char *session_field_input(struct session *session, unsigned short len,
+ char mask);
#endif /* __SESSION_H__ */
--- subtext.h Fri Dec 3 09:58:22 2021
+++ subtext.h Sun Dec 5 22:16:23 2021
@@ -21,16 +21,18 @@
#define PROGRAM_NAME "Subtext"
-#define MBAR_ID 128
+#define MBAR_ID 128
-#define APPLE_MENU_ID 128
-#define APPLE_MENU_ABOUT_ID 1
+#define APPLE_MENU_ID 128
+#define APPLE_MENU_ABOUT_ID 1
-#define FILE_MENU_ID 129
-#define FILE_MENU_QUIT_ID 1
+#define FILE_MENU_ID 129
+#define FILE_MENU_QUIT_ID 1
-extern struct db *db;
+#define STR_LAST_DB 128
+extern struct db *db;
+extern short mainResFile;
extern MenuHandle file_menu;
#endif /* __SUBTEXT_H__ */
--- user.c Sun Dec 5 16:06:29 2021
+++ user.c Sun Dec 5 20:21:25 2021
@@ -206,7 +206,33 @@ user_parse(struct db *tdb, Handle huser)
short
user_authenticate(struct db *tdb, struct user *user, char *password)
{
+ char hash[SHA256_DIGEST_STRING_LENGTH];
+ char *salted;
+ unsigned long tmp[8];
+ size_t plen, slen;
+ short n;
+ unsigned char res;
+
+ plen = strlen(password);
+ slen = SHA256_DIGEST_STRING_LENGTH - 1 + plen;
+ salted = xmalloc(slen);
+ memcpy(salted, user->password_salt, SHA256_DIGEST_STRING_LENGTH - 1);
+ memcpy(salted + SHA256_DIGEST_STRING_LENGTH - 1, password, plen);
+ SHA256Data((const u_int8_t *)salted, slen, hash);
+
+ /* timing-safe comparison */
+ for (res = 0, n = 0; n < SHA256_DIGEST_STRING_LENGTH; n++)
+ res |= (hash[n] ^ user->password_hash[n]);
+
+ memset(&hash, 0, sizeof(hash));
+ memset(salted, 0, slen);
+ free(salted);
+
+ if (res == 0)
+ return AUTH_USER_OK;
+
+ return AUTH_USER_FAILED;
}
void
@@ -216,20 +242,23 @@ user_set_password(struct db *tdb, struct user *user, c
char salt[SHA256_DIGEST_STRING_LENGTH];
char *salted;
unsigned long tmp[8];
- size_t plen;
+ size_t plen, slen;
short n;
+ /* make a random salt out of a sha256 of some random longs */
for (n = 0; n < sizeof(tmp); n++)
tmp[n] = xorshift32();
SHA256Data((const u_int8_t *)tmp, sizeof(tmp), salt);
- memcpy(&user->password_salt, &salt, sizeof(user->password_salt));
-
+ memcpy(&user->password_salt, &salt, sizeof(salt));
+
plen = strlen(password);
- salted = xmalloc(plen + sizeof(salt));
- memcpy(salted, salt, sizeof(salt));
- memcpy(salted + sizeof(salt), password, plen);
- SHA256Data((const u_int8_t *)salted, plen + sizeof(salt), hash);
+ slen = plen + sizeof(salt) - 1;
+ salted = xmalloc(slen);
+ memcpy(salted, salt, sizeof(salt) - 1); /* exclude null */
+ memcpy(salted + sizeof(salt) - 1, password, plen);
+ SHA256Data((const u_int8_t *)salted, slen, hash);
+ memset(salted, 0, slen);
free(salted);
memcpy(&user->password_hash, &hash, sizeof(user->password_hash));