Welcome to little lamb

Code » ssp » commit da4a68a

Add --debug & some debug messages

author Olivier Brunel
2023-04-23 15:31:41 UTC
committer Olivier Brunel
2023-04-25 15:02:08 UTC
parent a0ccd17a00a4d6bf81496b85834052a0ed296c4f

Add --debug & some debug messages

src/ssp/add.c +4 -0
src/ssp/database.c +29 -5
src/ssp/import.c +11 -0
src/ssp/list.c +2 -0
src/ssp/ssp.c +9 -0

diff --git a/src/ssp/add.c b/src/ssp/add.c
index 91ef2ee..7cc694c 100644
--- a/src/ssp/add.c
+++ b/src/ssp/add.c
@@ -20,6 +20,7 @@ struct add {
 int
 validate_algo(int *first, const char *data, size_t dlen)
 {
+    dbg("validating algo ", LEN(data, dlen), "...");
     int algo = byte_get_match(first, data, dlen, algos);
     if (algo < 0)
         warn("invalid algorithm: ", LEN(data, dlen));
@@ -29,6 +30,7 @@ validate_algo(int *first, const char *data, size_t dlen)
 int
 validate_digits(const char *data, size_t dlen)
 {
+    dbg("validating digits ", LEN(data, dlen), "...");
     int digits = *data - '0';
     if (dlen > 1 || digits < 5 || digits > 9) {
         warn("invalid number of digits, must be between 5 and 9: ", LEN(data, dlen));
@@ -40,6 +42,7 @@ validate_digits(const char *data, size_t dlen)
 int
 validate_precision(const char *data, size_t dlen)
 {
+    dbg("validating precision ", LEN(data, dlen), "...");
     u16 u;
     if (u16_scan(&u, data) != dlen || u < 10 || u > 120) {
         warn("invalid precision argument, must be between 10 and 120: ", LEN(data, dlen));
@@ -172,6 +175,7 @@ add_main(int argc, const char *argv[], const char *env[], const char usage[], vo
     if (clen >= 2 && add.comments[0] == '"' && add.comments[clen - 1] == '"') {
         ++add.comments;
         clen -= 2;
+        dbg("unescaping comments");
         l = unesc(p->data + l, clen, add.comments, clen);
         if (l < 0)
             diefusys(EX_DATA_ERR, "read comments");
diff --git a/src/ssp/database.c b/src/ssp/database.c
index 2ceffe1..0602571 100644
--- a/src/ssp/database.c
+++ b/src/ssp/database.c
@@ -22,12 +22,14 @@ get_key(char key[KEY_LEN], const char salt[SALT_LEN], const char *prompt, struct
 {
     ssize_t plen;
     if (!*ctx->pwd) {
+        dbg("asking for password");
         plen = ask_password(ctx->pwd, sizeof(ctx->pwd), prompt);
         if (plen < 0) return 0;
     } else {
         plen = strlen(ctx->pwd);
     }
 
+    dbg("deriving encryption key");
     /* get encryption key */
     pbkdf2(key, KEY_LEN, sha3_256, ctx->pwd, plen, salt, SALT_LEN, ITER);
 
@@ -37,6 +39,7 @@ get_key(char key[KEY_LEN], const char salt[SALT_LEN], const char *prompt, struct
 int
 open_db(struct ssp *ctx)
 {
+    dbg("opening database...");
     int fd = open_read(db_file(ctx));
     if (fd < 0) {
         /* no file is not an error at this point */
@@ -56,6 +59,7 @@ open_db(struct ssp *ctx)
     }
     fd_close(fd);
 
+    dbg("checking magic: ", HEX(ctx->sa.s + salen, sizeof(u32)));
     /* check our magic */
     u32p_be((u32 *) (ctx->sa.s + salen));
     if (* (u32 *) (ctx->sa.s + salen) != SSP_MAGIC) {
@@ -84,12 +88,14 @@ open_db(struct ssp *ctx)
         return -1;
     }
 
+    dbg("decrypting database");
     /* decrypt data in-place */
     char nonce[NONCE_LEN] = { 0 };
     chacha20(ctx->sa.s + salen, key, nonce, ctx->sa.s + off, ctx->sa.len - off);
     ctx->sa.len -= off - salen;
     off = salen;
 
+    dbg("checking internal magic: ", HEX(ctx->sa.s + off, sizeof(u32)));
     /* check internal magic, to "validate" the password */
     u32p_be((u32 *) (ctx->sa.s + off));
     if (* (u32 *) (ctx->sa.s + off) != SSP_MAGIC_INT) {
@@ -100,6 +106,7 @@ open_db(struct ssp *ctx)
     /* move off past internal magic, to actual cdb content */
     off += sizeof(u32);
 
+    dbg("initializing cdb");
     cdb_init_frommem(&ctx->cdb, ctx->sa.s + off, ctx->sa.len - off);
     return 1;
 }
@@ -111,6 +118,8 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
     size_t olen = 0, nlen = 0, vlen = 0;
     int r = 0;
 
+    dbg("rebuiling cdb...");
+
     /* oldkey & newkey  : renaming/editing an entry
      * oldkey & NULL    : removing an entry
      * NULL   & newkey  : adding an entry
@@ -123,16 +132,22 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
     }
     if (oldkey) olen = strlen(oldkey) + 1;
 
+    dbg("oldkey=", ESC, oldkey, ESC, " newkey=", ESC, newkey, ESC,
+        " vlen=", PUTMSG_UINT(vlen));
+
     if (!cdbmaker_sa_start(mkr))
         return 0;
     /* new file? */
     if (!ctx->cdb.map) {
+        dbg("new file, adding newkey");
         if (nlen && !cdbmaker_sa_add(mkr, newkey, nlen, (char *) otp, vlen))
             return 0;
     } else {
         int a = !nlen;
         db_reset(ctx);
+        dbg("iterating current cdb...");
         while ((r = db_next(ctx)) == 1) {
+            dbg("key=", ESC, db_entry(ctx), ESC);
             /* existing newkey isn't allowed when adding or renaming */
             if (nlen == ctx->key.len && !strcmp(newkey, ctx->key.s)
                     && (!olen || strcmp(oldkey, newkey))) {
@@ -142,6 +157,7 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
                 /* Note the use of strcoll() here to ensure we order entries
                  * using locale-specific rules. */
                 if (!a && strcoll(ctx->key.s, newkey) > 0) {
+                    dbg("inserting newkey before");
                     /* insert otp at the right place */
                     if (!cdbmaker_sa_add(mkr, newkey, nlen, (char *) otp, vlen))
                         return 0;
@@ -149,10 +165,12 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
                 }
                 /* if current entry isn't the old one nor the new one, re-add */
                 if (!(olen == ctx->key.len && !strcmp(oldkey, ctx->key.s))
-                        && !(nlen == ctx->key.len && !strcmp(newkey, ctx->key.s))
-                        && !cdbmaker_sa_add(mkr, ctx->key.s, ctx->key.len,
-                                            ctx->val.s, ctx->val.len))
-                    return 0;
+                        && !(nlen == ctx->key.len && !strcmp(newkey, ctx->key.s))) {
+                    dbg("preserving key");
+                    if (!cdbmaker_sa_add(mkr, ctx->key.s, ctx->key.len,
+                                ctx->val.s, ctx->val.len))
+                        return 0;
+                }
             }
         }
         if (r < 0) {
@@ -160,6 +178,7 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
             return (errno = EINVAL, 0);
         }
         if (!a) {
+            dbg("inserting newkey last");
             /* insert last */
             if (!cdbmaker_sa_add(mkr, newkey, nlen, (char *) otp, vlen))
                 return 0;
@@ -174,6 +193,8 @@ rebuild_cdb(cdbmaker_sa *mkr, const char *oldkey, const char *newkey,
 int
 write_db(char *data, size_t dlen, struct ssp *ctx)
 {
+    dbg("writing db...");
+
     char salt[SALT_LEN];
     char key[KEY_LEN];
     char nonce[NONCE_LEN] = { 0 };
@@ -188,13 +209,13 @@ write_db(char *data, size_t dlen, struct ssp *ctx)
     u32 magic_int = SSP_MAGIC_INT;
     u32p_be(&magic_int);
 
+    dbg("encrypting database");
     chacha20_ctx chacha;
     chacha20_init(key, nonce, &chacha);
     chacha20_crypt(&magic_int, &magic_int, sizeof(magic_int), &chacha);
     chacha20_crypt(data, data, dlen, &chacha);
     chacha20_clear(&chacha);
 
-
     u32 magic = SSP_MAGIC;
     u32p_be(&magic);
 
@@ -208,6 +229,7 @@ write_db(char *data, size_t dlen, struct ssp *ctx)
     v[3].iov_base = data;
     v[3].iov_len = dlen;
 
+    dbg("saving database");
     if (!openwritevnclose(db_file(ctx), v, 4)) {
         warnusys("write database to ", ESC, db_file(ctx), ESC);
         return 0;
@@ -219,6 +241,8 @@ write_db(char *data, size_t dlen, struct ssp *ctx)
 void
 rebuild_db(const char *oldkey, const char *newkey, const struct otp *otp, struct ssp *ctx)
 {
+    dbg("rebuilding database...");
+
     cdbmaker_sa mkr = CDBMAKER_SA_ZERO;
 
     if (!rebuild_cdb(&mkr, oldkey, newkey, otp, ctx))
diff --git a/src/ssp/import.c b/src/ssp/import.c
index 2188e53..ff78e5c 100644
--- a/src/ssp/import.c
+++ b/src/ssp/import.c
@@ -28,6 +28,7 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
     if (fd < 0)
         diefusys(EX_NOINPUT, "open ", ESC, argv[1], ESC);
 
+    dbg("reading ", ESC, argv[1], ESC);
     stralloc sa = STRALLOC_ZERO;
     if (!slurp(&sa, fd))
         diefusys(exitcode_from_errno(errno), "read ", ESC, argv[1], ESC);
@@ -43,14 +44,19 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
     size_t clen;
     struct copa copa;
     int r, n = 0;
+    dbg("init parsing");
     copa_init(sa.s, sa.len, &copa);
     while ((r = copa_next(&copa)) >= 0) {
+        dbg("r=", PUTMSG_INT(r));
+        if (r) dbg("is_section=", PUTMSG_INT(copa_is_section(&copa)),
+                   " name=", LEN(copa_name(&copa), copa_nlen(&copa)));
         if (!r || copa_is_section(&copa)) {
             if (name) {
                 if (!slen)
                     die(EX_DATA_ERR, "missing secret in section/entry ",
                         ESC, LEN(name, nlen), ESC);
 
+                dbg("preparing entry ", ESC, LEN(name, nlen), ESC);
                 char buf[sizeof(otp) + slen + clen + 1];
                 struct otp *p = (struct otp *) buf;
                 memcpy(p, &otp, sizeof(otp));
@@ -59,6 +65,7 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
                 if (clen >= 2 && comments[0] == '"' && comments[clen - 1] == '"') {
                     ++comments;
                     clen -= 2;
+                    dbg("unescaping comments");
                     if (unesc(p->data + slen, clen, comments, clen) < 0)
                         diefusys(EX_DATA_ERR, "read comments in section/entry ",
                                  ESC, LEN(name, nlen), ESC);
@@ -71,6 +78,7 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
                  * - and we'll reuse the memory for our maker
                  */
                 if (mkr.sa.s) {
+                    dbg("making previously generated cdb live");
                     stralloc sa = ctx->sa;
                     ctx->sa = mkr.sa;
                     cdb_init_frommem(&ctx->cdb, ctx->sa.s, ctx->sa.len);
@@ -92,6 +100,7 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
             }
             if (!r) break;
 
+            dbg("resetting new entry");
             name = copa_name(&copa);
             nlen = copa_nlen(&copa);
             otp.algo = ALGO_SHA256;
@@ -110,6 +119,8 @@ import_main(int argc, const char *argv[], const char *env[], const char usage[],
                      ESC, LEN(copa_name(&copa), copa_nlen(&copa)), ESC,
                      " in section/entry ", ESC, LEN(name, nlen), ESC);
 
+            dbg("value=", ESC, LEN(copa_value(&copa), copa_vlen(&copa)), ESC);
+
             if (copa_nlen(&copa) == 4 && !strncmp(copa_name(&copa), "algo", 4)) {
                 r = validate_algo(NULL, copa_value(&copa), copa_vlen(&copa));
                 if (r < 0) goto err;
diff --git a/src/ssp/list.c b/src/ssp/list.c
index 9b54909..6b5c51e 100644
--- a/src/ssp/list.c
+++ b/src/ssp/list.c
@@ -94,7 +94,9 @@ list_main(int argc, const char *argv[], const char *env[], const char usage[], v
 
     i = 0;
     db_reset(ctx);
+    dbg("iterating database...");
     while ((r = db_next(ctx)) == 1) {
+        dbg("entry ", ESC, db_entry(ctx), ESC);
         if (list.ptrn && fnmatch(list.ptrn, db_entry(ctx), 0))
             continue;
         if (list.options & OPT_FMT_INI) {
diff --git a/src/ssp/ssp.c b/src/ssp/ssp.c
index 6d456c4..6845a7e 100644
--- a/src/ssp/ssp.c
+++ b/src/ssp/ssp.c
@@ -4,6 +4,7 @@
 #include <errno.h>
 #include <locale.h>
 #include <skalibs/env.h>
+#include <limb/autoopt.h>
 #include <limb/bytestr.h>
 #include <limb/command.h>
 #include <limb/esc.h>
@@ -20,6 +21,7 @@ const char *algos[] = { "sha1", "sha256", "sha512", "sha3-224", "sha3-256",
 
 enum {
     OPTID_VERSION = OPTID_FIRST,
+    OPTID_DEBUG,
 };
 
 int
@@ -39,6 +41,7 @@ exitcode_from_errno(int e)
 int
 run_command(const char *name, int argc, const char *argv[], const char *env[], void *ctx)
 {
+    dbg("running command ", name, "...");
     for (struct command **c = commands; *c; ++c)
         if (!strcmp((*c)->name, name))
             return (*c)->main(argc, argv, env, "", ctx);
@@ -84,6 +87,7 @@ parse_cmdline(int *argc, const char **argv[], struct ssp *ctx)
 {
     const char usage[] = "[-h] [-D database] command [...]";
     const struct option options[] = {
+        OPTION_ARG_OPT ( 0 , "debug",                   0, OPTID_DEBUG),
         OPTION_ARG_REQ ('D', "database",                0, OPTID_SHORTOPT),
         OPTION_ARG_NONE('h', "help",                    0, OPTID_SHORTOPT),
         OPTION_ARG_NONE( 0 , "version",                 0, OPTID_VERSION),
@@ -99,6 +103,10 @@ parse_cmdline(int *argc, const char **argv[], struct ssp *ctx)
         case 'h':
             ctx->options |= OPT_HELP;
             break;
+        case OPTID_DEBUG:
+            if (!autoopt_debug(&options[PO_IDX(&po)], PO_ARG(&po)))
+                dieusage(EX_USAGE, usage);
+            break;
         case OPTID_VERSION:
             dieversion(SSP_VERSION, "2023", SSP_CURYEAR, SSP_AUTHOR, SSP_URL, NULL);
         case -1:
@@ -146,6 +154,7 @@ main(int argc, const char *argv[], const char *env[])
     if (ctx.options & OPT_HELP)
         diecmdhelp(0, usage, command);
 
+    dbg("database: ", ESC, db_file(&ctx), ESC, "; running command ", command->name, "...");
     int r = command->main(argc, argv, env, usage, &ctx);
     stralloc_free(&ctx.sa);
     return r;