[rt-commit] r182 - in /redwax-tool/trunk: ChangeLog redwax-tool.c redwax-tool.h redwax_keychain.c redwax_ldns.c redwax_openssl.c redwax_unbound.c redwax_unbound.h
rt-commit at redwax.eu
rt-commit at redwax.eu
Mon Jun 3 16:10:34 CEST 2024
Author: minfrin at redwax.eu
Date: Mon Jun 3 16:10:32 2024
New Revision: 182
Log:
Add --filter-verify-tlsa to perform a DNS lookup
and subsequent verification of certificates against
a TLSA record.
Modified:
redwax-tool/trunk/ChangeLog
redwax-tool/trunk/redwax-tool.c
redwax-tool/trunk/redwax-tool.h
redwax-tool/trunk/redwax_keychain.c
redwax-tool/trunk/redwax_ldns.c
redwax-tool/trunk/redwax_openssl.c
redwax-tool/trunk/redwax_unbound.c
redwax-tool/trunk/redwax_unbound.h
Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog (original)
+++ redwax-tool/trunk/ChangeLog Mon Jun 3 16:10:32 2024
@@ -1,5 +1,9 @@
Changes with v0.9.5
+
+ *) Add --filter-verify-tlsa to perform a DNS lookup
+ and subsequent verification of certificates against
+ a TLSA record. [Graham Leggett]
*) Add --filter-purpose option to allow search and
verify to limit certificates by certificate
Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c (original)
+++ redwax-tool/trunk/redwax-tool.c Mon Jun 3 16:10:32 2024
@@ -74,12 +74,18 @@
APR_HOOK_STRUCT(
APR_HOOK_LINK(initialise);
+ APR_HOOK_LINK(set_dns_server);
+ APR_HOOK_LINK(set_dns_trust_anchor);
APR_HOOK_LINK(set_verify_param);
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(set_tlsa);
+ APR_HOOK_LINK(process_tlsa);
+ APR_HOOK_LINK(set_smimea);
+ APR_HOOK_LINK(process_smimea);
APR_HOOK_LINK(process_pem_in);
APR_HOOK_LINK(process_trust_pem_in);
APR_HOOK_LINK(complete_pkcs11_in);
@@ -120,10 +126,16 @@
APR_HOOK_LINK(normalise_key);
APR_HOOK_LINK(normalise_certificate);
APR_HOOK_LINK(add_dns_metadata);
+ APR_HOOK_LINK(process_dns);
+ APR_HOOK_LINK(filter_poll);
);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, initialise,
(redwax_tool_t * r), (r), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_dns_server,
+ (redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_dns_trust_anchor,
+ (redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_verify_param,
(redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, complete_verify_param,
@@ -136,6 +148,14 @@
(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_ALL(rt, REDWAX, int, set_tlsa,
+ (redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_tlsa,
+ (redwax_tool_t * r, redwax_dns_t *dns), (r, dns), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, set_smimea,
+ (redwax_tool_t * r, const char *arg), (r, arg), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_smimea,
+ (redwax_tool_t * r, redwax_dns_t *dns), (r, dns), 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,
@@ -211,6 +231,10 @@
(redwax_tool_t * r, redwax_certificate_t *cert, int index), (r, cert, index), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, apr_status_t, add_dns_metadata,
(redwax_tool_t *r, redwax_metadata_t *m, const redwax_certificate_t *cert), (r, m, cert), OK, DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_dns,
+ (redwax_tool_t * r, redwax_dns_t *dns, redwax_rdata_t *rdata), (r, dns, rdata), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, apr_status_t, filter_poll,
+ (redwax_tool_t *r), (r), OK, DECLINED);
#define REDWAX_TOOL_COMPLINE "COMP_LINE"
#define REDWAX_TOOL_COMMANDLINE "COMMAND_LINE"
@@ -232,56 +256,60 @@
#define REDWAX_TOOL_FILTER_DATE 267
#define REDWAX_TOOL_FILTER_EXPIRY 268
#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_TOOL_FILTER_VERIFY_PARAM 270
+#define REDWAX_TOOL_FILTER_VERIFY_TLSA 271
+#define REDWAX_TOOL_FILTER_VERIFY_SMIMEA 272
+#define REDWAX_TOOL_CERT_OUT 274
+#define REDWAX_TOOL_NO_CERT_OUT 275
+#define REDWAX_TOOL_CHAIN_OUT 276
+#define REDWAX_TOOL_NO_CHAIN_OUT 277
+#define REDWAX_TOOL_ROOT_OUT 278
+#define REDWAX_TOOL_NO_ROOT_OUT 279
+#define REDWAX_TOOL_TRUST_OUT 280
+#define REDWAX_TOOL_NO_TRUST_OUT 281
+#define REDWAX_TOOL_CRL_OUT 282
+#define REDWAX_TOOL_NO_CRL_OUT 283
+#define REDWAX_TOOL_PARAM_OUT 284
+#define REDWAX_TOOL_NO_PARAM_OUT 285
+#define REDWAX_TOOL_KEY_IN 286
+#define REDWAX_TOOL_NO_KEY_IN 287
+#define REDWAX_TOOL_KEY_OUT 288
+#define REDWAX_TOOL_NO_KEY_OUT 289
+#define REDWAX_TOOL_AUTO_OUT 290
+#define REDWAX_TOOL_NO_AUTO_OUT 291
+#define REDWAX_TOOL_SECRET_SUFFIX_IN 292
+#define REDWAX_TOOL_SECRET_SUFFIX_OUT 293
+#define REDWAX_TOOL_SECRET_TOKEN_IN 294
+#define REDWAX_TOOL_SECRET_TOKEN_OUT 295
+#define REDWAX_TOOL_LABEL_OUT 296
+#define REDWAX_TOOL_NSS_OUT 297
+#define REDWAX_TOOL_NSS_SLOT_OUT 298
+#define REDWAX_TOOL_DER_OUT 299
+#define REDWAX_TOOL_PEM_OUT 300
+#define REDWAX_TOOL_PKCS12_OUT 301
+#define REDWAX_TOOL_PKCS11_OUT 302
+#define REDWAX_TOOL_PKCS11_MODULE_OUT 303
+#define REDWAX_TOOL_METADATA_OUT 304
+#define REDWAX_TOOL_METADATA_THRESHOLD 305
+#define REDWAX_TOOL_FORMAT_OUT 306
+#define REDWAX_TOOL_CALENDAR_OUT 307
+#define REDWAX_TOOL_CALENDAR_ALARM 308
+#define REDWAX_TOOL_REMINDER_OUT 309
+#define REDWAX_TOOL_JWKS_OUT 310
+#define REDWAX_TOOL_TEXT_OUT 311
+#define REDWAX_TOOL_NO_TEXT_OUT 312
+#define REDWAX_TOOL_SSH_PRIVATE_OUT 313
+#define REDWAX_TOOL_SSH_PUBLIC_OUT 314
+#define REDWAX_TOOL_SMIMEA_OUT 315
+#define REDWAX_TOOL_SSHFP_OUT 316
+#define REDWAX_TOOL_TLSA_OUT 317
+#define REDWAX_TOOL_USER_IN 318
+#define REDWAX_TOOL_USER_OUT 319
+#define REDWAX_TOOL_GROUP_IN 320
+#define REDWAX_TOOL_GROUP_OUT 321
+#define REDWAX_TOOL_ORDER_OUT 322
+#define REDWAX_TOOL_DNS_SERVER 323
+#define REDWAX_TOOL_DNS_TRUST_ANCHOR 324
#define REDWAX_EXIT_OK 0
#define REDWAX_EXIT_INIT 1
@@ -307,13 +335,15 @@
" -q, --quiet\t\t\tBe quiet. Errors are suppressed." },
{ "debug", 'd', 0,
" -d, --debug\t\t\tBe loud. Print additional details of our progress." },
+ { "dns-server", REDWAX_TOOL_DNS_SERVER, 1, " --dns-server=ip\t\tIf specified, supplies the IP address of the\n\t\t\t\tupstream DNS server. May be specified more\n\t\t\t\tthan once. If unspecified, will read from\n\t\t\t\t/etc/resolv.conf." },
+ { "dns-trust-anchor", REDWAX_TOOL_DNS_TRUST_ANCHOR, 1, " --dns-trust-anchor=file\tSpecify the file containing the DNSSEC trust\n\t\t\t\tanchor. If unspecified, the key may be read\n\t\t\t\tfrom an OS specific default location." },
{ "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." },
- { "trust-pem-in", REDWAX_TOOL_TRUST_PEM_IN, 1, " --trust-pem-in=wildcard\tRead pem files containing trusted certificates from here. Use '-' for stdin." },
+ { "trust-pem-in", REDWAX_TOOL_TRUST_PEM_IN, 1, " --trust-pem-in=wildcard\tRead pem files containing trusted certificates\n\t\t\t\tfrom here. Use '-' for stdin." },
{ "pkcs12-in", REDWAX_TOOL_PKCS12_IN, 1, " --pkcs12-in=file\t\tRead certificates, intermediate certificates,\n\t\t\t\troot certificates, crls, and keys from a PKCS12\n\t\t\t\tfile. Use '-' for stdin. Provide the secret\n\t\t\t\tusing --secret-suffix-in." },
{ "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." },
{ "pkcs11-module-in", REDWAX_TOOL_PKCS11_MODULE_IN, 1, " --pkcs11-module-in=mod\tSpecify the name of the PKCS11 module to be used,\n\t\t\t\toverriding system defaults. If relative, use the\n\t\t\t\tdefault PKCS11 module path, otherwise specify the\n\t\t\t\tabsolute path. Include the extension of the module." },
@@ -325,6 +355,12 @@
{ "filter-current", REDWAX_TOOL_FILTER_CURRENT, 0, " --filter-current\t\tMatch the top ranking leaf certificate, and\n\t\t\t\tignore all other leaf certificates. The top\n\t\t\t\tcertificate is valid, and has the longest time\n\t\t\t\tto expiry." },
{ "filter-verify-params", REDWAX_TOOL_FILTER_VERIFY_PARAM, 1,
" --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-verify-tlsa", REDWAX_TOOL_FILTER_VERIFY_TLSA, 1,
+ " --filter-verify-tlsa=url\tPerform DANE verification on the server\n\t\t\t\tcertificate. The parameter is an URL, with a\n\t\t\t\thostname, optional scheme defaulting to tcp,\n\t\t\t\tand optional port defaulting to 443 (example:\n\t\t\t\ttcp://example.com:443). If unspecified, no\n\t\t\t\tDANE verification is performed." },
+#if 0
+ { "filter-verify-smimea", REDWAX_TOOL_FILTER_VERIFY_SMIMEA, 1,
+ " --filter-verify-smimea=addr\tPerform DANE verification on the client\n\t\t\t\tcertificate. The parameter is an email address.\n\t\t\t\tIf unspecified, no DANE verification\n\t\t\t\tis performed." },
+#endif
{ "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." },
@@ -1175,6 +1211,28 @@
return APR_SUCCESS;
}
+static apr_status_t redwax_set_dns_server(redwax_tool_t *r, const char *arg)
+{
+ apr_status_t status = rt_run_set_dns_server(r, arg);
+
+ if (status) {
+ r->rc = REDWAX_EXIT_FILTER;
+ }
+
+ return status;
+}
+
+static apr_status_t redwax_set_dns_trust_anchor(redwax_tool_t *r, const char *arg)
+{
+ apr_status_t status = rt_run_set_dns_trust_anchor(r, arg);
+
+ if (status) {
+ r->rc = REDWAX_EXIT_FILTER;
+ }
+
+ return status;
+}
+
apr_status_t redwax_set_user(redwax_tool_t *r, const char *user)
{
struct passwd *pw;
@@ -2052,6 +2110,34 @@
return APR_SUCCESS;
}
+static apr_status_t redwax_filter_poll_cb(void *baton, apr_pollfd_t *descriptor)
+{
+ redwax_tool_t *r = (redwax_tool_t *) baton;
+ redwax_pollfd_t *ctx = (redwax_pollfd_t *) descriptor->client_data;
+
+ /* remove our event */
+ apr_pollcb_remove(r->poll, descriptor);
+
+ return ctx->cb(r, ctx->ctx, descriptor);
+}
+
+static apr_status_t redwax_filter_poll(redwax_tool_t *r)
+{
+ apr_status_t status = APR_SUCCESS;
+
+ while (r->poll_work) {
+
+ status = apr_pollcb_poll(r->poll, -1, redwax_filter_poll_cb, r);
+
+ if (APR_SUCCESS != status) {
+ break;
+ }
+
+ }
+
+ return status;
+}
+
apr_status_t redwax_complete_filter_passthrough(redwax_tool_t *r,
apr_hash_t *filters)
{
@@ -2318,6 +2404,28 @@
return status;
}
+static apr_status_t redwax_set_tlsa(redwax_tool_t *r, const char *arg)
+{
+ apr_status_t status = rt_run_set_tlsa(r, arg);
+
+ if (status) {
+ r->rc = REDWAX_EXIT_OPTIONS;
+ }
+
+ return status;
+}
+
+static apr_status_t redwax_set_smimea(redwax_tool_t *r, const char *arg)
+{
+ apr_status_t status = rt_run_set_smimea(r, arg);
+
+ if (status) {
+ r->rc = REDWAX_EXIT_OPTIONS;
+ }
+
+ 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);
@@ -2537,6 +2645,7 @@
void redwax_add_default_hooks()
{
+ rt_hook_filter_poll(redwax_filter_poll, NULL, NULL, APR_HOOK_LAST);
rt_hook_complete_filter(redwax_complete_filter_passthrough, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_filter(redwax_process_filter_passthrough, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_filter(redwax_process_filter_default, NULL, NULL,
@@ -2574,6 +2683,18 @@
r->debug++;
break;
}
+ case REDWAX_TOOL_DNS_SERVER: {
+ if (redwax_set_dns_server(r, optarg)) {
+ return REDWAX_EXIT_AUTH;
+ }
+ break;
+ }
+ case REDWAX_TOOL_DNS_TRUST_ANCHOR: {
+ if (redwax_set_dns_trust_anchor(r, optarg)) {
+ return REDWAX_EXIT_AUTH;
+ }
+ break;
+ }
}
}
@@ -2699,9 +2820,28 @@
}
break;
}
- }
-
- }
+ case REDWAX_TOOL_FILTER_VERIFY_TLSA: {
+ if (redwax_set_tlsa(r, optarg)) {
+ return REDWAX_EXIT_OPTIONS;
+ }
+ break;
+ }
+ case REDWAX_TOOL_FILTER_VERIFY_SMIMEA: {
+ if (redwax_set_smimea(r, optarg)) {
+ return REDWAX_EXIT_OPTIONS;
+ }
+ break;
+ }
+ }
+
+ }
+
+ /* filters poll */
+
+ if (rt_run_filter_poll(r)) {
+ return REDWAX_EXIT_OPTIONS;
+ }
+
/* walk filters */
@@ -3116,6 +3256,10 @@
redwax_complete_order_out(r, optarg, state.isquoted);
break;
}
+ case REDWAX_TOOL_DNS_TRUST_ANCHOR: {
+ redwax_complete_file(r, optarg, state.isquoted);
+ break;
+ }
}
}
@@ -3326,6 +3470,10 @@
}
case REDWAX_TOOL_ORDER_OUT: {
redwax_complete_order_out(r, "", state.isquoted);
+ break;
+ }
+ case REDWAX_TOOL_DNS_TRUST_ANCHOR: {
+ redwax_complete_file(r, "", state.isquoted);
break;
}
}
@@ -3433,6 +3581,8 @@
apr_hook_sort_all();
+ r.per_module = redwax_create_module_config(r.pool);
+
#if HAVE_LIBGEN_H
r.base = basename(apr_pstrdup(r.pool, argv[0]));
#endif
@@ -3472,10 +3622,16 @@
r.hostnames = apr_hash_make(r.pool);
r.ips = apr_hash_make(r.pool);
+ r.dns_requests = apr_array_make(r.pool, 10, sizeof(redwax_dns_t));
+
r.pkcs11_in.pkcs11_modules = apr_array_make(r.pool, 10,
sizeof(const char*));
r.pkcs11_out.pkcs11_modules = apr_array_make(r.pool, 10,
sizeof(const char*));
+
+ if (APR_SUCCESS != (status = apr_pollcb_create(&r.poll, 1, r.pool, APR_POLLSET_DEFAULT))) {
+ exit(REDWAX_EXIT_INIT);
+ }
if (apr_gethostname(str, sizeof(str) - 1, r.pool) != APR_SUCCESS) {
apr_file_printf(r.err, "%s: could not read the servername.\n", argv[0]);
Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h (original)
+++ redwax-tool/trunk/redwax-tool.h Mon Jun 3 16:10:32 2024
@@ -26,6 +26,7 @@
#include <apr_file_io.h>
#include <apr_hash.h>
#include <apr_hooks.h>
+#include <apr_poll.h>
#include <apr_pools.h>
#include <apr_tables.h>
@@ -120,6 +121,7 @@
apr_array_header_t *crls_out;
apr_array_header_t *keys_in;
apr_array_header_t *keys_out;
+ apr_array_header_t *dns_requests;
apr_hash_t *emails;
apr_hash_t *hostnames;
apr_hash_t *ips;
@@ -143,6 +145,8 @@
const char *group_in;
const char *group_out;
const char *calendar_alarm;
+ const char *dane_basename;
+ apr_pollcb_t *poll;
redwax_filter_t filter;
redwax_nss_t nss_out;
redwax_pkcs11_t pkcs11_in;
@@ -151,6 +155,7 @@
redwax_format_e format;
redwax_order_e order;
redwax_expiry_e expiry;
+ int poll_work;
int current;
int cert_out;
int chain_out;
@@ -334,6 +339,53 @@
apr_size_t size;
} redwax_offset_t;
+typedef struct redwax_dns_t redwax_dns_t;
+
+typedef apr_status_t(* redwax_dns_cb_t) (redwax_tool_t *r, redwax_dns_t *dns);
+
+typedef struct redwax_rdata_tlsa_t {
+ const char *usage_name;
+ const char *selector_name;
+ const char *mtype_name;
+ unsigned char usage;
+ unsigned char selector;
+ unsigned char mtype;
+ unsigned char *data;
+ int len;
+} redwax_rdata_tlsa_t;
+
+typedef struct redwax_rdata_t {
+ unsigned char *data;
+ int len;
+ union {
+ redwax_rdata_tlsa_t tlsa;
+ } rr;
+} redwax_rdata_t;
+
+typedef struct redwax_dns_t {
+ redwax_tool_t *r;
+ const char *basename;
+ const char *qname;
+ int rrtype;
+ int rrclass;
+ apr_array_header_t *rdata;
+ const char *canonname;
+ int havedata;
+ int nxdomain;
+ int secure;
+ int bogus;
+ const char *why_bogus;
+ redwax_dns_cb_t cb;
+ void *ctx;
+} redwax_dns_t;
+
+typedef apr_status_t(* redwax_pollfd_cb_t) (redwax_tool_t *r, void *ctx, apr_pollfd_t *descriptor);
+
+typedef struct redwax_pollfd_t {
+ redwax_pollfd_cb_t cb;
+ void *ctx;
+} redwax_pollfd_t;
+
typedef enum redwax_token_escape_e {
REDWAX_TOKEN_NOESCAPE = 0,
REDWAX_TOKEN_WASESCAPE,
@@ -400,6 +452,14 @@
#define MAXHOSTNAMELEN 256
#endif
+#ifndef APR_WANT_READ
+#define APR_WANT_READ (APR_UTIL_START_STATUS + 115)
+#endif
+
+#ifndef APR_WANT_WRITE
+#define APR_WANT_WRITE (APR_UTIL_START_STATUS + 116)
+#endif
+
/*
* Comparisons.
*/
@@ -736,6 +796,38 @@
(redwax_tool_t *r, const char *arg));
/**
+ * Hook to set the tlsa.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_tlsa,
+ (redwax_tool_t *r, const char *arg));
+
+/**
+ * Hook to set the smimea.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_smimea,
+ (redwax_tool_t *r, const char *arg));
+
+/**
+ * Hook to set the DNS server address.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_dns_server,
+ (redwax_tool_t *r, const char *arg));
+
+/**
+ * Hook to set the DNS trust anchor.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_dns_trust_anchor,
+ (redwax_tool_t *r, const char *arg));
+
+/**
* Hook to search for intermediate and root certificates.
*
* @param r The redwax-tool context.
@@ -797,4 +889,42 @@
APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, add_dns_metadata,
(redwax_tool_t *r, redwax_metadata_t *m, const redwax_certificate_t *cert));
+/**
+ * Hook to process DNS results.
+ *
+ * @param r The redwax-tool context.
+ * @param dns The dns result.
+ * @param rdata The dns record.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_dns,
+ (redwax_tool_t *r, redwax_dns_t *dns, redwax_rdata_t *rdata));
+
+/**
+ * Hook to process TLSA results.
+ *
+ * @param r The redwax-tool context.
+ * @param dns The dns result.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_tlsa,
+ (redwax_tool_t *r, redwax_dns_t *dns));
+
+/**
+ * Hook to process SMIMEA results.
+ *
+ * @param r The redwax-tool context.
+ * @param dns The dns result.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_smimea,
+ (redwax_tool_t *r, redwax_dns_t *dns));
+
+/**
+ * Hook to run the pre-filter poll.
+ *
+ * This is where DNS lookups and TLS connection attempts happen.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, filter_poll,
+ (redwax_tool_t *r));
+
#endif
Modified: redwax-tool/trunk/redwax_keychain.c
==============================================================================
--- redwax-tool/trunk/redwax_keychain.c (original)
+++ redwax-tool/trunk/redwax_keychain.c Mon Jun 3 16:10:32 2024
@@ -578,7 +578,6 @@
keychain_config_t *config;
- r->per_module = redwax_create_module_config(r->pool);
config = apr_pcalloc(r->pool, sizeof(keychain_config_t));
redwax_set_module_config(r->per_module, &keychain_module, config);
Modified: redwax-tool/trunk/redwax_ldns.c
==============================================================================
--- redwax-tool/trunk/redwax_ldns.c (original)
+++ redwax-tool/trunk/redwax_ldns.c Mon Jun 3 16:10:32 2024
@@ -178,10 +178,103 @@
return OK;
}
+static apr_status_t redwax_ldns_process_dns(redwax_tool_t *r,
+ redwax_dns_t *dns, redwax_rdata_t *rdata)
+{
+
+ switch (dns->rrtype) {
+ case LDNS_RR_TYPE_TLSA: {
+
+ ldns_buffer buffer;
+
+ ldns_buffer_new_frm_data(&buffer, rdata->data, rdata->len);
+
+ if (!ldns_buffer_available(&buffer, 3)) {
+ redwax_print_error(r, "process-dns: TLSA record too short (<3)\n");
+ return APR_EGENERAL;
+ }
+ else {
+
+ rdata->rr.tlsa.usage = ldns_buffer_read_u8(&buffer);
+ rdata->rr.tlsa.selector = ldns_buffer_read_u8(&buffer);
+ rdata->rr.tlsa.mtype = ldns_buffer_read_u8(&buffer);
+
+ rdata->rr.tlsa.len = ldns_buffer_remaining(&buffer);
+ rdata->rr.tlsa.data = apr_palloc(r->pool, rdata->rr.tlsa.len);
+
+ ldns_buffer_read(&buffer, rdata->rr.tlsa.data, rdata->rr.tlsa.len);
+
+ switch (rdata->rr.tlsa.usage) {
+ case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+ rdata->rr.tlsa.usage_name = "CA constraint";
+ break;
+ case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+ rdata->rr.tlsa.usage_name = "Service certificate constraint";
+ break;
+ case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+ rdata->rr.tlsa.usage_name = "Trust anchor assertion";
+ break;
+ case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
+ rdata->rr.tlsa.usage_name = "Domain issued certificate";
+ break;
+ case LDNS_TLSA_USAGE_PRIVCERT:
+ rdata->rr.tlsa.usage_name = "Private use";
+ break;
+ default:
+ rdata->rr.tlsa.usage_name = "Unassigned";
+ break;
+ }
+
+ switch (rdata->rr.tlsa.selector) {
+ case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
+ rdata->rr.tlsa.selector_name = "CA constraint";
+ break;
+ case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
+ rdata->rr.tlsa.selector_name = "Service certificate constraint";
+ break;
+ case LDNS_TLSA_SELECTOR_PRIVSEL:
+ rdata->rr.tlsa.selector_name = "Private use";
+ break;
+ default:
+ rdata->rr.tlsa.selector_name = "Unassigned";
+ break;
+ }
+
+ switch (rdata->rr.tlsa.mtype) {
+ case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
+ rdata->rr.tlsa.mtype_name = "No hash used";
+ break;
+ case LDNS_TLSA_MATCHING_TYPE_SHA256:
+ rdata->rr.tlsa.mtype_name = "SHA-256";
+ break;
+ case LDNS_TLSA_MATCHING_TYPE_SHA512:
+ rdata->rr.tlsa.mtype_name = "SHA-512";
+ break;
+ case LDNS_TLSA_MATCHING_TYPE_PRIVMATCH:
+ rdata->rr.tlsa.mtype_name = "Private use";
+ break;
+ default:
+ rdata->rr.tlsa.mtype_name = "Unassigned";
+ break;
+ }
+
+ }
+
+ break;
+ }
+ default: {
+ redwax_print_error(r, "process-dns: unexpected record type: %d\n", dns->rrtype);
+ return APR_ENOTIMPL;
+ }
+ }
+ return APR_SUCCESS;
+}
+
void redwax_add_default_ldns_hooks()
{
rt_hook_initialise(redwax_ldns_initialise, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_add_dns_metadata(redwax_ldns_add_tlsa_metadata, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_process_dns(redwax_ldns_process_dns, NULL, NULL, APR_HOOK_MIDDLE);
}
#else
Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c (original)
+++ redwax-tool/trunk/redwax_openssl.c Mon Jun 3 16:10:32 2024
@@ -47,6 +47,7 @@
#if HAVE_OPENSSL_CT_H
#include <openssl/ct.h>
#endif
+#include <openssl/ssl.h>
#define REDWAX_OPENSSL_SEARCH "search"
#define REDWAX_OPENSSL_VERIFY "verify"
@@ -60,6 +61,12 @@
module openssl_module;
+typedef struct {
+ SSL_CTX *dane_ctx;
+ SSL *dane_ssl;
+} openssl_config_t;
+
+// move to config above
static STACK_OF(X509) *cert_index;
static STACK_OF(X509) *chain_index;
static STACK_OF(X509) *trusted_index;
@@ -1069,8 +1076,42 @@
return APR_SUCCESS;
}
+static apr_status_t cleanup_SSL_CTX(void *dummy)
+{
+ if (dummy) {
+ SSL_CTX_free(dummy);
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t cleanup_SSL(void *dummy)
+{
+ if (dummy) {
+ SSL_free(dummy);
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t redwax_openssl_initialise(redwax_tool_t *r)
{
+ openssl_config_t *config;
+
+ config = apr_pcalloc(r->pool, sizeof(openssl_config_t));
+ redwax_set_module_config(r->per_module, &openssl_module, config);
+
+ config->dane_ctx = SSL_CTX_new(TLS_client_method());
+
+ SSL_CTX_dane_enable(config->dane_ctx);
+
+ config->dane_ssl = SSL_new(config->dane_ctx);
+
+ apr_pool_cleanup_register(r->pool, config->dane_ctx, cleanup_SSL_CTX,
+ apr_pool_cleanup_null);
+ apr_pool_cleanup_register(r->pool, config->dane_ssl, cleanup_SSL,
+ apr_pool_cleanup_null);
+
cert_index = sk_X509_new_null();
chain_index = sk_X509_new_null();
trusted_index = sk_X509_new_null();
@@ -1819,6 +1860,95 @@
}
return 1;
+}
+
+static apr_status_t redwax_openssl_set_tlsa(redwax_tool_t *r, const char *arg)
+{
+ openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
+ if (r->dane_basename) {
+
+ if (SSL_dane_enable(config->dane_ssl, r->dane_basename) <= 0) {
+
+ redwax_openssl_print_errors(r);
+ redwax_print_error(r,
+ "Warning: Could not enable dane for '%s'\n",
+ r->dane_basename);
+
+ return APR_EINVAL;
+ }
+
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_process_tlsa(redwax_tool_t *r, redwax_dns_t *dns)
+{
+ openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
+ if (dns->bogus) {
+
+ redwax_print_error(r,
+ "filter-verify-tlsa: DNS TLSA response for '%s' failed "
+ "DNSSEC validation, ignoring: %s.\n", dns->qname, dns->why_bogus);
+
+ return APR_SUCCESS;
+ }
+
+ if (!dns->secure) {
+
+ redwax_print_error(r,
+ "filter-verify-tlsa: DNS TLSA response for '%s' is "
+ "not DNSSEC secured, ignoring.\n", dns->qname);
+
+ return APR_SUCCESS;
+ }
+
+ if (dns->nxdomain) {
+
+ redwax_print_error(r,
+ "filter-verify-tlsa: DNS TLSA record for '%s' does "
+ "not exist, ignoring.\n", dns->qname);
+
+ return APR_SUCCESS;
+ }
+
+ if (dns->rdata) {
+
+ int i;
+
+ for (i = 0; i < dns->rdata->nelts; i++)
+ {
+ const redwax_rdata_t *rdata = &APR_ARRAY_IDX(dns->rdata, i,
+ const redwax_rdata_t);
+
+ if (SSL_dane_tlsa_add(config->dane_ssl, rdata->rr.tlsa.usage, rdata->rr.tlsa.selector, rdata->rr.tlsa.mtype,
+ rdata->rr.tlsa.data, rdata->rr.tlsa.len) <= 0) {
+
+ redwax_openssl_print_errors(r);
+ redwax_print_error(r,
+ "filter-verify-tlsa: DNS TLSA record for '%s' not "
+ "accepted, ignoring.\n", dns->qname);
+
+ }
+ else {
+
+ redwax_print_error(r,
+ "filter-verify-tlsa: DNS TLSA record for '%s' found "
+ "(usage: %s[%d], selector: %s[%d], matching: %s[%d], digest: %d bytes)\n", dns->qname,
+ rdata->rr.tlsa.usage_name, rdata->rr.tlsa.usage,
+ rdata->rr.tlsa.selector_name, rdata->rr.tlsa.selector,
+ rdata->rr.tlsa.mtype_name, rdata->rr.tlsa.mtype,
+ rdata->rr.tlsa.len);
+
+ }
+
+ }
+
+ }
+
+ return APR_SUCCESS;
}
static apr_status_t redwax_openssl_process_filter_search(redwax_tool_t *r,
@@ -1983,6 +2113,8 @@
static apr_status_t redwax_openssl_process_filter_verify(redwax_tool_t *r,
const char *arg)
{
+ openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
X509_STORE_CTX *ctx;
X509_STORE *store;
apr_hash_index_t *hi;
@@ -2109,6 +2241,10 @@
now_t = mktime(&now_tm);
X509_STORE_CTX_set_time(ctx, 0, now_t);
+ }
+
+ if (r->dane_basename) {
+ X509_STORE_CTX_set0_dane(ctx, SSL_get0_dane(config->dane_ssl));
}
X509_STORE_CTX_set_verify_cb(ctx, &verify_cb);
@@ -6107,6 +6243,8 @@
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);
+ rt_hook_set_tlsa(redwax_openssl_set_tlsa, NULL, NULL, APR_HOOK_LAST);
+ rt_hook_process_tlsa(redwax_openssl_process_tlsa, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_complete_filter(redwax_openssl_complete_filter_verify, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_process_filter(redwax_openssl_process_filter_verify, NULL, NULL, APR_HOOK_MIDDLE);
rt_hook_complete_filter(redwax_openssl_complete_filter_search, NULL, NULL, APR_HOOK_MIDDLE);
Modified: redwax-tool/trunk/redwax_unbound.c
==============================================================================
--- redwax-tool/trunk/redwax_unbound.c (original)
+++ redwax-tool/trunk/redwax_unbound.c Mon Jun 3 16:10:32 2024
@@ -25,21 +25,469 @@
#include "config.h"
#include "redwax-tool.h"
+#include "redwax_unbound.h"
#include "redwax_util.h"
#if HAVE_UNBOUND_H
+#include "apr_portable.h"
+#include "apr_uri.h"
+
+#include <netdb.h>
+
+#include <unbound.h>
+
module unbound_module;
+typedef struct {
+ struct ub_ctx *ctx;
+ apr_pollfd_t socket_read;
+ redwax_pollfd_t read_ctx;
+ apr_pollfd_t socket_write;
+ redwax_pollfd_t write_ctx;
+ apr_status_t status;
+ int socket_read_work;
+ int dns_work;
+ int dns_server_set;
+ int dns_trust_anchor_set;
+} unbound_config_t;
+
+static apr_status_t cleanup_ub(void *dummy)
+{
+ struct ub_ctx *ctx = dummy;
+
+ ub_ctx_delete(ctx);
+
+ return APR_SUCCESS;
+}
+
static apr_status_t redwax_unbound_initialise(redwax_tool_t *r)
{
+ unbound_config_t *config;
+
+ config = apr_pcalloc(r->pool, sizeof(unbound_config_t));
+ redwax_set_module_config(r->per_module, &unbound_module, config);
+
+ /* create an unbound context */
+ config->ctx = ub_ctx_create();
+ if(!config->ctx) {
+ redwax_print_error(r,
+ "Could not create unbound context\n");
+ return APR_EINIT;
+ }
+
+ apr_pool_cleanup_register(r->pool, config->ctx, cleanup_ub,
+ apr_pool_cleanup_null);
return OK;
}
+static apr_status_t redwax_unbound_set_dns_server(redwax_tool_t *r, const char *arg)
+{
+ unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ int rv;
+
+ if ((rv = ub_ctx_set_fwd(config->ctx, arg)) != 0) {
+ redwax_print_error(r,
+ "Could not assign DNS server '%s': %s\n",
+ arg, ub_strerror(rv));
+ return APR_EINIT;
+ }
+
+ config->dns_server_set++;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_unbound_set_dns_trust_anchor(redwax_tool_t *r, const char *arg)
+{
+ unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ int rv;
+
+ if ((rv = ub_ctx_add_ta_file(config->ctx, arg)) != 0) {
+ redwax_print_error(r,
+ "Could not read DNS trust anchor '%s': %s (%s)\n",
+ arg, ub_strerror(rv), strerror(errno));
+ return APR_EINIT;
+ }
+
+ config->dns_trust_anchor_set++;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_unbound_set_tlsa(redwax_tool_t *r, const char *arg)
+{
+ apr_uri_t uri;
+
+ apr_status_t status;
+
+ if (r->dane_basename) {
+ redwax_print_error(r,
+ "URI '%s': filter-verify-tlsa can only be specified once\n", arg);
+ return APR_EINVAL;
+ }
+
+ status = apr_uri_parse(r->pool, arg, &uri);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not parse URI '%s': %pm\n", arg, &status);
+ return status;
+ }
+
+ if (!uri.hostname) {
+ redwax_print_error(r,
+ "URI '%s': hostname missing\n", arg);
+ return APR_EINVAL;
+ }
+ else {
+ r->dane_basename = uri.hostname;
+ }
+
+ if (!strcmp(uri.scheme, "tcp") || !strcmp(uri.scheme, "udp")) {
+
+ if (uri.port) {
+
+ const char *tlsa = apr_psprintf(r->pool, "_%d._%s.%s", uri.port, uri.scheme, uri.hostname);
+
+ redwax_dns_t *dns = apr_array_push(r->dns_requests);
+
+ dns->r = r;
+ dns->basename = uri.hostname;
+ dns->qname = tlsa;
+ dns->rrtype = 52 /* TYPE TLSA */;
+ dns->rrclass = 1 /* CLASS IN (internet) */;
+ dns->cb = rt_run_process_tlsa;
+
+ return APR_SUCCESS;
+ }
+ else {
+ redwax_print_error(r,
+ "URI '%s': port missing\n", arg);
+ return APR_EINVAL;
+ }
+ }
+
+ if (uri.scheme) {
+
+ int found = 0;
+
+ setservent(1);
+
+ struct servent *ent;
+
+ while ((ent = getservent())) {
+
+ if (!strcmp(uri.scheme, ent->s_name)) {
+
+ const char *tlsa = apr_psprintf(r->pool, "_%d._%s.%s",
+ uri.port ? uri.port : ntohs(ent->s_port),
+ ent->s_proto, uri.hostname);
+
+ redwax_dns_t *dns = apr_array_push(r->dns_requests);
+
+ dns->r = r;
+ dns->basename = uri.hostname;
+ dns->qname = tlsa;
+ dns->rrtype = 52 /* TYPE TLSA */;
+ dns->rrclass = 1 /* CLASS IN (internet) */;
+ dns->cb = rt_run_process_tlsa;
+
+ found = 1;
+ }
+
+ }
+
+ endservent();
+
+ if (!found) {
+ redwax_print_error(r,
+ "URI '%s': protocol '%s' not found\n", arg, uri.scheme);
+ return APR_EINVAL;
+ }
+ else {
+ return APR_SUCCESS;
+ }
+
+ }
+
+ else {
+ redwax_print_error(r,
+ "URI '%s': scheme missing\n", arg);
+ return APR_EINVAL;
+ }
+
+}
+
+static apr_status_t redwax_unbound_set_smimea(redwax_tool_t *r, const char *arg)
+{
+
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t redwax_unbound_filter_read_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
+{
+ unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ apr_status_t status = APR_SUCCESS;
+ int rv;
+
+ /* ack readcb work */
+ r->poll_work--;
+
+ /* ack socket read work */
+ config->socket_read_work--;
+
+ rv = ub_process(config->ctx);
+
+ if (rv) {
+ redwax_print_error(r,
+ "Could not process DNS: %s (%s)\n",
+ ub_strerror(rv), strerror(errno));
+ return APR_EGENERAL;
+ }
+
+ if (config->status) {
+ return config->status;
+ }
+
+ if (config->dns_work) {
+
+ status = apr_pollcb_add(r->poll, &config->socket_read);
+
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not add read descriptor to poll: %pm\n", &status);
+ return status;
+ }
+
+ /* req readcb work */
+ r->poll_work++;
+
+ /* req socket read work */
+ config->socket_read_work++;
+ }
+
+ return status;
+}
+
+void redwax_unbound_filter_result_cb(void *ctx, int rv, struct ub_result* result)
+{
+ redwax_dns_t *dns = ctx;
+
+ redwax_tool_t *r = dns->r;
+
+ unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ /* ack dns lookup work */
+ config->dns_work--;
+
+ if (rv) {
+ redwax_print_error(r,
+ "Could not resolve: %s\n",
+ ub_strerror(rv));
+ return;
+ }
+
+ dns->canonname = result->canonname;
+ dns->havedata = result->havedata;
+ dns->nxdomain = result->nxdomain;
+ dns->secure = result->secure;
+ dns->bogus = result->bogus;
+ dns->why_bogus = result->why_bogus;
+
+ if (result->data) {
+
+ int i, count;
+
+ for (count = 0; result->data[count]; count++);
+
+ dns->rdata = apr_array_make(r->pool, count, sizeof(redwax_rdata_t));
+
+ for (i = 0; i < count; i++) {
+
+ redwax_rdata_t *rdata = apr_array_push(dns->rdata);
+
+ rdata->data = (unsigned char *)result->data[i];
+ rdata->len = result->len[i];
+
+ rt_run_process_dns(r, dns, rdata);
+
+ }
+
+ }
+
+ config->status = dns->cb(r, dns);
+
+ ub_resolve_free(result);
+}
+
+static apr_status_t redwax_unbound_filter_write_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
+{
+ unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ redwax_dns_t *dns = apr_array_pop(r->dns_requests);
+
+ apr_status_t status = APR_SUCCESS;
+ int rv;
+
+ /* ack writecb work */
+ r->poll_work--;
+
+ rv = ub_resolve_async(config->ctx, dns->qname,
+ dns->rrtype,
+ dns->rrclass,
+ (void *)dns, redwax_unbound_filter_result_cb, NULL);
+
+ if (rv) {
+ redwax_print_error(r,
+ "Could not resolve '%s': %s (%s)\n",
+ dns->qname, ub_strerror(rv), strerror(errno));
+ return APR_EGENERAL;
+ }
+
+ /* req dns lookup work */
+ config->dns_work++;
+
+ if (!config->socket_read_work) {
+
+ status = apr_pollcb_add(r->poll, &config->socket_read);
+
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not add read descriptor to poll: %pm\n", &status);
+ return status;
+ }
+
+ /* req readcb work */
+ r->poll_work++;
+
+ /* req socket read work */
+ config->socket_read_work++;
+
+ }
+
+ if (r->dns_requests->nelts) {
+
+ status = apr_pollcb_add(r->poll, &config->socket_write);
+
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not add write descriptor to poll: %pm\n", &status);
+ return status;
+ }
+
+ /* req writecb work */
+ r->poll_work++;
+
+ }
+
+ return status;
+}
+
+static apr_status_t redwax_unbound_filter_poll(redwax_tool_t *r)
+{
+ unbound_config_t *config;
+ apr_socket_t *s = NULL;
+
+ apr_os_sock_t fd;
+ apr_status_t status;
+
+ if (!r->dns_requests->nelts) {
+ return OK;
+ }
+
+ config = redwax_get_module_config(r->per_module, &unbound_module);
+
+ /*
+ * Apply defaults if no explicit values are set.
+ */
+
+ /* read /etc/resolv.conf for DNS proxy settings (from DHCP) */
+ if (!config->dns_server_set) {
+
+ int rv;
+
+ if ((rv = ub_ctx_resolvconf(config->ctx, "/etc/resolv.conf"))) {
+ redwax_print_error(r,
+ "Could not read /etc/resolv.conf: %s (%s)\n",
+ ub_strerror(rv), strerror(errno));
+ return APR_EINIT;
+ }
+ }
+
+ /* read public keys for DNSSEC verification */
+ if (!config->dns_trust_anchor_set) {
+
+ int rv;
+
+ if ((rv = ub_ctx_add_ta_file(config->ctx, REDWAX_DEFAULT_ROOT_KEY))) {
+ redwax_print_error(r,
+ "Could not read " REDWAX_DEFAULT_ROOT_KEY ": %s (%s)\n",
+ ub_strerror(rv), strerror(errno));
+ return APR_EINIT;
+ }
+ }
+
+ fd = ub_fd(config->ctx);
+
+ if (-1 == fd) {
+ redwax_print_error(r,
+ "Could not obtain unbound fd: %s\n",
+ strerror(errno));
+ return APR_EGENERAL;
+ }
+
+ status = apr_os_sock_put(&s, &fd, r->pool);
+
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not convert unbound fd: %pm\n", &status);
+ return status;
+ }
+
+ /* set up the read callback */
+ config->read_ctx.cb = redwax_unbound_filter_read_cb;
+
+ /* set up read descriptor */
+ config->socket_read.desc_type = APR_POLL_SOCKET;
+ config->socket_read.reqevents = APR_POLLIN;
+ config->socket_read.desc.s = s;
+ config->socket_read.client_data = &config->read_ctx;
+
+ /* set up the write callback */
+ config->write_ctx.cb = redwax_unbound_filter_write_cb;
+
+ /* set up write descriptor */
+ config->socket_write.desc_type = APR_POLL_SOCKET;
+ config->socket_write.reqevents = APR_POLLOUT;
+ config->socket_write.desc.s = s;
+ config->socket_write.client_data = &config->write_ctx;
+
+ status = apr_pollcb_add(r->poll, &config->socket_write);
+
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not add descriptor to poll: %pm\n", &status);
+ return status;
+ }
+
+ /* req writecb work */
+ r->poll_work++;
+
+ return APR_SUCCESS;
+}
+
void redwax_add_default_unbound_hooks()
{
rt_hook_initialise(redwax_unbound_initialise, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_dns_server(redwax_unbound_set_dns_server, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_dns_trust_anchor(redwax_unbound_set_dns_trust_anchor, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_tlsa(redwax_unbound_set_tlsa, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_smimea(redwax_unbound_set_smimea, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_filter_poll(redwax_unbound_filter_poll, NULL, NULL, APR_HOOK_MIDDLE);
}
#else
Modified: redwax-tool/trunk/redwax_unbound.h
==============================================================================
--- redwax-tool/trunk/redwax_unbound.h (original)
+++ redwax-tool/trunk/redwax_unbound.h Mon Jun 3 16:10:32 2024
@@ -25,6 +25,12 @@
#include "config.h"
+#if 0
+#define REDWAX_DEFAULT_ROOT_KEY "/var/lib/unbound/root.key"
+#endif
+
+#define REDWAX_DEFAULT_ROOT_KEY "/opt/local/etc/unbound/root.key"
+
void redwax_add_default_unbound_hooks();
#endif /* REDWAX_UNBOUND_H_ */
More information about the rt-commit
mailing list