From ee6809eac527e101a077bc1d10e2acce96754ca8 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sat, 25 Mar 2023 09:57:19 +0100 Subject: auth.c: Ensure absolute path for a->dir Otherwise, slcl would create broken symbolic links if the user passes a relative path as command line argument. --- auth.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/auth.c b/auth.c index 5ea6a3b..e6f86fe 100644 --- a/auth.c +++ b/auth.c @@ -510,14 +510,51 @@ static int init_db(struct auth *const a) return 0; } +static char *resolve_cwd(void) +{ + size_t len = 1; + char *p = NULL; + + for (;;) + { + char *const pp = realloc(p, len); + + if (!pp) + { + fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno)); + break; + } + + p = pp; + + if (!getcwd(pp, len)) + { + if (errno != ERANGE) + { + fprintf(stderr, "%s: getcwd(3): %s\n", + __func__, strerror(errno)); + break; + } + else + len++; + } + else + return p; + } + + free(p); + return NULL; +} + struct auth *auth_alloc(const char *const dir) { - struct auth *const a = malloc(sizeof *a); + struct auth *const a = malloc(sizeof *a), *ret = NULL; + char *abspath = NULL; if (!a) { fprintf(stderr, "%s: malloc(3) auth: %s\n", __func__, strerror(errno)); - goto failure; + goto end; } *a = (const struct auth){0}; @@ -525,25 +562,39 @@ struct auth *auth_alloc(const char *const dir) dynstr_init(&a->db); dynstr_init(&a->dir); - if (dynstr_append(&a->dir, "%s", dir)) + if (*dir != '/' && !(abspath = resolve_cwd())) { - fprintf(stderr, "%s: dynstr_append failed\n", __func__); - goto failure; + fprintf(stderr, "%s: resolve_cwd failed\n", __func__); + goto end; } - else if (dynstr_append(&a->db, "%s/db.json", dir)) + else if (abspath && dynstr_append(&a->dir, "%s", abspath)) { - fprintf(stderr, "%s: dynstr_append failed\n", __func__); - goto failure; + fprintf(stderr, "%s: dynstr_append abspath failed\n", __func__); + goto end; + } + else if (dynstr_append(&a->dir, "%s%s", abspath ? "/" : "", dir)) + { + fprintf(stderr, "%s: dynstr_append dir failed\n", __func__); + goto end; + } + else if (dynstr_append(&a->db, "%s/db.json", a->dir.str)) + { + fprintf(stderr, "%s: dynstr_append db failed\n", __func__); + goto end; } else if (init_db(a)) { fprintf(stderr, "%s: init_db failed\n", __func__); - goto failure; + goto end; } - return a; + ret = a; -failure: - auth_free(a); - return NULL; +end: + free(abspath); + + if (!ret) + auth_free(a); + + return ret; } -- cgit v1.2.3