[asterisk-commits] file: branch file/sha256-a-harsh-reality r417132 - /team/file/sha256-a-harsh-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Jun 23 11:23:03 CDT 2014
Author: file
Date: Mon Jun 23 11:23:00 2014
New Revision: 417132
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=417132
Log:
Perform DTLS handshake on RTCP.
Modified:
team/file/sha256-a-harsh-reality/res/res_rtp_asterisk.c
Modified: team/file/sha256-a-harsh-reality/res/res_rtp_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sha256-a-harsh-reality/res/res_rtp_asterisk.c?view=diff&rev=417132&r1=417131&r2=417132
==============================================================================
--- team/file/sha256-a-harsh-reality/res/res_rtp_asterisk.c (original)
+++ team/file/sha256-a-harsh-reality/res/res_rtp_asterisk.c Mon Jun 23 11:23:00 2014
@@ -361,6 +361,14 @@
double normdevrtt;
double stdevrtt;
unsigned int rtt_count;
+
+#ifdef HAVE_OPENSSL_SRTP
+ SSL *ssl; /*!< SSL session */
+ BIO *read_bio; /*!< Memory buffer for reading */
+ BIO *write_bio; /*!< Memory buffer for writing */
+ enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
+ enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
+#endif
};
struct rtp_red {
@@ -408,7 +416,7 @@
#ifdef HAVE_OPENSSL_SRTP
static int ast_rtp_activate(struct ast_rtp_instance *instance);
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp);
+static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
#endif
static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *ice, int use_srtp);
@@ -804,6 +812,69 @@
return 1;
}
+static int dtls_setup_rtcp(struct ast_rtp_instance *instance)
+{
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+ if (!rtp->ssl_ctx) {
+ return 0;
+ }
+
+ rtp->rtcp->dtls_setup = rtp->dtls_setup;
+
+ if (!(rtp->rtcp->ssl = SSL_new(rtp->ssl_ctx))) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for SSL context on RTCP of RTP instance '%p'\n",
+ instance);
+ goto error;
+ }
+
+ SSL_set_ex_data(rtp->rtcp->ssl, 0, rtp);
+ SSL_set_info_callback(rtp->rtcp->ssl, dtls_info_callback);
+
+ if (!(rtp->rtcp->read_bio = BIO_new(BIO_s_mem()))) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for inbound SSL traffic on RTCP of RTP instance '%p'\n",
+ instance);
+ goto error;
+ }
+ BIO_set_mem_eof_return(rtp->rtcp->read_bio, -1);
+
+ if (!(rtp->rtcp->write_bio = BIO_new(BIO_s_mem()))) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic on RTCP of RTP instance '%p'\n",
+ instance);
+ goto error;
+ }
+ BIO_set_mem_eof_return(rtp->rtcp->write_bio, -1);
+
+ SSL_set_bio(rtp->rtcp->ssl, rtp->rtcp->read_bio, rtp->rtcp->write_bio);
+
+ if (rtp->rtcp->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ SSL_set_accept_state(rtp->rtcp->ssl);
+ } else {
+ SSL_set_connect_state(rtp->rtcp->ssl);
+ }
+
+ rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+
+ return 0;
+
+error:
+ if (rtp->rtcp->read_bio) {
+ BIO_free(rtp->rtcp->read_bio);
+ rtp->rtcp->read_bio = NULL;
+ }
+
+ if (rtp->rtcp->write_bio) {
+ BIO_free(rtp->rtcp->write_bio);
+ rtp->rtcp->write_bio = NULL;
+ }
+
+ if (rtp->rtcp->ssl) {
+ SSL_free(rtp->rtcp->ssl);
+ rtp->rtcp->ssl = NULL;
+ }
+ return -1;
+}
+
static int ast_rtp_dtls_set_configuration(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
@@ -992,19 +1063,26 @@
SSL_free(rtp->ssl);
rtp->ssl = NULL;
}
+
+ if (rtp->rtcp && rtp->rtcp->ssl) {
+ SSL_free(rtp->rtcp->ssl);
+ rtp->rtcp->ssl = NULL;
+ }
}
static void ast_rtp_dtls_reset(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- /* If the SSL session is not yet finalized don't bother resetting */
- if (!SSL_is_init_finished(rtp->ssl)) {
- return;
- }
-
- SSL_shutdown(rtp->ssl);
- rtp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+ if (SSL_is_init_finished(rtp->ssl)) {
+ SSL_shutdown(rtp->ssl);
+ rtp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+ }
+
+ if (rtp->rtcp && SSL_is_init_finished(rtp->rtcp->ssl)) {
+ SSL_shutdown(rtp->rtcp->ssl);
+ rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+ }
}
static enum ast_rtp_dtls_connection ast_rtp_dtls_get_connection(struct ast_rtp_instance *instance)
@@ -1021,26 +1099,25 @@
return rtp->dtls_setup;
}
-static void ast_rtp_dtls_set_setup(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
-{
- struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- enum ast_rtp_dtls_setup old = rtp->dtls_setup;
+static void dtls_set_setup(enum ast_rtp_dtls_setup *dtls_setup, enum ast_rtp_dtls_setup setup, SSL *ssl)
+{
+ enum ast_rtp_dtls_setup old = *dtls_setup;
switch (setup) {
case AST_RTP_DTLS_SETUP_ACTIVE:
- rtp->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
+ *dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
break;
case AST_RTP_DTLS_SETUP_PASSIVE:
- rtp->dtls_setup = AST_RTP_DTLS_SETUP_ACTIVE;
+ *dtls_setup = AST_RTP_DTLS_SETUP_ACTIVE;
break;
case AST_RTP_DTLS_SETUP_ACTPASS:
/* We can't respond to an actpass setup with actpass ourselves... so respond with active, as we can initiate connections */
- if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
- rtp->dtls_setup = AST_RTP_DTLS_SETUP_ACTIVE;
+ if (*dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
+ *dtls_setup = AST_RTP_DTLS_SETUP_ACTIVE;
}
break;
case AST_RTP_DTLS_SETUP_HOLDCONN:
- rtp->dtls_setup = AST_RTP_DTLS_SETUP_HOLDCONN;
+ *dtls_setup = AST_RTP_DTLS_SETUP_HOLDCONN;
break;
default:
/* This should never occur... if it does exit early as we don't know what state things are in */
@@ -1048,21 +1125,34 @@
}
/* If the setup state did not change we go on as if nothing happened */
- if (old == rtp->dtls_setup) {
+ if (old == *dtls_setup) {
return;
}
/* If they don't want us to establish a connection wait until later */
- if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_HOLDCONN) {
+ if (*dtls_setup == AST_RTP_DTLS_SETUP_HOLDCONN) {
return;
}
- if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_ACTIVE) {
- SSL_set_connect_state(rtp->ssl);
- } else if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
- SSL_set_accept_state(rtp->ssl);
+ if (*dtls_setup == AST_RTP_DTLS_SETUP_ACTIVE) {
+ SSL_set_connect_state(ssl);
+ } else if (*dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ SSL_set_accept_state(ssl);
} else {
return;
+ }
+}
+
+static void ast_rtp_dtls_set_setup(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
+{
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+ if (rtp->ssl) {
+ dtls_set_setup(&rtp->dtls_setup, setup, rtp->ssl);
+ }
+
+ if (rtp->rtcp && rtp->rtcp->ssl) {
+ dtls_set_setup(&rtp->rtcp->dtls_setup, setup, rtp->rtcp->ssl);
}
}
@@ -1160,7 +1250,12 @@
#ifdef HAVE_OPENSSL_SRTP
if (rtp->ssl) {
SSL_do_handshake(rtp->ssl);
- dtls_srtp_check_pending(instance, rtp);
+ dtls_srtp_check_pending(instance, rtp, 0);
+ }
+
+ if (rtp->rtcp && rtp->rtcp->ssl) {
+ SSL_do_handshake(rtp->rtcp->ssl);
+ dtls_srtp_check_pending(instance, rtp, 1);
}
#endif
@@ -1386,21 +1481,33 @@
rtp->dtlstimerid = -1;
ast_mutex_unlock(&rtp->dtls_timer_lock);
- if (rtp->ssl) {
+ if (rtp->ssl && !SSL_is_init_finished(rtp->ssl)) {
DTLSv1_handle_timeout(rtp->ssl);
}
-
- dtls_srtp_check_pending(instance, rtp);
+ dtls_srtp_check_pending(instance, rtp, 0);
+
+ if (rtp->rtcp && rtp->rtcp->ssl && !SSL_is_init_finished(rtp->rtcp->ssl)) {
+ DTLSv1_handle_timeout(rtp->rtcp->ssl);
+ }
+ dtls_srtp_check_pending(instance, rtp, 1);
ao2_ref(instance, -1);
return 0;
}
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
-{
- size_t pending = BIO_ctrl_pending(rtp->write_bio);
+static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
+{
+ SSL *ssl = !rtcp ? rtp->ssl : rtp->rtcp->ssl;
+ BIO *write_bio = !rtcp ? rtp->write_bio : rtp->rtcp->write_bio;
+ size_t pending;
struct timeval dtls_timeout; /* timeout on DTLS */
+
+ if (!ssl || !write_bio) {
+ return;
+ }
+
+ pending = BIO_ctrl_pending(write_bio);
if (pending > 0) {
char outgoing[pending];
@@ -1408,14 +1515,18 @@
struct ast_sockaddr remote_address = { {0, } };
int ice;
- ast_rtp_instance_get_remote_address(instance, &remote_address);
+ if (!rtcp) {
+ ast_rtp_instance_get_remote_address(instance, &remote_address);
+ } else {
+ ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
+ }
/* If we do not yet know an address to send this to defer it until we do */
if (ast_sockaddr_isnull(&remote_address)) {
return;
}
- out = BIO_read(rtp->write_bio, outgoing, sizeof(outgoing));
+ out = BIO_read(write_bio, outgoing, sizeof(outgoing));
/* Stop existing DTLS timer if running */
ast_mutex_lock(&rtp->dtls_timer_lock);
@@ -1424,7 +1535,7 @@
rtp->dtlstimerid = -1;
}
- if (DTLSv1_get_timeout(rtp->ssl, &dtls_timeout)) {
+ if (DTLSv1_get_timeout(ssl, &dtls_timeout)) {
int timeout = dtls_timeout.tv_sec * 1000 + dtls_timeout.tv_usec / 1000;
ao2_ref(instance, +1);
if ((rtp->dtlstimerid = ast_sched_add(rtp->sched, timeout, dtls_srtp_handle_timeout, instance)) < 0) {
@@ -1434,7 +1545,7 @@
}
ast_mutex_unlock(&rtp->dtls_timer_lock);
- __rtp_sendto(instance, outgoing, out, 0, &remote_address, 0, &ice, 0);
+ __rtp_sendto(instance, outgoing, out, 0, &remote_address, rtcp, &ice, 0);
}
}
@@ -1445,7 +1556,13 @@
SSL_renegotiate(rtp->ssl);
SSL_do_handshake(rtp->ssl);
- dtls_srtp_check_pending(instance, rtp);
+ dtls_srtp_check_pending(instance, rtp, 0);
+
+ if (rtp->rtcp && rtp->rtcp->ssl) {
+ SSL_renegotiate(rtp->rtcp->ssl);
+ SSL_do_handshake(rtp->rtcp->ssl);
+ dtls_srtp_check_pending(instance, rtp, 1);
+ }
rtp->rekeyid = -1;
ao2_ref(instance, -1);
@@ -1598,50 +1715,53 @@
}
#ifdef HAVE_OPENSSL_SRTP
- if (!rtcp) {
- dtls_srtp_check_pending(instance, rtp);
-
- /* If this is an SSL packet pass it to OpenSSL for processing */
- if ((*in >= 20) && (*in <= 64)) {
- int res = 0;
-
- /* If no SSL session actually exists terminate things */
- if (!rtp->ssl) {
- ast_log(LOG_ERROR, "Received SSL traffic on RTP instance '%p' without an SSL session\n",
- instance);
- return -1;
- }
-
- /* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
- if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
- rtp->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
- SSL_set_accept_state(rtp->ssl);
- }
-
- dtls_srtp_check_pending(instance, rtp);
-
- BIO_write(rtp->read_bio, buf, len);
-
- len = SSL_read(rtp->ssl, buf, len);
-
- dtls_srtp_check_pending(instance, rtp);
-
- if (rtp->dtls_failure) {
- ast_log(LOG_ERROR, "DTLS failure occurred on RTP instance '%p', terminating\n",
- instance);
- return -1;
- }
-
- if (SSL_is_init_finished(rtp->ssl)) {
- /* Any further connections will be existing since this is now established */
+ dtls_srtp_check_pending(instance, rtp, rtcp);
+
+ /* If this is an SSL packet pass it to OpenSSL for processing */
+ if ((*in >= 20) && (*in <= 64)) {
+ SSL *ssl = !rtcp ? rtp->ssl : rtp->rtcp->ssl;
+ BIO *read_bio = !rtcp ? rtp->read_bio : rtp->rtcp->read_bio;
+ int res = 0;
+
+ /* If no SSL session actually exists terminate things */
+ if (!ssl) {
+ ast_log(LOG_ERROR, "Received SSL traffic on RTP instance '%p' without an SSL session\n",
+ instance);
+ return -1;
+ }
+
+ /* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
+ if (rtp->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
+ rtp->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
+ SSL_set_accept_state(ssl);
+ }
+
+ dtls_srtp_check_pending(instance, rtp, rtcp);
+
+ BIO_write(read_bio, buf, len);
+
+ len = SSL_read(ssl, buf, len);
+
+ dtls_srtp_check_pending(instance, rtp, rtcp);
+
+ if (rtp->dtls_failure) {
+ ast_log(LOG_ERROR, "DTLS failure occurred on RTP instance '%p', terminating\n",
+ instance);
+ return -1;
+ }
+
+ if (SSL_is_init_finished(ssl)) {
+ /* Any further connections will be existing since this is now established */
+ if (!rtcp) {
rtp->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
-
/* Use the keying material to set up key/salt information */
res = dtls_srtp_setup(rtp, srtp, instance);
+ } else {
+ rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
}
-
- return res;
- }
+ }
+
+ return res;
}
#endif
@@ -2107,6 +2227,11 @@
* RTP instance while it's active.
*/
close(rtp->rtcp->s);
+#ifdef HAVE_OPENSSL_SRTP
+ if (rtp->rtcp->ssl) {
+ SSL_free(rtp->rtcp->ssl);
+ }
+#endif
ast_free(rtp->rtcp);
}
@@ -4183,6 +4308,10 @@
}
#endif
+#ifdef HAVE_OPENSSL_SRTP
+ dtls_setup_rtcp(instance);
+#endif
+
return;
} else {
if (rtp->rtcp) {
@@ -4198,6 +4327,11 @@
rtp->rtcp->schedid = -1;
}
close(rtp->rtcp->s);
+#ifdef HAVE_OPENSSL_SRTP
+ if (rtp->rtcp->ssl) {
+ SSL_free(rtp->rtcp->ssl);
+ }
+#endif
ast_free(rtp->rtcp);
rtp->rtcp = NULL;
}
@@ -4496,16 +4630,19 @@
/* If ICE negotiation is enabled the DTLS Handshake will be performed upon completion of it */
#ifdef USE_PJPROJECT
- if (!rtp->ssl || rtp->ice) {
-#else
- if (!rtp->ssl) {
+ if (rtp->ice) {
+ return 0;
+ }
#endif
- return 0;
- }
-
- SSL_do_handshake(rtp->ssl);
-
- dtls_srtp_check_pending(instance, rtp);
+
+ if (rtp->ssl) {
+ SSL_do_handshake(rtp->ssl);
+ dtls_srtp_check_pending(instance, rtp, 0);
+ }
+ if (rtp->rtcp && rtp->rtcp->ssl) {
+ SSL_do_handshake(rtp->rtcp->ssl);
+ dtls_srtp_check_pending(instance, rtp, 1);
+ }
return 0;
}
More information about the asterisk-commits
mailing list