diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-25 04:41:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-25 04:41:28 +0000 |
commit | b1a1c1d95059e2fefd7b5671eb110ab690409a84 (patch) | |
tree | 97ecfcc9425e2d09d2cd669594d626a616f324a3 /modules/md/md_store.h | |
parent | Releasing progress-linux version 2.4.38-3+deb10u10progress5u1. (diff) | |
download | apache2-b1a1c1d95059e2fefd7b5671eb110ab690409a84.tar.xz apache2-b1a1c1d95059e2fefd7b5671eb110ab690409a84.zip |
Merging upstream version 2.4.59.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/md/md_store.h')
-rw-r--r-- | modules/md/md_store.h | 310 |
1 files changed, 248 insertions, 62 deletions
diff --git a/modules/md/md_store.h b/modules/md/md_store.h index 5825189..73c840f 100644 --- a/modules/md/md_store.h +++ b/modules/md/md_store.h @@ -20,101 +20,208 @@ struct apr_array_header_t; struct md_cert_t; struct md_pkey_t; +struct md_pkey_spec_t; -typedef struct md_store_t md_store_t; - -typedef void md_store_destroy_cb(md_store_t *store); - -const char *md_store_group_name(int group); - - -typedef apr_status_t md_store_load_cb(md_store_t *store, md_store_group_t group, - const char *name, const char *aspect, - md_store_vtype_t vtype, void **pvalue, - apr_pool_t *p); -typedef apr_status_t md_store_save_cb(md_store_t *store, apr_pool_t *p, md_store_group_t group, - const char *name, const char *aspect, - md_store_vtype_t vtype, void *value, - int create); -typedef apr_status_t md_store_remove_cb(md_store_t *store, md_store_group_t group, - const char *name, const char *aspect, - apr_pool_t *p, int force); -typedef apr_status_t md_store_purge_cb(md_store_t *store, apr_pool_t *p, md_store_group_t group, - const char *name); +const char *md_store_group_name(unsigned int group); -typedef int md_store_inspect(void *baton, const char *name, const char *aspect, - md_store_vtype_t vtype, void *value, apr_pool_t *ptemp); - -typedef apr_status_t md_store_iter_cb(md_store_inspect *inspect, void *baton, md_store_t *store, - apr_pool_t *p, md_store_group_t group, const char *pattern, - const char *aspect, md_store_vtype_t vtype); - -typedef apr_status_t md_store_move_cb(md_store_t *store, apr_pool_t *p, md_store_group_t from, - md_store_group_t to, const char *name, int archive); - -typedef apr_status_t md_store_get_fname_cb(const char **pfname, - md_store_t *store, md_store_group_t group, - const char *name, const char *aspect, - apr_pool_t *p); - -typedef int md_store_is_newer_cb(md_store_t *store, - md_store_group_t group1, md_store_group_t group2, - const char *name, const char *aspect, apr_pool_t *p); +typedef struct md_store_t md_store_t; -struct md_store_t { - md_store_destroy_cb *destroy; +/** + * A store for domain related data. + * + * The Key for a piece of data is the set of 3 items + * <group> + <domain> + <aspect> + * + * Examples: + * "domains" + "greenbytes.de" + "pubcert.pem" + * "ocsp" + "greenbytes.de" + "ocsp-XXXXX.json" + * + * Storage groups are pre-defined, domain and aspect names can be freely chosen. + * + * Groups reflect use cases and come with security restrictions. The groups + * DOMAINS, ARCHIVE and NONE are only accessible during the startup + * phase of httpd. + * + * Private key are stored unencrypted only in restricted groups. Meaning that certificate + * keys in group DOMAINS are not encrypted, but only readable at httpd start/reload. + * Keys in unrestricted groups are encrypted using a pass phrase generated once and stored + * in NONE. + */ - md_store_save_cb *save; - md_store_load_cb *load; - md_store_remove_cb *remove; - md_store_move_cb *move; - md_store_iter_cb *iterate; - md_store_purge_cb *purge; - md_store_get_fname_cb *get_fname; - md_store_is_newer_cb *is_newer; -}; +/** Value types handled by a store */ +typedef enum { + MD_SV_TEXT, /* plain text, value is (char*) */ + MD_SV_JSON, /* JSON serialization, value is (md_json_t*) */ + MD_SV_CERT, /* PEM x509 certificate, value is (md_cert_t*) */ + MD_SV_PKEY, /* PEM private key, value is (md_pkey_t*) */ + MD_SV_CHAIN, /* list of PEM x509 certificates, value is + (apr_array_header_t*) of (md_cert*) */ +} md_store_vtype_t; + +/** Store storage groups */ +typedef enum { + MD_SG_NONE, /* top level of store, name MUST be NULL in calls */ + MD_SG_ACCOUNTS, /* ACME accounts */ + MD_SG_CHALLENGES, /* challenge response data for a domain */ + MD_SG_DOMAINS, /* live certificates and settings for a domain */ + MD_SG_STAGING, /* staged set of certificate and settings, maybe incomplete */ + MD_SG_ARCHIVE, /* Archived live sets of a domain */ + MD_SG_TMP, /* temporary domain storage */ + MD_SG_OCSP, /* OCSP stapling related domain data */ + MD_SG_COUNT, /* number of storage groups, used in setups */ +} md_store_group_t; + +#define MD_FN_MD "md.json" +#define MD_FN_JOB "job.json" +#define MD_FN_HTTPD_JSON "httpd.json" + +/* The corresponding names for current cert & key files are constructed + * in md_store and md_crypt. + */ -void md_store_destroy(md_store_t *store); +/* These three legacy filenames are only used in md_store_fs to + * upgrade 1.0 directories. They should not be used for any other + * purpose. + */ +#define MD_FN_PRIVKEY "privkey.pem" +#define MD_FN_PUBCERT "pubcert.pem" +#define MD_FN_CERT "cert.pem" +/** + * Load the JSON value at key "group/name/aspect", allocated from pool p. + * @return APR_ENOENT if there is no such value + */ apr_status_t md_store_load_json(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, struct md_json_t **pdata, apr_pool_t *p); +/** + * Save the JSON value at key "group/name/aspect". If create != 0, fail if there + * already is a value for this key. + */ apr_status_t md_store_save_json(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, const char *aspect, struct md_json_t *data, int create); - +/** + * Load the value of type at key "group/name/aspect", allocated from pool p. Usually, the + * type is expected to be the same as used in saving the value. Some conversions will work, + * others will fail the format. + * @return APR_ENOENT if there is no such value + */ apr_status_t md_store_load(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, md_store_vtype_t vtype, void **pdata, apr_pool_t *p); +/** + * Save the JSON value at key "group/name/aspect". If create != 0, fail if there + * already is a value for this key. The provided data MUST be of the correct type. + */ apr_status_t md_store_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, const char *aspect, md_store_vtype_t vtype, void *data, int create); + +/** + * Remove the value stored at key "group/name/aspect". Unless force != 0, a missing + * value will cause the call to fail with APR_ENOENT. + */ apr_status_t md_store_remove(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, apr_pool_t *p, int force); +/** + * Remove everything matching key "group/name". + */ apr_status_t md_store_purge(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name); +/** + * Remove all items matching the name/aspect patterns that have not been + * modified since the given timestamp. + */ +apr_status_t md_store_remove_not_modified_since(md_store_t *store, apr_pool_t *p, + apr_time_t modified, + md_store_group_t group, + const char *name, + const char *aspect); + +/** + * inspect callback function. Invoked for each matched value. Values allocated from + * ptemp may disappear any time after the call returned. If this function returns + * 0, the iteration is aborted. + */ +typedef int md_store_inspect(void *baton, const char *name, const char *aspect, + md_store_vtype_t vtype, void *value, apr_pool_t *ptemp); +/** + * Iterator over all existing values matching the name pattern. Patterns are evaluated + * using apr_fnmatch() without flags. + */ apr_status_t md_store_iter(md_store_inspect *inspect, void *baton, md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *pattern, const char *aspect, md_store_vtype_t vtype); +/** + * Move everything matching key "from/name" from one group to another. If archive != 0, + * move any existing "to/name" into a new "archive/new_name" location. + */ apr_status_t md_store_move(md_store_t *store, apr_pool_t *p, md_store_group_t from, md_store_group_t to, const char *name, int archive); +/** + * Rename a group member. + */ +apr_status_t md_store_rename(md_store_t *store, apr_pool_t *p, + md_store_group_t group, const char *name, const char *to); + +/** + * Get the filename of an item stored in "group/name/aspect". The item does + * not have to exist. + */ apr_status_t md_store_get_fname(const char **pfname, md_store_t *store, md_store_group_t group, const char *name, const char *aspect, apr_pool_t *p); +/** + * Make a compare on the modification time of "group1/name/aspect" vs. "group2/name/aspect". + */ int md_store_is_newer(md_store_t *store, md_store_group_t group1, md_store_group_t group2, const char *name, const char *aspect, apr_pool_t *p); +/** + * Iterate over all names that exist in a group, e.g. there are items matching + * "group/pattern". The inspect function is called with the name and NULL aspect + * and value. + */ +apr_status_t md_store_iter_names(md_store_inspect *inspect, void *baton, md_store_t *store, + apr_pool_t *p, md_store_group_t group, const char *pattern); + +/** + * Get the modification time of the item store under "group/name/aspect". + * @return modification time or 0 if the item does not exist. + */ +apr_time_t md_store_get_modified(md_store_t *store, md_store_group_t group, + const char *name, const char *aspect, apr_pool_t *p); + +/** + * Acquire a cooperative, global lock on store modifications. + + * This will only prevent other children/processes/cluster nodes from + * doing the same and does not protect individual store functions from + * being called without it. + * @param store the store + * @param p memory pool to use + * @param max_wait maximum time to wait in order to acquire + * @return APR_SUCCESS when lock was obtained + */ +apr_status_t md_store_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait); + +/** + * Realease the global store lock. Will do nothing if there is no lock. + */ +void md_store_unlock_global(md_store_t *store, apr_pool_t *p); + /**************************************************************************************************/ /* Storage handling utils */ @@ -134,24 +241,103 @@ apr_status_t md_store_md_iter(md_store_md_inspect *inspect, void *baton, md_stor apr_pool_t *p, md_store_group_t group, const char *pattern); +const char *md_pkey_filename(struct md_pkey_spec_t *spec, apr_pool_t *p); +const char *md_chain_filename(struct md_pkey_spec_t *spec, apr_pool_t *p); + apr_status_t md_pkey_load(md_store_t *store, md_store_group_t group, - const char *name, struct md_pkey_t **ppkey, apr_pool_t *p); + const char *name, struct md_pkey_spec_t *spec, + struct md_pkey_t **ppkey, apr_pool_t *p); apr_status_t md_pkey_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, - const char *name, struct md_pkey_t *pkey, int create); -apr_status_t md_cert_load(md_store_t *store, md_store_group_t group, - const char *name, struct md_cert_t **pcert, apr_pool_t *p); -apr_status_t md_cert_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, - const char *name, struct md_cert_t *cert, int create); -apr_status_t md_chain_load(md_store_t *store, md_store_group_t group, - const char *name, struct apr_array_header_t **pchain, apr_pool_t *p); -apr_status_t md_chain_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, - const char *name, struct apr_array_header_t *chain, int create); + const char *name, struct md_pkey_spec_t *spec, + struct md_pkey_t *pkey, int create); apr_status_t md_pubcert_load(md_store_t *store, md_store_group_t group, const char *name, - struct apr_array_header_t **ppubcert, apr_pool_t *p); + struct md_pkey_spec_t *spec, struct apr_array_header_t **ppubcert, + apr_pool_t *p); apr_status_t md_pubcert_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, + struct md_pkey_spec_t *spec, struct apr_array_header_t *pubcert, int create); +/**************************************************************************************************/ +/* X509 complete credentials */ + +typedef struct md_credentials_t md_credentials_t; +struct md_credentials_t { + struct md_pkey_spec_t *spec; + struct md_pkey_t *pkey; + struct apr_array_header_t *chain; +}; + +apr_status_t md_creds_load(md_store_t *store, md_store_group_t group, const char *name, + struct md_pkey_spec_t *spec, md_credentials_t **pcreds, apr_pool_t *p); +apr_status_t md_creds_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, + const char *name, md_credentials_t *creds, int create); + +/**************************************************************************************************/ +/* implementation interface */ + +typedef apr_status_t md_store_load_cb(md_store_t *store, md_store_group_t group, + const char *name, const char *aspect, + md_store_vtype_t vtype, void **pvalue, + apr_pool_t *p); +typedef apr_status_t md_store_save_cb(md_store_t *store, apr_pool_t *p, md_store_group_t group, + const char *name, const char *aspect, + md_store_vtype_t vtype, void *value, + int create); +typedef apr_status_t md_store_remove_cb(md_store_t *store, md_store_group_t group, + const char *name, const char *aspect, + apr_pool_t *p, int force); +typedef apr_status_t md_store_purge_cb(md_store_t *store, apr_pool_t *p, md_store_group_t group, + const char *name); + +typedef apr_status_t md_store_iter_cb(md_store_inspect *inspect, void *baton, md_store_t *store, + apr_pool_t *p, md_store_group_t group, const char *pattern, + const char *aspect, md_store_vtype_t vtype); + +typedef apr_status_t md_store_names_iter_cb(md_store_inspect *inspect, void *baton, md_store_t *store, + apr_pool_t *p, md_store_group_t group, const char *pattern); + +typedef apr_status_t md_store_move_cb(md_store_t *store, apr_pool_t *p, md_store_group_t from, + md_store_group_t to, const char *name, int archive); + +typedef apr_status_t md_store_rename_cb(md_store_t *store, apr_pool_t *p, md_store_group_t group, + const char *from, const char *to); + +typedef apr_status_t md_store_get_fname_cb(const char **pfname, + md_store_t *store, md_store_group_t group, + const char *name, const char *aspect, + apr_pool_t *p); + +typedef int md_store_is_newer_cb(md_store_t *store, + md_store_group_t group1, md_store_group_t group2, + const char *name, const char *aspect, apr_pool_t *p); + +typedef apr_time_t md_store_get_modified_cb(md_store_t *store, md_store_group_t group, + const char *name, const char *aspect, apr_pool_t *p); + +typedef apr_status_t md_store_remove_nms_cb(md_store_t *store, apr_pool_t *p, + apr_time_t modified, md_store_group_t group, + const char *name, const char *aspect); +typedef apr_status_t md_store_lock_global_cb(md_store_t *store, apr_pool_t *p, apr_time_t max_wait); +typedef void md_store_unlock_global_cb(md_store_t *store, apr_pool_t *p); + +struct md_store_t { + md_store_save_cb *save; + md_store_load_cb *load; + md_store_remove_cb *remove; + md_store_move_cb *move; + md_store_rename_cb *rename; + md_store_iter_cb *iterate; + md_store_names_iter_cb *iterate_names; + md_store_purge_cb *purge; + md_store_get_fname_cb *get_fname; + md_store_is_newer_cb *is_newer; + md_store_get_modified_cb *get_modified; + md_store_remove_nms_cb *remove_nms; + md_store_lock_global_cb *lock_global; + md_store_unlock_global_cb *unlock_global; +}; + #endif /* mod_md_md_store_h */ |