]> granicus.if.org Git - apache/blob - modules/ssl/ssl_engine_config.c
XML updates.
[apache] / modules / ssl / ssl_engine_config.c
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 /*                      _             _
18  *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
19  * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
20  * | | | | | | (_) | (_| |   \__ \__ \ |
21  * |_| |_| |_|\___/ \__,_|___|___/___/_|
22  *                      |_____|
23  *  ssl_engine_config.c
24  *  Apache Configuration Directives
25  */
26                                       /* ``Damned if you do,
27                                            damned if you don't.''
28                                                -- Unknown        */
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "ssl_private.h"
33 #include "ssl_policies.h"
34 #include "util_mutex.h"
35 #include "ap_provider.h"
36
37 /*  _________________________________________________________________
38 **
39 **  Support for Global Configuration
40 **  _________________________________________________________________
41 */
42
43 #define SSL_MOD_CONFIG_KEY "ssl_module"
44
45 SSLModConfigRec *ssl_config_global_create(server_rec *s)
46 {
47     apr_pool_t *pool = s->process->pool;
48     SSLModConfigRec *mc;
49     void *vmc;
50
51     apr_pool_userdata_get(&vmc, SSL_MOD_CONFIG_KEY, pool);
52     if (vmc) {
53         return vmc; /* reused for lifetime of the server */
54     }
55
56     /*
57      * allocate an own subpool which survives server restarts
58      */
59     mc = (SSLModConfigRec *)apr_palloc(pool, sizeof(*mc));
60     mc->pPool = pool;
61     mc->bFixed = FALSE;
62
63     /*
64      * initialize per-module configuration
65      */
66     mc->sesscache_mode         = SSL_SESS_CACHE_OFF;
67     mc->sesscache              = NULL;
68     mc->pMutex                 = NULL;
69     mc->aRandSeed              = apr_array_make(pool, 4,
70                                                 sizeof(ssl_randseed_t));
71     mc->tVHostKeys             = apr_hash_make(pool);
72     mc->tPrivateKey            = apr_hash_make(pool);
73 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
74     mc->szCryptoDevice         = NULL;
75 #endif
76 #ifdef HAVE_OCSP_STAPLING
77     mc->stapling_cache         = NULL;
78     mc->stapling_cache_mutex   = NULL;
79     mc->stapling_refresh_mutex = NULL;
80 #endif
81
82     apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
83                           apr_pool_cleanup_null,
84                           pool);
85
86     return mc;
87 }
88
89 void ssl_config_global_fix(SSLModConfigRec *mc)
90 {
91     mc->bFixed = TRUE;
92 }
93
94 BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
95 {
96     return mc && mc->bFixed;
97 }
98
99 /*  _________________________________________________________________
100 **
101 **  Configuration handling
102 **  _________________________________________________________________
103 */
104
105 #ifdef HAVE_SSL_CONF_CMD
106 static apr_status_t modssl_ctx_config_cleanup(void *ctx)
107 {
108     SSL_CONF_CTX_free(ctx);
109     return APR_SUCCESS;
110 }
111 #endif
112
113 static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
114 {
115     mctx->sc                  = NULL; /* set during module init */
116
117     mctx->ssl_ctx             = NULL; /* set during module init */
118
119     mctx->pks                 = NULL;
120     mctx->pkp                 = NULL;
121
122 #ifdef HAVE_TLS_SESSION_TICKETS
123     mctx->ticket_key          = NULL;
124 #endif
125
126     mctx->protocol            = SSL_PROTOCOL_DEFAULT;
127     mctx->protocol_set        = 0;
128
129     mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET;
130     mctx->pphrase_dialog_path = NULL;
131
132     mctx->cert_chain          = NULL;
133
134     mctx->crl_path            = NULL;
135     mctx->crl_file            = NULL;
136     mctx->crl_check_mask      = UNSET;
137
138     mctx->auth.ca_cert_path   = NULL;
139     mctx->auth.ca_cert_file   = NULL;
140     mctx->auth.cipher_suite   = NULL;
141     mctx->auth.verify_depth   = UNSET;
142     mctx->auth.verify_mode    = SSL_CVERIFY_UNSET;
143     mctx->auth.tls13_ciphers = NULL;
144
145     mctx->ocsp_mask           = UNSET;
146     mctx->ocsp_force_default  = UNSET;
147     mctx->ocsp_responder      = NULL;
148     mctx->ocsp_resptime_skew  = UNSET;
149     mctx->ocsp_resp_maxage    = UNSET;
150     mctx->ocsp_responder_timeout = UNSET;
151     mctx->ocsp_use_request_nonce = UNSET;
152     mctx->proxy_uri              = NULL;
153
154 /* Set OCSP Responder Certificate Verification variable */
155     mctx->ocsp_noverify       = UNSET;
156 /* Set OCSP Responder File variables */
157     mctx->ocsp_verify_flags   = 0;
158     mctx->ocsp_certs_file     = NULL;
159     mctx->ocsp_certs          = NULL;
160
161 #ifdef HAVE_OCSP_STAPLING
162     mctx->stapling_enabled           = UNSET;
163     mctx->stapling_resptime_skew     = UNSET;
164     mctx->stapling_resp_maxage       = UNSET;
165     mctx->stapling_cache_timeout     = UNSET;
166     mctx->stapling_return_errors     = UNSET;
167     mctx->stapling_fake_trylater     = UNSET;
168     mctx->stapling_errcache_timeout  = UNSET;
169     mctx->stapling_responder_timeout = UNSET;
170     mctx->stapling_force_url         = NULL;
171 #endif
172
173 #ifdef HAVE_SRP
174     mctx->srp_vfile =             NULL;
175     mctx->srp_unknown_user_seed = NULL;
176     mctx->srp_vbase =             NULL;
177 #endif
178 #ifdef HAVE_SSL_CONF_CMD
179     mctx->ssl_ctx_config = SSL_CONF_CTX_new();
180     apr_pool_cleanup_register(p, mctx->ssl_ctx_config,
181                               modssl_ctx_config_cleanup,
182                               apr_pool_cleanup_null);
183     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_FILE);
184     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_SERVER);
185     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
186     mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
187 #endif
188
189     mctx->ssl_check_peer_cn     = UNSET;
190     mctx->ssl_check_peer_name   = UNSET;
191     mctx->ssl_check_peer_expire = UNSET;
192 }
193
194 static void modssl_ctx_init_server(SSLSrvConfigRec *sc,
195                                    apr_pool_t *p)
196 {
197     modssl_ctx_t *mctx;
198
199     mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
200
201     modssl_ctx_init(mctx, p);
202
203     mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks));
204
205     mctx->pks->cert_files = apr_array_make(p, 3, sizeof(char *));
206     mctx->pks->key_files  = apr_array_make(p, 3, sizeof(char *));
207
208 #ifdef HAVE_TLS_SESSION_TICKETS
209     mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key));
210 #endif
211 }
212
213 static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
214 {
215     SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
216
217     sc->mc                     = NULL;
218     sc->enabled                = SSL_ENABLED_UNSET;
219     sc->vhost_id               = NULL;  /* set during module init */
220     sc->vhost_id_len           = 0;     /* set during module init */
221     sc->session_cache_timeout  = UNSET;
222     sc->cipher_server_pref     = UNSET;
223     sc->insecure_reneg         = UNSET;
224 #ifdef HAVE_TLSEXT
225     sc->strict_sni_vhost_check = SSL_ENABLED_UNSET;
226 #endif
227 #ifdef HAVE_FIPS
228     sc->fips                   = UNSET;
229 #endif
230 #ifndef OPENSSL_NO_COMP
231     sc->compression            = UNSET;
232 #endif
233     sc->session_tickets        = UNSET;
234
235     modssl_ctx_init_server(sc, p);
236
237     return sc;
238 }
239
240 /*
241  *  Create per-server SSL configuration
242  */
243 void *ssl_config_server_create(apr_pool_t *p, server_rec *s)
244 {
245     SSLSrvConfigRec *sc = ssl_config_server_new(p);
246
247     sc->mc = ssl_config_global_create(s);
248
249     return sc;
250 }
251
252 #define cfgMerge(el,unset)  mrg->el = (add->el == (unset)) ? base->el : add->el
253 #define cfgMergeArray(el)   mrg->el = apr_array_append(p, base->el, add->el)
254 #define cfgMergeString(el)  cfgMerge(el, NULL)
255 #define cfgMergeBool(el)    cfgMerge(el, UNSET)
256 #define cfgMergeInt(el)     cfgMerge(el, UNSET)
257
258 /*
259  *  Merge per-server SSL configurations
260  */
261
262 static void modssl_ctx_cfg_merge(apr_pool_t *p,
263                                  modssl_ctx_t *base,
264                                  modssl_ctx_t *add,
265                                  modssl_ctx_t *mrg)
266 {
267     if (add->protocol_set) {
268         mrg->protocol = add->protocol;
269     }
270     else {
271         mrg->protocol = base->protocol;
272     }
273
274     cfgMerge(pphrase_dialog_type, SSL_PPTYPE_UNSET);
275     cfgMergeString(pphrase_dialog_path);
276
277     cfgMergeString(cert_chain);
278
279     cfgMerge(crl_path, NULL);
280     cfgMerge(crl_file, NULL);
281     cfgMergeInt(crl_check_mask);
282
283     cfgMergeString(auth.ca_cert_path);
284     cfgMergeString(auth.ca_cert_file);
285     cfgMergeString(auth.cipher_suite);
286     cfgMergeInt(auth.verify_depth);
287     cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET);
288     cfgMergeString(auth.tls13_ciphers);
289
290     cfgMergeInt(ocsp_mask);
291     cfgMergeBool(ocsp_force_default);
292     cfgMerge(ocsp_responder, NULL);
293     cfgMergeInt(ocsp_resptime_skew);
294     cfgMergeInt(ocsp_resp_maxage);
295     cfgMergeInt(ocsp_responder_timeout);
296     cfgMergeBool(ocsp_use_request_nonce);
297     cfgMerge(proxy_uri, NULL);
298
299 /* Set OCSP Responder Certificate Verification directive */
300     cfgMergeBool(ocsp_noverify);  
301 /* Set OCSP Responder File directive for importing */
302     cfgMerge(ocsp_certs_file, NULL);
303
304 #ifdef HAVE_OCSP_STAPLING
305     cfgMergeBool(stapling_enabled);
306     cfgMergeInt(stapling_resptime_skew);
307     cfgMergeInt(stapling_resp_maxage);
308     cfgMergeInt(stapling_cache_timeout);
309     cfgMergeBool(stapling_return_errors);
310     cfgMergeBool(stapling_fake_trylater);
311     cfgMergeInt(stapling_errcache_timeout);
312     cfgMergeInt(stapling_responder_timeout);
313     cfgMerge(stapling_force_url, NULL);
314 #endif
315
316 #ifdef HAVE_SRP
317     cfgMergeString(srp_vfile);
318     cfgMergeString(srp_unknown_user_seed);
319 #endif
320
321 #ifdef HAVE_SSL_CONF_CMD
322     cfgMergeArray(ssl_ctx_param);
323 #endif
324
325     cfgMergeBool(ssl_check_peer_cn);
326     cfgMergeBool(ssl_check_peer_name);
327     cfgMergeBool(ssl_check_peer_expire);
328 }
329
330 static void modssl_ctx_cfg_merge_server(apr_pool_t *p,
331                                         modssl_ctx_t *base,
332                                         modssl_ctx_t *add,
333                                         modssl_ctx_t *mrg)
334 {
335     modssl_ctx_cfg_merge(p, base, add, mrg);
336
337     cfgMergeArray(pks->cert_files);
338     cfgMergeArray(pks->key_files);
339
340     cfgMergeString(pks->ca_name_path);
341     cfgMergeString(pks->ca_name_file);
342
343 #ifdef HAVE_TLS_SESSION_TICKETS
344     cfgMergeString(ticket_key->file_path);
345 #endif
346 }
347
348 void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
349 {
350     SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
351     SSLSrvConfigRec *add  = (SSLSrvConfigRec *)addv;
352     SSLSrvConfigRec *mrg  = ssl_config_server_new(p);
353
354     cfgMerge(mc, NULL);
355     cfgMerge(enabled, SSL_ENABLED_UNSET);
356     cfgMergeInt(session_cache_timeout);
357     cfgMergeBool(cipher_server_pref);
358     cfgMergeBool(insecure_reneg);
359 #ifdef HAVE_TLSEXT
360     cfgMerge(strict_sni_vhost_check, SSL_ENABLED_UNSET);
361 #endif
362 #ifdef HAVE_FIPS
363     cfgMergeBool(fips);
364 #endif
365 #ifndef OPENSSL_NO_COMP
366     cfgMergeBool(compression);
367 #endif
368     cfgMergeBool(session_tickets);
369
370     modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server);
371
372     return mrg;
373 }
374
375 /*
376  *  Create per-directory SSL configuration
377  */
378
379 static void modssl_ctx_init_proxy(SSLDirConfigRec *dc,
380                                   apr_pool_t *p)
381 {
382     modssl_ctx_t *mctx;
383
384     mctx = dc->proxy = apr_palloc(p, sizeof(*dc->proxy));
385
386     modssl_ctx_init(mctx, p);
387
388     mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp));
389
390     mctx->pkp->cert_file = NULL;
391     mctx->pkp->cert_path = NULL;
392     mctx->pkp->ca_cert_file = NULL;
393     mctx->pkp->certs     = NULL;
394     mctx->pkp->ca_certs  = NULL;
395 }
396
397 void *ssl_config_perdir_create(apr_pool_t *p, char *dir)
398 {
399     SSLDirConfigRec *dc = apr_palloc(p, sizeof(*dc));
400
401     dc->bSSLRequired  = FALSE;
402     dc->aRequirement  = apr_array_make(p, 4, sizeof(ssl_require_t));
403     dc->nOptions      = SSL_OPT_NONE|SSL_OPT_RELSET;
404     dc->nOptionsAdd   = SSL_OPT_NONE;
405     dc->nOptionsDel   = SSL_OPT_NONE;
406
407     dc->szCipherSuite          = NULL;
408     dc->nVerifyClient          = SSL_CVERIFY_UNSET;
409     dc->nVerifyDepth           = UNSET;
410
411     dc->szUserName             = NULL;
412
413     dc->nRenegBufferSize = UNSET;
414
415     dc->proxy_enabled = UNSET;
416     modssl_ctx_init_proxy(dc, p);
417     dc->proxy_post_config = FALSE;
418
419     return dc;
420 }
421
422 /*
423  *  Merge per-directory SSL configurations
424  */
425
426 static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
427                                        modssl_ctx_t *base,
428                                        modssl_ctx_t *add,
429                                        modssl_ctx_t *mrg)
430 {
431     modssl_ctx_cfg_merge(p, base, add, mrg);
432
433     cfgMergeString(pkp->cert_file);
434     cfgMergeString(pkp->cert_path);
435     cfgMergeString(pkp->ca_cert_file);
436 }
437
438 void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv)
439 {
440     SSLDirConfigRec *base = (SSLDirConfigRec *)basev;
441     SSLDirConfigRec *add  = (SSLDirConfigRec *)addv;
442     SSLDirConfigRec *mrg  = (SSLDirConfigRec *)apr_palloc(p, sizeof(*mrg));
443
444     cfgMerge(bSSLRequired, FALSE);
445     cfgMergeArray(aRequirement);
446
447     if (add->nOptions & SSL_OPT_RELSET) {
448         mrg->nOptionsAdd =
449             (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd;
450         mrg->nOptionsDel =
451             (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel;
452         mrg->nOptions    =
453             (base->nOptions    & ~(mrg->nOptionsDel)) | mrg->nOptionsAdd;
454     }
455     else {
456         mrg->nOptions    = add->nOptions;
457         mrg->nOptionsAdd = add->nOptionsAdd;
458         mrg->nOptionsDel = add->nOptionsDel;
459     }
460
461     cfgMergeString(szCipherSuite);
462     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
463     cfgMergeInt(nVerifyDepth);
464
465     cfgMergeString(szUserName);
466
467     cfgMergeInt(nRenegBufferSize);
468
469     mrg->proxy_post_config = add->proxy_post_config;
470     if (!mrg->proxy_post_config) {
471         cfgMergeBool(proxy_enabled);
472         modssl_ctx_init_proxy(mrg, p);
473         modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy);
474
475         /* Since ssl_proxy_section_post_config() hook won't be called if there
476          * is no SSLProxy* in this dir config, the ssl_ctx may still be NULL
477          * here at runtime. Merging it is either a no-op (NULL => NULL) because
478          * we are still before post config, or we really want to reuse the one
479          * from the upper/server context (outside of <Proxy> sections).
480          */
481         cfgMerge(proxy->ssl_ctx, NULL);
482     }
483     else {
484         /* The post_config hook has already merged and initialized the
485          * proxy context, use it.
486          */
487         mrg->proxy_enabled = add->proxy_enabled;
488         mrg->proxy = add->proxy;
489     }
490
491     return mrg;
492 }
493
494 /* Simply merge conf with base into conf, no third party. */
495 void ssl_config_proxy_merge(apr_pool_t *p,
496                             SSLDirConfigRec *base,
497                             SSLDirConfigRec *conf)
498 {
499     if (conf->proxy_enabled == UNSET) {
500         conf->proxy_enabled = base->proxy_enabled;
501     }
502     modssl_ctx_cfg_merge_proxy(p, base->proxy, conf->proxy, conf->proxy);
503 }
504
505 /*  _________________________________________________________________
506 **
507 **  Policy handling
508 **  _________________________________________________________________
509 */
510
511 static void add_policy(apr_hash_t *policies, apr_pool_t *p, const char *name,
512                        int protocols, const char *ssl_ciphers, const char *tls13_ciphers, 
513                        int honor_order, int compression, int session_tickets)
514 {
515     SSLPolicyRec *policy;
516     
517     policy = apr_pcalloc(p, sizeof(*policy));
518     policy->name = name;
519     policy->sc = ssl_config_server_new(p);
520     
521     if (protocols) {
522         policy->sc->server->protocol_set      = 1;
523         policy->sc->server->protocol          = protocols;
524     }
525     if (ssl_ciphers) {
526         policy->sc->server->auth.cipher_suite = ssl_ciphers;
527     }
528     if (tls13_ciphers) {
529         policy->sc->server->auth.tls13_ciphers = tls13_ciphers;
530     }
531
532 #ifndef OPENSSL_NO_COMP
533     policy->sc->compression               = compression ? TRUE : FALSE;
534 #endif
535     policy->sc->session_tickets           = session_tickets ? TRUE : FALSE;
536     
537     apr_hash_set(policies, policy->name, APR_HASH_KEY_STRING, policy);
538 }
539
540 static apr_hash_t *get_policies(apr_pool_t *p, int create)
541 {
542     apr_hash_t *policies;
543     void *vp;
544     
545     apr_pool_userdata_get(&vp, SSL_MOD_POLICIES_KEY, p);
546     if (vp) {
547         return vp; /* reused for lifetime of the pool */
548     }
549     if (create) {
550         policies = apr_hash_make(p);
551         
552 #if SSL_POLICY_MODERN
553         add_policy(policies, p, "modern", 
554                    SSL_POLICY_MODERN_PROTOCOLS, 
555                    SSL_POLICY_MODERN_SSL_CIPHERS, 
556                    SSL_POLICY_MODERN_TLS13_CIPHERS, 
557                    SSL_POLICY_HONOR_ORDER, 
558                    SSL_POLICY_COMPRESSION, 
559                    SSL_POLICY_SESSION_TICKETS);
560 #endif        
561 #if SSL_POLICY_INTERMEDIATE
562         add_policy(policies, p, "intermediate", 
563                    SSL_POLICY_INTERMEDIATE_PROTOCOLS, 
564                    SSL_POLICY_INTERMEDIATE_SSL_CIPHERS, 
565                    SSL_POLICY_INTERMEDIATE_TLS13_CIPHERS, 
566                    SSL_POLICY_HONOR_ORDER, 
567                    SSL_POLICY_COMPRESSION, 
568                    SSL_POLICY_SESSION_TICKETS);
569 #endif        
570 #if SSL_POLICY_OLD
571         add_policy(policies, p, "old", 
572                    SSL_POLICY_OLD_PROTOCOLS, 
573                    SSL_POLICY_OLD_SSL_CIPHERS, 
574                    SSL_POLICY_OLD_TLS13_CIPHERS, 
575                    SSL_POLICY_HONOR_ORDER, 
576                    SSL_POLICY_COMPRESSION, 
577                    SSL_POLICY_SESSION_TICKETS);
578 #endif        
579         
580         apr_pool_userdata_set(policies, SSL_MOD_POLICIES_KEY,
581                               apr_pool_cleanup_null, p);
582         return policies;
583     }
584     return NULL;
585 }
586
587 static int policy_collect_names(void *baton, const void *key, apr_ssize_t klen, const void *val)
588 {
589     apr_array_header_t *names = baton;
590     APR_ARRAY_PUSH(names, const char *) = (const char*)key;
591     return 1;
592 }
593
594 static int qstrcmp(const void *v1, const void *v2)
595 {
596     return strcmp(*(const char**)v1, *(const char**)v2);
597 }
598
599 static apr_array_header_t *get_policy_names(apr_pool_t *p, int create)
600 {
601     apr_array_header_t *names = apr_array_make(p, 10, sizeof(const char*));
602     apr_hash_t *policies = get_policies(p, create);
603     
604     if (policies) {
605         apr_hash_do(policy_collect_names, names, policies);
606         qsort(names->elts, names->nelts, sizeof(const char*), qstrcmp);
607     }
608     return names;
609 }
610
611 SSLPolicyRec *ssl_policy_lookup(apr_pool_t *pool, const char *name)
612 {
613     apr_hash_t *policies = get_policies(pool, 1);
614     return apr_hash_get(policies, name, APR_HASH_KEY_STRING);
615 }
616
617 const char *ssl_cmd_SSLPolicyApply(cmd_parms *cmd, void *mconfig, const char *arg)
618 {
619     SSLSrvConfigRec *mrg, *sc = mySrvConfig(cmd->server);
620     SSLPolicyRec *policy;
621     
622     policy = ssl_policy_lookup(cmd->pool, arg);
623     if (policy) {
624         mrg = ssl_config_server_merge(cmd->pool, policy->sc, sc);
625         /* apply in place */
626         memcpy(sc, mrg, sizeof(*sc));
627         return NULL;
628     }
629     return apr_pstrcat(cmd->pool,
630                        "An SSLPolicy with the name '", arg,
631                        "' does not exist", NULL);
632 }
633
634 /*
635  *  Configuration functions for particular directives
636  */
637
638 const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd,
639                                         void *dcfg,
640                                         const char *arg)
641 {
642     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
643     const char *err;
644     int arglen = strlen(arg);
645
646     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
647         return err;
648     }
649
650     if (strcEQ(arg, "builtin")) {
651         sc->server->pphrase_dialog_type  = SSL_PPTYPE_BUILTIN;
652         sc->server->pphrase_dialog_path = NULL;
653     }
654     else if ((arglen > 5) && strEQn(arg, "exec:", 5)) {
655         sc->server->pphrase_dialog_type  = SSL_PPTYPE_FILTER;
656         sc->server->pphrase_dialog_path =
657             ap_server_root_relative(cmd->pool, arg+5);
658         if (!sc->server->pphrase_dialog_path) {
659             return apr_pstrcat(cmd->pool,
660                                "Invalid SSLPassPhraseDialog exec: path ",
661                                arg+5, NULL);
662         }
663         if (!ssl_util_path_check(SSL_PCM_EXISTS,
664                                  sc->server->pphrase_dialog_path,
665                                  cmd->pool))
666         {
667             return apr_pstrcat(cmd->pool,
668                                "SSLPassPhraseDialog: file '",
669                                sc->server->pphrase_dialog_path,
670                                "' does not exist", NULL);
671         }
672
673     }
674     else if ((arglen > 1) && (arg[0] == '|')) {
675         sc->server->pphrase_dialog_type  = SSL_PPTYPE_PIPE;
676         sc->server->pphrase_dialog_path = arg + 1;
677     }
678     else {
679         return "SSLPassPhraseDialog: Invalid argument";
680     }
681
682     return NULL;
683 }
684
685 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
686 const char *ssl_cmd_SSLCryptoDevice(cmd_parms *cmd,
687                                     void *dcfg,
688                                     const char *arg)
689 {
690     SSLModConfigRec *mc = myModConfig(cmd->server);
691     const char *err;
692     ENGINE *e;
693
694     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
695         return err;
696     }
697     if (!mc) {
698         return "SSLCryptoDevice: cannot be used inside SSLPolicyDefine";
699     }
700
701     if (strcEQ(arg, "builtin")) {
702         mc->szCryptoDevice = NULL;
703     }
704     else if ((e = ENGINE_by_id(arg))) {
705         mc->szCryptoDevice = arg;
706         ENGINE_free(e);
707     }
708     else {
709         err = "SSLCryptoDevice: Invalid argument; must be one of: "
710               "'builtin' (none)";
711         e = ENGINE_get_first();
712         while (e) {
713             err = apr_pstrcat(cmd->pool, err, ", '", ENGINE_get_id(e),
714                                          "' (", ENGINE_get_name(e), ")", NULL);
715             /* Iterate; this call implicitly decrements the refcount
716              * on the 'old' e, per the docs in engine.h. */
717             e = ENGINE_get_next(e);
718         }
719         return err;
720     }
721
722     return NULL;
723 }
724 #endif
725
726 const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd,
727                                   void *dcfg,
728                                   const char *arg1,
729                                   const char *arg2,
730                                   const char *arg3)
731 {
732     SSLModConfigRec *mc = myModConfig(cmd->server);
733     const char *err;
734     ssl_randseed_t *seed;
735     int arg2len = strlen(arg2);
736
737     /* replace: check_no_policy_and(flags) */
738     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
739         return err;
740     }
741     if (!mc) {
742         return "SSLRandomSeed: cannot be used inside SSLPolicyDefine";
743     }
744
745     if (ssl_config_global_isfixed(mc)) {
746         return NULL;
747     }
748
749     seed = apr_array_push(mc->aRandSeed);
750
751     if (strcEQ(arg1, "startup")) {
752         seed->nCtx = SSL_RSCTX_STARTUP;
753     }
754     else if (strcEQ(arg1, "connect")) {
755         seed->nCtx = SSL_RSCTX_CONNECT;
756     }
757     else {
758         return apr_pstrcat(cmd->pool, "SSLRandomSeed: "
759                            "invalid context: `", arg1, "'",
760                            NULL);
761     }
762
763     if ((arg2len > 5) && strEQn(arg2, "file:", 5)) {
764         seed->nSrc   = SSL_RSSRC_FILE;
765         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
766     }
767     else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) {
768         seed->nSrc   = SSL_RSSRC_EXEC;
769         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
770     }
771     else if ((arg2len > 4) && strEQn(arg2, "egd:", 4)) {
772 #ifdef HAVE_RAND_EGD
773         seed->nSrc   = SSL_RSSRC_EGD;
774         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+4);
775 #else
776         return apr_pstrcat(cmd->pool, "Invalid SSLRandomSeed entropy source `",
777                            arg2, "': This version of " MODSSL_LIBRARY_NAME
778                            " does not support the Entropy Gathering Daemon "
779                            "(EGD).", NULL);
780 #endif
781     }
782     else if (strcEQ(arg2, "builtin")) {
783         seed->nSrc   = SSL_RSSRC_BUILTIN;
784         seed->cpPath = NULL;
785     }
786     else {
787         seed->nSrc   = SSL_RSSRC_FILE;
788         seed->cpPath = ap_server_root_relative(mc->pPool, arg2);
789     }
790
791     if (seed->nSrc != SSL_RSSRC_BUILTIN) {
792         if (!seed->cpPath) {
793             return apr_pstrcat(cmd->pool,
794                                "Invalid SSLRandomSeed path ",
795                                arg2, NULL);
796         }
797         if (!ssl_util_path_check(SSL_PCM_EXISTS, seed->cpPath, cmd->pool)) {
798             return apr_pstrcat(cmd->pool,
799                                "SSLRandomSeed: source path '",
800                                seed->cpPath, "' does not exist", NULL);
801         }
802     }
803
804     if (!arg3) {
805         seed->nBytes = 0; /* read whole file */
806     }
807     else {
808         if (seed->nSrc == SSL_RSSRC_BUILTIN) {
809             return "SSLRandomSeed: byte specification not "
810                    "allowed for builtin seed source";
811         }
812
813         seed->nBytes = atoi(arg3);
814
815         if (seed->nBytes < 0) {
816             return "SSLRandomSeed: invalid number of bytes specified";
817         }
818     }
819
820     return NULL;
821 }
822
823 const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
824 {
825     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
826
827     if (!strcasecmp(arg, "On")) {
828         sc->enabled = SSL_ENABLED_TRUE;
829         return NULL;
830     }
831     else if (!strcasecmp(arg, "Off")) {
832         sc->enabled = SSL_ENABLED_FALSE;
833         return NULL;
834     }
835     else if (!strcasecmp(arg, "Optional")) {
836         sc->enabled = SSL_ENABLED_OPTIONAL;
837         return NULL;
838     }
839
840     return "Argument must be On, Off, or Optional";
841 }
842
843 const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag)
844 {
845 #ifdef HAVE_FIPS
846     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
847 #endif
848     const char *err;
849
850     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
851         return err;
852     }
853
854 #ifdef HAVE_FIPS
855     if ((sc->fips != UNSET) && (sc->fips != (BOOL)(flag ? TRUE : FALSE)))
856         return "Conflicting SSLFIPS options, cannot be both On and Off";
857     sc->fips = flag ? TRUE : FALSE;
858 #else
859     if (flag)
860         return "SSLFIPS invalid, rebuild httpd and openssl compiled for FIPS";
861 #endif
862
863     return NULL;
864 }
865
866 const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
867                                    void *dcfg,
868                                    const char *arg1, const char *arg2)
869 {
870     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
871     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
872
873     if (arg2 == NULL) {
874         arg2 = arg1;
875         arg1 = "SSL";
876     }
877     
878     if (!strcmp("SSL", arg1)) {
879         /* always disable null and export ciphers */
880         arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
881         if (cmd->path) {
882             dc->szCipherSuite = arg2;
883         }
884         else {
885             sc->server->auth.cipher_suite = arg2;
886         }
887         return NULL;
888     }
889 #ifdef SSL_OP_NO_TLSv1_3
890     else if (!strcmp("TLSv1.3", arg1)) {
891         if (cmd->path) {
892             return "TLSv1.3 ciphers cannot be set inside a directory context";
893         }
894         sc->server->auth.tls13_ciphers = arg2;
895         return NULL;
896     }
897 #endif
898     return apr_pstrcat(cmd->pool, "procotol '", arg1, "' not supported", NULL);
899 }
900
901 #define SSL_FLAGS_CHECK_FILE \
902     (SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO)
903
904 #define SSL_FLAGS_CHECK_DIR \
905     (SSL_PCM_EXISTS|SSL_PCM_ISDIR)
906
907 static const char *ssl_cmd_check_file(cmd_parms *parms,
908                                       const char **file)
909 {
910     const char *filepath = ap_server_root_relative(parms->pool, *file);
911
912     if (!filepath) {
913         return apr_pstrcat(parms->pool, parms->cmd->name,
914                            ": Invalid file path ", *file, NULL);
915     }
916     *file = filepath;
917
918     if (ssl_util_path_check(SSL_FLAGS_CHECK_FILE, *file, parms->pool)) {
919         return NULL;
920     }
921
922     return apr_pstrcat(parms->pool, parms->cmd->name,
923                        ": file '", *file,
924                        "' does not exist or is empty", NULL);
925
926 }
927
928 const char *ssl_cmd_SSLCompression(cmd_parms *cmd, void *dcfg, int flag)
929 {
930 #if !defined(OPENSSL_NO_COMP)
931     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
932 #ifndef SSL_OP_NO_COMPRESSION
933     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
934     if (err)
935         return "This version of OpenSSL does not support enabling "
936                "SSLCompression within <VirtualHost> sections.";
937 #endif
938     if (flag) {
939         /* Some (packaged) versions of OpenSSL do not support
940          * compression by default.  Enabling this directive would not
941          * have the desired effect, so fail with an error. */
942         STACK_OF(SSL_COMP) *meths = SSL_COMP_get_compression_methods();
943
944         if (sk_SSL_COMP_num(meths) == 0) {
945             return "This version of OpenSSL does not have any compression methods "
946                 "available, cannot enable SSLCompression.";
947         }
948     }
949     sc->compression = flag ? TRUE : FALSE;
950     return NULL;
951 #else
952     return "Setting Compression mode unsupported; not implemented by the SSL library";
953 #endif
954 }
955
956 const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag)
957 {
958 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
959     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
960     sc->cipher_server_pref = flag?TRUE:FALSE;
961     return NULL;
962 #else
963     return "SSLHonorCipherOrder unsupported; not implemented by the SSL library";
964 #endif
965 }
966
967 const char *ssl_cmd_SSLSessionTickets(cmd_parms *cmd, void *dcfg, int flag)
968 {
969     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
970 #ifndef SSL_OP_NO_TICKET
971     return "This version of OpenSSL does not support using "
972            "SSLSessionTickets.";
973 #endif
974     sc->session_tickets = flag ? TRUE : FALSE;
975     return NULL;
976 }
977
978 const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag)
979 {
980 #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
981     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
982     sc->insecure_reneg = flag?TRUE:FALSE;
983     return NULL;
984 #else
985     return "The SSLInsecureRenegotiation directive is not available "
986         "with this SSL library";
987 #endif
988 }
989
990
991 static const char *ssl_cmd_check_dir(cmd_parms *parms,
992                                      const char **dir)
993 {
994     const char *dirpath = ap_server_root_relative(parms->pool, *dir);
995
996     if (!dirpath) {
997         return apr_pstrcat(parms->pool, parms->cmd->name,
998                            ": Invalid dir path ", *dir, NULL);
999     }
1000     *dir = dirpath;
1001
1002     if (ssl_util_path_check(SSL_FLAGS_CHECK_DIR, *dir, parms->pool)) {
1003         return NULL;
1004     }
1005
1006     return apr_pstrcat(parms->pool, parms->cmd->name,
1007                        ": directory '", *dir,
1008                        "' does not exist", NULL);
1009
1010 }
1011
1012 const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd,
1013                                        void *dcfg,
1014                                        const char *arg)
1015 {
1016     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1017     const char *err;
1018
1019     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1020         return err;
1021     }
1022
1023     *(const char **)apr_array_push(sc->server->pks->cert_files) = arg;
1024     
1025     return NULL;
1026 }
1027
1028 const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd,
1029                                           void *dcfg,
1030                                           const char *arg)
1031 {
1032     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1033     const char *err;
1034
1035     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1036         return err;
1037     }
1038
1039     *(const char **)apr_array_push(sc->server->pks->key_files) = arg;
1040
1041     return NULL;
1042 }
1043
1044 const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd,
1045                                             void *dcfg,
1046                                             const char *arg)
1047 {
1048     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1049     const char *err;
1050
1051     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1052         return err;
1053     }
1054
1055     sc->server->cert_chain = arg;
1056
1057     return NULL;
1058 }
1059
1060 #ifdef HAVE_TLS_SESSION_TICKETS
1061 const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd,
1062                                             void *dcfg,
1063                                             const char *arg)
1064 {
1065     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1066     const char *err;
1067
1068     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1069         return err;
1070     }
1071
1072     sc->server->ticket_key->file_path = arg;
1073
1074     return NULL;
1075 }
1076 #endif
1077
1078 #define NO_PER_DIR_SSL_CA \
1079     "Your SSL library does not have support for per-directory CA"
1080
1081 const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd,
1082                                          void *dcfg,
1083                                          const char *arg)
1084 {
1085     /*SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;*/
1086     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1087     const char *err;
1088
1089     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1090         return err;
1091     }
1092
1093     if (cmd->path) {
1094         return NO_PER_DIR_SSL_CA;
1095     }
1096
1097     /* XXX: bring back per-dir */
1098     sc->server->auth.ca_cert_path = arg;
1099
1100     return NULL;
1101 }
1102
1103 const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd,
1104                                          void *dcfg,
1105                                          const char *arg)
1106 {
1107     /*SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;*/
1108     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1109     const char *err;
1110
1111     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1112         return err;
1113     }
1114
1115     if (cmd->path) {
1116         return NO_PER_DIR_SSL_CA;
1117     }
1118
1119     /* XXX: bring back per-dir */
1120     sc->server->auth.ca_cert_file = arg;
1121
1122     return NULL;
1123 }
1124
1125 const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *cmd, void *dcfg,
1126                                        const char *arg)
1127 {
1128     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1129     const char *err;
1130
1131     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1132         return err;
1133     }
1134
1135     sc->server->pks->ca_name_path = arg;
1136
1137     return NULL;
1138 }
1139
1140 const char *ssl_cmd_SSLCADNRequestFile(cmd_parms *cmd, void *dcfg,
1141                                        const char *arg)
1142 {
1143     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1144     const char *err;
1145
1146     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1147         return err;
1148     }
1149
1150     sc->server->pks->ca_name_file = arg;
1151
1152     return NULL;
1153 }
1154
1155 const char *ssl_cmd_SSLCARevocationPath(cmd_parms *cmd,
1156                                         void *dcfg,
1157                                         const char *arg)
1158 {
1159     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1160     const char *err;
1161
1162     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1163         return err;
1164     }
1165
1166     sc->server->crl_path = arg;
1167
1168     return NULL;
1169 }
1170
1171 const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd,
1172                                         void *dcfg,
1173                                         const char *arg)
1174 {
1175     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1176     const char *err;
1177
1178     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1179         return err;
1180     }
1181
1182     sc->server->crl_file = arg;
1183
1184     return NULL;
1185 }
1186
1187 static const char *ssl_cmd_crlcheck_parse(cmd_parms *parms,
1188                                           const char *arg,
1189                                           int *mask)
1190 {
1191     const char *w;
1192
1193     w = ap_getword_conf(parms->temp_pool, &arg);
1194     if (strcEQ(w, "none")) {
1195         *mask = SSL_CRLCHECK_NONE;
1196     }
1197     else if (strcEQ(w, "leaf")) {
1198         *mask = SSL_CRLCHECK_LEAF;
1199     }
1200     else if (strcEQ(w, "chain")) {
1201         *mask = SSL_CRLCHECK_CHAIN;
1202     }
1203     else {
1204         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1205                            ": Invalid argument '", w, "'",
1206                            NULL);
1207     }
1208
1209     while (*arg) {
1210         w = ap_getword_conf(parms->temp_pool, &arg);
1211         if (strcEQ(w, "no_crl_for_cert_ok")) {
1212             *mask |= SSL_CRLCHECK_NO_CRL_FOR_CERT_OK;
1213         }
1214         else {
1215             return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1216                                ": Invalid argument '", w, "'",
1217                                NULL);
1218         }
1219     }
1220
1221     return NULL;
1222 }
1223
1224 const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *cmd,
1225                                          void *dcfg,
1226                                          const char *arg)
1227 {
1228     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1229
1230     return ssl_cmd_crlcheck_parse(cmd, arg, &sc->server->crl_check_mask);
1231 }
1232
1233 static const char *ssl_cmd_verify_parse(cmd_parms *parms,
1234                                         const char *arg,
1235                                         ssl_verify_t *id)
1236 {
1237     if (strcEQ(arg, "none") || strcEQ(arg, "off")) {
1238         *id = SSL_CVERIFY_NONE;
1239     }
1240     else if (strcEQ(arg, "optional")) {
1241         *id = SSL_CVERIFY_OPTIONAL;
1242     }
1243     else if (strcEQ(arg, "require") || strcEQ(arg, "on")) {
1244         *id = SSL_CVERIFY_REQUIRE;
1245     }
1246     else if (strcEQ(arg, "optional_no_ca")) {
1247         *id = SSL_CVERIFY_OPTIONAL_NO_CA;
1248     }
1249     else {
1250         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1251                            ": Invalid argument '", arg, "'",
1252                            NULL);
1253     }
1254
1255     return NULL;
1256 }
1257
1258 const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd,
1259                                     void *dcfg,
1260                                     const char *arg)
1261 {
1262     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1263     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1264     ssl_verify_t mode = SSL_CVERIFY_NONE;
1265     const char *err;
1266
1267     if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) {
1268         return err;
1269     }
1270
1271     if (cmd->path) {
1272         dc->nVerifyClient = mode;
1273     }
1274     else {
1275         sc->server->auth.verify_mode = mode;
1276     }
1277
1278     return NULL;
1279 }
1280
1281 static const char *ssl_cmd_verify_depth_parse(cmd_parms *parms,
1282                                               const char *arg,
1283                                               int *depth)
1284 {
1285     if ((*depth = atoi(arg)) >= 0) {
1286         return NULL;
1287     }
1288
1289     return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1290                        ": Invalid argument '", arg, "'",
1291                        NULL);
1292 }
1293
1294 const char *ssl_cmd_SSLVerifyDepth(cmd_parms *cmd,
1295                                    void *dcfg,
1296                                    const char *arg)
1297 {
1298     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1299     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1300     int depth;
1301     const char *err;
1302
1303     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
1304         return err;
1305     }
1306
1307     if (cmd->path) {
1308         dc->nVerifyDepth = depth;
1309     }
1310     else {
1311         sc->server->auth.verify_depth = depth;
1312     }
1313
1314     return NULL;
1315 }
1316
1317 const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd,
1318                                     void *dcfg,
1319                                     const char *arg)
1320 {
1321     SSLModConfigRec *mc = myModConfig(cmd->server);
1322     const char *err, *sep, *name;
1323     long enabled_flags;
1324
1325     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
1326         return err;
1327     }
1328     if (!mc) {
1329         return "SSLSessionCache: cannot be used inside SSLPolicyDefine";
1330     }
1331
1332     /* The OpenSSL session cache mode must have both the flags
1333      * SSL_SESS_CACHE_SERVER and SSL_SESS_CACHE_NO_INTERNAL set if a
1334      * session cache is configured; NO_INTERNAL prevents the
1335      * OpenSSL-internal session cache being used in addition to the
1336      * "external" (mod_ssl-provided) cache, which otherwise causes
1337      * additional memory consumption. */
1338     enabled_flags = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL;
1339
1340     if (strcEQ(arg, "none")) {
1341         /* Nothing to do; session cache will be off. */
1342     }
1343     else if (strcEQ(arg, "nonenotnull")) {
1344         /* ### Having a separate mode for this seems logically
1345          * unnecessary; the stated purpose of sending non-empty
1346          * session IDs would be better fixed in OpenSSL or simply
1347          * doing it by default if "none" is used. */
1348         mc->sesscache_mode = enabled_flags;
1349     }
1350     else {
1351         /* Argument is of form 'name:args' or just 'name'. */
1352         sep = ap_strchr_c(arg, ':');
1353         if (sep) {
1354             name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
1355             sep++;
1356         }
1357         else {
1358             name = arg;
1359         }
1360
1361         /* Find the provider of given name. */
1362         mc->sesscache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
1363                                            name,
1364                                            AP_SOCACHE_PROVIDER_VERSION);
1365         if (mc->sesscache) {
1366             /* Cache found; create it, passing anything beyond the colon. */
1367             mc->sesscache_mode = enabled_flags;
1368             err = mc->sesscache->create(&mc->sesscache_context, sep,
1369                                         cmd->temp_pool, cmd->pool);
1370         }
1371         else {
1372             apr_array_header_t *name_list;
1373             const char *all_names;
1374
1375             /* Build a comma-separated list of all registered provider
1376              * names: */
1377             name_list = ap_list_provider_names(cmd->pool,
1378                                                AP_SOCACHE_PROVIDER_GROUP,
1379                                                AP_SOCACHE_PROVIDER_VERSION);
1380             all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
1381
1382             err = apr_psprintf(cmd->pool, "'%s' session cache not supported "
1383                                "(known names: %s). Maybe you need to load the "
1384                                "appropriate socache module (mod_socache_%s?).",
1385                                name, all_names, name);
1386         }
1387     }
1388
1389     if (err) {
1390         return apr_psprintf(cmd->pool, "SSLSessionCache: %s", err);
1391     }
1392
1393     return NULL;
1394 }
1395
1396 const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *cmd,
1397                                            void *dcfg,
1398                                            const char *arg)
1399 {
1400     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1401
1402     sc->session_cache_timeout = atoi(arg);
1403
1404     if (sc->session_cache_timeout < 0) {
1405         return "SSLSessionCacheTimeout: Invalid argument";
1406     }
1407
1408     return NULL;
1409 }
1410
1411 const char *ssl_cmd_SSLOptions(cmd_parms *cmd,
1412                                void *dcfg,
1413                                const char *arg)
1414 {
1415     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1416     ssl_opt_t opt;
1417     int first = TRUE;
1418     char action, *w;
1419
1420     while (*arg) {
1421         w = ap_getword_conf(cmd->temp_pool, &arg);
1422         action = NUL;
1423
1424         if ((*w == '+') || (*w == '-')) {
1425             action = *(w++);
1426         }
1427         else if (first) {
1428             dc->nOptions = SSL_OPT_NONE;
1429             first = FALSE;
1430         }
1431
1432         if (strcEQ(w, "StdEnvVars")) {
1433             opt = SSL_OPT_STDENVVARS;
1434         }
1435         else if (strcEQ(w, "ExportCertData")) {
1436             opt = SSL_OPT_EXPORTCERTDATA;
1437         }
1438         else if (strcEQ(w, "FakeBasicAuth")) {
1439             opt = SSL_OPT_FAKEBASICAUTH;
1440         }
1441         else if (strcEQ(w, "StrictRequire")) {
1442             opt = SSL_OPT_STRICTREQUIRE;
1443         }
1444         else if (strcEQ(w, "OptRenegotiate")) {
1445             opt = SSL_OPT_OPTRENEGOTIATE;
1446         }
1447         else if (strcEQ(w, "LegacyDNStringFormat")) {
1448             opt = SSL_OPT_LEGACYDNFORMAT;
1449         }
1450         else {
1451             return apr_pstrcat(cmd->pool,
1452                                "SSLOptions: Illegal option '", w, "'",
1453                                NULL);
1454         }
1455
1456         if (action == '-') {
1457             dc->nOptionsAdd &= ~opt;
1458             dc->nOptionsDel |=  opt;
1459             dc->nOptions    &= ~opt;
1460         }
1461         else if (action == '+') {
1462             dc->nOptionsAdd |=  opt;
1463             dc->nOptionsDel &= ~opt;
1464             dc->nOptions    |=  opt;
1465         }
1466         else {
1467             dc->nOptions    = opt;
1468             dc->nOptionsAdd = opt;
1469             dc->nOptionsDel = SSL_OPT_NONE;
1470         }
1471     }
1472
1473     return NULL;
1474 }
1475
1476 const char *ssl_cmd_SSLRequireSSL(cmd_parms *cmd, void *dcfg)
1477 {
1478     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1479
1480     dc->bSSLRequired = TRUE;
1481
1482     return NULL;
1483 }
1484
1485 const char *ssl_cmd_SSLRequire(cmd_parms *cmd,
1486                                void *dcfg,
1487                                const char *arg)
1488 {
1489     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1490     ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
1491     ssl_require_t *require;
1492     const char *errstring;
1493
1494     info->flags = AP_EXPR_FLAG_SSL_EXPR_COMPAT;
1495     info->filename = cmd->directive->filename;
1496     info->line_number = cmd->directive->line_num;
1497     info->module_index = APLOG_MODULE_INDEX;
1498     errstring = ap_expr_parse(cmd->pool, cmd->temp_pool, info, arg, NULL);
1499     if (errstring) {
1500         return apr_pstrcat(cmd->pool, "SSLRequire: ", errstring, NULL);
1501     }
1502
1503     require = apr_array_push(dc->aRequirement);
1504     require->cpExpr = arg;
1505     require->mpExpr = info;
1506
1507     return NULL;
1508 }
1509
1510 const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg)
1511 {
1512     SSLDirConfigRec *dc = dcfg;
1513     int val;
1514
1515     val = atoi(arg);
1516     if (val < 0) {
1517         return apr_pstrcat(cmd->pool, "Invalid size for SSLRenegBufferSize: ",
1518                            arg, NULL);
1519     }
1520     dc->nRenegBufferSize = val;
1521
1522     return NULL;
1523 }
1524
1525 static const char *ssl_cmd_protocol_parse(cmd_parms *parms,
1526                                           const char *arg,
1527                                           ssl_proto_t *options)
1528 {
1529     ssl_proto_t thisopt;
1530
1531     *options = SSL_PROTOCOL_NONE;
1532
1533     while (*arg) {
1534         char *w = ap_getword_conf(parms->temp_pool, &arg);
1535         char action = '\0';
1536
1537         if ((*w == '+') || (*w == '-')) {
1538             action = *(w++);
1539         }
1540
1541         if (strcEQ(w, "SSLv2")) {
1542             if (action == '-') {
1543                 continue;
1544             }
1545             else {
1546                 return "SSLProtocol: SSLv2 is no longer supported";
1547             }
1548         }
1549         else if (strcEQ(w, "SSLv3")) {
1550 #ifdef OPENSSL_NO_SSL3
1551             if (action != '-') {
1552                 return "SSLv3 not supported by this version of OpenSSL";
1553             }
1554             /* Nothing to do, the flag is not present to be toggled */
1555             continue;
1556 #else
1557             thisopt = SSL_PROTOCOL_SSLV3;
1558 #endif
1559         }
1560         else if (strcEQ(w, "TLSv1")) {
1561             thisopt = SSL_PROTOCOL_TLSV1;
1562         }
1563 #ifdef HAVE_TLSV1_X
1564         else if (strcEQ(w, "TLSv1.1")) {
1565             thisopt = SSL_PROTOCOL_TLSV1_1;
1566         }
1567         else if (strcEQ(w, "TLSv1.2")) {
1568             thisopt = SSL_PROTOCOL_TLSV1_2;
1569         }
1570         else if (SSL_HAVE_PROTOCOL_TLSV1_3 && strcEQ(w, "TLSv1.3")) {
1571             thisopt = SSL_PROTOCOL_TLSV1_3;
1572         }
1573 #endif
1574         else if (strcEQ(w, "all")) {
1575             thisopt = SSL_PROTOCOL_ALL;
1576         }
1577         else {
1578             return apr_pstrcat(parms->temp_pool,
1579                                parms->cmd->name,
1580                                ": Illegal protocol '", w, "'", NULL);
1581         }
1582
1583         if (action == '-') {
1584             *options &= ~thisopt;
1585         }
1586         else if (action == '+') {
1587             *options |= thisopt;
1588         }
1589         else {
1590             if (*options != SSL_PROTOCOL_NONE) {
1591                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, parms->server, APLOGNO(02532)
1592                              "%s: Protocol '%s' overrides already set parameter(s). "
1593                              "Check if a +/- prefix is missing.",
1594                              parms->cmd->name, w);
1595             }
1596             *options = thisopt;
1597         }
1598     }
1599
1600     return NULL;
1601 }
1602
1603 const char *ssl_cmd_SSLProtocol(cmd_parms *cmd,
1604                                 void *dcfg,
1605                                 const char *arg)
1606 {
1607     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1608
1609     sc->server->protocol_set = 1;
1610     return ssl_cmd_protocol_parse(cmd, arg, &sc->server->protocol);
1611 }
1612
1613 const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag)
1614 {
1615     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1616
1617     dc->proxy_enabled = flag ? TRUE : FALSE;
1618
1619     return NULL;
1620 }
1621
1622 const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cmd,
1623                                      void *dcfg,
1624                                      const char *arg)
1625 {
1626     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1627
1628     dc->proxy->protocol_set = 1;
1629     return ssl_cmd_protocol_parse(cmd, arg, &dc->proxy->protocol);
1630 }
1631
1632 const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
1633                                         void *dcfg,
1634                                         const char *arg1, const char *arg2)
1635 {
1636     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1637     
1638     if (arg2 == NULL) {
1639         arg2 = arg1;
1640         arg1 = "SSL";
1641     }
1642     
1643     if (!strcmp("SSL", arg1)) {
1644         /* always disable null and export ciphers */
1645         arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
1646         dc->proxy->auth.cipher_suite = arg2;
1647         return NULL;
1648     }
1649 #ifdef SSL_OP_NO_TLSv1_3
1650     else if (!strcmp("TLSv1.3", arg1)) {
1651         dc->proxy->auth.tls13_ciphers = arg2;
1652         return NULL;
1653     }
1654 #endif
1655     return apr_pstrcat(cmd->pool, "procotol '", arg1, "' not supported", NULL);
1656 }
1657
1658 const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd,
1659                                    void *dcfg,
1660                                    const char *arg)
1661 {
1662     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1663     ssl_verify_t mode = SSL_CVERIFY_NONE;
1664     const char *err;
1665
1666     if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) {
1667         return err;
1668     }
1669
1670     dc->proxy->auth.verify_mode = mode;
1671
1672     return NULL;
1673 }
1674
1675 const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd,
1676                                         void *dcfg,
1677                                         const char *arg)
1678 {
1679     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1680     int depth;
1681     const char *err;
1682
1683     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
1684         return err;
1685     }
1686
1687     dc->proxy->auth.verify_depth = depth;
1688
1689     return NULL;
1690 }
1691
1692 const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *cmd,
1693                                               void *dcfg,
1694                                               const char *arg)
1695 {
1696     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1697     const char *err;
1698
1699     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1700         return err;
1701     }
1702
1703     dc->proxy->auth.ca_cert_file = arg;
1704
1705     return NULL;
1706 }
1707
1708 const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *cmd,
1709                                               void *dcfg,
1710                                               const char *arg)
1711 {
1712     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1713     const char *err;
1714
1715     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1716         return err;
1717     }
1718
1719     dc->proxy->auth.ca_cert_path = arg;
1720
1721     return NULL;
1722 }
1723
1724 const char *ssl_cmd_SSLProxyCARevocationPath(cmd_parms *cmd,
1725                                              void *dcfg,
1726                                              const char *arg)
1727 {
1728     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1729     const char *err;
1730
1731     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1732         return err;
1733     }
1734
1735     dc->proxy->crl_path = arg;
1736
1737     return NULL;
1738 }
1739
1740 const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *cmd,
1741                                              void *dcfg,
1742                                              const char *arg)
1743 {
1744     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1745     const char *err;
1746
1747     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1748         return err;
1749     }
1750
1751     dc->proxy->crl_file = arg;
1752
1753     return NULL;
1754 }
1755
1756 const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd,
1757                                               void *dcfg,
1758                                               const char *arg)
1759 {
1760     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1761
1762     return ssl_cmd_crlcheck_parse(cmd, arg, &dc->proxy->crl_check_mask);
1763 }
1764
1765 const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
1766                                                    void *dcfg,
1767                                                    const char *arg)
1768 {
1769     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1770     const char *err;
1771
1772     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1773         return err;
1774     }
1775
1776     dc->proxy->pkp->cert_file = arg;
1777
1778     return NULL;
1779 }
1780
1781 const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd,
1782                                                    void *dcfg,
1783                                                    const char *arg)
1784 {
1785     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1786     const char *err;
1787
1788     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1789         return err;
1790     }
1791
1792     dc->proxy->pkp->cert_path = arg;
1793
1794     return NULL;
1795 }
1796
1797 const char *ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms *cmd,
1798                                                    void *dcfg,
1799                                                    const char *arg)
1800 {
1801     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1802     const char *err;
1803
1804     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1805         return err;
1806     }
1807
1808     dc->proxy->pkp->ca_cert_file = arg;
1809
1810     return NULL;
1811 }
1812
1813 const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg,
1814                                 const char *arg)
1815 {
1816     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1817     dc->szUserName = arg;
1818     return NULL;
1819 }
1820
1821 static const char *ssl_cmd_ocspcheck_parse(cmd_parms *parms,
1822                                            const char *arg,
1823                                            int *mask)
1824 {
1825     const char *w;
1826
1827     w = ap_getword_conf(parms->temp_pool, &arg);
1828     if (strcEQ(w, "off")) {
1829         *mask = SSL_OCSPCHECK_NONE;
1830     }
1831     else if (strcEQ(w, "leaf")) {
1832         *mask = SSL_OCSPCHECK_LEAF;
1833     }
1834     else if (strcEQ(w, "on")) {
1835         *mask = SSL_OCSPCHECK_CHAIN;
1836     }
1837     else {
1838         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1839                            ": Invalid argument '", w, "'",
1840                            NULL);
1841     }
1842
1843     while (*arg) {
1844         w = ap_getword_conf(parms->temp_pool, &arg);
1845         if (strcEQ(w, "no_ocsp_for_cert_ok")) {
1846             *mask |= SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK;
1847         }
1848         else {
1849             return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1850                                ": Invalid argument '", w, "'",
1851                                NULL);
1852         }
1853     }
1854
1855     return NULL;
1856 }
1857
1858 const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg)
1859 {
1860     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1861
1862 #ifdef OPENSSL_NO_OCSP
1863     if (flag) {
1864         return "OCSP support disabled in SSL library; cannot enable "
1865             "OCSP validation";
1866     }
1867 #endif
1868
1869     return ssl_cmd_ocspcheck_parse(cmd, arg, &sc->server->ocsp_mask);
1870 }
1871
1872 const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag)
1873 {
1874     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1875
1876     sc->server->ocsp_force_default = flag ? TRUE : FALSE;
1877
1878     return NULL;
1879 }
1880
1881 const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg)
1882 {
1883     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1884
1885     sc->server->ocsp_responder = arg;
1886
1887     return NULL;
1888 }
1889
1890 const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg)
1891 {
1892     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1893     sc->server->ocsp_resptime_skew = atoi(arg);
1894     if (sc->server->ocsp_resptime_skew < 0) {
1895         return "SSLOCSPResponseTimeSkew: invalid argument";
1896     }
1897     return NULL;
1898 }
1899
1900 const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg)
1901 {
1902     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1903     sc->server->ocsp_resp_maxage = atoi(arg);
1904     if (sc->server->ocsp_resp_maxage < 0) {
1905         return "SSLOCSPResponseMaxAge: invalid argument";
1906     }
1907     return NULL;
1908 }
1909
1910 const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg)
1911 {
1912     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1913     sc->server->ocsp_responder_timeout = apr_time_from_sec(atoi(arg));
1914     if (sc->server->ocsp_responder_timeout < 0) {
1915         return "SSLOCSPResponderTimeout: invalid argument";
1916     }
1917     return NULL;
1918 }
1919
1920 const char *ssl_cmd_SSLOCSPUseRequestNonce(cmd_parms *cmd, void *dcfg, int flag)
1921 {
1922     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1923
1924     sc->server->ocsp_use_request_nonce = flag ? TRUE : FALSE;
1925
1926     return NULL;
1927 }
1928
1929 const char *ssl_cmd_SSLOCSPProxyURL(cmd_parms *cmd, void *dcfg,
1930                                     const char *arg)
1931 {
1932     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1933     sc->server->proxy_uri = apr_palloc(cmd->pool, sizeof(apr_uri_t));
1934     if (apr_uri_parse(cmd->pool, arg, sc->server->proxy_uri) != APR_SUCCESS) {
1935         return apr_psprintf(cmd->pool,
1936                             "SSLOCSPProxyURL: Cannot parse URL %s", arg);
1937     }
1938     return NULL;
1939 }
1940
1941 /* Set OCSP responder certificate verification directive */
1942 const char *ssl_cmd_SSLOCSPNoVerify(cmd_parms *cmd, void *dcfg, int flag)
1943 {
1944     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1945
1946     sc->server->ocsp_noverify = flag ? TRUE : FALSE;
1947
1948     return NULL;
1949 }
1950
1951 const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag)
1952 {
1953     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1954
1955     dc->proxy->ssl_check_peer_expire = flag ? TRUE : FALSE;
1956
1957     return NULL;
1958 }
1959
1960 const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag)
1961 {
1962     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1963
1964     dc->proxy->ssl_check_peer_cn = flag ? TRUE : FALSE;
1965
1966     return NULL;
1967 }
1968
1969 const char *ssl_cmd_SSLProxyCheckPeerName(cmd_parms *cmd, void *dcfg, int flag)
1970 {
1971     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1972
1973     dc->proxy->ssl_check_peer_name = flag ? TRUE : FALSE;
1974
1975     return NULL;
1976 }
1977
1978 const char  *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag)
1979 {
1980 #ifdef HAVE_TLSEXT
1981     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1982
1983     sc->strict_sni_vhost_check = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
1984
1985     return NULL;
1986 #else
1987     return "SSLStrictSNIVHostCheck failed; OpenSSL is not built with support "
1988            "for TLS extensions and SNI indication. Refer to the "
1989            "documentation, and build a compatible version of OpenSSL.";
1990 #endif
1991 }
1992
1993 #ifdef HAVE_OCSP_STAPLING
1994
1995 const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd,
1996                                     void *dcfg,
1997                                     const char *arg)
1998 {
1999     SSLModConfigRec *mc = myModConfig(cmd->server);
2000     const char *err, *sep, *name;
2001
2002     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
2003         return err;
2004     }
2005     if (!mc) {
2006         return "SSLStaplingCache: cannot be used inside SSLPolicyDefine";
2007     }
2008
2009     /* Argument is of form 'name:args' or just 'name'. */
2010     sep = ap_strchr_c(arg, ':');
2011     if (sep) {
2012         name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
2013         sep++;
2014     }
2015     else {
2016         name = arg;
2017     }
2018
2019     /* Find the provider of given name. */
2020     mc->stapling_cache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
2021                                             name,
2022                                             AP_SOCACHE_PROVIDER_VERSION);
2023     if (mc->stapling_cache) {
2024         /* Cache found; create it, passing anything beyond the colon. */
2025         err = mc->stapling_cache->create(&mc->stapling_cache_context,
2026                                          sep, cmd->temp_pool,
2027                                          cmd->pool);
2028     }
2029     else {
2030         apr_array_header_t *name_list;
2031         const char *all_names;
2032
2033         /* Build a comma-separated list of all registered provider
2034          * names: */
2035         name_list = ap_list_provider_names(cmd->pool,
2036                                            AP_SOCACHE_PROVIDER_GROUP,
2037                                            AP_SOCACHE_PROVIDER_VERSION);
2038         all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
2039
2040         err = apr_psprintf(cmd->pool, "'%s' stapling cache not supported "
2041                            "(known names: %s) Maybe you need to load the "
2042                            "appropriate socache module (mod_socache_%s?)",
2043                            name, all_names, name);
2044     }
2045
2046     if (err) {
2047         return apr_psprintf(cmd->pool, "SSLStaplingCache: %s", err);
2048     }
2049
2050     return NULL;
2051 }
2052
2053 const char *ssl_cmd_SSLUseStapling(cmd_parms *cmd, void *dcfg, int flag)
2054 {
2055     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2056     sc->server->stapling_enabled = flag ? TRUE : FALSE;
2057     return NULL;
2058 }
2059
2060 const char *ssl_cmd_SSLStaplingResponseTimeSkew(cmd_parms *cmd, void *dcfg,
2061                                                     const char *arg)
2062 {
2063     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2064     sc->server->stapling_resptime_skew = atoi(arg);
2065     if (sc->server->stapling_resptime_skew < 0) {
2066         return "SSLStaplingResponseTimeSkew: invalid argument";
2067     }
2068     return NULL;
2069 }
2070
2071 const char *ssl_cmd_SSLStaplingResponseMaxAge(cmd_parms *cmd, void *dcfg,
2072                                                     const char *arg)
2073 {
2074     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2075     sc->server->stapling_resp_maxage = atoi(arg);
2076     if (sc->server->stapling_resp_maxage < 0) {
2077         return "SSLStaplingResponseMaxAge: invalid argument";
2078     }
2079     return NULL;
2080 }
2081
2082 const char *ssl_cmd_SSLStaplingStandardCacheTimeout(cmd_parms *cmd, void *dcfg,
2083                                                     const char *arg)
2084 {
2085     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2086     sc->server->stapling_cache_timeout = atoi(arg);
2087     if (sc->server->stapling_cache_timeout < 0) {
2088         return "SSLStaplingStandardCacheTimeout: invalid argument";
2089     }
2090     return NULL;
2091 }
2092
2093 const char *ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms *cmd, void *dcfg,
2094                                                  const char *arg)
2095 {
2096     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2097     sc->server->stapling_errcache_timeout = atoi(arg);
2098     if (sc->server->stapling_errcache_timeout < 0) {
2099         return "SSLStaplingErrorCacheTimeout: invalid argument";
2100     }
2101     return NULL;
2102 }
2103
2104 const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *cmd,
2105                                                      void *dcfg, int flag)
2106 {
2107     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2108     sc->server->stapling_return_errors = flag ? TRUE : FALSE;
2109     return NULL;
2110 }
2111
2112 const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *cmd,
2113                                             void *dcfg, int flag)
2114 {
2115     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2116     sc->server->stapling_fake_trylater = flag ? TRUE : FALSE;
2117     return NULL;
2118 }
2119
2120 const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *cmd, void *dcfg,
2121                                                 const char *arg)
2122 {
2123     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2124     sc->server->stapling_responder_timeout = atoi(arg);
2125     sc->server->stapling_responder_timeout *= APR_USEC_PER_SEC;
2126     if (sc->server->stapling_responder_timeout < 0) {
2127         return "SSLStaplingResponderTimeout: invalid argument";
2128     }
2129     return NULL;
2130 }
2131
2132 const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg,
2133                                         const char *arg)
2134 {
2135     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2136     sc->server->stapling_force_url = arg;
2137     return NULL;
2138 }
2139
2140 #endif /* HAVE_OCSP_STAPLING */
2141
2142 #ifdef HAVE_SSL_CONF_CMD
2143 const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg,
2144                                       const char *arg1, const char *arg2)
2145 {
2146     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2147     SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
2148     int value_type = SSL_CONF_cmd_value_type(cctx, arg1);
2149     const char *err;
2150     ssl_ctx_param_t *param;
2151
2152     if (value_type == SSL_CONF_TYPE_UNKNOWN) {
2153         return apr_psprintf(cmd->pool,
2154                             "'%s': invalid OpenSSL configuration command",
2155                             arg1);
2156     }
2157
2158     if (value_type == SSL_CONF_TYPE_FILE) {
2159         if ((err = ssl_cmd_check_file(cmd, &arg2)))
2160             return err;
2161     }
2162     else if (value_type == SSL_CONF_TYPE_DIR) {
2163         if ((err = ssl_cmd_check_dir(cmd, &arg2)))
2164             return err;
2165     }
2166
2167     if (strcEQ(arg1, "CipherString")) {
2168         /* always disable null and export ciphers */
2169         arg2 = apr_pstrcat(cmd->pool, arg2, ":!aNULL:!eNULL:!EXP", NULL);
2170     }
2171
2172     param = apr_array_push(sc->server->ssl_ctx_param);
2173     param->name = arg1;
2174     param->value = arg2;
2175     return NULL;
2176 }
2177 #endif
2178
2179 #ifdef HAVE_SRP
2180
2181 const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
2182                                        const char *arg)
2183 {
2184     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2185     const char *err;
2186
2187     if ((err = ssl_cmd_check_file(cmd, &arg)))
2188         return err;
2189     /* SRP_VBASE_init takes char*, not const char*  */
2190     sc->server->srp_vfile = apr_pstrdup(cmd->pool, arg);
2191     return NULL;
2192 }
2193
2194 const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg,
2195                                           const char *arg)
2196 {
2197     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2198     /* SRP_VBASE_new takes char*, not const char*  */
2199     sc->server->srp_unknown_user_seed = apr_pstrdup(cmd->pool, arg);
2200     return NULL;
2201 }
2202
2203 #endif /* HAVE_SRP */
2204
2205 /* OCSP Responder File Function to read in value */
2206 const char *ssl_cmd_SSLOCSPResponderCertificateFile(cmd_parms *cmd, void *dcfg, 
2207                                            const char *arg)
2208 {
2209     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
2210     const char *err;
2211
2212     if ((err = ssl_cmd_check_file(cmd, &arg))) {
2213         return err;
2214     }
2215
2216     sc->server->ocsp_certs_file = arg;
2217     return NULL;
2218 }
2219
2220 static void ssl_srv_dump(SSLSrvConfigRec *sc, apr_pool_t *p, 
2221                             apr_file_t *out, const char *indent, const char **psep);
2222 static void ssl_policy_dump(SSLPolicyRec *policy, apr_pool_t *p, 
2223                             apr_file_t *out, const char *indent);
2224
2225 void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
2226 {
2227     apr_file_t *out = NULL;
2228     if (ap_exists_config_define("DUMP_CERTS") &&
2229         ap_exists_config_define("DUMP_CA_CERTS")) {
2230         return;
2231     }
2232
2233     if (ap_exists_config_define("DUMP_CERTS")) {
2234         apr_file_open_stdout(&out, pconf);
2235         apr_file_printf(out, "Server certificates:\n");
2236
2237         /* Dump the filenames of all configured server certificates to
2238         * stdout. */
2239         while (s) {
2240             SSLSrvConfigRec *sc = mySrvConfig(s);
2241
2242             if (sc && sc->server && sc->server->pks) {
2243                 modssl_pk_server_t *const pks = sc->server->pks;
2244                 int i;
2245
2246                 for (i = 0; (i < pks->cert_files->nelts) &&
2247                             APR_ARRAY_IDX(pks->cert_files, i, const char *);
2248                      i++) {
2249                     apr_file_printf(out, "  %s\n",
2250                                     APR_ARRAY_IDX(pks->cert_files,
2251                                                   i, const char *));
2252                 }
2253             }
2254
2255             s = s->next;
2256         }
2257         return;
2258     }
2259
2260     if (ap_exists_config_define("DUMP_CA_CERTS")) {
2261         apr_file_open_stdout(&out, pconf);
2262         apr_file_printf(out, "Server CA certificates:\n");
2263
2264         /* Dump the filenames of all configured server CA certificates to
2265         * stdout. */
2266         while (s) {
2267             SSLSrvConfigRec *sc = mySrvConfig(s);
2268
2269             if (sc && sc->server) {
2270                 if (sc->server->auth.ca_cert_path) {
2271                     apr_file_printf(out, "  %s\n",
2272                                     sc->server->auth.ca_cert_path);
2273                 }
2274                 if (sc->server->auth.ca_cert_file) {
2275                     apr_file_printf(out, "  %s\n",
2276                                     sc->server->auth.ca_cert_file);
2277                 }
2278             }
2279
2280             s = s->next;
2281         }
2282         return;
2283     }
2284
2285     if (ap_exists_config_define("DUMP_SSL_POLICIES")) {
2286         apr_array_header_t *names = get_policy_names(pconf, 1);
2287         SSLPolicyRec *policy;
2288         const char *name, *sep = "";
2289         int i;
2290         
2291         apr_file_open_stdout(&out, pconf);
2292         apr_file_printf(out, "SSLPolicies: {");
2293         for (i = 0; i < names->nelts; ++i) {
2294             name = APR_ARRAY_IDX(names, i, const char*);
2295             policy = ssl_policy_lookup(pconf, name);
2296             if (policy) {
2297                 apr_file_printf(out, "%s\n  \"%s\": {", sep, name);
2298                 sep = ", ";
2299                 ssl_policy_dump(policy, pconf, out, "    ");
2300                 apr_file_printf(out, "\n  }");
2301             }
2302         }
2303         apr_file_printf(out, "\n}\n");
2304         return;
2305     }
2306 }
2307
2308 /*  _________________________________________________________________
2309 **
2310 **  Dump Config Data
2311 **  _________________________________________________________________
2312 */
2313
2314 static const char *json_quote(const char *s, apr_pool_t *p)
2315 {
2316     const char *src, *dq = s;
2317     int n = 0;
2318     
2319     while ((dq = ap_strchr_c(dq, '\"'))) {
2320         ++n;
2321         ++dq;
2322     }
2323     if (n > 0) {
2324         char *dst, c;
2325         src = s;
2326         s = dst = apr_pcalloc(p, strlen(s) + n + 1);
2327         while ((c = *src++)) {
2328             if (c == '\"') {
2329                 *dst++ = '\\';
2330             }
2331             *dst++ = c;
2332         }
2333     }
2334     return s;
2335 }
2336
2337 static void val_str_dump(apr_file_t *out, const char *key, const char *val, 
2338                          apr_pool_t *p, const char *indent, const char **psep)
2339 {
2340     if (val) {
2341         /* TODO: JSON quite string val */
2342         apr_file_printf(out, "%s\n%s\"%s\": \"%s\"", *psep, indent, key, json_quote(val, p));
2343         *psep = ", ";
2344     }
2345 }
2346
2347 static void val_str_array_dump(apr_file_t *out, const char *key, apr_array_header_t *val, 
2348                                apr_pool_t *p, const char *indent, const char **psep)
2349 {
2350     if (val && val->nelts > 0) {
2351         const char *s; 
2352         int i;
2353         
2354         for (i = 0; i < val->nelts; ++i) {
2355             s = APR_ARRAY_IDX(val, i, const char*);
2356             val_str_dump(out, key, s, p, indent, psep);
2357         }
2358     }
2359 }
2360
2361 static void val_long_dump(apr_file_t *out, const char *key, long val, 
2362                           apr_pool_t *p, const char *indent, const char **psep)
2363 {
2364     if (val != UNSET) {
2365         apr_file_printf(out, "%s\n%s\"%s\": %ld", *psep, indent, key, val);
2366         *psep = ", ";
2367     }
2368 }
2369
2370 static void val_itime_dump(apr_file_t *out, const char *key, apr_interval_time_t val, 
2371                            apr_pool_t *p, const char *indent, const char **psep)
2372 {
2373     if (val != UNSET) {
2374         apr_file_printf(out, "%s\n%s\"%s\": %f", *psep, indent, key, 
2375                         ((double)val/APR_USEC_PER_SEC));
2376         *psep = ", ";
2377     }
2378 }
2379
2380 static void val_onoff_dump(apr_file_t *out, const char *key, BOOL val, 
2381                            apr_pool_t *p, const char *indent, const char **psep)
2382 {
2383     if (val != UNSET) {
2384         val_str_dump(out, key, val? "on" : "off", p, indent, psep);
2385     }
2386 }
2387
2388 static void val_uri_dump(apr_file_t *out, const char *key, apr_uri_t *val, 
2389                          apr_pool_t *p, const char *indent, const char **psep)
2390 {
2391     if (val) {
2392         val_str_dump(out, key, apr_uri_unparse(p, val, 0), p, indent, psep);
2393     }
2394 }
2395
2396 static void val_verify_dump(apr_file_t *out, const char *key, ssl_verify_t mode, 
2397                             apr_pool_t *p, const char *indent, const char **psep)
2398 {
2399     switch (mode) {
2400         case SSL_CVERIFY_NONE:
2401             val_str_dump(out, key, "none", p, indent, psep);
2402             return;
2403         case SSL_CVERIFY_OPTIONAL:
2404             val_str_dump(out, key, "optional", p, indent, psep);
2405             return;
2406         case SSL_CVERIFY_REQUIRE:
2407             val_str_dump(out, key, "require", p, indent, psep);
2408             return;
2409         case SSL_CVERIFY_OPTIONAL_NO_CA:
2410             val_str_dump(out, key, "optional_no_ca", p, indent, psep);
2411             return;
2412         default:
2413             return;
2414     }
2415 }
2416
2417 static void val_enabled_dump(apr_file_t *out, const char *key, ssl_enabled_t val, 
2418                              apr_pool_t *p, const char *indent, const char **psep)
2419 {
2420     switch (val) {
2421         case SSL_ENABLED_FALSE:
2422             val_str_dump(out, key, "off", p, indent, psep);
2423             return;
2424         case SSL_ENABLED_TRUE:
2425             val_str_dump(out, key, "on", p, indent, psep);
2426             return;
2427         case SSL_ENABLED_OPTIONAL:
2428             val_str_dump(out, key, "optional", p, indent, psep);
2429             return;
2430         default:                   
2431             return;
2432     }
2433 }
2434
2435 static void val_pphrase_dump(apr_file_t *out, const char *key, 
2436                              ssl_pphrase_t pphrase_type, const char *path, 
2437                              apr_pool_t *p, const char *indent, const char **psep)
2438 {
2439     switch (pphrase_type) {
2440         case SSL_PPTYPE_BUILTIN: 
2441             val_str_dump(out, key, "builtin", p, indent, psep);
2442             return;
2443         case SSL_PPTYPE_FILTER: 
2444             val_str_dump(out, key, apr_pstrcat(p, "|", path, NULL), p, indent, psep);
2445             return;
2446         case SSL_PPTYPE_PIPE: 
2447             val_str_dump(out, key, apr_pstrcat(p, "exec:", path, NULL), p, indent, psep);
2448             return;
2449         default:
2450             return;
2451     }
2452 }
2453
2454 static void val_crl_check_dump(apr_file_t *out, const char *key, int mask, 
2455                                apr_pool_t *p, const char *indent, const char **psep)
2456 {
2457     if (mask != UNSET) {
2458         if (mask == SSL_CRLCHECK_NONE) {
2459             val_str_dump(out, key, "none", p, indent, psep);
2460         }
2461         else if (mask == SSL_CRLCHECK_LEAF) {
2462             val_str_dump(out, key, "leaf", p, indent, psep);
2463         }
2464         else if (mask == SSL_CRLCHECK_CHAIN) {
2465             val_str_dump(out, key, "chain", p, indent, psep);
2466         }
2467         else if (mask == (SSL_CRLCHECK_CHAIN|SSL_CRLCHECK_NO_CRL_FOR_CERT_OK)) {
2468             val_str_dump(out, key, "chain no_crl_for_cert_ok", p, indent, psep);
2469         }
2470         else {
2471             val_str_dump(out, key, "???", p, indent, psep);
2472         }
2473     }
2474 }
2475
2476 static const char *protocol_str(ssl_proto_t proto, apr_pool_t *p)
2477 {
2478     if (SSL_PROTOCOL_NONE == proto) {
2479         return "none";
2480     }
2481     else if (SSL_PROTOCOL_ALL == proto) {
2482         return "all";
2483     }
2484     else {
2485         /* icing: I think it is nuts that we define our own IETF protocol constants
2486          * only whent the linked *SSL lib supports them. */
2487         apr_array_header_t *names = apr_array_make(p, 5, sizeof(const char*));
2488         if ((1<<4) & proto) {
2489             APR_ARRAY_PUSH(names, const char*) = "+TLSv1.2";
2490         }
2491         if ((1<<3) & proto) {
2492             APR_ARRAY_PUSH(names, const char*) = "+TLSv1.1";
2493         }
2494         if ((1<<2) & proto) {
2495             APR_ARRAY_PUSH(names, const char*) = "+TLSv1.0";
2496         }
2497         if ((1<<1) & proto) {
2498             APR_ARRAY_PUSH(names, const char*) = "+SSLv3";
2499         }
2500         return apr_array_pstrcat(p, names, ' ');
2501     }
2502 }
2503
2504 #define DMP_STRING(k,v) \
2505     val_str_dump(out, k, v, p, indent, psep)
2506 #define DMP_LONG(k,v) \
2507     val_long_dump(out, k, v, p, indent, psep)
2508 #define DMP_ITIME(k,v) \
2509     val_itime_dump(out, k, v, p, indent, psep)
2510 #define DMP_STRARR(k,v) \
2511     val_str_array_dump(out, k, v, p, indent, psep)
2512 #define DMP_VERIFY(k,v) \
2513     val_verify_dump(out, k, v, p, indent, psep)
2514 #define DMP_ON_OFF(k,v) \
2515     val_onoff_dump(out, k, v, p, indent, psep)
2516 #define DMP_URI(k,v) \
2517     val_uri_dump(out, k, v, p, indent, psep)
2518 #define DMP_CRLCHK(k,v) \
2519     val_crl_check_dump(out, k, v, p, indent, psep)
2520 #define DMP_PHRASE(k,v, v2) \
2521     val_pphrase_dump(out, k, v, v2, p, indent, psep)
2522 #define DMP_ENABLD(k,v) \
2523     val_enabled_dump(out, k, v, p, indent, psep)
2524 #define DMP_OPTION(n,v) \
2525     val_option_dump(out, "SSLOption", n, v, \
2526                     dc->nOptions, dc->nOptionsAdd, dc->nOptionsDel, p, indent, psep);
2527
2528 static void modssl_auth_ctx_dump(modssl_auth_ctx_t *auth, apr_pool_t *p, int proxy,
2529                                  apr_file_t *out, const char *indent, const char **psep)
2530 {
2531     DMP_STRING(proxy? "SSLProxyCipherSuite" : "SSLCipherSuite", auth->cipher_suite);
2532 #ifdef SSL_OP_NO_TLSv1_3
2533     if (auth->tls13_ciphers) {
2534         DMP_STRING(proxy? "SSLProxyCipherSuite" : "SSLCipherSuite", 
2535             apr_pstrcat(p, "TLSv1.3 ", auth->tls13_ciphers, NULL));
2536     }
2537 #endif
2538     DMP_VERIFY(proxy? "SSLProxyVerify" : "SSLVerifyClient", auth->verify_mode);
2539     DMP_LONG(  proxy? "SSLProxyVerify" : "SSLVerifyDepth", auth->verify_depth);
2540     DMP_STRING(proxy? "SSLProxyCACertificateFile" : "SSLCACertificateFile", auth->ca_cert_file);
2541     DMP_STRING(proxy? "SSLProxyCACertificatePath" : "SSLCACertificatePath", auth->ca_cert_path);
2542 }
2543
2544 static void modssl_ctx_dump(modssl_ctx_t *ctx, apr_pool_t *p, int proxy,
2545                             apr_file_t *out, const char *indent, const char **psep)
2546 {
2547 #ifdef HAVE_SSL_CONF_CMD
2548     int i;
2549 #endif
2550
2551     if (ctx->protocol_set) {
2552         DMP_STRING(proxy? "SSLProxyProtocol" : "SSLProtocol", protocol_str(ctx->protocol, p));
2553     }
2554
2555     modssl_auth_ctx_dump(&ctx->auth, p, proxy, out, indent, psep);
2556
2557     DMP_STRING(proxy? "SSLProxyCARevocationFile" : "SSLCARevocationFile", ctx->crl_file);
2558     DMP_STRING(proxy? "SSLProxyCARevocationPath" : "SSLCARevocationPath", ctx->crl_path);
2559     DMP_CRLCHK(proxy? "SSLProxyCARevocationCheck" : "SSLCARevocationCheck", ctx->crl_check_mask);
2560     if (!proxy) {
2561         DMP_PHRASE("SSLPassPhraseDialog", ctx->pphrase_dialog_type, ctx->pphrase_dialog_path);
2562         if (ctx->pks) {
2563             DMP_STRING("SSLCADNRequestFile", ctx->pks->ca_name_file);
2564             DMP_STRING("SSLCADNRequestPath", ctx->pks->ca_name_path);
2565             DMP_STRARR("SSLCertificateFile", ctx->pks->cert_files);
2566             DMP_STRARR("SSLCertificateKeyFile", ctx->pks->key_files);
2567         }
2568 #ifdef HAVE_OCSP_STAPLING
2569         DMP_ON_OFF("SSLUseStapling", ctx->stapling_enabled);
2570         DMP_LONG(  "SSLStaplingResponseTimeSkew", ctx->stapling_resptime_skew);
2571         DMP_LONG(  "SSLStaplingResponseMaxAge", ctx->stapling_resp_maxage);
2572         DMP_LONG(  "SSLStaplingStandardCacheTimeout", ctx->stapling_cache_timeout);
2573         DMP_ON_OFF("SSLStaplingReturnResponderErrors", ctx->stapling_return_errors);
2574         DMP_ON_OFF("SSLStaplingFakeTryLater", ctx->stapling_fake_trylater);
2575         DMP_LONG(  "SSLStaplingErrorCacheTimeout", ctx->stapling_errcache_timeout);
2576         DMP_ITIME( "SSLStaplingResponderTimeout", ctx->stapling_responder_timeout);
2577         DMP_STRING("SSLStaplingForceURL", ctx->stapling_force_url);
2578 #endif /* if HAVE_OCSP_STAPLING */ 
2579
2580 #ifdef HAVE_SRP
2581         DMP_STRING("SSLSRPUnknownUserSeed", ctx->srp_unknown_user_seed);
2582         DMP_STRING("SSLSRPVerifierFile", ctx->srp_vfile);
2583 #endif
2584         DMP_LONG(  "SSLOCSPEnable", ctx->ocsp_mask);
2585         DMP_ON_OFF("SSLOCSPOverrideResponder", ctx->ocsp_force_default);
2586         DMP_STRING("SSLOCSPDefaultResponder", ctx->ocsp_responder);
2587         DMP_LONG(  "SSLOCSPResponseTimeSkew", ctx->ocsp_resptime_skew);
2588         DMP_LONG(  "SSLOCSPResponseMaxAge", ctx->ocsp_resp_maxage);
2589         DMP_ITIME( "SSLOCSPResponderTimeout", ctx->ocsp_responder_timeout);
2590         DMP_ON_OFF("SSLOCSPUseRequestNonce", ctx->ocsp_use_request_nonce);
2591         DMP_URI(   "SSLOCSPProxyURL", ctx->proxy_uri);
2592         DMP_ON_OFF("SSLOCSPNoVerify", ctx->ocsp_noverify);
2593         DMP_STRING("SSLOCSPResponderCertificateFile", ctx->ocsp_certs_file);
2594
2595 #ifdef HAVE_SSL_CONF_CMD
2596         if (ctx->ssl_ctx_param && ctx->ssl_ctx_param->nelts > 0) {
2597             ssl_ctx_param_t *param = (ssl_ctx_param_t *)ctx->ssl_ctx_param->elts;
2598             for (i = 0; i < ctx->ssl_ctx_param->nelts; ++i, ++param) {
2599                 apr_file_printf(out, "%s\n%s\"%s\": \"%s %s\"", *psep, indent, 
2600                                 "SSLOpenSSLConfCmd", json_quote(param->name, p), 
2601                                 json_quote(param->value, p));
2602                 *psep = ", ";
2603             }
2604         }
2605 #endif
2606
2607 #ifdef HAVE_TLS_SESSION_TICKETS
2608         if (ctx->ticket_key) {
2609             DMP_STRING("SSLSessionTicketKeyFile", ctx->ticket_key->file_path);
2610         }
2611 #endif
2612     }
2613     else { /* proxy */
2614         if (ctx->pkp) {
2615             DMP_STRING("SSLProxyMachineCertificateFile", ctx->pkp->cert_file);
2616             DMP_STRING("SSLProxyMachineCertificatePath", ctx->pkp->cert_path);
2617             DMP_STRING("SSLProxyMachineCertificateChainFile", ctx->pkp->ca_cert_file);
2618         }
2619         DMP_ON_OFF("SSLProxyCheckPeerCN", ctx->ssl_check_peer_cn);
2620         DMP_ON_OFF("SSLProxyCheckPeerName", ctx->ssl_check_peer_cn);
2621         DMP_ON_OFF("SSLProxyCheckPeerExpire", ctx->ssl_check_peer_expire);
2622     }
2623 }
2624
2625 static void ssl_srv_dump(SSLSrvConfigRec *sc, apr_pool_t *p, 
2626                             apr_file_t *out, const char *indent, const char **psep)
2627 {
2628     DMP_ENABLD("SSLEngine", sc->enabled);
2629     DMP_ON_OFF("SSLHonorCipherOrder", sc->cipher_server_pref);
2630
2631 #ifndef OPENSSL_NO_COMP
2632     DMP_ON_OFF("SSLCompression", sc->compression);
2633 #endif
2634
2635     modssl_ctx_dump(sc->server, p, 0, out, indent, psep);
2636
2637     DMP_LONG(  "SSLSessionCacheTimeout", sc->session_cache_timeout);
2638     DMP_ON_OFF("SSLInsecureRenegotiation", sc->insecure_reneg);
2639     DMP_ON_OFF("SSLStrictSNIVHostCheck", sc->strict_sni_vhost_check);
2640 #ifdef HAVE_FIPS
2641     DMP_ON_OFF("SSLFIPS", sc->fips);
2642 #endif
2643     DMP_ON_OFF("SSLSessionTickets", sc->session_tickets);
2644 }
2645
2646 static void ssl_policy_dump(SSLPolicyRec *policy, apr_pool_t *p, 
2647                             apr_file_t *out, const char *indent)
2648 {
2649     const char *sep = "";
2650     if (policy->sc) {
2651         ssl_srv_dump(policy->sc, p, out, indent, &sep);
2652     }
2653 }
2654
2655
2656