/** * Copyright (C) 2021 Graham Leggett * * 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-tool - the redwax certificate munching tool * */ #ifndef REDWAX_TOOL_H #define REDWAX_TOOL_H #include #include #include #include #include #define REDWAX_DECLARE_MODULE(foo) \ module foo##_module /** Use this in all standard modules */ #define STANDARD_MODULE_STUFF -1, \ __FILE__, \ NULL typedef struct module_struct module; struct module_struct { int module_index; const char *name; struct module_struct *next; void (*register_hooks) (apr_pool_t *p); }; typedef struct redwax_conf_vector_t redwax_conf_vector_t; redwax_conf_vector_t *redwax_create_module_config(apr_pool_t *p); void *redwax_get_module_config(const redwax_conf_vector_t *cv, const module *m); void redwax_set_module_config(redwax_conf_vector_t *cv, const module *m, void *val); #define redwax_get_module_config(v,m) \ (v ? ((void **)(v))[(m)->module_index] : NULL) #define redwax_set_module_config(v,m,val) \ ((((void **)(v))[(m)->module_index]) = (val)) typedef struct redwax_metadata_t redwax_metadata_t; typedef struct redwax_filter_t { int filter_applied; } redwax_filter_t; typedef struct redwax_nss_t { const char *dir; const char *token; int needs_write; } redwax_nss_t; typedef struct redwax_pkcs11_t { apr_array_header_t *pkcs11_modules; const char *url; const char *token; int needs_write; } redwax_pkcs11_t; typedef enum redwax_format_e { REDWAX_FORMAT_TEXT = 0, REDWAX_FORMAT_XML, REDWAX_FORMAT_JSON, REDWAX_FORMAT_YAML, } redwax_format_e; typedef enum redwax_order_e { 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_e; typedef struct redwax_tool_t { apr_pool_t *pool; apr_pool_t *tpool; redwax_conf_vector_t *per_module; apr_file_t *err; apr_file_t *in; apr_file_t *out; const char *base; const char *hostname; const char *home; const char *breaks; apr_array_header_t *certs_in; apr_array_header_t *certs_out; apr_array_header_t *intermediates_in; apr_array_header_t *intermediates_out; apr_array_header_t *trusted_in; apr_array_header_t *trusted_out; apr_array_header_t *crls_in; apr_array_header_t *crls_out; apr_array_header_t *keys_in; apr_array_header_t *keys_out; apr_hash_t *emails; apr_hash_t *hostnames; apr_hash_t *ips; apr_hash_t *emails_index; apr_hash_t *hostnames_index; apr_hash_t *ips_index; apr_hash_t *keys_index; apr_hash_t *duplicates_index; apr_hash_t *trust_duplicates_index; apr_hash_t *cert_relationships; const char *verify_param; const char *verify_date; const char *secret_suffix_in; const char *secret_suffix_out; const char *secret_token_in; const char *secret_token_out; const char *label_out; const char *user_in; 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; redwax_pkcs11_t pkcs11_out; apr_time_t *now; redwax_format_e format; redwax_order_e order; redwax_expiry_e expiry; int current; int cert_out; int chain_out; int root_out; int trust_out; int crl_out; int param_out; int key_in; int key_out; int auto_out; int threshold; int quiet; int debug; int complete; int text; int rc; } redwax_tool_t; typedef enum redwax_certificate_type_e { REDWAX_CERTIFICATE_NONE, REDWAX_CERTIFICATE_X509, #if 0 REDWAX_CERTIFICATE_WTLS, REDWAX_CERTIFICATE_X509_ATTR, #endif } redwax_certificate_type_e; typedef enum redwax_certificate_e { REDWAX_CERTIFICATE_UNSPECIFIED, REDWAX_CERTIFICATE_END_ENTITY, REDWAX_CERTIFICATE_INTERMEDIATE, REDWAX_CERTIFICATE_ROOT, REDWAX_CERTIFICATE_TRUSTED, } redwax_certificate_e; typedef struct redwax_certificate_common_t { redwax_certificate_type_e type; int trusted; redwax_certificate_e category; const unsigned char *subjectpublickeyinfo_der; apr_size_t subjectpublickeyinfo_len; const char *subject; /* LABEL generated from the CN of the certificate subject */ const char *glabel; apr_size_t glabel_len; /* LABEL synced from a key */ const unsigned char *klabel_der; apr_size_t klabel_len; } redwax_certificate_common_t; typedef struct redwax_certificate_x509_t { const unsigned char *subject_der; apr_size_t subject_len; /* ID synced from a key */ const unsigned char *kid_der; apr_size_t kid_len; /* ID from the certificate SubjectKeyIdentifier */ const unsigned char *skid_der; apr_size_t skid_len; /* ID generated from public key */ const unsigned char *gid_der; apr_size_t gid_len; const unsigned char *issuer_der; 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 { apr_pool_t *pool; struct redwax_certificate_t *next; redwax_conf_vector_t *per_module; const char *header; const unsigned char *der; apr_size_t len; const char *origin; /* ID from the input certificate */ const unsigned char *id_der; apr_size_t id_len; /* LABEL from the input certificate */ const char *label; apr_size_t label_len; const char *token; apr_size_t token_len; void *ctx; redwax_certificate_common_t common; union { redwax_certificate_x509_t *x509; }; } redwax_certificate_t; typedef struct redwax_crl_t { apr_pool_t *pool; const char *header; const unsigned char *der; apr_size_t len; const char *origin; void *ctx; } redwax_crl_t; typedef enum redwax_key_type_e { REDWAX_KEY_NONE, REDWAX_KEY_RSA, #if 0 REDWAX_KEY_DSA, REDWAX_KEY_ECC, #endif } redwax_key_type_e; typedef struct redwax_key_common_t { redwax_key_type_e type; /* ID read from the input key */ const unsigned char *id_der; apr_size_t id_len; /* ID read from a certificate */ const unsigned char *cid_der; apr_size_t cid_len; /* ID generated from the public key */ const unsigned char *gid_der; apr_size_t gid_len; /* label read from a certificate */ const unsigned char *clabel_der; apr_size_t clabel_len; const unsigned char *subject_der; apr_size_t subject_len; const unsigned char *subjectpublickeyinfo_der; apr_size_t subjectpublickeyinfo_len; const char *subject; } redwax_key_common_t; typedef struct redwax_key_rsa_t { unsigned char *modulus; apr_size_t modulus_len; unsigned char *public_exponent; apr_size_t public_exponent_len; unsigned char *private_exponent; apr_size_t private_exponent_len; unsigned char *prime_1; apr_size_t prime_1_len; unsigned char *prime_2; apr_size_t prime_2_len; unsigned char *exponent_1; apr_size_t exponent_1_len; unsigned char *exponent_2; apr_size_t exponent_2_len; unsigned char *coefficient; apr_size_t coefficient_len; } redwax_key_rsa_t; typedef struct redwax_key_t { apr_pool_t *pool; redwax_conf_vector_t *per_module; const char *header; const unsigned char *der; apr_size_t len; const char *origin; /* label read from the input key */ const char *label; apr_size_t label_len; const char *token; apr_size_t token_len; apr_hash_t *keys_index; void *ctx; redwax_key_common_t common; union { redwax_key_rsa_t *rsa; }; } redwax_key_t; typedef struct redwax_offset_t { unsigned int *offsets; unsigned int start; unsigned int end; int equals; apr_size_t size; } redwax_offset_t; typedef enum redwax_token_escape_e { REDWAX_TOKEN_NOESCAPE = 0, REDWAX_TOKEN_WASESCAPE, REDWAX_TOKEN_ESCAPE_SLASH, REDWAX_TOKEN_ESCAPE_OCTAL2, REDWAX_TOKEN_ESCAPE_OCTAL3, REDWAX_TOKEN_ESCAPE_HEX1, REDWAX_TOKEN_ESCAPE_HEX2, REDWAX_TOKEN_ESCAPE_UTF16_1, REDWAX_TOKEN_ESCAPE_UTF16_2, REDWAX_TOKEN_ESCAPE_UTF16_3, REDWAX_TOKEN_ESCAPE_UTF16_4, REDWAX_TOKEN_ESCAPE_UTF32_1, REDWAX_TOKEN_ESCAPE_UTF32_2, REDWAX_TOKEN_ESCAPE_UTF32_3, REDWAX_TOKEN_ESCAPE_UTF32_4, REDWAX_TOKEN_ESCAPE_UTF32_5, REDWAX_TOKEN_ESCAPE_UTF32_6, REDWAX_TOKEN_ESCAPE_UTF32_7, REDWAX_TOKEN_ESCAPE_UTF32_8, REDWAX_TOKEN_ESCAPE_CONTROL, } redwax_token_escape_e; typedef enum redwax_token_quoted_e { REDWAX_TOKEN_NOQUOTE = 0, REDWAX_TOKEN_WASQUOTE, REDWAX_TOKEN_SINGLEQUOTE, REDWAX_TOKEN_DOUBLEQUOTE, } redwax_token_quoted_e; typedef enum redwax_token_inside_e { REDWAX_TOKEN_OUTSIDE = 0, REDWAX_TOKEN_INSIDE, } redwax_token_inside_e; typedef enum redwax_token_equals_e { REDWAX_TOKEN_NOTSEEN = 0, REDWAX_TOKEN_SEEN, } redwax_token_equals_e; typedef struct redwax_tokenize_state_t { redwax_token_escape_e escaped:5; redwax_token_quoted_e isquoted:2; redwax_token_inside_e intoken:1; redwax_token_equals_e equals:1; } redwax_tokenize_state_t; apr_status_t redwax_tokenize_to_argv(const char *arg_str, const char ***argv_out, redwax_offset_t **argo_out, redwax_tokenize_state_t **states_out, redwax_tokenize_state_t *state, const char **err_out, apr_pool_t *pool); apr_status_t redwax_print_error(redwax_tool_t *r, const char *fmt, ...) __attribute__((format(printf,2,3))); apr_status_t redwax_print_debug(redwax_tool_t *r, const char *fmt, ...) __attribute__((format(printf,2,3))); apr_status_t redwax_complete_directory(redwax_tool_t *r, const char *arg, redwax_token_quoted_e quoted); apr_status_t redwax_complete_file(redwax_tool_t *r, const char *arg, redwax_token_quoted_e quoted); #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif /* * Comparisons. */ #define RIGHT 2 #define SAME 0 #define LEFT -2 /** * Hooks */ #define DECLINED -1 #define DONE -2 #define OK 0 /* Create a set of REDWAX_DECLARE(type), REDWAX_DECLARE_NONSTD(type) and * REDWAX_DECLARE_DATA with appropriate export and import tags for the platform */ #if !defined(WIN32) #define REDWAX_DECLARE(type) type #define REDWAX_DECLARE_NONSTD(type) type #define REDWAX_DECLARE_DATA #elif defined(REDWAX_DECLARE_STATIC) #define REDWAX_DECLARE(type) type __stdcall #define REDWAX_DECLARE_NONSTD(type) type #define REDWAX_DECLARE_DATA #elif defined(REDWAX_DECLARE_EXPORT) #define REDWAX_DECLARE(type) __declspec(dllexport) type __stdcall #define REDWAX_DECLARE_NONSTD(type) __declspec(dllexport) type #define REDWAX_DECLARE_DATA __declspec(dllexport) #else #define REDWAX_DECLARE(type) __declspec(dllimport) type __stdcall #define REDWAX_DECLARE_NONSTD(type) __declspec(dllimport) type #define REDWAX_DECLARE_DATA __declspec(dllimport) #endif /** * Hook to initialise each subsystem. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, initialise, (redwax_tool_t *r)); /** * Hook to process incoming certificates / intermediates / keys. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pem_in, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to process incoming trusted certificates. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_trust_pem_in, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to complete PKCS11 URL in. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_pkcs11_in, (redwax_tool_t *r, const char *url, apr_hash_t *urls)); /** * Hook to write incoming PKCS11 URL. * * @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, apr_hash_t *secrets)); /** * Hook to complete the module for the incoming PKCS11 URL. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_pkcs11_module_in, (redwax_tool_t *r, const char *mod, redwax_token_quoted_e quoted)); /** * Hook to specify the module for the incoming PKCS11 URL. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs11_module_in, (redwax_tool_t *r, const char *arg)); /** * Hook to complete keychain in. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_keychain_in, (redwax_tool_t *r, const char *url, apr_hash_t *urls)); /** * Hook to write incoming keychain entries. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_keychain_in, (redwax_tool_t *r, const char *arg)); /** * Hook to complete incoming certificates / intermediates / keys * and pass filtered results to the outgoing certificates / * intermediates / keys. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_filter, (redwax_tool_t *r, apr_hash_t *filters)); /** * Hook to process incoming certificates / intermediates / keys * and pass filtered results to the outgoing certificates / * intermediates / keys. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_filter, (redwax_tool_t *r, const char *arg)); /** * Hook to write outgoing NSS database. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_nss_out, (redwax_tool_t *r, const char *path, const char *token, apr_hash_t *secrets)); /** * Hook to complete outgoing NSS token. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_nss_token_out, (redwax_tool_t *r, apr_hash_t *tokens)); /** * Hook to write outgoing certificates / intermediates / keys. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_der_out, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to write outgoing certificates / intermediates / keys. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pem_out, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to write outgoing pkcs12 file. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs12_out, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to complete PKCS11 URL out. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_pkcs11_out, (redwax_tool_t *r, const char *url, apr_hash_t *urls)); /** * Hook to write outgoing PKCS11 URL. * * @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, apr_hash_t *secrets)); /** * Hook to complete the module for the PKCS11 URL. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_pkcs11_module_out, (redwax_tool_t *r, const char *mod, redwax_token_quoted_e quoted)); /** * Hook to specify the module for the outgoing PKCS11 URL. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs11_module_out, (redwax_tool_t *r, const char *arg)); /** * Hook to write outgoing PKCS12 file. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_pkcs12_in, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to handle the output of metadata. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_metadata_out, (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. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_ssh_public_out, (redwax_tool_t *r, const char *arg, const char *secret)); /** * Hook to complete the metadata format. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_format_out, (redwax_tool_t *r, apr_hash_t *formats)); /** * Hook to set the metadata format. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_format_out, (redwax_tool_t *r, const char *arg)); /** * Hook to complete the output order. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_order_out, (redwax_tool_t *r, apr_hash_t *orders)); /** * Hook to set the output order. * * @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)); /** * Hook to handle the output of JWK sets. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_jwks_out, (redwax_tool_t *r, const char *arg)); /** * Hook to complete verification parameters. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, complete_verify_param, (redwax_tool_t *r, apr_hash_t *params)); /** * Hook to set the verification parameters. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_verify_param, (redwax_tool_t *r, const char *arg)); /** * Hook to set the verification date. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_verify_date, (redwax_tool_t *r, const char *arg)); /** * Hook to set the verification expiry. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_verify_expiry, (redwax_tool_t *r, const char *arg)); /** * Hook to search for intermediate and root certificates. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, search_chain, (redwax_tool_t *r, const redwax_certificate_t *cert, const redwax_certificate_t **current)); /** * Hook to search for the key corresponding to a certificate. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, search_key, (redwax_tool_t *r, const redwax_certificate_t *cert)); /** * Hook to compare two certificates. * * A certificate is "better" than another certificate if: * * - The certificate is valid but the other not. * - The highest hash strength. * - The longest validity. * * @param r The redwax-tool context. * @param c1 The first certificate * @param c2 The second certificate * @result greater than zero if the second certificate is better * than the first, zero if certificates are identical. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, int, compare_certificate, (redwax_tool_t *r, const redwax_certificate_t *c1, const redwax_certificate_t *c2)); /** * Hook to normalise a key. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, normalise_key, (redwax_tool_t *r, redwax_key_t *key, int index)); /** * Hook to normalise a certificate. * * @param r The redwax-tool context. */ APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, normalise_certificate, (redwax_tool_t *r, redwax_certificate_t *cert, int index)); /** * Hook to add DNS entries to metadata. * * @param r The redwax-tool context. * @param m The metadata tree. * @param cert The certificate. */ 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)); #endif