*/
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.
*
int rbuflen;
char *rbufhead;
char rbuf[2048];
+ char *sni_hostname;
};
#if defined(DO_SSL)
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)
{
struct timeval start;
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;
-#endif
+ ast_free(stream->sni_hostname);
ast_assert(stream->fd == -1);
}
*/
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);
if (res <= 0) {
int sslerr = SSL_get_error(stream->ssl, res);
/* Set current info */
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;
error: