[rt-commit] r154 - in /redwax-tool/trunk: ChangeLog Makefile.am config.h.in configure.ac redwax-tool.c redwax-tool.h redwax_libical.c redwax_libical.h redwax_openssl.c redwax_util.h
rt-commit at redwax.eu
rt-commit at redwax.eu
Sun Oct 15 13:09:28 CEST 2023
Author: minfrin at redwax.eu
Date: Sun Oct 15 13:09:27 2023
New Revision: 154
Log:
Add the --calendar-out and --reminder-out options
to publish certificate expiry to a calendar.
Added:
redwax-tool/trunk/redwax_libical.c
redwax-tool/trunk/redwax_libical.h
Modified:
redwax-tool/trunk/ChangeLog
redwax-tool/trunk/Makefile.am
redwax-tool/trunk/config.h.in
redwax-tool/trunk/configure.ac
redwax-tool/trunk/redwax-tool.c
redwax-tool/trunk/redwax-tool.h
redwax-tool/trunk/redwax_openssl.c
redwax-tool/trunk/redwax_util.h
Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog (original)
+++ redwax-tool/trunk/ChangeLog Sun Oct 15 13:09:27 2023
@@ -1,5 +1,9 @@
Changes with v0.9.3
+
+ *) Add the --calendar-out and --reminder-out options
+ to publish certificate expiry to a calendar.
+ [Graham Leggett]
*) Add the --filter-expiry option to allow acceptance
of expired leaf and chain certificates. [Graham
Modified: redwax-tool/trunk/Makefile.am
==============================================================================
--- redwax-tool/trunk/Makefile.am (original)
+++ redwax-tool/trunk/Makefile.am Sun Oct 15 13:09:27 2023
@@ -8,7 +8,7 @@
endif
bin_PROGRAMS = redwax-tool
-redwax_tool_SOURCES = redwax-tool.c redwax-tool.h redwax_openssl.c redwax_openssl.h redwax_nss.c redwax_nss.h redwax_p11kit.c redwax_p11kit.h redwax_util.c redwax_util.h
+redwax_tool_SOURCES = redwax-tool.c redwax-tool.h redwax_openssl.c redwax_openssl.h redwax_nss.c redwax_nss.h redwax_p11kit.c redwax_p11kit.h redwax_libical.c redwax_libical.h redwax_util.c redwax_util.h
EXTRA_DIST = redwax-tool.spec
dist_man_MANS = redwax-tool.1
Modified: redwax-tool/trunk/config.h.in
==============================================================================
--- redwax-tool/trunk/config.h.in (original)
+++ redwax-tool/trunk/config.h.in Sun Oct 15 13:09:27 2023
@@ -26,6 +26,9 @@
/* Define to 1 if you have the <libgen.h> header file. */
#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the <libical/ical.h> header file. */
+#undef HAVE_LIBICAL_ICAL_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
Modified: redwax-tool/trunk/configure.ac
==============================================================================
--- redwax-tool/trunk/configure.ac (original)
+++ redwax-tool/trunk/configure.ac Sun Oct 15 13:09:27 2023
@@ -57,6 +57,21 @@
fi
])
+AC_ARG_WITH(libical,[ --with-libical use libical library],
+ [
+ if test "$with_libical" != "no"; then
+ PKG_CHECK_MODULES(libical, [libical >= 0.40])
+
+ CFLAGS="$CFLAGS $libical_CFLAGS"
+ CPPFLAGS="$CPPFLAGS $libical_CPPFLAGS"
+ LDFLAGS="$LDFLAGS $libical_LDFLAGS"
+ LIBS="$LIBS $libical_LIBS"
+
+ AC_CHECK_HEADERS(libical/ical.h)
+
+ fi
+ ])
+
AC_ARG_WITH([bash-completion-dir],
AS_HELP_STRING([--with-bash-completion-dir[=PATH]],
[Install the bash auto-completion script in this directory. @<:@default=yes@:>@]),
Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c (original)
+++ redwax-tool/trunk/redwax-tool.c Sun Oct 15 13:09:27 2023
@@ -42,6 +42,7 @@
#include "redwax_nss.h"
#include "redwax_openssl.h"
#include "redwax_p11kit.h"
+#include "redwax_libical.h"
#if HAVE_LIBGEN_H
#include <libgen.h>
@@ -75,12 +76,15 @@
APR_HOOK_LINK(complete_pkcs11_module_out);
APR_HOOK_LINK(process_pkcs11_module_out);
APR_HOOK_LINK(process_metadata_out);
+ APR_HOOK_LINK(process_calendar_out);
+ APR_HOOK_LINK(process_reminder_out);
APR_HOOK_LINK(process_ssh_public_out);
APR_HOOK_LINK(complete_format_out);
APR_HOOK_LINK(process_jwks_out);
APR_HOOK_LINK(set_format_out);
APR_HOOK_LINK(complete_order_out);
APR_HOOK_LINK(set_order_out);
+ APR_HOOK_LINK(set_calendar_alarm);
APR_HOOK_LINK(search_chain);
APR_HOOK_LINK(search_key);
APR_HOOK_LINK(compare_certificate);
@@ -135,6 +139,10 @@
(redwax_tool_t * r, const char *mod, redwax_token_quoted_e quoted), (r, mod, quoted), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_metadata_out,
(redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_calendar_out,
+ (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_reminder_out,
+ (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_ssh_public_out,
(redwax_tool_t * r, const char *arg, const char *secret), (r, arg, secret), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, set_format_out,
@@ -145,6 +153,8 @@
(redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_order_out,
(redwax_tool_t * r, apr_hash_t *orders), (r, orders), DECLINED);
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, set_calendar_alarm,
+ (redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_jwks_out,
(redwax_tool_t * r, const char *arg), (r, arg), DECLINED);
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, apr_status_t, search_chain,
@@ -211,19 +221,22 @@
#define REDWAX_TOOL_METADATA_OUT 298
#define REDWAX_TOOL_METADATA_THRESHOLD 299
#define REDWAX_TOOL_FORMAT_OUT 300
-#define REDWAX_TOOL_JWKS_OUT 301
-#define REDWAX_TOOL_TEXT_OUT 302
-#define REDWAX_TOOL_NO_TEXT_OUT 303
-#define REDWAX_TOOL_SSH_PRIVATE_OUT 304
-#define REDWAX_TOOL_SSH_PUBLIC_OUT 305
-#define REDWAX_TOOL_SMIMEA_OUT 306
-#define REDWAX_TOOL_SSHFP_OUT 307
-#define REDWAX_TOOL_TLSA_OUT 308
-#define REDWAX_TOOL_USER_IN 309
-#define REDWAX_TOOL_USER_OUT 310
-#define REDWAX_TOOL_GROUP_IN 311
-#define REDWAX_TOOL_GROUP_OUT 312
-#define REDWAX_TOOL_ORDER_OUT 313
+#define REDWAX_TOOL_CALENDAR_OUT 301
+#define REDWAX_TOOL_CALENDAR_ALARM 302
+#define REDWAX_TOOL_REMINDER_OUT 303
+#define REDWAX_TOOL_JWKS_OUT 304
+#define REDWAX_TOOL_TEXT_OUT 305
+#define REDWAX_TOOL_NO_TEXT_OUT 306
+#define REDWAX_TOOL_SSH_PRIVATE_OUT 307
+#define REDWAX_TOOL_SSH_PUBLIC_OUT 308
+#define REDWAX_TOOL_SMIMEA_OUT 309
+#define REDWAX_TOOL_SSHFP_OUT 310
+#define REDWAX_TOOL_TLSA_OUT 311
+#define REDWAX_TOOL_USER_IN 312
+#define REDWAX_TOOL_USER_OUT 313
+#define REDWAX_TOOL_GROUP_IN 314
+#define REDWAX_TOOL_GROUP_OUT 315
+#define REDWAX_TOOL_ORDER_OUT 316
#define REDWAX_EXIT_OK 0
#define REDWAX_EXIT_INIT 1
@@ -314,6 +327,9 @@
{ "metadata-out", REDWAX_TOOL_METADATA_OUT, 1, " --metadata-out=file\t\tWrite metadata of each certificate and key to the\n\t\t\t\tgiven file in the format given by the format\n\t\t\t\tparameter." },
{ "metadata-threshold", REDWAX_TOOL_METADATA_THRESHOLD, 1, " --metadata-threshold=days\tSet the threshold in days below which an expiry\n\t\t\t\tbecomes a warning. If unset, defaults to no\n\t\t\t\twarning." },
{ "format-out", REDWAX_TOOL_FORMAT_OUT, 1, " --format-out=xml|json|yaml\tFormat of output metadata." },
+ { "calendar-out", REDWAX_TOOL_CALENDAR_OUT, 1, " --calendar-out=file\t\tWrite a calendar containing entries until the expiry\n\t\t\t\tdate of each certificate to the given file or\n\t\t\t\tdirectory. If a directory is specified, entries will\n\t\t\t\tbe created in discrete ICS files." },
+ { "reminder-out", REDWAX_TOOL_REMINDER_OUT, 1, " --reminder-out=file\t\tWrite a calendar containing reminders at the expiry\n\t\t\t\tdate of each certificate to the given file or\n\t\t\t\tdirectory. If a directory is specified, entries will\n\t\t\t\tbe created in discrete ICS files." },
+ { "calendar-alarm", REDWAX_TOOL_CALENDAR_ALARM, 1, " --calendar-alarm=duration\tIf specified, add an alarm to each calendar entry if\n\t\t\t\tnot already present. The alarm format is a RFC5545\n\t\t\t\tDURATION as described in section 3.3.6. Example:\n\t\t\t\t-P1W is one week prior to expiry." },
{ "user-in", REDWAX_TOOL_USER_IN, 1, " --user-in=user\t\tUse the privileges of this user when reading\n\t\t\t\tcertificates and keys." },
{ "user-out", REDWAX_TOOL_USER_OUT, 1, " --user-out=user\t\tUse the privileges of this user when writing\n\t\t\t\tcertificates and keys." },
{ "group-in", REDWAX_TOOL_GROUP_IN, 1, " --group-in=group\t\tUse the privileges of this group when reading\n\t\t\t\tcertificates and keys. If you have set a user\n\t\t\t\tbefore setting a group, you may no longer have\n\t\t\t\tpermission to set the group. It is recommended\n\t\t\t\tthat if user and group are set, the group is set\n\t\t\t\tfirst." },
@@ -2366,6 +2382,32 @@
return status;
}
+static apr_status_t redwax_calendar_out(redwax_tool_t *r, const char *arg)
+{
+ arg = redwax_home(r, arg);
+
+ apr_status_t status = rt_run_process_calendar_out(r, arg);
+
+ return status;
+}
+
+static apr_status_t redwax_calendar_alarm(redwax_tool_t *r, const char *arg)
+{
+
+ apr_status_t status = rt_run_set_calendar_alarm(r, arg);
+
+ return status;
+}
+
+static apr_status_t redwax_reminder_out(redwax_tool_t *r, const char *arg)
+{
+ arg = redwax_home(r, arg);
+
+ apr_status_t status = rt_run_process_reminder_out(r, arg);
+
+ return status;
+}
+
static apr_status_t redwax_jwks_out(redwax_tool_t *r, const char *arg)
{
arg = redwax_home(r, arg);
@@ -2691,6 +2733,18 @@
if (redwax_set_threshold(r, optarg)) {
return REDWAX_EXIT_OPTIONS;
}
+ break;
+ }
+ case REDWAX_TOOL_CALENDAR_OUT: {
+ redwax_calendar_out(r, optarg);
+ break;
+ }
+ case REDWAX_TOOL_CALENDAR_ALARM: {
+ redwax_calendar_alarm(r, optarg);
+ break;
+ }
+ case REDWAX_TOOL_REMINDER_OUT: {
+ redwax_reminder_out(r, optarg);
break;
}
case REDWAX_TOOL_SSH_PUBLIC_OUT: {
@@ -3176,6 +3230,9 @@
#if HAVE_P11_KIT_MODULES_LOAD_AND_INITIALIZE
redwax_add_default_p11kit_hooks();
#endif
+#if HAVE_LIBICAL_ICAL_H
+ redwax_add_default_libical_hooks();
+#endif
redwax_add_default_hooks();
apr_hook_sort_all();
Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h (original)
+++ redwax-tool/trunk/redwax-tool.h Sun Oct 15 13:09:27 2023
@@ -54,16 +54,16 @@
} redwax_format_e;
typedef enum redwax_order_e {
- REDWAX_ORDER_ALL = 0,
- REDWAX_ORDER_KEY_FIRST,
- REDWAX_ORDER_KEY_LAST,
+ REDWAX_ORDER_ALL = 0,
+ REDWAX_ORDER_KEY_FIRST,
+ REDWAX_ORDER_KEY_LAST,
} redwax_order_e;
typedef enum redwax_expiry_e {
- REDWAX_EXPIRY_CHECK = 0,
- REDWAX_EXPIRY_IGNORE,
- REDWAX_EXPIRY_IGNORE_LEAF,
- REDWAX_EXPIRY_IGNORE_CHAIN
+ REDWAX_EXPIRY_CHECK = 0,
+ REDWAX_EXPIRY_IGNORE,
+ REDWAX_EXPIRY_IGNORE_LEAF,
+ REDWAX_EXPIRY_IGNORE_CHAIN
} redwax_expiry_e;
typedef struct redwax_tool_t {
@@ -106,6 +106,7 @@
const char *user_out;
const char *group_in;
const char *group_out;
+ const char *calendar_alarm;
redwax_filter_t filter;
redwax_nss_t nss_out;
redwax_pkcs11_t pkcs11_in;
@@ -180,6 +181,11 @@
apr_size_t issuer_len;
const unsigned char *serial_der;
apr_size_t serial_len;
+ apr_time_t *before;
+ apr_time_t *after;
+ const char *text;
+ const char *compact;
+ const char *pem;
} redwax_certificate_x509_t;
typedef struct redwax_certificate_t {
@@ -548,6 +554,22 @@
(redwax_tool_t *r, const char *arg));
/**
+ * Hook to handle the output of calendar data.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_calendar_out,
+ (redwax_tool_t *r, const char *arg));
+
+/**
+ * Hook to handle the output of calendar (reminder) data.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_reminder_out,
+ (redwax_tool_t *r, const char *arg));
+
+/**
* Hook to write SSH public keys.
*
* @param r The redwax-tool context.
@@ -585,6 +607,14 @@
* @param r The redwax-tool context.
*/
APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_order_out,
+ (redwax_tool_t *r, const char *arg));
+
+/**
+ * Hook to set the calendar alarm.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_calendar_alarm,
(redwax_tool_t *r, const char *arg));
/**
Added: redwax-tool/trunk/redwax_libical.c
==============================================================================
--- redwax-tool/trunk/redwax_libical.c (added)
+++ redwax-tool/trunk/redwax_libical.c Sun Oct 15 13:09:27 2023
@@ -0,0 +1,701 @@
+/**
+ * Copyright (C) 2022 Graham Leggett <minfrin at sharp.fm>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * redwax_libical - libical routines for generating calendars
+ *
+ */
+
+#include <apr_strings.h>
+#include <apr_uuid.h>
+
+#include "config.h"
+#include "redwax-tool.h"
+
+#include "redwax_util.h"
+
+#if HAVE_LIBICAL_ICAL_H
+
+#include <libical/ical.h>
+
+/**
+ * Keep track of calendar.
+ */
+typedef struct redwax_libical_vcalendar_t {
+ const char *path;
+ const char *file;
+ apr_file_t *out;
+ icalcomponent *cal;
+} redwax_libical_vcalendar_t;
+
+static apr_status_t redwax_libical_initialise(redwax_tool_t *r)
+{
+
+ return OK;
+}
+
+static void redwax_libical_make_vcalendar(redwax_libical_vcalendar_t *vcal)
+{
+ vcal->cal = icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid("-//Redwax Project//redwax-tool//EN"),
+ NULL);
+// vcal->cal = icalcomponent_new_vcalendar();
+}
+
+static apr_status_t redwax_libical_open_vcalendar(redwax_tool_t *r, const char *path, redwax_libical_vcalendar_t **pvcal)
+{
+ apr_finfo_t finfo;
+
+ apr_file_t *out;
+
+ redwax_libical_vcalendar_t *vcal = apr_pcalloc(r->pool,
+ sizeof(redwax_libical_vcalendar_t));
+
+ apr_status_t status;
+
+ if (!strcmp(path, "-")) {
+ out = r->out;
+ redwax_libical_make_vcalendar(vcal);
+ }
+ else if (APR_SUCCESS == apr_stat(&finfo, path, APR_FINFO_TYPE, r->pool) && finfo.filetype == APR_DIR) {
+ out = NULL;
+ }
+ else {
+ status = apr_file_open(&out, path, APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE,
+ APR_FPROT_OS_DEFAULT, r->pool);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not open '%s': %pm\n", path, &status);
+ return status;
+ }
+ redwax_libical_make_vcalendar(vcal);
+ }
+
+ vcal->path = path;
+ vcal->out = out;
+
+ *pvcal = vcal;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_libical_load_vcomponent(redwax_tool_t *r,
+ redwax_libical_vcalendar_t *vcal, icalcomponent_kind kind,
+ const char *uid, icalcomponent **comp)
+{
+ if (vcal->out) {
+ *comp = icalcomponent_new(kind);
+
+ icalcomponent_add_component(vcal->cal, *comp);
+
+ icalcomponent_set_uid(*comp, uid);
+
+ }
+ else {
+ char *calname, *calpath, *buffer;
+
+ apr_file_t *in;
+
+ apr_off_t end = 0, start = 0;
+ apr_size_t bytes_read;
+
+ apr_status_t status;
+
+ calname = apr_pstrcat(r->pool, uid, ".ics", NULL);
+ if (APR_SUCCESS
+ != (status = apr_filepath_merge(&calpath, vcal->path,
+ calname, APR_FILEPATH_NATIVE, r->pool))) {
+ redwax_print_error(r,
+ "Could not merge '%s' and '%s': %pm\n", vcal->path, calname, &status);
+ return status;
+ }
+ else {
+ vcal->file = calpath;
+ }
+
+ status = apr_file_open(&in, vcal->file, APR_FOPEN_READ,
+ APR_FPROT_OS_DEFAULT, r->pool);
+ if (APR_ENOENT == status) {
+
+ redwax_libical_make_vcalendar(vcal);
+
+ *comp = icalcomponent_new(kind);
+
+ icalcomponent_set_uid(*comp, uid);
+
+ icalcomponent_add_component(vcal->cal, *comp);
+
+ return APR_SUCCESS;
+ }
+ else if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not read '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ /* how long is the key? */
+ status = apr_file_seek(in, APR_END, &end);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not seek '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ /* back to the beginning */
+ status = apr_file_seek(in, APR_SET, &start);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not seek '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ buffer = apr_palloc(r->pool, end + 1);
+ buffer[end] = 0;
+
+ status = apr_file_read_full(in, buffer, end, &bytes_read);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not get '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ vcal->cal = icalparser_parse_string(buffer);
+ if(icalerrno != ICAL_NO_ERROR) {
+ redwax_print_error(r,
+ "Could not parse '%s': %s\n", vcal->file, icalerror_perror());
+ return APR_EINVAL;
+ }
+
+ apr_file_close(in);
+
+ *comp = icalcomponent_get_first_component(vcal->cal, kind);
+
+ while (*comp) {
+ const char *u = icalcomponent_get_uid(*comp);
+
+ if (u && !strcmp(uid, u)) {
+ return APR_SUCCESS;
+ }
+
+ *comp = icalcomponent_get_next_component(*comp, kind);
+ }
+
+ *comp = icalcomponent_new(kind);
+
+ icalcomponent_set_uid(*comp, uid);
+
+ icalcomponent_add_component(vcal->cal, *comp);
+
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_libical_save_vcomponent(redwax_tool_t *r, redwax_libical_vcalendar_t *vcal)
+{
+ if (!vcal->out && vcal->cal) {
+
+ apr_file_t *out;
+
+ apr_status_t status;
+
+ status = apr_file_open(&out, vcal->file, APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE,
+ APR_FPROT_OS_DEFAULT, r->pool);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not open '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ status = apr_file_puts(icalcomponent_as_ical_string(vcal->cal), out);
+ if (APR_SUCCESS != status) {
+ redwax_print_error(r,
+ "Could not write '%s': %pm\n", vcal->file, &status);
+ return status;
+ }
+
+ icalcomponent_free(vcal->cal);
+ vcal->cal = NULL;
+
+ apr_file_close(out);
+ vcal->file = NULL;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_libical_close_vcalendar(redwax_tool_t *r, redwax_libical_vcalendar_t *vcal)
+{
+ if (vcal->out && vcal->cal) {
+ apr_status_t status;
+
+ status = apr_file_puts(icalcomponent_as_ical_string(vcal->cal), vcal->out);
+
+ icalcomponent_free(vcal->cal);
+
+ return status;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t redwax_libical_add_event(redwax_tool_t *r,
+ redwax_libical_vcalendar_t *vcal, const redwax_certificate_t *cert)
+{
+ icalcomponent *event, *alarm;
+
+ apr_status_t status;
+
+ if (cert->x509) {
+
+ const char *uid;
+
+ if (cert->x509->skid_der) {
+
+ uid = redwax_pencode_base16_binary(r->pool,
+ cert->x509->skid_der, cert->x509->skid_len,
+ REDWAX_ENCODE_NONE, NULL);
+
+ }
+ else {
+ /* skip */
+ return APR_SUCCESS;
+ }
+
+ status = redwax_libical_load_vcomponent(r, vcal,
+ ICAL_VEVENT_COMPONENT, uid, &event);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (cert->common.subject) {
+
+ icalcomponent_set_summary(event,
+ apr_psprintf(r->pool, "%s", cert->common.subject));
+
+ }
+
+ if (cert->x509->before) {
+
+ icalcomponent_set_dtstamp(event,
+ icaltime_from_timet_with_zone(*cert->x509->before,
+ 0, icaltimezone_get_utc_timezone()));
+
+ }
+
+ if (cert->x509->after) {
+
+ struct icaltimetype after = icaltime_from_timet_with_zone(*cert->x509->after,
+ 0, icaltimezone_get_utc_timezone());
+
+ after.is_date = 1;
+
+ icalcomponent_set_dtstart(event, after);
+
+ icaltime_adjust(&after, 1, 0, 0, 0);
+
+ icalcomponent_set_dtend(event, after);
+
+ }
+
+ if (cert->x509->compact && cert->x509->pem) {
+
+ icalcomponent_set_description(event,
+ apr_pstrcat(r->pool, cert->x509->compact, cert->x509->pem, NULL));
+
+ }
+ else if (cert->x509->compact) {
+
+ icalcomponent_set_description(event, cert->x509->compact);
+
+ }
+ else if (cert->x509->pem) {
+
+ icalcomponent_set_description(event, cert->x509->pem);
+
+ }
+
+ alarm = icalcomponent_get_first_component(event, ICAL_VALARM_COMPONENT);
+
+ if (!alarm && r->calendar_alarm) {
+
+ apr_uuid_t uuid;
+ char ubuf[APR_UUID_FORMATTED_LENGTH + 1];
+
+ struct icaltriggertype trigger;
+
+ trigger = icaltriggertype_from_string(r->calendar_alarm);
+
+ alarm = icalcomponent_new_valarm();
+
+ apr_uuid_get(&uuid);
+ apr_uuid_format(ubuf, &uuid);
+
+ icalcomponent_set_uid(alarm, ubuf);
+
+ icalcomponent_add_property(alarm, icalproperty_new_action(ICAL_ACTION_DISPLAY));
+
+ icalcomponent_set_description(alarm, "Certificate renewal");
+
+ icalcomponent_add_property(alarm, icalproperty_new_trigger(trigger));
+
+ icalcomponent_add_component(event, alarm);
+
+ }
+
+ if (!icalcomponent_get_first_property(event, ICAL_TRANSP_PROPERTY)) {
+
+ icalcomponent_add_property(event,
+ icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT));
+
+ }
+
+ }
+
+ return redwax_libical_save_vcomponent(r, vcal);
+}
+
+static apr_status_t redwax_libical_add_todo(redwax_tool_t *r,
+ redwax_libical_vcalendar_t *vcal, const redwax_certificate_t *cert)
+{
+ icalcomponent *todo, *alarm;
+
+ apr_status_t status;
+
+ if (cert->x509) {
+
+ const char *uid;
+
+ if (cert->x509->skid_der) {
+
+ uid = redwax_pencode_base16_binary(r->pool,
+ cert->x509->skid_der, cert->x509->skid_len,
+ REDWAX_ENCODE_NONE, NULL);
+
+ }
+ else {
+ /* skip */
+ return APR_SUCCESS;
+ }
+
+ status = redwax_libical_load_vcomponent(r, vcal,
+ ICAL_VTODO_COMPONENT, uid, &todo);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (cert->common.subject) {
+
+ icalcomponent_set_summary(todo,
+ apr_psprintf(r->pool, "%s", cert->common.subject));
+
+ }
+
+ if (cert->x509->before) {
+
+ icalcomponent_set_dtstamp(todo,
+ icaltime_from_timet_with_zone(*cert->x509->before,
+ 0, icaltimezone_get_utc_timezone()));
+
+ icalcomponent_set_dtstart(todo,
+ icaltime_from_timet_with_zone(*cert->x509->before,
+ 0, icaltimezone_get_utc_timezone()));
+
+ }
+
+ if (cert->x509->after) {
+
+ icalcomponent_set_due(todo,
+ icaltime_from_timet_with_zone(*cert->x509->after,
+ 0, icaltimezone_get_utc_timezone()));
+
+ }
+
+ if (cert->x509->compact && cert->x509->pem) {
+
+ icalcomponent_set_description(todo,
+ apr_pstrcat(r->pool, cert->x509->compact, cert->x509->pem, NULL));
+
+ }
+ else if (cert->x509->compact) {
+
+ icalcomponent_set_description(todo, cert->x509->compact);
+
+ }
+ else if (cert->x509->pem) {
+
+ icalcomponent_set_description(todo, cert->x509->pem);
+
+ }
+
+ alarm = icalcomponent_get_first_component(todo, ICAL_VALARM_COMPONENT);
+
+ if (!alarm && r->calendar_alarm) {
+
+ apr_uuid_t uuid;
+ char ubuf[APR_UUID_FORMATTED_LENGTH + 1];
+
+ struct icaltriggertype trigger;
+
+ trigger = icaltriggertype_from_string(r->calendar_alarm);
+
+ alarm = icalcomponent_new_valarm();
+
+ apr_uuid_get(&uuid);
+ apr_uuid_format(ubuf, &uuid);
+
+ icalcomponent_set_uid(alarm, ubuf);
+
+ icalcomponent_add_property(alarm, icalproperty_new_action(ICAL_ACTION_DISPLAY));
+
+ icalcomponent_set_description(alarm, "Certificate renewal");
+
+ icalcomponent_add_property(alarm, icalproperty_new_trigger(trigger));
+
+ icalcomponent_add_component(todo, alarm);
+
+ }
+ }
+
+ return redwax_libical_save_vcomponent(r, vcal);
+}
+
+static apr_status_t redwax_libical_process_calendar_out(redwax_tool_t *r,
+ const char *file)
+{
+ redwax_libical_vcalendar_t *vcal;
+
+ int i;
+ apr_status_t status;
+
+ if (r->cert_out) {
+
+ for (i = 0; i < r->certs_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->certs_out,
+ i, const redwax_certificate_t);
+
+ redwax_print_error(r, "calendar-out: certificate: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ if (r->chain_out) {
+
+ for (i = 0; i < r->intermediates_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->intermediates_out,
+ i, const redwax_certificate_t);
+
+ redwax_print_error(r, "calendar-out: intermediate: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ if (r->trust_out) {
+ for (i = 0; i < r->trusted_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+ redwax_print_error(r, "calendar-out: trusted: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ status = redwax_libical_open_vcalendar(r, file, &vcal);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (r->cert_out) {
+
+ for (i = 0; i < r->certs_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->certs_out,
+ i, const redwax_certificate_t);
+
+ status = redwax_libical_add_event(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ if (r->chain_out) {
+
+ for (i = 0; i < r->intermediates_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->intermediates_out,
+ i, const redwax_certificate_t);
+
+ status = redwax_libical_add_event(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ if (r->trust_out) {
+
+ for (i = 0; i < r->trusted_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+ status = redwax_libical_add_event(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ return redwax_libical_close_vcalendar(r, vcal);
+
+}
+
+static apr_status_t redwax_libical_process_reminder_out(redwax_tool_t *r,
+ const char *file)
+{
+ redwax_libical_vcalendar_t *vcal;
+
+ int i;
+ apr_status_t status;
+
+ if (r->cert_out) {
+
+ for (i = 0; i < r->certs_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->certs_out,
+ i, const redwax_certificate_t);
+
+ redwax_print_error(r, "reminder-out: certificate: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ if (r->chain_out) {
+
+ for (i = 0; i < r->intermediates_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->intermediates_out,
+ i, const redwax_certificate_t);
+
+ redwax_print_error(r, "reminder-out: intermediate: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ if (r->trust_out) {
+ for (i = 0; i < r->trusted_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+ redwax_print_error(r, "reminder-out: trusted: %s\n",
+ cert->common.subject);
+ }
+ }
+
+ status = redwax_libical_open_vcalendar(r, file, &vcal);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (r->cert_out) {
+
+ for (i = 0; i < r->certs_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->certs_out,
+ i, const redwax_certificate_t);
+
+ status = redwax_libical_add_todo(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ if (r->chain_out) {
+
+ for (i = 0; i < r->intermediates_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->intermediates_out,
+ i, const redwax_certificate_t);
+
+ status = redwax_libical_add_todo(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ if (r->trust_out) {
+
+ for (i = 0; i < r->trusted_out->nelts; i++)
+ {
+ const redwax_certificate_t *cert = &APR_ARRAY_IDX(r->trusted_out, i, const redwax_certificate_t);
+
+ status = redwax_libical_add_todo(r, vcal, cert);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ }
+
+ return redwax_libical_close_vcalendar(r, vcal);
+
+}
+
+static apr_status_t redwax_libical_set_calendar_alarm(redwax_tool_t *r,
+ const char *alarm)
+{
+ struct icaltriggertype trigger;
+
+ trigger = icaltriggertype_from_string(alarm);
+
+ if (icaltriggertype_is_null_trigger(trigger) ||
+ icaltriggertype_is_bad_trigger(trigger)) {
+
+ redwax_print_error(r, "calendar-alarm: trigger is bad: %s\n",
+ alarm);
+
+ return APR_EINVAL;
+
+ }
+ else {
+
+ r->calendar_alarm = alarm;
+
+ }
+
+ return APR_SUCCESS;
+}
+
+void redwax_add_default_libical_hooks()
+{
+ rt_hook_initialise(redwax_libical_initialise, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_process_calendar_out(redwax_libical_process_calendar_out, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_process_reminder_out(redwax_libical_process_reminder_out, NULL, NULL, APR_HOOK_MIDDLE);
+ rt_hook_set_calendar_alarm(redwax_libical_set_calendar_alarm, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+#endif
Added: redwax-tool/trunk/redwax_libical.h
==============================================================================
--- redwax-tool/trunk/redwax_libical.h (added)
+++ redwax-tool/trunk/redwax_libical.h Sun Oct 15 13:09:27 2023
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2022 Graham Leggett <minfrin at sharp.fm>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * redwax_libical - libical routines for generating calendars
+ *
+ */
+
+#ifndef REDWAX_LIBICAL_H_
+#define REDWAX_LIBICAL_H_
+
+#include "config.h"
+
+#if HAVE_LIBICAL_ICAL_H
+
+void redwax_add_default_libical_hooks();
+
+#endif
+#endif /* REDWAX_LIBICAL_H_ */
Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c (original)
+++ redwax-tool/trunk/redwax_openssl.c Sun Oct 15 13:09:27 2023
@@ -818,6 +818,50 @@
}
}
+static const char *redwax_openssl_x509_text(apr_pool_t *p, X509 *x, unsigned long flags)
+{
+ BIO *bio;
+ char *buf = NULL;
+ int len = 0;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ return NULL;
+ }
+
+ if (x) {
+ X509_print_ex(bio, x, XN_FLAG_RFC2253, flags);
+ len = BIO_get_mem_data(bio, &buf);
+ }
+
+ buf = apr_pstrndup(p, buf, len);
+
+ BIO_free(bio);
+
+ return buf;
+}
+
+static const char *redwax_openssl_x509_pem(apr_pool_t *p, X509 *x)
+{
+ BIO *bio;
+ char *buf = NULL;
+ int len = 0;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ return NULL;
+ }
+
+ if (x) {
+ PEM_write_bio_X509(bio, x);
+ len = BIO_get_mem_data(bio, &buf);
+ }
+
+ buf = apr_pstrndup(p, buf, len);
+
+ BIO_free(bio);
+
+ return buf;
+}
+
static const char *redwax_openssl_name(apr_pool_t *p, X509_NAME *name)
{
BIO *bio;
@@ -1608,16 +1652,16 @@
len = BIO_get_mem_data(bio, &buf);
}
- if ((r->expiry == REDWAX_EXPIRY_IGNORE
- || (r->expiry == REDWAX_EXPIRY_IGNORE_LEAF && depth == 0)
- || (r->expiry == REDWAX_EXPIRY_IGNORE_CHAIN && depth > 0))
- && X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED) {
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
- redwax_print_error(r,
- "verify-filter: %d: %.*s: certificate expired, accepting anyway\n",
- X509_STORE_CTX_get_error_depth(ctx), len, buf);
- }
+ if ((r->expiry == REDWAX_EXPIRY_IGNORE
+ || (r->expiry == REDWAX_EXPIRY_IGNORE_LEAF && depth == 0)
+ || (r->expiry == REDWAX_EXPIRY_IGNORE_CHAIN && depth > 0))
+ && X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ redwax_print_error(r,
+ "verify-filter: %d: %.*s: certificate expired, accepting anyway\n",
+ X509_STORE_CTX_get_error_depth(ctx), len, buf);
+ }
else if (!ok) {
redwax_print_error(r,
"verify-filter: %d: %.*s: verify failed: %s\n",
@@ -4690,8 +4734,10 @@
if (r->key_out) {
for (i = 0; i < r->keys_out->nelts; i++)
{
+#if 0
const redwax_key_t
*key = &APR_ARRAY_IDX(r->keys_out, i, const redwax_key_t);
+#endif
redwax_print_error(r, "metadata-out: key\n");
}
@@ -5461,6 +5507,7 @@
X509_PUBKEY *pub;
ASN1_INTEGER *integer;
ASN1_OCTET_STRING *skid;
+ const ASN1_TIME *before, *after;
const unsigned char *der;
@@ -5690,6 +5737,26 @@
x509->serial_der = der = apr_palloc(r->pool, x509->serial_len);
i2d_ASN1_INTEGER(integer, &der);
}
+
+ before = X509_get0_notBefore(x);
+ if (before) {
+ struct tm stime = { 0 };
+ ASN1_TIME_to_tm(before, &stime);
+ x509->before = apr_palloc(r->pool, sizeof(apr_time_t));
+ *x509->before = timegm(&stime);
+ }
+
+ after = X509_get0_notAfter(x);
+ if (after) {
+ struct tm stime = { 0 };
+ ASN1_TIME_to_tm(after, &stime);
+ x509->after = apr_palloc(r->pool, sizeof(apr_time_t));
+ *x509->after = timegm(&stime);
+ }
+
+ x509->text = redwax_openssl_x509_text(r->pool, x, 0);
+ x509->compact = redwax_openssl_x509_text(r->pool, x, X509_FLAG_NO_VERSION | X509_FLAG_NO_PUBKEY | X509_FLAG_NO_SIGDUMP);
+ x509->pem = redwax_openssl_x509_pem(r->pool, x);
X509_free(x);
Modified: redwax-tool/trunk/redwax_util.h
==============================================================================
--- redwax-tool/trunk/redwax_util.h (original)
+++ redwax-tool/trunk/redwax_util.h Sun Oct 15 13:09:27 2023
@@ -91,11 +91,11 @@
typedef struct redwax_metadata_level_t {
void *k;
int klen;
- int root:1;
- int object:1;
- int array:1;
- int empty:1;
- int next:1;
+ unsigned int root:1;
+ unsigned int object:1;
+ unsigned int array:1;
+ unsigned int empty:1;
+ unsigned int next:1;
} redwax_metadata_level_t;
/**
More information about the rt-commit
mailing list