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 * 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 * _ __ ___ ___ __| | ___ ___| | mod_ssl
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * | | | | | | (_) | (_| | \__ \__ \ |
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * |_| |_| |_|\___/ \__,_|___|___/___/_|
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Variable Lookup Facility
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* ``Those of you who think they
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding know everything are very annoying
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding to those of us who do.''
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding -- Unknown */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* _________________________________________________________________
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding** Variable Lookup
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);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char var_interface[] = "mod_ssl/" MOD_SSL_VERSION;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char var_library_interface[] = SSL_LIBRARY_TEXT;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx_t *ctx,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const void *dummy,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *arg)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *expr_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int ssl_expr_lookup(ap_expr_lookup_parms *parms)
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 /* Perform once-per-process library version determination: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cp = strchr(var_library_interface, ' ')) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_hook_expr_lookup(ssl_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
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 const char *result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * When no pool is given try to find one
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (p == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (c != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Request dependent stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (r != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding switch (var[0]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "User-Agent");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Forwarded");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_table_get(r->headers_in, "Proxy-Connection");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* all other headers from which we are still not know about */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ap_get_remote_host(r->connection, r->per_dir_config,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "%u", ap_get_server_port(r));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Connection stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Totally independent stuff
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* all other env-variables from the parent Apache process */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (char *)result;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = apr_psprintf(p, "%lu", X509_get_version(xs)+1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notBefore(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notAfter(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_signature_algorithm(xs));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nid = OBJ_obj2nid((ASN1_OBJECT *)X509_get_key_algorithm(xs));
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 { "ST", NID_stateOrProvinceName, 1 }, /* officially (RFC2156) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding { "SP", NID_stateOrProvinceName, 0 }, /* compatibility (SSLeay) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int i, j, n, idx = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* if an _N suffix is used, find the Nth attribute of given name */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) {
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 xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
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 ap_xlate_proto_from_ascii(result, X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* APR_CHARSET_EBCDIC */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_UTCTIME *tm)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define DIGIT2NUM(x) (((x)[0] - '0') * 10 + (x)[1] - '0')
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 /* 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 (apr_time_exp_gmt_get(&then, &exp) != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding diff = (long)((apr_time_sec(then) - apr_time_sec(now)) / (60*60*24));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return diff > 0 ? apr_ltoa(p, diff) : apr_pstrdup(p, "0");
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)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *verr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *vinfo;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (vrc == X509_V_OK && verr == NULL && xs == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* no client verification done at all */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification done successful */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (vrc == X509_V_OK && vinfo != NULL && strEQ(vinfo, "GENEROUS"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification done in generous way */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* client verification failed */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char *var)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ssl_var_lookup_ssl_cipher_bits(ssl, &usekeysize, &algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding MODSSL_SSL_CIPHER_CONST SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding result = (cipher != NULL ? (char *)SSL_CIPHER_get_name(cipher) : NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((cipher = SSL_get_current_cipher(ssl)) != NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *usekeysize = SSL_CIPHER_get_bits(cipher, algkeysize);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var)
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 STACK_OF(X509_NAME_ENTRY) *ents = X509_NAME_get_entries(xn);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Hash of (int) NID -> (int *) counter to count each time an RDN
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * with the given NID has been seen. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For each RDN... */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < sk_X509_NAME_ENTRY_num(ents); i++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *tag;
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 unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *key;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Check whether a variable with this nid was already
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * been used; if so, use the foo_N=bar syntax. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding key = apr_psprintf(p, "%s%s_%d", pfx, tag, ++(*dup));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Otherwise, use the plain foo=bar syntax. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* cast needed from 'unsigned char *' to 'char *' */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_xlate_proto_from_ascii(value, X509_NAME_ENTRY_get_data_len(xsne));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* APR_CHARSET_EBCDIC */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingvoid modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned n;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Build up a hash table of (int *)NID->(char *)short-name for all
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the tags which are to be extracted: */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (n = 0; ssl_var_lookup_ssl_cert_dn_rec[n].name; n++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_hash_set(nids, &ssl_var_lookup_ssl_cert_dn_rec[n].nid,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Extract the server cert DNS -- note that the refcount does NOT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * increase: */
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 /* Extract the client cert DNs -- note that the refcount DOES
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * increase: */
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/* 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 MODSSL_D2I_ASN1_type_bytes_CONST unsigned char *pp = str->data;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* This allows UTF8String, IA5String, VisibleString, or BMPString;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * conversion to UTF-8 is forced. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ASN1_STRING_print_ex(bio, ret, ASN1_STRFLGS_UTF8_CONVERT);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingapr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer,
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).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding xs = peer ? SSL_get_peer_certificate(ssl) : SSL_get_certificate(ssl);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Create an array large enough to accomodate every extension. This is
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * likely overkill, but safe.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (j = 0; j < count; j++) {
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 dump_extn_value(bio, X509_EXTENSION_get_data(ext)) == 1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "Found an extension '%s', but failed to "
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* only SSL_get_peer_certificate raises the refcount */
return array;
#ifdef OPENSSL_VERSION_NUMBER
if (pSession) {
return result;
#include "../../modules/loggers/mod_log_config.h"
if (log_pfn_register) {
char *result;
return NULL;
return result;
char *result;
return result;