ssl_engine_vars.c revision 68dfc95acc4fde241e0124dd29cdda973bd6ec2c
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * contributor license agreements. See the NOTICE file distributed with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * this work for additional information regarding copyright ownership.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The ASF licenses this file to You under the Apache License, Version 2.0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * (the "License"); you may not use this file except in compliance with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the License. You may obtain a copy of the License at
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http://www.apache.org/licenses/LICENSE-2.0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Unless required by applicable law or agreed to in writing, software
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distributed under the License is distributed on an "AS IS" BASIS,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * See the License for the specific language governing permissions and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * limitations under the License.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* _ _
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * _ __ ___ ___ __| | ___ ___| | mod_ssl
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * | | | | | | (_) | (_| | \__ \__ \ |
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * |_| |_| |_|\___/ \__,_|___|___/___/_|
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * |_____|
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ssl_engine_vars.c
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Variable Lookup Facility
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* ``Those of you who think they
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding know everything are very annoying
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding to those of us who do.''
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding -- Unknown */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "ssl_private.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "mod_ssl.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "ap_expr.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "apr_time.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* _________________________________________________________________
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding**
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Variable Lookup
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** _________________________________________________________________
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding*/
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_serial(apr_pool_t *p, X509 *xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) *sk, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, X509 *xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int ssl_is_https(conn_rec *c)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return sslconn && sslconn->ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char var_interface[] = "mod_ssl/" MOD_SSL_VERSION;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char var_library_interface[] = SSL_LIBRARY_TEXT;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *var_library = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx_t *ctx,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const void *dummy,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *arg)
51af95bb51b5084e883bad250b2afa2838e9ceebfielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return ssl_ext_list(ctx->p, ctx->c, 1, arg);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *expr_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *var = (char *)data;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return ssl_var_lookup_ssl(ctx->p, ctx->c, var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int ssl_expr_lookup(ap_expr_lookup_parms *parms)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding switch (parms->type) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case AP_EXPR_FUNC_VAR:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* for now, we just handle everything that starts with SSL_, but
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * register our hook as APR_HOOK_LAST
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * XXX: This can be optimized
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQn(parms->name, "SSL_", 4)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *parms->func = expr_var_fn;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *parms->data = parms->name + 4;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return OK;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case AP_EXPR_FUNC_LIST:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(parms->name, "PeerExtList")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *parms->func = expr_peer_ext_list_fn;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *parms->data = "PeerExtList";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return OK;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return DECLINED;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingvoid ssl_var_register(apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *cp, *cp2;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_REGISTER_OPTIONAL_FN(ssl_is_https);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_REGISTER_OPTIONAL_FN(ssl_ext_list);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Perform once-per-process library version determination: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding var_library = apr_pstrdup(p, SSL_LIBRARY_DYNTEXT);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cp = strchr(var_library, ' ')) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *cp = '/';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cp2 = strchr(cp, ' ')) != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *cp2 = NUL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cp = strchr(var_library_interface, ' ')) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *cp = '/';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cp2 = strchr(cp, ' ')) != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *cp2 = NUL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_hook_expr_lookup(ssl_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* This function must remain safe to use for a non-SSL connection. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingchar *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLModConfigRec *mc = myModConfig(s);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BOOL resdup;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_exp_t tm;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = TRUE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * When no pool is given try to find one
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (p == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (r != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding p = r->pool;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (c != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding p = c->pool;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding p = mc->pPool;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Request dependent stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (r != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding switch (var[0]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 'H':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 'h':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(var, "HTTP_USER_AGENT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "User-Agent");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_REFERER"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Referer");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_COOKIE"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Cookie");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_FORWARDED"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Forwarded");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_HOST"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Host");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_PROXY_CONNECTION"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Proxy-Connection");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTP_ACCEPT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Accept");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* all other headers from which we are still not know about */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, var+5);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 'R':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 'r':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(var, "REQUEST_METHOD"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->method;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REQUEST_SCHEME"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_http_scheme(r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REQUEST_URI"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->uri;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REQUEST_FILENAME"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->filename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REMOTE_HOST"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_get_remote_host(r->connection, r->per_dir_config,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding REMOTE_NAME, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REMOTE_IDENT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_get_remote_logname(r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REMOTE_USER"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->user;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 'S':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case 's':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(var, "SERVER_ADMIN"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->server->server_admin;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "SERVER_NAME"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_get_server_name(r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "SERVER_PORT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "%u", ap_get_server_port(r));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "SERVER_PROTOCOL"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->protocol;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "SCRIPT_FILENAME"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->filename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding default:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(var, "PATH_INFO"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->path_info;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "QUERY_STRING"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->args;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "IS_SUBREQ"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = (r->main != NULL ? "true" : "false");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "DOCUMENT_ROOT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_document_root(r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "AUTH_TYPE"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->ap_auth_type;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "THE_REQUEST"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = r->the_request;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->notes, var+4);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->subprocess_env, var+4);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Connection stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result == NULL && c != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding && sslconn && sslconn->ssl)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl(p, c, var+4);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "REMOTE_ADDR"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = c->remote_ip;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "HTTPS")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (sslconn && sslconn->ssl)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "on";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "off";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Totally independent stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_version(p, var+12);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "SERVER_SOFTWARE"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_get_server_banner();
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "API_VERSION")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_itoa(p, MODULE_MAGIC_NUMBER);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_YEAR")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_exp_lt(&tm, apr_time_now());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "%02d%02d",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (tm.tm_year / 100) + 19, tm.tm_year % 100);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define MKTIMESTR(format, tmfield) \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_exp_lt(&tm, apr_time_now()); \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, format, tm.tmfield); \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_MON")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%02d", tm_mon+1)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_DAY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%02d", tm_mday)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_HOUR")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%02d", tm_hour)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_MIN")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%02d", tm_min)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_SEC")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%02d", tm_sec)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME_WDAY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MKTIMESTR("%d", tm_wday)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "TIME")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_exp_lt(&tm, apr_time_now());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tm.tm_hour, tm.tm_min, tm.tm_sec);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* all other env-variables from the parent Apache process */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = getenv(var+4);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result != NULL && resdup)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, result);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (char *)result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509 *xs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding STACK_OF(X509) *sk;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL *ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl = sslconn->ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_version(p, var+8);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "PROTOCOL")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = (char *)SSL_get_version(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char buf[SSL_SESSION_ID_STRING_LEN];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL_SESSION *pSession = SSL_get_session(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (pSession) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, SSL_SESSION_id2sz(
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL_SESSION_get_session_id(pSession),
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL_SESSION_get_session_id_length(pSession),
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding buf, sizeof(buf)));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (SSL_session_reused(ssl) == 1)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "Resumed";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "Initial";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cipher(p, c, var+6);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sk = SSL_get_peer_cert_chain(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_verify(p, c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert(p, xs, var+7);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_free(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((xs = SSL_get_certificate(ssl)) != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert(p, xs, var+7);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_compress_meth(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifndef OPENSSL_NO_TLSEXT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, SSL_get_servername(ssl,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding TLSEXT_NAMETYPE_host_name));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int flag = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef SSL_get_secure_renegotiation_support
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding flag = SSL_get_secure_renegotiation_support(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, flag ? "true" : "false");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BOOL resdup;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME *xsname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int nid;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *cp;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = TRUE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQ(var, "M_VERSION")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "%lu", X509_get_version(xs)+1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "M_SERIAL")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_serial(p, xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "V_START")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notBefore(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "V_END")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notAfter(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "V_REMAIN")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "S_DN")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsname = X509_get_subject_name(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cp = X509_NAME_oneline(xsname, NULL, 0);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, cp);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding modssl_free(cp);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsname = X509_get_subject_name(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "I_DN")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsname = X509_get_issuer_name(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cp = X509_NAME_oneline(xsname, NULL, 0);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, cp);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding modssl_free(cp);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsname = X509_get_issuer_name(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "A_SIG")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_signature_algorithm(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "A_KEY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_key_algorithm(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "CERT")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_PEM(p, xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result != NULL && resdup)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, result);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* In this table, .extract is non-zero if RDNs using the NID should be
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * extracted to for the SSL_{CLIENT,SERVER}_{I,S}_DN_* environment
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * variables. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const struct {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *name;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int nid;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int extract;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding} ssl_var_lookup_ssl_cert_dn_rec[] = {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "C", NID_countryName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "ST", NID_stateOrProvinceName, 1 }, /* officially (RFC2156) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "SP", NID_stateOrProvinceName, 0 }, /* compatibility (SSLeay) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "L", NID_localityName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "O", NID_organizationName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "OU", NID_organizationalUnitName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "CN", NID_commonName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "T", NID_title, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "I", NID_initials, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "G", NID_givenName, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "S", NID_surname, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "D", NID_description, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef NID_userId
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "UID", NID_userId, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "Email", NID_pkcs9_emailAddress, 1 },
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { NULL, 0, 0 }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding};
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result, *ptr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_ENTRY *xsne;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int i, j, n, idx = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t varlen;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* if an _N suffix is used, find the Nth attribute of given name */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = strchr(var, '_');
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding idx = atoi(ptr + 1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding varlen = ptr - var;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding } else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding varlen = strlen(var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_get_entries(xsname));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding j++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_get_entries(xsname), j);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* cast needed from unsigned char to char */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrmemdup(p, (char *)data,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if APR_CHARSET_EBCDIC
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_xlate_proto_from_ascii(result, X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* APR_CHARSET_EBCDIC */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO* bio;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((bio = BIO_new(BIO_s_mem())) == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_UTCTIME_print(bio, tm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_pending(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pcalloc(p, n+1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_read(bio, result, n);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result[n] = NUL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO_free(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define DIGIT2NUM(x) (((x)[0] - '0') * 10 + (x)[1] - '0')
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Return a string giving the number of days remaining until 'tm', or
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "0" if this can't be determined. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_t then, now = apr_time_now();
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_exp_t exp = {0};
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding long diff;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Fail if the time isn't a valid ASN.1 UTCTIME; RFC3280 mandates
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * that the seconds digits are present even though ASN.1
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * doesn't. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (tm->length < 11 || !ASN1_UTCTIME_check(tm)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrdup(p, "0");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_year = DIGIT2NUM(tm->data);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_mon = DIGIT2NUM(tm->data + 2) - 1;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_mday = DIGIT2NUM(tm->data + 4) + 1;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_hour = DIGIT2NUM(tm->data + 6);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_min = DIGIT2NUM(tm->data + 8);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exp.tm_sec = DIGIT2NUM(tm->data + 10);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (exp.tm_year <= 50) exp.tm_year += 100;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_time_exp_gmt_get(&then, &exp) != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrdup(p, "0");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding diff = (long)((apr_time_sec(then) - apr_time_sec(now)) / (60*60*24));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return diff > 0 ? apr_ltoa(p, diff) : apr_pstrdup(p, "0");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_serial(apr_pool_t *p, X509 *xs)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO *bio;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((bio = BIO_new(BIO_s_mem())) == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding i2a_ASN1_INTEGER(bio, X509_get_serialNumber(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_pending(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pcalloc(p, n+1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_read(bio, result, n);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result[n] = NUL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO_free(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) *sk, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509 *xs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strspn(var, "0123456789") == strlen(var)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = atoi(var);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (n < sk_X509_num(sk)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = sk_X509_value(sk, n);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_PEM(p, xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, X509 *xs)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO *bio;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((bio = BIO_new(BIO_s_mem())) == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding PEM_write_bio_X509(bio, xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_pending(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pcalloc(p, n+1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n = BIO_read(bio, result, n);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result[n] = NUL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO_free(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding long vrc;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *verr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *vinfo;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL *ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509 *xs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
51af95bb51b5084e883bad250b2afa2838e9ceebfielding result = NULL;
51af95bb51b5084e883bad250b2afa2838e9ceebfielding ssl = sslconn->ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding verr = sslconn->verify_error;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding vinfo = sslconn->verify_info;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding vrc = SSL_get_verify_result(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = SSL_get_peer_certificate(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (vrc == X509_V_OK && verr == NULL && xs == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* no client verification done at all */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "NONE";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification done successful */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "SUCCESS";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (vrc == X509_V_OK && vinfo != NULL && strEQ(vinfo, "GENEROUS"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification done in generous way */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = "GENEROUS";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification failed */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "FAILED:%s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding verr ? verr : X509_verify_cert_error_string(vrc));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (xs)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_free(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BOOL resdup;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int usekeysize, algkeysize;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL *ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = TRUE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl = sslconn->ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl_var_lookup_ssl_cipher_bits(ssl, &usekeysize, &algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (ssl && strEQ(var, "")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MODSSL_SSL_CIPHER_CONST SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = (cipher != NULL ? (char *)SSL_CIPHER_get_name(cipher) : NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "_EXPORT"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = (usekeysize < 56 ? "true" : "false");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "_USEKEYSIZE")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_itoa(p, usekeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strcEQ(var, "_ALGKEYSIZE")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_itoa(p, algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding resdup = FALSE;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (result != NULL && resdup)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_pstrdup(p, result);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MODSSL_SSL_CIPHER_CONST SSL_CIPHER *cipher;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *usekeysize = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *algkeysize = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (ssl != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cipher = SSL_get_current_cipher(ssl)) != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *usekeysize = SSL_CIPHER_get_bits(cipher, algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strEQ(var, "INTERFACE")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrdup(p, var_interface);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strEQ(var, "LIBRARY_INTERFACE")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrdup(p, var_library_interface);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strEQ(var, "LIBRARY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrdup(p, var_library);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Add each RDN in 'xn' to the table 't' where the NID is present in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 'nids', using key prefix 'pfx'. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME *xn, apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding STACK_OF(X509_NAME_ENTRY) *ents = X509_NAME_get_entries(xn);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_ENTRY *xsne;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_hash_t *count;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int i, nid;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Hash of (int) NID -> (int *) counter to count each time an RDN
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * with the given NID has been seen. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding count = apr_hash_make(p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For each RDN... */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < sk_X509_NAME_ENTRY_num(ents); i++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *tag;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xsne = sk_X509_NAME_ENTRY_value(ents, i);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Retrieve the nid, and check whether this is one of the nids
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * which are to be extracted. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nid = OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tag = apr_hash_get(nids, &nid, sizeof nid);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (tag) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *key;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int *dup;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *value;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Check whether a variable with this nid was already
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * been used; if so, use the foo_N=bar syntax. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding dup = apr_hash_get(count, &nid, sizeof nid);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (dup) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding key = apr_psprintf(p, "%s%s_%d", pfx, tag, ++(*dup));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Otherwise, use the plain foo=bar syntax. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding dup = apr_pcalloc(p, sizeof *dup);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_hash_set(count, &nid, sizeof nid, dup);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding key = apr_pstrcat(p, pfx, tag, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* cast needed from 'unsigned char *' to 'char *' */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding value = apr_pstrmemdup(p, (char *)data,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if APR_CHARSET_EBCDIC
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_xlate_proto_from_ascii(value, X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* APR_CHARSET_EBCDIC */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_table_setn(t, key, value);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingvoid modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_hash_t *nids;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509 *xs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Build up a hash table of (int *)NID->(char *)short-name for all
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the tags which are to be extracted: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nids = apr_hash_make(p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (n = 0; ssl_var_lookup_ssl_cert_dn_rec[n].name; n++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (ssl_var_lookup_ssl_cert_dn_rec[n].extract) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_hash_set(nids, &ssl_var_lookup_ssl_cert_dn_rec[n].nid,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding sizeof(ssl_var_lookup_ssl_cert_dn_rec[0].nid),
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl_var_lookup_ssl_cert_dn_rec[n].name);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Extract the server cert DNS -- note that the refcount does NOT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * increase: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = SSL_get_certificate(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (xs) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding extract_dn(t, nids, "SSL_SERVER_S_DN_", X509_get_subject_name(xs), p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding extract_dn(t, nids, "SSL_SERVER_I_DN_", X509_get_issuer_name(xs), p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Extract the client cert DNs -- note that the refcount DOES
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * increase: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = SSL_get_peer_certificate(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (xs) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding extract_dn(t, nids, "SSL_CLIENT_S_DN_", X509_get_subject_name(xs), p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding extract_dn(t, nids, "SSL_CLIENT_I_DN_", X509_get_issuer_name(xs), p);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_free(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* For an extension type which OpenSSL does not recognize, attempt to
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * parse the extension type as a primitive string. This will fail for
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * any structured extension type per the docs. Returns non-zero on
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * success and writes the string to the given bio. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int dump_extn_value(BIO *bio, ASN1_OCTET_STRING *str)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MODSSL_D2I_ASN1_type_bytes_CONST unsigned char *pp = str->data;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_STRING *ret = ASN1_STRING_new();
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int rv = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* This allows UTF8String, IA5String, VisibleString, or BMPString;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * conversion to UTF-8 is forced. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (d2i_DISPLAYTEXT(&ret, &pp, str->length)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_STRING_print_ex(bio, ret, ASN1_STRFLGS_UTF8_CONVERT);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = 1;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_STRING_free(ret);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingapr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *extension)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSLConnRec *sslconn = myConnConfig(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SSL *ssl = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *array = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509 *xs = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_OBJECT *oid = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int count = 0, j;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!sslconn || !sslconn->ssl || !extension) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl = sslconn->ssl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* We accept the "extension" string to be converted as
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * a long name (nsComment), short name (DN) or
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * numeric OID (1.2.3.4).
51af95bb51b5084e883bad250b2afa2838e9ceebfielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding oid = OBJ_txt2obj(extension, 0);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!oid) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "could not parse OID '%s'", extension);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ERR_clear_error();
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = peer ? SSL_get_peer_certificate(ssl) : SSL_get_certificate(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (xs == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding count = X509_get_ext_count(xs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Create an array large enough to accomodate every extension. This is
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * likely overkill, but safe.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding array = apr_array_make(p, count, sizeof(char *));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (j = 0; j < count; j++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_EXTENSION *ext = X509_get_ext(xs, j);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (OBJ_cmp(ext->object, oid) == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO *bio = BIO_new(BIO_s_mem());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* We want to obtain a string representation of the extensions
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * value and add it to the array we're building.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * X509V3_EXT_print() doesn't know about all the possible
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * data types, but the value is stored as an ASN1_OCTET_STRING
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * allowing us a fallback in case of X509V3_EXT_print
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * not knowing how to handle the data.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (X509V3_EXT_print(bio, ext, 0, 0) == 1 ||
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding dump_extn_value(bio, X509_EXTENSION_get_data(ext)) == 1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BUF_MEM *buf;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char **ptr = apr_array_push(array);
51af95bb51b5084e883bad250b2afa2838e9ceebfielding BIO_get_mem_ptr(bio, &buf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *ptr = apr_pstrmemdup(p, buf->data, buf->length);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding } else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "Found an extension '%s', but failed to "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "create a string from it", extension);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BIO_vfree(bio);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (array->nelts == 0)
51af95bb51b5084e883bad250b2afa2838e9ceebfielding array = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (peer) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* only SSL_get_peer_certificate raises the refcount */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding X509_free(xs);
}
ASN1_OBJECT_free(oid);
ERR_clear_error();
return array;
}
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl)
{
char *result = "NULL";
#ifdef OPENSSL_VERSION_NUMBER
#if (OPENSSL_VERSION_NUMBER >= 0x00908000)
SSL_SESSION *pSession = SSL_get_session(ssl);
if (pSession) {
switch (pSession->compress_meth) {
case 0:
/* default "NULL" already set */
break;
/* Defined by RFC 3749, deflate is coded by "1" */
case 1:
result = "DEFLATE";
break;
/* IANA assigned compression number for LZS */
case 0x40:
result = "LZS";
break;
default:
result = "UNKNOWN";
break;
}
}
#endif
#endif
return result;
}
/* _________________________________________________________________
**
** SSL Extension to mod_log_config
** _________________________________________________________________
*/
#include "../../modules/loggers/mod_log_config.h"
static const char *ssl_var_log_handler_c(request_rec *r, char *a);
static const char *ssl_var_log_handler_x(request_rec *r, char *a);
/*
* register us for the mod_log_config function registering phase
* to establish %{...}c and to be able to expand %{...}x variables.
*/
void ssl_var_log_config_register(apr_pool_t *p)
{
static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
if (log_pfn_register) {
log_pfn_register(p, "c", ssl_var_log_handler_c, 0);
log_pfn_register(p, "x", ssl_var_log_handler_x, 0);
}
return;
}
/*
* implement the %{..}c log function
* (we are the only function)
*/
static const char *ssl_var_log_handler_c(request_rec *r, char *a)
{
SSLConnRec *sslconn = myConnConfig(r->connection);
char *result;
if (sslconn == NULL || sslconn->ssl == NULL)
return NULL;
result = NULL;
if (strEQ(a, "version"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_PROTOCOL");
else if (strEQ(a, "cipher"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER");
else if (strEQ(a, "subjectdn") || strEQ(a, "clientcert"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_S_DN");
else if (strEQ(a, "issuerdn") || strEQ(a, "cacert"))
result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_I_DN");
else if (strEQ(a, "errcode"))
result = "-";
else if (strEQ(a, "errstr"))
result = (char *)sslconn->verify_error;
if (result != NULL && result[0] == NUL)
result = NULL;
return result;
}
/*
* extend the implementation of the %{..}x log function
* (there can be more functions)
*/
static const char *ssl_var_log_handler_x(request_rec *r, char *a)
{
char *result;
result = ssl_var_lookup(r->pool, r->server, r->connection, r, a);
if (result != NULL && result[0] == NUL)
result = NULL;
return result;
}