[rs-commit] r45 - in /redwax-tool/trunk: redwax-tool.c redwax-tool.h redwax_p11kit.c

rs-commit at redwax.eu rs-commit at redwax.eu
Sat Nov 20 10:48:46 CET 2021


Author: minfrin at redwax.eu
Date: Sat Nov 20 10:48:45 2021
New Revision: 45

Log:
Add ability to read secrets for tokens from a secrets file.

Modified:
    redwax-tool/trunk/redwax-tool.c
    redwax-tool/trunk/redwax-tool.h
    redwax-tool/trunk/redwax_p11kit.c

Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c	(original)
+++ redwax-tool/trunk/redwax-tool.c	Sat Nov 20 10:48:45 2021
@@ -80,7 +80,7 @@
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pem_in,
         (redwax_tool_t * r, const char *arg, const char *secret), (r, arg, secret), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pkcs11_in,
-        (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
+        (redwax_tool_t * r, const char *arg, apr_hash_t *secrets), (r, arg, secrets), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_pkcs11_in,
         (redwax_tool_t * r, const char *url, apr_hash_t *urls), (r, url, urls), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pkcs11_module_in,
@@ -100,7 +100,7 @@
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pkcs12_out,
         (redwax_tool_t * r, const char *arg, const char *secret), (r, arg, secret), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pkcs11_out,
-        (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
+        (redwax_tool_t * r, const char *arg, apr_hash_t *secrets), (r, arg, secrets), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_pkcs11_out,
         (redwax_tool_t * r, const char *url, apr_hash_t *urls), (r, url, urls), DECLINED);
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_pkcs11_module_out,
@@ -152,13 +152,15 @@
 #define REDWAX_TOOL_VERIFY_PARAM 280
 #define REDWAX_TOOL_SECRET_SUFFIX_IN 281
 #define REDWAX_TOOL_SECRET_SUFFIX_OUT 282
-#define REDWAX_TOOL_LABEL_OUT 283
-#define REDWAX_TOOL_NSS_OUT 284
-#define REDWAX_TOOL_NSS_SLOT_OUT 285
-#define REDWAX_TOOL_PEM_OUT 286
-#define REDWAX_TOOL_PKCS12_OUT 287
-#define REDWAX_TOOL_PKCS11_OUT 288
-#define REDWAX_TOOL_PKCS11_MODULE_OUT 289
+#define REDWAX_TOOL_SECRET_TOKEN_IN 283
+#define REDWAX_TOOL_SECRET_TOKEN_OUT 284
+#define REDWAX_TOOL_LABEL_OUT 285
+#define REDWAX_TOOL_NSS_OUT 286
+#define REDWAX_TOOL_NSS_SLOT_OUT 287
+#define REDWAX_TOOL_PEM_OUT 288
+#define REDWAX_TOOL_PKCS12_OUT 289
+#define REDWAX_TOOL_PKCS11_OUT 290
+#define REDWAX_TOOL_PKCS11_MODULE_OUT 291
 
 #define REDWAX_EXIT_OK 0
 #define REDWAX_EXIT_INIT 1
@@ -166,6 +168,8 @@
 #define REDWAX_EXIT_FILTER 3
 
 #define REDWAX_PASSTHROUGH "passthrough"
+
+#define REDWAX_SECRET_MAX HUGE_STRING_LEN
 
 static const apr_getopt_option_t
     cmdline_opts[] =
@@ -180,6 +184,8 @@
         "  -t, --text\t\t\tInclude text in certificate output." },
     { "secret-suffix-in", REDWAX_TOOL_SECRET_SUFFIX_IN, 1, "  --secret-suffix-in=suffix\tIf specified, secrets will be read from a file\n\t\t\t\twith the same name as the source file, and\n\t\t\t\tthe suffix specified. With value 'secret',\n\t\t\t\ta file 'key.pem' will have the secret loaded\n\t\t\t\tfrom 'key.secret' in the same directory." },
     { "secret-suffix-out", REDWAX_TOOL_SECRET_SUFFIX_OUT, 1, "  --secret-suffix-out=suffix\tIf specified, secrets will be read from a file\n\t\t\t\twith the same name as the target file, and\n\t\t\t\tthe suffix specified. With value 'secret',\n\t\t\t\ta file 'key.pem' will have the secret loaded\n\t\t\t\tfrom 'key.secret' in the same directory." },
