33#define LOG_PREFIX "tls"
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/server/pair.h>
40#include <freeradius-devel/protocol/tls/freeradius.h>
88static bool tls_alpn_valid(
unsigned char const *alpn,
size_t len)
92 if (
len == 0)
return false;
95 if (alpn[i] == 0)
return false;
121static int tls_session_alpn_select_cb(SSL *ssl,
unsigned char const **
out,
unsigned char *outlen,
122 unsigned char const *
in,
unsigned int inlen,
UNUSED void *arg)
125 fr_tls_conf_t
const *
conf = fr_tls_session_conf(ssl);
141 for (i = 0; i < inlen; i +=
in[i] + 1) {
142 RDEBUG2(
"(TLS) ALPN - peer offers \"%.*s\"",
in[i], &
in[i + 1]);
152 if (SSL_select_next_proto(
UNCONST(
unsigned char **,
out), outlen,
153 conf->alpn, (
unsigned int)
conf->sizeof_alpn,
154 in, inlen) != OPENSSL_NPN_NEGOTIATED) {
155 REDEBUG(
"(TLS) ALPN - no protocol in common with the peer");
156 return SSL_TLSEXT_ERR_ALERT_FATAL;
159 RDEBUG2(
"(TLS) ALPN - chose \"%.*s\"", (
int) *outlen, *
out);
161 return SSL_TLSEXT_ERR_OK;
177int fr_tls_ctx_alpn_set(SSL_CTX *ctx, fr_tls_conf_t
const *
conf,
bool client)
183 if (
conf->alpn_required) {
184 ERROR(
"ALPN is required, but no protocols were set");
191 if (!tls_alpn_valid(
conf->alpn,
conf->sizeof_alpn)) {
192 ERROR(
"ALPN protocol list is malformed, or does not match sizeof_alpn (%zu)",
202 if (SSL_CTX_set_alpn_protos(ctx,
conf->alpn, (
unsigned int)
conf->sizeof_alpn) != 0) {
203 fr_tls_log_perror(NULL,
"Failed setting the ALPN protocol list");
207 SSL_CTX_set_alpn_select_cb(ctx, tls_session_alpn_select_cb, NULL);
220static bool tls_session_alpn(fr_tls_session_t *tls_session)
222 unsigned char const *
data;
223 unsigned int len = 0;
225 SSL_get0_alpn_selected(tls_session->ssl, &
data, &
len);
227 tls_session->alpn = NULL;
228 tls_session->sizeof_alpn = 0;
232 MEM(tls_session->alpn = talloc_memdup(tls_session,
data,
len));
233 tls_session->sizeof_alpn =
len;
253int fr_tls_session_alpn_check(
request_t *
request, fr_tls_session_t *tls_session)
255 fr_tls_conf_t
const *
conf = tls_session->conf;
263 if (!
conf->alpn)
return 0;
270 if (tls_session_alpn(tls_session)) {
273 RDEBUG2(
"(TLS) ALPN - agreed on \"%.*s\"",
274 (
int) tls_session->sizeof_alpn, tls_session->alpn);
284 if (!
conf->alpn_required) {
285 RDEBUG2(
"(TLS) ALPN - No protocols in common, not using ALPN");
289 REDEBUG(
"(TLS) ALPN - Failure, no protocols in common");
290 fr_tls_session_error_alert(
request, tls_session,
291 FR_ERROR_VALUE_ALPN_FAILED, SSL_AD_NO_APPLICATION_PROTOCOL);
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
HIDDEN fr_dict_attr_t const * attr_tls_alpn
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
#define RDEBUG_ENABLED2()
#define pair_append_session_state(_attr, _da)
Allocate and append a fr_pair_t to session-state list.
Stores an attribute, a value and various bits of other data.
static fr_sbuff_err_t char size_t fr_sbuff_t * in
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len