]> granicus.if.org Git - apache/blob - modules/ssl/ssl_engine_config.c
folding some command handler duplication into two generic functions:
[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 const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd, void *ctx,
563                                        const char *arg)
564 {
565     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
566     const char *err;
567     int i;
568
569     if ((err = ssl_cmd_check_file(cmd, &arg))) {
570         return err;
571     }
572
573     for (i = 0; i < SSL_AIDX_MAX; i++) {
574         if (!sc->szPublicCertFile[i]) {
575             sc->szPublicCertFile[i] = arg;
576             return NULL;
577         }
578     }
579
580     return apr_psprintf(cmd->pool,
581                         "SSLCertificateFile: only up to %d "
582                         "different certificates per virtual host allowed", 
583                         SSL_AIDX_MAX);
584 }
585
586 const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd, void *ctx,
587                                           const char *arg)
588 {
589     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
590     const char *err;
591     int i;
592
593     if ((err = ssl_cmd_check_file(cmd, &arg))) {
594         return err;
595     }
596
597     for (i = 0; i < SSL_AIDX_MAX; i++) {
598         if (!sc->szPrivateKeyFile[i]) {
599             sc->szPrivateKeyFile[i] = arg;
600             return NULL;
601         }
602     }
603
604     return apr_psprintf(cmd->pool,
605                         "SSLCertificateKeyFile: only up to %d "
606                         "different private keys per virtual host allowed", 
607                         SSL_AIDX_MAX);
608 }
609
610 const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, void *ctx,
611                                             const char *arg)
612 {
613     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
614     const char *err;
615
616     if ((err = ssl_cmd_check_file(cmd, &arg))) {
617         return err;
618     }
619
620     sc->szCertificateChain = arg;
621
622     return NULL;
623 }
624
625 const char *ssl_cmd_SSLCACertificatePath(cmd_parms *cmd, void *ctx,
626                                          const char *arg)
627 {
628 #ifdef SSL_EXPERIMENTAL_PERDIRCA
629     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
630 #endif
631     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
632     const char *err;
633
634     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
635         return err;
636     }
637
638 #ifdef SSL_EXPERIMENTAL_PERDIRCA
639     if (!(cmd->path || dc)) {
640         sc->szCACertificatePath = arg;
641     }
642     else {
643         dc->szCACertificatePath = arg;
644     }
645 #else
646     sc->szCACertificatePath = arg;
647 #endif
648
649     return NULL;
650 }
651
652 const char *ssl_cmd_SSLCACertificateFile(cmd_parms *cmd, void *ctx,
653                                          const char *arg)
654 {
655 #ifdef SSL_EXPERIMENTAL_PERDIRCA
656     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
657 #endif
658     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
659     const char *err;
660
661     if ((err = ssl_cmd_check_file(cmd, &arg))) {
662         return err;
663     }
664
665 #ifdef SSL_EXPERIMENTAL_PERDIRCA
666     if (!(cmd->path || dc)) {
667         sc->szCACertificateFile = arg;
668     }
669     else {
670         dc->szCACertificateFile = arg;
671     }
672 #else
673     sc->szCACertificateFile = arg;
674 #endif
675
676     return NULL;
677 }
678
679 const char *ssl_cmd_SSLCARevocationPath(cmd_parms *cmd, void *ctx,
680                                         const char *arg)
681 {
682     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
683     const char *err;
684
685     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
686         return err;
687     }
688
689     sc->szCARevocationPath = arg;
690
691     return NULL;
692 }
693
694 const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd, void *ctx,
695                                         const char *arg)
696 {
697     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
698     const char *err;
699
700     if ((err = ssl_cmd_check_file(cmd, &arg))) {
701         return err;
702     }
703
704     sc->szCARevocationFile = arg;
705
706     return NULL;
707 }
708
709 const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd, void *ctx,
710                                     const char *level)
711 {
712     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
713     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
714     ssl_verify_t id;
715
716     if (strEQ(level, "0") || strcEQ(level, "none")) {
717         id = SSL_CVERIFY_NONE;
718     }
719     else if (strEQ(level, "1") || strcEQ(level, "optional")) {
720         id = SSL_CVERIFY_OPTIONAL;
721     }
722     else if (strEQ(level, "2") || strcEQ(level, "require")) {
723         id = SSL_CVERIFY_REQUIRE;
724     }
725     else if (strEQ(level, "3") || strcEQ(level, "optional_no_ca")) {
726         id = SSL_CVERIFY_OPTIONAL_NO_CA;
727     }
728     else {
729         return "SSLVerifyClient: Invalid argument";
730     }
731
732     if (!(cmd->path || dc)) {
733         sc->nVerifyClient = id;
734     }
735     else {
736         dc->nVerifyClient = id;
737     }
738
739     return NULL;
740 }
741
742 const char *ssl_cmd_SSLVerifyDepth(cmd_parms *cmd, void *ctx,
743                                    const char *arg)
744 {
745     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
746     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
747     int d = atoi(arg);
748
749     if (d < 0) {
750         return "SSLVerifyDepth: Invalid argument";
751     }
752
753     if (!(cmd->path || dc)) {
754         sc->nVerifyDepth = d;
755     }
756     else {
757         dc->nVerifyDepth = d;
758     }
759
760     return NULL;
761 }
762
763 const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd, void *ctx,
764                                     const char *arg)
765 {
766     SSLModConfigRec *mc = myModConfig(cmd->server);
767     const char *err, *colon;
768     char *cp, *cp2;
769     int maxsize;
770     int arglen = strlen(arg);
771
772     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
773         return err;
774     }
775
776     if (ssl_config_global_isfixed(mc)) {
777         return NULL;
778     }
779
780     if (strcEQ(arg, "none")) {
781         mc->nSessionCacheMode      = SSL_SCMODE_NONE;
782         mc->szSessionCacheDataFile = NULL;
783     }
784     else if ((arglen > 4) && strcEQn(arg, "dbm:", 4)) {
785         mc->nSessionCacheMode      = SSL_SCMODE_DBM;
786         mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+4);
787     }
788     else if (((arglen > 4) && strcEQn(arg, "shm:", 4)) ||
789              ((arglen > 6) && strcEQn(arg, "shmht:", 6)))
790     {
791 #if 0 /* XXX */
792         if (!ap_mm_useable()) {
793             return "SSLSessionCache: shared memory cache "
794                    "not useable on this platform";
795         }
796 #endif
797
798         mc->nSessionCacheMode = SSL_SCMODE_SHMHT;
799         colon = ap_strchr_c(arg, ':');
800         mc->szSessionCacheDataFile =
801             ap_server_root_relative(mc->pPool, colon+1);
802         mc->tSessionCacheDataTable = NULL;
803         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
804
805         if ((cp = strchr(mc->szSessionCacheDataFile, '('))) {
806             *cp++ = NUL;
807
808             if (!(cp2 = strchr(cp, ')'))) {
809                 return "SSLSessionCache: Invalid argument: "
810                        "no closing parenthesis";
811             }
812
813             *cp2 = NUL;
814
815             mc->nSessionCacheDataSize = atoi(cp);
816
817             if (mc->nSessionCacheDataSize <= 8192) {
818                 return "SSLSessionCache: Invalid argument: "
819                        "size has to be >= 8192 bytes";
820             }
821
822 #if 0 /* XXX */
823             maxsize = ap_mm_core_maxsegsize();
824 #else
825             maxsize = 1024 * 512;
826 #endif
827
828             if (mc->nSessionCacheDataSize >= maxsize) {
829                 return apr_psprintf(cmd->pool,
830                                     "SSLSessionCache: Invalid argument: "
831                                     "size has to be < %d bytes on this "
832                                     "platform", maxsize);
833             }
834         }
835     }
836     else if ((arglen > 6) && strcEQn(arg, "shmcb:", 6)) {
837 #if 0 /* XXX */
838         if (!ap_mm_useable()) {
839             return "SSLSessionCache: shared memory cache "
840                    "not useable on this platform";
841         }
842 #endif
843         mc->nSessionCacheMode      = SSL_SCMODE_SHMCB;
844         mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+6);
845         mc->tSessionCacheDataTable = NULL;
846         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
847
848         if ((cp = strchr(mc->szSessionCacheDataFile, '('))) {
849             *cp++ = NUL;
850
851             if ((cp2 = strchr(cp, ')'))) {
852                 return "SSLSessionCache: Invalid argument: "
853                        "no closing parenthesis";
854             }
855
856             *cp2 = NUL;
857
858             mc->nSessionCacheDataSize = atoi(cp);
859
860             if (mc->nSessionCacheDataSize <= 8192) {
861                 return "SSLSessionCache: Invalid argument: "
862                        "size has to be >= 8192 bytes";
863
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 {
881             return "SSLSessionCache: Invalid argument";
882         }
883     }
884
885     return NULL;
886 }
887
888 const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *cmd, void *ctx,
889                                            const char *arg)
890 {
891     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
892
893     sc->nSessionCacheTimeout = atoi(arg);
894
895     if (sc->nSessionCacheTimeout < 0) {
896         return "SSLSessionCacheTimeout: Invalid argument";
897     }
898
899     return NULL;
900 }
901
902 #define SSL_FLAGS_LOG_CONTEXT \
903     (NOT_IN_LIMIT|NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES)
904
905 const char *ssl_cmd_SSLLog(cmd_parms *cmd, void *ctx,
906                            const char *arg)
907 {
908     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
909     const char *err;
910
911     if ((err = ap_check_cmd_context(cmd, SSL_FLAGS_LOG_CONTEXT))) {
912         return err;
913     }
914
915     sc->szLogFile = arg;
916
917     return NULL;
918 }
919
920 const char *ssl_cmd_SSLLogLevel(cmd_parms *cmd, void *ctx,
921                                 const char *level)
922 {
923     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
924     const char *err;
925
926     if ((err = ap_check_cmd_context(cmd, SSL_FLAGS_LOG_CONTEXT))) {
927         return err;
928     }
929
930     if (strcEQ(level, "none")) {
931         sc->nLogLevel = SSL_LOG_NONE;
932     }
933     else if (strcEQ(level, "error")) {
934         sc->nLogLevel = SSL_LOG_ERROR;
935     }
936     else if (strcEQ(level, "warn")) {
937         sc->nLogLevel = SSL_LOG_WARN;
938     }
939     else if (strcEQ(level, "info")) {
940         sc->nLogLevel = SSL_LOG_INFO;
941     }
942     else if (strcEQ(level, "trace")) {
943         sc->nLogLevel = SSL_LOG_TRACE;
944     }
945     else if (strcEQ(level, "debug")) {
946         sc->nLogLevel = SSL_LOG_DEBUG;
947     }
948     else {
949         return "SSLLogLevel: Invalid argument";
950     }
951
952     return NULL;
953 }
954
955 const char *ssl_cmd_SSLOptions(cmd_parms *cmd, void *ctx,
956                                const char *arg)
957 {
958     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
959     ssl_opt_t opt;
960     int first = TRUE;
961     char action, *w;
962
963     while (*arg) {
964         w = ap_getword_conf(cmd->pool, &arg);
965         action = NUL;
966
967         if ((*w == '+') || (*w == '-')) {
968             action = *(w++);
969         }
970         else if (first) {
971             dc->nOptions = SSL_OPT_NONE;
972             first = FALSE;
973         }
974
975         if (strcEQ(w, "StdEnvVars")) {
976             opt = SSL_OPT_STDENVVARS;
977         }
978         else if (strcEQ(w, "CompatEnvVars")) {
979             opt = SSL_OPT_COMPATENVVARS;
980         }
981         else if (strcEQ(w, "ExportCertData")) {
982             opt = SSL_OPT_EXPORTCERTDATA;
983         }
984         else if (strcEQ(w, "FakeBasicAuth")) {
985             opt = SSL_OPT_FAKEBASICAUTH;
986         }
987         else if (strcEQ(w, "StrictRequire")) {
988             opt = SSL_OPT_STRICTREQUIRE;
989         }
990         else if (strcEQ(w, "OptRenegotiate")) {
991             opt = SSL_OPT_OPTRENEGOTIATE;
992         }
993         else {
994             return apr_pstrcat(cmd->pool,
995                                "SSLOptions: Illegal option '", w, "'",
996                                NULL);
997         }
998
999         if (action == '-') {
1000             dc->nOptionsAdd &= ~opt;
1001             dc->nOptionsDel |=  opt;
1002             dc->nOptions    &= ~opt;
1003         }
1004         else if (action == '+') {
1005             dc->nOptionsAdd |=  opt;
1006             dc->nOptionsDel &= ~opt;
1007             dc->nOptions    |=  opt;
1008         }
1009         else {
1010             dc->nOptions    = opt;
1011             dc->nOptionsAdd = opt;
1012             dc->nOptionsDel = SSL_OPT_NONE;
1013         }
1014     }
1015
1016     return NULL;
1017 }
1018
1019 const char *ssl_cmd_SSLRequireSSL(cmd_parms *cmd, void *ctx)
1020 {
1021     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
1022
1023     dc->bSSLRequired = TRUE;
1024
1025     return NULL;
1026 }
1027
1028 const char *ssl_cmd_SSLRequire(cmd_parms *cmd, void *ctx,
1029                                const char *arg)
1030 {
1031     SSLDirConfigRec *dc = (SSLDirConfigRec *)ctx;
1032     ssl_expr *expr;
1033     ssl_require_t *require;
1034
1035     if (!(expr = ssl_expr_comp(cmd->pool, (char *)arg))) {
1036         return apr_pstrcat(cmd->pool, "SSLRequire: ",
1037                            ssl_expr_get_error(), NULL);
1038     }
1039
1040     require = apr_array_push(dc->aRequirement);
1041     require->cpExpr = apr_pstrdup(cmd->pool, arg);
1042     require->mpExpr = expr;
1043
1044     return NULL;
1045 }
1046
1047 const char *ssl_cmd_SSLProtocol(cmd_parms *cmd, void *ctx,
1048                                 const char *opt)
1049 {
1050     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1051     ssl_proto_t thisopt, options = SSL_PROTOCOL_NONE;
1052
1053     while (*opt) {
1054         char *w = ap_getword_conf(cmd->pool, &opt);
1055         char action = '\0';
1056
1057         if ((*w == '+') || (*w == '-')) {
1058             action = *(w++);
1059         }
1060
1061         if (strcEQ(w, "SSLv2")) {
1062             thisopt = SSL_PROTOCOL_SSLV2;
1063         }
1064         else if (strcEQ(w, "SSLv3")) {
1065             thisopt = SSL_PROTOCOL_SSLV3;
1066         }
1067         else if (strcEQ(w, "TLSv1")) {
1068             thisopt = SSL_PROTOCOL_TLSV1;
1069         }
1070         else if (strcEQ(w, "all")) {
1071             thisopt = SSL_PROTOCOL_ALL;
1072         }
1073         else {
1074             return apr_pstrcat(cmd->pool,
1075                                "SSLProtocol: Illegal protocol '",
1076                                w, "'", NULL);
1077         }
1078
1079         if (action == '-') {
1080             options &= ~thisopt;
1081         }
1082         else if (action == '+') {
1083             options |= thisopt;
1084         }
1085         else {
1086             options = thisopt;
1087         }
1088     }
1089
1090     sc->nProtocol = options;
1091
1092     return NULL;
1093 }
1094
1095 #ifdef SSL_EXPERIMENTAL_PROXY
1096
1097 const char *ssl_cmd_SSLProxyProtocol(cmd_parms *cmd, char *struct_ptr,
1098                                      const char *opt)
1099 {
1100     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1101     ssl_proto_t thisopt, options = SSL_PROTOCOL_NONE;
1102
1103     while (*opt) {
1104         char *w = ap_getword_conf(cmd->pool, &opt);
1105         char action = '\0';
1106
1107         if ((*w == '+') || (*w == '-')) {
1108             action = *(w++);
1109         }
1110
1111         if (strcEQ(w, "SSLv2")) {
1112             thisopt = SSL_PROTOCOL_SSLV2;
1113         }
1114         else if (strcEQ(w, "SSLv3")) {
1115             thisopt = SSL_PROTOCOL_SSLV3;
1116         }
1117         else if (strcEQ(w, "TLSv1")) {
1118             thisopt = SSL_PROTOCOL_TLSV1;
1119         }
1120         else if (strcEQ(w, "all")) {
1121             thisopt = SSL_PROTOCOL_ALL;
1122         }
1123         else {
1124             return apr_pstrcat(cmd->pool,
1125                                "SSLProxyProtocol: Illegal protocol '",
1126                                w, "'", NULL);
1127         }
1128
1129         if (action == '-') {
1130             options &= ~thisopt;
1131         }
1132         else if (action == '+') {
1133             options |= thisopt;
1134         }
1135         else {
1136             options = thisopt;
1137         }
1138     }
1139
1140     sc->nProxyProtocol = options;
1141
1142     return NULL;
1143 }
1144
1145 const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd, char *struct_ptr,
1146                                         char *arg)
1147 {
1148     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1149
1150     sc->szProxyCipherSuite = arg;
1151
1152     return NULL;
1153 }
1154
1155 const char *ssl_cmd_SSLProxyVerify(cmd_parms *cmd, char *struct_ptr,
1156                                    int flag)
1157 {
1158     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1159
1160     sc->bProxyVerify = flag ? TRUE : FALSE;
1161
1162     return NULL;
1163 }
1164
1165 const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *cmd, char *struct_ptr,
1166                                         char *arg)
1167 {
1168     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1169     int d = atoi(arg);
1170
1171     if (d < 0) {
1172         return "SSLProxyVerifyDepth: Invalid argument";
1173     }
1174
1175     sc->nProxyVerifyDepth = d;
1176
1177     return NULL;
1178 }
1179
1180 const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *cmd,
1181                                               char *struct_ptr,
1182                                               char *arg)
1183 {
1184     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1185     const char *err;
1186
1187     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1188         return err;
1189     }
1190
1191     sc->szProxyCACertificateFile = arg;
1192
1193     return NULL;
1194 }
1195
1196 const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *cmd,
1197                                               char *struct_ptr,
1198                                               char *arg)
1199 {
1200     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1201     const char *err;
1202
1203     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1204         return err;
1205     }
1206
1207     sc->szProxyCACertificatePath = arg;
1208
1209     return NULL;
1210 }
1211
1212 const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
1213                                                    char *struct_ptr,
1214                                                    char *arg)
1215 {
1216     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1217     const char *err;
1218
1219     if ((err = ssl_cmd_check_file(cmd, &arg))) {
1220         return err;
1221     }
1222
1223     sc->szProxyClientCertificateFile = arg;
1224
1225     return NULL;
1226 }
1227
1228 const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *cmd,
1229                                                    char *struct_ptr,
1230                                                    char *arg)
1231 {
1232     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1233     const char *err;
1234
1235     if ((err = ssl_cmd_check_dir(cmd, &arg))) {
1236         return err;
1237     }
1238
1239     sc->szProxyClientCertificatePath = arg;
1240
1241     return NULL;
1242 }
1243
1244 #endif /* SSL_EXPERIMENTAL_PROXY */
1245