+    { "secret-token-in", REDWAX_TOOL_SECRET_TOKEN_IN, 1, "  --secret-token-in=file\tIf specified, secrets needed to read\n\t\t\t\tcertificates and keys from tokens will be read\n\t\t\t\tfrom a file one secret per line. Each secret\n\t\t\t\tis preceded by the name of the token and a\n\t\t\t\tcolon, as per the NSS pwdfile.txt file." },
+    { "secret-token-out", REDWAX_TOOL_SECRET_TOKEN_OUT, 1, "  --secret-token-out=file\tIf specified, secrets needed to write\n\t\t\t\tcertificates and keys to tokens (PKCS11 and\n\t\t\t\tNSS) will be read from a file one secret per\n\t\t\t\tline. Each secret is preceded by the name of\n\t\t\t\tthe token and a colon, as per the NSS\n\t\t\t\tpwdfile.txt file." },
     { "label-out", REDWAX_TOOL_LABEL_OUT, 1, "  --label-out=label\t\tSet the name of the label to be applied to\n\t\t\t\tthe leaf certificates. If unspecified, the\n\t\t\t\tlabel is set to the subject of the certificate." },
     { "pem-in", REDWAX_TOOL_PEM_IN, 1, "  --pem-in=wildcard\t\tRead pem files from here. Use '-' for stdin." },
     { "pkcs11-in", REDWAX_TOOL_PKCS11_IN, 1, "  --pkcs11-in=url\t\tRead certificates, intermediate certificates,\n\t\t\t\troot certificates, crls, and keys from a PKCS11\n\t\t\t\ttoken identified by the given url." },
@@ -1027,6 +1033,98 @@
     return NULL;
 }
 
+apr_hash_t *redwax_secrets_path(redwax_tool_t *r, const char *secrets_path)
+{
+    if (secrets_path && secrets_path[0]) {
+
+        apr_file_t *sfile;
+        apr_status_t status;
+
+        apr_size_t max = REDWAX_SECRET_MAX;
+
+        apr_pool_t *pool;
+        apr_hash_t *hash;
+
+        apr_pool_create(&pool, r->pool);
+
+        hash = apr_hash_make(pool);
+
+        do {
+
+            char *buf;
+            char *lf;
+            char *cl;
+
+            if (!strcmp("-", secrets_path)) {
+                sfile = r->in;
+            }
+            else {
+                status = apr_file_open(&sfile, secrets_path, APR_FOPEN_READ,
+                        APR_FPROT_OS_DEFAULT, pool);
+                if (APR_SUCCESS != status) {
+                    break;
+                }
+            }
+
+            do {
+
+                buf = apr_pcalloc(pool, max);
+
+#if HAVE_APR_CRYPTO_CLEAR
+                apr_crypto_clear(pool, buf, max);
+#endif
+
+                status = apr_file_gets(buf, max - 1, sfile);
+
+                if (APR_EOF == status) {
+                    break;
+                }
+                else if (APR_SUCCESS != status) {
+                    redwax_print_error(r,
+                            "Could not read '%s': %pm\n", secrets_path, &status);
+                    apr_file_close(sfile);
+                    apr_pool_destroy(pool);
+                    return NULL;
+                }
+
+                /* string too long? */
+                if (strlen(buf) == max - 1) {
+                    redwax_print_error(r,
+                            "When reading '%s', line was too long (>%d)\n",
+                            secrets_path, (int) (max - 1));
+                    apr_file_close(sfile);
+                    apr_pool_destroy(pool);
+                    return NULL;
+                }
+
+                /* ignore comments */
+                if (buf[0] == '#') {
+                    continue;
+                }
+
+                /* strip linefeed */
+                lf = strchr(buf, '\n');
+                if (lf) {
+                    *lf = 0;
+                }
+
+                /* isolate the token */
+                cl = strchr(buf, ':');
+                if (cl) {
+                    *cl = 0;
+                    apr_hash_set(hash, buf, cl - buf, cl + 1);
+                }
+
+            } while (1);
+
+        } while (0);
+
+        return hash;
+    }
+
+    return NULL;
+}
+
 apr_status_t redwax_complete_filter(redwax_tool_t *r, const char *arg,
         redwax_token_quoted_e quoted)
 {
@@ -1739,6 +1837,30 @@
     return APR_SUCCESS;
 }
 
+static apr_status_t redwax_set_secret_token_in(redwax_tool_t *r, const char *arg)
+{
+    if (arg && arg[0]) {
+        r->secret_token_in = arg;
+    }
+    else {
+        r->secret_token_in = NULL;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_set_secret_token_out(redwax_tool_t *r, const char *arg)
+{
+    if (arg && arg[0]) {
+        r->secret_token_out = arg;
+    }
+    else {
+        r->secret_token_out = NULL;
+    }
+
+    return APR_SUCCESS;
+}
+
 static apr_status_t redwax_set_label_out(redwax_tool_t *r, const char *arg)
 {
     if (arg && arg[0]) {
@@ -1787,7 +1909,8 @@
 static apr_status_t redwax_pkcs11_in(redwax_tool_t *r, const char *arg)
 {
 
-    apr_status_t status = rt_run_process_pkcs11_in(r, arg);
+    apr_status_t status = rt_run_process_pkcs11_in(r, arg,
+            redwax_secrets_path(r, r->secret_token_in));
 
     apr_array_clear(r->pkcs11_in.pkcs11_modules);
 
@@ -1805,7 +1928,8 @@
 static apr_status_t redwax_pkcs11_out(redwax_tool_t *r, const char *arg)
 {
 
-    apr_status_t status = rt_run_process_pkcs11_out(r, arg);
+    apr_status_t status = rt_run_process_pkcs11_out(r, arg,
+            redwax_secrets_path(r, r->secret_token_out));
 
     apr_array_clear(r->pkcs11_out.pkcs11_modules);
 
@@ -1890,6 +2014,10 @@
             redwax_set_secret_suffix_in(r, optarg);
             break;
         }
+        case REDWAX_TOOL_SECRET_TOKEN_IN: {
+            redwax_set_secret_token_in(r, optarg);
+            break;
+        }
         case REDWAX_TOOL_PEM_IN: {
             redwax_dir_walk(r, optarg, &rt_run_process_pem_in);
             break;
@@ -2023,6 +2151,10 @@
         }
         case REDWAX_TOOL_SECRET_SUFFIX_OUT: {
             redwax_set_secret_suffix_out(r, optarg);
+            break;
+        }
+        case REDWAX_TOOL_SECRET_TOKEN_OUT: {
+            redwax_set_secret_token_out(r, optarg);
             break;
         }
         case REDWAX_TOOL_NSS_OUT: {
@@ -2126,6 +2258,10 @@
                 rt_run_complete_pkcs11_module_in(r, optarg, state.isquoted);
                 break;
             }
+            case REDWAX_TOOL_SECRET_TOKEN_IN: {
+                redwax_complete_file(r, optarg, state.isquoted);
+                break;
+            }
             case REDWAX_TOOL_FILTER: {
                 redwax_complete_filter(r, optarg, state.isquoted);
                 break;
@@ -2168,6 +2304,10 @@
             }
             case REDWAX_TOOL_PKCS11_MODULE_OUT: {
                 rt_run_complete_pkcs11_module_out(r, optarg, state.isquoted);
+                break;
+            }
+            case REDWAX_TOOL_SECRET_TOKEN_OUT: {
+                redwax_complete_file(r, optarg, state.isquoted);
                 break;
             }
             }
@@ -2190,6 +2330,10 @@
             }
             case REDWAX_TOOL_SECRET_SUFFIX_IN: {
                 redwax_set_secret_suffix_in(r, optarg);
+                break;
+            }
+            case REDWAX_TOOL_SECRET_TOKEN_IN: {
+                redwax_set_secret_token_in(r, optarg);
                 break;
             }
             case REDWAX_TOOL_PEM_IN: {
@@ -2298,6 +2442,10 @@
             rt_run_complete_pkcs11_module_in(r, "", state.isquoted);
             break;
         }
+        case REDWAX_TOOL_SECRET_TOKEN_IN: {
+            redwax_complete_file(r, "", state.isquoted);
+            break;
+        }
         case REDWAX_TOOL_FILTER: {
             redwax_complete_filter(r, "", state.isquoted);
             break;
@@ -2340,6 +2488,10 @@
         }
         case REDWAX_TOOL_PKCS11_MODULE_OUT: {
             rt_run_complete_pkcs11_module_out(r, "", state.isquoted);
+            break;
+        }
+        case REDWAX_TOOL_SECRET_TOKEN_OUT: {
+            redwax_complete_file(r, "", state.isquoted);
             break;
         }
         }

Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h	(original)
+++ redwax-tool/trunk/redwax-tool.h	Sat Nov 20 10:48:45 2021
@@ -72,6 +72,8 @@
     const char *verify_param;
     const char *secret_suffix_in;
     const char *secret_suffix_out;
+    const char *secret_token_in;
+    const char *secret_token_out;
     const char *label_out;
     redwax_nss_t nss_out;
     redwax_pkcs11_t pkcs11_in;
@@ -339,7 +341,7 @@
  * @param r The redwax-tool context.
  */
 APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs11_in,
-        (redwax_tool_t *r, const char *arg));
+        (redwax_tool_t *r, const char *arg, apr_hash_t *secrets));
 
 /**
  * Hook to complete the module for the incoming PKCS11 URL.
@@ -423,7 +425,7 @@
  * @param r The redwax-tool context.
  */
 APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs11_out,
