static int server_setup_sni(void) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) goto end; /* set SNI at server side */ SSL_set_tlsext_host_name(serverssl, host); if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; if (!TEST_ptr_null(SSL_get_servername(serverssl, TLSEXT_NAMETYPE_host_name))) { /* SNI should have been cleared during handshake */ goto end; } testresult = 1; end: SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); SSL_CTX_free(cctx); return testresult; }
/* Select the appropriate server CTX. * Returns SSL_TLSEXT_ERR_OK if a match was found. * If |ignore| is 1, returns SSL_TLSEXT_ERR_NOACK on mismatch. * Otherwise, returns SSL_TLSEXT_ERR_ALERT_FATAL on mismatch. * An empty SNI extension also returns SSL_TSLEXT_ERR_NOACK. */ static int select_server_ctx(SSL *s, void *arg, int ignore) { const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); HANDSHAKE_EX_DATA *ex_data = (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx)); if (servername == NULL) { ex_data->servername = SSL_TEST_SERVERNAME_SERVER1; return SSL_TLSEXT_ERR_NOACK; } if (strcmp(servername, "server2") == 0) { SSL_CTX *new_ctx = (SSL_CTX*)arg; SSL_set_SSL_CTX(s, new_ctx); /* * Copy over all the SSL_CTX options - reasonable behavior * allows testing of cases where the options between two * contexts differ/conflict */ SSL_clear_options(s, 0xFFFFFFFFL); SSL_set_options(s, SSL_CTX_get_options(new_ctx)); ex_data->servername = SSL_TEST_SERVERNAME_SERVER2; return SSL_TLSEXT_ERR_OK; } else if (strcmp(servername, "server1") == 0) { ex_data->servername = SSL_TEST_SERVERNAME_SERVER1; return SSL_TLSEXT_ERR_OK; } else if (ignore) { ex_data->servername = SSL_TEST_SERVERNAME_SERVER1; return SSL_TLSEXT_ERR_NOACK; } else { /* Don't set an explicit alert, to test library defaults. */ return SSL_TLSEXT_ERR_ALERT_FATAL; } }
static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { VALUE ary, ssl_obj, ret_obj; void *ptr; int state = 0; const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) return SSL_TLSEXT_ERR_OK; if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) return SSL_TLSEXT_ERR_ALERT_FATAL; ssl_obj = (VALUE)ptr; ary = rb_ary_new2(2); rb_ary_push(ary, ssl_obj); rb_ary_push(ary, rb_str_new2(servername)); ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state); if (state) { rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); return SSL_TLSEXT_ERR_ALERT_FATAL; } return SSL_TLSEXT_ERR_OK; }
int ServerNameIndication::callback(void *s, int *ad, void *arg) { SSL *ssl = (SSL *)s; const char *sn_ptr = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!sn_ptr) { return SSL_TLSEXT_ERR_OK; // No server name; use the default. } // Calculate the names to search for: fqdn and wildcard. std::string fqdn = sn_ptr; size_t pos = fqdn.find('.'); std::string wildcard; if (pos != string::npos) { wildcard = fqdn.substr(pos + 1); } // Search in memory for matching certificate. if (setCTXFromMemory(ssl, wildcard) || setCTXFromMemory(ssl, fqdn)) { return SSL_TLSEXT_ERR_OK; } if (setCTXFromFile(ssl, wildcard) || setCTXFromFile(ssl, fqdn)) { return SSL_TLSEXT_ERR_OK; } // Didn't find a match based on SNI, fallback to default. return SSL_TLSEXT_ERR_OK; }
int bud_config_select_sni_context(SSL* s, int* ad, void* arg) { bud_config_t* config; bud_context_t* ctx; const char* servername; config = arg; servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); /* No servername - no context selection */ if (servername == NULL) return SSL_TLSEXT_ERR_OK; /* Async SNI */ ctx = SSL_get_ex_data(s, kBudSSLSNIIndex); /* Normal SNI */ if (ctx == NULL) ctx = bud_config_select_context(config, servername, strlen(servername)); if (ctx != NULL) { SSL_set_SSL_CTX(s, ctx->ctx); if (!SSL_set_ex_data(s, kBudSSLSNIIndex, ctx)) return SSL_TLSEXT_ERR_ALERT_FATAL; } return SSL_TLSEXT_ERR_OK; }
int CALLBACK CSSLContext::InternalServerNameCallback(SSL* ssl, int* ad, void* arg) { USES_CONVERSION; CSSLContext* pThis = (CSSLContext*)arg; ASSERT(pThis->m_fnServerNameCallback != nullptr); const char* lpszServerName = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if(lpszServerName == nullptr) return SSL_TLSEXT_ERR_NOACK; int iIndex = pThis->m_fnServerNameCallback(A2CT(lpszServerName)); if(iIndex == 0) return SSL_TLSEXT_ERR_OK; if(iIndex < 0) { ::SetLastError(ERROR_INVALID_NAME); return SSL_TLSEXT_ERR_ALERT_FATAL; } SSL_CTX* sslCtx = pThis->GetContext(iIndex); if(sslCtx == nullptr) { ::SetLastError(ERROR_INVALID_INDEX); return SSL_TLSEXT_ERR_ALERT_FATAL; } SSL_set_SSL_CTX(ssl, sslCtx); return SSL_TLSEXT_ERR_OK; }
static int tlsext_servername_callback(SSL *ssl, int *ad, void *arg) { SSL_CTX *newctx = NULL; SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); lua_State *L = SSL_CTX_get_app_data(ctx); const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); /* No name, use default context */ if (!name) return SSL_TLSEXT_ERR_NOACK; /* Search for the name in the map */ openssl_getvalue(L, ctx, "tlsext_servername"); if (lua_istable(L, -1)) { lua_getfield(L, -1, name); if (auxiliar_isclass(L, "openssl.ssl_ctx", -1)) { newctx = CHECK_OBJECT(-1, SSL_CTX, "openssl.ssl_ctx"); SSL_set_SSL_CTX(ssl, newctx); lua_pop(L, 2); return SSL_TLSEXT_ERR_OK; } } else if (lua_isfunction(L, -1)) { } else { } lua_pop(L, 1); return SSL_TLSEXT_ERR_ALERT_FATAL; }
static int meth_getsniname(lua_State *L) { p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); const char *name = SSL_get_servername(ssl->ssl, TLSEXT_NAMETYPE_host_name); if (name) lua_pushstring(L, name); else lua_pushnil(L); return 1; }
static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { tlsextctx * p = (tlsextctx *) arg; const char * hn= SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); if (SSL_get_servername_type(s) != -1) p->ack = !SSL_session_reused(s) && hn != NULL; else BIO_printf(bio_err,"Can't use SSL_get_servername\n"); return SSL_TLSEXT_ERR_OK; }
SSLContext::ServerNameCallbackResult SSLContextManager::serverNameCallback(SSL* ssl) { shared_ptr<SSLContext> ctx; const char* sn = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!sn) { VLOG(6) << "Server Name (tlsext_hostname) is missing"; if (clientHelloTLSExtStats_) { clientHelloTLSExtStats_->recordAbsentHostname(); } return SSLContext::SERVER_NAME_NOT_FOUND; } size_t snLen = strlen(sn); VLOG(6) << "Server Name (SNI TLS extension): '" << sn << "' "; // FIXME: This code breaks the abstraction. Suggestion? AsyncSSLSocket* sslSocket = AsyncSSLSocket::getFromSSL(ssl); CHECK(sslSocket); DNString dnstr(sn, snLen); uint32_t count = 0; do { // Try exact match first ctx = getSSLCtx(dnstr); if (ctx) { sslSocket->switchServerSSLContext(ctx); if (clientHelloTLSExtStats_) { clientHelloTLSExtStats_->recordMatch(); } return SSLContext::SERVER_NAME_FOUND; } ctx = getSSLCtxBySuffix(dnstr); if (ctx) { sslSocket->switchServerSSLContext(ctx); if (clientHelloTLSExtStats_) { clientHelloTLSExtStats_->recordMatch(); } return SSLContext::SERVER_NAME_FOUND; } // Give the noMatchFn one chance to add the correct cert } while (count++ == 0 && noMatchFn_ && noMatchFn_(sn)); VLOG(6) << folly::stringPrintf("Cannot find a SSL_CTX for \"%s\"", sn); if (clientHelloTLSExtStats_) { clientHelloTLSExtStats_->recordNotMatch(); } return SSLContext::SERVER_NAME_NOT_FOUND; }
static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) { const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) return SSL_TLSEXT_ERR_NOACK; size_t servername_len = strlen(servername); struct uwsgi_string_list *usl = uwsgi.sni; while(usl) { if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) { SSL_set_SSL_CTX(ssl, usl->custom_ptr); return SSL_TLSEXT_ERR_OK; } usl = usl->next; } #ifdef UWSGI_PCRE struct uwsgi_regexp_list *url = uwsgi.sni_regexp; while(url) { if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) { SSL_set_SSL_CTX(ssl, url->custom_ptr); return SSL_TLSEXT_ERR_OK; } url = url->next; } #endif if (uwsgi.sni_dir) { size_t sni_dir_len = strlen(uwsgi.sni_dir); char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4); char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4); char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3); if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) { char *client_ca = NULL; if (uwsgi_file_exists(sni_dir_client_ca)) { client_ca = sni_dir_client_ca; } usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca); if (!usl) goto done; free(sni_dir_cert); free(sni_dir_key); free(sni_dir_client_ca); SSL_set_SSL_CTX(ssl, usl->custom_ptr); uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername); return SSL_TLSEXT_ERR_OK; } done: free(sni_dir_cert); free(sni_dir_key); free(sni_dir_client_ca); } return SSL_TLSEXT_ERR_NOACK; }
std::string Socket::getSNIServerName() const { if (!_sslConnection) return ""; if (!_sslConnection->ssl) return ""; const char* name = SSL_get_servername(_sslConnection->ssl, TLSEXT_NAMETYPE_host_name); if (!name) return ""; return name; }
static int lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg) { struct lws_context *context = (struct lws_context *)arg; struct lws_vhost *vhost, *vh; const char *servername; if (!ssl) return SSL_TLSEXT_ERR_NOACK; /* * We can only get ssl accepted connections by using a vhost's ssl_ctx * find out which listening one took us and only match vhosts on the * same port. */ vh = context->vhost_list; while (vh) { if (!vh->being_destroyed && vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl)) break; vh = vh->vhost_next; } if (!vh) { assert(vh); /* can't match the incoming vh? */ return SSL_TLSEXT_ERR_OK; } servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) { /* the client doesn't know what hostname it wants */ lwsl_info("SNI: Unknown ServerName: %s\n", servername); return SSL_TLSEXT_ERR_OK; } vhost = lws_select_vhost(context, vh->listen_port, servername); if (!vhost) { lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port); return SSL_TLSEXT_ERR_OK; } lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port); /* select the ssl ctx from the selected vhost for this conn */ SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx); return SSL_TLSEXT_ERR_OK; }
static int openssl_sni_servername_cb (SSL *ssl, int *ad, void *arg) { ret_t ret; int re; const char *servername; cherokee_connection_t *conn; cherokee_buffer_t tmp; cherokee_server_t *srv = SRV(arg); cherokee_virtual_server_t *vsrv = NULL; UNUSED(ad); /* Get the pointer to the socket */ conn = SSL_get_app_data (ssl); if (unlikely (conn == NULL)) { LOG_ERROR (CHEROKEE_ERROR_SSL_SOCKET, ssl); return SSL_TLSEXT_ERR_ALERT_FATAL; } cherokee_buffer_init(&tmp); cherokee_buffer_ensure_size(&tmp, 40); /* Read the SNI server name */ servername = SSL_get_servername (ssl, TLSEXT_NAMETYPE_host_name); if (servername == NULL) { /* Set the server name to the IP address if we couldn't get the host name via SNI */ cherokee_socket_ntop (&conn->socket, tmp.buf, tmp.size); TRACE (ENTRIES, "No SNI: Did not provide a server name, using IP='%s' as servername.\n", tmp.buf); } else { cherokee_buffer_add (&tmp, servername, strlen(servername)); TRACE (ENTRIES, "SNI: Switching to servername='%s'\n", servername); } /* Look up and change the vserver */ ret = cherokee_cryptor_libssl_find_vserver(ssl, srv, &tmp, conn); if (ret != ret_ok) { re = SSL_TLSEXT_ERR_NOACK; } else { re = SSL_TLSEXT_ERR_OK; } cherokee_buffer_mrproper (&tmp); return re; }
static int get_tlsext_sn(str* res, sip_msg_t* msg) { static char buf[1024]; struct tcp_connection* c; str server_name; SSL* ssl; c = get_cur_connection(msg); if (!c) { INFO("TLS connection not found in select_desc\n"); goto error; } ssl = get_ssl(c); if (!ssl) goto error; buf[0] = '\0'; server_name.s = (char*)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (server_name.s) { server_name.len = strlen(server_name.s); DBG("received server_name (TLS extension): '%.*s'\n", STR_FMT(&server_name)); } else { DBG("SSL_get_servername returned NULL\n"); goto error; } /* copy server_name into the buffer. If the buffer is too small copy only * the last bytes as these are the more important ones and prefix with * '+' */ if (server_name.len > sizeof(buf)) { ERR("server_name to big for buffer\n"); buf[0] = '+'; memcpy(buf + 1, server_name.s + 1 + server_name.len - sizeof(buf), sizeof(buf) - 1); res->len = sizeof(buf); } else { memcpy(buf, server_name.s, server_name.len); res->len = server_name.len; } res->s = buf; tcpconn_put(c); return 0; error: if (c) tcpconn_put(c); return -1; }
static int lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg) { struct lws_context *context; struct lws_vhost *vhost, *vh; const char *servername; int port; if (!ssl) return SSL_TLSEXT_ERR_NOACK; context = (struct lws_context *)SSL_CTX_get_ex_data( SSL_get_SSL_CTX(ssl), openssl_SSL_CTX_private_data_index); /* * We can only get ssl accepted connections by using a vhost's ssl_ctx * find out which listening one took us and only match vhosts on the * same port. */ vh = context->vhost_list; while (vh) { if (!vh->being_destroyed && vh->ssl_ctx == SSL_get_SSL_CTX(ssl)) break; vh = vh->vhost_next; } assert(vh); /* we cannot get an ssl without using a vhost ssl_ctx */ port = vh->listen_port; servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (servername) { vhost = lws_select_vhost(context, port, servername); if (vhost) { lwsl_debug("SNI: Found: %s (port %d)\n", servername, port); SSL_set_SSL_CTX(ssl, vhost->ssl_ctx); return SSL_TLSEXT_ERR_OK; } lwsl_err("SNI: Unknown ServerName: %s\n", servername); } return SSL_TLSEXT_ERR_OK; }
static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) { const char *servername; connection *con = (connection *) SSL_get_app_data(ssl); UNUSED(al); buffer_copy_string(con->uri.scheme, "https"); if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { #if 0 /* this "error" just means the client didn't support it */ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "failed to get TLS server name"); #endif return SSL_TLSEXT_ERR_NOACK; } buffer_copy_string(con->tlsext_server_name, servername); buffer_to_lower(con->tlsext_server_name); /* Sometimes this is still set, confusing COMP_HTTP_HOST */ buffer_reset(con->uri.authority); config_cond_cache_reset(srv, con); config_setup_connection(srv, con); config_patch_connection(srv, con, COMP_SERVER_SOCKET); config_patch_connection(srv, con, COMP_HTTP_SCHEME); config_patch_connection(srv, con, COMP_HTTP_HOST); if (NULL == con->conf.ssl_ctx) { /* ssl_ctx <=> pemfile was set <=> ssl_ctx got patched: so this should never happen */ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", "null SSL_CTX for TLS server name", con->tlsext_server_name); return SSL_TLSEXT_ERR_ALERT_FATAL; } /* switch to new SSL_CTX in reaction to a client's server_name extension */ if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", "failed to set SSL_CTX for TLS server name", con->tlsext_server_name); return SSL_TLSEXT_ERR_ALERT_FATAL; } return SSL_TLSEXT_ERR_OK; }
NOEXPORT int servername_cb(SSL *ssl, int *ad, void *arg) { SERVICE_OPTIONS *section=(SERVICE_OPTIONS *)arg; const char *servername=SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); SERVERNAME_LIST *list; CLI *c; #ifdef USE_LIBWRAP char *accepted_address; #endif /* USE_LIBWRAP */ /* leave the alert type at SSL_AD_UNRECOGNIZED_NAME */ (void)ad; /* squash the unused parameter warning */ if(!section->servername_list_head) { s_log(LOG_DEBUG, "SNI: no virtual services defined"); return SSL_TLSEXT_ERR_OK; } if(!servername) { s_log(LOG_NOTICE, "SNI: no servername received"); return SSL_TLSEXT_ERR_NOACK; } s_log(LOG_INFO, "SNI: requested servername: %s", servername); for(list=section->servername_list_head; list; list=list->next) if(matches_wildcard((char *)servername, list->servername)) { s_log(LOG_DEBUG, "SNI: matched pattern: %s", list->servername); c=SSL_get_ex_data(ssl, index_cli); c->opt=list->opt; SSL_set_SSL_CTX(ssl, c->opt->ctx); SSL_set_verify(ssl, SSL_CTX_get_verify_mode(c->opt->ctx), SSL_CTX_get_verify_callback(c->opt->ctx)); s_log(LOG_NOTICE, "SNI: switched to service [%s]", c->opt->servname); #ifdef USE_LIBWRAP accepted_address=s_ntop(&c->peer_addr, c->peer_addr_len); libwrap_auth(c, accepted_address); /* retry on a service switch */ str_free(accepted_address); #endif /* USE_LIBWRAP */ return SSL_TLSEXT_ERR_OK; } s_log(LOG_ERR, "SNI: no pattern matched servername: %s", servername); return SSL_TLSEXT_ERR_ALERT_FATAL; }
static int bb_ssl_servername(SSL *ssl,int *ad, void *arg) { const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) return SSL_TLSEXT_ERR_NOACK; struct bb_connection *bbc = SSL_get_ex_data(ssl, blastbeat.ssl_index); struct bb_acceptor *bba = bbc->acceptor; size_t servername_len = strlen(servername); struct bb_virtualhost *vhost = NULL; struct bb_hostname *bbhn = NULL; if (bba->addr.in4.sin_port != htons(443) && !strchr(servername, ':')) { size_t port_len = strlen(bba->port_str); char *new_sn = bb_alloc(servername_len+port_len); if (!new_sn) return SSL_TLSEXT_ERR_NOACK; memcpy(new_sn, servername, servername_len); memcpy(new_sn + servername_len, bba->port_str, port_len); vhost = bb_vhost_get(new_sn, servername_len+port_len, &bbhn); bb_free(new_sn, servername_len+port_len); } else { vhost = bb_vhost_get((char *)servername, servername_len, &bbhn); } if (!vhost) return SSL_TLSEXT_ERR_NOACK; // per vhost-context is required to decrypt keys sent by dealers if (!vhost->ctx) return SSL_TLSEXT_ERR_NOACK; // prefer dealer-defined context if (bbhn->ctx) { SSL_set_SSL_CTX(ssl, bbhn->ctx); return SSL_TLSEXT_ERR_OK; } SSL_set_SSL_CTX(ssl, vhost->ctx); return SSL_TLSEXT_ERR_OK; }
//sni lookup server name int httpSSLServerName(SSL *ssl,int *ad,void *arg) { const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (servername==NULL) { return SSL_TLSEXT_ERR_NOACK; } KConnectionSelectable *c = (KConnectionSelectable *)SSL_get_ex_data(ssl,kangle_ssl_conntion_index); if (c==NULL) { return SSL_TLSEXT_ERR_NOACK; } if (c->sni) { return SSL_TLSEXT_ERR_OK; } c->sni = new KSSLSniContext; if (query_vh_success != conf.gvm->queryVirtualHost(c->ls,&c->sni->svh,servername)) { return SSL_TLSEXT_ERR_OK; } if (c->sni->svh->vh && c->sni->svh->vh->ssl_ctx) { SSL_set_SSL_CTX(ssl,c->sni->svh->vh->ssl_ctx); } return SSL_TLSEXT_ERR_OK; }
static int sni_cb(SSL *ssl, int *ad, void *arg) { int strict; SSL_CTX *newctx = NULL; SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); lua_State *L = ((p_context)SSL_CTX_get_app_data(ctx))->L; const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); /* No name, use default context */ if (!name) return SSL_TLSEXT_ERR_NOACK; /* Retrieve struct from registry */ luaL_getmetatable(L, "SSL:SNI:Registry"); lua_pushlightuserdata(L, (void*)ssl); lua_gettable(L, -2); /* Strict search? */ lua_pushstring(L, "strict"); lua_gettable(L, -2); strict = lua_toboolean(L, -1); lua_pop(L, 1); /* Search for the name in the map */ lua_pushstring(L, "map"); lua_gettable(L, -2); lua_pushstring(L, name); lua_gettable(L, -2); if (lua_isuserdata(L, -1)) newctx = lsec_checkcontext(L, -1); lua_pop(L, 4); /* Found, use this context */ if (newctx) { SSL_set_SSL_CTX(ssl, newctx); return SSL_TLSEXT_ERR_OK; } /* Not found, but use initial context */ if (!strict) return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_ALERT_FATAL; }
static int sniHostname(SSL *handle, int *ad, void *arg) { MprSocket *sp; MprSsl *ssl; OpenSocket *osp; OpenConfig *cfg; SSL_CTX *ctx; cchar *hostname; if (!handle) { return SSL_TLSEXT_ERR_NOACK; } osp = (OpenSocket*) SSL_get_app_data(handle); sp = osp->sock; hostname = SSL_get_servername(handle, TLSEXT_NAMETYPE_host_name); /* Select the appropriate SSL for this hostname */ if ((ssl = (sp->ssl->matchSsl)(sp, hostname)) == 0) { return SSL_TLSEXT_ERR_ALERT_FATAL; } lock(ssl); if (configOss(ssl, sp->flags, &sp->errorMsg) < 0) { unlock(ssl); return SSL_TLSEXT_ERR_ALERT_FATAL; } unlock(ssl); sp->ssl = ssl; cfg = ssl->config; ctx = cfg->ctx; SSL_set_SSL_CTX(handle, ctx); return SSL_TLSEXT_ERR_OK; }
int hr_https_add_vars(struct http_session *hr, struct corerouter_peer *peer, struct uwsgi_buffer *out) { // HTTPS (adapted from nginx) if (hr->session.ugs->mode == UWSGI_HTTP_SSL) { if (uwsgi_buffer_append_keyval(out, "HTTPS", 5, "on", 2)) return -1; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME const char *servername = SSL_get_servername(hr->ssl, TLSEXT_NAMETYPE_host_name); if (servername && strlen(servername) <= 0xff) { peer->key_len = strlen(servername); memcpy(peer->key, servername, peer->key_len) ; } #endif hr->ssl_client_cert = SSL_get_peer_certificate(hr->ssl); if (hr->ssl_client_cert) { X509_NAME *name = X509_get_subject_name(hr->ssl_client_cert); if (name) { hr->ssl_client_dn = X509_NAME_oneline(name, NULL, 0); if (uwsgi_buffer_append_keyval(out, "HTTPS_DN", 8, hr->ssl_client_dn, strlen(hr->ssl_client_dn))) return -1; } if (uhttp.https_export_cert) { hr->ssl_bio = BIO_new(BIO_s_mem()); if (hr->ssl_bio) { if (PEM_write_bio_X509(hr->ssl_bio, hr->ssl_client_cert) > 0) { size_t cc_len = BIO_pending(hr->ssl_bio); hr->ssl_cc = uwsgi_malloc(cc_len); BIO_read(hr->ssl_bio, hr->ssl_cc, cc_len); if (uwsgi_buffer_append_keyval(out, "HTTPS_CC", 8, hr->ssl_cc, cc_len)) return -1; } } } } } else if (hr->session.ugs->mode == UWSGI_HTTP_FORCE_SSL) { hr->force_https = 1; } return 0; }
static int openssl_ssl_get(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); for (i = 2; i <= top; i++) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { lua_pushinteger(L, SSL_get_fd(s)); } else if (strcmp(what, "rfd") == 0) { lua_pushinteger(L, SSL_get_rfd(s)); } else if (strcmp(what, "wfd") == 0) { lua_pushinteger(L, SSL_get_wfd(s)); } else if (strcmp(what, "client_CA_list") == 0) { STACK_OF(X509_NAME)* sn = SSL_get_client_CA_list(s); PUSH_OBJECT(sn, "openssl.sk_x509_name"); } else if (strcmp(what, "read_ahead") == 0) { lua_pushboolean(L, SSL_get_read_ahead(s)); } else if (strcmp(what, "shared_ciphers") == 0) { char buf[LUAL_BUFFERSIZE] = {0}; lua_pushstring(L, SSL_get_shared_ciphers(s, buf, sizeof(buf))); } else if (strcmp(what, "cipher_list") == 0) { //TODO FIX lua_pushstring(L, SSL_get_cipher_list(s, 0)); } else if (strcmp(what, "verify_mode") == 0) { //FIX lua_pushinteger(L, SSL_get_verify_mode(s)); } else if (strcmp(what, "verify_depth") == 0) { lua_pushinteger(L, SSL_get_verify_depth(s)); } else if (strcmp(what, "state_string") == 0) { lua_pushstring(L, SSL_state_string(s)); } else if (strcmp(what, "state_string_long") == 0) { lua_pushstring(L, SSL_state_string_long(s)); } else if (strcmp(what, "rstate_string") == 0) { lua_pushstring(L, SSL_rstate_string(s)); } else if (strcmp(what, "rstate_string_long") == 0) { lua_pushstring(L, SSL_rstate_string_long(s)); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "iversion") == 0) { lua_pushinteger(L, SSL_version(s)); } else if (strcmp(what, "default_timeout") == 0) { lua_pushinteger(L, SSL_get_default_timeout(s)); } else if (strcmp(what, "certificate") == 0) { X509* cert = SSL_get_certificate(s); PUSH_OBJECT(cert, "openssl.x509"); } else if (strcmp(what, "verify_result") == 0) { long l = SSL_get_verify_result(s); lua_pushinteger(L, l); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "state") == 0) { lua_pushinteger(L, SSL_state(s)); } else if (strcmp(what, "hostname") == 0) { lua_pushstring(L, SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)); } else luaL_argerror(L, i, "can't understant"); } return top - 1; }
static int ssl_servername_cb(SSL *cnx, int *al, void *arg) { CertResult result; const char *sni_name; (void) al; (void) arg; if ((sni_name = SSL_get_servername(cnx, TLSEXT_NAMETYPE_host_name)) == NULL || *sni_name == 0 || validate_sni_name(sni_name) != 0) { return SSL_TLSEXT_ERR_NOACK; } logfile(LOG_INFO, "SNI: [%s]", sni_name); if (chrooted != 0 || loggedin != 0) { return SSL_TLSEXT_ERR_NOACK; } if (use_extcert == 0) { return SSL_TLSEXT_ERR_OK; } memset(&result, 0, sizeof result); tls_extcert_get(&result, sni_name); if (result.cert_ok != 1) { die(400, LOG_ERR, "Cert handler not ready"); } if (result.action == CERT_ACTION_DENY) { die(400, LOG_INFO, MSG_LOGOUT); } if (result.action == CERT_ACTION_DEFAULT) { return SSL_TLSEXT_ERR_OK; } if (result.cert_file == NULL) { if (result.action == CERT_ACTION_STRICT) { die(400, LOG_ERR, "Missing certificate"); } else { return SSL_TLSEXT_ERR_OK; } } if (result.key_file == NULL) { result.key_file = result.cert_file; } SSL_CTX_free(tls_ctx); tls_ctx = NULL; if (tls_create_new_context(result.cert_file, result.key_file) != 0) { if (result.action != CERT_ACTION_FALLBACK) { die(400, LOG_ERR, "Invalid certificate"); } if (tls_create_new_context(cert_file, key_file) != 0) { die(400, LOG_ERR, "SSL error"); } } if ((client_sni_name = strdup(sni_name)) == NULL) { die_mem(); } if (tls_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_cnx, ctx_options); } if (tls_data_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_data_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_data_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_data_cnx, ctx_options); } return SSL_TLSEXT_ERR_OK; }
static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) { const char *servername; connection *con = (connection *) SSL_get_app_data(ssl); UNUSED(al); buffer_copy_string(con->uri.scheme, "https"); if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { #if 0 /* this "error" just means the client didn't support it */ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "failed to get TLS server name"); #endif return SSL_TLSEXT_ERR_NOACK; } buffer_copy_string(con->tlsext_server_name, servername); buffer_to_lower(con->tlsext_server_name); /* Sometimes this is still set, confusing COMP_HTTP_HOST */ buffer_reset(con->uri.authority); config_cond_cache_reset(srv, con); config_setup_connection(srv, con); con->conditional_is_valid[COMP_SERVER_SOCKET] = 1; con->conditional_is_valid[COMP_HTTP_SCHEME] = 1; con->conditional_is_valid[COMP_HTTP_HOST] = 1; config_patch_connection(srv, con); if (NULL == con->conf.ssl_pemfile_x509 || NULL == con->conf.ssl_pemfile_pkey) { /* x509/pkey available <=> pemfile was set <=> pemfile got patched: so this should never happen, unless you nest $SERVER["socket"] */ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", "no certificate/private key for TLS server name", con->tlsext_server_name); return SSL_TLSEXT_ERR_ALERT_FATAL; } /* first set certificate! setting private key checks whether certificate matches it */ if (!SSL_use_certificate(ssl, con->conf.ssl_pemfile_x509)) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "failed to set certificate for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } if (!SSL_use_PrivateKey(ssl, con->conf.ssl_pemfile_pkey)) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "failed to set private key for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } if (con->conf.ssl_verifyclient) { if (NULL == con->conf.ssl_ca_file_cert_names) { log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:", "can't verify client without ssl.ca-file for TLS server name", con->tlsext_server_name, ERR_error_string(ERR_get_error(), NULL)); return SSL_TLSEXT_ERR_ALERT_FATAL; } SSL_set_client_CA_list(ssl, SSL_dup_CA_list(con->conf.ssl_ca_file_cert_names)); /* forcing verification here is really not that useful - a client could just connect without SNI */ SSL_set_verify( ssl, SSL_VERIFY_PEER | (con->conf.ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), NULL ); SSL_set_verify_depth(ssl, con->conf.ssl_verifyclient_depth); } else { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } return SSL_TLSEXT_ERR_OK; }
// int VSslServer::ssl_servername_cb_debug(SSL *con, int *ad, void *arg, int* debug) // gilgil temp 2014.03.14 int VSslServer::ssl_servername_cb(SSL *con, int *ad, void *arg) { Q_UNUSED(ad) const char* serverName = SSL_get_servername(con, TLSEXT_NAMETYPE_host_name); // *debug = 1000; // gilgil temp 2014.03.14 if (serverName == NULL) { LOG_DEBUG("serverName is null"); return SSL_TLSEXT_ERR_NOACK; } // *debug = 2500; // gilgil temp 2014.03.14 // LOG_DEBUG("serverName=%p %s", serverName, serverName); // gilgil temp 2014.03.14 // *debug = 3000; // gilgil temp 2014.03.14 VSslServer* server = (VSslServer*)(arg); LOG_ASSERT(server != NULL); VSslServerSession* session = (VSslServerSession*)SSL_get_ex_data(con, VSslSession::VSSL_SESSION_IDENTIFY_INDEX); LOG_ASSERT(session->con == con); // *debug = 500; // gilgil temp 2014.03.14 // LOG_DEBUG("server=%p session=%p", server, session); // gilgil temp 2014.03.14 QString path = server->certificatePath; QFileInfo fi(path); if (!fi.isAbsolute()) { // path = VApp::_filePath() + path; // gilgil temp 2014.12.25 path = QCoreApplication::applicationDirPath() + QDir::separator() + path; } if (!path.endsWith('/') && !path.endsWith('\\')) path += QDir::separator(); QString fileName = path + serverName + ".pem"; // *debug = 4000; // gilgil temp 2014.03.14 { VLock lock(server->certificateCs); // protect file create critical section // *debug = 5000; // gilgil temp 2014.03.14 if (!QFile::exists(fileName)) { QProcess process; process.setWorkingDirectory(path); LOG_DEBUG("working directory=%s", qPrintable(process.workingDirectory())); // gilgil temp 2014.03.01 QString command = QString("\"%1_make_site.bat\" %2 2>&1").arg(path).arg(serverName); LOG_INFO("command=%s", qPrintable(command)); process.start(command); // LOG_DEBUG("pid=%llx", process.pid()); // gilgil temp 2015.01.02 // *debug = 6000; // gilgil temp 2014.03.14 if(!process.waitForStarted()) { LOG_FATAL("process.waitForStarted(%s) return false", qPrintable(command)); } // *debug = 700; // gilgil temp 2014.03.14 while(process.waitForReadyRead()) { QByteArray ba = process.readAll(); LOG_DEBUG("ba.size=%d", ba.size()) LOG_DEBUG("ba.datas=%s", ba.data()); } // *debug = 8000; // gilgil temp 2014.03.14 } // *debug = 9000; // gilgil temp 2014.03.14 // LOG_DEBUG("con=%p", con); // gilgil temp 2014.03.14 // *debug = 9100; // gilgil temp 2014.03.14 if (!session->setup(fileName)) { LOG_ERROR("session->setup(%s) return false", qPrintable(fileName)); } // *debug = 9500; // gilgil temp 2014.03.14 } return SSL_TLSEXT_ERR_NOACK; }
static int ngx_http_multiple_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { ngx_connection_t *c; ngx_http_connection_t *hc; const char *servername; ngx_str_t cert; ngx_str_t key; ngx_str_t host; ngx_http_multiple_ssl_srv_conf_t *mscf; c = ngx_ssl_get_connection(ssl_conn); if (c == NULL) { return 0; } hc = c->data; if (NULL == hc) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "multiple ssl connection data hc NULL"); return 0; } servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); if (servername == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl SSL_get_servername NULL"); return SSL_TLSEXT_ERR_NOACK; } host.len = ngx_strlen(servername); if (host.len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl servername len == 0"); return SSL_TLSEXT_ERR_NOACK; } host.data = (u_char *) servername; ngx_log_error(NGX_LOG_INFO, c->log, 0, "multiple ssl servername \"%V\"", &host); mscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_multiple_ssl_module); if (NULL == mscf) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl mscf NULL"); return SSL_TLSEXT_ERR_NOACK; } if (!mscf->multiple_ssl_enable) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl multiple_ssl_enable OFF"); return SSL_TLSEXT_ERR_NOACK; } cert.len = mscf->multiple_ssl_cert_path.len + 2 + host.len + ngx_strlen(".cert.der"); key.len = mscf->multiple_ssl_cert_path.len + 2 + host.len + ngx_strlen(".key.der"); cert.data = ngx_pnalloc(c->pool, cert.len); if (NULL == cert.data) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl cert.data NULL"); return SSL_TLSEXT_ERR_NOACK; } ngx_memzero(cert.data, cert.len); ngx_sprintf(cert.data, "%V/%V.cert.der", &mscf->multiple_ssl_cert_path, &host); *(cert.data+cert.len) = 0; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl cert %V", &cert); key.data = ngx_pnalloc(c->pool, key.len+1); if (NULL == key.data) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "multiple ssl key.data NULL"); return SSL_TLSEXT_ERR_NOACK; } ngx_memzero(key.data, key.len); ngx_sprintf(key.data, "%V/%V.key.der", &mscf->multiple_ssl_cert_path, &host); *(key.data+key.len) = 0; if (0 != access((const char *)cert.data, F_OK|R_OK)) { ngx_log_debug1(NGX_LOG_WARN, c->log, 0, "multiple ssl cert [%V] not exists or not read", &cert); return SSL_TLSEXT_ERR_NOACK; } ngx_http_multiple_ssl_set_der_certificate(ssl_conn, &cert, &key); return SSL_TLSEXT_ERR_OK; }
static ssize_t sr_read(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct sslrouter_session *sr = (struct sslrouter_session *) cs; int ret = SSL_read(sr->ssl, main_peer->in->buf + main_peer->in->pos, main_peer->in->len - main_peer->in->pos); if (ret > 0) { // fix the buffer main_peer->in->pos += ret; // check for pending data int ret2 = SSL_pending(sr->ssl); if (ret2 > 0) { if (uwsgi_buffer_fix(main_peer->in, main_peer->in->len + ret2 )) { uwsgi_cr_log(main_peer, "cannot fix the buffer to %d\n", main_peer->in->len + ret2); return -1; } if (SSL_read(sr->ssl, main_peer->in->buf + main_peer->in->pos, ret2) != ret2) { uwsgi_cr_log(main_peer, "SSL_read() on %d bytes of pending data failed\n", ret2); return -1; } // fix the buffer main_peer->in->pos += ret2; } if (!main_peer->session->peers) { // add a new peer struct corerouter_peer *peer = uwsgi_cr_peer_add(cs); // set default peer hook peer->last_hook_read = sr_instance_read; // use the address as hostname peer->key = cs->ugs->name; peer->key_len = cs->ugs->name_len; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (usr.sni) { const char *servername = SSL_get_servername(sr->ssl, TLSEXT_NAMETYPE_host_name); if (servername) { peer->key = (char *) servername; peer->key_len = strlen(servername); } } #endif // the mapper hook if (cs->corerouter->mapper(cs->corerouter, peer)) { return -1; } if (peer->instance_address_len == 0) { return -1; } peer->can_retry = 1; cr_connect(peer, sr_instance_connected); return 1; } main_peer->session->peers->out = main_peer->in; main_peer->session->peers->out_pos = 0; cr_write_to_backend(main_peer, sr_instance_write); return ret; } if (ret == 0) return 0; int err = SSL_get_error(sr->ssl, ret); if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, sr_read); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, sr_read); return 1; } else if (err == SSL_ERROR_SYSCALL) { uwsgi_cr_error(main_peer, "sr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
static char *ssl_var_lookup_ssl(apr_pool_t *p, SSLConnRec *sslconn, request_rec *r, char *var) { char *result; X509 *xs; STACK_OF(X509) *sk; SSL *ssl; result = NULL; ssl = sslconn->ssl; if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) { result = ssl_var_lookup_ssl_version(p, var+8); } else if (ssl != NULL && strcEQ(var, "PROTOCOL")) { result = (char *)SSL_get_version(ssl); } else if (ssl != NULL && strcEQ(var, "SESSION_ID")) { char buf[MODSSL_SESSION_ID_STRING_LEN]; SSL_SESSION *pSession = SSL_get_session(ssl); if (pSession) { IDCONST unsigned char *id; unsigned int idlen; #ifdef OPENSSL_NO_SSL_INTERN id = (unsigned char *)SSL_SESSION_get_id(pSession, &idlen); #else id = pSession->session_id; idlen = pSession->session_id_length; #endif result = apr_pstrdup(p, modssl_SSL_SESSION_id2sz(id, idlen, buf, sizeof(buf))); } } else if(ssl != NULL && strcEQ(var, "SESSION_RESUMED")) { if (SSL_session_reused(ssl) == 1) result = "Resumed"; else result = "Initial"; } else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) { result = ssl_var_lookup_ssl_cipher(p, sslconn, var+6); } else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) { sk = SSL_get_peer_cert_chain(ssl); result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18); } else if (ssl != NULL && strcEQ(var, "CLIENT_CERT_RFC4523_CEA")) { result = ssl_var_lookup_ssl_cert_rfc4523_cea(p, ssl); } else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) { result = ssl_var_lookup_ssl_cert_verify(p, sslconn); } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) { if ((xs = SSL_get_peer_certificate(ssl)) != NULL) { result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); X509_free(xs); } } else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) { if ((xs = SSL_get_certificate(ssl)) != NULL) { result = ssl_var_lookup_ssl_cert(p, r, xs, var+7); /* SSL_get_certificate is different from SSL_get_peer_certificate. * No need to X509_free(xs). */ } } else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) { result = ssl_var_lookup_ssl_compress_meth(ssl); } #ifdef HAVE_TLSEXT else if (ssl != NULL && strcEQ(var, "TLS_SNI")) { result = apr_pstrdup(p, SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)); } #endif else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) { int flag = 0; #ifdef SSL_get_secure_renegotiation_support flag = SSL_get_secure_renegotiation_support(ssl); #endif result = apr_pstrdup(p, flag ? "true" : "false"); } #ifdef HAVE_SRP else if (ssl != NULL && strcEQ(var, "SRP_USER")) { if ((result = SSL_get_srp_username(ssl)) != NULL) { result = apr_pstrdup(p, result); } } else if (ssl != NULL && strcEQ(var, "SRP_USERINFO")) { if ((result = SSL_get_srp_userinfo(ssl)) != NULL) { result = apr_pstrdup(p, result); } } #endif return result; }