Skip to content

Commit

Permalink
WIP tls: move server-side ALPN negotiation into tls_init_serverengine
Browse files Browse the repository at this point in the history
  • Loading branch information
elliefm committed Oct 28, 2024
1 parent 0ddd4ab commit 78f4949
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 83 deletions.
7 changes: 5 additions & 2 deletions cunit/backend.testc
Original file line number Diff line number Diff line change
Expand Up @@ -1210,8 +1210,11 @@ static void cmd_starttls(struct server_state *state)
SSL *tls_conn = NULL;
static struct saslprops_t saslprops = SASLPROPS_INITIALIZER;

r = tls_init_serverengine("backend_test", /*verifydepth*/5,
/*askcert*/1, NULL);
r = tls_init_serverengine("backend_test",
/*verifydepth*/5,
/*askcert*/1,
/*ALPN*/NULL,
NULL);
if (r < 0) {
server_printf(state, "BAD error initializing TLS\r\n");
server_flush(state);
Expand Down
12 changes: 6 additions & 6 deletions imap/httpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,16 +1289,16 @@ static int tls_init(int client_auth, struct buf *serverinfo)
if (!tls_enabled()) return HTTP_UNAVAILABLE;

SSL_CTX *ctx = NULL;
if (tls_init_serverengine("http", 5 /* depth */, client_auth, &ctx) == -1) {
if (tls_init_serverengine("http",
5 /* depth */,
client_auth,
http_alpn_map,
&ctx) == -1)
{
syslog(LOG_ERR, "error initializing TLS");
return HTTP_SERVER_ERROR;
}

#ifdef HAVE_TLS_ALPN
/* enable TLS ALPN extension */
SSL_CTX_set_alpn_select_cb(ctx, tls_alpn_select, (void *) http_alpn_map);
#endif

httpd_tls_enabled = 1;

return 0;
Expand Down
6 changes: 1 addition & 5 deletions imap/imapd.c
Original file line number Diff line number Diff line change
Expand Up @@ -9301,6 +9301,7 @@ static void cmd_starttls(char *tag, int imaps)
result=tls_init_serverengine("imap",
5, /* depth to verify */
!imaps, /* can client auth? */
imap_alpn_map,
&ctx);

if (result == -1) {
Expand All @@ -9316,11 +9317,6 @@ static void cmd_starttls(char *tag, int imaps)
return;
}

#ifdef HAVE_TLS_ALPN
/* enable TLS ALPN extension */
SSL_CTX_set_alpn_select_cb(ctx, tls_alpn_select, (void *) imap_alpn_map);
#endif

if (imaps == 0)
{
prot_printf(imapd_out, "%s OK Begin TLS negotiation now\r\n", tag);
Expand Down
5 changes: 3 additions & 2 deletions imap/lmtpengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,8 +1439,9 @@ void lmtpmode(struct lmtp_func *func,
}

r=tls_init_serverengine("lmtp",
5, /* depth to verify */
1, /* can client auth? */
5, /* depth to verify */
1, /* can client auth? */
NULL, /* no ALPN id for lmtp */
NULL);

if (r == -1) {
Expand Down
1 change: 1 addition & 0 deletions imap/mupdate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,7 @@ static void cmd_starttls(struct conn *C, const char *tag)
result=tls_init_serverengine("mupdate",
5, /* depth to verify */
1, /* can client auth? */
NULL, /* no ALPN id for mupdate */
NULL);

if (result == -1) {
Expand Down
10 changes: 3 additions & 7 deletions imap/nntpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4021,8 +4021,9 @@ static void cmd_starttls(int nntps)

SSL_CTX *ctx = NULL;
result=tls_init_serverengine("nntp",
5, /* depth to verify */
!nntps, /* can client auth? */
5, /* depth to verify */
!nntps, /* can client auth? */
nntp_alpn_map, /* ALPN protocols */
&ctx);

if (result == -1) {
Expand All @@ -4037,11 +4038,6 @@ static void cmd_starttls(int nntps)
return;
}

#ifdef HAVE_TLS_ALPN
/* enable TLS ALPN extension */
SSL_CTX_set_alpn_select_cb(ctx, tls_alpn_select, (void *) nntp_alpn_map);
#endif

if (nntps == 0)
{
prot_printf(nntp_out, "382 %s\r\n", "Begin TLS negotiation now");
Expand Down
10 changes: 3 additions & 7 deletions imap/pop3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -1169,8 +1169,9 @@ static void cmd_starttls(int pop3s)

SSL_CTX *ctx = NULL;
result=tls_init_serverengine("pop3",
5, /* depth to verify */
!pop3s, /* can client auth? */
5, /* depth to verify */
!pop3s, /* can client auth? */
pop3_alpn_map, /* ALPN protocols */
&ctx);

if (result == -1) {
Expand All @@ -1185,11 +1186,6 @@ static void cmd_starttls(int pop3s)
return;
}

#ifdef HAVE_TLS_ALPN
/* enable TLS ALPN extension */
SSL_CTX_set_alpn_select_cb(ctx, tls_alpn_select, (void *) pop3_alpn_map);
#endif

if (pop3s == 0)
{
prot_printf(popd_out, "+OK %s\r\n", "Begin TLS negotiation now");
Expand Down
1 change: 1 addition & 0 deletions imap/sync_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ static void cmd_starttls(void)
result=tls_init_serverengine("csync",
5, /* depth to verify */
1, /* can client auth? */
NULL, /* no ALPN id for csync */
NULL);

if (result == -1) {
Expand Down
86 changes: 47 additions & 39 deletions imap/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,41 @@ static int tls_rand_init(void)
#endif
}

/* Select an application protocol from the client list in order of preference */
static int alpn_select_cb(SSL *ssl __attribute__((unused)),
const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *server_list)
{
strarray_t ids = STRARRAY_INITIALIZER;

for (; inlen; inlen -= (in[0] + 1), in += in[0] + 1) {
struct tls_alpn_t *alpn;

for (alpn = (struct tls_alpn_t *) server_list; alpn->id; alpn++) {
if ((in[0] == strlen(alpn->id)) &&
memcmp(alpn->id, in + 1, in[0]) == 0 &&
(!alpn->check_availabilty || alpn->check_availabilty(alpn->rock))) {

strarray_fini(&ids);

*out = in + 1;
*outlen = in[0];
return SSL_TLSEXT_ERR_OK;
}
}

strarray_appendm(&ids, xstrndup((const char *) in + 1, in[0]));
}

char *proto = strarray_join(&ids, ", ");
xsyslog(LOG_NOTICE, "ALPN failed", "proto=<%s>", proto);
free(proto);
strarray_fini(&ids);

return SSL_TLSEXT_ERR_ALERT_FATAL;
}

/*
* This is the setup routine for the SSL server. As smtpd might be called
* more than once, we only want to do the initialization one time.
Expand All @@ -727,10 +762,11 @@ static int tls_rand_init(void)

/* must be called after cyrus_init */
// I am the server
EXPORTED int tls_init_serverengine(const char *ident,
int verifydepth,
int askcert,
SSL_CTX **ret)
EXPORTED int tls_init_serverengine(const char *ident,
int verifydepth,
int askcert,
const struct tls_alpn_t *alpn_map,
SSL_CTX **ret)
{
int off = 0;
int verify_flags = SSL_VERIFY_NONE;
Expand Down Expand Up @@ -1082,6 +1118,13 @@ EXPORTED int tls_init_serverengine(const char *ident,
free(tofree);
}

#ifdef HAVE_TLS_ALPN
if (alpn_map)
SSL_CTX_set_alpn_select_cb(s_ctx, alpn_select_cb, (void *) alpn_map);
else
SSL_CTX_set_alpn_select_cb(s_ctx, NULL, NULL);
#endif

tls_serverengine = 1;
if (ret) *ret = s_ctx;

Expand Down Expand Up @@ -1751,41 +1794,6 @@ HIDDEN int tls_start_clienttls(int readfd, int writefd,
return r;
}

/* Select an application protocol from the client list in order of preference */
EXPORTED int tls_alpn_select(SSL *ssl __attribute__((unused)),
const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *server_list)
{
strarray_t ids = STRARRAY_INITIALIZER;

for (; inlen; inlen -= (in[0] + 1), in += in[0] + 1) {
struct tls_alpn_t *alpn;

for (alpn = (struct tls_alpn_t *) server_list; alpn->id; alpn++) {
if ((in[0] == strlen(alpn->id)) &&
memcmp(alpn->id, in + 1, in[0]) == 0 &&
(!alpn->check_availabilty || alpn->check_availabilty(alpn->rock))) {

strarray_fini(&ids);

*out = in + 1;
*outlen = in[0];
return SSL_TLSEXT_ERR_OK;
}
}

strarray_appendm(&ids, xstrndup((const char *) in + 1, in[0]));
}

char *proto = strarray_join(&ids, ", ");
xsyslog(LOG_NOTICE, "ALPN failed", "proto=<%s>", proto);
free(proto);
strarray_fini(&ids);

return SSL_TLSEXT_ERR_ALERT_FATAL;
}

#else

EXPORTED int tls_enabled(void)
Expand Down
11 changes: 3 additions & 8 deletions imap/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ struct tls_alpn_t {

/* init tls */
int tls_init_serverengine(const char *ident,
int verifydepth, /* depth to verify */
int askcert, /* 1 = client auth */
int verifydepth, /* depth to verify */
int askcert, /* 1 = client auth */
const struct tls_alpn_t *alpn_map, /* ALPN protocols */
SSL_CTX **ret);

int tls_init_clientengine(int verifydepth,
Expand All @@ -95,12 +96,6 @@ int tls_prune_sessions(void);
/* fill string buffer with info about tls connection */
int tls_get_info(SSL *conn, char *buf, size_t len);

/* Select an application protocol from the client list in order of preference */
int tls_alpn_select(SSL *ssl,
const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *server_list);

#endif /* HAVE_SSL */

#endif /* INCLUDED_TLS_H */
10 changes: 3 additions & 7 deletions timsieved/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,8 +935,9 @@ static int cmd_starttls(struct protstream *sieved_out,

SSL_CTX *ctx = NULL;
result=tls_init_serverengine("sieve",
5, /* depth to verify */
1, /* can client auth? */
5, /* depth to verify */
1, /* can client auth? */
sieve_alpn_map, /* ALPN protocols */
&ctx);

if (result == -1) {
Expand All @@ -948,11 +949,6 @@ static int cmd_starttls(struct protstream *sieved_out,
return TIMSIEVE_FAIL;
}

#ifdef HAVE_TLS_ALPN
/* enable TLS ALPN extension */
SSL_CTX_set_alpn_select_cb(ctx, tls_alpn_select, (void *) sieve_alpn_map);
#endif

prot_printf(sieved_out, "OK \"Begin TLS negotiation now\"\r\n");
/* must flush our buffers before starting tls */
prot_flush(sieved_out);
Expand Down

0 comments on commit 78f4949

Please sign in to comment.