-        (redwax_tool_t *r, const char *arg));
+        (redwax_tool_t *r, const char *arg, apr_hash_t *secrets));
 
 /**
  * Hook to complete the module for the PKCS11 URL.

Modified: redwax-tool/trunk/redwax_p11kit.c
==============================================================================
--- redwax-tool/trunk/redwax_p11kit.c	(original)
+++ redwax-tool/trunk/redwax_p11kit.c	Sat Nov 20 10:48:45 2021
@@ -725,13 +725,12 @@
 static apr_status_t redwax_p11kit_handle_token_login(redwax_tool_t *r,
         apr_pool_t *pool, P11KitUri *parsed, CK_FUNCTION_LIST *module,
         CK_TOKEN_INFO *tokenInfo, CK_SLOT_ID_PTR slot_id,
-        CK_SESSION_HANDLE session, const char *direction)
+        CK_SESSION_HANDLE session, const char *direction, apr_hash_t *secrets)
 {
     redwax_pkcs11_session_t *s;
 
-// FIXME
-
     const char *urlPIN = p11_kit_uri_get_pin_value(parsed);
+    const char *tokenPIN = NULL;
     CK_UTF8CHAR *userPIN = NULL;
     CK_RV ret;
     apr_status_t status;
@@ -779,12 +778,15 @@
 
         userPIN_len = strlen(urlPIN);
         userPIN = apr_pmemdup(pool, urlPIN, userPIN_len);
+#if HAVE_APR_CRYPTO_CLEAR
+        apr_crypto_clear(pool, userPIN, userPIN_len);
+#endif
 
         /* try once */
         ret = module->C_Login(session, CKU_USER, userPIN, userPIN_len);
         if (ret != CKR_OK) {
 
-            redwax_print_error(r, "%s: login to '%s' with user PIN "
+            redwax_print_error(r, "%s: login to '%s' with URL PIN "
                     "failed, skipping: %s\n", direction,
                     redwax_pstrntrim(pool, (const char*) tokenInfo->label,
                             sizeof(tokenInfo->label)), pkcs11_errstr(ret));
@@ -796,9 +798,38 @@
     }
 
     /* otherwise see if there is a pinfile */
-#if 0
-    // TODO - load the secret from a pinfile, compatible with 389ds.
-#endif
+    else if (secrets) {
+
+        /* if a pinfile exists, we try to log in to listed tokens, but we
+         * make no attempt to log in to anything not listed - the intention
+         * is we've been told explicitly which tokens to log in with, anything
+         * outside the list stays public.
+         */
+        if ((tokenPIN = apr_hash_get(secrets,
+                redwax_pstrntrim(pool, (const char*) tokenInfo->label,
+                        sizeof(tokenInfo->label)), APR_HASH_KEY_STRING))) {
+
+            userPIN_len = strlen(tokenPIN);
+            userPIN = apr_pmemdup(pool, tokenPIN, userPIN_len);
+    #if HAVE_APR_CRYPTO_CLEAR
+            apr_crypto_clear(pool, userPIN, userPIN_len);
+    #endif
+
+            /* try once */
+            ret = module->C_Login(session, CKU_USER, userPIN, userPIN_len);
+            if (ret != CKR_OK) {
+
+                redwax_print_error(r, "%s: login to '%s' with token PIN "
+                        "failed, skipping: %s\n", direction,
+                        redwax_pstrntrim(pool, (const char*) tokenInfo->label,
+                                sizeof(tokenInfo->label)), pkcs11_errstr(ret));
+
+                return APR_EGENERAL;
+
+            }
+
+        }
+    }
 
     /* otherwise load from stdin */
     else {
@@ -899,7 +930,7 @@
 
 static apr_status_t redwax_p11kit_handle_slot_automatic(redwax_tool_t *r,
         P11KitUri *parsed, CK_FUNCTION_LIST *module, CK_TOKEN_INFO *tokenInfo,
-        CK_SLOT_ID_PTR slot_id)
+        CK_SLOT_ID_PTR slot_id, apr_hash_t *secrets)
 {
 
     return APR_ENOTIMPL;
@@ -907,7 +938,7 @@
 
 static apr_status_t redwax_p11kit_handle_slot_manual(redwax_tool_t *r,
         P11KitUri *parsed, CK_FUNCTION_LIST *module, CK_TOKEN_INFO *tokenInfo,
-        CK_SLOT_ID_PTR slot_id)
+        CK_SLOT_ID_PTR slot_id, apr_hash_t *secrets)
 {
     apr_pool_t *pool;
     CK_SESSION_HANDLE session;
@@ -944,7 +975,7 @@
             apr_pool_cleanup_null);
 
     status = redwax_p11kit_handle_token_login(r, pool, parsed,
-            module, tokenInfo, slot_id, session, "pkcs11-out");
+            module, tokenInfo, slot_id, session, "pkcs11-out", secrets);
     if (status != APR_SUCCESS) {
         return status;
     }
