ssl_engine_kernel.c revision 59bdac473e4f8e7b7aa2548947722c278289ed26
55cf6e01272ec475edea32aa9b7923de2d36cb42Christian Maeder/* Licensed to the Apache Software Foundation (ASF) under one or more
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * contributor license agreements. See the NOTICE file distributed with
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * this work for additional information regarding copyright ownership.
b43458b4d81f7451112cecbd757f3a05216e7088Kristina Sojakova * The ASF licenses this file to You under the Apache License, Version 2.0
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * (the "License"); you may not use this file except in compliance with
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * the License. You may obtain a copy of the License at
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * http://www.apache.org/licenses/LICENSE-2.0
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * Unless required by applicable law or agreed to in writing, software
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * distributed under the License is distributed on an "AS IS" BASIS,
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * See the License for the specific language governing permissions and
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * limitations under the License.
b2e01ef1b5d4c7a62260eb792291e8e1b10e545bIulia Ignatov * _ __ ___ ___ __| | ___ ___| | mod_ssl
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova * | | | | | | (_) | (_| | \__ \__ \ |
9f85afecbd79b3df5a0bb17bd28cd0b288dc3213Kristina Sojakova * |_| |_| |_|\___/ \__,_|___|___/___/_|
b2e01ef1b5d4c7a62260eb792291e8e1b10e545bIulia Ignatov * The SSL engine kernel
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova /* ``It took me fifteen years to discover
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova I had no talent for programming, but
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova I couldn't give it up because by that
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova time I was too famous.''
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakovastatic void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakovastatic int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova#define CONNECTION_HEADER "Connection: Upgrade"
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakova/* Perform an upgrade-to-TLS for the given request, per RFC 2817. */
14650c9e129d8dc51ed55b2edc6ec27d9f0f6d00Kristina Sojakovastatic apr_status_t upgrade_connection(request_rec *r)
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02028)
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova "upgrading connection to TLS");
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova bb = apr_brigade_create(r->pool, conn->bucket_alloc);
a669e4685b32ff5ca1bca785eacc5e30a545b010Christian Maeder rv = ap_fputstrs(conn->output_filters, bb, SWITCH_STATUS_LINE, CRLF,
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova apr_bucket_flush_create(conn->bucket_alloc));
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova rv = ap_pass_brigade(conn->output_filters, bb);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02029)
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova "failed to send 101 interim response for connection "
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova /* Perform initial SSL handshake. */
a669e4685b32ff5ca1bca785eacc5e30a545b010Christian Maeder ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02030)
80d2ec8f37d5ddec13c14b17b1bab01e9c94630aChristian Maeder "TLS upgrade handshake failed: not accepted by client!?");
d2786879b4733fd4886a5b654f7c6de1d234f638Kristina Sojakova/* Perform a speculative (and non-blocking) read from the connection
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * filters for the given request, to determine whether there is any
b3bacd257ffcdd346b70ab690f03b28ad5f33fdcKristina Sojakova * pending data to read. Return non-zero if there is, else zero. */
b3bacd257ffcdd346b70ab690f03b28ad5f33fdcKristina Sojakovastatic int has_buffered_data(request_rec *r)
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
80d2ec8f37d5ddec13c14b17b1bab01e9c94630aChristian Maeder rv = ap_get_brigade(r->connection->input_filters, bb, AP_MODE_SPECULATIVE,
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova && apr_brigade_length(bb, 1, &len) == APR_SUCCESS
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * Post Read Request Handler
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova SSLSrvConfigRec *sc = mySrvConfig(r->server);
if (upgrade_connection(r)) {
return HTTP_INTERNAL_SERVER_ERROR;
if (!sslconn) {
return DECLINED;
const char *errmsg;
char *thisurl;
thisport));
return HTTP_BAD_REQUEST;
if (!ssl) {
return DECLINED;
#ifndef OPENSSL_NO_TLSEXT
if (!r->hostname) {
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
== SSL_ENABLED_TRUE)
return HTTP_FORBIDDEN;
return DECLINED;
switch (*key) {
int ok, i;
if (ssl) {
return HTTP_UPGRADE_REQUIRED;
return HTTP_FORBIDDEN;
return DECLINED;
* reconfigured/new cipher suite. Any other changes are not important
if (cipher_list_old) {
if (cipher_list_old) {
return HTTP_FORBIDDEN;
if (cipher_list_old) {
if (renegotiate) {
* renegotiation if the reconfigured/new verify depth is less than the
* currently active/remembered verify depth (because this means more
* We force a renegotiation if the reconfigured/new verify type is
* verification but at least skip the I/O-intensive renegotiation
&& renegotiate
return HTTP_FORBIDDEN;
&& !r->expecting_100) {
int rv;
if (rsize > 0) {
if (rv) {
return rv;
if (renegotiate) {
if (renegotiate_quick) {
return HTTP_FORBIDDEN;
if (!(cert_store ||
return HTTP_FORBIDDEN;
if (!cert) {
if (depth >= 0) {
(char *)ssl);
if (has_buffered_data(r)) {
#if defined(SSL_get_secure_renegotiation_support)
(unsigned char *)&id,
sizeof(id));
return HTTP_FORBIDDEN;
return HTTP_FORBIDDEN;
return HTTP_FORBIDDEN;
if (do_verify) {
return HTTP_FORBIDDEN;
if (cipher_list) {
r->filename,
return HTTP_FORBIDDEN;
const char *errstring;
if (ok < 0) {
return HTTP_FORBIDDEN;
r->filename,
return HTTP_FORBIDDEN;
return DECLINED;
char *clientdn;
return HTTP_FORBIDDEN;
if (!ap_is_initial_req(r)) {
return DECLINED;
auth_line++;
return HTTP_FORBIDDEN;
return DECLINED;
NULL);
return DECLINED;
return HTTP_FORBIDDEN;
return DECLINED;
static const char *ssl_hook_Fixup_vars[] = {
#ifndef OPENSSL_NO_TLSEXT
const char *servername;
&& !r->main) {
if (!(((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) && sslconn && (ssl = sslconn->ssl))) {
return DECLINED;
#ifndef OPENSSL_NO_TLSEXT
for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
r, var);
if (val) {
return DECLINED;
const char *require_line,
const void *parsed)
if (ssl)
return AUTHZ_GRANTED;
return AUTHZ_DENIED;
const char *require_line,
const void **parsed)
return NULL;
const char *require_line,
const void *parsed)
if (!ssl)
return AUTHZ_DENIED;
if (xs) {
return AUTHZ_GRANTED;
return AUTHZ_DENIED;
const char *require_line,
const void **parsed)
return NULL;
int idx;
switch (keylen) {
int idx;
switch (keylen) {
#ifndef OPENSSL_NO_EC
static int init = 0;
if (init == 0) {
return ecdh;
return TRUE;
* s3_both.c:ssl_verify_alarm_type() maps to SSL_AD_CERTIFICATE_UNKNOWN,
#ifndef OPENSSL_NO_OCSP
if (!ok) {
if (!ok) {
return ok;
#define SSLPROXY_CERT_CB_LOG_FMT \
const char *msg)
return FALSE;
return TRUE;
return TRUE;
if (ca_cert_chains) {
return TRUE;
return FALSE;
const char *request,
unsigned char *id,
unsigned int idlen,
const char *status,
const char *result,
long timeout)
if (!APLOGdebug(s)) {
if (timeout) {
unsigned char *id;
unsigned int idlen;
+ timeout),
unsigned char *id,
*do_copy = 0;
return session;
server_rec *s;
unsigned char *id;
unsigned int idlen;
if (rc == 0) {
else if (rc < 0) {
conn_rec *c;
server_rec *s;
s = mySrvFromConn(c);
if (s && APLOGdebug(s)) {
#ifndef OPENSSL_NO_TLSEXT
const char *servername =
if (servername) {
(void *)servername)) {
return SSL_TLSEXT_ERR_OK;
return SSL_TLSEXT_ERR_ALERT_WARNING;
return SSL_TLSEXT_ERR_NOACK;
* (adapted from vhost.c:matches_aliases())
if (!found) {
if (names) {
if (!name[i])
if (!found) {
if (names) {
if (!name[i])
if (APLOGtrace4(s)) {
#ifdef HAVE_TLSEXT_TICKETS
#ifndef tlsext_tick_md
#ifdef OPENSSL_NO_SHA256
unsigned char *keyname,
unsigned char *iv,
int mode)
else if (mode == 0) {