diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-09-22 17:32:44 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-02-13 09:57:39 +0100 |
| commit | 78bf2fe4a5bf37514f6dfd203ef969da0bf40c2e (patch) | |
| tree | 33f9440b8ee0fa7a3b3ad033616d722d2101bb4d /tokengen.c | |
| parent | 107a2e43d54f9a42fb85b00b83cb0d9abb194680 (diff) | |
Diffstat (limited to 'tokengen.c')
| -rw-r--r-- | tokengen.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/tokengen.c b/tokengen.c new file mode 100644 index 0000000..9b88085 --- /dev/null +++ b/tokengen.c @@ -0,0 +1,155 @@ +#define _POSIX_C_SOURCE 200809L + +#include "jwt.h" +#include <cjson/cJSON.h> +#include <dynstr.h> +#include <sodium.h> +#include <sqlite3.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static int tokenkey(void *const args, const int n, char **const values, + char **const keys) +{ + char *key; + + if (n != 1) + { + fprintf(stderr, "%s: expected 1 key only, got %d\n", __func__, n); + return -1; + } + else if (!(key = strdup(*values))) + { + fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno)); + return -1; + } + + *(char **)args = key; + return 0; +} + +static int process(sqlite3 *const db, const char *const user) +{ + static const char query[] = "SELECT value FROM globals " + "WHERE key = 'tokenkey';"; + int ret = -1, error; + cJSON *j = NULL; + char *s = NULL, *key = NULL, *jwt = NULL; + unsigned char dkey[32]; + time_t t; + + if ((error = sqlite3_exec(db, query, tokenkey, &key, &s)) != SQLITE_OK) + { + fprintf(stderr, "%s: sqlite3_exec \"%s\": %s (%s)\n", __func__, query, + sqlite3_errstr(error), s); + goto end; + } + else if (strlen(key) != sizeof dkey * 2) + { + fprintf(stderr, "%s: unexpected key length: %zu\n", __func__, + strlen(key)); + goto end; + } + else if (sodium_hex2bin(dkey, sizeof dkey, key, strlen(key), NULL, NULL, + NULL)) + { + fprintf(stderr, "%s: sodium_hex2bin failed\n", __func__); + goto end; + } + else if (!(j = cJSON_CreateObject())) + { + fprintf(stderr, "%s: cJSON_CreateObject failed\n", __func__); + goto end; + } + else if (!cJSON_AddStringToObject(j, "name", user)) + { + fprintf(stderr, "%s: cJSON_AddStringToObject failed\n", __func__); + goto end; + } + else if ((t = time(NULL)) == (time_t)-1) + { + fprintf(stderr, "%s: time(2): %s\n", __func__, strerror(errno)); + goto end; + } + else if (!cJSON_AddNumberToObject(j, "exp", t + 24 * 60 * 60)) + { + fprintf(stderr, "%s: cJSON_AddNumberToObject failed\n", __func__); + goto end; + } + else if (!(jwt = jwt_encode(j, dkey, sizeof dkey))) + { + fprintf(stderr, "%s: jwt_encode failed\n", __func__); + goto end; + } + + printf("%s %s\n", user, jwt); + ret = 0; + +end: + free(jwt); + free(key); + sqlite3_free(s); + cJSON_Delete(j); + return ret; +} + +static sqlite3 *open_db(const char *const dir) +{ + sqlite3 *ret = NULL, *db = NULL; + struct dynstr d; + int error; + + dynstr_init(&d); + + if (dynstr_append(&d, "%s/nanobbs.db", dir)) + { + fprintf(stderr, "%s: dynstr_append failed\n", __func__); + goto end; + } + else if ((error = sqlite3_open(d.str, &db)) != SQLITE_OK) + { + fprintf(stderr, "%s: sqlite3_open %s: %s\n", __func__, d.str, + sqlite3_errstr(error)); + goto end; + } + + ret = db; + +end: + dynstr_free(&d); + return ret; +} + +int main(int argc, char *argv[]) +{ + int ret = EXIT_FAILURE, error; + sqlite3 *db = NULL; + + if (argc < 3) + { + fprintf(stderr, "%s <dir> <user> [...]\n", *argv); + goto end; + } + else if (!(db = open_db(argv[1]))) + goto end; + + for (int i = 2; i < argc; i++) + if (process(db, argv[i])) + goto end; + + ret = EXIT_SUCCESS; + +end: + + if ((error = sqlite3_close(db)) != SQLITE_OK) + { + fprintf(stderr, "%s: sqlite3_close: %s\n", __func__, + sqlite3_errstr(error)); + ret = EXIT_FAILURE; + } + + return ret; +} |