@@ -1061,7 +1092,7 @@
 
 static apr_status_t redwax_p11kit_read_slot(redwax_tool_t *r,
         P11KitUri *parsed, CK_FUNCTION_LIST *module, CK_TOKEN_INFO *tokenInfo,
-        CK_SLOT_ID_PTR slot_id)
+        CK_SLOT_ID_PTR slot_id, apr_hash_t *secrets)
 {
     apr_pool_t *pool;
     CK_SESSION_HANDLE session;
@@ -1101,7 +1132,7 @@
         apr_status_t status;
 
         status = redwax_p11kit_handle_token_login(r, pool, parsed,
-                module, tokenInfo, slot_id, session, "pkcs11-in");
+                module, tokenInfo, slot_id, session, "pkcs11-in", secrets);
         if (status != APR_SUCCESS) {
 
             apr_pool_destroy(pool);
@@ -1440,8 +1471,8 @@
         else {
 
             redwax_print_error(r,
-                    "pkcs11-in: Object %d found on '%s', skipping\n",
-                    (int)clazz, redwax_pstrntrim(pool, (const char*) tokenInfo->label,
+                    "pkcs11-in: Object %lu found on '%s', skipping\n",
+                    clazz, redwax_pstrntrim(pool, (const char*) tokenInfo->label,
                             sizeof(tokenInfo->label)));
 
         }
@@ -1459,7 +1490,7 @@
 }
 
 static apr_status_t redwax_p11kit_process_pkcs11_in(redwax_tool_t *r,
-        const char *url)
+        const char *url, apr_hash_t *secrets)
 {
     apr_pool_t *pool;
     P11KitUri *parsed;
@@ -1646,7 +1677,7 @@
             }
 
             status = redwax_p11kit_read_slot(r, parsed,
-                    modules[i], &tokenInfo, &pSlotList[j]);
+                    modules[i], &tokenInfo, &pSlotList[j], secrets);
             if (status != APR_SUCCESS) {
                 return status;
             }
@@ -1664,7 +1695,7 @@
 }
 
 static apr_status_t redwax_p11kit_process_pkcs11_out(redwax_tool_t *r,
-        const char *url)
+        const char *url, apr_hash_t *secrets)
 {
     apr_pool_t *pool;
     P11KitUri *parsed;
@@ -1855,11 +1886,11 @@
             /* automatic or manual? */
             if (r->auto_out) {
                 status = redwax_p11kit_handle_slot_automatic(r, parsed,
-                        modules[i], &tokenInfo, &pSlotList[j]);
+                        modules[i], &tokenInfo, &pSlotList[j], secrets);
             }
             else {
                 status = redwax_p11kit_handle_slot_manual(r, parsed,
-                        modules[i], &tokenInfo, &pSlotList[j]);
+                        modules[i], &tokenInfo, &pSlotList[j], secrets);
             }
             if (status != APR_SUCCESS) {
                 return status;



More information about the rs-commit mailing list