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 "ssl_private.h"
30 #include "util_mutex.h"
31 #include "ap_provider.h"
32 
33 /*  _________________________________________________________________
34 **
35 **  Support for Global Configuration
36 **  _________________________________________________________________
37 */
38 
39 #define SSL_MOD_CONFIG_KEY "ssl_module"
40 
ssl_config_global_create(server_rec * s)41 SSLModConfigRec *ssl_config_global_create(server_rec *s)
42 {
43     apr_pool_t *pool = s->process->pool;
44     SSLModConfigRec *mc;
45     void *vmc;
46 
47     apr_pool_userdata_get(&vmc, SSL_MOD_CONFIG_KEY, pool);
48     if (vmc) {
49         return vmc; /* reused for lifetime of the server */
50     }
51 
52     /*
53      * allocate an own subpool which survives server restarts
54      */
55     mc = (SSLModConfigRec *)apr_palloc(pool, sizeof(*mc));
56     mc->pPool = pool;
57     mc->bFixed = FALSE;
58 
59     /*
60      * initialize per-module configuration
61      */
62     mc->sesscache_mode         = SSL_SESS_CACHE_OFF;
63     mc->sesscache              = NULL;
64     mc->pMutex                 = NULL;
65     mc->aRandSeed              = apr_array_make(pool, 4,
66                                                 sizeof(ssl_randseed_t));
67     mc->tVHostKeys             = apr_hash_make(pool);
68     mc->tPrivateKey            = apr_hash_make(pool);
69     mc->tPublicCert            = apr_hash_make(pool);
70 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
71     mc->szCryptoDevice         = NULL;
72 #endif
73 #ifdef HAVE_OCSP_STAPLING
74     mc->stapling_cache         = NULL;
75     mc->stapling_mutex         = NULL;
76 #endif
77 
78     memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
79 
80     apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
81                           apr_pool_cleanup_null,
82                           pool);
83 
84     return mc;
85 }
86 
ssl_config_global_fix(SSLModConfigRec * mc)87 void ssl_config_global_fix(SSLModConfigRec *mc)
88 {
89     mc->bFixed = TRUE;
90 }
91 
ssl_config_global_isfixed(SSLModConfigRec * mc)92 BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
93 {
94     return mc->bFixed;
95 }
96 
97 /*  _________________________________________________________________
98 **
99 **  Configuration handling
100 **  _________________________________________________________________
101 */
102 
modssl_ctx_init(modssl_ctx_t * mctx)103 static void modssl_ctx_init(modssl_ctx_t *mctx)
104 {
105     mctx->sc                  = NULL; /* set during module init */
106 
107     mctx->ssl_ctx             = NULL; /* set during module init */
108 
109     mctx->pks                 = NULL;
110     mctx->pkp                 = NULL;
111 
112 #ifdef HAVE_TLS_SESSION_TICKETS
113     mctx->ticket_key          = NULL;
114 #endif
115 
116     mctx->protocol            = SSL_PROTOCOL_ALL;
117 
118     mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET;
119     mctx->pphrase_dialog_path = NULL;
120 
121     mctx->pkcs7               = NULL;
122     mctx->cert_chain          = NULL;
123 
124     mctx->crl_path            = NULL;
125     mctx->crl_file            = NULL;
126     mctx->crl_check_mode      = SSL_CRLCHECK_UNSET;
127 
128     mctx->auth.ca_cert_path   = NULL;
129     mctx->auth.ca_cert_file   = NULL;
130     mctx->auth.cipher_suite   = NULL;
131     mctx->auth.verify_depth   = UNSET;
132     mctx->auth.verify_mode    = SSL_CVERIFY_UNSET;
133 
134     mctx->ocsp_enabled        = FALSE;
135     mctx->ocsp_force_default  = FALSE;
136     mctx->ocsp_responder      = NULL;
137     mctx->ocsp_resptime_skew  = UNSET;
138     mctx->ocsp_resp_maxage    = UNSET;
139     mctx->ocsp_responder_timeout = UNSET;
140 
141 #ifdef HAVE_OCSP_STAPLING
142     mctx->stapling_enabled           = UNSET;
143     mctx->stapling_resptime_skew     = UNSET;
144     mctx->stapling_resp_maxage       = UNSET;
145     mctx->stapling_cache_timeout     = UNSET;
146     mctx->stapling_return_errors     = UNSET;
147     mctx->stapling_fake_trylater     = UNSET;
148     mctx->stapling_errcache_timeout  = UNSET;
149     mctx->stapling_responder_timeout = UNSET;
150     mctx->stapling_force_url         = NULL;
151 #endif
152 
153 #ifndef OPENSSL_NO_SRP
154     mctx->srp_vfile =             NULL;
155     mctx->srp_unknown_user_seed = NULL;
156     mctx->srp_vbase =             NULL;
157 #endif
158 }
159 
modssl_ctx_init_proxy(SSLSrvConfigRec * sc,apr_pool_t * p)160 static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
161                                   apr_pool_t *p)
162 {
163     modssl_ctx_t *mctx;
164 
165     mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy));
166 
167     modssl_ctx_init(mctx);
168 
169     mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp));
170 
171     mctx->pkp->cert_file = NULL;
172     mctx->pkp->cert_path = NULL;
173     mctx->pkp->ca_cert_file = NULL;
174     mctx->pkp->certs     = NULL;
175     mctx->pkp->ca_certs  = NULL;
176 }
177 
modssl_ctx_init_server(SSLSrvConfigRec * sc,apr_pool_t * p)178 static void modssl_ctx_init_server(SSLSrvConfigRec *sc,
179                                    apr_pool_t *p)
180 {
181     modssl_ctx_t *mctx;
182 
183     mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
184 
185     modssl_ctx_init(mctx);
186 
187     mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks));
188 
189     /* mctx->pks->... certs/keys are set during module init */
190 
191 #ifdef HAVE_TLS_SESSION_TICKETS
192     mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key));
193 #endif
194 }
195 
ssl_config_server_new(apr_pool_t * p)196 static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
197 {
198     SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
199 
200     sc->mc                     = NULL;
201     sc->enabled                = SSL_ENABLED_FALSE;
202     sc->proxy_enabled          = UNSET;
203     sc->vhost_id               = NULL;  /* set during module init */
204     sc->vhost_id_len           = 0;     /* set during module init */
205     sc->session_cache_timeout  = UNSET;
206     sc->cipher_server_pref     = UNSET;
207     sc->insecure_reneg         = UNSET;
208     sc->proxy_ssl_check_peer_expire = SSL_ENABLED_UNSET;
209     sc->proxy_ssl_check_peer_cn     = SSL_ENABLED_UNSET;
210     sc->proxy_ssl_check_peer_name   = SSL_ENABLED_UNSET;
211 #ifndef OPENSSL_NO_TLSEXT
212     sc->strict_sni_vhost_check = SSL_ENABLED_UNSET;
213 #endif
214 #ifdef HAVE_FIPS
215     sc->fips                   = UNSET;
216 #endif
217 #ifndef OPENSSL_NO_COMP
218     sc->compression            = UNSET;
219 #endif
220 
221     modssl_ctx_init_proxy(sc, p);
222 
223     modssl_ctx_init_server(sc, p);
224 
225     return sc;
226 }
227 
228 /*
229  *  Create per-server SSL configuration
230  */
ssl_config_server_create(apr_pool_t * p,server_rec * s)231 void *ssl_config_server_create(apr_pool_t *p, server_rec *s)
232 {
233     SSLSrvConfigRec *sc = ssl_config_server_new(p);
234 
235     sc->mc = ssl_config_global_create(s);
236 
237     return sc;
238 }
239 
240 #define cfgMerge(el,unset)  mrg->el = (add->el == (unset)) ? base->el : add->el
241 #define cfgMergeArray(el)   mrg->el = apr_array_append(p, add->el, base->el)
242 #define cfgMergeString(el)  cfgMerge(el, NULL)
243 #define cfgMergeBool(el)    cfgMerge(el, UNSET)
244 #define cfgMergeInt(el)     cfgMerge(el, UNSET)
245 
modssl_ctx_cfg_merge(modssl_ctx_t * base,modssl_ctx_t * add,modssl_ctx_t * mrg)246 static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
247                                  modssl_ctx_t *add,
248                                  modssl_ctx_t *mrg)
249 {
250     cfgMerge(protocol, SSL_PROTOCOL_ALL);
251 
252     cfgMerge(pphrase_dialog_type, SSL_PPTYPE_UNSET);
253     cfgMergeString(pphrase_dialog_path);
254 
255     cfgMergeString(cert_chain);
256 
257     cfgMerge(crl_path, NULL);
258     cfgMerge(crl_file, NULL);
259     cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET);
260 
261     cfgMergeString(auth.ca_cert_path);
262     cfgMergeString(auth.ca_cert_file);
263     cfgMergeString(auth.cipher_suite);
264     cfgMergeInt(auth.verify_depth);
265     cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET);
266 
267     cfgMergeBool(ocsp_enabled);
268     cfgMergeBool(ocsp_force_default);
269     cfgMerge(ocsp_responder, NULL);
270     cfgMergeInt(ocsp_resptime_skew);
271     cfgMergeInt(ocsp_resp_maxage);
272     cfgMergeInt(ocsp_responder_timeout);
273 #ifdef HAVE_OCSP_STAPLING
274     cfgMergeBool(stapling_enabled);
275     cfgMergeInt(stapling_resptime_skew);
276     cfgMergeInt(stapling_resp_maxage);
277     cfgMergeInt(stapling_cache_timeout);
278     cfgMergeBool(stapling_return_errors);
279     cfgMergeBool(stapling_fake_trylater);
280     cfgMergeInt(stapling_errcache_timeout);
281     cfgMergeInt(stapling_responder_timeout);
282     cfgMerge(stapling_force_url, NULL);
283 #endif
284 
285 #ifndef OPENSSL_NO_SRP
286     cfgMergeString(srp_vfile);
287     cfgMergeString(srp_unknown_user_seed);
288 #endif
289 }
290 
modssl_ctx_cfg_merge_proxy(modssl_ctx_t * base,modssl_ctx_t * add,modssl_ctx_t * mrg)291 static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base,
292                                        modssl_ctx_t *add,
293                                        modssl_ctx_t *mrg)
294 {
295     modssl_ctx_cfg_merge(base, add, mrg);
296 
297     cfgMergeString(pkp->cert_file);
298     cfgMergeString(pkp->cert_path);
299     cfgMergeString(pkp->ca_cert_file);
300 }
301 
modssl_ctx_cfg_merge_server(modssl_ctx_t * base,modssl_ctx_t * add,modssl_ctx_t * mrg)302 static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base,
303                                         modssl_ctx_t *add,
304                                         modssl_ctx_t *mrg)
305 {
306     int i;
307 
308     modssl_ctx_cfg_merge(base, add, mrg);
309 
310     for (i = 0; i < SSL_AIDX_MAX; i++) {
311         cfgMergeString(pks->cert_files[i]);
312         cfgMergeString(pks->key_files[i]);
313     }
314 
315     cfgMergeString(pks->ca_name_path);
316     cfgMergeString(pks->ca_name_file);
317 
318 #ifdef HAVE_TLS_SESSION_TICKETS
319     cfgMergeString(ticket_key->file_path);
320 #endif
321 }
322 
323 /*
324  *  Merge per-server SSL configurations
325  */
ssl_config_server_merge(apr_pool_t * p,void * basev,void * addv)326 void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
327 {
328     SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
329     SSLSrvConfigRec *add  = (SSLSrvConfigRec *)addv;
330     SSLSrvConfigRec *mrg  = ssl_config_server_new(p);
331 
332     cfgMerge(mc, NULL);
333     cfgMerge(enabled, SSL_ENABLED_UNSET);
334     cfgMergeBool(proxy_enabled);
335     cfgMergeInt(session_cache_timeout);
336     cfgMergeBool(cipher_server_pref);
337     cfgMergeBool(insecure_reneg);
338     cfgMerge(proxy_ssl_check_peer_expire, SSL_ENABLED_UNSET);
339     cfgMerge(proxy_ssl_check_peer_cn, SSL_ENABLED_UNSET);
340     cfgMerge(proxy_ssl_check_peer_name, SSL_ENABLED_UNSET);
341 #ifndef OPENSSL_NO_TLSEXT
342     cfgMerge(strict_sni_vhost_check, SSL_ENABLED_UNSET);
343 #endif
344 #ifdef HAVE_FIPS
345     cfgMergeBool(fips);
346 #endif
347 #ifndef OPENSSL_NO_COMP
348     cfgMergeBool(compression);
349 #endif
350 
351     modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
352 
353     modssl_ctx_cfg_merge_server(base->server, add->server, mrg->server);
354 
355     return mrg;
356 }
357 
358 /*
359  *  Create per-directory SSL configuration
360  */
ssl_config_perdir_create(apr_pool_t * p,char * dir)361 void *ssl_config_perdir_create(apr_pool_t *p, char *dir)
362 {
363     SSLDirConfigRec *dc = apr_palloc(p, sizeof(*dc));
364 
365     dc->bSSLRequired  = FALSE;
366     dc->aRequirement  = apr_array_make(p, 4, sizeof(ssl_require_t));
367     dc->nOptions      = SSL_OPT_NONE|SSL_OPT_RELSET;
368     dc->nOptionsAdd   = SSL_OPT_NONE;
369     dc->nOptionsDel   = SSL_OPT_NONE;
370 
371     dc->szCipherSuite          = NULL;
372     dc->nVerifyClient          = SSL_CVERIFY_UNSET;
373     dc->nVerifyDepth           = UNSET;
374 
375     dc->szCACertificatePath    = NULL;
376     dc->szCACertificateFile    = NULL;
377     dc->szUserName             = NULL;
378 
379     dc->nRenegBufferSize = UNSET;
380 
381     return dc;
382 }
383 
384 /*
385  *  Merge per-directory SSL configurations
386  */
ssl_config_perdir_merge(apr_pool_t * p,void * basev,void * addv)387 void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv)
388 {
389     SSLDirConfigRec *base = (SSLDirConfigRec *)basev;
390     SSLDirConfigRec *add  = (SSLDirConfigRec *)addv;
391     SSLDirConfigRec *mrg  = (SSLDirConfigRec *)apr_palloc(p, sizeof(*mrg));
392 
393     cfgMerge(bSSLRequired, FALSE);
394     cfgMergeArray(aRequirement);
395 
396     if (add->nOptions & SSL_OPT_RELSET) {
397         mrg->nOptionsAdd =
398             (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd;
399         mrg->nOptionsDel =
400             (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel;
401         mrg->nOptions    =
402             (base->nOptions    & ~(mrg->nOptionsDel)) | mrg->nOptionsAdd;
403     }
404     else {
405         mrg->nOptions    = add->nOptions;
406         mrg->nOptionsAdd = add->nOptionsAdd;
407         mrg->nOptionsDel = add->nOptionsDel;
408     }
409 
410     cfgMergeString(szCipherSuite);
411     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
412     cfgMergeInt(nVerifyDepth);
413 
414     cfgMergeString(szCACertificatePath);
415     cfgMergeString(szCACertificateFile);
416     cfgMergeString(szUserName);
417 
418     cfgMergeInt(nRenegBufferSize);
419 
420     return mrg;
421 }
422 
423 /*
424  *  Configuration functions for particular directives
425  */
426 
ssl_cmd_SSLPassPhraseDialog(cmd_parms * cmd,void * dcfg,const char * arg)427 const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd,
428                                         void *dcfg,
429                                         const char *arg)
430 {
431     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
432     const char *err;
433     int arglen = strlen(arg);
434 
435     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
436         return err;
437     }
438 
439     if (strcEQ(arg, "builtin")) {
440         sc->server->pphrase_dialog_type  = SSL_PPTYPE_BUILTIN;
441         sc->server->pphrase_dialog_path = NULL;
442     }
443     else if ((arglen > 5) && strEQn(arg, "exec:", 5)) {
444         sc->server->pphrase_dialog_type  = SSL_PPTYPE_FILTER;
445         sc->server->pphrase_dialog_path =
446             ap_server_root_relative(cmd->pool, arg+5);
447         if (!sc->server->pphrase_dialog_path) {
448             return apr_pstrcat(cmd->pool,
449                                "Invalid SSLPassPhraseDialog exec: path ",
450                                arg+5, NULL);
451         }
452         if (!ssl_util_path_check(SSL_PCM_EXISTS,
453                                  sc->server->pphrase_dialog_path,
454                                  cmd->pool))
455         {
456             return apr_pstrcat(cmd->pool,
457                                "SSLPassPhraseDialog: file '",
458                                sc->server->pphrase_dialog_path,
459                                "' does not exist", NULL);
460         }
461 
462     }
463     else if ((arglen > 1) && (arg[0] == '|')) {
464         sc->server->pphrase_dialog_type  = SSL_PPTYPE_PIPE;
465         sc->server->pphrase_dialog_path = arg + 1;
466     }
467     else {
468         return "SSLPassPhraseDialog: Invalid argument";
469     }
470 
471     return NULL;
472 }
473 
474 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
ssl_cmd_SSLCryptoDevice(cmd_parms * cmd,void * dcfg,const char * arg)475 const char *ssl_cmd_SSLCryptoDevice(cmd_parms *cmd,
476                                     void *dcfg,
477                                     const char *arg)
478 {
479     SSLModConfigRec *mc = myModConfig(cmd->server);
480     const char *err;
481     ENGINE *e;
482 
483     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
484         return err;
485     }
486 
487     if (strcEQ(arg, "builtin")) {
488         mc->szCryptoDevice = NULL;
489     }
490     else if ((e = ENGINE_by_id(arg))) {
491         mc->szCryptoDevice = arg;
492         ENGINE_free(e);
493     }
494     else {
495         err = "SSLCryptoDevice: Invalid argument; must be one of: "
496               "'builtin' (none)";
497         e = ENGINE_get_first();
498         while (e) {
499             err = apr_pstrcat(cmd->pool, err, ", '", ENGINE_get_id(e),
500                                          "' (", ENGINE_get_name(e), ")", NULL);
501             /* Iterate; this call implicitly decrements the refcount
502              * on the 'old' e, per the docs in engine.h. */
503             e = ENGINE_get_next(e);
504         }
505         return err;
506     }
507 
508     return NULL;
509 }
510 #endif
511 
ssl_cmd_SSLRandomSeed(cmd_parms * cmd,void * dcfg,const char * arg1,const char * arg2,const char * arg3)512 const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd,
513                                   void *dcfg,
514                                   const char *arg1,
515                                   const char *arg2,
516                                   const char *arg3)
517 {
518     SSLModConfigRec *mc = myModConfig(cmd->server);
519     const char *err;
520     ssl_randseed_t *seed;
521     int arg2len = strlen(arg2);
522 
523     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
524         return err;
525     }
526 
527     if (ssl_config_global_isfixed(mc)) {
528         return NULL;
529     }
530 
531     seed = apr_array_push(mc->aRandSeed);
532 
533     if (strcEQ(arg1, "startup")) {
534         seed->nCtx = SSL_RSCTX_STARTUP;
535     }
536     else if (strcEQ(arg1, "connect")) {
537         seed->nCtx = SSL_RSCTX_CONNECT;
538     }
539     else {
540         return apr_pstrcat(cmd->pool, "SSLRandomSeed: "
541                            "invalid context: `", arg1, "'",
542                            NULL);
543     }
544 
545     if ((arg2len > 5) && strEQn(arg2, "file:", 5)) {
546         seed->nSrc   = SSL_RSSRC_FILE;
547         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
548     }
549     else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) {
550         seed->nSrc   = SSL_RSSRC_EXEC;
551         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
552     }
553     else if ((arg2len > 4) && strEQn(arg2, "egd:", 4)) {
554         seed->nSrc   = SSL_RSSRC_EGD;
555         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+4);
556     }
557     else if (strcEQ(arg2, "builtin")) {
558         seed->nSrc   = SSL_RSSRC_BUILTIN;
559         seed->cpPath = NULL;
560     }
561     else {
562         seed->nSrc   = SSL_RSSRC_FILE;
563         seed->cpPath = ap_server_root_relative(mc->pPool, arg2);
564     }
565 
566     if (seed->nSrc != SSL_RSSRC_BUILTIN) {
567         if (!seed->cpPath) {
568             return apr_pstrcat(cmd->pool,
569                                "Invalid SSLRandomSeed path ",
570                                arg2, NULL);
571         }
572         if (!ssl_util_path_check(SSL_PCM_EXISTS, seed->cpPath, cmd->pool)) {
573             return apr_pstrcat(cmd->pool,
574                                "SSLRandomSeed: source path '",
575                                seed->cpPath, "' does not exist", NULL);
576         }
577     }
578 
579     if (!arg3) {
580         seed->nBytes = 0; /* read whole file */
581     }
582     else {
583         if (seed->nSrc == SSL_RSSRC_BUILTIN) {
584             return "SSLRandomSeed: byte specification not "
585                    "allowed for builtin seed source";
586         }
587 
588         seed->nBytes = atoi(arg3);
589 
590         if (seed->nBytes < 0) {
591             return "SSLRandomSeed: invalid number of bytes specified";
592         }
593     }
594 
595     return NULL;
596 }
597 
ssl_cmd_SSLEngine(cmd_parms * cmd,void * dcfg,const char * arg)598 const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
599 {
600     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
601 
602     if (!strcasecmp(arg, "On")) {
603         sc->enabled = SSL_ENABLED_TRUE;
604     return NULL;
605     }
606     else if (!strcasecmp(arg, "Off")) {
607         sc->enabled = SSL_ENABLED_FALSE;
608         return NULL;
609     }
610     else if (!strcasecmp(arg, "Optional")) {
611         sc->enabled = SSL_ENABLED_OPTIONAL;
612         return NULL;
613     }
614 
615     return "Argument must be On, Off, or Optional";
616 }
617 
ssl_cmd_SSLFIPS(cmd_parms * cmd,void * dcfg,int flag)618 const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag)
619 {
620 #ifdef HAVE_FIPS
621     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
622 #endif
623     const char *err;
624 
625     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
626         return err;
627     }
628 
629 #ifdef HAVE_FIPS
630     if ((sc->fips != UNSET) && (sc->fips != (BOOL)(flag ? TRUE : FALSE)))
631         return "Conflicting SSLFIPS options, cannot be both On and Off";
632     sc->fips = flag ? TRUE : FALSE;
633 #else
634     if (flag)
635         return "SSLFIPS invalid, rebuild httpd and openssl compiled for FIPS";
636 #endif
637 
638     return NULL;
639 }
640 
ssl_cmd_SSLCipherSuite(cmd_parms * cmd,void * dcfg,const char * arg)641 const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
642                                    void *dcfg,
643                                    const char *arg)
644 {
645     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
646     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
647 
648     if (cmd->path) {
649         dc->szCipherSuite = arg;
650     }
651     else {
652         sc->server->auth.cipher_suite = arg;
653     }
654 
655     return NULL;
656 }
657 
658 #define SSL_FLAGS_CHECK_FILE \
659     (SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO)
660 
661 #define SSL_FLAGS_CHECK_DIR \
662     (SSL_PCM_EXISTS|SSL_PCM_ISDIR)
663 
ssl_cmd_check_file(cmd_parms * parms,const char ** file)664 static const char *ssl_cmd_check_file(cmd_parms *parms,
665                                       const char **file)
666 {
667     const char *filepath = ap_server_root_relative(parms->pool, *file);
668 
669     if (!filepath) {
670         return apr_pstrcat(parms->pool, parms->cmd->name,
671                            ": Invalid file path ", *file, NULL);
672     }
673     *file = filepath;
674 
675     if (ssl_util_path_check(SSL_FLAGS_CHECK_FILE, *file, parms->pool)) {
676         return NULL;
677     }
678 
679     return apr_pstrcat(parms->pool, parms->cmd->name,
680                        ": file '", *file,
681                        "' does not exist or is empty", NULL);
682 
683 }
684 
ssl_cmd_SSLCompression(cmd_parms * cmd,void * dcfg,int flag)685 const char *ssl_cmd_SSLCompression(cmd_parms *cmd, void *dcfg, int flag)
686 {
687 #if !defined(OPENSSL_NO_COMP)
688     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
689 #ifndef SSL_OP_NO_COMPRESSION
690     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
691     if (err)
692         return "This version of openssl does not support configuring "
693                "compression within <VirtualHost> sections.";
694 #endif
695     sc->compression = flag ? TRUE : FALSE;
696     return NULL;
697 #else
698     return "Setting Compression mode unsupported; not implemented by the SSL library";
699 #endif
700 }
701 
ssl_cmd_SSLHonorCipherOrder(cmd_parms * cmd,void * dcfg,int flag)702 const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag)
703 {
704 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
705     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
706     sc->cipher_server_pref = flag?TRUE:FALSE;
707     return NULL;
708 #else
709     return "SSLHonorCiperOrder unsupported; not implemented by the SSL library";
710 #endif
711 }
712 
ssl_cmd_SSLInsecureRenegotiation(cmd_parms * cmd,void * dcfg,int flag)713 const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag)
714 {
715 #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
716     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
717     sc->insecure_reneg = flag?TRUE:FALSE;
718     return NULL;
719 #else
720     return "The SSLInsecureRenegotiation directive is not available "
721         "with this SSL library";
722 #endif
723 }
724 
725 
ssl_cmd_check_dir(cmd_parms * parms,const char ** dir)726 static const char *ssl_cmd_check_dir(cmd_parms *parms,
727                                      const char **dir)
728 {
729     const char *dirpath = ap_server_root_relative(parms->pool, *dir);
730 
731     if (!dirpath) {
732         return apr_pstrcat(parms->pool, parms->cmd->name,
733                            ": Invalid dir path ", *dir, NULL);
734     }
735     *dir = dirpath;
736 
737     if (ssl_util_path_check(SSL_FLAGS_CHECK_DIR, *dir, parms->pool)) {
738         return NULL;
739     }
740 
741     return apr_pstrcat(parms->pool, parms->cmd->name,
742                        ": directory '", *dir,
743                        "' does not exist", NULL);
744 
745 }
746 
747 #define SSL_AIDX_CERTS 1
748 #define SSL_AIDX_KEYS  2
749 
ssl_cmd_check_aidx_max(cmd_parms * parms,const char * arg,int idx)750 static const char *ssl_cmd_check_aidx_max(cmd_parms *parms,
751                                           const char *arg,
752                                           int idx)
753 {
754     SSLSrvConfigRec *sc = mySrvConfig(parms->server);
755     const char *err, *desc=NULL, **files=NULL;
756     int i;
757 
758     if ((err = ssl_cmd_check_file(parms, &arg))) {
759         return err;
760     }
761 
762     switch (idx) {
763       case SSL_AIDX_CERTS:
764         desc = "certificates";
765         files = sc->server->pks->cert_files;
766         break;
767       case SSL_AIDX_KEYS:
768         desc = "private keys";
769         files = sc->server->pks->key_files;
770         break;
771     }
772 
773     for (i = 0; i < SSL_AIDX_MAX; i++) {
774         if (!files[i]) {
775             files[i] = arg;
776             return NULL;
777         }
778     }
779 
780     return apr_psprintf(parms->pool,
781                         "%s: only up to %d "
782                         "different %s per virtual host allowed",
783                          parms->cmd->name, SSL_AIDX_MAX, desc);
784 }
785 
ssl_cmd_SSLCertificateFile(cmd_parms * cmd,void * dcfg,const char * arg)786 const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd,
787                                        void *dcfg,
788                                        const char *arg)
789 {
790 
791     const char *err;
792 
793     if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_CERTS))) {
794         return err;
795     }
796 
797     return NULL;
798 }
799 
ssl_cmd_SSLCertificateKeyFile(cmd_parms * cmd,void * dcfg,const char * arg)800 const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd,
801                                           void *dcfg,
802                                           const char *arg)
803 {
804     const char *err;
805 
806     if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_KEYS))) {
807         return err;
808     }
809 
810     return NULL;
811 }
812 
ssl_cmd_SSLCertificateChainFile(cmd_parms * cmd,void * dcfg,const char * arg)813 const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd,
814                                             void *dcfg,
815                                             const char *arg)
816 {
817     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
818     const char *err;
819 
820     if ((err = ssl_cmd_check_file(cmd, &arg))) {
821         return err;
822     }
823 
824     sc->server->cert_chain = arg;
825 
826     return NULL;
827 }
828 
ssl_cmd_SSLPKCS7CertificateFile(cmd_parms * cmd,void * dcfg,const char * arg)829 const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *cmd,
830                                             void *dcfg,
831                                             const char *arg)
832 {
833     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
834     const char *err;
835 
836     if ((err = ssl_cmd_check_file(cmd, &arg))) {
837         return err;
838     }
839 
840     sc->server->pkcs7 = arg;
841 
842     return NULL;
843 }
844 
845 #ifdef HAVE_TLS_SESSION_TICKETS
ssl_cmd_SSLSessionTicketKeyFile(cmd_parms * cmd,void * dcfg,const char * arg)846 const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd,
847                                             void *dcfg,
848                                             const char *arg)
849 {
850     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
851     const char *err;
852 
853     if ((err = ssl_cmd_check_file(cmd, &arg))) {
854         return err;
855     }
856 
857     sc->server->ticket_key->file_path = arg;
858 
859     return NULL;
860 }
861 #endif
862 
863 #define NO_PER_DIR_SSL_CA \
864     "Your SSL library does not have support for per-directory CA"
865 
ssl_cmd_SSLCACertificatePath(cmd_parms * cmd,void * dcfg,const char * arg)866 const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd,
867                                          void *dcfg,
868                                          const char *arg)
869 {
870     /*SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;*/
871     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
872     const char *err;
873 
874     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
875         return err;
876     }
877 
878     if (cmd->path) {
879         return NO_PER_DIR_SSL_CA;
880     }
881 
882     /* XXX: bring back per-dir */
883     sc->server->auth.ca_cert_path = arg;
884 
885     return NULL;
886 }
887 
ssl_cmd_SSLCACertificateFile(cmd_parms * cmd,void * dcfg,const char * arg)888 const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd,
889                                          void *dcfg,
890                                          const char *arg)
891 {
892     /*SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;*/
893     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
894     const char *err;
895 
896     if ((err = ssl_cmd_check_file(cmd, &arg))) {
897         return err;
898     }
899 
900     if (cmd->path) {
901         return NO_PER_DIR_SSL_CA;
902     }
903 
904     /* XXX: bring back per-dir */
905     sc->server->auth.ca_cert_file = arg;
906 
907     return NULL;
908 }
909 
ssl_cmd_SSLCADNRequestPath(cmd_parms * cmd,void * dcfg,const char * arg)910 const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *cmd, void *dcfg,
911                                        const char *arg)
912 {
913     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
914     const char *err;
915 
916     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
917         return err;
918     }
919 
920     sc->server->pks->ca_name_path = arg;
921 
922     return NULL;
923 }
924 
ssl_cmd_SSLCADNRequestFile(cmd_parms * cmd,void * dcfg,const char * arg)925 const char *ssl_cmd_SSLCADNRequestFile(cmd_parms *cmd, void *dcfg,
926                                        const char *arg)
927 {
928     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
929     const char *err;
930 
931     if ((err = ssl_cmd_check_file(cmd, &arg))) {
932         return err;
933     }
934 
935     sc->server->pks->ca_name_file = arg;
936 
937     return NULL;
938 }
939 
ssl_cmd_SSLCARevocationPath(cmd_parms * cmd,void * dcfg,const char * arg)940 const char *ssl_cmd_SSLCARevocationPath(cmd_parms *cmd,
941                                         void *dcfg,
942                                         const char *arg)
943 {
944     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
945     const char *err;
946 
947     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
948         return err;
949     }
950 
951     sc->server->crl_path = arg;
952 
953     return NULL;
954 }
955 
ssl_cmd_SSLCARevocationFile(cmd_parms * cmd,void * dcfg,const char * arg)956 const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd,
957                                         void *dcfg,
958                                         const char *arg)
959 {
960     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
961     const char *err;
962 
963     if ((err = ssl_cmd_check_file(cmd, &arg))) {
964         return err;
965     }
966 
967     sc->server->crl_file = arg;
968 
969     return NULL;
970 }
971 
ssl_cmd_crlcheck_parse(cmd_parms * parms,const char * arg,ssl_crlcheck_t * mode)972 static const char *ssl_cmd_crlcheck_parse(cmd_parms *parms,
973                                           const char *arg,
974                                           ssl_crlcheck_t *mode)
975 {
976     if (strcEQ(arg, "none")) {
977         *mode = SSL_CRLCHECK_NONE;
978     }
979     else if (strcEQ(arg, "leaf")) {
980         *mode = SSL_CRLCHECK_LEAF;
981     }
982     else if (strcEQ(arg, "chain")) {
983         *mode = SSL_CRLCHECK_CHAIN;
984     }
985     else {
986         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
987                            ": Invalid argument '", arg, "'",
988                            NULL);
989     }
990 
991     return NULL;
992 }
993 
ssl_cmd_SSLCARevocationCheck(cmd_parms * cmd,void * dcfg,const char * arg)994 const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *cmd,
995                                          void *dcfg,
996                                          const char *arg)
997 {
998     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
999 
1000     return ssl_cmd_crlcheck_parse(cmd, arg, &sc->server->crl_check_mode);
1001 }
1002 
ssl_cmd_verify_parse(cmd_parms * parms,const char * arg,ssl_verify_t * id)1003 static const char *ssl_cmd_verify_parse(cmd_parms *parms,
1004                                         const char *arg,
1005                                         ssl_verify_t *id)
1006 {
1007     if (strcEQ(arg, "none") || strcEQ(arg, "off")) {
1008         *id = SSL_CVERIFY_NONE;
1009     }
1010     else if (strcEQ(arg, "optional")) {
1011         *id = SSL_CVERIFY_OPTIONAL;
1012     }
1013     else if (strcEQ(arg, "require") || strcEQ(arg, "on")) {
1014         *id = SSL_CVERIFY_REQUIRE;
1015     }
1016     else if (strcEQ(arg, "optional_no_ca")) {
1017         *id = SSL_CVERIFY_OPTIONAL_NO_CA;
1018     }
1019     else {
1020         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1021                            ": Invalid argument '", arg, "'",
1022                            NULL);
1023     }
1024 
1025     return NULL;
1026 }
1027 
ssl_cmd_SSLVerifyClient(cmd_parms * cmd,void * dcfg,const char * arg)1028 const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd,
1029                                     void *dcfg,
1030                                     const char *arg)
1031 {
1032     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1033     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1034     ssl_verify_t mode;
1035     const char *err;
1036 
1037     if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) {
1038         return err;
1039     }
1040 
1041     if (cmd->path) {
1042         dc->nVerifyClient = mode;
1043     }
1044     else {
1045         sc->server->auth.verify_mode = mode;
1046     }
1047 
1048     return NULL;
1049 }
1050 
ssl_cmd_verify_depth_parse(cmd_parms * parms,const char * arg,int * depth)1051 static const char *ssl_cmd_verify_depth_parse(cmd_parms *parms,
1052                                               const char *arg,
1053                                               int *depth)
1054 {
1055     if ((*depth = atoi(arg)) >= 0) {
1056         return NULL;
1057     }
1058 
1059     return apr_pstrcat(parms->temp_pool, parms->cmd->name,
1060                        ": Invalid argument '", arg, "'",
1061                        NULL);
1062 }
1063 
ssl_cmd_SSLVerifyDepth(cmd_parms * cmd,void * dcfg,const char * arg)1064 const char *ssl_cmd_SSLVerifyDepth(cmd_parms *cmd,
1065                                    void *dcfg,
1066                                    const char *arg)
1067 {
1068     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1069     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1070     int depth;
1071     const char *err;
1072 
1073     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
1074         return err;
1075     }
1076 
1077     if (cmd->path) {
1078         dc->nVerifyDepth = depth;
1079     }
1080     else {
1081         sc->server->auth.verify_depth = depth;
1082     }
1083 
1084     return NULL;
1085 }
1086 
ssl_cmd_SSLSessionCache(cmd_parms * cmd,void * dcfg,const char * arg)1087 const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd,
1088                                     void *dcfg,
1089                                     const char *arg)
1090 {
1091     SSLModConfigRec *mc = myModConfig(cmd->server);
1092     const char *err, *sep, *name;
1093     long enabled_flags;
1094 
1095     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
1096         return err;
1097     }
1098 
1099     /* The OpenSSL session cache mode must have both the flags
1100      * SSL_SESS_CACHE_SERVER and SSL_SESS_CACHE_NO_INTERNAL set if a
1101      * session cache is configured; NO_INTERNAL prevents the
1102      * OpenSSL-internal session cache being used in addition to the
1103      * "external" (mod_ssl-provided) cache, which otherwise causes
1104      * additional memory consumption. */
1105     enabled_flags = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL;
1106 
1107     if (strcEQ(arg, "none")) {
1108         /* Nothing to do; session cache will be off. */
1109     }
1110     else if (strcEQ(arg, "nonenotnull")) {
1111         /* ### Having a separate mode for this seems logically
1112          * unnecessary; the stated purpose of sending non-empty
1113          * session IDs would be better fixed in OpenSSL or simply
1114          * doing it by default if "none" is used. */
1115         mc->sesscache_mode = enabled_flags;
1116     }
1117     else {
1118         /* Argument is of form 'name:args' or just 'name'. */
1119         sep = ap_strchr_c(arg, ':');
1120         if (sep) {
1121             name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
1122             sep++;
1123         }
1124         else {
1125             name = arg;
1126         }
1127 
1128         /* Find the provider of given name. */
1129         mc->sesscache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
1130                                            name,
1131                                            AP_SOCACHE_PROVIDER_VERSION);
1132         if (mc->sesscache) {
1133             /* Cache found; create it, passing anything beyond the colon. */
1134             mc->sesscache_mode = enabled_flags;
1135             err = mc->sesscache->create(&mc->sesscache_context, sep,
1136                                         cmd->temp_pool, cmd->pool);
1137         }
1138         else {
1139             apr_array_header_t *name_list;
1140             const char *all_names;
1141 
1142             /* Build a comma-separated list of all registered provider
1143              * names: */
1144             name_list = ap_list_provider_names(cmd->pool,
1145                                                AP_SOCACHE_PROVIDER_GROUP,
1146                                                AP_SOCACHE_PROVIDER_VERSION);
1147             all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
1148 
1149             err = apr_psprintf(cmd->pool, "'%s' session cache not supported "
1150                                "(known names: %s). Maybe you need to load the "
1151                                "appropriate socache module (mod_socache_%s?).",
1152                                name, all_names, name);
1153         }
1154     }
1155 
1156     if (err) {
1157         return apr_psprintf(cmd->pool, "SSLSessionCache: %s", err);
1158     }
1159 
1160     return NULL;
1161 }
1162 
ssl_cmd_SSLSessionCacheTimeout(cmd_parms * cmd,void * dcfg,const char * arg)1163 const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *cmd,
1164                                            void *dcfg,
1165                                            const char *arg)
1166 {
1167     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1168 
1169     sc->session_cache_timeout = atoi(arg);
1170 
1171     if (sc->session_cache_timeout < 0) {
1172         return "SSLSessionCacheTimeout: Invalid argument";
1173     }
1174 
1175     return NULL;
1176 }
1177 
ssl_cmd_SSLOptions(cmd_parms * cmd,void * dcfg,const char * arg)1178 const char *ssl_cmd_SSLOptions(cmd_parms *cmd,
1179                                void *dcfg,
1180                                const char *arg)
1181 {
1182     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1183     ssl_opt_t opt;
1184     int first = TRUE;
1185     char action, *w;
1186 
1187     while (*arg) {
1188         w = ap_getword_conf(cmd->temp_pool, &arg);
1189         action = NUL;
1190 
1191         if ((*w == '+') || (*w == '-')) {
1192             action = *(w++);
1193         }
1194         else if (first) {
1195             dc->nOptions = SSL_OPT_NONE;
1196             first = FALSE;
1197         }
1198 
1199         if (strcEQ(w, "StdEnvVars")) {
1200             opt = SSL_OPT_STDENVVARS;
1201         }
1202         else if (strcEQ(w, "ExportCertData")) {
1203             opt = SSL_OPT_EXPORTCERTDATA;
1204         }
1205         else if (strcEQ(w, "FakeBasicAuth")) {
1206             opt = SSL_OPT_FAKEBASICAUTH;
1207         }
1208         else if (strcEQ(w, "StrictRequire")) {
1209             opt = SSL_OPT_STRICTREQUIRE;
1210         }
1211         else if (strcEQ(w, "OptRenegotiate")) {
1212             opt = SSL_OPT_OPTRENEGOTIATE;
1213         }
1214         else if (strcEQ(w, "LegacyDNStringFormat")) {
1215             opt = SSL_OPT_LEGACYDNFORMAT;
1216         }
1217         else {
1218             return apr_pstrcat(cmd->pool,
1219                                "SSLOptions: Illegal option '", w, "'",
1220                                NULL);
1221         }
1222 
1223         if (action == '-') {
1224             dc->nOptionsAdd &= ~opt;
1225             dc->nOptionsDel |=  opt;
1226             dc->nOptions    &= ~opt;
1227         }
1228         else if (action == '+') {
1229             dc->nOptionsAdd |=  opt;
1230             dc->nOptionsDel &= ~opt;
1231             dc->nOptions    |=  opt;
1232         }
1233         else {
1234             dc->nOptions    = opt;
1235             dc->nOptionsAdd = opt;
1236             dc->nOptionsDel = SSL_OPT_NONE;
1237         }
1238     }
1239 
1240     return NULL;
1241 }
1242 
ssl_cmd_SSLRequireSSL(cmd_parms * cmd,void * dcfg)1243 const char *ssl_cmd_SSLRequireSSL(cmd_parms *cmd, void *dcfg)
1244 {
1245     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1246 
1247     dc->bSSLRequired = TRUE;
1248 
1249     return NULL;
1250 }
1251 
ssl_cmd_SSLRequire(cmd_parms * cmd,void * dcfg,const char * arg)1252 const char *ssl_cmd_SSLRequire(cmd_parms *cmd,
1253                                void *dcfg,
1254                                const char *arg)
1255 {
1256     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1257     ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
1258     ssl_require_t *require;
1259     const char *errstring;
1260 
1261     info->flags = AP_EXPR_FLAG_SSL_EXPR_COMPAT;
1262     info->filename = cmd->directive->filename;
1263     info->line_number = cmd->directive->line_num;
1264     info->module_index = APLOG_MODULE_INDEX;
1265     errstring = ap_expr_parse(cmd->pool, cmd->temp_pool, info, arg, NULL);
1266     if (errstring) {
1267         return apr_pstrcat(cmd->pool, "SSLRequire: ", errstring, NULL);
1268     }
1269 
1270     require = apr_array_push(dc->aRequirement);
1271     require->cpExpr = apr_pstrdup(cmd->pool, arg);
1272     require->mpExpr = info;
1273 
1274     return NULL;
1275 }
1276 
ssl_cmd_SSLRenegBufferSize(cmd_parms * cmd,void * dcfg,const char * arg)1277 const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg)
1278 {
1279     SSLDirConfigRec *dc = dcfg;
1280     int val;
1281 
1282     val = atoi(arg);
1283     if (val < 0) {
1284         return apr_pstrcat(cmd->pool, "Invalid size for SSLRenegBufferSize: ",
1285                            arg, NULL);
1286     }
1287     dc->nRenegBufferSize = val;
1288 
1289     return NULL;
1290 }
1291 
ssl_cmd_protocol_parse(cmd_parms * parms,const char * arg,ssl_proto_t * options)1292 static const char *ssl_cmd_protocol_parse(cmd_parms *parms,
1293                                           const char *arg,
1294                                           ssl_proto_t *options)
1295 {
1296     ssl_proto_t thisopt;
1297 
1298     *options = SSL_PROTOCOL_NONE;
1299 
1300     while (*arg) {
1301         char *w = ap_getword_conf(parms->temp_pool, &arg);
1302         char action = '\0';
1303 
1304         if ((*w == '+') || (*w == '-')) {
1305             action = *(w++);
1306         }
1307 
1308         if (strcEQ(w, "SSLv2")) {
1309             if (action == '-') {
1310                 continue;
1311             }
1312             else {
1313                 return "SSLProtocol: SSLv2 is no longer supported";
1314             }
1315         }
1316         else if (strcEQ(w, "SSLv3")) {
1317             thisopt = SSL_PROTOCOL_SSLV3;
1318         }
1319         else if (strcEQ(w, "TLSv1")) {
1320             thisopt = SSL_PROTOCOL_TLSV1;
1321         }
1322 #ifdef HAVE_TLSV1_X
1323         else if (strcEQ(w, "TLSv1.1")) {
1324             thisopt = SSL_PROTOCOL_TLSV1_1;
1325         }
1326         else if (strcEQ(w, "TLSv1.2")) {
1327             thisopt = SSL_PROTOCOL_TLSV1_2;
1328         }
1329 #endif
1330         else if (strcEQ(w, "all")) {
1331             thisopt = SSL_PROTOCOL_ALL;
1332         }
1333         else {
1334             return apr_pstrcat(parms->temp_pool,
1335                                parms->cmd->name,
1336                                ": Illegal protocol '",
1337                                w, "'", NULL);
1338         }
1339 
1340         if (action == '-') {
1341             *options &= ~thisopt;
1342         }
1343         else if (action == '+') {
1344             *options |= thisopt;
1345         }
1346         else {
1347             *options = thisopt;
1348         }
1349     }
1350 
1351     return NULL;
1352 }
1353 
ssl_cmd_SSLProtocol(cmd_parms * cmd,void * dcfg,const char * arg)1354 const char *ssl_cmd_SSLProtocol(cmd_parms *cmd,
1355                                 void *dcfg,
1356                                 const char *arg)
1357 {
1358     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1359 
1360     return ssl_cmd_protocol_parse(cmd, arg, &sc->server->protocol);
1361 }
1362 
ssl_cmd_SSLProxyEngine(cmd_parms * cmd,void * dcfg,int flag)1363 const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag)
1364 {
1365     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1366 
1367     sc->proxy_enabled = flag ? TRUE : FALSE;
1368 
1369     return NULL;
1370 }
1371 
ssl_cmd_SSLProxyProtocol(cmd_parms * cmd,void * dcfg,const char * arg)1372 const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cmd,
1373                                      void *dcfg,
1374                                      const char *arg)
1375 {
1376     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1377 
1378     return ssl_cmd_protocol_parse(cmd, arg, &sc->proxy->protocol);
1379 }
1380 
ssl_cmd_SSLProxyCipherSuite(cmd_parms * cmd,void * dcfg,const char * arg)1381 const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
1382                                         void *dcfg,
1383                                         const char *arg)
1384 {
1385     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1386 
1387     sc->proxy->auth.cipher_suite = arg;
1388 
1389     return NULL;
1390 }
1391 
ssl_cmd_SSLProxyVerify(cmd_parms * cmd,void * dcfg,const char * arg)1392 const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd,
1393                                    void *dcfg,
1394                                    const char *arg)
1395 {
1396     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1397     ssl_verify_t mode;
1398     const char *err;
1399 
1400     if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) {
1401         return err;
1402     }
1403 
1404     sc->proxy->auth.verify_mode = mode;
1405 
1406     return NULL;
1407 }
1408 
ssl_cmd_SSLProxyVerifyDepth(cmd_parms * cmd,void * dcfg,const char * arg)1409 const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd,
1410                                         void *dcfg,
1411                                         const char *arg)
1412 {
1413     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1414     int depth;
1415     const char *err;
1416 
1417     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
1418         return err;
1419     }
1420 
1421     sc->proxy->auth.verify_depth = depth;
1422 
1423     return NULL;
1424 }
1425 
ssl_cmd_SSLProxyCACertificateFile(cmd_parms * cmd,void * dcfg,const char * arg)1426 const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *cmd,
1427                                               void *dcfg,
1428                                               const char *arg)
1429 {
1430     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1431     const char *err;
1432 
1433     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1434         return err;
1435     }
1436 
1437     sc->proxy->auth.ca_cert_file = arg;
1438 
1439     return NULL;
1440 }
1441 
ssl_cmd_SSLProxyCACertificatePath(cmd_parms * cmd,void * dcfg,const char * arg)1442 const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *cmd,
1443                                               void *dcfg,
1444                                               const char *arg)
1445 {
1446     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1447     const char *err;
1448 
1449     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1450         return err;
1451     }
1452 
1453     sc->proxy->auth.ca_cert_path = arg;
1454 
1455     return NULL;
1456 }
1457 
ssl_cmd_SSLProxyCARevocationPath(cmd_parms * cmd,void * dcfg,const char * arg)1458 const char *ssl_cmd_SSLProxyCARevocationPath(cmd_parms *cmd,
1459                                              void *dcfg,
1460                                              const char *arg)
1461 {
1462     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1463     const char *err;
1464 
1465     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1466         return err;
1467     }
1468 
1469     sc->proxy->crl_path = arg;
1470 
1471     return NULL;
1472 }
1473 
ssl_cmd_SSLProxyCARevocationFile(cmd_parms * cmd,void * dcfg,const char * arg)1474 const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *cmd,
1475                                              void *dcfg,
1476                                              const char *arg)
1477 {
1478     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1479     const char *err;
1480 
1481     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1482         return err;
1483     }
1484 
1485     sc->proxy->crl_file = arg;
1486 
1487     return NULL;
1488 }
1489 
ssl_cmd_SSLProxyCARevocationCheck(cmd_parms * cmd,void * dcfg,const char * arg)1490 const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd,
1491                                               void *dcfg,
1492                                               const char *arg)
1493 {
1494     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1495 
1496     return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mode);
1497 }
1498 
ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms * cmd,void * dcfg,const char * arg)1499 const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
1500                                                    void *dcfg,
1501                                                    const char *arg)
1502 {
1503     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1504     const char *err;
1505 
1506     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1507         return err;
1508     }
1509 
1510     sc->proxy->pkp->cert_file = arg;
1511 
1512     return NULL;
1513 }
1514 
ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms * cmd,void * dcfg,const char * arg)1515 const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd,
1516                                                    void *dcfg,
1517                                                    const char *arg)
1518 {
1519     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1520     const char *err;
1521 
1522     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1523         return err;
1524     }
1525 
1526     sc->proxy->pkp->cert_path = arg;
1527 
1528     return NULL;
1529 }
1530 
ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms * cmd,void * dcfg,const char * arg)1531 const char *ssl_cmd_SSLProxyMachineCertificateChainFile(cmd_parms *cmd,
1532                                                    void *dcfg,
1533                                                    const char *arg)
1534 {
1535     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1536     const char *err;
1537 
1538     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1539         return err;
1540     }
1541 
1542     sc->proxy->pkp->ca_cert_file = arg;
1543 
1544     return NULL;
1545 }
1546 
ssl_cmd_SSLUserName(cmd_parms * cmd,void * dcfg,const char * arg)1547 const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg,
1548                                 const char *arg)
1549 {
1550     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
1551     dc->szUserName = arg;
1552     return NULL;
1553 }
1554 
ssl_cmd_SSLOCSPEnable(cmd_parms * cmd,void * dcfg,int flag)1555 const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag)
1556 {
1557     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1558 
1559     sc->server->ocsp_enabled = flag ? TRUE : FALSE;
1560 
1561 #ifdef OPENSSL_NO_OCSP
1562     if (flag) {
1563         return "OCSP support disabled in SSL library; cannot enable "
1564             "OCSP validation";
1565     }
1566 #endif
1567 
1568     return NULL;
1569 }
1570 
ssl_cmd_SSLOCSPOverrideResponder(cmd_parms * cmd,void * dcfg,int flag)1571 const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag)
1572 {
1573     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1574 
1575     sc->server->ocsp_force_default = flag ? TRUE : FALSE;
1576 
1577     return NULL;
1578 }
1579 
ssl_cmd_SSLOCSPDefaultResponder(cmd_parms * cmd,void * dcfg,const char * arg)1580 const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg)
1581 {
1582     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1583 
1584     sc->server->ocsp_responder = arg;
1585 
1586     return NULL;
1587 }
1588 
ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms * cmd,void * dcfg,const char * arg)1589 const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg)
1590 {
1591     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1592     sc->server->ocsp_resptime_skew = atoi(arg);
1593     if (sc->server->ocsp_resptime_skew < 0) {
1594         return "SSLOCSPResponseTimeSkew: invalid argument";
1595     }
1596     return NULL;
1597 }
1598 
ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms * cmd,void * dcfg,const char * arg)1599 const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg)
1600 {
1601     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1602     sc->server->ocsp_resp_maxage = atoi(arg);
1603     if (sc->server->ocsp_resp_maxage < 0) {
1604         return "SSLOCSPResponseMaxAge: invalid argument";
1605     }
1606     return NULL;
1607 }
1608 
ssl_cmd_SSLOCSPResponderTimeout(cmd_parms * cmd,void * dcfg,const char * arg)1609 const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg)
1610 {
1611     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1612     sc->server->ocsp_responder_timeout = apr_time_from_sec(atoi(arg));
1613     if (sc->server->ocsp_responder_timeout < 0) {
1614         return "SSLOCSPResponderTimeout: invalid argument";
1615     }
1616     return NULL;
1617 }
1618 
ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms * cmd,void * dcfg,int flag)1619 const char *ssl_cmd_SSLProxyCheckPeerExpire(cmd_parms *cmd, void *dcfg, int flag)
1620 {
1621     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1622 
1623     sc->proxy_ssl_check_peer_expire = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
1624 
1625     return NULL;
1626 }
1627 
ssl_cmd_SSLProxyCheckPeerCN(cmd_parms * cmd,void * dcfg,int flag)1628 const char *ssl_cmd_SSLProxyCheckPeerCN(cmd_parms *cmd, void *dcfg, int flag)
1629 {
1630     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1631 
1632     sc->proxy_ssl_check_peer_cn = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
1633 
1634     return NULL;
1635 }
1636 
ssl_cmd_SSLProxyCheckPeerName(cmd_parms * cmd,void * dcfg,int flag)1637 const char *ssl_cmd_SSLProxyCheckPeerName(cmd_parms *cmd, void *dcfg, int flag)
1638 {
1639     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1640 
1641     sc->proxy_ssl_check_peer_name = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
1642 
1643     return NULL;
1644 }
1645 
ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms * cmd,void * dcfg,int flag)1646 const char  *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag)
1647 {
1648 #ifndef OPENSSL_NO_TLSEXT
1649     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1650 
1651     sc->strict_sni_vhost_check = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
1652 
1653     return NULL;
1654 #else
1655     return "SSLStrictSNIVHostCheck failed; OpenSSL is not built with support "
1656            "for TLS extensions and SNI indication. Refer to the "
1657            "documentation, and build a compatible version of OpenSSL.";
1658 #endif
1659 }
1660 
1661 #ifdef HAVE_OCSP_STAPLING
1662 
ssl_cmd_SSLStaplingCache(cmd_parms * cmd,void * dcfg,const char * arg)1663 const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd,
1664                                     void *dcfg,
1665                                     const char *arg)
1666 {
1667     SSLModConfigRec *mc = myModConfig(cmd->server);
1668     const char *err, *sep, *name;
1669 
1670     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
1671         return err;
1672     }
1673 
1674     /* Argument is of form 'name:args' or just 'name'. */
1675     sep = ap_strchr_c(arg, ':');
1676     if (sep) {
1677         name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
1678         sep++;
1679     }
1680     else {
1681         name = arg;
1682     }
1683 
1684     /* Find the provider of given name. */
1685     mc->stapling_cache = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
1686                                             name,
1687                                             AP_SOCACHE_PROVIDER_VERSION);
1688     if (mc->stapling_cache) {
1689         /* Cache found; create it, passing anything beyond the colon. */
1690         err = mc->stapling_cache->create(&mc->stapling_cache_context,
1691                                          sep, cmd->temp_pool,
1692                                          cmd->pool);
1693     }
1694     else {
1695         apr_array_header_t *name_list;
1696         const char *all_names;
1697 
1698         /* Build a comma-separated list of all registered provider
1699          * names: */
1700         name_list = ap_list_provider_names(cmd->pool,
1701                                            AP_SOCACHE_PROVIDER_GROUP,
1702                                            AP_SOCACHE_PROVIDER_VERSION);
1703         all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
1704 
1705         err = apr_psprintf(cmd->pool, "'%s' stapling cache not supported "
1706                            "(known names: %s) Maybe you need to load the "
1707                            "appropriate socache module (mod_socache_%s?)",
1708                            name, all_names, name);
1709     }
1710 
1711     if (err) {
1712         return apr_psprintf(cmd->pool, "SSLStaplingCache: %s", err);
1713     }
1714 
1715     return NULL;
1716 }
1717 
ssl_cmd_SSLUseStapling(cmd_parms * cmd,void * dcfg,int flag)1718 const char *ssl_cmd_SSLUseStapling(cmd_parms *cmd, void *dcfg, int flag)
1719 {
1720     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1721     sc->server->stapling_enabled = flag ? TRUE : FALSE;
1722     return NULL;
1723 }
1724 
ssl_cmd_SSLStaplingResponseTimeSkew(cmd_parms * cmd,void * dcfg,const char * arg)1725 const char *ssl_cmd_SSLStaplingResponseTimeSkew(cmd_parms *cmd, void *dcfg,
1726                                                     const char *arg)
1727 {
1728     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1729     sc->server->stapling_resptime_skew = atoi(arg);
1730     if (sc->server->stapling_resptime_skew < 0) {
1731         return "SSLStaplingResponseTimeSkew: invalid argument";
1732     }
1733     return NULL;
1734 }
1735 
ssl_cmd_SSLStaplingResponseMaxAge(cmd_parms * cmd,void * dcfg,const char * arg)1736 const char *ssl_cmd_SSLStaplingResponseMaxAge(cmd_parms *cmd, void *dcfg,
1737                                                     const char *arg)
1738 {
1739     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1740     sc->server->stapling_resp_maxage = atoi(arg);
1741     if (sc->server->stapling_resp_maxage < 0) {
1742         return "SSLStaplingResponseMaxAge: invalid argument";
1743     }
1744     return NULL;
1745 }
1746 
ssl_cmd_SSLStaplingStandardCacheTimeout(cmd_parms * cmd,void * dcfg,const char * arg)1747 const char *ssl_cmd_SSLStaplingStandardCacheTimeout(cmd_parms *cmd, void *dcfg,
1748                                                     const char *arg)
1749 {
1750     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1751     sc->server->stapling_cache_timeout = atoi(arg);
1752     if (sc->server->stapling_cache_timeout < 0) {
1753         return "SSLStaplingStandardCacheTimeout: invalid argument";
1754     }
1755     return NULL;
1756 }
1757 
ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms * cmd,void * dcfg,const char * arg)1758 const char *ssl_cmd_SSLStaplingErrorCacheTimeout(cmd_parms *cmd, void *dcfg,
1759                                                  const char *arg)
1760 {
1761     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1762     sc->server->stapling_errcache_timeout = atoi(arg);
1763     if (sc->server->stapling_errcache_timeout < 0) {
1764         return "SSLStaplingErrorCacheTimeout: invalid argument";
1765     }
1766     return NULL;
1767 }
1768 
ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms * cmd,void * dcfg,int flag)1769 const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *cmd,
1770                                                      void *dcfg, int flag)
1771 {
1772     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1773     sc->server->stapling_return_errors = flag ? TRUE : FALSE;
1774     return NULL;
1775 }
1776 
ssl_cmd_SSLStaplingFakeTryLater(cmd_parms * cmd,void * dcfg,int flag)1777 const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *cmd,
1778                                             void *dcfg, int flag)
1779 {
1780     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1781     sc->server->stapling_fake_trylater = flag ? TRUE : FALSE;
1782     return NULL;
1783 }
1784 
ssl_cmd_SSLStaplingResponderTimeout(cmd_parms * cmd,void * dcfg,const char * arg)1785 const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *cmd, void *dcfg,
1786                                                 const char *arg)
1787 {
1788     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1789     sc->server->stapling_responder_timeout = atoi(arg);
1790     sc->server->stapling_responder_timeout *= APR_USEC_PER_SEC;
1791     if (sc->server->stapling_responder_timeout < 0) {
1792         return "SSLStaplingResponderTimeout: invalid argument";
1793     }
1794     return NULL;
1795 }
1796 
ssl_cmd_SSLStaplingForceURL(cmd_parms * cmd,void * dcfg,const char * arg)1797 const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg,
1798                                         const char *arg)
1799 {
1800     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1801     sc->server->stapling_force_url = arg;
1802     return NULL;
1803 }
1804 
1805 #endif /* HAVE_OCSP_STAPLING */
1806 
1807 #ifndef OPENSSL_NO_SRP
1808 
ssl_cmd_SSLSRPVerifierFile(cmd_parms * cmd,void * dcfg,const char * arg)1809 const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
1810                                        const char *arg)
1811 {
1812     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1813     const char *err;
1814 
1815     if ((err = ssl_cmd_check_file(cmd, &arg)))
1816         return err;
1817     /* SRP_VBASE_init takes char*, not const char*  */
1818     sc->server->srp_vfile = apr_pstrdup(cmd->pool, arg);
1819     return NULL;
1820 }
1821 
ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms * cmd,void * dcfg,const char * arg)1822 const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg,
1823                                           const char *arg)
1824 {
1825     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1826     /* SRP_VBASE_new takes char*, not const char*  */
1827     sc->server->srp_unknown_user_seed = apr_pstrdup(cmd->pool, arg);
1828     return NULL;
1829 }
1830 
1831 #endif /* OPENSSL_NO_SRP */
1832 
ssl_hook_ConfigTest(apr_pool_t * pconf,server_rec * s)1833 void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
1834 {
1835     apr_file_t *out = NULL;
1836     if (!ap_exists_config_define("DUMP_CERTS")) {
1837         return;
1838     }
1839     apr_file_open_stdout(&out, pconf);
1840     apr_file_printf(out, "Server certificates:\n");
1841 
1842     /* Dump the filenames of all configured server certificates to
1843      * stdout. */
1844     while (s) {
1845         SSLSrvConfigRec *sc = mySrvConfig(s);
1846 
1847         if (sc && sc->server && sc->server->pks) {
1848             modssl_pk_server_t *const pks = sc->server->pks;
1849             int i;
1850 
1851             for (i = 0; (i < SSL_AIDX_MAX) && pks->cert_files[i]; i++) {
1852                 apr_file_printf(out, "  %s\n", pks->cert_files[i]);
1853             }
1854         }
1855 
1856         s = s->next;
1857     }
1858 
1859 }
1860