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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "ssl_private.h"
19 #ifndef OPENSSL_NO_OCSP
20 #include "apr_base64.h"
22 /* Return the responder URI specified in the given certificate, or
23 * NULL if none specified. */
24 static const char *extract_responder_uri(X509 *cert, apr_pool_t *pool)
26 STACK_OF(ACCESS_DESCRIPTION) *values;
30 values = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL);
35 for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values) && !result; j++) {
36 ACCESS_DESCRIPTION *value = sk_ACCESS_DESCRIPTION_value(values, j);
38 /* Name found in extension, and is a URI: */
39 if (OBJ_obj2nid(value->method) == NID_ad_OCSP
40 && value->location->type == GEN_URI) {
41 result = apr_pstrdup(pool,
42 (char *)value->location->d.uniformResourceIdentifier->data);
46 AUTHORITY_INFO_ACCESS_free(values);
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
54 static apr_uri_t *determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert,
55 conn_rec *c, apr_pool_t *p)
57 apr_uri_t *u = apr_palloc(p, sizeof *u);
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;
68 s = extract_responder_uri(cert, p);
70 if (s == NULL && sc->server->ocsp_responder) {
71 s = sc->server->ocsp_responder;
76 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01918)
77 "no OCSP responder specified in certificate and "
78 "no default configured");
82 rv = apr_uri_parse(p, s, u);
83 if (rv || !u->hostname) {
84 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01919)
85 "failed to parse OCSP responder URI '%s'", s);
89 if (strcasecmp(u->scheme, "http") != 0) {
90 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01920)
91 "cannot handle OCSP responder URI '%s'", s);
96 u->port = apr_uri_port_of_scheme(u->scheme);
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. */
105 static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert,
106 OCSP_CERTID **certid,
107 server_rec *s, apr_pool_t *p,
110 OCSP_REQUEST *req = OCSP_REQUEST_new();
112 *certid = OCSP_cert_to_id(NULL, cert, ctx->current_issuer);
113 if (!*certid || !OCSP_request_add0_id(req, *certid)) {
114 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01921)
115 "could not retrieve certificate id");
116 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
120 if (sc->server->ocsp_use_request_nonce != FALSE) {
121 OCSP_request_add1_nonce(req, 0, -1);
127 /* Verify the OCSP status of given certificate. Returns
128 * V_OCSP_CERTSTATUS_* result code. */
129 static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c,
130 SSLSrvConfigRec *sc, server_rec *s,
133 int rc = V_OCSP_CERTSTATUS_GOOD;
134 OCSP_RESPONSE *response = NULL;
135 OCSP_BASICRESP *basicResponse = NULL;
136 OCSP_REQUEST *request = NULL;
137 OCSP_CERTID *certID = NULL;
140 ruri = determine_responder_uri(sc, cert, c, pool);
142 return V_OCSP_CERTSTATUS_UNKNOWN;
145 request = create_request(ctx, cert, &certID, s, pool, sc);
147 apr_interval_time_t to = sc->server->ocsp_responder_timeout == UNSET ?
148 apr_time_from_sec(DEFAULT_OCSP_TIMEOUT) :
149 sc->server->ocsp_responder_timeout;
150 response = modssl_dispatch_ocsp_request(ruri, to, request, c, pool);
153 if (!request || !response) {
154 rc = V_OCSP_CERTSTATUS_UNKNOWN;
157 if (rc == V_OCSP_CERTSTATUS_GOOD) {
158 int r = OCSP_response_status(response);
160 if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
161 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01922)
162 "OCSP response not successful: %d", rc);
163 rc = V_OCSP_CERTSTATUS_UNKNOWN;
167 if (rc == V_OCSP_CERTSTATUS_GOOD) {
168 basicResponse = OCSP_response_get1_basic(response);
169 if (!basicResponse) {
170 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01923)
171 "could not retrieve OCSP basic response");
172 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
173 rc = V_OCSP_CERTSTATUS_UNKNOWN;
177 if (rc == V_OCSP_CERTSTATUS_GOOD &&
178 sc->server->ocsp_use_request_nonce != FALSE &&
179 OCSP_check_nonce(request, basicResponse) != 1) {
180 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01924)
181 "Bad OCSP responder answer (bad nonce)");
182 rc = V_OCSP_CERTSTATUS_UNKNOWN;
185 if (rc == V_OCSP_CERTSTATUS_GOOD) {
186 /* TODO: allow flags configuration. */
187 if (OCSP_basic_verify(basicResponse, NULL, ctx->ctx, 0) != 1) {
188 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925)
189 "failed to verify the OCSP response");
190 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
191 rc = V_OCSP_CERTSTATUS_UNKNOWN;
195 if (rc == V_OCSP_CERTSTATUS_GOOD) {
196 int reason = -1, status;
197 ASN1_GENERALIZEDTIME *thisup = NULL, *nextup = NULL;
199 rc = OCSP_resp_find_status(basicResponse, certID, &status,
200 &reason, NULL, &thisup, &nextup);
202 ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02272)
203 "failed to retrieve OCSP response status");
204 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
205 rc = V_OCSP_CERTSTATUS_UNKNOWN;
211 /* Check whether the response is inside the defined validity
212 * period; otherwise fail. */
213 if (rc != V_OCSP_CERTSTATUS_UNKNOWN) {
214 long resptime_skew = sc->server->ocsp_resptime_skew == UNSET ?
215 DEFAULT_OCSP_MAX_SKEW : sc->server->ocsp_resptime_skew;
216 /* oscp_resp_maxage can be passed verbatim - UNSET (-1) means
217 * that responses can be of any age as long as nextup is in the
219 int vrc = OCSP_check_validity(thisup, nextup, resptime_skew,
220 sc->server->ocsp_resp_maxage);
222 ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02273)
223 "OCSP response outside validity period");
224 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
225 rc = V_OCSP_CERTSTATUS_UNKNOWN;
231 (status == V_OCSP_CERTSTATUS_GOOD) ? APLOG_INFO : APLOG_ERR;
233 status == V_OCSP_CERTSTATUS_GOOD ? "good" :
234 (status == V_OCSP_CERTSTATUS_REVOKED ? "revoked" : "unknown");
236 ssl_log_cxerror(SSLLOG_MARK, level, 0, c, cert,
237 "OCSP validation completed, "
238 "certificate status: %s (%d, %d)",
239 result, status, reason);
243 if (request) OCSP_REQUEST_free(request);
244 if (response) OCSP_RESPONSE_free(response);
245 if (basicResponse) OCSP_BASICRESP_free(basicResponse);
246 /* certID is freed when the request is freed */
251 int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc,
252 server_rec *s, conn_rec *c, apr_pool_t *pool)
254 X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
259 /* starting with OpenSSL 1.0, X509_STORE_CTX_get_current_cert()
260 * may yield NULL. Return early, but leave the ctx error as is. */
261 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
262 "No cert available to check with OCSP");
265 else if (cert->valid && X509_check_issued(cert,cert) == X509_V_OK) {
266 /* don't do OCSP checking for valid self-issued certs */
267 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
268 "Skipping OCSP check for valid self-issued cert");
269 X509_STORE_CTX_set_error(ctx, X509_V_OK);
273 /* Create a temporary pool to constrain memory use (the passed-in
274 * pool may be e.g. a connection pool). */
275 apr_pool_create(&vpool, pool);
277 rv = verify_ocsp_status(cert, ctx, c, sc, s, vpool);
279 apr_pool_destroy(vpool);
281 /* Propagate the verification status back to the passed-in
284 case V_OCSP_CERTSTATUS_GOOD:
285 X509_STORE_CTX_set_error(ctx, X509_V_OK);
288 case V_OCSP_CERTSTATUS_REVOKED:
289 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
292 case V_OCSP_CERTSTATUS_UNKNOWN:
293 /* correct error code for application errors? */
294 X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
298 return rv == V_OCSP_CERTSTATUS_GOOD;
300 #endif /* HAVE_OCSP */