Apache HTTPD
mod_md_ocsp.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <apr_optional.h>
19#include <apr_time.h>
20#include <apr_date.h>
21#include <apr_strings.h>
22
23#include <httpd.h>
24#include <http_core.h>
25#include <http_log.h>
26#include <http_ssl.h>
27
28#include "mod_watchdog.h"
29
30#include "md.h"
31#include "md_crypt.h"
32#include "md_http.h"
33#include "md_json.h"
34#include "md_ocsp.h"
35#include "md_store.h"
36#include "md_log.h"
37#include "md_reg.h"
38#include "md_time.h"
39#include "md_util.h"
40
41#include "mod_md.h"
42#include "mod_md_config.h"
43#include "mod_md_private.h"
44#include "mod_md_ocsp.h"
45
46static int staple_here(md_srv_conf_t *sc)
47{
48 if (!sc || !sc->mc->ocsp) return 0;
49 if (sc->assigned
50 && sc->assigned->nelts == 1
51 && APR_ARRAY_IDX(sc->assigned, 0, const md_t*)->stapling) return 1;
54}
55
57 const char *id, apr_size_t id_len, const char *pem)
58{
59 md_srv_conf_t *sc;
60 const md_t *md;
61 apr_array_header_t *chain;
63
64 sc = md_config_get(s);
65 if (!staple_here(sc)) goto cleanup;
66
67 md = ((sc->assigned && sc->assigned->nelts == 1)?
68 APR_ARRAY_IDX(sc->assigned, 0, const md_t*) : NULL);
69 chain = apr_array_make(p, 5, sizeof(md_cert_t*));
70 rv = md_cert_read_chain(chain, p, pem, strlen(pem));
71 if (APR_SUCCESS != rv) {
72 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10268) "init stapling for: %s, "
73 "unable to parse PEM data", md? md->name : s->server_hostname);
74 goto cleanup;
75 }
76 else if (chain->nelts < 2) {
77 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10269) "init stapling for: %s, "
78 "need at least 2 certificates in PEM data", md? md->name : s->server_hostname);
79 rv = APR_EINVAL;
80 goto cleanup;
81 }
82
83 rv = md_ocsp_prime(sc->mc->ocsp, id, id_len,
84 APR_ARRAY_IDX(chain, 0, md_cert_t*),
85 APR_ARRAY_IDX(chain, 1, md_cert_t*), md);
86 ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, s, "init stapling for: %s",
87 md? md->name : s->server_hostname);
88
90 return (APR_SUCCESS == rv)? OK : DECLINED;
91}
92
93typedef struct {
94 unsigned char *der;
97
99 const char *id, apr_size_t id_len,
100 ap_ssl_ocsp_copy_resp *cb, void *userdata)
101{
102 md_srv_conf_t *sc;
103 const md_t *md;
104 apr_status_t rv;
105
106 sc = md_config_get(s);
107 if (!staple_here(sc)) goto declined;
108
109 md = ((sc->assigned && sc->assigned->nelts == 1)?
110 APR_ARRAY_IDX(sc->assigned, 0, const md_t*) : NULL);
111 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "get stapling for: %s",
112 md? md->name : s->server_hostname);
113
114 rv = md_ocsp_get_status(cb, userdata, sc->mc->ocsp, id, id_len, c->pool, md);
115 if (APR_STATUS_IS_ENOENT(rv)) goto declined;
116 return OK;
117
119 return DECLINED;
120}
121
122
123/**************************************************************************************************/
124/* watchdog based impl. */
125
126#define MD_OCSP_WATCHDOG_NAME "_md_ocsp_"
127
131
133
140
142{
143 /* we'd like to run at least hourly */
145}
146
147static apr_status_t run_watchdog(int state, void *baton, apr_pool_t *ptemp)
148{
150 apr_time_t next_run, wait_time;
151
152 /* mod_watchdog invoked us as a single thread inside the whole server (on this machine).
153 * This might be a repeated run inside the same child (mod_watchdog keeps affinity as
154 * long as the child lives) or another/new child.
155 */
156 switch (state) {
159 "md ocsp watchdog start, ocsp stapling %d certificates",
160 (int)md_ocsp_count(octx->mc->ocsp));
161 break;
162
165 "md ocsp watchdog run, ocsp stapling %d certificates",
166 (int)md_ocsp_count(octx->mc->ocsp));
167
168 /* Process all drive jobs. They will update their next_run property
169 * and we schedule ourself at the earliest of all. A job may specify 0
170 * as next_run to indicate that it wants to participate in the normal
171 * regular runs. */
172 next_run = next_run_default();
173
174 md_ocsp_renew(octx->mc->ocsp, octx->p, ptemp, &next_run);
175
176 wait_time = next_run - apr_time_now();
177 if (APLOGdebug(octx->s)) {
179 "md ocsp watchdog next run in %s",
181 }
183 break;
184
187 "md ocsp watchdog stopping");
188 break;
189 }
190
191 return APR_SUCCESS;
192}
193
195{
197
200 keep = md_timeperiod_slice_before_end(&keep_norm, mc->ocsp_keep_window);
201 /* remove any ocsp response older than keep.start */
202 return md_ocsp_remove_responses_older_than(mc->ocsp, p, keep.start);
203}
204
206{
210 apr_status_t rv;
211
215
218 "mod_watchdog is required for OCSP stapling");
219 return APR_EGENERAL;
220 }
221
222 /* We want our own pool with own allocator to keep data across watchdog invocations.
223 * Since we'll run in a single watchdog thread, using our own allocator will prevent
224 * any confusion in the parent pool. */
228 if (rv != APR_SUCCESS) {
229 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10205) "md_ocsp_watchdog: create pool");
230 return rv;
231 }
233 apr_pool_tag(octxp, "md_ocsp_watchdog");
234
235 octx = apr_pcalloc(octxp, sizeof(*octx));
236 octx->p = octxp;
237 octx->s = s;
238 octx->mc = mc;
239
240 /* Time for some house keeping, before the server goes live (again):
241 * - we store OCSP responses for each certificate individually by its SHA-1 id
242 * - this means, as long as certificate do not change, the number of response
243 * files remains stable.
244 * - But when a certificate changes (is replaced), the response is obsolete
245 * - we do not get notified when a certificate is no longer used. An admin
246 * might just reconfigure or change the content of a file (backup/restore etc.)
247 * - also, certificates might be added by some openssl config commands or other
248 * modules that we do not immediately see right at startup. We cannot assume
249 * that any OCSP response we cannot relate to a certificate RIGHT NOW, is no
250 * longer needed.
251 * - since the response files are relatively small, we have no problem with
252 * keeping them around for a while. We just do not want an ever growing store.
253 * - The simplest and effective way seems to be to just remove files older
254 * a certain amount of time. Take a 7 day default and let the admin configure
255 * it for very special setups.
256 */
258
259 rv = wd_get_instance(&octx->watchdog, MD_OCSP_WATCHDOG_NAME, 0, 1, octx->p);
260 if (APR_SUCCESS != rv) {
262 "create md ocsp watchdog(%s)", MD_OCSP_WATCHDOG_NAME);
263 return rv;
264 }
265 rv = wd_register_callback(octx->watchdog, 0, octx, run_watchdog);
267 "register md ocsp watchdog(%s)", MD_OCSP_WATCHDOG_NAME);
268 return rv;
269}
270
271
272
APR-UTIL date routines.
APR-UTIL registration of functions exported by modules.
APR Strings library.
APR Time Library.
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define ap_log_cerror
Definition http_log.h:498
#define APLOGdebug(s)
Definition http_log.h:234
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_TRACE2
Definition http_log.h:73
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_DEBUG
Definition http_log.h:71
void ap_ssl_ocsp_copy_resp(const unsigned char *der, apr_size_t der_len, void *userdata)
Definition http_ssl.h:271
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_memcache_t * mc
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define APR_OPTIONAL_FN_TYPE(name)
#define AP_WATCHDOG_STATE_STARTING
#define AP_WATCHDOG_STATE_STOPPING
#define AP_WATCHDOG_STATE_RUNNING
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void const char apr_status_t(* cleanup)(void *))
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_abortfunc_t apr_allocator_t * allocator
Definition apr_pools.h:208
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
CORE HTTP Daemon.
Apache Logging library.
SSL protocol handling.
HTTP Daemon routines.
#define MD_TIME_OCSP_KEEP_NORM
Definition md.h:48
apr_status_t md_cert_read_chain(apr_array_header_t *chain, apr_pool_t *p, const char *pem, apr_size_t pem_len)
Definition md_crypt.c:1472
apr_pool_t * p
Definition md_event.c:32
apr_size_t md_ocsp_count(md_ocsp_reg_t *reg)
Definition md_ocsp.c:491
void md_ocsp_renew(md_ocsp_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp, apr_time_t *pnext_run)
Definition md_ocsp.c:880
apr_status_t md_ocsp_remove_responses_older_than(md_ocsp_reg_t *reg, apr_pool_t *p, apr_time_t timestamp)
Definition md_ocsp.c:922
apr_status_t md_ocsp_prime(md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ext_id_len, md_cert_t *cert, md_cert_t *issuer, const md_t *md)
Definition md_ocsp.c:305
apr_status_t md_ocsp_get_status(md_ocsp_copy_der *cb, void *userdata, md_ocsp_reg_t *reg, const char *ext_id, apr_size_t ext_id_len, apr_pool_t *p, const md_t *md)
Definition md_ocsp.c:373
const char * md_duration_print(apr_pool_t *p, apr_interval_time_t duration)
Definition md_time.c:108
md_timeperiod_t md_timeperiod_slice_before_end(const md_timeperiod_t *period, const md_timeslice_t *ts)
Definition md_time.c:286
#define MD_SECS_PER_HOUR
Definition md_time.h:22
md_srv_conf_t * md_config_get(server_rec *s)
int md_config_geti(const md_srv_conf_t *sc, md_config_var_t var)
@ MD_CONFIG_STAPLING
@ MD_CONFIG_STAPLE_OTHERS
static apr_time_t next_run_default(void)
static apr_OFN_ap_watchdog_register_callback_t * wd_register_callback
int md_ocsp_provide_status(server_rec *s, conn_rec *c, const char *id, apr_size_t id_len, ap_ssl_ocsp_copy_resp *cb, void *userdata)
Definition mod_md_ocsp.c:98
static apr_OFN_ap_watchdog_set_callback_interval_t * wd_set_interval
int md_ocsp_prime_status(server_rec *s, apr_pool_t *p, const char *id, apr_size_t id_len, const char *pem)
Definition mod_md_ocsp.c:56
static apr_status_t ocsp_remove_old_responses(md_mod_conf_t *mc, apr_pool_t *p)
static int staple_here(md_srv_conf_t *sc)
Definition mod_md_ocsp.c:46
static apr_status_t run_watchdog(int state, void *baton, apr_pool_t *ptemp)
#define MD_OCSP_WATCHDOG_NAME
apr_status_t md_ocsp_start_watching(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p)
static apr_OFN_ap_watchdog_get_instance_t * wd_get_instance
return NULL
Definition mod_so.c:359
static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w, apr_interval_time_t interval, const void *data, ap_watchdog_callback_fn_t *callback)
static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog, const char *name, int parent, int singleton, apr_pool_t *p)
static apr_status_t ap_watchdog_set_callback_interval(ap_watchdog_t *w, apr_interval_time_t interval, const void *data, ap_watchdog_callback_fn_t *callback)
Watchdog module for Apache.
apr_pool_t * p
Structure to store things which are per connection.
Definition httpd.h:1152
struct md_ocsp_reg_t * ocsp
server_rec * s
md_mod_conf_t * mc
ap_watchdog_t * watchdog
apr_pool_t * p
struct apr_array_header_t * assigned
md_mod_conf_t * mc
Definition md.h:76
const char * name
Definition md.h:77
apr_time_t end
Definition md_time.h:29
unsigned char * der
Definition mod_md_ocsp.c:94
apr_size_t der_len
Definition mod_md_ocsp.c:95
A structure to store information for each virtual server.
Definition httpd.h:1322