]> granicus.if.org Git - apache/blob - modules/ssl/ssl_engine_config.c
mod_ssl integration step 2:
[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 **
68 **  Support for Global Configuration
69 **  _________________________________________________________________
70 */
71
72 void ssl_hook_AddModule(module *m)
73 {
74     if (m == &ssl_module) {
75         /*
76          * Announce us for the configuration files
77          */
78         ap_add_config_define("MOD_SSL");
79
80         /*
81          * Link ourself into the Apache kernel
82          */
83         ssl_var_register();
84         ssl_ext_register();
85         ssl_io_register();
86 #if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
87         ssl_vendor_register();
88 #endif
89     }
90     return;
91 }
92
93 void ssl_hook_RemoveModule(module *m)
94 {
95     if (m == &ssl_module) {
96         /*
97          * Unlink ourself from the Apache kernel
98          */
99         ssl_var_unregister();
100         ssl_ext_unregister();
101         ssl_io_unregister();
102 #if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
103         ssl_vendor_unregister();
104 #endif
105     }
106     return;
107 }
108
109 void ssl_config_global_create(void)
110 {
111     pool *pPool;
112     SSLModConfigRec *mc;
113
114     mc = ap_ctx_get(ap_global_ctx, "ssl_module");
115     if (mc == NULL) {
116         /*
117          * allocate an own subpool which survives server restarts
118          */
119         pPool = ap_make_sub_pool(NULL);
120         mc = (SSLModConfigRec *)ap_palloc(pPool, sizeof(SSLModConfigRec));
121         mc->pPool = pPool;
122         mc->bFixed = FALSE;
123
124         /*
125          * initialize per-module configuration
126          */
127         mc->nInitCount             = 0;
128         mc->nSessionCacheMode      = SSL_SCMODE_UNSET;
129         mc->szSessionCacheDataFile = NULL;
130         mc->nSessionCacheDataSize  = 0;
131         mc->pSessionCacheDataMM    = NULL;
132         mc->tSessionCacheDataTable = NULL;
133         mc->nMutexMode             = SSL_MUTEXMODE_UNSET;
134         mc->szMutexFile            = NULL;
135         mc->nMutexFD               = -1;
136         mc->nMutexSEMID            = -1;
137         mc->aRandSeed              = ap_make_array(pPool, 4, sizeof(ssl_randseed_t));
138         mc->tPrivateKey            = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
139         mc->tPublicCert            = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
140         mc->tTmpKeys               = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
141 #ifdef SSL_EXPERIMENTAL_ENGINE
142         mc->szCryptoDevice         = NULL;
143 #endif
144
145         (void)memset(mc->pTmpKeys, 0, SSL_TKPIDX_MAX*sizeof(void *));
146
147 #ifdef SSL_VENDOR
148         mc->ctx = ap_ctx_new(pPool);
149         ap_hook_use("ap::mod_ssl::vendor::config_global_create",
150                 AP_HOOK_SIG2(void,ptr), AP_HOOK_MODE_ALL, mc);
151 #endif
152
153         /*
154          * And push it into Apache's global context
155          */
156         ap_ctx_set(ap_global_ctx, "ssl_module", mc);
157     }
158     return;
159 }
160
161 void ssl_config_global_fix(void)
162 {
163     SSLModConfigRec *mc = myModConfig();
164     mc->bFixed = TRUE;
165     return;
166 }
167
168 BOOL ssl_config_global_isfixed(void)
169 {
170     SSLModConfigRec *mc = myModConfig();
171     return (mc->bFixed);
172 }
173
174
175 /*  _________________________________________________________________
176 **
177 **  Configuration handling
178 **  _________________________________________________________________
179 */
180
181 /*
182  *  Create per-server SSL configuration
183  */
184 void *ssl_config_server_create(pool *p, server_rec *s)
185 {
186     SSLSrvConfigRec *sc;
187
188     ssl_config_global_create();
189
190     sc = ap_palloc(p, sizeof(SSLSrvConfigRec));
191     sc->bEnabled               = UNSET;
192     sc->szCACertificatePath    = NULL;
193     sc->szCACertificateFile    = NULL;
194     sc->szCertificateChain     = NULL;
195     sc->szLogFile              = NULL;
196     sc->szCipherSuite          = NULL;
197     sc->nLogLevel              = SSL_LOG_NONE;
198     sc->nVerifyDepth           = UNSET;
199     sc->nVerifyClient          = SSL_CVERIFY_UNSET;
200     sc->nSessionCacheTimeout   = UNSET;
201     sc->nPassPhraseDialogType  = SSL_PPTYPE_UNSET;
202     sc->szPassPhraseDialogPath = NULL;
203     sc->nProtocol              = SSL_PROTOCOL_ALL;
204     sc->fileLogFile            = NULL;
205     sc->pSSLCtx                = NULL;
206     sc->szCARevocationPath     = NULL;
207     sc->szCARevocationFile     = NULL;
208     sc->pRevocationStore       = NULL;
209
210 #ifdef SSL_EXPERIMENTAL_PROXY
211     sc->nProxyVerifyDepth             = UNSET;
212     sc->szProxyCACertificatePath      = NULL;
213     sc->szProxyCACertificateFile      = NULL;
214     sc->szProxyClientCertificateFile  = NULL;
215     sc->szProxyClientCertificatePath  = NULL;
216     sc->szProxyCipherSuite            = NULL;
217     sc->nProxyProtocol                = SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1;
218     sc->bProxyVerify                  = UNSET;
219     sc->pSSLProxyCtx                  = NULL;
220 #endif
221
222     (void)memset(sc->szPublicCertFile, 0, SSL_AIDX_MAX*sizeof(char *));
223     (void)memset(sc->szPrivateKeyFile, 0, SSL_AIDX_MAX*sizeof(char *));
224     (void)memset(sc->pPublicCert, 0, SSL_AIDX_MAX*sizeof(X509 *));
225     (void)memset(sc->pPrivateKey, 0, SSL_AIDX_MAX*sizeof(EVP_PKEY *));
226
227 #ifdef SSL_VENDOR
228     sc->ctx = ap_ctx_new(p);
229     ap_hook_use("ap::mod_ssl::vendor::config_server_create",
230                 AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
231                 p, s, sc);
232 #endif
233
234     return sc;
235 }
236
237 /*
238  *  Merge per-server SSL configurations
239  */
240 void *ssl_config_server_merge(pool *p, void *basev, void *addv)
241 {
242     SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
243     SSLSrvConfigRec *add  = (SSLSrvConfigRec *)addv;
244     SSLSrvConfigRec *new  = (SSLSrvConfigRec *)ap_palloc(p, sizeof(SSLSrvConfigRec));
245     int i;
246
247     cfgMergeBool(bEnabled);
248     cfgMergeString(szCACertificatePath);
249     cfgMergeString(szCACertificateFile);
250     cfgMergeString(szCertificateChain);
251     cfgMergeString(szLogFile);
252     cfgMergeString(szCipherSuite);
253     cfgMerge(nLogLevel, SSL_LOG_NONE);
254     cfgMergeInt(nVerifyDepth);
255     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
256     cfgMergeInt(nSessionCacheTimeout);
257     cfgMerge(nPassPhraseDialogType, SSL_PPTYPE_UNSET);
258     cfgMergeString(szPassPhraseDialogPath);
259     cfgMerge(nProtocol, SSL_PROTOCOL_ALL);
260     cfgMerge(fileLogFile, NULL);
261     cfgMerge(pSSLCtx, NULL);
262     cfgMerge(szCARevocationPath, NULL);
263     cfgMerge(szCARevocationFile, NULL);
264     cfgMerge(pRevocationStore, NULL);
265
266     for (i = 0; i < SSL_AIDX_MAX; i++) {
267         cfgMergeString(szPublicCertFile[i]);
268         cfgMergeString(szPrivateKeyFile[i]);
269         cfgMerge(pPublicCert[i], NULL);
270         cfgMerge(pPrivateKey[i], NULL);
271     }
272
273 #ifdef SSL_VENDOR
274     cfgMergeCtx(ctx);
275     ap_hook_use("ap::mod_ssl::vendor::config_server_merge",
276                 AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
277                 p, base, add, new);
278 #endif
279
280 #ifdef SSL_EXPERIMENTAL_PROXY
281     cfgMergeInt(nProxyVerifyDepth);
282     cfgMergeString(szProxyCACertificatePath);
283     cfgMergeString(szProxyCACertificateFile);
284     cfgMergeString(szProxyClientCertificateFile);
285     cfgMergeString(szProxyClientCertificatePath);
286     cfgMergeString(szProxyCipherSuite);
287     cfgMerge(nProxyProtocol, (SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1));
288     cfgMergeBool(bProxyVerify);
289     cfgMerge(pSSLProxyCtx, NULL);
290 #endif
291
292     return new;
293 }
294
295 /*
296  *  Create per-directory SSL configuration
297  */
298 void *ssl_config_perdir_create(pool *p, char *dir)
299 {
300     SSLDirConfigRec *dc = ap_palloc(p, sizeof(SSLDirConfigRec));
301
302     dc->bSSLRequired  = FALSE;
303     dc->aRequirement  = ap_make_array(p, 4, sizeof(ssl_require_t));
304     dc->nOptions      = SSL_OPT_NONE|SSL_OPT_RELSET;
305     dc->nOptionsAdd   = SSL_OPT_NONE;
306     dc->nOptionsDel   = SSL_OPT_NONE;
307
308     dc->szCipherSuite          = NULL;
309     dc->nVerifyClient          = SSL_CVERIFY_UNSET;
310     dc->nVerifyDepth           = UNSET;
311 #ifdef SSL_EXPERIMENTAL_PERDIRCA
312     dc->szCACertificatePath    = NULL;
313     dc->szCACertificateFile    = NULL;
314 #endif
315
316 #ifdef SSL_VENDOR
317     dc->ctx = ap_ctx_new(p);
318     ap_hook_use("ap::mod_ssl::vendor::config_perdir_create",
319                 AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
320                 p, dir, dc);
321 #endif
322
323     return dc;
324 }
325
326 /*
327  *  Merge per-directory SSL configurations
328  */
329 void *ssl_config_perdir_merge(pool *p, void *basev, void *addv)
330 {
331     SSLDirConfigRec *base = (SSLDirConfigRec *)basev;
332     SSLDirConfigRec *add  = (SSLDirConfigRec *)addv;
333     SSLDirConfigRec *new  = (SSLDirConfigRec *)ap_palloc(p,
334                                                sizeof(SSLDirConfigRec));
335
336     cfgMerge(bSSLRequired, FALSE);
337     cfgMergeArray(aRequirement);
338
339     if (add->nOptions & SSL_OPT_RELSET) {
340         new->nOptionsAdd = (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd;
341         new->nOptionsDel = (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel;
342         new->nOptions    = (base->nOptions    & ~(new->nOptionsDel)) | new->nOptionsAdd;
343     }
344     else {
345         new->nOptions    = add->nOptions;
346         new->nOptionsAdd = add->nOptionsAdd;
347         new->nOptionsDel = add->nOptionsDel;
348     }
349
350     cfgMergeString(szCipherSuite);
351     cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
352     cfgMergeInt(nVerifyDepth);
353 #ifdef SSL_EXPERIMENTAL_PERDIRCA
354     cfgMergeString(szCACertificatePath);
355     cfgMergeString(szCACertificateFile);
356 #endif
357
358 #ifdef SSL_VENDOR
359     cfgMergeCtx(ctx);
360     ap_hook_use("ap::mod_ssl::vendor::config_perdir_merge",
361                 AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
362                 p, base, add, new);
363 #endif
364
365     return new;
366 }
367
368 /*
369  * Directive Rewriting
370  */
371
372 char *ssl_hook_RewriteCommand(cmd_parms *cmd, void *config, const char *cmd_line)
373 {
374 #ifdef SSL_COMPAT
375     return ssl_compat_directive(cmd->server, cmd->pool, cmd_line);
376 #else
377     return NULL;
378 #endif
379 }
380
381 /*
382  *  Configuration functions for particular directives
383  */
384
385 const char *ssl_cmd_SSLMutex(
386     cmd_parms *cmd, char *struct_ptr, char *arg)
387 {
388     const char *err;
389     SSLModConfigRec *mc = myModConfig();
390
391     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
392         return err;
393     if (ssl_config_global_isfixed())
394         return NULL;
395     if (strcEQ(arg, "none")) {
396         mc->nMutexMode  = SSL_MUTEXMODE_NONE;
397     }
398     else if (strlen(arg) > 5 && strcEQn(arg, "file:", 5)) {
399 #ifndef WIN32
400         mc->nMutexMode  = SSL_MUTEXMODE_FILE;
401         mc->szMutexFile = ap_psprintf(mc->pPool, "%s.%lu",
402                                       ssl_util_server_root_relative(cmd->pool, "mutex", arg+5),
403                                       (unsigned long)getpid());
404 #else
405         return "SSLMutex: Lockfiles not available on this platform";
406 #endif
407     }
408     else if (strcEQ(arg, "sem")) {
409 #ifdef SSL_CAN_USE_SEM
410         mc->nMutexMode  = SSL_MUTEXMODE_SEM;
411 #else
412         return "SSLMutex: Semaphores not available on this platform";
413 #endif
414     }
415     else
416         return "SSLMutex: Invalid argument";
417     return NULL;
418 }
419
420 const char *ssl_cmd_SSLPassPhraseDialog(
421     cmd_parms *cmd, char *struct_ptr, char *arg)
422 {
423     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
424     const char *err;
425
426     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
427         return err;
428     if (strcEQ(arg, "builtin")) {
429         sc->nPassPhraseDialogType  = SSL_PPTYPE_BUILTIN;
430         sc->szPassPhraseDialogPath = NULL;
431     }
432     else if (strlen(arg) > 5 && strEQn(arg, "exec:", 5)) {
433         sc->nPassPhraseDialogType  = SSL_PPTYPE_FILTER;
434         sc->szPassPhraseDialogPath = ssl_util_server_root_relative(cmd->pool, "dialog", arg+5);
435         if (!ssl_util_path_check(SSL_PCM_EXISTS, sc->szPassPhraseDialogPath))
436             return ap_pstrcat(cmd->pool, "SSLPassPhraseDialog: file '",
437                               sc->szPassPhraseDialogPath, "' not exists", NULL);
438     }
439     else
440         return "SSLPassPhraseDialog: Invalid argument";
441     return NULL;
442 }
443
444 #ifdef SSL_EXPERIMENTAL_ENGINE
445 const char *ssl_cmd_SSLCryptoDevice(
446     cmd_parms *cmd, char *struct_ptr, char *arg)
447 {
448     SSLModConfigRec *mc = myModConfig();
449     const char *err;
450     ENGINE *e;
451 #if SSL_LIBRARY_VERSION >= 0x00907000
452     static int loaded_engines = FALSE;
453
454     /* early loading to make sure the engines are already 
455        available for ENGINE_by_id() above... */
456     if (!loaded_engines) {
457         ENGINE_load_builtin_engines();
458         loaded_engines = TRUE;
459     }
460 #endif
461     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
462         return err;
463     if (strcEQ(arg, "builtin")) {
464         mc->szCryptoDevice = NULL;
465     }
466     else if ((e = ENGINE_by_id(arg)) != NULL) {
467         mc->szCryptoDevice = arg;
468         ENGINE_free(e);
469     }
470     else
471         return "SSLCryptoDevice: Invalid argument";
472     return NULL;
473 }
474 #endif
475
476 const char *ssl_cmd_SSLRandomSeed(
477     cmd_parms *cmd, char *struct_ptr, char *arg1, char *arg2, char *arg3)
478 {
479     SSLModConfigRec *mc = myModConfig();
480     const char *err;
481     ssl_randseed_t *pRS;
482
483     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
484         return err;
485     if (ssl_config_global_isfixed())
486         return NULL;
487     pRS = ap_push_array(mc->aRandSeed);
488     if (strcEQ(arg1, "startup"))
489         pRS->nCtx = SSL_RSCTX_STARTUP;
490     else if (strcEQ(arg1, "connect"))
491         pRS->nCtx = SSL_RSCTX_CONNECT;
492     else
493         return ap_pstrcat(cmd->pool, "SSLRandomSeed: "
494                           "invalid context: `", arg1, "'");
495     if (strlen(arg2) > 5 && strEQn(arg2, "file:", 5)) {
496         pRS->nSrc   = SSL_RSSRC_FILE;
497         pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+5));
498     }
499     else if (strlen(arg2) > 5 && strEQn(arg2, "exec:", 5)) {
500         pRS->nSrc   = SSL_RSSRC_EXEC;
501         pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+5));
502     }
503 #if SSL_LIBRARY_VERSION >= 0x00905100
504     else if (strlen(arg2) > 4 && strEQn(arg2, "egd:", 4)) {
505         pRS->nSrc   = SSL_RSSRC_EGD;
506         pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+4));
507     }
508 #endif
509     else if (strcEQ(arg2, "builtin")) {
510         pRS->nSrc   = SSL_RSSRC_BUILTIN;
511         pRS->cpPath = NULL;
512     }
513     else {
514         pRS->nSrc   = SSL_RSSRC_FILE;
515         pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2));
516     }
517     if (pRS->nSrc != SSL_RSSRC_BUILTIN)
518         if (!ssl_util_path_check(SSL_PCM_EXISTS, pRS->cpPath))
519             return ap_pstrcat(cmd->pool, "SSLRandomSeed: source path '",
520                               pRS->cpPath, "' not exists", NULL);
521     if (arg3 == NULL)
522         pRS->nBytes = 0; /* read whole file */
523     else {
524         if (pRS->nSrc == SSL_RSSRC_BUILTIN)
525             return "SSLRandomSeed: byte specification not "
526                    "allowed for builtin seed source";
527         pRS->nBytes = atoi(arg3);
528         if (pRS->nBytes < 0)
529             return "SSLRandomSeed: invalid number of bytes specified";
530     }
531     return NULL;
532 }
533
534 const char *ssl_cmd_SSLEngine(
535     cmd_parms *cmd, char *struct_ptr, int flag)
536 {
537     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
538
539     sc->bEnabled = (flag ? TRUE : FALSE);
540     return NULL;
541 }
542
543 const char *ssl_cmd_SSLCipherSuite(
544     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
545 {
546     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
547
548     if (cmd->path == NULL || dc == NULL)
549         sc->szCipherSuite = arg;
550     else
551         dc->szCipherSuite = arg;
552     return NULL;
553 }
554
555 const char *ssl_cmd_SSLCertificateFile(
556     cmd_parms *cmd, char *struct_ptr, char *arg)
557 {
558     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
559     char *cpPath;
560     int i;
561
562     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
563     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
564         return ap_pstrcat(cmd->pool, "SSLCertificateFile: file '",
565                           cpPath, "' not exists or empty", NULL);
566     for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++)
567         ;
568     if (i == SSL_AIDX_MAX)
569         return ap_psprintf(cmd->pool, "SSLCertificateFile: only up to %d "
570                           "different certificates per virtual host allowed", 
571                           SSL_AIDX_MAX);
572     sc->szPublicCertFile[i] = cpPath;
573     return NULL;
574 }
575
576 const char *ssl_cmd_SSLCertificateKeyFile(
577     cmd_parms *cmd, char *struct_ptr, char *arg)
578 {
579     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
580     char *cpPath;
581     int i;
582
583     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
584     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
585         return ap_pstrcat(cmd->pool, "SSLCertificateKeyFile: file '",
586                           cpPath, "' not exists or empty", NULL);
587     for (i = 0; i < SSL_AIDX_MAX && sc->szPrivateKeyFile[i] != NULL; i++)
588         ;
589     if (i == SSL_AIDX_MAX)
590         return ap_psprintf(cmd->pool, "SSLCertificateKeyFile: only up to %d "
591                           "different private keys per virtual host allowed", 
592                           SSL_AIDX_MAX);
593     sc->szPrivateKeyFile[i] = cpPath;
594     return NULL;
595 }
596
597 const char *ssl_cmd_SSLCertificateChainFile(
598     cmd_parms *cmd, char *struct_ptr, char *arg)
599 {
600     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
601     char *cpPath;
602
603     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
604     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
605         return ap_pstrcat(cmd->pool, "SSLCertificateChainFile: file '",
606                           cpPath, "' not exists or empty", NULL);
607     sc->szCertificateChain = cpPath;
608     return NULL;
609 }
610
611 const char *ssl_cmd_SSLCACertificatePath(
612     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
613 {
614     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
615     char *cpPath;
616
617     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
618     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
619         return ap_pstrcat(cmd->pool, "SSLCACertificatePath: directory '",
620                           cpPath, "' not exists", NULL);
621 #ifdef SSL_EXPERIMENTAL_PERDIRCA
622     if (cmd->path == NULL || dc == NULL)
623         sc->szCACertificatePath = cpPath;
624     else
625         dc->szCACertificatePath = cpPath;
626 #else
627     sc->szCACertificatePath = cpPath;
628 #endif
629     return NULL;
630 }
631
632 const char *ssl_cmd_SSLCACertificateFile(
633     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
634 {
635     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
636     char *cpPath;
637
638     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
639     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
640         return ap_pstrcat(cmd->pool, "SSLCACertificateFile: file '",
641                           cpPath, "' not exists or empty", NULL);
642 #ifdef SSL_EXPERIMENTAL_PERDIRCA
643     if (cmd->path == NULL || dc == NULL)
644         sc->szCACertificateFile = cpPath;
645     else
646         dc->szCACertificateFile = cpPath;
647 #else
648     sc->szCACertificateFile = cpPath;
649 #endif
650     return NULL;
651 }
652
653 const char *ssl_cmd_SSLCARevocationPath(
654     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
655 {
656     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
657     char *cpPath;
658
659     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
660     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
661         return ap_pstrcat(cmd->pool, "SSLCARecocationPath: directory '",
662                           cpPath, "' not exists", NULL);
663     sc->szCARevocationPath = cpPath;
664     return NULL;
665 }
666
667 const char *ssl_cmd_SSLCARevocationFile(
668     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
669 {
670     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
671     char *cpPath;
672
673     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
674     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
675         return ap_pstrcat(cmd->pool, "SSLCARevocationFile: file '",
676                           cpPath, "' not exists or empty", NULL);
677     sc->szCARevocationFile = cpPath;
678     return NULL;
679 }
680
681 const char *ssl_cmd_SSLVerifyClient(
682     cmd_parms *cmd, SSLDirConfigRec *dc, char *level)
683 {
684     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
685     ssl_verify_t id;
686
687     if (strEQ(level, "0") || strcEQ(level, "none"))
688         id = SSL_CVERIFY_NONE;
689     else if (strEQ(level, "1") || strcEQ(level, "optional"))
690         id = SSL_CVERIFY_OPTIONAL;
691     else if (strEQ(level, "2") || strcEQ(level, "require"))
692         id = SSL_CVERIFY_REQUIRE;
693     else if (strEQ(level, "3") || strcEQ(level, "optional_no_ca"))
694         id = SSL_CVERIFY_OPTIONAL_NO_CA;
695     else
696         return "SSLVerifyClient: Invalid argument";
697     if (cmd->path == NULL || dc == NULL)
698         sc->nVerifyClient = id;
699     else
700         dc->nVerifyClient = id;
701     return NULL;
702 }
703
704 const char *ssl_cmd_SSLVerifyDepth(
705     cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
706 {
707     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
708     int d;
709
710     d = atoi(arg);
711     if (d < 0)
712         return "SSLVerifyDepth: Invalid argument";
713     if (cmd->path == NULL || dc == NULL)
714         sc->nVerifyDepth = d;
715     else
716         dc->nVerifyDepth = d;
717     return NULL;
718 }
719
720 const char *ssl_cmd_SSLSessionCache(
721     cmd_parms *cmd, char *struct_ptr, char *arg)
722 {
723     const char *err;
724     SSLModConfigRec *mc = myModConfig();
725     char *cp, *cp2;
726     int maxsize;
727
728     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
729         return err;
730     if (ssl_config_global_isfixed())
731         return NULL;
732     if (strcEQ(arg, "none")) {
733         mc->nSessionCacheMode      = SSL_SCMODE_NONE;
734         mc->szSessionCacheDataFile = NULL;
735     }
736     else if (strlen(arg) > 4 && strcEQn(arg, "dbm:", 4)) {
737         mc->nSessionCacheMode      = SSL_SCMODE_DBM;
738         mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
739                                      ssl_util_server_root_relative(cmd->pool, "scache", arg+4));
740     }
741     else if (   (strlen(arg) > 4 && strcEQn(arg, "shm:",   4)) 
742              || (strlen(arg) > 6 && strcEQn(arg, "shmht:", 6))) {
743         if (!ap_mm_useable())
744             return "SSLSessionCache: shared memory cache not useable on this platform";
745         mc->nSessionCacheMode      = SSL_SCMODE_SHMHT;
746         cp = strchr(arg, ':');
747         mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
748                                      ssl_util_server_root_relative(cmd->pool, "scache", cp+1));
749         mc->tSessionCacheDataTable = NULL;
750         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
751         if ((cp = strchr(mc->szSessionCacheDataFile, '(')) != NULL) {
752             *cp++ = NUL;
753             if ((cp2 = strchr(cp, ')')) == NULL)
754                 return "SSLSessionCache: Invalid argument: no closing parenthesis";
755             *cp2 = NUL;
756             mc->nSessionCacheDataSize = atoi(cp);
757             if (mc->nSessionCacheDataSize <= 8192)
758                 return "SSLSessionCache: Invalid argument: size has to be >= 8192 bytes";
759             maxsize = ap_mm_core_maxsegsize();
760             if (mc->nSessionCacheDataSize >= maxsize)
761                 return ap_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: "
762                                    "size has to be < %d bytes on this platform", maxsize);
763         }
764     }
765     else if (strlen(arg) > 6 && strcEQn(arg, "shmcb:", 6)) {
766         if (!ap_mm_useable())
767             return "SSLSessionCache: shared memory cache not useable on this platform";
768         mc->nSessionCacheMode      = SSL_SCMODE_SHMCB;
769         mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
770                                      ap_server_root_relative(cmd->pool, arg+6));
771         mc->tSessionCacheDataTable = NULL;
772         mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
773         if ((cp = strchr(mc->szSessionCacheDataFile, '(')) != NULL) {
774             *cp++ = NUL;
775             if ((cp2 = strchr(cp, ')')) == NULL)
776                 return "SSLSessionCache: Invalid argument: no closing parenthesis";
777             *cp2 = NUL;
778             mc->nSessionCacheDataSize = atoi(cp);
779             if (mc->nSessionCacheDataSize <= 8192)
780                 return "SSLSessionCache: Invalid argument: size has to be >= 8192 bytes";
781             maxsize = ap_mm_core_maxsegsize();
782             if (mc->nSessionCacheDataSize >= maxsize)
783                 return ap_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: "
784                                    "size has to be < %d bytes on this platform", maxsize);
785         }
786     }
787         else
788 #ifdef SSL_VENDOR
789         if (!ap_hook_use("ap::mod_ssl::vendor::cmd_sslsessioncache",
790              AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
791              cmd, arg, mc))
792 #endif
793         return "SSLSessionCache: Invalid argument";
794     return NULL;
795 }
796
797 const char *ssl_cmd_SSLSessionCacheTimeout(
798     cmd_parms *cmd, char *struct_ptr, char *arg)
799 {
800     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
801
802     sc->nSessionCacheTimeout = atoi(arg);
803     if (sc->nSessionCacheTimeout < 0)
804         return "SSLSessionCacheTimeout: Invalid argument";
805     return NULL;
806 }
807
808 const char *ssl_cmd_SSLLog(
809     cmd_parms *cmd, char *struct_ptr, char *arg)
810 {
811     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
812     const char *err;
813
814     if ((err = ap_check_cmd_context(cmd,  NOT_IN_LIMIT|NOT_IN_DIRECTORY
815                                          |NOT_IN_LOCATION|NOT_IN_FILES )) != NULL)
816         return err;
817     sc->szLogFile = arg;
818     return NULL;
819 }
820
821 const char *ssl_cmd_SSLLogLevel(
822     cmd_parms *cmd, char *struct_ptr, char *level)
823 {
824     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
825     const char *err;
826
827     if ((err = ap_check_cmd_context(cmd,  NOT_IN_LIMIT|NOT_IN_DIRECTORY
828                                          |NOT_IN_LOCATION|NOT_IN_FILES )) != NULL)
829         return err;
830     if (strcEQ(level, "none"))
831         sc->nLogLevel = SSL_LOG_NONE;
832     else if (strcEQ(level, "error"))
833         sc->nLogLevel = SSL_LOG_ERROR;
834     else if (strcEQ(level, "warn"))
835         sc->nLogLevel = SSL_LOG_WARN;
836     else if (strcEQ(level, "info"))
837         sc->nLogLevel = SSL_LOG_INFO;
838     else if (strcEQ(level, "trace"))
839         sc->nLogLevel = SSL_LOG_TRACE;
840     else if (strcEQ(level, "debug"))
841         sc->nLogLevel = SSL_LOG_DEBUG;
842     else
843         return "SSLLogLevel: Invalid argument";
844     return NULL;
845 }
846
847 const char *ssl_cmd_SSLOptions(
848     cmd_parms *cmd, SSLDirConfigRec *dc, const char *cpLine)
849 {
850     ssl_opt_t opt;
851     int first;
852     char action;
853     char *w;
854
855     first = TRUE;
856     while (cpLine[0] != NUL) {
857         w = ap_getword_conf(cmd->pool, &cpLine);
858         action = NUL;
859
860         if (*w == '+' || *w == '-') {
861             action = *(w++);
862         }
863         else if (first) {
864             dc->nOptions = SSL_OPT_NONE;
865             first = FALSE;
866         }
867
868         if (strcEQ(w, "StdEnvVars"))
869             opt = SSL_OPT_STDENVVARS;
870         else if (strcEQ(w, "CompatEnvVars"))
871             opt = SSL_OPT_COMPATENVVARS;
872         else if (strcEQ(w, "ExportCertData"))
873             opt = SSL_OPT_EXPORTCERTDATA;
874         else if (strcEQ(w, "FakeBasicAuth"))
875             opt = SSL_OPT_FAKEBASICAUTH;
876         else if (strcEQ(w, "StrictRequire"))
877             opt = SSL_OPT_STRICTREQUIRE;
878         else if (strcEQ(w, "OptRenegotiate"))
879             opt = SSL_OPT_OPTRENEGOTIATE;
880         else
881             return ap_pstrcat(cmd->pool, "SSLOptions: Illegal option '", w, "'", NULL);
882
883         if (action == '-') {
884             dc->nOptionsAdd &= ~opt;
885             dc->nOptionsDel |=  opt;
886             dc->nOptions    &= ~opt;
887         }
888         else if (action == '+') {
889             dc->nOptionsAdd |=  opt;
890             dc->nOptionsDel &= ~opt;
891             dc->nOptions    |=  opt;
892         }
893         else {
894             dc->nOptions    = opt;
895             dc->nOptionsAdd = opt;
896             dc->nOptionsDel = SSL_OPT_NONE;
897         }
898     }
899     return NULL;
900 }
901
902 const char *ssl_cmd_SSLRequireSSL(
903     cmd_parms *cmd, SSLDirConfigRec *dc, char *cipher)
904 {
905     dc->bSSLRequired = TRUE;
906     return NULL;
907 }
908
909 const char *ssl_cmd_SSLRequire(
910     cmd_parms *cmd, SSLDirConfigRec *dc, char *cpExpr)
911 {
912     ssl_expr *mpExpr;
913     ssl_require_t *pReqRec;
914
915     if ((mpExpr = ssl_expr_comp(cmd->pool, cpExpr)) == NULL)
916         return ap_pstrcat(cmd->pool, "SSLRequire: ", ssl_expr_get_error(), NULL);
917     pReqRec = ap_push_array(dc->aRequirement);
918     pReqRec->cpExpr = ap_pstrdup(cmd->pool, cpExpr);
919     pReqRec->mpExpr = mpExpr;
920     return NULL;
921 }
922
923 const char *ssl_cmd_SSLProtocol(
924     cmd_parms *cmd, char *struct_ptr, const char *opt)
925 {
926     SSLSrvConfigRec *sc;
927     ssl_proto_t options, thisopt;
928     char action;
929     char *w;
930
931     sc = mySrvConfig(cmd->server);
932     options = SSL_PROTOCOL_NONE;
933     while (opt[0] != NUL) {
934         w = ap_getword_conf(cmd->pool, &opt);
935
936         action = NUL;
937         if (*w == '+' || *w == '-')
938             action = *(w++);
939
940         if (strcEQ(w, "SSLv2"))
941             thisopt = SSL_PROTOCOL_SSLV2;
942         else if (strcEQ(w, "SSLv3"))
943             thisopt = SSL_PROTOCOL_SSLV3;
944         else if (strcEQ(w, "TLSv1"))
945             thisopt = SSL_PROTOCOL_TLSV1;
946         else if (strcEQ(w, "all"))
947             thisopt = SSL_PROTOCOL_ALL;
948         else
949             return ap_pstrcat(cmd->pool, "SSLProtocol: Illegal protocol '", w, "'", NULL);
950
951         if (action == '-')
952             options &= ~thisopt;
953         else if (action == '+')
954             options |= thisopt;
955         else
956             options = thisopt;
957     }
958     sc->nProtocol = options;
959     return NULL;
960 }
961
962 #ifdef SSL_EXPERIMENTAL_PROXY
963
964 const char *ssl_cmd_SSLProxyProtocol(
965     cmd_parms *cmd, char *struct_ptr, const char *opt)
966 {
967     SSLSrvConfigRec *sc;
968     ssl_proto_t options, thisopt;
969     char action;
970     char *w;
971
972     sc = mySrvConfig(cmd->server);
973     options = SSL_PROTOCOL_NONE;
974     while (opt[0] != NUL) {
975         w = ap_getword_conf(cmd->pool, &opt);
976
977         action = NUL;
978         if (*w == '+' || *w == '-')
979             action = *(w++);
980
981         if (strcEQ(w, "SSLv2"))
982             thisopt = SSL_PROTOCOL_SSLV2;
983         else if (strcEQ(w, "SSLv3"))
984             thisopt = SSL_PROTOCOL_SSLV3;
985         else if (strcEQ(w, "TLSv1"))
986             thisopt = SSL_PROTOCOL_TLSV1;
987         else if (strcEQ(w, "all"))
988             thisopt = SSL_PROTOCOL_ALL;
989         else
990             return ap_pstrcat(cmd->pool, "SSLProxyProtocol: "
991                               "Illegal protocol '", w, "'", NULL);
992         if (action == '-')
993             options &= ~thisopt;
994         else if (action == '+')
995             options |= thisopt;
996         else
997             options = thisopt;
998     }
999     sc->nProxyProtocol = options;
1000     return NULL;
1001 }
1002
1003 const char *ssl_cmd_SSLProxyCipherSuite(
1004     cmd_parms *cmd, char *struct_ptr, char *arg)
1005 {
1006     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1007
1008     sc->szProxyCipherSuite = arg;
1009     return NULL;
1010 }
1011
1012 const char *ssl_cmd_SSLProxyVerify(
1013     cmd_parms *cmd, char *struct_ptr, int flag)
1014 {
1015     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1016
1017     sc->bProxyVerify = (flag ? TRUE : FALSE);
1018     return NULL;
1019 }
1020
1021 const char *ssl_cmd_SSLProxyVerifyDepth(
1022     cmd_parms *cmd, char *struct_ptr, char *arg)
1023 {
1024     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1025     int d;
1026
1027     d = atoi(arg);
1028     if (d < 0)
1029         return "SSLProxyVerifyDepth: Invalid argument";
1030     sc->nProxyVerifyDepth = d;
1031     return NULL;
1032 }
1033
1034 const char *ssl_cmd_SSLProxyCACertificateFile(
1035     cmd_parms *cmd, char *struct_ptr, char *arg)
1036 {
1037     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1038     char *cpPath;
1039
1040     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
1041     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
1042         return ap_pstrcat(cmd->pool, "SSLProxyCACertificateFile: file '",
1043                           cpPath, "' not exists or empty", NULL);
1044     sc->szProxyCACertificateFile = cpPath;
1045     return NULL;
1046 }
1047
1048 const char *ssl_cmd_SSLProxyCACertificatePath(
1049     cmd_parms *cmd, char *struct_ptr, char *arg)
1050 {
1051     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1052     char *cpPath;
1053
1054     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
1055     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
1056         return ap_pstrcat(cmd->pool, "SSLProxyCACertificatePath: directory '",
1057                           cpPath, "' does not exists", NULL);
1058     sc->szProxyCACertificatePath = cpPath;
1059     return NULL;
1060 }
1061
1062 const char *ssl_cmd_SSLProxyMachineCertificateFile(
1063     cmd_parms *cmd, char *struct_ptr, char *arg)
1064 {
1065     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1066     char *cpPath;
1067
1068     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
1069     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
1070         return ap_pstrcat(cmd->pool, "SSLProxyMachineCertFile: file '",
1071                           cpPath, "' not exists or empty", NULL);
1072     sc->szProxyClientCertificateFile = cpPath;
1073     return NULL;
1074 }
1075
1076 const char *ssl_cmd_SSLProxyMachineCertificatePath(
1077     cmd_parms *cmd, char *struct_ptr, char *arg)
1078 {
1079     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1080     char *cpPath;
1081
1082     cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
1083     if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
1084         return ap_pstrcat(cmd->pool, "SSLProxyMachineCertPath: directory '",
1085                           cpPath, "' does not exists", NULL);
1086     sc->szProxyClientCertificatePath = cpPath;
1087     return NULL;
1088 }
1089
1090 #endif /* SSL_EXPERIMENTAL_PROXY */
1091