]> granicus.if.org Git - apache/blob - modules/ssl/ssl_engine_config.c
3be8ff845f93493dcd3decf459335c6ea2bcac24
[apache] / modules / ssl / ssl_engine_config.c
1 /*                      _             _
2 **  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
3 ** | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| |   \__ \__ \ |  www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_|  ftp.modssl.org
6 **                      |_____|
7 **  ssl_engine_config.c
8 **  Apache Configuration Directives
9 */
10
11 /* ====================================================================
12  * The Apache Software License, Version 1.1
13  *
14  * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
15  * reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  *
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  *
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in
26  *    the documentation and/or other materials provided with the
27  *    distribution.
28  *
29  * 3. The end-user documentation included with the redistribution,
30  *    if any, must include the following acknowledgment:
31  *       "This product includes software developed by the
32  *        Apache Software Foundation (http://www.apache.org/)."
33  *    Alternately, this acknowledgment may appear in the software itself,
34  *    if and wherever such third-party acknowledgments normally appear.
35  *
36  * 4. The names "Apache" and "Apache Software Foundation" must
37  *    not be used to endorse or promote products derived from this
38  *    software without prior written permission. For written
39  *    permission, please contact apache@apache.org.
40  *
41  * 5. Products derived from this software may not be called "Apache",
42  *    nor may "Apache" appear in their name, without prior written
43  *    permission of the Apache Software Foundation.
44  *
45  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
49  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  * ====================================================================
58  */
59
60                                       /* ``Damned if you do,
61                                            damned if you don't.''
62                                                -- Unknown        */
63 #include "mod_ssl.h"
64
65 /*  _________________________________________________________________
66 **
67 **  Support for Global Configuration
68 **  _________________________________________________________________
69 */
70
71 #define SSL_MOD_CONFIG_KEY "ssl_module"
72
73 SSLModConfigRec *ssl_config_global_create(server_rec *s)
74 {
75     apr_pool_t *pool = s->process->pool;
76     SSLModConfigRec *mc;
77
78     apr_pool_userdata_get((void **)&mc, SSL_MOD_CONFIG_KEY,
79                           pool);
80
81     if (mc) {
82         return mc; /* reused for lifetime of the server */
83     }
84
85     /*
86      * allocate an own subpool which survives server restarts
87      */
88     mc = (SSLModConfigRec *)apr_palloc(pool, sizeof(*mc));
89     mc->pPool = pool;
90     mc->bFixed = FALSE;
91
92     /*
93      * initialize per-module configuration
94      */
95     mc->nSessionCacheMode      = SSL_SCMODE_UNSET;
96     mc->szSessionCacheDataFile = NULL;
97     mc->nSessionCacheDataSize  = 0;
98 #if 0 /* XXX */
99     mc->pSessionCacheDataMM    = NULL;
100 #endif
101     mc->tSessionCacheDataTable = NULL;
102     mc->nMutexMode             = SSL_MUTEXMODE_UNSET;
103     mc->szMutexFile            = NULL;
104     mc->pMutex                 = NULL;
105     mc->aRandSeed              = apr_array_make(pool, 4,
106                                                 sizeof(ssl_randseed_t));
107     mc->tVHostKeys             = apr_hash_make(pool);
108     mc->tPrivateKey            = apr_hash_make(pool);
109     mc->tPublicCert            = apr_hash_make(pool);
110     mc->tTmpKeys               = apr_hash_make(pool);
111 #ifdef SSL_EXPERIMENTAL_ENGINE
112     mc->szCryptoDevice         = NULL;
113 #endif
114
115     memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
116
117     apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
118                           apr_pool_cleanup_null,
119                           pool);
120
121     return mc;
122 }
123
124 void ssl_config_global_fix(SSLModConfigRec *mc)
125 {
126     mc->bFixed = TRUE;
127 }
128
129 BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
130 {
131     return mc->bFixed;
132 }
133
134 /*  _________________________________________________________________
135 **
136 **  Configuration handling
137 **  _________________________________________________________________
138 */
139
140 /*
141  *  Create per-server SSL configuration
142  */
143 void *ssl_config_server_create(apr_pool_t *p, server_rec *s)
144 {
145     SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
146
147     sc->mc                     = ssl_config_global_create(s);
148     sc->bEnabled               = UNSET;
149     sc->szCACertificatePath    = NULL;
150     sc->szCACertificateFile    = NULL;
151     sc->szCertificateChain     = NULL;
152     sc->szLogFile              = NULL;
153     sc->szCipherSuite          = NULL;
154     sc->nLogLevel              = SSL_LOG_NONE;
155     sc->nVerifyDepth           = UNSET;
156     sc->nVerifyClient          = SSL_CVERIFY_UNSET;
157     sc->nSessionCacheTimeout   = UNSET;
158     sc->nPassPhraseDialogType  = SSL_PPTYPE_UNSET;
159     sc->szPassPhraseDialogPath = NULL;
160     sc->nProtocol              = SSL_PROTOCOL_ALL;
161     sc->fileLogFile            = NULL;
162     sc->pSSLCtx                = NULL;
163     sc->szCARevocationPath     = NULL;
164     sc->szCARevocationFile     = NULL;
165     sc->pRevocationStore       = NULL;
166
167 #ifdef SSL_EXPERIMENTAL_PROXY
168     sc->nProxyVerifyDepth             = UNSET;
169     sc->szProxyCACertificatePath      = NULL;
170     sc->szProxyCACertificateFile      = NULL;
171     sc->szProxyClientCertificateFile  = NULL;
172     sc->szProxyClientCertificatePath  = NULL;
173     sc->szProxyCipherSuite            = NULL;
174     sc->nProxyProtocol                = SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1;
175     sc->bProxyVerify                  = UNSET;
176     sc->pSSLProxyCtx                  = NULL;
177 #endif
178
179     memset(sc->szPublicCertFile, 0, sizeof(sc->szPublicCertFile));
180     memset(sc->szPrivateKeyFile, 0, sizeof(sc->szPrivateKeyFile));
181     memset(sc->pPublicCert,      0, sizeof(sc->pPublicCert));
182     memset(sc->pPrivateKey,      0, sizeof(sc->pPrivateKey));
183
184     return sc;
185 }
186
187 /*
188  *  Merge per-server SSL configurations
189  */
190 void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
191 {
192     int i;
193     SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
194     SSLSrvConfigRec *add  = (SSLSrvConfigRec *)addv;
195     SSLSrvConfigRec *new  = (SSLSrvConfigRec *)apr_palloc(p, sizeof(*new));
196
197     cfgMerge(mc, NULL);
198     cfgMergeString(szVHostID);
199     cfgMergeBool(bEnabled);
200     cfgMergeString(szCACertificatePath);
201     cfgMergeString(szCACertificateFile);
202     cfgMergeString(szCertificateChain);
203     cfgMergeString(szLogFile);
204     cfgMergeString(szCipherSuite);
205     cfgMerge(nLogLevel, SSL_LOG_NONE);
206     cfgMergeInt(nVerifyDepth);
207     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
208     cfgMergeInt(nSessionCacheTimeout);
209     cfgMerge(nPassPhraseDialogType, SSL_PPTYPE_UNSET);
210     cfgMergeString(szPassPhraseDialogPath);
211     cfgMerge(nProtocol, SSL_PROTOCOL_ALL);
212     cfgMerge(fileLogFile, NULL);
213     cfgMerge(pSSLCtx, NULL);
214     cfgMerge(szCARevocationPath, NULL);
215     cfgMerge(szCARevocationFile, NULL);
216     cfgMerge(pRevocationStore, NULL);
217
218     for (i = 0; i < SSL_AIDX_MAX; i++) {
219         cfgMergeString(szPublicCertFile[i]);
220         cfgMergeString(szPrivateKeyFile[i]);
221         cfgMerge(pPublicCert[i], NULL);
222         cfgMerge(pPrivateKey[i], NULL);
223     }
224
225 #ifdef SSL_EXPERIMENTAL_PROXY
226     cfgMergeInt(nProxyVerifyDepth);
227     cfgMergeString(szProxyCACertificatePath);
228     cfgMergeString(szProxyCACertificateFile);
229     cfgMergeString(szProxyClientCertificateFile);
230     cfgMergeString(szProxyClientCertificatePath);
231     cfgMergeString(szProxyCipherSuite);
232     cfgMerge(nProxyProtocol, (SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1));
233     cfgMergeBool(bProxyVerify);
234     cfgMerge(pSSLProxyCtx, NULL);
235 #endif
236
237     return new;
238 }
239
240 /*
241  *  Create per-directory SSL configuration
242  */
243 void *ssl_config_perdir_create(apr_pool_t *p, char *dir)
244 {
245     SSLDirConfigRec *dc = apr_palloc(p, sizeof(*dc));
246
247     dc->bSSLRequired  = FALSE;
248     dc->aRequirement  = apr_array_make(p, 4, sizeof(ssl_require_t));
249     dc->nOptions      = SSL_OPT_NONE|SSL_OPT_RELSET;
250     dc->nOptionsAdd   = SSL_OPT_NONE;
251     dc->nOptionsDel   = SSL_OPT_NONE;
252
253     dc->szCipherSuite          = NULL;
254     dc->nVerifyClient          = SSL_CVERIFY_UNSET;
255     dc->nVerifyDepth           = UNSET;
256
257 #ifdef SSL_EXPERIMENTAL_PERDIRCA
258     dc->szCACertificatePath    = NULL;
259     dc->szCACertificateFile    = NULL;
260 #endif
261
262     return dc;
263 }
264
265 /*
266  *  Merge per-directory SSL configurations
267  */
268 void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv)
269 {
270     SSLDirConfigRec *base = (SSLDirConfigRec *)basev;
271     SSLDirConfigRec *add  = (SSLDirConfigRec *)addv;
272     SSLDirConfigRec *new  = (SSLDirConfigRec *)apr_palloc(p, sizeof(*new));
273
274     cfgMerge(bSSLRequired, FALSE);
275     cfgMergeArray(aRequirement);
276
277     if (add->nOptions & SSL_OPT_RELSET) {
278         new->nOptionsAdd =
279             (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd;
280         new->nOptionsDel =
281             (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel;
282         new->nOptions    =
283             (base->nOptions    & ~(new->nOptionsDel)) | new->nOptionsAdd;
284     }
285     else {
286         new->nOptions    = add->nOptions;
287         new->nOptionsAdd = add->nOptionsAdd;
288         new->nOptionsDel = add->nOptionsDel;
289     }
290
291     cfgMergeString(szCipherSuite);
292     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
293     cfgMergeInt(nVerifyDepth);
294
295 #ifdef SSL_EXPERIMENTAL_PERDIRCA
296     cfgMergeString(szCACertificatePath);
297     cfgMergeString(szCACertificateFile);
298 #endif
299
300     return new;
301 }
302
303 /*
304  *  Configuration functions for particular directives
305  */
306
307 const char *ssl_cmd_SSLMutex(cmd_parms *cmd, void *ctx,
308                              const char *arg)
309 {
310     const char *err;
311     SSLModConfigRec *mc = myModConfig(cmd->server);
312
313     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
314         return err;
315     }
316
317     if (ssl_config_global_isfixed(mc)) {
318         return NULL;
319     }
320
321     if (strcEQ(arg, "none") || strcEQ(arg, "no")) {
322         mc->nMutexMode  = SSL_MUTEXMODE_NONE;
323     }
324     else if (strlen(arg) > 5 && strcEQn(arg, "file:", 5)) {
325         mc->nMutexMode  = SSL_MUTEXMODE_USED;
326         mc->szMutexFile =
327             (char *)apr_psprintf(mc->pPool, "%s.%lu",
328                                  ap_server_root_relative(cmd->pool, arg+5),
329                                  (unsigned long)getpid());
330     }
331     else if (strcEQ(arg, "sem") || strcEQ(arg, "yes")) {
332         mc->nMutexMode  = SSL_MUTEXMODE_USED;
333         mc->szMutexFile = NULL; /* APR determines temporary filename */
334     }
335     else {
336         return "SSLMutex: Invalid argument";
337     }
338
339     return NULL;
340 }
341
342 const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd, void *ctx,
343                                         const char *arg)
344 {
345     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
346     const char *err;
347     int arglen = strlen(arg);
348
349     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
350         return err;
351     }
352
353     if (strcEQ(arg, "builtin")) {
354         sc->nPassPhraseDialogType  = SSL_PPTYPE_BUILTIN;
355         sc->szPassPhraseDialogPath = NULL;
356     }
357     else if ((arglen > 5) && strEQn(arg, "exec:", 5)) {
358         sc->nPassPhraseDialogType  = SSL_PPTYPE_FILTER;
359         /* XXX This is broken, exec: may contain args! */
360         sc->szPassPhraseDialogPath =
361             ap_server_root_relative(cmd->pool, arg+5);
362         
363         if (!ssl_util_path_check(SSL_PCM_EXISTS,
364                                  sc->szPassPhraseDialogPath,
365                                  cmd->pool))
366         {
367             return apr_pstrcat(cmd->pool,
368                                "SSLPassPhraseDialog: file '",
369                                sc->szPassPhraseDialogPath,
370                                "' does not exist", NULL);
371         }
372
373     }
374     else if ((arglen > 1) && (arg[0] == '|')) {
375         sc->nPassPhraseDialogType  = SSL_PPTYPE_PIPE;
376         sc->szPassPhraseDialogPath = arg + 1;
377     }
378     else {
379         return "SSLPassPhraseDialog: Invalid argument";
380     }
381
382     return NULL;
383 }
384
385 #ifdef SSL_EXPERIMENTAL_ENGINE
386 const char *ssl_cmd_SSLCryptoDevice(cmd_parms *cmd, void *ctx,
387                                     const char *arg)
388 {
389     SSLModConfigRec *mc = myModConfig(cmd->server);
390     const char *err;
391     ENGINE *e;
392 #if SSL_LIBRARY_VERSION >= 0x00907000
393     static int loaded_engines = FALSE;
394
395     /* early loading to make sure the engines are already 
396        available for ENGINE_by_id() above... */
397     if (!loaded_engines) {
398         ENGINE_load_builtin_engines();
399         loaded_engines = TRUE;
400     }
401 #endif
402     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
403         return err;
404     }
405
406     if (strcEQ(arg, "builtin")) {
407         mc->szCryptoDevice = NULL;
408     }
409     else if ((e = ENGINE_by_id(arg))) {
410         mc->szCryptoDevice = arg;
411         ENGINE_free(e);
412     }
413     else {
414         return "SSLCryptoDevice: Invalid argument";
415     }
416
417     return NULL;
418 }
419 #endif
420
421 const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd, void *ctx,
422                                   const char *arg1, 
423                                   const char *arg2,
424                                   const char *arg3)
425 {
426     SSLModConfigRec *mc = myModConfig(cmd->server);
427     const char *err;
428     ssl_randseed_t *seed;
429     int arg2len = strlen(arg2);
430
431     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
432         return err;
433     }
434
435     if (ssl_config_global_isfixed(mc)) {
436         return NULL;
437     }
438
439     seed = apr_array_push(mc->aRandSeed);
440
441     if (strcEQ(arg1, "startup")) {
442         seed->nCtx = SSL_RSCTX_STARTUP;
443     }
444     else if (strcEQ(arg1, "connect")) {
445         seed->nCtx = SSL_RSCTX_CONNECT;
446     }
447     else {
448         return apr_pstrcat(cmd->pool, "SSLRandomSeed: "
449                            "invalid context: `", arg1, "'",
450                            NULL);
451     }
452
453     if ((arg2len > 5) && strEQn(arg2, "file:", 5)) {
454         seed->nSrc   = SSL_RSSRC_FILE;
455         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
456     }
457     else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) {
458         seed->nSrc   = SSL_RSSRC_EXEC;
459         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
460     }
461     else if ((arg2len > 4) && strEQn(arg2, "egd:", 4)) {
462         seed->nSrc   = SSL_RSSRC_EGD;
463         seed->cpPath = ap_server_root_relative(mc->pPool, arg2+4);
464     }
465     else if (strcEQ(arg2, "builtin")) {
466         seed->nSrc   = SSL_RSSRC_BUILTIN;
467         seed->cpPath = NULL;
468     }
469     else {
470         seed->nSrc   = SSL_RSSRC_FILE;
471         seed->cpPath = ap_server_root_relative(mc->pPool, arg2);
472     }
473
474     if (seed->nSrc != SSL_RSSRC_BUILTIN) {
475         if (!ssl_util_path_check(SSL_PCM_EXISTS, seed->cpPath, cmd->pool)) {
476             return apr_pstrcat(cmd->pool,
477                                "SSLRandomSeed: source path '",
478                                seed->cpPath, "' does not exist", NULL);
479         }
480     }
481
482     if (!arg3) {
483         seed->nBytes = 0; /* read whole file */
484     }
485     else {
486         if (seed->nSrc == SSL_RSSRC_BUILTIN) {
487             return "SSLRandomSeed: byte specification not "
488                    "allowed for builtin seed source";
489         }
490
491         seed->nBytes = atoi(arg3);
492
493         if (seed->nBytes < 0) {
494             return "SSLRandomSeed: invalid number of bytes specified";
495         }
496     }
497
498     return NULL;
499 }
500
501 const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *ctx, int flag)
502 {
503     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
504
505     sc->bEnabled = flag ? TRUE : FALSE;
506
507     return NULL;
508 }
509
510 const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd, void *ctx,
511                                    const char *arg)
512 {
513     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
514     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
515
516     if (!(cmd->path || dc)) {
517         sc->szCipherSuite = arg;
518     }
519     else {
520         dc->szCipherSuite = (char *)arg;
521     }
522
523     return NULL;
524 }
525
526 #define SSL_FLAGS_CHECK_FILE \
527     (SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO)
528
529 #define SSL_FLAGS_CHECK_DIR \
530     (SSL_PCM_EXISTS|SSL_PCM_ISDIR)
531
532 static const char *ssl_cmd_check_file(cmd_parms *parms,
533                                       const char **file)
534 {
535     *file = ap_server_root_relative(parms->pool, *file);
536
537     if (ssl_util_path_check(SSL_FLAGS_CHECK_FILE, *file, parms->pool)) {
538         return NULL;
539     }
540
541     return apr_pstrcat(parms->pool, parms->cmd->name,
542                        ": file '", *file, 
543                        "' does not exist or is empty", NULL);
544
545 }
546
547 static const char *ssl_cmd_check_dir(cmd_parms *parms,
548                                      const char **dir)
549 {
550     *dir = ap_server_root_relative(parms->pool, *dir);
551
552     if (ssl_util_path_check(SSL_FLAGS_CHECK_DIR, *dir, parms->pool)) {
553         return NULL;
554     }
555
556     return apr_pstrcat(parms->pool, parms->cmd->name,
557                        ": directory '", *dir, 
558                        "' does not exist", NULL);
559
560 }
561
562 #define SSL_AIDX_CERTS 1
563 #define SSL_AIDX_KEYS  2
564
565 static const char *ssl_cmd_check_aidx_max(cmd_parms *parms,
566                                           const char *arg,
567                                           int idx)
568 {
569     SSLSrvConfigRec *sc = mySrvConfig(parms->server);
570     const char *err, *desc, **files;
571     int i;
572
573     if ((err = ssl_cmd_check_file(parms, &arg))) {
574         return err;
575     }
576
577     switch (idx) {
578       case SSL_AIDX_CERTS:
579         desc = "certificates";
580         files = sc->szPublicCertFile;
581         break;
582       case SSL_AIDX_KEYS:
583         desc = "private keys";
584         files = sc->szPrivateKeyFile;
585         break;
586     }
587
588     for (i = 0; i < SSL_AIDX_MAX; i++) {
589         if (!files[i]) {
590             files[i] = arg;
591             return NULL;
592         }
593     }
594
595     return apr_psprintf(parms->pool,
596                         "%s: only up to %d "
597                         "different %s per virtual host allowed", 
598                          parms->cmd->name, SSL_AIDX_MAX, desc);
599 }
600
601 const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd, void *ctx,
602                                        const char *arg)
603 {
604
605     const char *err;
606
607     if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_CERTS))) {
608         return err;
609     }
610
611     return NULL;
612 }
613
614 const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd, void *ctx,
615                                           const char *arg)
616 {
617     const char *err;
618
619     if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_KEYS))) {
620         return err;
621     }
622
623     return NULL;
624 }
625
626 const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, void *ctx,
627                                             const char *arg)
628 {
629     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
630     const char *err;
631
632     if ((err = ssl_cmd_check_file(cmd, &arg))) {
633         return err;
634     }
635
636     sc->szCertificateChain = arg;
637
638     return NULL;
639 }
640
641 const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *ctx,
642                                          const char *arg)
643 {
644 #ifdef SSL_EXPERIMENTAL_PERDIRCA
645     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
646 #endif
647     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
648     const char *err;
649
650     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
651         return err;
652     }
653
654 #ifdef SSL_EXPERIMENTAL_PERDIRCA
655     if (!(cmd->path || dc)) {
656         sc->szCACertificatePath = arg;
657     }
658     else {
659         dc->szCACertificatePath = arg;
660     }
661 #else
662     sc->szCACertificatePath = arg;
663 #endif
664
665     return NULL;
666 }
667
668 const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd, void *ctx,
669                                          const char *arg)
670 {
671 #ifdef SSL_EXPERIMENTAL_PERDIRCA
672     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
673 #endif
674     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
675     const char *err;
676
677     if ((err = ssl_cmd_check_file(cmd, &arg))) {
678         return err;
679     }
680
681 #ifdef SSL_EXPERIMENTAL_PERDIRCA
682     if (!(cmd->path || dc)) {
683         sc->szCACertificateFile = arg;
684     }
685     else {
686         dc->szCACertificateFile = arg;
687     }
688 #else
689     sc->szCACertificateFile = arg;
690 #endif
691
692     return NULL;
693 }
694
695 const char *ssl_cmd_SSLCARevocationPath(cmd_parms *cmd, void *ctx,
696                                         const char *arg)
697 {
698     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
699     const char *err;
700
701     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
702         return err;
703     }
704
705     sc->szCARevocationPath = arg;
706
707     return NULL;
708 }
709
710 const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd, void *ctx,
711                                         const char *arg)
712 {
713     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
714     const char *err;
715
716     if ((err = ssl_cmd_check_file(cmd, &arg))) {
717         return err;
718     }
719
720     sc->szCARevocationFile = arg;
721
722     return NULL;
723 }
724
725 static const char *ssl_cmd_verify_parse(cmd_parms *parms,
726                                         const char *arg,
727                                         ssl_verify_t *id)
728 {
729     if (strcEQ(arg, "none") || strcEQ(arg, "off")) {
730         *id = SSL_CVERIFY_NONE;
731     }
732     else if (strcEQ(arg, "optional")) {
733         *id = SSL_CVERIFY_OPTIONAL;
734     }
735     else if (strcEQ(arg, "require") || strcEQ(arg, "on")) {
736         *id = SSL_CVERIFY_REQUIRE;
737     }
738     else if (strcEQ(arg, "optional_no_ca")) {
739         *id = SSL_CVERIFY_OPTIONAL_NO_CA;
740     }
741     else {
742         return apr_pstrcat(parms->temp_pool, parms->cmd->name,
743                            ": Invalid argument '", arg, "'",
744                            NULL);
745     }
746
747     return NULL;
748 }
749
750 const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd, void *ctx,
751                                     const char *arg)
752 {
753     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
754     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
755     ssl_verify_t id;
756     const char *err;
757
758     if ((err = ssl_cmd_verify_parse(cmd, arg, &id))) {
759         return err;
760     }
761     
762     if (!(cmd->path || dc)) {
763         sc->nVerifyClient = id;
764     }
765     else {
766         dc->nVerifyClient = id;
767     }
768
769     return NULL;
770 }
771
772 static const char *ssl_cmd_verify_depth_parse(cmd_parms *parms,
773                                               const char *arg,
774                                               int *depth)
775 {
776     if ((*depth = atoi(arg)) >= 0) {
777         return NULL;
778     }
779
780     return apr_pstrcat(parms->temp_pool, parms->cmd->name,
781                        ": Invalid argument '", arg, "'",
782                        NULL);
783 }
784
785 const char *ssl_cmd_SSLVerifyDepth(cmd_parms *cmd, void *ctx,
786                                    const char *arg)
787 {
788     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
789     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
790     int depth;
791     const char *err;
792
793     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
794         return err;
795     }
796
797     if (!(cmd->path || dc)) {
798         sc->nVerifyDepth = depth;
799     }
800     else {
801         dc->nVerifyDepth = depth;
802     }
803
804     return NULL;
805 }
806
807 const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd, void *ctx,
808                                     const char *arg)
809 {
810     SSLModConfigRec *mc = myModConfig(cmd->server);
811     const char *err, *colon;
812     char *cp, *cp2;
813     int maxsize;
814     int arglen = strlen(arg);
815
816     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
817         return err;
818     }
819
820     if (ssl_config_global_isfixed(mc)) {
821         return NULL;
822     }
823
824     if (strcEQ(arg, "none")) {
825         mc->nSessionCacheMode      = SSL_SCMODE_NONE;
826         mc->szSessionCacheDataFile = NULL;
827     }
828     else if ((arglen > 4) && strcEQn(arg, "dbm:", 4)) {
829         mc->nSessionCacheMode      = SSL_SCMODE_DBM;
830         mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+4);
831     }
832     else if (((arglen > 4) && strcEQn(arg, "shm:", 4)) ||
833              ((arglen > 6) && strcEQn(arg, "shmht:", 6)))
834     {
835 #if 0 /* XXX */
836         if (!ap_mm_useable()) {
837             return "SSLSessionCache: shared memory cache "
838                    "not useable on this platform";
839         }
840 #endif
841
842         mc->nSessionCacheMode = SSL_SCMODE_SHMHT;
843         colon = ap_strchr_c(arg, ':');
844         mc->szSessionCacheDataFile =
845             ap_server_root_relative(mc->pPool, colon+1);
846         mc->tSessionCacheDataTable = NULL;
847         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
848
849         if ((cp = strchr(mc->szSessionCacheDataFile, '('))) {
850             *cp++ = NUL;
851
852             if (!(cp2 = strchr(cp, ')'))) {
853                 return "SSLSessionCache: Invalid argument: "
854                        "no closing parenthesis";
855             }
856
857             *cp2 = NUL;
858
859             mc->nSessionCacheDataSize = atoi(cp);
860
861             if (mc->nSessionCacheDataSize <= 8192) {
862                 return "SSLSessionCache: Invalid argument: "
863                        "size has to be >= 8192 bytes";
864             }
865
866 #if 0 /* XXX */
867             maxsize = ap_mm_core_maxsegsize();
868 #else
869             maxsize = 1024 * 512;
870 #endif
871
872             if (mc->nSessionCacheDataSize >= maxsize) {
873                 return apr_psprintf(cmd->pool,
874                                     "SSLSessionCache: Invalid argument: "
875                                     "size has to be < %d bytes on this "
876                                     "platform", maxsize);
877             }
878         }
879     }
880     else if ((arglen > 6) && strcEQn(arg, "shmcb:", 6)) {
881 #if 0 /* XXX */
882         if (!ap_mm_useable()) {
883             return "SSLSessionCache: shared memory cache "
884                    "not useable on this platform";
885         }
886 #endif
887         mc->nSessionCacheMode      = SSL_SCMODE_SHMCB;
888         mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+6);
889         mc->tSessionCacheDataTable = NULL;
890         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
891
892         if ((cp = strchr(mc->szSessionCacheDataFile, '('))) {
893             *cp++ = NUL;
894
895             if ((cp2 = strchr(cp, ')'))) {
896                 return "SSLSessionCache: Invalid argument: "
897                        "no closing parenthesis";
898             }
899
900             *cp2 = NUL;
901
902             mc->nSessionCacheDataSize = atoi(cp);
903
904             if (mc->nSessionCacheDataSize <= 8192) {
905                 return "SSLSessionCache: Invalid argument: "
906                        "size has to be >= 8192 bytes";
907
908             }
909
910 #if 0 /* XXX */
911             maxsize = ap_mm_core_maxsegsize();
912 #else
913             maxsize = 1024 * 512;
914 #endif
915
916             if (mc->nSessionCacheDataSize >= maxsize) {
917                 return apr_psprintf(cmd->pool,
918                                     "SSLSessionCache: Invalid argument: "
919                                     "size has to be < %d bytes on this "
920                                     "platform", maxsize);
921
922             }
923         }
924         else {
925             return "SSLSessionCache: Invalid argument";
926         }
927     }
928
929     return NULL;
930 }
931
932 const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *cmd, void *ctx,
933                                            const char *arg)
934 {
935     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
936
937     sc->nSessionCacheTimeout = atoi(arg);
938
939     if (sc->nSessionCacheTimeout < 0) {
940         return "SSLSessionCacheTimeout: Invalid argument";
941     }
942
943     return NULL;
944 }
945
946 #define SSL_FLAGS_LOG_CONTEXT \
947     (NOT_IN_LIMIT|NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES)
948
949 const char *ssl_cmd_SSLLog(cmd_parms *cmd, void *ctx,
950                            const char *arg)
951 {
952     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
953     const char *err;
954
955     if ((err = ap_check_cmd_context(cmd, SSL_FLAGS_LOG_CONTEXT))) {
956         return err;
957     }
958
959     sc->szLogFile = arg;
960
961     return NULL;
962 }
963
964 const char *ssl_cmd_SSLLogLevel(cmd_parms *cmd, void *ctx,
965                                 const char *level)
966 {
967     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
968     const char *err;
969
970     if ((err = ap_check_cmd_context(cmd, SSL_FLAGS_LOG_CONTEXT))) {
971         return err;
972     }
973
974     if (strcEQ(level, "none")) {
975         sc->nLogLevel = SSL_LOG_NONE;
976     }
977     else if (strcEQ(level, "error")) {
978         sc->nLogLevel = SSL_LOG_ERROR;
979     }
980     else if (strcEQ(level, "warn")) {
981         sc->nLogLevel = SSL_LOG_WARN;
982     }
983     else if (strcEQ(level, "info")) {
984         sc->nLogLevel = SSL_LOG_INFO;
985     }
986     else if (strcEQ(level, "trace")) {
987         sc->nLogLevel = SSL_LOG_TRACE;
988     }
989     else if (strcEQ(level, "debug")) {
990         sc->nLogLevel = SSL_LOG_DEBUG;
991     }
992     else {
993         return "SSLLogLevel: Invalid argument";
994     }
995
996     return NULL;
997 }
998
999 const char *ssl_cmd_SSLOptions(cmd_parms *cmd, void *ctx,
1000                                const char *arg)
1001 {
1002     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
1003     ssl_opt_t opt;
1004     int first = TRUE;
1005     char action, *w;
1006
1007     while (*arg) {
1008         w = ap_getword_conf(cmd->pool, &arg);
1009         action = NUL;
1010
1011         if ((*w == '+') || (*w == '-')) {
1012             action = *(w++);
1013         }
1014         else if (first) {
1015             dc->nOptions = SSL_OPT_NONE;
1016             first = FALSE;
1017         }
1018
1019         if (strcEQ(w, "StdEnvVars")) {
1020             opt = SSL_OPT_STDENVVARS;
1021         }
1022         else if (strcEQ(w, "CompatEnvVars")) {
1023             opt = SSL_OPT_COMPATENVVARS;
1024         }
1025         else if (strcEQ(w, "ExportCertData")) {
1026             opt = SSL_OPT_EXPORTCERTDATA;
1027         }
1028         else if (strcEQ(w, "FakeBasicAuth")) {
1029             opt = SSL_OPT_FAKEBASICAUTH;
1030         }
1031         else if (strcEQ(w, "StrictRequire")) {
1032             opt = SSL_OPT_STRICTREQUIRE;
1033         }
1034         else if (strcEQ(w, "OptRenegotiate")) {
1035             opt = SSL_OPT_OPTRENEGOTIATE;
1036         }
1037         else {
1038             return apr_pstrcat(cmd->pool,
1039                                "SSLOptions: Illegal option '", w, "'",
1040                                NULL);
1041         }
1042
1043         if (action == '-') {
1044             dc->nOptionsAdd &= ~opt;
1045             dc->nOptionsDel |=  opt;
1046             dc->nOptions    &= ~opt;
1047         }
1048         else if (action == '+') {
1049             dc->nOptionsAdd |=  opt;
1050             dc->nOptionsDel &= ~opt;
1051             dc->nOptions    |=  opt;
1052         }
1053         else {
1054             dc->nOptions    = opt;
1055             dc->nOptionsAdd = opt;
1056             dc->nOptionsDel = SSL_OPT_NONE;
1057         }
1058     }
1059
1060     return NULL;
1061 }
1062
1063 const char *ssl_cmd_SSLRequireSSL(cmd_parms *cmd, void *ctx)
1064 {
1065     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
1066
1067     dc->bSSLRequired = TRUE;
1068
1069     return NULL;
1070 }
1071
1072 const char *ssl_cmd_SSLRequire(cmd_parms *cmd, void *ctx,
1073                                const char *arg)
1074 {
1075     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
1076     ssl_expr *expr;
1077     ssl_require_t *require;
1078
1079     if (!(expr = ssl_expr_comp(cmd->pool, (char *)arg))) {
1080         return apr_pstrcat(cmd->pool, "SSLRequire: ",
1081                            ssl_expr_get_error(), NULL);
1082     }
1083
1084     require = apr_array_push(dc->aRequirement);
1085     require->cpExpr = apr_pstrdup(cmd->pool, arg);
1086     require->mpExpr = expr;
1087
1088     return NULL;
1089 }
1090
1091 static const char *ssl_cmd_protocol_parse(cmd_parms *parms,
1092                                           const char *arg,
1093                                           ssl_proto_t *options)
1094 {
1095     ssl_proto_t thisopt;
1096
1097     *options = SSL_PROTOCOL_NONE;
1098
1099     while (*arg) {
1100         char *w = ap_getword_conf(parms->temp_pool, &arg);
1101         char action = '\0';
1102
1103         if ((*w == '+') || (*w == '-')) {
1104             action = *(w++);
1105         }
1106
1107         if (strcEQ(w, "SSLv2")) {
1108             thisopt = SSL_PROTOCOL_SSLV2;
1109         }
1110         else if (strcEQ(w, "SSLv3")) {
1111             thisopt = SSL_PROTOCOL_SSLV3;
1112         }
1113         else if (strcEQ(w, "TLSv1")) {
1114             thisopt = SSL_PROTOCOL_TLSV1;
1115         }
1116         else if (strcEQ(w, "all")) {
1117             thisopt = SSL_PROTOCOL_ALL;
1118         }
1119         else {
1120             return apr_pstrcat(parms->temp_pool,
1121                                parms->cmd->name,
1122                                ": Illegal protocol '",
1123                                w, "'", NULL);
1124         }
1125
1126         if (action == '-') {
1127             *options &= ~thisopt;
1128         }
1129         else if (action == '+') {
1130             *options |= thisopt;
1131         }
1132         else {
1133             *options = thisopt;
1134         }
1135     }
1136
1137     return NULL;
1138 }
1139
1140 const char *ssl_cmd_SSLProtocol(cmd_parms *cmd, void *ctx,
1141                                 const char *opt)
1142 {
1143     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1144
1145     return ssl_cmd_protocol_parse(cmd, opt, &sc->nProtocol);
1146 }
1147
1148 #ifdef SSL_EXPERIMENTAL_PROXY
1149
1150 const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cmd, char *struct_ptr,
1151                                      const char *opt)
1152 {
1153     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1154
1155     return ssl_cmd_protocol_parse(cmd, opt, &sc->nProxyProtocol);
1156 }
1157
1158 const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd, char *struct_ptr,
1159                                         char *arg)
1160 {
1161     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1162
1163     sc->szProxyCipherSuite = arg;
1164
1165     return NULL;
1166 }
1167
1168 const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd, char *struct_ptr,
1169                                    int flag)
1170 {
1171     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1172
1173     sc->bProxyVerify = flag ? TRUE : FALSE;
1174
1175     return NULL;
1176 }
1177
1178 const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd, char *struct_ptr,
1179                                         char *arg)
1180 {
1181     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1182     int depth;
1183     const char *err;
1184
1185     if ((err = ssl_cmd_verify_depth_parse(cmd, arg, &depth))) {
1186         return err;
1187     }
1188
1189     sc->nProxyVerifyDepth = depth;
1190
1191     return NULL;
1192 }
1193
1194 const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *cmd,
1195                                               char *struct_ptr,
1196                                               char *arg)
1197 {
1198     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1199     const char *err;
1200
1201     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1202         return err;
1203     }
1204
1205     sc->szProxyCACertificateFile = arg;
1206
1207     return NULL;
1208 }
1209
1210 const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *cmd,
1211                                               char *struct_ptr,
1212                                               char *arg)
1213 {
1214     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1215     const char *err;
1216
1217     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1218         return err;
1219     }
1220
1221     sc->szProxyCACertificatePath = arg;
1222
1223     return NULL;
1224 }
1225
1226 const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
1227                                                    char *struct_ptr,
1228                                                    char *arg)
1229 {
1230     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1231     const char *err;
1232
1233     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1234         return err;
1235     }
1236
1237     sc->szProxyClientCertificateFile = arg;
1238
1239     return NULL;
1240 }
1241
1242 const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd,
1243                                                    char *struct_ptr,
1244                                                    char *arg)
1245 {
1246     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1247     const char *err;
1248
1249     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1250         return err;
1251     }
1252
1253     sc->szProxyClientCertificatePath = arg;
1254
1255     return NULL;
1256 }
1257
1258 #endif /* SSL_EXPERIMENTAL_PROXY */
1259