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. */
extract_responder_uri(X509 * cert,apr_pool_t * pool)24 static const char *extract_responder_uri(X509 *cert, apr_pool_t *pool)
25 {
26     STACK_OF(ACCESS_DESCRIPTION) *values;
27     char *result = NULL;
28     int j;
29 
30     values = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL);
31     if (!values) {
32         return NULL;
33     }
34 
35     for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values) && !result; j++) {
36         ACCESS_DESCRIPTION *value = sk_ACCESS_DESCRIPTION_value(values, 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) {
41             result = apr_pstrdup(pool,
42                                  (char *)value->location->d.uniformResourceIdentifier->data);
43         }
44     }
45 
46     AUTHORITY_INFO_ACCESS_free(values);
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. */
determine_responder_uri(SSLSrvConfigRec * sc,X509 * cert,conn_rec * c,apr_pool_t * p)54 static apr_uri_t *determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert,
55                                           conn_rec *c, apr_pool_t *p)
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 {
68         s = extract_responder_uri(cert, p);
69 
70         if (s == NULL && sc->server->ocsp_responder) {
71             s = sc->server->ocsp_responder;
72         }
73     }
74 
75     if (s == NULL) {
76         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01918)
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) {
84         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01919)
85                       "failed to parse OCSP responder URI '%s'", s);
86         return NULL;
87     }
88 
89     if (ap_cstr_casecmp(u->scheme, "http") != 0) {
90         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01920)
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. */
create_request(X509_STORE_CTX * ctx,X509 * cert,OCSP_CERTID ** certid,server_rec * s,apr_pool_t * p,SSLSrvConfigRec * sc)105 static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert,
106                                     OCSP_CERTID **certid,
107                                     server_rec *s, apr_pool_t *p,
108                                     SSLSrvConfigRec *sc)
109 {
110     OCSP_REQUEST *req = OCSP_REQUEST_new();
111 
112     *certid = OCSP_cert_to_id(NULL, cert, X509_STORE_CTX_get0_current_issuer(ctx));
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);
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. */
verify_ocsp_status(X509 * cert,X509_STORE_CTX * ctx,conn_rec * c,SSLSrvConfigRec * sc,server_rec * s,apr_pool_t * pool)129 static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c,
130                               SSLSrvConfigRec *sc, server_rec *s,
131                               apr_pool_t *pool)
132 {
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;
138     apr_uri_t *ruri;
139 
140     ruri = determine_responder_uri(sc, cert, c, pool);
141     if (!ruri) {
142         if (sc->server->ocsp_mask & SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK) {
143             ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
144                           "Skipping OCSP check for certificate cos no OCSP URL"
145                           " found and no_ocsp_for_cert_ok is set");
146             return V_OCSP_CERTSTATUS_GOOD;
147         } else {
148             return V_OCSP_CERTSTATUS_UNKNOWN;
149         }
150     }
151 
152     request = create_request(ctx, cert, &certID, s, pool, sc);
153     if (request) {
154         apr_interval_time_t to = sc->server->ocsp_responder_timeout == UNSET ?
155                                  apr_time_from_sec(DEFAULT_OCSP_TIMEOUT) :
156                                  sc->server->ocsp_responder_timeout;
157         response = modssl_dispatch_ocsp_request(ruri, to, request, c, pool);
158     }
159 
160     if (!request || !response) {
161         rc = V_OCSP_CERTSTATUS_UNKNOWN;
162     }
163 
164     if (rc == V_OCSP_CERTSTATUS_GOOD) {
165         int r = OCSP_response_status(response);
166 
167         if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
168             ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01922)
169                          "OCSP response not successful: %d", r);
170             rc = V_OCSP_CERTSTATUS_UNKNOWN;
171         }
172     }
173 
174     if (rc == V_OCSP_CERTSTATUS_GOOD) {
175         basicResponse = OCSP_response_get1_basic(response);
176         if (!basicResponse) {
177             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01923)
178                           "could not retrieve OCSP basic response");
179             ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
180             rc = V_OCSP_CERTSTATUS_UNKNOWN;
181         }
182     }
183 
184     if (rc == V_OCSP_CERTSTATUS_GOOD &&
185             sc->server->ocsp_use_request_nonce != FALSE &&
186             OCSP_check_nonce(request, basicResponse) != 1) {
187         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01924)
188                     "Bad OCSP responder answer (bad nonce)");
189         rc = V_OCSP_CERTSTATUS_UNKNOWN;
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 */
196             if (OCSP_basic_verify(basicResponse, sc->server->ocsp_certs, X509_STORE_CTX_get0_store(ctx),
197                                   sc->server->ocsp_verify_flags) != 1) {
198                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925)
199                             "failed to verify the OCSP response");
200                 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
201                 rc = V_OCSP_CERTSTATUS_UNKNOWN;
202             }
203         }
204     }
205 
206     if (rc == V_OCSP_CERTSTATUS_GOOD) {
207         int reason = -1, status;
208         ASN1_GENERALIZEDTIME *thisup = NULL, *nextup = NULL;
209 
210         rc = OCSP_resp_find_status(basicResponse, certID, &status,
211                                    &reason, NULL, &thisup, &nextup);
212         if (rc != 1) {
213             ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02272)
214                             "failed to retrieve OCSP response status");
215             ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
216             rc = V_OCSP_CERTSTATUS_UNKNOWN;
217         }
218         else {
219             rc = status;
220         }
221 
222         /* Check whether the response is inside the defined validity
223          * period; otherwise fail.  */
224         if (rc != V_OCSP_CERTSTATUS_UNKNOWN) {
225             long resptime_skew = sc->server->ocsp_resptime_skew == UNSET ?
226                                  DEFAULT_OCSP_MAX_SKEW : sc->server->ocsp_resptime_skew;
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. */
230             int vrc  = OCSP_check_validity(thisup, nextup, resptime_skew,
231                                            sc->server->ocsp_resp_maxage);
232             if (vrc != 1) {
233                 ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02273)
234                                 "OCSP response outside validity period");
235                 ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
236                 rc = V_OCSP_CERTSTATUS_UNKNOWN;
237             }
238         }
239 
240         {
241             int level =
242                 (status == V_OCSP_CERTSTATUS_GOOD) ? APLOG_INFO : APLOG_ERR;
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)",
250                             result, status, reason);
251         }
252     }
253 
254     if (request) OCSP_REQUEST_free(request);
255     if (response) OCSP_RESPONSE_free(response);
256     if (basicResponse) OCSP_BASICRESP_free(basicResponse);
257     /* certID is freed when the request is freed */
258 
259     return rc;
260 }
261 
modssl_verify_ocsp(X509_STORE_CTX * ctx,SSLSrvConfigRec * sc,server_rec * s,conn_rec * c,apr_pool_t * pool)262 int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc,
263                        server_rec *s, conn_rec *c, apr_pool_t *pool)
264 {
265     X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
266     apr_pool_t *vpool;
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. */
272         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
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 */
278         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
279                       "Skipping OCSP check for valid self-issued cert");
280         X509_STORE_CTX_set_error(ctx, X509_V_OK);
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). */
286     apr_pool_create(&vpool, pool);
287     apr_pool_tag(vpool, "modssl_verify_ocsp");
288 
289     rv = verify_ocsp_status(cert, ctx, c, sc, s, vpool);
290 
291     apr_pool_destroy(vpool);
292 
293     /* Propagate the verification status back to the passed-in
294      * context. */
295     switch (rv) {
296     case V_OCSP_CERTSTATUS_GOOD:
297         X509_STORE_CTX_set_error(ctx, X509_V_OK);
298         break;
299 
300     case V_OCSP_CERTSTATUS_REVOKED:
301         X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
302         break;
303 
304     case V_OCSP_CERTSTATUS_UNKNOWN:
305         /* correct error code for application errors? */
306         X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
307         break;
308     }
309 
310     return rv == V_OCSP_CERTSTATUS_GOOD;
311 }
312 #endif /* HAVE_OCSP */
313