int SSLContext::selectNextProtocolCallback( SSL* ssl, unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, void *data) { SSLContext* ctx = (SSLContext*)data; if (ctx->advertisedNextProtocols_.size() > 1) { VLOG(3) << "SSLContext::selectNextProcolCallback() " << "client should be deterministic in selecting protocols."; } unsigned char *client; int client_len; if (ctx->advertisedNextProtocols_.empty()) { client = (unsigned char *) ""; client_len = 0; } else { client = ctx->advertisedNextProtocols_[0].protocols; client_len = ctx->advertisedNextProtocols_[0].length; } int retval = SSL_select_next_proto(out, outlen, server, server_len, client, client_len); if (retval != OPENSSL_NPN_NEGOTIATED) { VLOG(3) << "SSLContext::selectNextProcolCallback() " << "unable to pick a next protocol."; } return SSL_TLSEXT_ERR_OK; }
int SSLContext::alpnSelectCallback(SSL* /* ssl */, const unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* data) { SSLContext* context = (SSLContext*)data; CHECK(context); if (context->advertisedNextProtocols_.empty()) { *out = nullptr; *outlen = 0; } else { auto i = context->pickNextProtocols(); const auto& item = context->advertisedNextProtocols_[i]; if (SSL_select_next_proto((unsigned char**)out, outlen, item.protocols, item.length, in, inlen) != OPENSSL_NPN_NEGOTIATED) { return SSL_TLSEXT_ERR_NOACK; } } return SSL_TLSEXT_ERR_OK; }
static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { unsigned int srvlen; unsigned char *srv; #if (NGX_DEBUG) unsigned int i; #endif #if (NGX_HTTP_V2) ngx_http_connection_t *hc; #endif #if (NGX_HTTP_V2 || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); #endif #if (NGX_DEBUG) for (i = 0; i < inlen; i += in[i] + 1) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL ALPN supported by client: %*s", (size_t) in[i], &in[i + 1]); } #endif #if (NGX_HTTP_V2) hc = c->data; if (hc->addr_conf->http2) { srv = (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; } else #endif { srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1; } if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, in, inlen) != OPENSSL_NPN_NEGOTIATED) { return SSL_TLSEXT_ERR_NOACK; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL ALPN selected: %*s", (size_t) *outlen, *out); return SSL_TLSEXT_ERR_OK; }
static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { struct alpn_ctx *alpn_ctx = arg; if (SSL_select_next_proto((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) return SSL_TLSEXT_ERR_NOACK; return SSL_TLSEXT_ERR_OK; }
extern "C" int32_t CryptoNative_SslSelectNextProto(uint8_t** out, uint8_t* outlen, const uint8_t* server, uint32_t server_len, const uint8_t* client, uint32_t client_len) { #ifdef HAVE_OPENSSL_ALPN if (API_EXISTS(SSL_select_next_proto)) { return SSL_select_next_proto(out, outlen, server, server_len, client, client_len); } else #endif { return -1; } }
/* * The client SHOULD select the first protocol advertised by the server that it * also supports. In the event that the client doesn't support any of server's * protocols, or the server doesn't advertise any, it SHOULD select the first * protocol that it supports. */ static int client_npn_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { CTX_DATA *ctx_data = (CTX_DATA*)(arg); int ret; ret = SSL_select_next_proto(out, outlen, in, inlen, ctx_data->npn_protocols, ctx_data->npn_protocols_len); /* Accept both OPENSSL_NPN_NEGOTIATED and OPENSSL_NPN_NO_OVERLAP. */ TEST_check(ret == OPENSSL_NPN_NEGOTIATED || ret == OPENSSL_NPN_NO_OVERLAP); return SSL_TLSEXT_ERR_OK; }
static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { #if !defined(LWS_WITH_MBEDTLS) struct alpn_ctx *alpn_ctx = (struct alpn_ctx *)arg; if (SSL_select_next_proto((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) return SSL_TLSEXT_ERR_NOACK; #endif return SSL_TLSEXT_ERR_OK; }
static int next_proto_cb(SSL * s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { tlsextnextprotoctx *ctx = arg; if (!c_quiet) { /* We can assume that |in| is syntactically valid. */ unsigned i; BIO_printf(bio_c_out, "Protocols advertised by server: "); for (i = 0; i < inlen;) { if (i) BIO_write(bio_c_out, ", ", 2); BIO_write(bio_c_out, &in[i + 1], in[i]); i += in[i] + 1; } BIO_write(bio_c_out, "\n", 1); } ctx->status = SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len); return SSL_TLSEXT_ERR_OK; }
int SSLContext::selectNextProtocolCallback(SSL* ssl, unsigned char** out, unsigned char* outlen, const unsigned char* server, unsigned int server_len, void* data) { (void)ssl; // Make -Wunused-parameters happy SSLContext* ctx = (SSLContext*)data; if (ctx->advertisedNextProtocols_.size() > 1) { VLOG(3) << "SSLContext::selectNextProcolCallback() " << "client should be deterministic in selecting protocols."; } unsigned char* client = nullptr; unsigned int client_len = 0; bool filtered = false; auto cpf = ctx->getClientProtocolFilterCallback(); if (cpf) { filtered = (*cpf)(&client, &client_len, server, server_len); } if (!filtered) { if (ctx->advertisedNextProtocols_.empty()) { client = (unsigned char *) ""; client_len = 0; } else { client = ctx->advertisedNextProtocols_[0].protocols; client_len = ctx->advertisedNextProtocols_[0].length; } } int retval = SSL_select_next_proto(out, outlen, server, server_len, client, client_len); if (retval != OPENSSL_NPN_NEGOTIATED) { VLOG(3) << "SSLContext::selectNextProcolCallback() " << "unable to pick a next protocol."; } return SSL_TLSEXT_ERR_OK; }
/* * The server SHOULD select the most highly preferred protocol that it supports * and that is also advertised by the client. In the event that the server * supports no protocols that the client advertises, then the server SHALL * respond with a fatal "no_application_protocol" alert. */ static int server_alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { CTX_DATA *ctx_data = (CTX_DATA*)(arg); int ret; /* SSL_select_next_proto isn't const-correct... */ unsigned char *tmp_out; /* * The result points either to |in| or to |ctx_data->alpn_protocols|. * The callback is allowed to point to |in| or to a long-lived buffer, * so we can return directly without storing a copy. */ ret = SSL_select_next_proto(&tmp_out, outlen, ctx_data->alpn_protocols, ctx_data->alpn_protocols_len, in, inlen); *out = tmp_out; /* Unlike NPN, we don't tolerate a mismatch. */ return ret == OPENSSL_NPN_NEGOTIATED ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK; }
static int swSSL_alpn_advertised(SSL *ssl, const uchar **out, uchar *outlen, const uchar *in, uint32_t inlen, void *arg) { unsigned int srvlen; unsigned char *srv; #ifdef SW_USE_HTTP2 swSSL_config *cfg = arg; if (cfg->http_v2) { srv = (unsigned char *) SW_SSL_HTTP2_NPN_ADVERTISE SW_SSL_NPN_ADVERTISE; srvlen = sizeof(SW_SSL_HTTP2_NPN_ADVERTISE SW_SSL_NPN_ADVERTISE) - 1; } else #endif { srv = (unsigned char *) SW_SSL_NPN_ADVERTISE; srvlen = sizeof(SW_SSL_NPN_ADVERTISE) - 1; } if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, in, inlen) != OPENSSL_NPN_NEGOTIATED) { return SSL_TLSEXT_ERR_NOACK; } return SSL_TLSEXT_ERR_OK; }