Skip to content

Commit

Permalink
*) mod_md: full squash of all changes in trunk, since people
Browse files Browse the repository at this point in the history
    do changes and miss proposing them for backport.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1923593 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
icing committed Feb 5, 2025
1 parent 347d7b3 commit 2a01ce2
Show file tree
Hide file tree
Showing 48 changed files with 842 additions and 371 deletions.
14 changes: 14 additions & 0 deletions changes-entries/md_v2.5.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
*) mod_md: update to version 2.5.1
- Added support for ACME profiles with new directives MDProfile and
MDProfileMandatory.
- When installing a custom CA file via `MDCACertificateFile`, also set the
libcurl option CURLSSLOPT_NO_REVOKE that suppresses complains by Schannel
(when curl is linked with it) about missing CRL/OCSP in certificates.
- Fixed handling of corrupted httpd.json and added test 300_30 for it.
File is removed on error and written again. Fixes #369.
- Added explanation in log for how to proceed when md_store.json could not be
parsed and prevented the server start.
- restored fixed to #336 and #337 which got lost in a sync with Apache svn
- Add Issue Name/Uris to certificate information in md-status handler
- MDomains with static certificate files have MDRenewMode "manual", unless
"always" is configured.
6 changes: 6 additions & 0 deletions modules/md/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ struct md_t {
struct apr_array_header_t *pkey_files; /* != NULL iff privkeys explicitly configured */
const char *ca_eab_kid; /* optional KEYID for external account binding */
const char *ca_eab_hmac; /* optional HMAC for external account binding */
const char *profile; /* optional cert profile to order */
int profile_mandatory; /* if profile, when given, is mandatory */

const char *state_descr; /* description of state of NULL */

Expand Down Expand Up @@ -154,6 +156,8 @@ struct md_t {
#define MD_KEY_HTTPS "https"
#define MD_KEY_ID "id"
#define MD_KEY_IDENTIFIER "identifier"
#define MD_KEY_ISSUER_NAME "issuer-name"
#define MD_KEY_ISSUER_URI "issuer-uri"
#define MD_KEY_KEY "key"
#define MD_KEY_KID "kid"
#define MD_KEY_KEYAUTHZ "keyAuthorization"
Expand All @@ -175,6 +179,8 @@ struct md_t {
#define MD_KEY_PKEY "privkey"
#define MD_KEY_PKEY_FILES "pkey-files"
#define MD_KEY_PROBLEM "problem"
#define MD_KEY_PROFILE "profile"
#define MD_KEY_PROFILE_MANDATORY "profile-mandatory"
#define MD_KEY_PROTO "proto"
#define MD_KEY_READY "ready"
#define MD_KEY_REGISTRATION "registration"
Expand Down
23 changes: 23 additions & 0 deletions modules/md/md_acme.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,15 @@ typedef struct {
md_result_t *result;
} update_dir_ctx;

static int collect_profiles(void *baton, const char* key, md_json_t *json)
{
update_dir_ctx *ctx = baton;
(void)json;
APR_ARRAY_PUSH(ctx->acme->api.v2.profiles, const char *) =
apr_pstrdup(ctx->acme->p, key);
return 1;
}

static apr_status_t update_directory(const md_http_response_t *res, void *data)
{
md_http_request_t *req = res->req;
Expand Down Expand Up @@ -728,6 +737,20 @@ static apr_status_t update_directory(const md_http_response_t *res, void *data)
acme->new_nonce_fn = acmev2_new_nonce;
acme->req_init_fn = acmev2_req_init;
acme->post_new_account_fn = acmev2_POST_new_account;

if (md_json_has_key(json, "meta", "profiles", NULL)) {
acme->api.v2.profiles = apr_array_make(acme->p, 5, sizeof(const char*));
md_json_iterkey(collect_profiles, data, json, "meta", "profiles", NULL);
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, req->pool,
"found %d profiles in ACME directory meta",
acme->api.v2.profiles->nelts);
}
else {
acme->api.v2.profiles = NULL;
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, req->pool,
"no profiles in ACME directory meta");

}
}
else if ((s = md_json_dups(acme->p, json, "new-authz", NULL))) {
acme->api.v1.new_authz = s;
Expand Down
1 change: 1 addition & 0 deletions modules/md/md_acme.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct md_acme_t {
const char *key_change;
const char *revoke_cert;
const char *new_nonce;
struct apr_array_header_t *profiles;
} v2;
} api;
const char *ca_agreement;
Expand Down
4 changes: 3 additions & 1 deletion modules/md/md_acme_drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,9 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
if (!ad->domains) {
ad->domains = md_dns_make_minimal(d->p, ad->md->domains);
}

ad->profile = ad->md->profile;
ad->profile_mandatory = ad->md->profile_mandatory;

md_result_activity_printf(result, "Contacting ACME server for %s at %s",
d->md->name, ca_effective);
if (APR_SUCCESS != (rv = md_acme_create(&ad->acme, d->p, ca_effective,
Expand Down
2 changes: 2 additions & 0 deletions modules/md/md_acme_drive.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ typedef struct md_acme_driver_t {
md_t *md;
struct apr_array_header_t *domains;
apr_array_header_t *ca_challenges;
const char *profile;
int profile_mandatory;

int complete;
apr_array_header_t *creds; /* the new md_credentials_t */
Expand Down
20 changes: 12 additions & 8 deletions modules/md/md_acme_order.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,14 @@ typedef struct {
md_acme_order_t *order;
md_acme_t *acme;
const char *name;
const char *profile;
apr_array_header_t *domains;
md_result_t *result;
} order_ctx_t;

#define ORDER_CTX_INIT(ctx, p, o, a, n, d, r) \
#define ORDER_CTX_INIT(ctx, p, o, a, n, d, pf, r) \
(ctx)->p = (p); (ctx)->order = (o); (ctx)->acme = (a); \
(ctx)->name = (n); (ctx)->domains = d; (ctx)->result = r
(ctx)->name = (n); (ctx)->domains = d; (ctx)->profile = pf; (ctx)->result = r

static apr_status_t identifier_to_json(void *value, md_json_t *json, apr_pool_t *p, void *baton)
{
Expand All @@ -289,6 +290,8 @@ static apr_status_t on_init_order_register(md_acme_req_t *req, void *baton)

jpayload = md_json_create(req->p);
md_json_seta(ctx->domains, identifier_to_json, NULL, jpayload, "identifiers", NULL);
if (ctx->profile)
md_json_sets(ctx->profile, jpayload, "profile", NULL);

return md_acme_req_body_init(req, jpayload);
}
Expand Down Expand Up @@ -321,13 +324,14 @@ static apr_status_t on_order_upd(md_acme_t *acme, apr_pool_t *p, const apr_table
}

apr_status_t md_acme_order_register(md_acme_order_t **porder, md_acme_t *acme, apr_pool_t *p,
const char *name, apr_array_header_t *domains)
const char *name, apr_array_header_t *domains,
const char *profile)
{
order_ctx_t ctx;
apr_status_t rv;

assert(MD_ACME_VERSION_MAJOR(acme->version) > 1);
ORDER_CTX_INIT(&ctx, p, NULL, acme, name, domains, NULL);
ORDER_CTX_INIT(&ctx, p, NULL, acme, name, domains, profile, NULL);
rv = md_acme_POST(acme, acme->api.v2.new_order, on_init_order_register, on_order_upd, NULL, NULL, &ctx);
*porder = (APR_SUCCESS == rv)? ctx.order : NULL;
return rv;
Expand All @@ -340,7 +344,7 @@ apr_status_t md_acme_order_update(md_acme_order_t *order, md_acme_t *acme,
apr_status_t rv;

assert(MD_ACME_VERSION_MAJOR(acme->version) > 1);
ORDER_CTX_INIT(&ctx, p, order, acme, NULL, NULL, result);
ORDER_CTX_INIT(&ctx, p, order, acme, NULL, NULL, NULL, result);
rv = md_acme_GET(acme, order->url, NULL, on_order_upd, NULL, NULL, &ctx);
if (APR_SUCCESS != rv && APR_SUCCESS != acme->last->status) {
md_result_dup(result, acme->last);
Expand Down Expand Up @@ -380,7 +384,7 @@ apr_status_t md_acme_order_await_ready(md_acme_order_t *order, md_acme_t *acme,
apr_status_t rv;

assert(MD_ACME_VERSION_MAJOR(acme->version) > 1);
ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, NULL, result);

md_result_activity_setn(result, "Waiting for order to become ready");
rv = md_util_try(await_ready, &ctx, 0, timeout, 0, 0, 1);
Expand Down Expand Up @@ -423,7 +427,7 @@ apr_status_t md_acme_order_await_valid(md_acme_order_t *order, md_acme_t *acme,
apr_status_t rv;

assert(MD_ACME_VERSION_MAJOR(acme->version) > 1);
ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, NULL, result);

md_result_activity_setn(result, "Waiting for finalized order to become valid");
rv = md_util_try(await_valid, &ctx, 0, timeout, 0, 0, 1);
Expand Down Expand Up @@ -552,7 +556,7 @@ apr_status_t md_acme_order_monitor_authzs(md_acme_order_t *order, md_acme_t *acm
order_ctx_t ctx;
apr_status_t rv;

ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, NULL, result);

md_result_activity_printf(result, "Monitoring challenge status for %s", md->name);
rv = md_util_try(check_challenges, &ctx, 0, timeout, 0, 0, 1);
Expand Down
3 changes: 2 additions & 1 deletion modules/md/md_acme_order.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ apr_status_t md_acme_order_monitor_authzs(md_acme_order_t *order, md_acme_t *acm
/* ACMEv2 only ************************************************************************************/

apr_status_t md_acme_order_register(md_acme_order_t **porder, md_acme_t *acme, apr_pool_t *p,
const char *name, struct apr_array_header_t *domains);
const char *name, struct apr_array_header_t *domains,
const char *profile);

apr_status_t md_acme_order_update(md_acme_order_t *order, md_acme_t *acme,
struct md_result_t *result, apr_pool_t *p);
Expand Down
29 changes: 28 additions & 1 deletion modules/md/md_acmev2_drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static apr_status_t ad_setup_order(md_proto_driver_t *d, md_result_t *result, in
md_acme_driver_t *ad = d->baton;
apr_status_t rv;
md_t *md = ad->md;
const char *profile = NULL;

assert(ad->md);
assert(ad->acme);
Expand All @@ -77,7 +78,33 @@ static apr_status_t ad_setup_order(md_proto_driver_t *d, md_result_t *result, in
}

md_result_activity_setn(result, "Creating new order");
rv = md_acme_order_register(&ad->order, ad->acme, d->p, d->md->name, ad->domains);
if (ad->profile) {
if(ad->acme->api.v2.profiles) {
int i;
for (i = 0; !profile && i < ad->acme->api.v2.profiles->nelts; ++i) {
const char *s = APR_ARRAY_IDX(ad->acme->api.v2.profiles, i, const char*);
if (!apr_strnatcasecmp(s, ad->profile))
profile = s;
}
}
if (profile)
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p,
"%s: ordering ACME profile '%s'", md->name, profile);
else if (ad->profile_mandatory) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, d->p,
"%s: mandatory ACME profile '%s' is not offered by CA",
md->name, ad->profile);
rv = APR_EINVAL;
goto leave;
}
else {
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p,
"%s: ACME profile '%s' is not offered by CA, continuing without",
md->name, ad->profile);
}
}

rv = md_acme_order_register(&ad->order, ad->acme, d->p, d->md->name, ad->domains, profile);
if (APR_SUCCESS !=rv) goto leave;
rv = md_acme_order_save(d->store, d->p, MD_SG_STAGING, d->md->name, ad->order, 0);
if (APR_SUCCESS != rv) {
Expand Down
6 changes: 6 additions & 0 deletions modules/md/md_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
md_json_sets(md->ca_eab_kid, json, MD_KEY_EAB, MD_KEY_KID, NULL);
if (md->ca_eab_hmac) md_json_sets(md->ca_eab_hmac, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
}
if (md->profile) md_json_sets(md->profile, json, MD_KEY_PROFILE, NULL);
md_json_setb(md->profile_mandatory > 0, json, MD_KEY_PROFILE_MANDATORY, NULL);
return json;
}
return NULL;
Expand Down Expand Up @@ -383,6 +385,10 @@ md_t *md_from_json(md_json_t *json, apr_pool_t *p)
md->ca_eab_kid = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_KID, NULL);
md->ca_eab_hmac = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
}

md->profile_mandatory = (int)md_json_getb(json, MD_KEY_PROFILE_MANDATORY, NULL);
if (md_json_has_key(json, MD_KEY_PROFILE, NULL))
md->profile = md_json_dups(p, json, MD_KEY_PROFILE, NULL);
return md;
}
return NULL;
Expand Down
63 changes: 50 additions & 13 deletions modules/md/md_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
|| LIBRESSL_VERSION_NUMBER >= 0x3050000fL)
/* Missing from LibreSSL < 3.5.0 and only available since OpenSSL v1.1.x */
#include <openssl/ct.h>
#define MD_HAVE_CT 1
#endif
#ifndef MD_HAVE_CT
#define MD_HAVE_CT 0
#endif

