[rt-commit] r181 - in /redwax-tool/trunk: ChangeLog redwax-tool.c redwax-tool.h redwax_openssl.c
rt-commit at redwax.eu
rt-commit at redwax.eu
Tue May 28 20:18:06 CEST 2024
Author: minfrin at redwax.eu
Date: Tue May 28 20:18:05 2024
New Revision: 181
Log:
Add --filter-purpose option to allow search and
verify to limit certificates by certificate
purpose.
Modified:
redwax-tool/trunk/ChangeLog
redwax-tool/trunk/redwax-tool.c
redwax-tool/trunk/redwax-tool.h
redwax-tool/trunk/redwax_openssl.c
Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog (original)
+++ redwax-tool/trunk/ChangeLog Tue May 28 20:18:05 2024
@@ -1,5 +1,9 @@
Changes with v0.9.5
+
+ *) Add --filter-purpose option to allow search and
+ verify to limit certificates by certificate
+ purpose. [Graham Leggett]
*) Fix a crash triggered when keychain is present but
not used. [Graham Leggett]
Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c (original)
+++ redwax-tool/trunk/redwax-tool.c Tue May 28 20:18:05 2024
@@ -78,6 +78,8 @@
APR_HOOK_LINK(complete_verify_param);
APR_HOOK_LINK(set_verify_date);
APR_HOOK_LINK(set_verify_expiry);
+ APR_HOOK_LINK(set_purpose);
+ APR_HOOK_LINK(complete_purpose);
APR_HOOK_LINK(process_pem_in);
APR_HOOK_LINK(process_trust_pem_in);
APR_HOOK_LINK(complete_pkcs11_in);
@@ -130,6 +132,10 @@
(redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_verify_expiry,
(redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_purpose,
+ (redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, complete_purpose,
+ (redwax_tool_t * r, apr_hash_t *purposes), (r, purposes), OK, DECLINED);
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_trust_pem_in,
@@ -225,56 +231,57 @@
#define REDWAX_TOOL_FILTER_CURRENT 266
#define REDWAX_TOOL_FILTER_DATE 267
#define REDWAX_TOOL_FILTER_EXPIRY 268
-#define REDWAX_TOOL_CERT_OUT 269
-#define REDWAX_TOOL_NO_CERT_OUT 270
-#define REDWAX_TOOL_CHAIN_OUT 271
-#define REDWAX_TOOL_NO_CHAIN_OUT 272
-#define REDWAX_TOOL_ROOT_OUT 273
-#define REDWAX_TOOL_NO_ROOT_OUT 274
-#define REDWAX_TOOL_TRUST_OUT 275
-#define REDWAX_TOOL_NO_TRUST_OUT 276
-#define REDWAX_TOOL_CRL_OUT 277
-#define REDWAX_TOOL_NO_CRL_OUT 278
-#define REDWAX_TOOL_PARAM_OUT 279
-#define REDWAX_TOOL_NO_PARAM_OUT 280
-#define REDWAX_TOOL_KEY_IN 281
-#define REDWAX_TOOL_NO_KEY_IN 282
-#define REDWAX_TOOL_KEY_OUT 283
-#define REDWAX_TOOL_NO_KEY_OUT 284
-#define REDWAX_TOOL_AUTO_OUT 285
-#define REDWAX_TOOL_NO_AUTO_OUT 286
-#define REDWAX_TOOL_FILTER_VERIFY_PARAM 287
-#define REDWAX_TOOL_SECRET_SUFFIX_IN 288
-#define REDWAX_TOOL_SECRET_SUFFIX_OUT 289
-#define REDWAX_TOOL_SECRET_TOKEN_IN 290
-#define REDWAX_TOOL_SECRET_TOKEN_OUT 291
-#define REDWAX_TOOL_LABEL_OUT 292
-#define REDWAX_TOOL_NSS_OUT 293
-#define REDWAX_TOOL_NSS_SLOT_OUT 294
-#define REDWAX_TOOL_DER_OUT 295
-#define REDWAX_TOOL_PEM_OUT 296
-#define REDWAX_TOOL_PKCS12_OUT 297
-#define REDWAX_TOOL_PKCS11_OUT 298
-#define REDWAX_TOOL_PKCS11_MODULE_OUT 299
-#define REDWAX_TOOL_METADATA_OUT 300
-#define REDWAX_TOOL_METADATA_THRESHOLD 301
-#define REDWAX_TOOL_FORMAT_OUT 302
-#define REDWAX_TOOL_CALENDAR_OUT 303
-#define REDWAX_TOOL_CALENDAR_ALARM 304
-#define REDWAX_TOOL_REMINDER_OUT 305
-#define REDWAX_TOOL_JWKS_OUT 306
-#define REDWAX_TOOL_TEXT_OUT 307
-#define REDWAX_TOOL_NO_TEXT_OUT 308
-#define REDWAX_TOOL_SSH_PRIVATE_OUT 309
-#define REDWAX_TOOL_SSH_PUBLIC_OUT 310
-#define REDWAX_TOOL_SMIMEA_OUT 311
-#define REDWAX_TOOL_SSHFP_OUT 312
-#define REDWAX_TOOL_TLSA_OUT 313
-#define REDWAX_TOOL_USER_IN 314
-#define REDWAX_TOOL_USER_OUT 315
-#define REDWAX_TOOL_GROUP_IN 316
-#define REDWAX_TOOL_GROUP_OUT 317
-#define REDWAX_TOOL_ORDER_OUT 318
+#define REDWAX_TOOL_FILTER_PURPOSE 269
+#define REDWAX_TOOL_CERT_OUT 270
+#define REDWAX_TOOL_NO_CERT_OUT 271
+#define REDWAX_TOOL_CHAIN_OUT 272
+#define REDWAX_TOOL_NO_CHAIN_OUT 273
+#define REDWAX_TOOL_ROOT_OUT 274
+#define REDWAX_TOOL_NO_ROOT_OUT 275
+#define REDWAX_TOOL_TRUST_OUT 276
+#define REDWAX_TOOL_NO_TRUST_OUT 277
+#define REDWAX_TOOL_CRL_OUT 278
+#define REDWAX_TOOL_NO_CRL_OUT 279
+#define REDWAX_TOOL_PARAM_OUT 280
+#define REDWAX_TOOL_NO_PARAM_OUT 281
+#define REDWAX_TOOL_KEY_IN 282
+#define REDWAX_TOOL_NO_KEY_IN 283
+#define REDWAX_TOOL_KEY_OUT 284
+#define REDWAX_TOOL_NO_KEY_OUT 285
+#define REDWAX_TOOL_AUTO_OUT 286
+#define REDWAX_TOOL_NO_AUTO_OUT 287
+#define REDWAX_TOOL_FILTER_VERIFY_PARAM 288
+#define REDWAX_TOOL_SECRET_SUFFIX_IN 289
+#define REDWAX_TOOL_SECRET_SUFFIX_OUT 290
+#define REDWAX_TOOL_SECRET_TOKEN_IN 291
+#define REDWAX_TOOL_SECRET_TOKEN_OUT 292
+#define REDWAX_TOOL_LABEL_OUT 293
+#define REDWAX_TOOL_NSS_OUT 294
+#define REDWAX_TOOL_NSS_SLOT_OUT 295
+#define REDWAX_TOOL_DER_OUT 296
+#define REDWAX_TOOL_PEM_OUT 297
+#define REDWAX_TOOL_PKCS12_OUT 298
+#define REDWAX_TOOL_PKCS11_OUT 299
+#define REDWAX_TOOL_PKCS11_MODULE_OUT 300
+#define REDWAX_TOOL_METADATA_OUT 301
+#define REDWAX_TOOL_METADATA_THRESHOLD 302
+#define REDWAX_TOOL_FORMAT_OUT 303
+#define REDWAX_TOOL_CALENDAR_OUT 304
+#define REDWAX_TOOL_CALENDAR_ALARM 305
+#define REDWAX_TOOL_REMINDER_OUT 306
+#define REDWAX_TOOL_JWKS_OUT 307
+#define REDWAX_TOOL_TEXT_OUT 308
+#define REDWAX_TOOL_NO_TEXT_OUT 309
+#define REDWAX_TOOL_SSH_PRIVATE_OUT 310
+#define REDWAX_TOOL_SSH_PUBLIC_OUT 311
+#define REDWAX_TOOL_SMIMEA_OUT 312
+#define REDWAX_TOOL_SSHFP_OUT 313
+#define REDWAX_TOOL_TLSA_OUT 314
+#define REDWAX_TOOL_USER_IN 315
+#define REDWAX_TOOL_USER_OUT 316
+#define REDWAX_TOOL_GROUP_IN 317
+#define REDWAX_TOOL_GROUP_OUT 318
+#define REDWAX_TOOL_ORDER_OUT 319
#define REDWAX_EXIT_OK 0
#define REDWAX_EXIT_INIT 1
@@ -320,6 +327,7 @@
" --filter-verify-params=name\tSpecify the name of the set of parameters used\n\t\t\t\tfor verification. If unspecified, set to\n\t\t\t\t'default'." },
{ "filter-date", REDWAX_TOOL_FILTER_DATE, 1, " --filter-date=date\t\tSet the date to be used for certificate\n\t\t\t\tverification. If unset, it will default to the\n\t\t\t\tcurrent time. Date format is generalized time\n\t\t\t\tsyntax as defined in RFC 4517 section 3.3.13." },
{ "filter-expiry", REDWAX_TOOL_FILTER_EXPIRY, 1, " --filter-expiry=[option]\tVerify certificate expiry. 'check' does expiry\n\t\t\t\tverification. 'ignore' allows expired\n\t\t\t\tcertificates. 'ignore-leaf' allows expired leaf\n\t\t\t\tcertificates. 'ignore-chain' allows expired\n\t\t\t\tchain certificates. Default is 'check'." },
+ { "filter-purpose", REDWAX_TOOL_FILTER_PURPOSE, 1, " --filter-purpose=purpose\tSet the purpose of the certificate to verify.\n\t\t\t\tIf unset, it will default to any purpose." },
{ "text-out", REDWAX_TOOL_TEXT_OUT, 0,
" --text-out\t\t\tInclude additional text in certificate PEM and\n\t\t\t\tmetadata output." },
{ "no-text-out", REDWAX_TOOL_NO_TEXT_OUT, 0,
@@ -1749,6 +1757,31 @@
return APR_SUCCESS;
}
+static apr_status_t redwax_complete_purpose(redwax_tool_t *r, const char *arg,
+ redwax_token_quoted_e quoted)
+{
+ apr_hash_t *purposes = apr_hash_make(r->pool);
+
+ apr_hash_index_t *hi;
+ void *val;
+ int arglen = strlen(arg);
+
+ rt_run_complete_purpose(r, purposes);
+
+ for (hi = apr_hash_first(r->pool, purposes); hi; hi = apr_hash_next(hi)) {
+ apr_hash_this(hi, NULL, NULL, &val);
+
+ if (!strncmp(arg, (const char *)val, arglen)) {
+
+ apr_file_printf(r->out, "%s \n",
+ redwax_pescape_echo_quoted(r->pool,
+ (const char *)val, quoted, 1));
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t redwax_complete_nss_token_out(redwax_tool_t *r, const char *arg,
redwax_token_quoted_e quoted)
{
@@ -2285,6 +2318,17 @@
return status;
}
+static apr_status_t redwax_set_purpose(redwax_tool_t *r, const char *arg)
+{
+ apr_status_t status = rt_run_set_purpose(r, arg);
+
+ if (status) {
+ r->rc = REDWAX_EXIT_OPTIONS;
+ }
+
+ return status;
+}
+
static apr_status_t redwax_set_threshold(redwax_tool_t *r, const char *arg)
{
r->threshold = atoi(arg) * 86400;
@@ -2645,6 +2689,12 @@
}
case REDWAX_TOOL_FILTER_EXPIRY: {
if (redwax_set_verify_expiry(r, optarg)) {
+ return REDWAX_EXIT_OPTIONS;
+ }
+ break;
+ }
+ case REDWAX_TOOL_FILTER_PURPOSE: {
+ if (redwax_set_purpose(r, optarg)) {
return REDWAX_EXIT_OPTIONS;
}
break;
@@ -3006,6 +3056,10 @@
redwax_complete_verify_param(r, optarg, state.isquoted);
break;
}
+ case REDWAX_TOOL_FILTER_PURPOSE: {
+ redwax_complete_purpose(r, optarg, state.isquoted);
+ break;
+ }
case REDWAX_TOOL_NSS_OUT: {
redwax_complete_directory(r, optarg, state.isquoted);
break;
@@ -3212,6 +3266,10 @@
}
case REDWAX_TOOL_FILTER_VERIFY_PARAM: {
redwax_complete_verify_param(r, "", state.isquoted);
+ break;
+ }
+ case REDWAX_TOOL_FILTER_PURPOSE: {
+ redwax_complete_purpose(r, "", state.isquoted);
break;
}
case REDWAX_TOOL_NSS_OUT: {
Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h (original)
+++ redwax-tool/trunk/redwax-tool.h Tue May 28 20:18:05 2024
@@ -132,6 +132,7 @@
apr_hash_t *cert_relationships;
const char *verify_param;
const char *verify_date;
+ const char *purpose;
const char *secret_suffix_in;
const char *secret_suffix_out;
const char *secret_token_in;
@@ -719,6 +720,22 @@
(redwax_tool_t *r, const char *arg));
/**
+ * Hook to complete purposes.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_purpose,
+ (redwax_tool_t *r, apr_hash_t *purposes));
+
+/**
+ * Hook to set the purposes.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_purpose,
+ (redwax_tool_t *r, const char *arg));
+
+/**
* Hook to search for intermediate and root certificates.
*
* @param r The redwax-tool context.
Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c (original)
+++ redwax-tool/trunk/redwax_openssl.c Tue May 28 20:18:05 2024
@@ -1660,6 +1660,58 @@
return APR_SUCCESS;
}
+static apr_status_t redwax_openssl_set_purpose(redwax_tool_t *r, const char *arg)
+{
+ int purpose;
+
+ if (0 > (purpose = X509_PURPOSE_get_by_sname(arg))) {
+
+ int i, nelts;
+ int count = X509_PURPOSE_get_count();
+
+ struct iovec *purposes = apr_palloc(r->pool, count * sizeof(struct iovec) * 2);
+
+ for (i = 0, nelts = 0; i < count; i++) {
+ X509_PURPOSE *purpose = X509_PURPOSE_get0(i);
+ char *name = X509_PURPOSE_get0_sname(purpose);
+ if (nelts) {
+ purposes[nelts].iov_base = ", ";
+ purposes[nelts].iov_len = 2;
+ nelts++;
+ }
+ purposes[nelts].iov_base = name;
+ purposes[nelts].iov_len = strlen(name);
+ nelts++;
+ }
+
+ redwax_print_error(r,
+ "Purpose '%s' not found, must be one of: %s\n", arg,
+ apr_pstrcatv(r->pool, purposes, nelts, NULL));
+
+ return APR_ENOENT;
+ }
+
+ r->purpose = arg;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_complete_purpose(redwax_tool_t *r,
+ apr_hash_t *params)
+{
+ int i;
+ int count = X509_PURPOSE_get_count();
+
+ for (i = 0; i < count; i++) {
+ X509_PURPOSE *purpose = X509_PURPOSE_get0(i);
+ char *name = X509_PURPOSE_get0_sname(purpose);
+
+ apr_hash_set(params, name, APR_HASH_KEY_STRING, name);
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t redwax_openssl_complete_filter_search(redwax_tool_t *r,
apr_hash_t *filters)
{
@@ -1671,41 +1723,94 @@
static int search_cert_match(redwax_tool_t *r, const redwax_certificate_t *cert)
{
+ apr_hash_index_t *hi;
+ const void *key;
+ apr_ssize_t klen;
+
const unsigned char *der = cert->der;
X509 *x = d2i_X509(NULL, &der, cert->len);
- int match = 0;
-
if (x) {
- apr_hash_index_t *hi;
- const void *key;
- apr_ssize_t klen;
-
- for (hi = apr_hash_first(r->pool, r->emails); hi; hi = apr_hash_next(hi)) {
- apr_hash_this(hi, &key, &klen, NULL);
-
- if (X509_check_email(x, key, klen, 0) == 1) {
- match = 1;
- }
-
- }
-
- for (hi = apr_hash_first(r->pool, r->hostnames); hi; hi = apr_hash_next(hi)) {
- apr_hash_this(hi, &key, &klen, NULL);
-
- if (X509_check_host(x, key, klen, 0, NULL) == 1) {
- match = 1;
- }
-
- }
-
- for (hi = apr_hash_first(r->pool, r->ips); hi; hi = apr_hash_next(hi)) {
- apr_hash_this(hi, &key, &klen, NULL);
-
- if (X509_check_ip_asc(x, key, 0) == 1) {
- match = 1;
+ if (r->purpose) {
+
+ X509_PURPOSE *xptmp;
+
+ int purpose = X509_PURPOSE_get_by_sname(r->purpose);
+
+ if (purpose == -1) {
+ redwax_print_error(r,
+ "When searchinging, purpose was not recognised: %s\n", r->purpose);
+ return APR_EINVAL;
+ }
+
+ /* purpose index -> purpose object */
+ xptmp = X509_PURPOSE_get0(purpose);
+
+ /* purpose object -> purpose value */
+ purpose = X509_PURPOSE_get_id(xptmp);
+
+ if (!X509_check_purpose(x, purpose, 0)) {
+ X509_free(x);
+ return 0;
+ }
+ }
+
+ if (apr_hash_count(r->emails)) {
+
+ int match = 0;
+
+ for (hi = apr_hash_first(r->pool, r->emails); hi; hi = apr_hash_next(hi)) {
+ apr_hash_this(hi, &key, &klen, NULL);
+
+ if (X509_check_email(x, key, klen, 0) == 1) {
+ match = 1;
+ }
+ }
+
+ if (!match) {
+ X509_free(x);
+ return 0;
+ }
+
+ }
+
+ if (apr_hash_count(r->hostnames)) {
+
+ int match = 0;
+
+ for (hi = apr_hash_first(r->pool, r->hostnames); hi; hi = apr_hash_next(hi)) {
+ apr_hash_this(hi, &key, &klen, NULL);
+
+ if (X509_check_host(x, key, klen, 0, NULL) == 1) {
+ match = 1;
+ }
+
+ }
+ if (!match) {
+ X509_free(x);
+ return 0;
+ }
+
+ }
+
+ if (apr_hash_count(r->ips)) {
+
+ int match = 0;
+
+ for (hi = apr_hash_first(r->pool, r->ips); hi; hi = apr_hash_next(hi)) {
+ apr_hash_this(hi, &key, &klen, NULL);
+
+ if (X509_check_ip_asc(x, key, 0) == 1) {
+ match = 1;
+ }
+
+ }
+
+ if (!match) {
+ X509_free(x);
+ return 0;
}
}
@@ -1713,7 +1818,7 @@
X509_free(x);
}
- return match;
+ return 1;
}
static apr_status_t redwax_openssl_process_filter_search(redwax_tool_t *r,
@@ -1947,6 +2052,31 @@
return APR_ENOENT;
}
+ if (r->purpose) {
+
+ X509_PURPOSE *xptmp;
+
+ int purpose = X509_PURPOSE_get_by_sname(r->purpose);
+
+ if (purpose == -1) {
+ redwax_print_error(r,
+ "When verifying, purpose was not recognised: %s\n", r->purpose);
+ return APR_EINVAL;
+ }
+
+ /* purpose index -> purpose object */
+ xptmp = X509_PURPOSE_get0(purpose);
+
+ /* purpose object -> purpose value */
+ purpose = X509_PURPOSE_get_id(xptmp);
+
+ if (!X509_VERIFY_PARAM_set_purpose(X509_STORE_get0_param(store), purpose)) {
+ redwax_print_error(r,
+ "When verifying, purpose could not be specifed\n");
+ redwax_openssl_print_errors(r);
+ return APR_ENOENT;
+ }
+ }
for (i = 0; i < r->certs_in->nelts; i++)
{
@@ -5972,6 +6102,8 @@
rt_hook_set_verify_param(redwax_openssl_set_verify_param, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_set_verify_date(redwax_openssl_set_verify_date, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_set_verify_expiry(redwax_openssl_set_verify_expiry, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_complete_purpose(redwax_openssl_complete_purpose, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_purpose(redwax_openssl_set_purpose, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_pem_in(redwax_openssl_process_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_trust_pem_in(redwax_openssl_process_trust_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_pkcs12_in(redwax_openssl_process_pkcs12_in, NULL, NULL, APR_HOOK_MIDDLE);
More information about the rt-commit
mailing list