mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 19:16:15 +00:00
tcptls/iostream: Add support for setting SNI on client TLS connections
If the hostname field of the ast_tcptls_session_args structure is set (which it is for websocket client connections), that hostname will now automatically be used in an SNI TLS extension in the client hello. Resolves: #713 UserNote: Secure websocket client connections now send SNI in the TLS client hello.
This commit is contained in:
@@ -106,6 +106,17 @@ void ast_iostream_set_timeout_sequence(struct ast_iostream *stream, struct timev
|
|||||||
*/
|
*/
|
||||||
void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input);
|
void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Set the iostream's SNI hostname for TLS client connections
|
||||||
|
*
|
||||||
|
* \param stream A pointer to an iostream
|
||||||
|
* \param sni_hostname The hostname to use for SNI when in client mode
|
||||||
|
*
|
||||||
|
* \retval 0 if the hostname was set successfully.
|
||||||
|
* \retval -1 if memory could not be allocated for the hostname.
|
||||||
|
*/
|
||||||
|
int ast_iostream_set_sni_hostname(struct ast_iostream *stream, const char *sni_hostname);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Get an iostream's file descriptor.
|
* \brief Get an iostream's file descriptor.
|
||||||
*
|
*
|
||||||
|
@@ -46,6 +46,7 @@ struct ast_iostream {
|
|||||||
int rbuflen;
|
int rbuflen;
|
||||||
char *rbufhead;
|
char *rbufhead;
|
||||||
char rbuf[2048];
|
char rbuf[2048];
|
||||||
|
char *sni_hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(DO_SSL)
|
#if defined(DO_SSL)
|
||||||
@@ -152,6 +153,16 @@ void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive
|
|||||||
stream->exclusive_input = exclusive_input;
|
stream->exclusive_input = exclusive_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ast_iostream_set_sni_hostname(struct ast_iostream *stream, const char *sni_hostname)
|
||||||
|
{
|
||||||
|
ast_assert(stream != NULL);
|
||||||
|
|
||||||
|
ast_free(stream->sni_hostname);
|
||||||
|
stream->sni_hostname = ast_strdup(sni_hostname);
|
||||||
|
|
||||||
|
return stream->sni_hostname ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t iostream_read(struct ast_iostream *stream, void *buf, size_t size)
|
static ssize_t iostream_read(struct ast_iostream *stream, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct timeval start;
|
struct timeval start;
|
||||||
@@ -591,13 +602,9 @@ int ast_iostream_close(struct ast_iostream *stream)
|
|||||||
|
|
||||||
static void iostream_dtor(void *cookie)
|
static void iostream_dtor(void *cookie)
|
||||||
{
|
{
|
||||||
#ifdef AST_DEVMODE
|
|
||||||
/* Since the ast_assert below is the only one using stream,
|
|
||||||
* and ast_assert is only available with AST_DEVMODE, we
|
|
||||||
* put this in a conditional to avoid compiler warnings. */
|
|
||||||
struct ast_iostream *stream = cookie;
|
struct ast_iostream *stream = cookie;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
ast_free(stream->sni_hostname);
|
||||||
ast_assert(stream->fd == -1);
|
ast_assert(stream->fd == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,6 +646,15 @@ int ast_iostream_start_tls(struct ast_iostream **pstream, SSL_CTX *ssl_ctx, int
|
|||||||
*/
|
*/
|
||||||
SSL_set_fd(stream->ssl, stream->fd);
|
SSL_set_fd(stream->ssl, stream->fd);
|
||||||
|
|
||||||
|
if (client && !ast_strlen_zero(stream->sni_hostname)) {
|
||||||
|
if (!SSL_set_tlsext_host_name(stream->ssl, stream->sni_hostname)) {
|
||||||
|
ast_log(LOG_ERROR, "Unable to set SNI hostname '%s'\n",
|
||||||
|
stream->sni_hostname);
|
||||||
|
errno = EIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res = ssl_setup(stream->ssl);
|
res = ssl_setup(stream->ssl);
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
int sslerr = SSL_get_error(stream->ssl, res);
|
int sslerr = SSL_get_error(stream->ssl, res);
|
||||||
|
@@ -741,6 +741,13 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s
|
|||||||
/* Set current info */
|
/* Set current info */
|
||||||
ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
|
ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
|
||||||
|
|
||||||
|
if (!ast_strlen_zero(desc->hostname)) {
|
||||||
|
if (ast_iostream_set_sni_hostname(tcptls_session->stream, desc->hostname) != 0) {
|
||||||
|
ast_log(LOG_WARNING, "Unable to set SNI hostname '%s' on connection '%s'\n",
|
||||||
|
desc->hostname, desc->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tcptls_session;
|
return tcptls_session;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
Reference in New Issue
Block a user