/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
#include"ssl_private.h"
#ifndef OPENSSL_NO_OCSP #include"apr_base64.h"
/* Return the responder URI specified in the given certificate, or
* NULL if none specified. */ staticconstchar *extract_responder_uri(X509 *cert, apr_pool_t *pool)
{
STACK_OF(ACCESS_DESCRIPTION) *values; char *result = NULL; int j;
/* Name found in extension, and is a URI: */ if (OBJ_obj2nid(value->method) == NID_ad_OCSP
&& value->location->type == GEN_URI) {
result = apr_pstrdup(pool,
(char *)value->location->d.uniformResourceIdentifier->data);
}
}
AUTHORITY_INFO_ACCESS_free(values);
return result;
}
/* Return the responder URI object which should be used in the given * configuration for the given certificate, or NULL if none can be
* determined. */ static apr_uri_t *determine_responder_uri(SSLSrvConfigRec *sc, X509 *cert,
conn_rec *c, apr_pool_t *p)
{
apr_uri_t *u = apr_palloc(p, sizeof *u); constchar *s;
apr_status_t rv;
/* Use default responder URL if forced by configuration, else use * certificate-specified responder, falling back to default if
* necessary and possible. */ if (sc->server->ocsp_force_default == TRUE) {
s = sc->server->ocsp_responder;
} else {
s = extract_responder_uri(cert, p);
if (s == NULL && sc->server->ocsp_responder) {
s = sc->server->ocsp_responder;
}
}
if (s == NULL) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01918) "no OCSP responder specified in certificate and " "no default configured"); return NULL;
}
rv = apr_uri_parse(p, s, u); if (rv || !u->hostname) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(01919) "failed to parse OCSP responder URI '%s'", s); return NULL;
}
if (!u->port) {
u->port = apr_uri_port_of_scheme(u->scheme);
}
return u;
}
/* Create an OCSP request for the given certificate; returning the * certificate ID in *certid and *issuer on success. Returns the
* request object on success, or NULL on error. */ static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert,
OCSP_CERTID **certid,
server_rec *s, apr_pool_t *p,
SSLSrvConfigRec *sc)
{
OCSP_REQUEST *req = OCSP_REQUEST_new();
/* Check whether the response is inside the defined validity
* period; otherwise fail. */ if (rc != V_OCSP_CERTSTATUS_UNKNOWN) { long resptime_skew = sc->server->ocsp_resptime_skew == UNSET ?
DEFAULT_OCSP_MAX_SKEW : sc->server->ocsp_resptime_skew; /* oscp_resp_maxage can be passed verbatim - UNSET (-1) means * that responses can be of any age as long as nextup is in the
* future. */ int vrc = OCSP_check_validity(thisup, nextup, resptime_skew,
sc->server->ocsp_resp_maxage); if (vrc != 1) {
ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02273) "OCSP response outside validity period");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
rc = V_OCSP_CERTSTATUS_UNKNOWN;
}
}
if (request) OCSP_REQUEST_free(request); if (response) OCSP_RESPONSE_free(response); if (basicResponse) OCSP_BASICRESP_free(basicResponse); /* certID is freed when the request is freed */
return rc;
}
int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc,
server_rec *s, conn_rec *c, apr_pool_t *pool)
{
X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
apr_pool_t *vpool; int rv;
if (!cert) { /* starting with OpenSSL 1.0, X509_STORE_CTX_get_current_cert()
* may yield NULL. Return early, but leave the ctx error as is. */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "No cert available to check with OCSP"); return 1;
} elseif (X509_check_issued(cert,cert) == X509_V_OK) { /* don't do OCSP checking for valid self-issued certs */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "Skipping OCSP check for valid self-issued cert");
X509_STORE_CTX_set_error(ctx, X509_V_OK); return 1;
}
/* Create a temporary pool to constrain memory use (the passed-in
* pool may be e.g. a connection pool). */
apr_pool_create(&vpool, pool);
apr_pool_tag(vpool, "modssl_verify_ocsp");
/* Propagate the verification status back to the passed-in
* context. */ switch (rv) { case V_OCSP_CERTSTATUS_GOOD:
X509_STORE_CTX_set_error(ctx, X509_V_OK); break;
case V_OCSP_CERTSTATUS_REVOKED:
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); break;
case V_OCSP_CERTSTATUS_UNKNOWN: /* correct error code for application errors? */
X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.