SSL *ssl;
struct xprt_ops *xprt;
void *xprt_ctx;
+ int xprt_st; /* transport layer state, initialized to zero */
+ int tmp_early_data; /* 1st byte of early data, if any */
+ int sent_early_data; /* Amount of early data we sent so far */
+
};
DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
{
struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
+ struct ssl_sock_ctx *ctx = conn->xprt_ctx;
BIO *write_bio;
(void)ret; /* shut gcc stupid warning */
#endif
if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
- if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
+ if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
/* Long certificate chains optimz
If write and read bios are differents, we
consider that the buffering was activated,
write_bio = SSL_get_wbio(ssl);
if (write_bio != SSL_get_rbio(ssl)) {
BIO_set_write_buffer_size(write_bio, 16384);
- conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
+ ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
}
}
}
{
SSL *ssl;
struct connection *conn;
+ struct ssl_sock_ctx *ctx;
int err, depth;
ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
conn = SSL_get_ex_data(ssl, ssl_app_data_index);
- conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
+ ctx = conn->xprt_ctx;
+
+ ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
if (ok) /* no errors */
return ok;
/* check if CA error needs to be ignored */
if (depth > 0) {
- if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
- conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
- conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
+ if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
+ ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
+ ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
}
if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
return 0;
}
- if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
- conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
+ if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
+ ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
/* check if certificate error needs to be ignored */
if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
for a received record) */
if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
+ struct ssl_sock_ctx *ctx = conn->ctx;
const unsigned char *p = buf;
unsigned int payload;
- conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
+ ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
/* Check if this is a CVE-2014-0160 exploitation attempt. */
if (*p != TLS1_HB_REQUEST)
conn->err_code = CO_ER_SSL_NO_MEM;
return -1;
}
+ ctx->sent_early_data = 0;
+ ctx->tmp_early_data = -1;
if (global.maxsslconn && sslconns >= global.maxsslconn) {
conn->err_code = CO_ER_SSL_TOO_MANY;
if (conn->flags & CO_FL_EARLY_SSL_HS) {
size_t read_data;
- ret = SSL_read_early_data(ctx->ssl, &conn->tmp_early_data,
+ ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
1, &read_data);
if (ret == SSL_READ_EARLY_DATA_ERROR)
goto check_error;
#endif
if (empty_handshake) {
if (!errno) {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_EMPTY;
}
else {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_ABORT;
}
}
else {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_HANDSHAKE;
*/
conn_sock_drain(conn);
if (!conn->err_code)
- conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
+ conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
goto out_error;
}
#endif
if (empty_handshake) {
if (!errno) {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_EMPTY;
}
else {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_ABORT;
}
}
else {
- if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
+ if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
else
conn->err_code = CO_ER_SSL_HANDSHAKE;
*/
conn_sock_drain(conn);
if (!conn->err_code)
- conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
+ conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
goto out_error;
}
try = count;
if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
- conn->tmp_early_data != -1) {
- *b_tail(buf) = conn->tmp_early_data;
+ ctx->tmp_early_data != -1) {
+ *b_tail(buf) = ctx->tmp_early_data;
done++;
try--;
count--;
b_add(buf, 1);
- conn->tmp_early_data = -1;
+ ctx->tmp_early_data = -1;
continue;
}
try = count;
if (!(flags & CO_SFL_STREAMER) &&
- !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
+ !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
global_ssl.max_record && try > global_ssl.max_record) {
try = global_ssl.max_record;
}
* we're not limiting the upcoming send(), because if it
* fails, we'll have to retry with at least as many data.
*/
- conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
+ ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
}
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
max_early = 0;
}
- if (try + conn->sent_early_data > max_early) {
- try -= (try + conn->sent_early_data) - max_early;
+ if (try + ctx->sent_early_data > max_early) {
+ try -= (try + ctx->sent_early_data) - max_early;
if (try <= 0) {
if (!(conn->flags & CO_FL_EARLY_SSL_HS))
conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
if (ret == 1) {
ret = written_data;
- conn->sent_early_data += ret;
+ ctx->sent_early_data += ret;
if (objt_server(conn->target)) {
conn->flags &= ~CO_FL_EARLY_SSL_HS;
conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
if (ret > 0) {
/* A send succeeded, so we can consier ourself connected */
conn->flags |= CO_FL_CONNECTED;
- conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
+ ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
count -= ret;
done += ret;
}
/* returns 1 if client passed a certificate for this connection, 0 if not */
int ssl_sock_get_cert_used_conn(struct connection *conn)
{
+ struct ssl_sock_ctx *ctx = conn->xprt_ctx;
+
if (!ssl_sock_is_ssl(conn))
return 0;
- return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
+ return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
}
/* returns result from SSL verify */
smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
+ struct ssl_sock_ctx *ctx;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
return 0;
+ ctx = conn->xprt_ctx;
+
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
smp->flags = 0;
smp->data.type = SMP_T_BOOL;
- smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
+ smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
return 1;
}
smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
+ struct ssl_sock_ctx *ctx;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
return 0;
+ ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
}
smp->data.type = SMP_T_SINT;
- smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
+ smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
smp->flags = 0;
return 1;
smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
+ struct ssl_sock_ctx *ctx;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
+ ctx = conn->xprt_ctx;
smp->data.type = SMP_T_SINT;
- smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
+ smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
smp->flags = 0;
return 1;
smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
+ struct ssl_sock_ctx *ctx;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
return 0;
}
+ ctx = conn->xprt_ctx;
+
smp->data.type = SMP_T_SINT;
- smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
+ smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
smp->flags = 0;
return 1;