summaryrefslogtreecommitdiff
path: root/authfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'authfile.c')
-rw-r--r--authfile.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/authfile.c b/authfile.c
new file mode 100644
index 0000000..1468958
--- /dev/null
+++ b/authfile.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "authfile.h"
+
+// TODO: frontend needs a refactor so this can avoid global objects.
+
+#define MAX_ENTRY_LEN 256
+// Not supposed to be a huge database!
+#define MAX_ENTRIES 8
+
+typedef struct auth_entry {
+ char *user;
+ size_t ulen;
+ char *pass;
+ size_t plen;
+} auth_t;
+
+auth_t main_auth_entries[MAX_ENTRIES];
+int entry_cnt = 0;
+char *main_auth_data = NULL;
+
+enum authfile_ret authfile_load(const char *file) {
+ struct stat sb;
+ char *auth_data = NULL;
+ auth_t auth_entries[MAX_ENTRIES];
+
+ if (stat(file, &sb) == -1) {
+ return AUTHFILE_MISSING;
+ }
+
+ auth_data = calloc(1, sb.st_size);
+
+ if (auth_data == NULL) {
+ return AUTHFILE_OOM;
+ }
+
+ FILE *pwfile = fopen(file, "r");
+ if (pwfile == NULL) {
+ // not strictly necessary but to be safe.
+ free(auth_data);
+ return AUTHFILE_OPENFAIL;
+ }
+
+ char *auth_cur = auth_data;
+ auth_t *entry_cur = auth_entries;
+ int used = 0;
+
+ while ((fgets(auth_cur, MAX_ENTRY_LEN, pwfile)) != NULL) {
+ int x;
+ int found = 0;
+
+ for (x = 0; x < MAX_ENTRY_LEN; x++) {
+ if (!found && auth_cur[x] == ':') {
+ entry_cur->user = auth_cur;
+ entry_cur->ulen = x;
+ entry_cur->pass = &auth_cur[x+1];
+ found = 1;
+ } else if (found) {
+ // Find end of password.
+ if (auth_cur[x] == '\n' ||
+ auth_cur[x] == '\r' ||
+ auth_cur[x] == '\0') {
+ entry_cur->plen = x - (entry_cur->ulen + 1);
+ break;
+ }
+ }
+ }
+
+ // malformed line.
+ if (!found) {
+ (void)fclose(pwfile);
+ free(auth_data);
+ return AUTHFILE_MALFORMED;
+ }
+
+ // FIXME: no silent truncation.
+ if (++used == MAX_ENTRIES) {
+ break;
+ }
+ // EOF
+ if (auth_cur[x] == '\0')
+ break;
+
+ auth_cur += x;
+ entry_cur++;
+ }
+
+ // swap the main pointer out now, so if there's an error reloading we
+ // don't break the existing authentication.
+ if (main_auth_data != NULL) {
+ free(main_auth_data);
+ }
+
+ entry_cnt = used;
+ main_auth_data = auth_data;
+ memcpy(main_auth_entries, auth_entries, sizeof(auth_entries));
+
+ (void)fclose(pwfile);
+
+ return AUTHFILE_OK;
+}
+
+// if only loading the file could be this short...
+int authfile_check(const char *user, const char *pass) {
+ size_t ulen = strlen(user);
+ size_t plen = strlen(pass);
+
+ for (int x = 0; x < entry_cnt; x++) {
+ auth_t *e = &main_auth_entries[x];
+ if (ulen == e->ulen && plen == e->plen &&
+ memcmp(user, e->user, e->ulen) == 0 &&
+ memcmp(pass, e->pass, e->plen) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}