static int initialized;
Expand Down Expand Up @@ -978,42 +982,64 @@ static const char *bn64(const BIGNUM *b, apr_pool_t *p)

const char *md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p)
{
const char *e64 = NULL;

#if OPENSSL_VERSION_NUMBER < 0x30000000L

#if OPENSSL_VERSION_NUMBER < 0x10101000L
RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey);
#else
const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey);
#endif
if (rsa) {
const BIGNUM *e;
RSA_get0_key(rsa, NULL, &e, NULL);
return bn64(e, p);
e64 = bn64(e, p);
#if OPENSSL_VERSION_NUMBER < 0x10101000L
RSA_free(rsa);
#endif
}
#else

#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
BIGNUM *e = NULL;
if (EVP_PKEY_get_bn_param(pkey->pkey, OSSL_PKEY_PARAM_RSA_E, &e)) {
const char *e64 = bn64(e, p);
e64 = bn64(e, p);
BN_free(e);
return e64;
}
#endif
return NULL;

return e64;
}

const char *md_pkey_get_rsa_n64(md_pkey_t *pkey, apr_pool_t *p)
{
const char *n64 = NULL;

#if OPENSSL_VERSION_NUMBER < 0x30000000L

#if OPENSSL_VERSION_NUMBER < 0x10101000L
RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey);
#else
const RSA *rsa = EVP_PKEY_get0_RSA(pkey->pkey);
#endif
if (rsa) {
const BIGNUM *n;
RSA_get0_key(rsa, &n, NULL, NULL);
return bn64(n, p);
n64 = bn64(n, p);
#if OPENSSL_VERSION_NUMBER < 0x10101000L
RSA_free(rsa);
#endif
}
#else

