Skip to content
This repository was archived by the owner on Jun 9, 2026. It is now read-only.

Commit f4b4a13

Browse files
committed
New directive: MDHttpProxyCACertificateFile
Sets the CA certificates to use for connections to the HTTPS proxy that has been configured with MDHttpProxy.
1 parent e820482 commit f4b4a13

14 files changed

Lines changed: 98 additions & 13 deletions

src/md.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ struct md_t {
103103
const char *proxy_url; /* Proxy URL, override global command */
104104
const char *ca_certs; /* root certificates to use for connections,
105105
override global command */
106+
const char *proxy_ca_certs; /* root certificates to use for proxy connections,
107+
override global command */
106108
const struct md_srv_conf_t *sc; /* server config where it was defined or NULL */
107109
const char *defn_name; /* config file this MD was defined */
108110
unsigned defn_line_number; /* line number of definition */
@@ -188,6 +190,7 @@ struct md_t {
188190
#define MD_KEY_PROFILE "profile"
189191
#define MD_KEY_PROFILE_MANDATORY "profile-mandatory"
190192
#define MD_KEY_PROTO "proto"
193+
#define MD_KEY_PROXY_CA_CERTS "proxy-ca-certs"
191194
#define MD_KEY_PROXY_URL "proxy-url"
192195
#define MD_KEY_READY "ready"
193196
#define MD_KEY_REGISTRATION "registration"

src/md_acme.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ apr_status_t md_acme_POST_new_account(md_acme_t *acme,
622622
/* ACME setup */
623623

624624
apr_status_t md_acme_create(md_acme_t **pacme, apr_pool_t *p, const char *url,
625-
const char *proxy_url, const char *ca_file)
625+
const char *proxy_url, const char *ca_file,
626+
const char *proxy_ca_file)
626627
{
627628
md_acme_t *acme;
628629
const char *err = NULL;
@@ -648,6 +649,7 @@ apr_status_t md_acme_create(md_acme_t **pacme, apr_pool_t *p, const char *url,
648649
acme->proxy_url = apr_pstrdup(p, proxy_url);
649650
acme->max_retries = 9;
650651
acme->ca_file = ca_file;
652+
acme->proxy_ca_file = proxy_ca_file;
651653

652654
if (APR_SUCCESS != (rv = apr_uri_parse(p, url, &uri_parsed))) {
653655
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "parsing ACME uri: %s", url);
@@ -800,6 +802,7 @@ apr_status_t md_acme_setup(md_acme_t *acme, md_result_t *result)
800802
md_http_set_connect_timeout_default(acme->http, apr_time_from_sec(30));
801803
md_http_set_stalling_default(acme->http, 10, apr_time_from_sec(30));
802804
md_http_set_ca_file(acme->http, acme->ca_file);
805+
md_http_set_proxy_ca_file(acme->http, acme->proxy_ca_file);
803806

804807
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, acme->p, "get directory from %s", acme->url);
805808

src/md_acme.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct md_acme_t {
9898
const char *user_agent;
9999
const char *proxy_url;
100100
const char *ca_file;
101+
const char *proxy_ca_file;
101102

102103
const char *acct_id; /* local storage id account was loaded from or NULL */
103104
struct md_acme_acct_t *acct; /* account at ACME server to use for requests */
@@ -152,9 +153,11 @@ apr_status_t md_acme_init(apr_pool_t *pool, const char *base_version, int init_s
152153
* @param url url of the server, optional if known at path
153154
* @param proxy_url optional url of a HTTP(S) proxy to use
154155
* @param ca_file optional CA trust anchor file to use
156+
* @param proxy_ca_file optional CA trust anchor file to use for the HTTP proxy
155157
*/
156158
apr_status_t md_acme_create(md_acme_t **pacme, apr_pool_t *p, const char *url,
157-
const char *proxy_url, const char *ca_file);
159+
const char *proxy_url, const char *ca_file,
160+
const char *proxy_ca_file);
158161

159162
/**
160163
* Contact the ACME server and retrieve its directory information.

src/md_acme_drive.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,8 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
772772
d->md->name, ca_effective);
773773
if (APR_SUCCESS != (rv = md_acme_create(&ad->acme, d->p, ca_effective,
774774
ad->md->proxy_url ? ad->md->proxy_url : d->proxy_url,
775-
ad->md->ca_certs ? ad->md->ca_certs : d->ca_certs))) {
775+
ad->md->ca_certs ? ad->md->ca_certs : d->ca_certs,
776+
ad->md->proxy_ca_certs ? ad->md->proxy_ca_certs : d->proxy_ca_certs))) {
776777
md_result_printf(result, rv, "setup ACME communications");
777778
md_result_log(result, MD_LOG_ERR);
778779
goto out;
@@ -1035,7 +1036,8 @@ static apr_status_t acme_preload(md_proto_driver_t *d, md_store_group_t load_gro
10351036

10361037
if (APR_SUCCESS != (rv = md_acme_create(&acme, d->p, md->ca_effective,
10371038
d->md->proxy_url ? d->md->proxy_url : d->proxy_url,
1038-
d->md->ca_certs ? d->md->ca_certs : d->ca_certs))) {
1039+
d->md->ca_certs ? d->md->ca_certs : d->ca_certs,
1040+
d->md->proxy_ca_certs ? d->md->proxy_ca_certs : d->proxy_ca_certs))) {
10391041
md_result_set(result, rv, "error setting up acme");
10401042
goto leave;
10411043
}
@@ -1145,7 +1147,8 @@ static apr_status_t acme_get_ari(md_proto_driver_t *d,
11451147

11461148
if (APR_SUCCESS != (rv = md_acme_create(&ad->acme, d->p, ca_effective,
11471149
d->md->proxy_url ? d->md->proxy_url : d->proxy_url,
1148-
d->md->ca_certs ? d->md->ca_certs : d->ca_certs))) {
1150+
d->md->ca_certs ? d->md->ca_certs : d->ca_certs,
1151+
d->md->proxy_ca_certs ? d->md->proxy_ca_certs : d->proxy_ca_certs))) {
11491152
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, d->p,
11501153
"create ACME communications");
11511154
goto out;

src/md_cmd_main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static apr_status_t cmd_process(md_cmd_ctx *ctx, const md_cmd_t *cmd)
186186
}
187187
if (APR_SUCCESS != (rv = md_reg_create(&ctx->reg, ctx->p, ctx->store,
188188
md_cmd_ctx_get_option(ctx, MD_CMD_OPT_PROXY_URL),
189-
ctx->ca_file, apr_time_from_sec(15), 10,
189+
ctx->ca_file, NULL, apr_time_from_sec(15), 10,
190190
0, apr_time_from_sec(5)))) {
191191
fprintf(stderr, "error %d creating registry from store: %s\n", rv, ctx->base_dir);
192192
return APR_EINVAL;
@@ -199,7 +199,7 @@ static apr_status_t cmd_process(md_cmd_ctx *ctx, const md_cmd_t *cmd)
199199
}
200200
rv = md_acme_create(&ctx->acme, ctx->p, ctx->ca_url,
201201
md_cmd_ctx_get_option(ctx, MD_CMD_OPT_PROXY_URL),
202-
ctx->ca_file);
202+
ctx->ca_file, NULL);
203203
if (APR_SUCCESS != rv) {
204204
fprintf(stderr, "error creating acme instance %s (%s)\n",
205205
ctx->ca_url, ctx->base_dir);

src/md_core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ md_t *md_clone(apr_pool_t *p, const md_t *src)
260260
if (src->dns01_cmd) md->dns01_cmd = apr_pstrdup(p, src->dns01_cmd);
261261
if (src->proxy_url) md->proxy_url = apr_pstrdup(p, src->proxy_url);
262262
if (src->ca_certs) md->ca_certs = apr_pstrdup(p, src->ca_certs);
263+
if (src->proxy_ca_certs) md->proxy_ca_certs = apr_pstrdup(p, src->proxy_ca_certs);
263264
if (src->cert_files) md->cert_files = md_array_str_clone(p, src->cert_files);
264265
if (src->pkey_files) md->pkey_files = md_array_str_clone(p, src->pkey_files);
265266
}
@@ -319,6 +320,7 @@ md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
319320
if (md->dns01_cmd) md_json_sets(md->dns01_cmd, json, MD_KEY_CMD_DNS01, NULL);
320321
if (md->proxy_url) md_json_sets(md->proxy_url, json, MD_KEY_PROXY_URL, NULL);
321322
if (md->ca_certs) md_json_sets(md->ca_certs, json, MD_KEY_CA_CERTS, NULL);
323+
if (md->proxy_ca_certs) md_json_sets(md->proxy_ca_certs, json, MD_KEY_PROXY_CA_CERTS, NULL);
322324
if (md->ca_eab_kid && strcmp("none", md->ca_eab_kid)) {
323325
md_json_sets(md->ca_eab_kid, json, MD_KEY_EAB, MD_KEY_KID, NULL);
324326
if (md->ca_eab_hmac) md_json_sets(md->ca_eab_hmac, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
@@ -390,6 +392,7 @@ md_t *md_from_json(md_json_t *json, apr_pool_t *p)
390392
md->dns01_cmd = md_json_dups(p, json, MD_KEY_CMD_DNS01, NULL);
391393
md->proxy_url = md_json_dups(p, json, MD_KEY_PROXY_URL, NULL);
392394
md->ca_certs = md_json_dups(p, json, MD_KEY_CA_CERTS, NULL);
395+
md->proxy_ca_certs = md_json_dups(p, json, MD_KEY_PROXY_CA_CERTS, NULL);
393396
if (md_json_has_key(json, MD_KEY_EAB, NULL)) {
394397
md->ca_eab_kid = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_KID, NULL);
395398
md->ca_eab_hmac = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);

src/md_curl.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ static apr_status_t internals_setup(md_http_request_t *req)
246246
CURL *curl;
247247
apr_status_t rv = APR_SUCCESS;
248248
long ssl_options = 0;
249+
long proxy_ssl_options = 0;
249250

250251
curl = md_http_get_impl_data(req->http);
251252
if (!curl) {
@@ -313,6 +314,16 @@ static apr_status_t internals_setup(md_http_request_t *req)
313314
ssl_options |= CURLSSLOPT_NO_REVOKE;
314315
#endif
315316
}
317+
if (req->proxy_ca_file) {
318+
curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO, req->proxy_ca_file);
319+
/* for a custom CA, allow certificates checking to ignore the
320+
* Schannel error CRYPT_E_NO_REVOCATION_CHECK (could be a missing OCSP
321+
* responder URL in the certs???). See issue #361 */
322+
#ifdef CURLSSLOPT_NO_REVOKE
323+
proxy_ssl_options |= CURLSSLOPT_NO_REVOKE;
324+
#endif
325+
}
326+
316327
if (req->unix_socket_path) {
317328
curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, req->unix_socket_path);
318329
}
@@ -354,6 +365,9 @@ static apr_status_t internals_setup(md_http_request_t *req)
354365
if (ssl_options)
355366
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, ssl_options);
356367

368+
if (proxy_ssl_options)
369+
curl_easy_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS, proxy_ssl_options);
370+
357371
leave:
358372
req->internals = (APR_SUCCESS == rv)? internals : NULL;
359373
return rv;

