diff options
Diffstat (limited to 'nss_engine_config.c')
-rw-r--r-- | nss_engine_config.c | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/nss_engine_config.c b/nss_engine_config.c new file mode 100644 index 0000000..d662763 --- /dev/null +++ b/nss_engine_config.c @@ -0,0 +1,535 @@ +/* Copyright 2001-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mod_nss.h" + +/* _________________________________________________________________ +** +** Support for Global Configuration +** _________________________________________________________________ +*/ + +#define SSL_MOD_CONFIG_KEY "nss_module" + +SSLModConfigRec *ssl_config_global_create(server_rec *s) +{ + apr_pool_t *pool = s->process->pool; + SSLModConfigRec *mc; + void *vmc; + + apr_pool_userdata_get(&vmc, SSL_MOD_CONFIG_KEY, pool); + if (vmc) { + return vmc; /* reused for lifetime of the server */ + } + + /* + * allocate an own subpool which survives server restarts + */ + mc = (SSLModConfigRec *)apr_palloc(pool, sizeof(*mc)); + mc->pPool = pool; + + /* + * initialize per-module configuration + */ + mc->nInitCount = 0; + mc->pCertificateDatabase = NULL; + mc->session_cache_size = UNSET; + mc->session_cache_timeout = UNSET; + mc->ssl3_session_cache_timeout = UNSET; + mc->pphrase_dialog_helper = NULL; + mc->pphrase_dialog_path = NULL; + + apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY, + apr_pool_cleanup_null, + pool); + + return mc; +} + +/* _________________________________________________________________ +** +** Configuration handling +** _________________________________________________________________ +*/ + +static void modnss_ctx_init(modnss_ctx_t *mctx) +{ + + ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "modnss_ctx_init"); + + mctx->sc = NULL; /* set during module init */ + + mctx->ssl2 = PR_FALSE; + mctx->ssl3 = PR_FALSE; + mctx->tls = PR_FALSE; + mctx->tlsrollback = PR_FALSE; + + mctx->nickname = NULL; + mctx->servercert = NULL; + mctx->serverkey = NULL; + + mctx->model = NULL; + + mctx->auth.protocols = NULL; + mctx->auth.cipher_suite = NULL; + mctx->auth.verify_mode = SSL_CVERIFY_UNSET; + +} + +static void modnss_ctx_init_server(SSLSrvConfigRec *sc, + apr_pool_t *p) +{ + modnss_ctx_t *mctx; + + mctx = sc->server = apr_palloc(p, sizeof(*sc->server)); + + modnss_ctx_init(mctx); +} + +static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) +{ + SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc)); + + sc->mc = NULL; + sc->enabled = UNSET; + sc->proxy_enabled = UNSET; + sc->vhost_id = NULL; /* set during module init */ + sc->vhost_id_len = 0; /* set during module init */ + sc->proxy = NULL; + sc->server = NULL; + +#ifdef PROXY + modssl_ctx_init_proxy(sc, p); +#endif + + modnss_ctx_init_server(sc, p); + + return sc; +} + +/* + * Create per-server SSL configuration + */ +void *ssl_config_server_create(apr_pool_t *p, server_rec *s) { + SSLSrvConfigRec *sc = ssl_config_server_new(p); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "ssl_config_server_create"); + + sc->mc = ssl_config_global_create(s); + + return sc; +} + +#define cfgMerge(el,unset) mrg->el = (add->el == (unset)) ? base->el : add->el +#define cfgMergeArray(el) mrg->el = apr_array_append(p, add->el, base->el) +#define cfgMergeString(el) cfgMerge(el, NULL) +#define cfgMergeBool(el) cfgMerge(el, UNSET) +#define cfgMergeInt(el) cfgMerge(el, UNSET) + +static void modnss_ctx_cfg_merge(modnss_ctx_t *base, + modnss_ctx_t *add, + modnss_ctx_t *mrg) +{ + cfgMerge(auth.protocols, NULL); + cfgMerge(auth.cipher_suite, NULL); + cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET); + + cfgMerge(nickname, NULL); +} + +static void modnss_ctx_cfg_merge_server(modnss_ctx_t *base, + modnss_ctx_t *add, + modnss_ctx_t *mrg) +{ + modnss_ctx_cfg_merge(base, add, mrg); +} + +/* + * Merge per-server SSL configurations + */ +void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) { + SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev; + SSLSrvConfigRec *add = (SSLSrvConfigRec *)addv; + SSLSrvConfigRec *mrg = ssl_config_server_new(p); + + ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "ssl_config_server_merge"); + + cfgMerge(mc, NULL); + cfgMergeBool(enabled); + cfgMergeBool(proxy_enabled); + +#ifdef PROXY + modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy); +#endif + + modnss_ctx_cfg_merge_server(base->server, add->server, mrg->server); + + return mrg; +} + +/* + * Create per-directory SSL configuration + */ +void *ssl_config_perdir_create(apr_pool_t *p, char *dir) { + SSLDirConfigRec *dc = apr_palloc(p, sizeof(*dc)); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "ssl_config_perdir_create"); + + dc->bSSLRequired = FALSE; + dc->aRequirement = apr_array_make(p, 4, sizeof(ssl_require_t)); + dc->nOptions = SSL_OPT_NONE|SSL_OPT_RELSET; + dc->nOptionsAdd = SSL_OPT_NONE; + dc->nOptionsDel = SSL_OPT_NONE; + + dc->szCipherSuite = NULL; + dc->nVerifyClient = SSL_CVERIFY_UNSET; + + dc->szUserName = NULL; + + return dc; +} + +const char *ssl_cmd_SSLRequireSSL(cmd_parms *cmd, void *dcfg) +{ + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + + dc->bSSLRequired = TRUE; + + return NULL; +} + +const char *ssl_cmd_SSLRequire(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + ssl_expr *expr; + ssl_require_t *require; + + if (!(expr = ssl_expr_comp(cmd->pool, (char *)arg))) { + return apr_pstrcat(cmd->pool, "SSLRequire: ", + ssl_expr_get_error(), NULL); + } + + require = apr_array_push(dc->aRequirement); + require->cpExpr = apr_pstrdup(cmd->pool, arg); + require->mpExpr = expr; + + return NULL; +} + +void *ssl_config_perdir_merge(apr_pool_t *p, void *basev, void *addv) { + SSLDirConfigRec *base = (SSLDirConfigRec *)basev; + SSLDirConfigRec *add = (SSLDirConfigRec *)addv; + SSLDirConfigRec *mrg = (SSLDirConfigRec *)apr_palloc(p, sizeof(*mrg)); + + cfgMerge(bSSLRequired, FALSE); + cfgMergeArray(aRequirement); + + if (add->nOptions & SSL_OPT_RELSET) { + mrg->nOptionsAdd = + (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd; + mrg->nOptionsDel = + (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel; + mrg->nOptions = + (base->nOptions & ~(mrg->nOptionsDel)) | mrg->nOptionsAdd; + } + else { + mrg->nOptions = add->nOptions; + mrg->nOptionsAdd = add->nOptionsAdd; + mrg->nOptionsDel = add->nOptionsDel; + } + + cfgMergeString(szCipherSuite); + cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET); + + cfgMergeString(szUserName); + + return mrg; +} + +const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, int flag) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->enabled = flag ? TRUE : FALSE; + + return NULL; +} + +const char *ssl_cmd_SSLCertificateDatabase(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + mc->pCertificateDatabase = arg; + + return NULL; +} + +const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + + if (cmd->path) { + dc->szCipherSuite = arg; + } + else { + sc->server->auth.cipher_suite = arg; + } + + return NULL; +} + +static const char *ssl_cmd_verify_parse(cmd_parms *parms, + const char *arg, + ssl_verify_t *id) +{ + if (strcEQ(arg, "none") || strcEQ(arg, "off")) { + *id = SSL_CVERIFY_NONE; + } + else if (strcEQ(arg, "optional")) { + *id = SSL_CVERIFY_OPTIONAL; + } + else if (strcEQ(arg, "require") || strcEQ(arg, "on")) { + *id = SSL_CVERIFY_REQUIRE; + } + else if (strcEQ(arg, "optional_no_ca")) { + return apr_pstrcat(parms->temp_pool, parms->cmd->name, + "SSL_CVERIFY_OPTIONAL_NO_CA is not supported", NULL); + } + else { + return apr_pstrcat(parms->temp_pool, parms->cmd->name, + ": Invalid argument '", arg, "'", + NULL); + } + + return NULL; +} + +const char *ssl_cmd_SSLVerifyClient(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + ssl_verify_t mode; + const char *err; + + if ((err = ssl_cmd_verify_parse(cmd, arg, &mode))) { + return err; + } + + if (cmd->path) { + dc->nVerifyClient = mode; + } + else { + sc->server->auth.verify_mode = mode; + } + + return NULL; +} + +const char *ssl_cmd_SSLProtocol(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->auth.protocols = arg; + + return NULL; +} + +const char *ssl_cmd_SSLNickname(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->server->nickname = arg; + + return NULL; +} + +const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + mc->session_cache_timeout = atoi(arg); + + if (mc->session_cache_timeout < 0) { + return "SSLSessionCacheTimeout: Invalid argument"; + } + + return NULL; +} + +const char *ssl_cmd_SSL3SessionCacheTimeout(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + mc->ssl3_session_cache_timeout = atoi(arg); + + if (mc->session_cache_timeout < 0) { + return "SSLSessionCacheTimeout: Invalid argument"; + } + + return NULL; +} + +const char *ssl_cmd_SSLSessionCacheSize(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + mc->session_cache_size = atoi(arg); + + if (mc->session_cache_size < 0) { + return "SSLSessionCacheTimeout: Invalid argument"; + } + + return NULL; +} + +const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + int arglen = strlen(arg); + + if (strcEQ(arg, "builtin")) { + mc->pphrase_dialog_type = SSL_PPTYPE_BUILTIN; + mc->pphrase_dialog_path = NULL; + } + else if ((arglen > 5) && strEQn(arg, "file:", 5)) { + apr_finfo_t finfo; + apr_status_t rc; + + mc->pphrase_dialog_type = SSL_PPTYPE_FILE; + mc->pphrase_dialog_path = ap_server_root_relative(cmd->pool, arg+5); + if (!mc->pphrase_dialog_path) + return apr_pstrcat(cmd->pool, + "Invalid SSLPassPhraseDialog file: path ", + arg+5, NULL); + rc = apr_stat(&finfo, mc->pphrase_dialog_path, + APR_FINFO_TYPE|APR_FINFO_SIZE, cmd->pool); + if ((rc != APR_SUCCESS) || (finfo.filetype != APR_REG)) { + return apr_pstrcat(cmd->pool, + "SSLPassPhraseDialog: file '", + mc->pphrase_dialog_path, + "' does not exist", NULL); + } + } + + return NULL; +} + +const char *ssl_cmd_SSLPassPhraseHelper(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLModConfigRec *mc = myModConfig(cmd->server); + + if (access(arg, R_OK|X_OK) != -1) { + mc->pphrase_dialog_helper = arg; + } else { + return apr_pstrcat(cmd->pool, + "SSLPassPhraseHelper: ", mc->pphrase_dialog_path, + "does not exist or is not executable.", NULL); + } + + return NULL; +} + +const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, + const char *arg) +{ + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + dc->szUserName = arg; + return NULL; +} + +const char *ssl_cmd_SSLOptions(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; + ssl_opt_t opt; + int first = TRUE; + char action, *w; + + while (*arg) { + w = ap_getword_conf(cmd->pool, &arg); + action = NUL; + + if ((*w == '+') || (*w == '-')) { + action = *(w++); + } + else if (first) { + dc->nOptions = SSL_OPT_NONE; + first = FALSE; + } + + if (strcEQ(w, "StdEnvVars")) { + opt = SSL_OPT_STDENVVARS; + } + else if (strcEQ(w, "CompatEnvVars")) { + opt = SSL_OPT_COMPATENVVARS; + } + else if (strcEQ(w, "ExportCertData")) { + opt = SSL_OPT_EXPORTCERTDATA; + } + else if (strcEQ(w, "FakeBasicAuth")) { + opt = SSL_OPT_FAKEBASICAUTH; + } + else if (strcEQ(w, "StrictRequire")) { + opt = SSL_OPT_STRICTREQUIRE; + } + else if (strcEQ(w, "OptRenegotiate")) { + opt = SSL_OPT_OPTRENEGOTIATE; + } + else { + return apr_pstrcat(cmd->pool, + "SSLOptions: Illegal option '", w, "'", + NULL); + } + if (action == '-') { + dc->nOptionsAdd &= ~opt; + dc->nOptionsDel |= opt; + dc->nOptions &= ~opt; + } + else if (action == '+') { + dc->nOptionsAdd |= opt; + dc->nOptionsDel &= ~opt; + dc->nOptions |= opt; + } + else { + dc->nOptions = opt; + dc->nOptionsAdd = opt; + dc->nOptionsDel = SSL_OPT_NONE; + } + } + + return NULL; +} |