#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
BIGNUM *n = NULL;
if (EVP_PKEY_get_bn_param(pkey->pkey, OSSL_PKEY_PARAM_RSA_N, &n)) {
const char *n64 = bn64(n, p);
n64 = bn64(n, p);
BN_free(n);
return n64;
}
#endif
return NULL;

return n64;
}

apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *p,
Expand Down Expand Up @@ -1265,6 +1291,18 @@ int md_cert_covers_md(md_cert_t *cert, const md_t *md)
return 0;
}

const char *md_cert_get_issuer_name(const md_cert_t *cert, apr_pool_t *p)
{
X509_NAME *xname = X509_get_issuer_name(cert->x509);
if(xname) {
char *name, *s = X509_NAME_oneline(xname, NULL, 0);
name = apr_pstrdup(p, s);
OPENSSL_free(s);
return name;
}
return NULL;
}

apr_status_t md_cert_get_issuers_uri(const char **puri, const md_cert_t *cert, apr_pool_t *p)
{
apr_status_t rv = APR_ENOENT;
Expand Down Expand Up @@ -2037,11 +2075,10 @@ apr_status_t md_cert_make_tls_alpn_01(md_cert_t **pcert, const char *domain,
return rv;
}

#if MD_HAVE_CT
#define MD_OID_CT_SCTS_NUM "1.3.6.1.4.1.11129.2.4.2"
#define MD_OID_CT_SCTS_SNAME "CT-SCTs"
#define MD_OID_CT_SCTS_LNAME "CT Certificate SCTs"

#ifndef OPENSSL_NO_CT
static int get_ct_scts_nid(void)
{
int nid = OBJ_txt2nid(MD_OID_CT_SCTS_NUM);
Expand All @@ -2065,7 +2102,7 @@ const char *md_nid_get_lname(int nid)

apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const md_cert_t *cert)
{
#ifndef OPENSSL_NO_CT
#if MD_HAVE_CT
int nid, i, idx, critical;
STACK_OF(SCT) *sct_list;
SCT *sct_handle;
Expand Down
1 change: 1 addition & 0 deletions modules/md/md_crypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ struct md_timeperiod_t md_cert_get_valid(const md_cert_t *cert);
*/
int md_certs_are_equal(const md_cert_t *a, const md_cert_t *b);

const char *md_cert_get_issuer_name(const md_cert_t *cert, apr_pool_t *p);
apr_status_t md_cert_get_issuers_uri(const char **puri, const md_cert_t *cert, apr_pool_t *p);
apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, const md_cert_t *cert, apr_pool_t *p);

Expand Down
Loading

0 comments on commit 2a01ce2

Please sign in to comment.