Apache HTTPD
ssl_engine_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 "ssl_private.h"
18
19#ifndef OPENSSL_NO_OCSP
20#include "apr_base64.h"
21
22/* Return the responder URI specified in the given certificate, or
23 * NULL if none specified. */
25{
27 char *result = NULL;
28 int j;
29
31 if (!values) {
32 return NULL;
33 }
34
35 for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values) && !result; j++) {
37
38 /* Name found in extension, and is a URI: */
39 if (OBJ_obj2nid(value->method) == NID_ad_OCSP
40 && value->location->type == GEN_URI) {
42 (char *)value->location->d.uniformResourceIdentifier->data);
43 }
44 }
45
47
48 return result;
49}
50
51/* Return the responder URI object which should be used in the given
52 * configuration for the given certificate, or NULL if none can be
53 * determined. */
56{
57 apr_uri_t *u = apr_palloc(p, sizeof *u);
58 const char *s;
59 apr_status_t rv;
60
61 /* Use default responder URL if forced by configuration, else use
62 * certificate-specified responder, falling back to default if
63 * necessary and possible. */
64 if (sc->server->ocsp_force_default == TRUE) {
65 s = sc->server->ocsp_responder;
66 }
67 else {
69
70 if (s == NULL && sc->server->ocsp_responder) {
71 s = sc->server->ocsp_responder;
72 }
73 }
74
75 if (s == NULL) {
77 "no OCSP responder specified in certificate and "
78 "no default configured");
79 return NULL;
80 }
81
82 rv = apr_uri_parse(p, s, u);
83 if (rv || !u->hostname) {
85 "failed to parse OCSP responder URI '%s'", s);
86 return NULL;
87 }
88
89 if (ap_cstr_casecmp(u->scheme, "http") != 0) {
91 "cannot handle OCSP responder URI '%s'", s);
92 return NULL;
93 }
94
95 if (!u->port) {
96 u->port = apr_uri_port_of_scheme(u->scheme);
97 }
98
99 return u;
100}
101
102/* Create an OCSP request for the given certificate; returning the
103 * certificate ID in *certid and *issuer on success. Returns the
104 * request object on success, or NULL on error. */
106 OCSP_CERTID **certid,
108 SSLSrvConfigRec *sc)
109{
111
113 if (!*certid || !OCSP_request_add0_id(req, *certid)) {
115 "could not retrieve certificate id");
117 return NULL;
118 }
119
120 if (sc->server->ocsp_use_request_nonce != FALSE) {
121 OCSP_request_add1_nonce(req, 0, -1);
122 }
123
124 return req;
125}
126
127/* Verify the OCSP status of given certificate. Returns
128 * V_OCSP_CERTSTATUS_* result code. */
132{
134 OCSP_RESPONSE *response = NULL;
136 OCSP_REQUEST *request = NULL;
139
141 if (!ruri) {
144 "Skipping OCSP check for certificate cos no OCSP URL"
145 " found and no_ocsp_for_cert_ok is set");
147 } else {
149 }
150 }
151
152 request = create_request(ctx, cert, &certID, s, pool, sc);
153 if (request) {
157 response = modssl_dispatch_ocsp_request(ruri, to, request, c, pool);
158 }
159
160 if (!request || !response) {
162 }
163
164 if (rc == V_OCSP_CERTSTATUS_GOOD) {
165 int r = OCSP_response_status(response);
166
169 "OCSP response not successful: %d", r);
171 }
172 }
173
174 if (rc == V_OCSP_CERTSTATUS_GOOD) {
176 if (!basicResponse) {
178 "could not retrieve OCSP basic response");
181 }
182 }
183
184 if (rc == V_OCSP_CERTSTATUS_GOOD &&
186 OCSP_check_nonce(request, basicResponse) != 1) {
188 "Bad OCSP responder answer (bad nonce)");
190 }
191
192 if (rc == V_OCSP_CERTSTATUS_GOOD) {
193 /* Check if OCSP certificate verification required */
194 if (sc->server->ocsp_noverify != TRUE) {
195 /* Modify OCSP response verification to include OCSP Responder cert */
197 sc->server->ocsp_verify_flags) != 1) {
199 "failed to verify the OCSP response");
202 }
203 }
204 }
205
206 if (rc == V_OCSP_CERTSTATUS_GOOD) {
207 int reason = -1, status;
209
211 &reason, NULL, &thisup, &nextup);
212 if (rc != 1) {
214 "failed to retrieve OCSP response status");
217 }
218 else {
219 rc = status;
220 }
221
222 /* Check whether the response is inside the defined validity
223 * period; otherwise fail. */
227 /* oscp_resp_maxage can be passed verbatim - UNSET (-1) means
228 * that responses can be of any age as long as nextup is in the
229 * future. */
232 if (vrc != 1) {
234 "OCSP response outside validity period");
237 }
238 }
239
240 {
241 int level =
243 const char *result =
244 status == V_OCSP_CERTSTATUS_GOOD ? "good" :
245 (status == V_OCSP_CERTSTATUS_REVOKED ? "revoked" : "unknown");
246
247 ssl_log_cxerror(SSLLOG_MARK, level, 0, c, cert, APLOGNO(03239)
248 "OCSP validation completed, "
249 "certificate status: %s (%d, %d)",
251 }
252 }
253
254 if (request) OCSP_REQUEST_free(request);
255 if (response) OCSP_RESPONSE_free(response);
257 /* certID is freed when the request is freed */
258
259 return rc;
260}
261
264{
267 int rv;
268
269 if (!cert) {
270 /* starting with OpenSSL 1.0, X509_STORE_CTX_get_current_cert()
271 * may yield NULL. Return early, but leave the ctx error as is. */
273 "No cert available to check with OCSP");
274 return 1;
275 }
276 else if (X509_check_issued(cert,cert) == X509_V_OK) {
277 /* don't do OCSP checking for valid self-issued certs */
279 "Skipping OCSP check for valid self-issued cert");
281 return 1;
282 }
283
284 /* Create a temporary pool to constrain memory use (the passed-in
285 * pool may be e.g. a connection pool). */
287 apr_pool_tag(vpool, "modssl_verify_ocsp");
288
289 rv = verify_ocsp_status(cert, ctx, c, sc, s, vpool);
290
292
293 /* Propagate the verification status back to the passed-in
294 * context. */
295 switch (rv) {
298 break;
299
302 break;
303
305 /* correct error code for application errors? */
307 break;
308 }
309
310 return rv == V_OCSP_CERTSTATUS_GOOD;
311}
312#endif /* HAVE_OCSP */
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
APR-UTIL Base64 Encoding.
request_rec * r
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_INFO
Definition http_log.h:70
#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 APLOG_MARK
Definition http_log.h:283
#define APLOG_TRACE2
Definition http_log.h:73
#define APLOG_DEBUG
Definition http_log.h:71
apr_brigade_flush void * ctx
const char apr_hash_t ** values
apr_redis_t * rc
Definition apr_redis.h:173
#define SSLLOG_MARK
int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, server_rec *s, conn_rec *c, apr_pool_t *pool)
OCSP_RESPONSE * modssl_dispatch_ocsp_request(const apr_uri_t *uri, apr_interval_time_t timeout, OCSP_REQUEST *request, conn_rec *c, apr_pool_t *p)
void ssl_log_ssl_error(const char *file, int line, int level, server_rec *s)
#define X509_STORE_CTX_get0_store(x)
#define X509_STORE_CTX_get0_current_issuer(x)
#define DEFAULT_OCSP_MAX_SKEW
#define DEFAULT_OCSP_TIMEOUT
@ SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * value
Definition apr_env.h:51
int apr_status_t
Definition apr_errno.h:44
apr_array_header_t ** result
apr_vformatter_buff_t * c
Definition apr_lib.h:175
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
int to
const char * s
Definition apr_strings.h:95
int reason
int int status
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_pool_t * p
Definition md_event.c:32
#define UNSET
return NULL
Definition mod_so.c:359
STACK_OF(X509_NAME)
void ssl_log_cxerror(const char *file, int line, int level, apr_status_t rv, conn_rec *c, X509 *cert, const char *fmt,...)
static const char * extract_responder_uri(X509 *cert, apr_pool_t *pool)
static OCSP_REQUEST * create_request(X509_STORE_CTX *ctx, X509 *cert, OCSP_CERTID **certid, server_rec *s, apr_pool_t *p, SSLSrvConfigRec *sc)
static apr_uri_t * determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert, conn_rec *c, apr_pool_t *p)
static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, SSLSrvConfigRec *sc, server_rec *s, apr_pool_t *pool)
Internal interfaces private to mod_ssl.
modssl_ctx_t * server
Structure to store things which are per connection.
Definition httpd.h:1152
long ocsp_resp_maxage
const char * ocsp_responder
long ocsp_resptime_skew
unsigned int ocsp_noverify
unsigned int ocsp_use_request_nonce
int ocsp_verify_flags
unsigned int ocsp_force_default
apr_interval_time_t ocsp_responder_timeout
A structure to store information for each virtual server.
Definition httpd.h:1322