static int ssl_expr_lookup(ap_expr_lookup_parms *parms) { switch (parms->type) { case AP_EXPR_FUNC_VAR: /* for now, we just handle everything that starts with SSL_, but * register our hook as APR_HOOK_LAST * XXX: This can be optimized */ if (strcEQn(parms->name, "SSL_", 4)) { *parms->func = expr_var_fn; *parms->data = parms->name + 4; return OK; } break; case AP_EXPR_FUNC_STRING: /* Function SSL() is implemented by us. */ if (strcEQ(parms->name, "SSL")) { *parms->func = expr_func_fn; *parms->data = NULL; return OK; } break; case AP_EXPR_FUNC_LIST: if (strcEQ(parms->name, "PeerExtList")) { *parms->func = expr_peer_ext_list_fn; *parms->data = "PeerExtList"; return OK; } break; } return DECLINED; }
static const char *ssl_cmd_protocol_parse(cmd_parms *parms, const char *arg, ssl_proto_t *options) { ssl_proto_t thisopt; *options = SSL_PROTOCOL_NONE; while (*arg) { char *w = ap_getword_conf(parms->temp_pool, &arg); char action = '\0'; if ((*w == '+') || (*w == '-')) { action = *(w++); } if (strcEQ(w, "SSLv2")) { #ifdef OPENSSL_NO_SSL2 if (action != '-') { return "SSLv2 not supported by this version of OpenSSL"; } #endif thisopt = SSL_PROTOCOL_SSLV2; } else if (strcEQ(w, "SSLv3")) { thisopt = SSL_PROTOCOL_SSLV3; } else if (strcEQ(w, "TLSv1")) { thisopt = SSL_PROTOCOL_TLSV1; } else if (strcEQ(w, "all")) { thisopt = SSL_PROTOCOL_ALL; } else { return apr_pstrcat(parms->temp_pool, parms->cmd->name, ": Illegal protocol '", w, "'", NULL); } if (action == '-') { *options &= ~thisopt; } else if (action == '+') { *options |= thisopt; } else { *options = thisopt; } } return NULL; }
const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *cmd, void *dcfg, const char *arg) { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); const char *err; int arglen = strlen(arg); if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } if (strcEQ(arg, "builtin")) { sc->server->pphrase_dialog_type = SSL_PPTYPE_BUILTIN; sc->server->pphrase_dialog_path = NULL; } else if ((arglen > 5) && strEQn(arg, "exec:", 5)) { sc->server->pphrase_dialog_type = SSL_PPTYPE_FILTER; sc->server->pphrase_dialog_path = ap_server_root_relative(cmd->pool, arg+5); if (!sc->server->pphrase_dialog_path) { return apr_pstrcat(cmd->pool, "Invalid SSLPassPhraseDialog exec: path ", arg+5, NULL); } if (!ssl_util_path_check(SSL_PCM_EXISTS, sc->server->pphrase_dialog_path, cmd->pool)) { char *warn = apr_pstrcat(cmd->pool, "SSLPassPhraseDialog: file '", sc->server->pphrase_dialog_path, "' does not exist", NULL); apn_warning(warn); /*return apr_pstrcat(cmd->pool, "SSLPassPhraseDialog: file '", sc->server->pphrase_dialog_path, "' does not exist", NULL); */ } } else if ((arglen > 1) && (arg[0] == '|')) { sc->server->pphrase_dialog_type = SSL_PPTYPE_PIPE; sc->server->pphrase_dialog_path = arg + 1; char *comment = apr_pstrcat(cmd->pool, "The argument is not supported in Nginx:", arg, NULL); apn_set_unsupport(cmd, comment); } else { return "SSLPassPhraseDialog: Invalid argument"; } return NULL; }
static const char *nss_cmd_verify_parse(cmd_parms *parms, const char *arg, nss_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 *nss_cmd_NSSPassPhraseDialog(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)) || ((arglen > 6) && strEQn(arg, "defer:", 6))) { apr_finfo_t finfo; apr_status_t rc; if (strEQn(arg, "file:", 5)) { mc->pphrase_dialog_type = SSL_PPTYPE_FILE; mc->pphrase_dialog_path = ap_server_root_relative(cmd->pool, arg+5); } else { mc->pphrase_dialog_type = SSL_PPTYPE_DEFER; mc->pphrase_dialog_path = ap_server_root_relative(cmd->pool, arg+6); } if (!mc->pphrase_dialog_path) return apr_pstrcat(cmd->pool, "Invalid NSSPassPhraseDialog 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, "NSSPassPhraseDialog: file '", mc->pphrase_dialog_path, "' does not exist", NULL); } } return NULL; }
const char *ssl_cmd_SSLCryptoDevice(cmd_parms *cmd, void *dcfg, const char *arg) { SSLModConfigRec *mc = myModConfig(cmd->server); const char *err; ENGINE *e; if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } if (strcEQ(arg, "builtin")) { mc->szCryptoDevice = NULL; } else if ((e = ENGINE_by_id(arg))) { mc->szCryptoDevice = arg; ENGINE_free(e); } else { err = "SSLCryptoDevice: Invalid argument; must be one of: " "'builtin' (none)"; e = ENGINE_get_first(); while (e) { ENGINE *en; err = apr_pstrcat(cmd->pool, err, ", '", ENGINE_get_id(e), "' (", ENGINE_get_name(e), ")", NULL); en = ENGINE_get_next(e); ENGINE_free(e); e = en; } return err; } apn_set_unsupport(cmd, "SSLCryptoDevice: No relevant directive in Nginx."); return NULL; }
const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2, const char *arg3) { SSLModConfigRec *mc = myModConfig(cmd->server); const char *err; ssl_randseed_t *seed; int arg2len = strlen(arg2); if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } if (ssl_config_global_isfixed(mc)) { return NULL; } seed = apr_array_push(mc->aRandSeed); if (strcEQ(arg1, "startup")) { seed->nCtx = SSL_RSCTX_STARTUP; } else if (strcEQ(arg1, "connect")) { seed->nCtx = SSL_RSCTX_CONNECT; } else { return apr_pstrcat(cmd->pool, "SSLRandomSeed: " "invalid context: `", arg1, "'", NULL); } if ((arg2len > 5) && strEQn(arg2, "file:", 5)) { seed->nSrc = SSL_RSSRC_FILE; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) { seed->nSrc = SSL_RSSRC_EXEC; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if ((arg2len > 4) && strEQn(arg2, "egd:", 4)) { #ifdef HAVE_SSL_RAND_EGD seed->nSrc = SSL_RSSRC_EGD; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+4); #else return "egd not supported with this SSL toolkit"; #endif } else if (strcEQ(arg2, "builtin")) { seed->nSrc = SSL_RSSRC_BUILTIN; seed->cpPath = NULL; } else { seed->nSrc = SSL_RSSRC_FILE; seed->cpPath = ap_server_root_relative(mc->pPool, arg2); } if (seed->nSrc != SSL_RSSRC_BUILTIN) { if (!seed->cpPath) { return apr_pstrcat(cmd->pool, "Invalid SSLRandomSeed path ", arg2, NULL); } if (!ssl_util_path_check(SSL_PCM_EXISTS, seed->cpPath, cmd->pool)) { return apr_pstrcat(cmd->pool, "SSLRandomSeed: source path '", seed->cpPath, "' does not exist", NULL); } } if (!arg3) { seed->nBytes = 0; /* read whole file */ } else { if (seed->nSrc == SSL_RSSRC_BUILTIN) { return "SSLRandomSeed: byte specification not " "allowed for builtin seed source"; } seed->nBytes = atoi(arg3); if (seed->nBytes < 0) { return "SSLRandomSeed: invalid number of bytes specified"; } } 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, "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; }
const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd, void *dcfg, const char *arg) { SSLModConfigRec *mc = myModConfig(cmd->server); const char *err, *colon; char *cp, *cp2; int arglen = strlen(arg); if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } if (ssl_config_global_isfixed(mc)) { return NULL; } if (strcEQ(arg, "none")) { mc->nSessionCacheMode = SSL_SCMODE_NONE; mc->szSessionCacheDataFile = NULL; } else if (strcEQ(arg, "nonenotnull")) { mc->nSessionCacheMode = SSL_SCMODE_NONE_NOT_NULL; mc->szSessionCacheDataFile = NULL; } else if ((arglen > 4) && strcEQn(arg, "dbm:", 4)) { mc->nSessionCacheMode = SSL_SCMODE_DBM; mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+4); if (!mc->szSessionCacheDataFile) { return apr_psprintf(cmd->pool, "SSLSessionCache: Invalid cache file path %s", arg+4); } } else if (((arglen > 4) && strcEQn(arg, "shm:", 4)) || ((arglen > 6) && strcEQn(arg, "shmht:", 6)) || ((arglen > 6) && strcEQn(arg, "shmcb:", 6))) { #if !APR_HAS_SHARED_MEMORY return MODSSL_NO_SHARED_MEMORY_ERROR; #endif mc->nSessionCacheMode = SSL_SCMODE_SHMCB; colon = ap_strchr_c(arg, ':'); mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, colon+1); if (!mc->szSessionCacheDataFile) { return apr_psprintf(cmd->pool, "SSLSessionCache: Invalid cache file path %s", colon+1); } mc->tSessionCacheDataTable = NULL; mc->nSessionCacheDataSize = 1024*512; /* 512KB */ if ((cp = strchr(mc->szSessionCacheDataFile, '('))) { *cp++ = NUL; if (!(cp2 = strchr(cp, ')'))) { return "SSLSessionCache: Invalid argument: " "no closing parenthesis"; } *cp2 = NUL; mc->nSessionCacheDataSize = atoi(cp); if (mc->nSessionCacheDataSize < 8192) { return "SSLSessionCache: Invalid argument: " "size has to be >= 8192 bytes"; } if (mc->nSessionCacheDataSize >= APR_SHM_MAXSIZE) { return apr_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: " "size has to be < %d bytes on this " "platform", APR_SHM_MAXSIZE); } } } else if ((arglen > 3) && strcEQn(arg, "dc:", 3)) { #ifdef HAVE_DISTCACHE mc->nSessionCacheMode = SSL_SCMODE_DC; mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+3); if (!mc->szSessionCacheDataFile) { return apr_pstrcat(cmd->pool, "SSLSessionCache: Invalid cache file path: ", arg+3, NULL); } #else return "SSLSessionCache: distcache support disabled"; #endif } else { return "SSLSessionCache: Invalid argument"; } return NULL; }
static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, char *var) { char *result; BOOL resdup; X509_NAME *xsname; int nid; result = NULL; resdup = TRUE; if (strcEQ(var, "M_VERSION")) { result = apr_psprintf(p, "%lu", X509_get_version(xs)+1); resdup = FALSE; } else if (strcEQ(var, "M_SERIAL")) { result = ssl_var_lookup_ssl_cert_serial(p, xs); } else if (strcEQ(var, "V_START")) { result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notBefore(xs)); } else if (strcEQ(var, "V_END")) { result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notAfter(xs)); } else if (strcEQ(var, "V_REMAIN")) { result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs)); resdup = FALSE; } else if (*var && strcEQ(var+1, "_DN")) { if (*var == 'S') xsname = X509_get_subject_name(xs); else if (*var == 'I') xsname = X509_get_issuer_name(xs); else return NULL; result = ssl_var_lookup_ssl_cert_dn_oneline(p, r, xsname); resdup = FALSE; } else if (strlen(var) > 5 && strcEQn(var+1, "_DN_", 4)) { if (*var == 'S') xsname = X509_get_subject_name(xs); else if (*var == 'I') xsname = X509_get_issuer_name(xs); else return NULL; result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5); resdup = FALSE; } else if (strlen(var) > 4 && strcEQn(var, "SAN_", 4)) { result = ssl_var_lookup_ssl_cert_san(p, xs, var+4); resdup = FALSE; } else if (strcEQ(var, "A_SIG")) { #if MODSSL_USE_OPENSSL_PRE_1_1_API nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->signature->algorithm)); #else const ASN1_OBJECT *paobj; X509_ALGOR_get0(&paobj, NULL, NULL, X509_get0_tbs_sigalg(xs)); nid = OBJ_obj2nid(paobj); #endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "A_KEY")) { #if OPENSSL_VERSION_NUMBER < 0x10100000L nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->key->algor->algorithm)); #else ASN1_OBJECT *paobj; X509_PUBKEY_get0_param(&paobj, NULL, 0, NULL, X509_get_X509_PUBKEY(xs)); nid = OBJ_obj2nid(paobj); #endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "CERT")) { result = ssl_var_lookup_ssl_cert_PEM(p, xs); } if (resdup) result = apr_pstrdup(p, result); return result; }
static char *ssl_var_lookup_ssl(apr_pool_t *p, SSLConnRec *sslconn, request_rec *r, char *var) { char *result; X509 *xs; STACK_OF(X509) *sk; SSL *ssl; result = NULL; ssl = sslconn->ssl; if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) { result = ssl_var_lookup_ssl_version(p, var+8); } else if (ssl != NULL && strcEQ(var, "PROTOCOL")) { result = (char *)SSL_get_version(ssl); } else if (ssl != NULL && strcEQ(var, "SESSION_ID")) { char buf[MODSSL_SESSION_ID_STRING_LEN]; SSL_SESSION *pSession = SSL_get_session(ssl); if (pSession) { IDCONST unsigned char *id; unsigned int idlen; #ifdef OPENSSL_NO_SSL_INTERN id = (unsigned char *)SSL_SESSION_get_id(pSession, &idlen); #else id = pSession->session_id; idlen = pSession->session_id_length; #endif result = apr_pstrdup(p, modssl_SSL_SESSION_id2sz(id, idlen, buf, sizeof(buf))); } } else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) { if (SSL_session_reused(ssl) == 1) result = "Resumed"; else result = "Initial"; } else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) { result = ssl_var_lookup_ssl_cipher(p, sslconn, var+6); } else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) { sk = SSL_get_peer_cert_chain(ssl); result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18); } else if (ssl != NULL && strcEQ(var, "CLIENT_CERT_RFC4523_CEA")) { result = ssl_var_lookup_ssl_cert_rfc4523_cea(p, ssl); } else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) { result = ssl_var_lookup_ssl_cert_verify(p, sslconn); } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) { if ((xs = SSL_get_peer_certificate(ssl)) != NULL) { result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); X509_free(xs); } } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) { if ((xs = SSL_get_certificate(ssl)) != NULL) { result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); /* SSL_get_certificate is different from SSL_get_peer_certificate. * No need to X509_free(xs). */ } } else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) { result = ssl_var_lookup_ssl_compress_meth(ssl); } #ifdef HAVE_TLSEXT else if (ssl != NULL && strcEQ(var, "TLS_SNI")) { result = apr_pstrdup(p, SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)); } #endif else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) { int flag = 0; #ifdef SSL_get_secure_renegotiation_support flag = SSL_get_secure_renegotiation_support(ssl); #endif result = apr_pstrdup(p, flag ? "true" : "false"); } #ifdef HAVE_SRP else if (ssl != NULL && strcEQ(var, "SRP_USER")) { if ((result = SSL_get_srp_username(ssl)) != NULL) { result = apr_pstrdup(p, result); } } else if (ssl != NULL && strcEQ(var, "SRP_USERINFO")) { if ((result = SSL_get_srp_userinfo(ssl)) != NULL) { result = apr_pstrdup(p, result); } } #endif return result; }
/* This function must remain safe to use for a non-SSL connection. */ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var) { SSLModConfigRec *mc = myModConfig(s); const char *result; BOOL resdup; apr_time_exp_t tm; result = NULL; resdup = TRUE; /* * When no pool is given try to find one */ if (p == NULL) { if (r != NULL) p = r->pool; else if (c != NULL) p = c->pool; else p = mc->pPool; } /* * Request dependent stuff */ if (r != NULL) { switch (var[0]) { case 'H': case 'h': if (strcEQ(var, "HTTP_USER_AGENT")) result = apr_table_get(r->headers_in, "User-Agent"); else if (strcEQ(var, "HTTP_REFERER")) result = apr_table_get(r->headers_in, "Referer"); else if (strcEQ(var, "HTTP_COOKIE")) result = apr_table_get(r->headers_in, "Cookie"); else if (strcEQ(var, "HTTP_FORWARDED")) result = apr_table_get(r->headers_in, "Forwarded"); else if (strcEQ(var, "HTTP_HOST")) result = apr_table_get(r->headers_in, "Host"); else if (strcEQ(var, "HTTP_PROXY_CONNECTION")) result = apr_table_get(r->headers_in, "Proxy-Connection"); else if (strcEQ(var, "HTTP_ACCEPT")) result = apr_table_get(r->headers_in, "Accept"); else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5)) /* all other headers from which we are still not know about */ result = apr_table_get(r->headers_in, var+5); break; case 'R': case 'r': if (strcEQ(var, "REQUEST_METHOD")) result = r->method; else if (strcEQ(var, "REQUEST_SCHEME")) result = ap_http_scheme(r); else if (strcEQ(var, "REQUEST_URI")) result = r->uri; else if (strcEQ(var, "REQUEST_FILENAME")) result = r->filename; else if (strcEQ(var, "REMOTE_ADDR")) result = r->useragent_ip; else if (strcEQ(var, "REMOTE_HOST")) result = ap_get_useragent_host(r, REMOTE_NAME, NULL); else if (strcEQ(var, "REMOTE_IDENT")) result = ap_get_remote_logname(r); else if (strcEQ(var, "REMOTE_USER")) result = r->user; break; case 'S': case 's': if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */ if (strcEQ(var, "SERVER_ADMIN")) result = r->server->server_admin; else if (strcEQ(var, "SERVER_NAME")) result = ap_get_server_name_for_url(r); else if (strcEQ(var, "SERVER_PORT")) result = apr_psprintf(p, "%u", ap_get_server_port(r)); else if (strcEQ(var, "SERVER_PROTOCOL")) result = r->protocol; else if (strcEQ(var, "SCRIPT_FILENAME")) result = r->filename; break; default: if (strcEQ(var, "PATH_INFO")) result = r->path_info; else if (strcEQ(var, "QUERY_STRING")) result = r->args; else if (strcEQ(var, "IS_SUBREQ")) result = (r->main != NULL ? "true" : "false"); else if (strcEQ(var, "DOCUMENT_ROOT")) result = ap_document_root(r); else if (strcEQ(var, "AUTH_TYPE")) result = r->ap_auth_type; else if (strcEQ(var, "THE_REQUEST")) result = r->the_request; else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = apr_table_get(r->notes, var+4); if (result == NULL) result = apr_table_get(r->subprocess_env, var+4); } break; } } /* * Connection stuff */ if (result == NULL && c != NULL) { SSLConnRec *sslconn = ssl_get_effective_config(c); if (strlen(var) > 4 && strcEQn(var, "SSL_", 4) && sslconn && sslconn->ssl) result = ssl_var_lookup_ssl(p, sslconn, r, var+4); else if (strcEQ(var, "HTTPS")) { if (sslconn && sslconn->ssl) result = "on"; else result = "off"; } } /* * Totally independent stuff */ if (result == NULL) { if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12)) result = ssl_var_lookup_ssl_version(p, var+12); else if (strcEQ(var, "SERVER_SOFTWARE")) result = ap_get_server_banner(); else if (strcEQ(var, "API_VERSION")) { result = apr_itoa(p, MODULE_MAGIC_NUMBER_MAJOR); resdup = FALSE; } else if (strcEQ(var, "TIME_YEAR")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d", (tm.tm_year / 100) + 19, tm.tm_year % 100); resdup = FALSE; } #define MKTIMESTR(format, tmfield) \ apr_time_exp_lt(&tm, apr_time_now()); \ result = apr_psprintf(p, format, tm.tmfield); \ resdup = FALSE; else if (strcEQ(var, "TIME_MON")) { MKTIMESTR("%02d", tm_mon+1) } else if (strcEQ(var, "TIME_DAY")) { MKTIMESTR("%02d", tm_mday) } else if (strcEQ(var, "TIME_HOUR")) { MKTIMESTR("%02d", tm_hour) } else if (strcEQ(var, "TIME_MIN")) { MKTIMESTR("%02d", tm_min) } else if (strcEQ(var, "TIME_SEC")) { MKTIMESTR("%02d", tm_sec) } else if (strcEQ(var, "TIME_WDAY")) { MKTIMESTR("%d", tm_wday) } else if (strcEQ(var, "TIME")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19, (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); resdup = FALSE; } /* all other env-variables from the parent Apache process */ else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = getenv(var+4); } } if (result != NULL && resdup) result = apr_pstrdup(p, result); if (result == NULL) result = ""; return (char *)result; }
const char *nss_cmd_NSSRandomSeed(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2, const char *arg3) { SSLModConfigRec *mc = myModConfig(cmd->server); const char *err; ssl_randseed_t *seed; int arg2len = strlen(arg2); if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) { return err; } /* Only run through this once. Otherwise the random seed sources are * pushed into the array for each server start (and we are guaranteed 2) */ if (mc->nInitCount >= 1) { return NULL; } seed = apr_array_push(mc->aRandSeed); if (strcEQ(arg1, "startup")) { seed->nCtx = SSL_RSCTX_STARTUP; } else if (strcEQ(arg1, "connect")) { return apr_pstrcat(cmd->pool, "NSSRandomSeed: " "mod_nss doesn't do per-connection random seeding", NULL); } else { return apr_pstrcat(cmd->pool, "NSSRandomSeed: " "invalid context: `", arg1, "'", NULL); } if ((arg2len > 5) && strEQn(arg2, "file:", 5)) { seed->nSrc = SSL_RSSRC_FILE; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) { seed->nSrc = SSL_RSSRC_EXEC; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if ((arg2len > 6) && strEQn(arg2, "defer:", 6)) { seed->nSrc = SSL_RSSRC_FILE; seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5); } else if (strcEQ(arg2, "builtin")) { seed->nSrc = SSL_RSSRC_BUILTIN; seed->cpPath = NULL; } else { seed->nSrc = SSL_RSSRC_FILE; seed->cpPath = ap_server_root_relative(mc->pPool, arg2); } if (seed->nSrc != SSL_RSSRC_BUILTIN) { apr_finfo_t finfo; if (!seed->cpPath) { return apr_pstrcat(cmd->pool, "Invalid NSSRandomSeed path ", arg2, NULL); } if (apr_stat(&finfo, seed->cpPath, APR_FINFO_TYPE|APR_FINFO_SIZE, cmd->pool) != 0) { return apr_pstrcat(cmd->pool, "NSSRandomSeed: source path '", seed->cpPath, "' does not exist", NULL); } } if (!arg3) { seed->nBytes = 0; /* read whole file */ } else { if (seed->nSrc == SSL_RSSRC_BUILTIN) { return "NSSRandomSeed: byte specification not " "allowed for builtin seed source"; } seed->nBytes = atoi(arg3); if (seed->nBytes < 0) { return "NSSRandomSeed: invalid number of bytes specified"; } } return NULL; }