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 #include <assert.h>
17 #include <apr_lib.h>
18 #include <apr_strings.h>
19 #include <apr_network_io.h>
20 
21 #include <httpd.h>
22 #include <http_core.h>
23 #include <http_log.h>
24 #include <http_protocol.h>
25 #include <http_ssl.h>
26 #include <http_vhost.h>
27 #include <http_main.h>
28 #include <ap_socache.h>
29 
30 #include <rustls.h>
31 
32 #include "tls_proto.h"
33 #include "tls_cert.h"
34 #include "tls_conf.h"
35 #include "tls_core.h"
36 #include "tls_ocsp.h"
37 #include "tls_util.h"
38 #include "tls_cache.h"
39 #include "tls_var.h"
40 
41 
42 extern module AP_MODULE_DECLARE_DATA tls_module;
43 APLOG_USE_MODULE(tls);
44 
tls_conf_conn_get(conn_rec * c)45 tls_conf_conn_t *tls_conf_conn_get(conn_rec *c)
46 {
47     return ap_get_module_config(c->conn_config, &tls_module);
48 }
49 
tls_conf_conn_set(conn_rec * c,tls_conf_conn_t * cc)50 void tls_conf_conn_set(conn_rec *c, tls_conf_conn_t *cc)
51 {
52     ap_set_module_config(c->conn_config, &tls_module, cc);
53 }
54 
tls_conn_check_ssl(conn_rec * c)55 int tls_conn_check_ssl(conn_rec *c)
56 {
57     tls_conf_conn_t *cc = tls_conf_conn_get(c->master? c->master : c);
58     if (TLS_CONN_ST_IS_ENABLED(cc)) {
59         return OK;
60     }
61     return DECLINED;
62 }
63 
we_listen_on(tls_conf_global_t * gc,server_rec * s,tls_conf_server_t * sc)64 static int we_listen_on(tls_conf_global_t *gc, server_rec *s, tls_conf_server_t *sc)
65 {
66     server_addr_rec *sa, *la;
67 
68     if (gc->tls_addresses && sc->base_server) {
69         /* The base server listens to every port and may be selected via SNI */
70         return 1;
71     }
72     for (la = gc->tls_addresses; la; la = la->next) {
73         for (sa = s->addrs; sa; sa = sa->next) {
74             if (la->host_port == sa->host_port
75                 && la->host_addr->ipaddr_len == sa->host_addr->ipaddr_len
76                 && !memcmp(la->host_addr->ipaddr_ptr,
77                     la->host_addr->ipaddr_ptr, (size_t)la->host_addr->ipaddr_len)) {
78                 /* exact match */
79                 return 1;
80             }
81         }
82     }
83     return 0;
84 }
85 
tls_core_free(void * data)86 static apr_status_t tls_core_free(void *data)
87 {
88     server_rec *base_server = (server_rec *)data;
89     tls_conf_server_t *sc = tls_conf_server_get(base_server);
90 
91     if (sc && sc->global && sc->global->rustls_hello_config) {
92         rustls_server_config_free(sc->global->rustls_hello_config);
93         sc->global->rustls_hello_config = NULL;
94     }
95     tls_cache_free(base_server);
96     return APR_SUCCESS;
97 }
98 
load_certified_keys(apr_array_header_t * keys,server_rec * s,apr_array_header_t * cert_specs,tls_cert_reg_t * cert_reg)99 static apr_status_t load_certified_keys(
100     apr_array_header_t *keys, server_rec *s,
101     apr_array_header_t *cert_specs,
102     tls_cert_reg_t *cert_reg)
103 {
104     apr_status_t rv = APR_SUCCESS;
105     const rustls_certified_key *ckey;
106     tls_cert_spec_t *spec;
107     int i;
108 
109     if (cert_specs && cert_specs->nelts > 0) {
110         for (i = 0; i < cert_specs->nelts; ++i) {
111             spec = APR_ARRAY_IDX(cert_specs, i, tls_cert_spec_t*);
112             rv = tls_cert_reg_get_certified_key(cert_reg, s, spec, &ckey);
113             if (APR_SUCCESS != rv) {
114                 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10318)
115                      "Failed to load certificate %d[cert=%s(%d), key=%s(%d)] for %s",
116                      i, spec->cert_file, (int)(spec->cert_pem? strlen(spec->cert_pem) : 0),
117                      spec->pkey_file, (int)(spec->pkey_pem? strlen(spec->pkey_pem) : 0),
118                      s->server_hostname);
119                 goto cleanup;
120             }
121             assert(ckey);
122             APR_ARRAY_PUSH(keys, const rustls_certified_key*) = ckey;
123         }
124     }
125 cleanup:
126     return rv;
127 }
128 
use_local_key(conn_rec * c,const char * cert_pem,const char * pkey_pem)129 static apr_status_t use_local_key(
130     conn_rec *c, const char *cert_pem, const char *pkey_pem)
131 {
132     tls_conf_conn_t *cc = tls_conf_conn_get(c);
133     const rustls_certified_key *ckey = NULL;
134     tls_cert_spec_t spec;
135     apr_status_t rv = APR_SUCCESS;
136 
137     memset(&spec, 0, sizeof(spec));
138     spec.cert_pem = cert_pem;
139     spec.pkey_pem = pkey_pem;
140     rv = tls_cert_load_cert_key(c->pool, &spec, NULL, &ckey);
141     if (APR_SUCCESS != rv) goto cleanup;
142 
143     cc->local_keys = apr_array_make(c->pool, 2, sizeof(const rustls_certified_key*));
144     APR_ARRAY_PUSH(cc->local_keys, const rustls_certified_key*) = ckey;
145     ckey = NULL;
146 
147 cleanup:
148     if (ckey != NULL) rustls_certified_key_free(ckey);
149     return rv;
150 }
151 
add_file_specs(apr_array_header_t * certificates,apr_pool_t * p,apr_array_header_t * cert_files,apr_array_header_t * key_files)152 static void add_file_specs(
153     apr_array_header_t *certificates,
154     apr_pool_t *p,
155     apr_array_header_t *cert_files,
156     apr_array_header_t *key_files)
157 {
158     tls_cert_spec_t *spec;
159     int i;
160 
161     for (i = 0; i < cert_files->nelts; ++i) {
162         spec = apr_pcalloc(p, sizeof(*spec));
163         spec->cert_file = APR_ARRAY_IDX(cert_files, i, const char*);
164         spec->pkey_file = (i < key_files->nelts)? APR_ARRAY_IDX(key_files, i, const char*) : NULL;
165         *(const tls_cert_spec_t**)apr_array_push(certificates) = spec;
166     }
167 }
168 
calc_ciphers(apr_pool_t * pool,server_rec * s,tls_conf_global_t * gc,const char * proxy,apr_array_header_t * pref_ciphers,apr_array_header_t * supp_ciphers,const apr_array_header_t ** pciphers)169 static apr_status_t calc_ciphers(
170     apr_pool_t *pool,
171     server_rec *s,
172     tls_conf_global_t *gc,
173     const char *proxy,
174     apr_array_header_t *pref_ciphers,
175     apr_array_header_t *supp_ciphers,
176     const apr_array_header_t **pciphers)
177 {
178     apr_array_header_t *ordered_ciphers;
179     const apr_array_header_t *ciphers;
180     apr_array_header_t *unsupported = NULL;
181     rustls_result rr = RUSTLS_RESULT_OK;
182     apr_status_t rv = APR_SUCCESS;
183     apr_uint16_t id;
184     int i;
185 
186 
187     /* remove all suppressed ciphers from the ones supported by rustls */
188     ciphers = tls_util_array_uint16_remove(pool, gc->proto->supported_cipher_ids, supp_ciphers);
189     ordered_ciphers = NULL;
190     /* if preferred ciphers are actually still present in allowed_ciphers, put
191      * them into `ciphers` in this order */
192     for (i = 0; i < pref_ciphers->nelts; ++i) {
193         id = APR_ARRAY_IDX(pref_ciphers, i, apr_uint16_t);
194         ap_log_error(APLOG_MARK, APLOG_TRACE4, rv, s,
195                      "checking preferred cipher %s: %d",
196                      s->server_hostname, id);
197         if (tls_util_array_uint16_contains(ciphers, id)) {
198             ap_log_error(APLOG_MARK, APLOG_TRACE4, rv, s,
199                          "checking preferred cipher %s: %d is known",
200                          s->server_hostname, id);
201             if (ordered_ciphers == NULL) {
202                 ordered_ciphers = apr_array_make(pool, ciphers->nelts, sizeof(apr_uint16_t));
203             }
204             APR_ARRAY_PUSH(ordered_ciphers, apr_uint16_t) = id;
205         }
206         else if (!tls_proto_is_cipher_supported(gc->proto, id)) {
207             ap_log_error(APLOG_MARK, APLOG_TRACE4, rv, s,
208                          "checking preferred cipher %s: %d is unsupported",
209                          s->server_hostname, id);
210             if (!unsupported) unsupported = apr_array_make(pool, 5, sizeof(apr_uint16_t));
211             APR_ARRAY_PUSH(unsupported, apr_uint16_t) = id;
212         }
213     }
214     /* if we found ciphers with preference among allowed_ciphers,
215      * append all other allowed ciphers. */
216     if (ordered_ciphers) {
217         for (i = 0; i < ciphers->nelts; ++i) {
218             id = APR_ARRAY_IDX(ciphers, i, apr_uint16_t);
219             if (!tls_util_array_uint16_contains(ordered_ciphers, id)) {
220                 APR_ARRAY_PUSH(ordered_ciphers, apr_uint16_t) = id;
221             }
222         }
223         ciphers = ordered_ciphers;
224     }
225 
226     if (ciphers == gc->proto->supported_cipher_ids) {
227         ciphers = NULL;
228     }
229 
230     if (unsupported && unsupported->nelts) {
231         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, APLOGNO(10319)
232                      "Server '%s' has TLS%sCiphersPrefer configured that are not "
233                      "supported by rustls. These will not have an effect: %s",
234                      s->server_hostname, proxy,
235                      tls_proto_get_cipher_names(gc->proto, unsupported, pool));
236     }
237 
238     if (RUSTLS_RESULT_OK != rr) {
239         const char *err_descr;
240         rv = tls_util_rustls_error(pool, rr, &err_descr);
241         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10320)
242                      "Failed to configure ciphers %s: [%d] %s",
243                      s->server_hostname, (int)rr, err_descr);
244     }
245     *pciphers = (APR_SUCCESS == rv)? ciphers : NULL;
246     return rv;
247 }
248 
get_server_ciphersuites(const apr_array_header_t ** pciphersuites,apr_pool_t * pool,tls_conf_server_t * sc)249 static apr_status_t get_server_ciphersuites(
250     const apr_array_header_t **pciphersuites,
251     apr_pool_t *pool, tls_conf_server_t *sc)
252 {
253     const apr_array_header_t *ciphers, *suites = NULL;
254     apr_status_t rv = APR_SUCCESS;
255 
256     rv = calc_ciphers(pool, sc->server, sc->global,
257         "", sc->tls_pref_ciphers, sc->tls_supp_ciphers,
258         &ciphers);
259     if (APR_SUCCESS != rv) goto cleanup;
260 
261     if (ciphers) {
262         suites = tls_proto_get_rustls_suites(
263             sc->global->proto, ciphers, pool);
264         if (APLOGtrace2(sc->server)) {
265             tls_proto_conf_t *conf = sc->global->proto;
266             ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, sc->server,
267                          "tls ciphers configured[%s]: %s",
268                          sc->server->server_hostname,
269                          tls_proto_get_cipher_names(conf, ciphers, pool));
270         }
271     }
272 
273 cleanup:
274     *pciphersuites = (APR_SUCCESS == rv)? suites : NULL;
275     return rv;
276 }
277 
complete_cert_specs(apr_pool_t * p,tls_conf_server_t * sc)278 static apr_array_header_t *complete_cert_specs(
279     apr_pool_t *p, tls_conf_server_t *sc)
280 {
281     apr_array_header_t *cert_adds, *key_adds, *specs;
282 
283     /* Take the configured certificate specifications and ask
284      * around for other modules to add specifications to this server.
285      * This is the way mod_md provides certificates.
286      *
287      * If the server then still has no cert specifications, ask
288      * around for `fallback` certificates which are commonly self-signed,
289      * temporary ones which let the server startup in order to
290      * obtain the `real` certificates from sources like ACME.
291      * Servers will fallbacks will answer all requests with 503.
292      */
293     specs = apr_array_copy(p, sc->cert_specs);
294     cert_adds = apr_array_make(p, 2, sizeof(const char*));
295     key_adds = apr_array_make(p, 2, sizeof(const char*));
296 
297     ap_ssl_add_cert_files(sc->server, p, cert_adds, key_adds);
298     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, sc->server,
299                  "init server: complete_cert_specs added %d certs", cert_adds->nelts);
300     add_file_specs(specs, p, cert_adds, key_adds);
301 
302     if (apr_is_empty_array(specs)) {
303         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, sc->server,
304                      "init server: no certs configured, looking for fallback");
305         ap_ssl_add_fallback_cert_files(sc->server, p, cert_adds, key_adds);
306         if (cert_adds->nelts > 0) {
307             add_file_specs(specs, p, cert_adds, key_adds);
308             sc->service_unavailable = 1;
309             ap_log_error(APLOG_MARK, APLOG_INFO, 0, sc->server, APLOGNO(10321)
310                          "Init: %s will respond with '503 Service Unavailable' for now. There "
311                          "are no SSL certificates configured and no other module contributed any.",
312                          sc->server->server_hostname);
313         }
314         else if (!sc->base_server) {
315             ap_log_error(APLOG_MARK, APLOG_ERR, 0, sc->server, APLOGNO(10322)
316                          "Init: %s has no certificates configured. Use 'TLSCertificate' to "
317                          "configure a certificate and key file.",
318                          sc->server->server_hostname);
319         }
320     }
321     return specs;
322 }
323 
select_certified_key(void * userdata,const rustls_client_hello * hello)324 static const rustls_certified_key *select_certified_key(
325     void* userdata, const rustls_client_hello *hello)
326 {
327     conn_rec *c = userdata;
328     tls_conf_conn_t *cc;
329     tls_conf_server_t *sc;
330     apr_array_header_t *keys;
331     const rustls_certified_key *clone;
332     rustls_result rr = RUSTLS_RESULT_OK;
333     apr_status_t rv;
334 
335     ap_assert(c);
336     cc = tls_conf_conn_get(c);
337     ap_assert(cc);
338     ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "client hello select certified key");
339     if (!cc || !cc->server) goto cleanup;
340     sc = tls_conf_server_get(cc->server);
341     if (!sc) goto cleanup;
342 
343     cc->key = NULL;
344     cc->key_cloned = 0;
345     if (cc->local_keys && cc->local_keys->nelts > 0) {
346         keys = cc->local_keys;
347     }
348     else {
349         keys = sc->certified_keys;
350     }
351     if (!keys || keys->nelts <= 0) goto cleanup;
352 
353     rr = rustls_client_hello_select_certified_key(hello,
354         (const rustls_certified_key**)keys->elts, (size_t)keys->nelts, &cc->key);
355     if (RUSTLS_RESULT_OK != rr) goto cleanup;
356 
357     if (APR_SUCCESS == tls_ocsp_update_key(c, cc->key, &clone)) {
358         /* got OCSP response data for it, meaning the key was cloned and we need to remember */
359         cc->key_cloned = 1;
360         cc->key = clone;
361     }
362     if (APLOGctrace2(c)) {
363         const char *key_id = tls_cert_reg_get_id(sc->global->cert_reg, cc->key);
364         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, APLOGNO(10323)
365                       "client hello selected key: %s", key_id? key_id : "unknown");
366     }
367     return cc->key;
368 
369 cleanup:
370     if (RUSTLS_RESULT_OK != rr) {
371         const char *err_descr;
372         rv = tls_util_rustls_error(c->pool, rr, &err_descr);
373         ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(10324)
374                       "Failed to select certified key: [%d] %s", (int)rr, err_descr);
375     }
376     return NULL;
377 }
378 
server_conf_setup(apr_pool_t * p,apr_pool_t * ptemp,tls_conf_server_t * sc,tls_conf_global_t * gc)379 static apr_status_t server_conf_setup(
380     apr_pool_t *p, apr_pool_t *ptemp, tls_conf_server_t *sc, tls_conf_global_t *gc)
381 {
382     apr_array_header_t *cert_specs;
383     apr_status_t rv = APR_SUCCESS;
384 
385     /* TODO: most code has been stripped here with the changes in rustls-ffi v0.8.0
386      * and this means that any errors are only happening at connection setup, which
387      * is too late.
388      */
389     (void)p;
390     ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, sc->server,
391                  "init server: %s", sc->server->server_hostname);
392 
393     if (sc->client_auth != TLS_CLIENT_AUTH_NONE && !sc->client_ca) {
394         ap_log_error(APLOG_MARK, APLOG_ERR, 0, sc->server, APLOGNO(10325)
395                      "TLSClientAuthentication is enabled for %s, but no client CA file is set. "
396                       "Use 'TLSClientCA <file>' to specify the trust anchors.",
397                      sc->server->server_hostname);
398         rv = APR_EINVAL; goto cleanup;
399     }
400 
401     cert_specs = complete_cert_specs(ptemp, sc);
402     sc->certified_keys = apr_array_make(p, 3, sizeof(rustls_certified_key *));
403     rv = load_certified_keys(sc->certified_keys, sc->server, cert_specs, gc->cert_reg);
404     if (APR_SUCCESS != rv) goto cleanup;
405 
406     rv = get_server_ciphersuites(&sc->ciphersuites, p, sc);
407     if (APR_SUCCESS != rv) goto cleanup;
408 
409     ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, sc->server,
410                  "init server: %s with %d certificates loaded",
411                  sc->server->server_hostname, sc->certified_keys->nelts);
412 cleanup:
413     return rv;
414 }
415 
get_proxy_ciphers(const apr_array_header_t ** pciphersuites,apr_pool_t * pool,tls_conf_proxy_t * pc)416 static apr_status_t get_proxy_ciphers(const apr_array_header_t **pciphersuites,
417     apr_pool_t *pool, tls_conf_proxy_t *pc)
418 {
419     const apr_array_header_t *ciphers, *suites = NULL;
420     apr_status_t rv = APR_SUCCESS;
421 
422     rv = calc_ciphers(pool, pc->defined_in, pc->global,
423         "", pc->proxy_pref_ciphers, pc->proxy_supp_ciphers, &ciphers);
424     if (APR_SUCCESS != rv) goto cleanup;
425 
426     if (ciphers) {
427         suites = tls_proto_get_rustls_suites(pc->global->proto, ciphers, pool);
428         /* this changed the default rustls ciphers, configure it. */
429         if (APLOGtrace2(pc->defined_in)) {
430             tls_proto_conf_t *conf = pc->global->proto;
431             ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, pc->defined_in,
432                          "tls proxy ciphers configured[%s]: %s",
433                          pc->defined_in->server_hostname,
434                          tls_proto_get_cipher_names(conf, ciphers, pool));
435         }
436     }
437 
438 cleanup:
439     *pciphersuites = (APR_SUCCESS == rv)? suites : NULL;
440     return rv;
441 }
442 
proxy_conf_setup(apr_pool_t * p,apr_pool_t * ptemp,tls_conf_proxy_t * pc,tls_conf_global_t * gc)443 static apr_status_t proxy_conf_setup(
444     apr_pool_t *p, apr_pool_t *ptemp, tls_conf_proxy_t *pc, tls_conf_global_t *gc)
445 {
446     apr_status_t rv = APR_SUCCESS;
447 
448     (void)p; (void)ptemp;
449     ap_assert(pc->defined_in);
450     pc->global = gc;
451 
452     if (pc->proxy_ca && strcasecmp(pc->proxy_ca, "default")) {
453         ap_log_error(APLOG_MARK, APLOG_TRACE2, rv, pc->defined_in,
454                      "proxy: will use roots in %s from %s",
455                      pc->defined_in->server_hostname, pc->proxy_ca);
456     }
457     else {
458         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, pc->defined_in,
459                      "proxy: there is no TLSProxyCA configured in %s which means "
460                      "the certificates of remote servers contacted from here will not be trusted.",
461                      pc->defined_in->server_hostname);
462     }
463 
464     if (pc->proxy_protocol_min > 0) {
465         apr_array_header_t *tls_versions;
466 
467         ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, pc->defined_in,
468                      "init server: set proxy protocol min version %04x", pc->proxy_protocol_min);
469         tls_versions = tls_proto_create_versions_plus(
470             gc->proto, (apr_uint16_t)pc->proxy_protocol_min, ptemp);
471         if (tls_versions->nelts > 0) {
472             if (pc->proxy_protocol_min != APR_ARRAY_IDX(tls_versions, 0, apr_uint16_t)) {
473                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, pc->defined_in, APLOGNO(10326)
474                              "Init: the minimum proxy protocol version configured for %s (%04x) "
475                              "is not supported and version %04x was selected instead.",
476                              pc->defined_in->server_hostname, pc->proxy_protocol_min,
477                              APR_ARRAY_IDX(tls_versions, 0, apr_uint16_t));
478             }
479         }
480         else {
481             ap_log_error(APLOG_MARK, APLOG_ERR, 0, pc->defined_in, APLOGNO(10327)
482                          "Unable to configure the proxy protocol version for %s: "
483                           "neither the configured minimum version (%04x), nor any higher one is "
484                          "available.", pc->defined_in->server_hostname, pc->proxy_protocol_min);
485             rv = APR_ENOTIMPL; goto cleanup;
486         }
487     }
488 
489 #if TLS_MACHINE_CERTS
490     rv = load_certified_keys(pc->machine_certified_keys, pc->defined_in,
491                              pc->machine_cert_specs, gc->cert_reg);
492     if (APR_SUCCESS != rv) goto cleanup;
493 #endif
494 
495 cleanup:
496     return rv;
497 }
498 
extract_client_hello_values(void * userdata,const rustls_client_hello * hello)499 static const rustls_certified_key *extract_client_hello_values(
500     void* userdata, const rustls_client_hello *hello)
501 {
502     conn_rec *c = userdata;
503     tls_conf_conn_t *cc = tls_conf_conn_get(c);
504     size_t i, len;
505     unsigned short n;
506 
507     ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "extract client hello values");
508     if (!cc) goto cleanup;
509     cc->client_hello_seen = 1;
510     if (hello->sni_name.len > 0) {
511         cc->sni_hostname = apr_pstrndup(c->pool, hello->sni_name.data, hello->sni_name.len);
512         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "sni detected: %s", cc->sni_hostname);
513     }
514     else {
515         cc->sni_hostname = NULL;
516         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "no sni from client");
517     }
518     if (APLOGctrace4(c) && hello->signature_schemes.len > 0) {
519         for (i = 0; i < hello->signature_schemes.len; ++i) {
520             n = hello->signature_schemes.data[i];
521             ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, c,
522                 "client supports signature scheme: %x", (int)n);
523         }
524     }
525     if ((len = rustls_slice_slice_bytes_len(hello->alpn)) > 0) {
526         apr_array_header_t *alpn = apr_array_make(c->pool, 5, sizeof(const char*));
527         const char *protocol;
528         ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "ALPN: client proposes %d protocols", (int)len);
529         for (i = 0; i < len; ++i) {
530             rustls_slice_bytes rs = rustls_slice_slice_bytes_get(hello->alpn, i);
531             protocol = apr_pstrndup(c->pool, (const char*)rs.data, rs.len);
532             APR_ARRAY_PUSH(alpn, const char*) = protocol;
533             ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
534                 "ALPN: client proposes %d: `%s`", (int)i, protocol);
535         }
536         cc->alpn = alpn;
537     }
538     else {
539         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "ALPN: no alpn proposed by client");
540     }
541 cleanup:
542     return NULL;
543 }
544 
setup_hello_config(apr_pool_t * p,server_rec * base_server,tls_conf_global_t * gc)545 static apr_status_t setup_hello_config(apr_pool_t *p, server_rec *base_server, tls_conf_global_t *gc)
546 {
547     rustls_server_config_builder *builder;
548     rustls_result rr = RUSTLS_RESULT_OK;
549     apr_status_t rv = APR_SUCCESS;
550 
551     builder = rustls_server_config_builder_new();
552     if (!builder) {
553         rr = RUSTLS_RESULT_PANIC; goto cleanup;
554     }
555     rustls_server_config_builder_set_hello_callback(builder, extract_client_hello_values);
556     gc->rustls_hello_config = rustls_server_config_builder_build(builder);
557     if (!gc->rustls_hello_config) {
558         rr = RUSTLS_RESULT_PANIC; goto cleanup;
559     }
560 
561 cleanup:
562     if (RUSTLS_RESULT_OK != rr) {
563         const char *err_descr = NULL;
564         rv = tls_util_rustls_error(p, rr, &err_descr);
565         ap_log_error(APLOG_MARK, APLOG_ERR, rv, base_server, APLOGNO(10328)
566                      "Failed to init generic hello config: [%d] %s", (int)rr, err_descr);
567         goto cleanup;
568     }
569     return rv;
570 }
571 
init_incoming(apr_pool_t * p,apr_pool_t * ptemp,server_rec * base_server)572 static apr_status_t init_incoming(apr_pool_t *p, apr_pool_t *ptemp, server_rec *base_server)
573 {
574     tls_conf_server_t *sc = tls_conf_server_get(base_server);
575     tls_conf_global_t *gc = sc->global;
576     server_rec *s;
577     apr_status_t rv = APR_ENOMEM;
578 
579     ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, base_server, "tls_core_init incoming");
580     apr_pool_cleanup_register(p, base_server, tls_core_free,
581                               apr_pool_cleanup_null);
582 
583     rv = tls_proto_post_config(p, ptemp, base_server);
584     if (APR_SUCCESS != rv) goto cleanup;
585 
586     for (s = base_server; s; s = s->next) {
587         sc = tls_conf_server_get(s);
588         assert(sc);
589         ap_assert(sc->global == gc);
590 
591         /* If 'TLSEngine' has been configured, use those addresses to
592          * decide if we are enabled on this server. */
593         sc->base_server = (s == base_server);
594         sc->enabled = we_listen_on(gc, s, sc)? TLS_FLAG_TRUE : TLS_FLAG_FALSE;
595     }
596 
597     rv = tls_cache_post_config(p, ptemp, base_server);
598     if (APR_SUCCESS != rv) goto cleanup;
599 
600     rv = setup_hello_config(p, base_server, gc);
601     if (APR_SUCCESS != rv) goto cleanup;
602 
603     /* Setup server configs and collect all certificates we use. */
604     gc->cert_reg = tls_cert_reg_make(p);
605     gc->stores = tls_cert_root_stores_make(p);
606     gc->verifiers = tls_cert_verifiers_make(p, gc->stores);
607     for (s = base_server; s; s = s->next) {
608         sc = tls_conf_server_get(s);
609         rv = tls_conf_server_apply_defaults(sc, p);
610         if (APR_SUCCESS != rv) goto cleanup;
611         if (sc->enabled != TLS_FLAG_TRUE) continue;
612         rv = server_conf_setup(p, ptemp, sc, gc);
613         if (APR_SUCCESS != rv) {
614             ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "server setup failed: %s",
615                 s->server_hostname);
616             goto cleanup;
617         }
618     }
619 
620 cleanup:
621     if (APR_SUCCESS != rv) {
622         ap_log_error(APLOG_MARK, APLOG_ERR, rv, base_server, "error during post_config");
623     }
624     return rv;
625 }
626 
init_outgoing(apr_pool_t * p,apr_pool_t * ptemp,server_rec * base_server)627 static apr_status_t init_outgoing(apr_pool_t *p, apr_pool_t *ptemp, server_rec *base_server)
628 {
629     tls_conf_server_t *sc = tls_conf_server_get(base_server);
630     tls_conf_global_t *gc = sc->global;
631     tls_conf_dir_t *dc;
632     tls_conf_proxy_t *pc;
633     server_rec *s;
634     apr_status_t rv = APR_SUCCESS;
635     int i;
636 
637     (void)p; (void)ptemp;
638     (void)gc;
639     ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, base_server, "tls_core_init outgoing");
640     ap_assert(gc->mod_proxy_post_config_done);
641     /* Collect all proxy'ing default server dir configs.
642      * All <Proxy> section dir_configs should already be there - if there were any. */
643     for (s = base_server; s; s = s->next) {
644         dc = tls_conf_dir_server_get(s);
645         rv = tls_conf_dir_apply_defaults(dc, p);
646         if (APR_SUCCESS != rv) goto cleanup;
647         if (dc->proxy_enabled != TLS_FLAG_TRUE) continue;
648         dc->proxy_config = tls_conf_proxy_make(p, dc, gc, s);
649         ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s, "%s: adding proxy_conf to globals",
650             s->server_hostname);
651         APR_ARRAY_PUSH(gc->proxy_configs, tls_conf_proxy_t*) = dc->proxy_config;
652     }
653     /* Now gc->proxy_configs contains all configurations we need to possibly
654      * act on for outgoing connections. */
655     for (i = 0; i < gc->proxy_configs->nelts; ++i) {
656         pc = APR_ARRAY_IDX(gc->proxy_configs, i, tls_conf_proxy_t*);
657         rv = proxy_conf_setup(p, ptemp, pc, gc);
658         if (APR_SUCCESS != rv) goto cleanup;
659     }
660 
661 cleanup:
662     return rv;
663 }
664 
tls_core_init(apr_pool_t * p,apr_pool_t * ptemp,server_rec * base_server)665 apr_status_t tls_core_init(apr_pool_t *p, apr_pool_t *ptemp, server_rec *base_server)
666 {
667     tls_conf_server_t *sc = tls_conf_server_get(base_server);
668     tls_conf_global_t *gc = sc->global;
669     apr_status_t rv = APR_SUCCESS;
670 
671     ap_assert(gc);
672     if (TLS_CONF_ST_INIT == gc->status) {
673         rv = init_incoming(p, ptemp, base_server);
674         if (APR_SUCCESS != rv) goto cleanup;
675         gc->status = TLS_CONF_ST_INCOMING_DONE;
676     }
677     if (TLS_CONF_ST_INCOMING_DONE == gc->status) {
678         if (!gc->mod_proxy_post_config_done) goto cleanup;
679 
680         rv = init_outgoing(p, ptemp, base_server);
681         if (APR_SUCCESS != rv) goto cleanup;
682         gc->status = TLS_CONF_ST_OUTGOING_DONE;
683     }
684     if (TLS_CONF_ST_OUTGOING_DONE == gc->status) {
685         /* register all loaded certificates for OCSP stapling */
686         rv = tls_ocsp_prime_certs(gc, p, base_server);
687         if (APR_SUCCESS != rv) goto cleanup;
688 
689         if (gc->verifiers) tls_cert_verifiers_clear(gc->verifiers);
690         if (gc->stores) tls_cert_root_stores_clear(gc->stores);
691         gc->status = TLS_CONF_ST_DONE;
692     }
693 cleanup:
694     return rv;
695 }
696 
tls_core_conn_free(void * data)697 static apr_status_t tls_core_conn_free(void *data)
698 {
699     tls_conf_conn_t *cc = data;
700 
701     /* free all rustls things we are owning. */
702     if (cc->rustls_connection) {
703         rustls_connection_free(cc->rustls_connection);
704         cc->rustls_connection = NULL;
705     }
706     if (cc->rustls_server_config) {
707         rustls_server_config_free(cc->rustls_server_config);
708         cc->rustls_server_config = NULL;
709     }
710     if (cc->rustls_client_config) {
711         rustls_client_config_free(cc->rustls_client_config);
712         cc->rustls_client_config = NULL;
713     }
714     if (cc->key_cloned && cc->key) {
715         rustls_certified_key_free(cc->key);
716         cc->key = NULL;
717     }
718     if (cc->local_keys) {
719         const rustls_certified_key *key;
720         int i;
721 
722         for (i = 0; i < cc->local_keys->nelts; ++i) {
723             key = APR_ARRAY_IDX(cc->local_keys, i, const rustls_certified_key*);
724             rustls_certified_key_free(key);
725         }
726         apr_array_clear(cc->local_keys);
727     }
728     return APR_SUCCESS;
729 }
730 
cc_get_or_make(conn_rec * c)731 static tls_conf_conn_t *cc_get_or_make(conn_rec *c)
732 {
733     tls_conf_conn_t *cc = tls_conf_conn_get(c);
734     if (!cc) {
735         cc = apr_pcalloc(c->pool, sizeof(*cc));
736         cc->server = c->base_server;
737         cc->state = TLS_CONN_ST_INIT;
738         tls_conf_conn_set(c, cc);
739         apr_pool_cleanup_register(c->pool, cc, tls_core_conn_free,
740                                   apr_pool_cleanup_null);
741     }
742     return cc;
743 }
744 
tls_core_conn_disable(conn_rec * c)745 void tls_core_conn_disable(conn_rec *c)
746 {
747     tls_conf_conn_t *cc;
748     cc = cc_get_or_make(c);
749     if (cc->state == TLS_CONN_ST_INIT) {
750         cc->state = TLS_CONN_ST_DISABLED;
751     }
752 }
753 
tls_core_conn_bind(conn_rec * c,ap_conf_vector_t * dir_conf)754 void tls_core_conn_bind(conn_rec *c, ap_conf_vector_t *dir_conf)
755 {
756     tls_conf_conn_t *cc = cc_get_or_make(c);
757     cc->dc = dir_conf? ap_get_module_config(dir_conf, &tls_module) : NULL;
758 }
759 
760 
init_outgoing_connection(conn_rec * c)761 static apr_status_t init_outgoing_connection(conn_rec *c)
762 {
763     tls_conf_conn_t *cc = tls_conf_conn_get(c);
764     tls_conf_proxy_t *pc;
765     const apr_array_header_t *ciphersuites = NULL;
766     apr_array_header_t *tls_versions = NULL;
767     rustls_client_config_builder *builder = NULL;
768     rustls_root_cert_store *ca_store = NULL;
769     const char *hostname = NULL, *alpn_note = NULL;
770     rustls_result rr = RUSTLS_RESULT_OK;
771     apr_status_t rv = APR_SUCCESS;
772 
773     ap_assert(cc->outgoing);
774     ap_assert(cc->dc);
775     pc = cc->dc->proxy_config;
776     ap_assert(pc);
777 
778     hostname = apr_table_get(c->notes, "proxy-request-hostname");
779     alpn_note = apr_table_get(c->notes, "proxy-request-alpn-protos");
780     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, c->base_server,
781         "setup_outgoing: to %s [ALPN: %s] from configuration in %s"
782         " using CA %s", hostname, alpn_note, pc->defined_in->server_hostname, pc->proxy_ca);
783 
784     rv = get_proxy_ciphers(&ciphersuites, c->pool, pc);
785     if (APR_SUCCESS != rv) goto cleanup;
786 
787     if (pc->proxy_protocol_min > 0) {
788         tls_versions = tls_proto_create_versions_plus(
789             pc->global->proto, (apr_uint16_t)pc->proxy_protocol_min, c->pool);
790     }
791 
792     if (ciphersuites && ciphersuites->nelts > 0
793         && tls_versions && tls_versions->nelts >= 0) {
794         rr = rustls_client_config_builder_new_custom(
795             (const struct rustls_supported_ciphersuite *const *)ciphersuites->elts,
796             (size_t)ciphersuites->nelts,
797             (const uint16_t *)tls_versions->elts, (size_t)tls_versions->nelts,
798             &builder);
799         if (RUSTLS_RESULT_OK != rr) goto cleanup;
800     }
801     else {
802         builder = rustls_client_config_builder_new();
803         if (NULL == builder) {
804             rv = APR_ENOMEM;
805             goto cleanup;
806         }
807     }
808 
809     if (pc->proxy_ca && strcasecmp(pc->proxy_ca, "default")) {
810         rv = tls_cert_root_stores_get(pc->global->stores, pc->proxy_ca, &ca_store);
811         if (APR_SUCCESS != rv) goto cleanup;
812         rustls_client_config_builder_use_roots(builder, ca_store);
813     }
814 
815 #if TLS_MACHINE_CERTS
816     if (pc->machine_certified_keys->nelts > 0) {
817         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, c->base_server,
818             "setup_outgoing: adding %d client certificate", (int)pc->machine_certified_keys->nelts);
819         rr = rustls_client_config_builder_set_certified_key(
820                 builder, (const rustls_certified_key**)pc->machine_certified_keys->elts,
821                 (size_t)pc->machine_certified_keys->nelts);
822         if (RUSTLS_RESULT_OK != rr) goto cleanup;
823     }
824 #endif
825 
826     if (hostname) {
827         rustls_client_config_builder_set_enable_sni(builder, true);
828     }
829     else {
830         hostname = "unknown.proxy.local";
831         rustls_client_config_builder_set_enable_sni(builder, false);
832     }
833 
834     if (alpn_note) {
835         apr_array_header_t *alpn_proposed = NULL;
836         char *p, *last;
837         apr_size_t len;
838 
839         alpn_proposed = apr_array_make(c->pool, 3, sizeof(const char*));
840         p = apr_pstrdup(c->pool, alpn_note);
841         while ((p = apr_strtok(p, ", ", &last))) {
842             len = (apr_size_t)(last - p - (*last? 1 : 0));
843             if (len > 255) {
844                 ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10329)
845                               "ALPN proxy protocol identifier too long: %s", p);
846                 rv = APR_EGENERAL;
847                 goto cleanup;
848             }
849             APR_ARRAY_PUSH(alpn_proposed, const char*) = apr_pstrndup(c->pool, p, len);
850             p = NULL;
851         }
852         if (alpn_proposed->nelts > 0) {
853             apr_array_header_t *rustls_protocols;
854             const char* proto;
855             rustls_slice_bytes bytes;
856             int i;
857 
858             rustls_protocols = apr_array_make(c->pool, alpn_proposed->nelts, sizeof(rustls_slice_bytes));
859             for (i = 0; i < alpn_proposed->nelts; ++i) {
860                 proto = APR_ARRAY_IDX(alpn_proposed, i, const char*);
861                 bytes.data = (const unsigned char*)proto;
862                 bytes.len = strlen(proto);
863                 APR_ARRAY_PUSH(rustls_protocols, rustls_slice_bytes) = bytes;
864             }
865 
866             rr = rustls_client_config_builder_set_alpn_protocols(builder,
867                 (rustls_slice_bytes*)rustls_protocols->elts, (size_t)rustls_protocols->nelts);
868             if (RUSTLS_RESULT_OK != rr) goto cleanup;
869 
870             ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, c->base_server,
871                 "setup_outgoing: to %s, added %d ALPN protocols from %s",
872                 hostname, rustls_protocols->nelts, alpn_note);
873         }
874     }
875 
876     cc->rustls_client_config = rustls_client_config_builder_build(builder);
877     builder = NULL;
878 
879     rr = rustls_client_connection_new(cc->rustls_client_config, hostname, &cc->rustls_connection);
880     if (RUSTLS_RESULT_OK != rr) goto cleanup;
881     rustls_connection_set_userdata(cc->rustls_connection, c);
882 
883 cleanup:
884     if (builder != NULL) rustls_client_config_builder_free(builder);
885     if (RUSTLS_RESULT_OK != rr) {
886         const char *err_descr = NULL;
887         rv = tls_util_rustls_error(c->pool, rr, &err_descr);
888         ap_log_error(APLOG_MARK, APLOG_ERR, rv, cc->server, APLOGNO(10330)
889                      "Failed to init pre_session for outgoing %s to %s: [%d] %s",
890                      cc->server->server_hostname, hostname, (int)rr, err_descr);
891         c->aborted = 1;
892         cc->state = TLS_CONN_ST_DISABLED;
893         goto cleanup;
894     }
895     return rv;
896 }
897 
tls_core_pre_conn_init(conn_rec * c)898 int tls_core_pre_conn_init(conn_rec *c)
899 {
900     tls_conf_server_t *sc = tls_conf_server_get(c->base_server);
901     tls_conf_conn_t *cc;
902 
903     cc = cc_get_or_make(c);
904     if (cc->state == TLS_CONN_ST_INIT) {
905         /* Need to decide if we TLS this connection or not */
906         int enabled =
907 #if AP_MODULE_MAGIC_AT_LEAST(20120211, 109)
908                 !c->outgoing &&
909 #endif
910                 sc->enabled == TLS_FLAG_TRUE;
911         cc->state = enabled? TLS_CONN_ST_CLIENT_HELLO : TLS_CONN_ST_DISABLED;
912         cc->client_auth = sc->client_auth;
913         ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, c->base_server,
914             "tls_core_conn_init: %s for tls: %s",
915             enabled? "enabled" : "disabled", c->base_server->server_hostname);
916     }
917     else if (cc->state == TLS_CONN_ST_DISABLED) {
918         ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, c->base_server,
919             "tls_core_conn_init, not our connection: %s",
920             c->base_server->server_hostname);
921         goto cleanup;
922     }
923 
924 cleanup:
925     return TLS_CONN_ST_IS_ENABLED(cc)? OK : DECLINED;
926 }
927 
tls_core_conn_init(conn_rec * c)928 apr_status_t tls_core_conn_init(conn_rec *c)
929 {
930     tls_conf_server_t *sc = tls_conf_server_get(c->base_server);
931     tls_conf_conn_t *cc;
932     rustls_result rr = RUSTLS_RESULT_OK;
933     apr_status_t rv = APR_SUCCESS;
934 
935     cc = tls_conf_conn_get(c);
936     if (cc && TLS_CONN_ST_IS_ENABLED(cc) && !cc->rustls_connection) {
937         if (cc->outgoing) {
938             rv = init_outgoing_connection(c);
939             if (APR_SUCCESS != rv) goto cleanup;
940         }
941         else {
942             /* Use a generic rustls_connection with its defaults, which we feed
943              * the first TLS bytes from the client. Its Hello message will trigger
944              * our callback where we can inspect the (possibly) supplied SNI and
945              * select another server.
946              */
947             rr = rustls_server_connection_new(sc->global->rustls_hello_config, &cc->rustls_connection);
948             if (RUSTLS_RESULT_OK != rr) goto cleanup;
949             /* we might refuse requests on this connection, e.g. ACME challenge */
950             cc->service_unavailable = sc->service_unavailable;
951         }
952         rustls_connection_set_userdata(cc->rustls_connection, c);
953     }
954 
955 cleanup:
956     if (RUSTLS_RESULT_OK != rr) {
957         const char *err_descr = NULL;
958         rv = tls_util_rustls_error(c->pool, rr, &err_descr);
959         ap_log_error(APLOG_MARK, APLOG_ERR, rv, sc->server, APLOGNO(10331)
960                      "Failed to init TLS connection for server %s: [%d] %s",
961                      sc->server->server_hostname, (int)rr, err_descr);
962         c->aborted = 1;
963         cc->state = TLS_CONN_ST_DISABLED;
964         goto cleanup;
965     }
966     return rv;
967 }
968 
find_vhost(void * sni_hostname,conn_rec * c,server_rec * s)969 static int find_vhost(void *sni_hostname, conn_rec *c, server_rec *s)
970 {
971     if (tls_util_name_matches_server(sni_hostname, s)) {
972         tls_conf_conn_t *cc = tls_conf_conn_get(c);
973         cc->server = s;
974         return 1;
975     }
976     return 0;
977 }
978 
select_application_protocol(conn_rec * c,server_rec * s,rustls_server_config_builder * builder)979 static apr_status_t select_application_protocol(
980     conn_rec *c, server_rec *s, rustls_server_config_builder *builder)
981 {
982     tls_conf_conn_t *cc = tls_conf_conn_get(c);
983     const char *proposed;
984     rustls_result rr = RUSTLS_RESULT_OK;
985     apr_status_t rv = APR_SUCCESS;
986 
987     /* The server always has a protocol it uses, normally "http/1.1".
988      * if the client, via ALPN, proposes protocols, they are in
989      * order of preference.
990      * We propose those to modules registered in the server and
991      * get the protocol back that someone is willing to run on this
992      * connection.
993      * If this is different from what the connection already does,
994      * we tell the server (and all protocol modules) to switch.
995      * If successful, we announce that protocol back to the client as
996      * our only ALPN protocol and then do the 'real' handshake.
997      */
998     cc->application_protocol = ap_get_protocol(c);
999     if (cc->alpn && cc->alpn->nelts > 0) {
1000         rustls_slice_bytes rsb;
1001 
1002         proposed = ap_select_protocol(c, NULL, s, cc->alpn);
1003         if (!proposed) {
1004             ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, c,
1005                 "ALPN: no protocol selected in server");
1006             goto cleanup;
1007         }
1008 
1009         if (strcmp(proposed, cc->application_protocol)) {
1010             ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, c,
1011                 "ALPN: switching protocol from `%s` to `%s`", cc->application_protocol, proposed);
1012             rv = ap_switch_protocol(c, NULL, cc->server, proposed);
1013             if (APR_SUCCESS != rv) goto cleanup;
1014         }
1015 
1016         rsb.data = (const unsigned char*)proposed;
1017         rsb.len = strlen(proposed);
1018         rr = rustls_server_config_builder_set_alpn_protocols(builder, &rsb, 1);
1019         if (RUSTLS_RESULT_OK != rr) goto cleanup;
1020 
1021         cc->application_protocol = proposed;
1022         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, c,
1023             "ALPN: using connection protocol `%s`", cc->application_protocol);
1024 
1025         /* protocol was switched, this could be a challenge protocol
1026          * such as "acme-tls/1". Give handlers the opportunity to
1027          * override the certificate for this connection. */
1028         if (strcmp("h2", proposed) && strcmp("http/1.1", proposed)) {
1029             const char *cert_pem = NULL, *key_pem = NULL;
1030             if (ap_ssl_answer_challenge(c, cc->sni_hostname, &cert_pem, &key_pem)) {
1031                 /* With ACME we can have challenge connections to a unknown domains
1032                  * that need to be answered with a special certificate and will
1033                  * otherwise not answer any requests. See RFC 8555 */
1034                 rv = use_local_key(c, cert_pem, key_pem);
1035                 if (APR_SUCCESS != rv) goto cleanup;
1036 
1037                 cc->service_unavailable = 1;
1038                 cc->client_auth = TLS_CLIENT_AUTH_NONE;
1039             }
1040         }
1041     }
1042 
1043 cleanup:
1044     if (rr != RUSTLS_RESULT_OK) {
1045         const char *err_descr = NULL;
1046         rv = tls_util_rustls_error(c->pool, rr, &err_descr);
1047         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10332)
1048                      "Failed to init session for server %s: [%d] %s",
1049                      s->server_hostname, (int)rr, err_descr);
1050         c->aborted = 1;
1051         goto cleanup;
1052     }
1053     return rv;
1054 }
1055 
build_server_connection(rustls_connection ** pconnection,const rustls_server_config ** pconfig,conn_rec * c)1056 static apr_status_t build_server_connection(rustls_connection **pconnection,
1057                                             const rustls_server_config **pconfig,
1058                                             conn_rec *c)
1059 {
1060     tls_conf_conn_t *cc = tls_conf_conn_get(c);
1061     tls_conf_server_t *sc;
1062     const apr_array_header_t *tls_versions = NULL;
1063     rustls_server_config_builder *builder = NULL;
1064     const rustls_server_config *config = NULL;
1065     rustls_connection *rconnection = NULL;
1066     rustls_result rr = RUSTLS_RESULT_OK;
1067     apr_status_t rv = APR_SUCCESS;
1068 
1069     sc = tls_conf_server_get(cc->server);
1070 
1071     if (sc->tls_protocol_min > 0) {
1072         ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, sc->server,
1073                      "init server: set protocol min version %04x", sc->tls_protocol_min);
1074         tls_versions = tls_proto_create_versions_plus(
1075             sc->global->proto, (apr_uint16_t)sc->tls_protocol_min, c->pool);
1076         if (tls_versions->nelts > 0) {
1077             if (sc->tls_protocol_min != APR_ARRAY_IDX(tls_versions, 0, apr_uint16_t)) {
1078                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, sc->server, APLOGNO(10333)
1079                              "Init: the minimum protocol version configured for %s (%04x) "
1080                              "is not supported and version %04x was selected instead.",
1081                              sc->server->server_hostname, sc->tls_protocol_min,
1082                              APR_ARRAY_IDX(tls_versions, 0, apr_uint16_t));
1083             }
1084         }
1085         else {
1086             ap_log_error(APLOG_MARK, APLOG_ERR, 0, sc->server, APLOGNO(10334)
1087                          "Unable to configure the protocol version for %s: "
1088                           "neither the configured minimum version (%04x), nor any higher one is "
1089                          "available.", sc->server->server_hostname, sc->tls_protocol_min);
1090             rv = APR_ENOTIMPL; goto cleanup;
1091         }
1092     }
1093     else if (sc->ciphersuites && sc->ciphersuites->nelts > 0) {
1094         /* FIXME: rustls-ffi current has not way to make a builder with ALL_PROTOCOL_VERSIONS */
1095         tls_versions = tls_proto_create_versions_plus(sc->global->proto, 0, c->pool);
1096     }
1097 
1098     if (sc->ciphersuites && sc->ciphersuites->nelts > 0
1099         && tls_versions && tls_versions->nelts >= 0) {
1100         rr = rustls_server_config_builder_new_custom(
1101             (const struct rustls_supported_ciphersuite *const *)sc->ciphersuites->elts,
1102             (size_t)sc->ciphersuites->nelts,
1103             (const uint16_t *)tls_versions->elts, (size_t)tls_versions->nelts,
1104             &builder);
1105         if (RUSTLS_RESULT_OK != rr) goto cleanup;
1106     }
1107     else {
1108         builder = rustls_server_config_builder_new();
1109         if (NULL == builder) {
1110             rv = APR_ENOMEM;
1111             goto cleanup;
1112         }
1113     }
1114 
1115     /* decide on the application protocol, this may change other
1116      * settings like client_auth. */
1117     rv = select_application_protocol(c, cc->server, builder);
1118 
1119     if (cc->client_auth != TLS_CLIENT_AUTH_NONE) {
1120         ap_assert(sc->client_ca);  /* checked in server_setup */
1121         if (cc->client_auth == TLS_CLIENT_AUTH_REQUIRED) {
1122             const rustls_client_cert_verifier *verifier;
1123             rv = tls_cert_client_verifiers_get(sc->global->verifiers, sc->client_ca, &verifier);
1124             if (APR_SUCCESS != rv) goto cleanup;
1125             rustls_server_config_builder_set_client_verifier(builder, verifier);
1126         }
1127         else {
1128             const rustls_client_cert_verifier_optional *verifier;
1129             rv = tls_cert_client_verifiers_get_optional(sc->global->verifiers, sc->client_ca, &verifier);
1130             if (APR_SUCCESS != rv) goto cleanup;
1131             rustls_server_config_builder_set_client_verifier_optional(builder, verifier);
1132         }
1133     }
1134 
1135     rustls_server_config_builder_set_hello_callback(builder, select_certified_key);
1136 
1137     rr = rustls_server_config_builder_set_ignore_client_order(
1138         builder, sc->honor_client_order == TLS_FLAG_FALSE);
1139     if (RUSTLS_RESULT_OK != rr) goto cleanup;
1140 
1141     rv = tls_cache_init_server(builder, sc->server);
1142     if (APR_SUCCESS != rv) goto cleanup;
1143 
1144     config = rustls_server_config_builder_build(builder);
1145     builder = NULL;
1146     if (!config) {
1147         rv = APR_ENOMEM; goto cleanup;
1148     }
1149 
1150     rr = rustls_server_connection_new(config, &rconnection);
1151     if (RUSTLS_RESULT_OK != rr) goto cleanup;
1152     rustls_connection_set_userdata(rconnection, c);
1153 
1154 cleanup:
1155     if (rr != RUSTLS_RESULT_OK) {
1156         const char *err_descr = NULL;
1157         rv = tls_util_rustls_error(c->pool, rr, &err_descr);
1158         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, sc->server, APLOGNO(10335)
1159                      "Failed to init session for server %s: [%d] %s",
1160                      sc->server->server_hostname, (int)rr, err_descr);
1161     }
1162     if (APR_SUCCESS == rv) {
1163         *pconfig = config;
1164         *pconnection = rconnection;
1165         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, sc->server,
1166                      "tls_core_conn_server_init done: %s",
1167                      sc->server->server_hostname);
1168     }
1169     else {
1170         ap_log_error(APLOG_MARK, APLOG_ERR, rv, sc->server, APLOGNO(10336)
1171                      "Failed to init session for server %s",
1172                      sc->server->server_hostname);
1173         c->aborted = 1;
1174         if (config) rustls_server_config_free(config);
1175         if (builder) rustls_server_config_builder_free(builder);
1176     }
1177     return rv;
1178 }
1179 
tls_core_conn_seen_client_hello(conn_rec * c)1180 apr_status_t tls_core_conn_seen_client_hello(conn_rec *c)
1181 {
1182     tls_conf_conn_t *cc = tls_conf_conn_get(c);
1183     tls_conf_server_t *sc;
1184     apr_status_t rv = APR_SUCCESS;
1185     int sni_match = 0;
1186 
1187     /* The initial rustls generic session has been fed the client hello and
1188      * we have extracted SNI and ALPN values (so present).
1189      * Time to select the actual server_rec and application protocol that
1190      * will be used on this connection. */
1191     ap_assert(cc);
1192     sc = tls_conf_server_get(cc->server);
1193     if (!cc->client_hello_seen) goto cleanup;
1194 
1195     if (cc->sni_hostname) {
1196         if (ap_vhost_iterate_given_conn(c, find_vhost, (void*)cc->sni_hostname)) {
1197             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(10337)
1198                 "vhost_init: virtual host found for SNI '%s'", cc->sni_hostname);
1199             sni_match = 1;
1200         }
1201         else if (tls_util_name_matches_server(cc->sni_hostname, ap_server_conf)) {
1202             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(10338)
1203                 "vhost_init: virtual host NOT found, but base server[%s] matches SNI '%s'",
1204                 ap_server_conf->server_hostname, cc->sni_hostname);
1205             cc->server = ap_server_conf;
1206             sni_match = 1;
1207         }
1208         else if (sc->strict_sni == TLS_FLAG_FALSE) {
1209             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(10339)
1210                 "vhost_init: no virtual host found, relaxed SNI checking enabled, SNI '%s'",
1211                 cc->sni_hostname);
1212         }
1213         else {
1214             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(10340)
1215                 "vhost_init: no virtual host, nor base server[%s] matches SNI '%s'",
1216                 c->base_server->server_hostname, cc->sni_hostname);
1217             cc->server = sc->global->ap_server;
1218             rv = APR_NOTFOUND; goto cleanup;
1219         }
1220     }
1221     else {
1222         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10341)
1223             "vhost_init: no SNI hostname provided by client");
1224     }
1225 
1226     /* reinit, we might have a new server selected */
1227     sc = tls_conf_server_get(cc->server);
1228     /* on relaxed SNI matches, we do not enforce the 503 of fallback
1229      * certificates. */
1230     if (!cc->service_unavailable) {
1231         cc->service_unavailable = sni_match? sc->service_unavailable : 0;
1232     }
1233 
1234     /* if found or not, cc->server will be the server we use now to do
1235      * the real handshake and, if successful, the traffic after that.
1236      * Free the current session and create the real one for the
1237      * selected server. */
1238     if (cc->rustls_server_config) {
1239         rustls_server_config_free(cc->rustls_server_config);
1240         cc->rustls_server_config = NULL;
1241     }
1242     rustls_connection_free(cc->rustls_connection);
1243     cc->rustls_connection = NULL;
1244 
1245     rv = build_server_connection(&cc->rustls_connection, &cc->rustls_server_config, c);
1246 
1247 cleanup:
1248     return rv;
1249 }
1250 
tls_core_conn_post_handshake(conn_rec * c)1251 apr_status_t tls_core_conn_post_handshake(conn_rec *c)
1252 {
1253     tls_conf_conn_t *cc = tls_conf_conn_get(c);
1254     tls_conf_server_t *sc = tls_conf_server_get(cc->server);
1255     const rustls_supported_ciphersuite *rsuite;
1256     const rustls_certificate *cert;
1257     apr_status_t rv = APR_SUCCESS;
1258 
1259     if (rustls_connection_is_handshaking(cc->rustls_connection)) {
1260         rv = APR_EGENERAL;
1261         ap_log_error(APLOG_MARK, APLOG_ERR, rv, cc->server, APLOGNO(10342)
1262                      "post handshake, but rustls claims to still be handshaking: %s",
1263                      cc->server->server_hostname);
1264         goto cleanup;
1265     }
1266 
1267     cc->tls_protocol_id = rustls_connection_get_protocol_version(cc->rustls_connection);
1268     cc->tls_protocol_name = tls_proto_get_version_name(sc->global->proto,
1269         cc->tls_protocol_id, c->pool);
1270     rsuite = rustls_connection_get_negotiated_ciphersuite(cc->rustls_connection);
1271     if (!rsuite) {
1272         rv = APR_EGENERAL;
1273         ap_log_error(APLOG_MARK, APLOG_ERR, rv, cc->server, APLOGNO(10343)
1274                      "post handshake, but rustls does not report negotiated cipher suite: %s",
1275                      cc->server->server_hostname);
1276         goto cleanup;
1277     }
1278     cc->tls_cipher_id = rustls_supported_ciphersuite_get_suite(rsuite);
1279     cc->tls_cipher_name = tls_proto_get_cipher_name(sc->global->proto,
1280         cc->tls_cipher_id, c->pool);
1281     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "post_handshake %s: %s [%s]",
1282         cc->server->server_hostname, cc->tls_protocol_name, cc->tls_cipher_name);
1283 
1284     cert = rustls_connection_get_peer_certificate(cc->rustls_connection, 0);
1285     if (cert) {
1286         size_t i = 0;
1287 
1288         cc->peer_certs = apr_array_make(c->pool, 5, sizeof(const rustls_certificate*));
1289         while (cert) {
1290             APR_ARRAY_PUSH(cc->peer_certs, const rustls_certificate*) = cert;
1291             cert = rustls_connection_get_peer_certificate(cc->rustls_connection, ++i);
1292         }
1293     }
1294     if (!cc->peer_certs && sc->client_auth == TLS_CLIENT_AUTH_REQUIRED) {
1295         ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(10344)
1296               "A client certificate is required, but no acceptable certificate was presented.");
1297         rv = APR_ECONNABORTED;
1298     }
1299 
1300     rv = tls_var_handshake_done(c);
1301 cleanup:
1302     return rv;
1303 }
1304 
1305 /**
1306  * Return != 0, if a connection also serve requests for server <other>.
1307  */
tls_conn_compatible_for(tls_conf_conn_t * cc,server_rec * other)1308 static int tls_conn_compatible_for(tls_conf_conn_t *cc, server_rec *other)
1309 {
1310     tls_conf_server_t *oc, *sc;
1311     const rustls_certified_key *sk, *ok;
1312     int i;
1313 
1314     /*   - differences in certificates are the responsibility of the client.
1315      *     if it thinks the SNI server works for r->server, we are fine with that.
1316      *   - if there are differences in requirements to client certificates, we
1317      *     need to deny the request.
1318      */
1319     if (!cc->server || !other) return 0;
1320     if (cc->server == other) return 1;
1321     oc = tls_conf_server_get(other);
1322     if (!oc) return 0;
1323     sc = tls_conf_server_get(cc->server);
1324     if (!sc) return 0;
1325 
1326     /* same certified keys used? */
1327     if (sc->certified_keys->nelts != oc->certified_keys->nelts) return 0;
1328     for (i = 0; i < sc->certified_keys->nelts; ++i) {
1329         sk = APR_ARRAY_IDX(sc->certified_keys, i, const rustls_certified_key*);
1330         ok = APR_ARRAY_IDX(oc->certified_keys, i, const rustls_certified_key*);
1331         if (sk != ok) return 0;
1332     }
1333 
1334     /* If the connection TLS version is below other other min one, no */
1335     if (oc->tls_protocol_min > 0 && cc->tls_protocol_id < oc->tls_protocol_min) return 0;
1336     /* If the connection TLS cipher is listed as suppressed by other, no */
1337     if (oc->tls_supp_ciphers && tls_util_array_uint16_contains(
1338         oc->tls_supp_ciphers, cc->tls_cipher_id)) return 0;
1339     return 1;
1340 }
1341 
tls_core_request_check(request_rec * r)1342 int tls_core_request_check(request_rec *r)
1343 {
1344     conn_rec *c = r->connection;
1345     tls_conf_conn_t *cc = tls_conf_conn_get(c->master? c->master : c);
1346     int rv = DECLINED; /* do not object to the request */
1347 
1348     /* If we are not enabled on this connection, leave. We are not renegotiating.
1349      * Otherwise:
1350      * - service is unavailable when we have only a fallback certificate or
1351      *   when a challenge protocol is active (ACME tls-alpn-01 for example).
1352      * - with vhosts configured and no SNI from the client, deny access.
1353      * - are servers compatible for connection sharing?
1354      */
1355     if (!TLS_CONN_ST_IS_ENABLED(cc)) goto cleanup;
1356 
1357     ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
1358                  "tls_core_request_check[%s, %d]: %s", r->hostname,
1359                  cc? cc->service_unavailable : 2, r->the_request);
1360     if (cc->service_unavailable) {
1361         rv = HTTP_SERVICE_UNAVAILABLE; goto cleanup;
1362     }
1363     if (!cc->sni_hostname && r->connection->vhost_lookup_data) {
1364         rv = HTTP_FORBIDDEN; goto cleanup;
1365     }
1366     if (!tls_conn_compatible_for(cc, r->server)) {
1367         rv = HTTP_MISDIRECTED_REQUEST;
1368         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10345)
1369                      "Connection host %s, selected via SNI, and request host %s"
1370                      " have incompatible TLS configurations.",
1371                      cc->server->server_hostname, r->hostname);
1372         goto cleanup;
1373     }
1374 cleanup:
1375     return rv;
1376 }
1377 
tls_core_error(conn_rec * c,rustls_result rr,const char ** perrstr)1378 apr_status_t tls_core_error(conn_rec *c, rustls_result rr, const char **perrstr)
1379 {
1380     tls_conf_conn_t *cc = tls_conf_conn_get(c);
1381     apr_status_t rv;
1382 
1383     rv = tls_util_rustls_error(c->pool, rr, perrstr);
1384     if (cc) {
1385         cc->last_error = rr;
1386         cc->last_error_descr = *perrstr;
1387     }
1388     return rv;
1389 }
1390 
tls_core_setup_outgoing(conn_rec * c)1391 int tls_core_setup_outgoing(conn_rec *c)
1392 {
1393     tls_conf_conn_t *cc;
1394     int rv = DECLINED;
1395 
1396     ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
1397                  "tls_core_setup_outgoing called");
1398 #if AP_MODULE_MAGIC_AT_LEAST(20120211, 109)
1399     if (!c->outgoing) goto cleanup;
1400 #endif
1401     cc = cc_get_or_make(c);
1402     if (cc->state == TLS_CONN_ST_DISABLED) {
1403         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
1404                      "tls_core_setup_outgoing: already disabled");
1405         goto cleanup;
1406     }
1407     if (TLS_CONN_ST_IS_ENABLED(cc)) {
1408         /* we already handle it, allow repeated calls */
1409         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
1410                      "tls_core_setup_outgoing: already enabled");
1411         rv = OK; goto cleanup;
1412     }
1413     cc->outgoing = 1;
1414     if (!cc->dc) {
1415         /* In case there is not dir_conf bound for this connection, we fallback
1416          * to the defaults in the base server (we have no virtual host config to use) */
1417         cc->dc = ap_get_module_config(c->base_server->lookup_defaults, &tls_module);
1418     }
1419     if (cc->dc->proxy_enabled != TLS_FLAG_TRUE) {
1420         cc->state = TLS_CONN_ST_DISABLED;
1421         ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
1422                      "tls_core_setup_outgoing: TLSProxyEngine not configured");
1423         goto cleanup;
1424     }
1425     /* we handle this connection */
1426     cc->state = TLS_CONN_ST_CLIENT_HELLO;
1427     rv = OK;
1428 
1429 cleanup:
1430     ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
1431                  "tls_core_setup_outgoing returns %s", rv == OK? "OK" : "DECLINED");
1432     return rv;
1433 }
1434