src/md_http.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct md_http_t {
3636
const char *unix_socket_path;
3737
md_http_timeouts_t timeout;
3838
const char *ca_file;
39+
const char *proxy_ca_file;
3940
};
4041

4142
static md_http_impl_t *cur_impl;
@@ -107,6 +108,9 @@ apr_status_t md_http_clone(md_http_t **phttp,
107108
if (source_http->ca_file) {
108109
(*phttp)->ca_file = apr_pstrdup(p, source_http->ca_file);
109110
}
111+
if (source_http->proxy_ca_file) {
112+
(*phttp)->proxy_ca_file = apr_pstrdup(p, source_http->proxy_ca_file);
113+
}
110114
}
111115
return rv;
112116
}
@@ -163,6 +167,11 @@ void md_http_set_ca_file(md_http_t *http, const char *ca_file)
163167
http->ca_file = ca_file;
164168
}
165169

170+
void md_http_set_proxy_ca_file(md_http_t *http, const char *ca_file)
171+
{
172+
http->proxy_ca_file = ca_file;
173+
}
174+
166175
void md_http_set_unix_socket_path(md_http_t *http, const char *path)
167176
{
168177
http->unix_socket_path = path;
@@ -235,6 +244,7 @@ static apr_status_t req_create(md_http_request_t **preq, md_http_t *http,
235244
req->proxy_url = http->proxy_url;
236245
req->timeout = http->timeout;
237246
req->ca_file = http->ca_file;
247+
req->proxy_ca_file = http->proxy_ca_file;
238248
req->unix_socket_path = http->unix_socket_path;
239249
*preq = req;
240250
return rv;

src/md_http.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct md_http_request_t {
6565
const char *user_agent;
6666
const char *proxy_url;
6767
const char *ca_file;
68+
const char *proxy_ca_file;
6869
const char *unix_socket_path;
6970
apr_table_t *headers;
7071
struct apr_bucket_brigade *body;
@@ -119,12 +120,19 @@ void md_http_set_stalling_default(md_http_t *http, long bytes_per_sec, apr_time_
119120
void md_http_set_stalling(md_http_request_t *req, long bytes_per_sec, apr_time_t timeout);
120121

121122
/**
122-
* Set a CA file (in PERM format) to use for root certificates when
123+
* Set a CA file (in PEM format) to use for root certificates when
123124
* verifying SSL connections. If not set (or set to NULL), the systems
124125
* certificate store will be used.
125126
*/
126127
void md_http_set_ca_file(md_http_t *http, const char *ca_file);
127128

129+
/**
130+
* Set a CA file (in PEM format) to use for root certificates when
131+
* verifying SSL connections to the HTTP proxy. If not set (or set to NULL),
132+
* the systems certificate store will be used.
133+
*/
134+
void md_http_set_proxy_ca_file(md_http_t *http, const char *ca_file);
135+
128136
/**
129137
* Set the path of a unix domain socket for use instead of TCP
130138
* in a connection. Disable by providing NULL as path.

src/md_reg.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct md_reg_t {
4848
int can_https;
4949
const char *proxy_url;
5050
const char *ca_certs;
51+
const char *proxy_ca_certs;
5152
int domains_frozen;
5253
md_timeslice_t *renew_window;
5354
md_timeslice_t *warn_window;
@@ -97,8 +98,9 @@ static apr_status_t load_props(md_reg_t *reg, apr_pool_t *p)
9798

9899
apr_status_t md_reg_create(md_reg_t **preg, apr_pool_t *p, struct md_store_t *store,
99100
const char *proxy_url, const char *ca_certs,
100-
apr_time_t min_delay, int retry_failover,
101-
int use_store_locks, apr_time_t lock_wait_timeout)
101+
const char *proxy_ca_certs, apr_time_t min_delay,
102+
int retry_failover, int use_store_locks,
103+
apr_time_t lock_wait_timeout)
102104
{
103105
md_reg_t *reg;
104106
apr_status_t rv;
@@ -113,6 +115,8 @@ apr_status_t md_reg_create(md_reg_t **preg, apr_pool_t *p, struct md_store_t *st
113115
reg->proxy_url = apr_pstrdup(p, proxy_url);
114116
reg->ca_certs = (ca_certs && apr_cstr_casecmp("none", ca_certs))?
115117
apr_pstrdup(p, ca_certs) : NULL;
118+
reg->proxy_ca_certs = (proxy_ca_certs && apr_cstr_casecmp("none", proxy_ca_certs))?
119+
apr_pstrdup(p, proxy_ca_certs) : NULL;
116120
reg->min_delay = min_delay;
117121
reg->retry_failover = retry_failover;
118122
reg->use_store_locks = use_store_locks;
@@ -1110,6 +1114,7 @@ static apr_status_t run_init(void *baton, apr_pool_t *p, ...)
11101114
driver->store = md_reg_store_get(reg);
11111115
driver->proxy_url = reg->proxy_url;
11121116
driver->ca_certs = reg->ca_certs;
1117+
driver->proxy_ca_certs = reg->proxy_ca_certs;
11131118
driver->md = md;
11141119
driver->can_http = reg->can_http;
11151120
driver->can_https = reg->can_https;

0 commit comments

Comments
 (0)