[asterisk-commits] twilson: branch group/srtp_reboot r244493 - in /team/group/srtp_reboot: ./ bu...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Feb 2 17:32:45 CST 2010
Author: twilson
Date: Tue Feb 2 17:32:41 2010
New Revision: 244493
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=244493
Log:
Initial import of newly merged SRTP code
The only test that has been done is that a polycom configured to use SRTP that
initiates a call, does result in an encrypted call. There's still a lot of work
to do, including a lot of documentation and cleanup. Progress, though.
Added:
team/group/srtp_reboot/channels/sdp_crypto.c (with props)
team/group/srtp_reboot/channels/sdp_crypto.h (with props)
team/group/srtp_reboot/channels/sip_srtp.c (with props)
team/group/srtp_reboot/channels/sip_srtp.h (with props)
team/group/srtp_reboot/include/asterisk/res_srtp.h (with props)
team/group/srtp_reboot/res/res_srtp.c (with props)
team/group/srtp_reboot/res/res_srtp.exports (with props)
Modified:
team/group/srtp_reboot/build_tools/menuselect-deps.in
team/group/srtp_reboot/channels/Makefile
team/group/srtp_reboot/channels/chan_sip.c
team/group/srtp_reboot/configure
team/group/srtp_reboot/configure.ac
team/group/srtp_reboot/include/asterisk/autoconfig.h.in
team/group/srtp_reboot/include/asterisk/rtp_engine.h
team/group/srtp_reboot/main/asterisk.exports
team/group/srtp_reboot/main/rtp_engine.c
team/group/srtp_reboot/makeopts.in
team/group/srtp_reboot/res/res_rtp_asterisk.c
Modified: team/group/srtp_reboot/build_tools/menuselect-deps.in
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/build_tools/menuselect-deps.in?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/build_tools/menuselect-deps.in (original)
+++ team/group/srtp_reboot/build_tools/menuselect-deps.in Tue Feb 2 17:32:41 2010
@@ -50,6 +50,7 @@
SPEEX_PREPROCESS=@PBX_SPEEX_PREPROCESS@
SQLITE3=@PBX_SQLITE3@
SQLITE=@PBX_SQLITE@
+SRTP=@PBX_SRTP@
SS7=@PBX_SS7@
OPENSSL=@PBX_OPENSSL@
SUPPSERV=@PBX_SUPPSERV@
Modified: team/group/srtp_reboot/channels/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/Makefile?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/channels/Makefile (original)
+++ team/group/srtp_reboot/channels/Makefile Tue Feb 2 17:32:41 2010
@@ -85,6 +85,8 @@
endif
endif
+chan_sip.so: sip_srtp.o sdp_crypto.o
+
chan_misdn.o: _ASTCFLAGS+=-Imisdn
misdn_config.o: _ASTCFLAGS+=-Imisdn
Modified: team/group/srtp_reboot/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/chan_sip.c?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/channels/chan_sip.c (original)
+++ team/group/srtp_reboot/channels/chan_sip.c Tue Feb 2 17:32:41 2010
@@ -270,6 +270,9 @@
#include "asterisk/stun.h"
#include "asterisk/cel.h"
#include "asterisk/strings.h"
+#include "sip_srtp.h"
+#include "sdp_crypto.h"
+
/*** DOCUMENTATION
<application name="SIPDtmfMode" language="en_US">
@@ -1519,6 +1522,7 @@
#define SIP_PAGE2_Q850_REASON (1 << 4) /*!< DP: Get/send cause code via Reason header */
/* Space for addition of other realtime flags in the future */
+#define SIP_PAGE2_SRTPCAPABLE (1 << 6) /*!< DP: Are we capable of handling SRTP? */
#define SIP_PAGE2_CONSTANT_SSRC (1 << 7) /*!< GDP: Don't change SSRC on reinvite */
#define SIP_PAGE2_SYMMETRICRTP (1 << 8) /*!< GDP: Whether symmetric RTP is enabled or not */
#define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
@@ -1852,6 +1856,7 @@
AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */
struct sip_invite_param *options; /*!< Options for INVITE */
struct sip_st_dlg *stimer; /*!< SIP Session-Timers */
+ struct sip_srtp *srtp; /*!< Structure for Secure RTP session data */
int red; /*!< T.140 RTP Redundancy */
int hangupcause; /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */
@@ -2755,6 +2760,10 @@
static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
+/*------ SRTP Support -------- */
+static int setup_srtp(struct sip_pvt *p);
+static int process_crypto(struct sip_pvt *p, const char *a);
+
/*------ T38 Support --------- */
static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan);
@@ -5711,6 +5720,17 @@
} else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) {
/* We're replacing a call. */
p->options->replaces = ast_var_value(current);
+ } else if (!strcasecmp(ast_var_name(current), "ENCRYPT_CALL") && ast_true(ast_var_value(current))) {
+ if (ast_test_flag(&p->flags[0], SIP_REINVITE)) {
+ ast_debug(1, "Reinviting not possible when using SRTP, ignoring canreinvite setting\n");
+ ast_clear_flag(&p->flags[0], SIP_REINVITE);
+ }
+
+ if (!p->srtp && setup_srtp(p) < 0) {
+ ast_log(LOG_WARNING, "SRTP setup failed\n");
+ return -1;
+ }
+
}
}
@@ -5914,6 +5934,11 @@
if (p->chanvars) {
ast_variables_destroy(p->chanvars);
p->chanvars = NULL;
+ }
+
+ if (p->srtp) {
+ sip_srtp_destroy(p->srtp);
+ p->srtp = NULL;
}
ast_string_field_free_memory(p);
@@ -8421,6 +8446,10 @@
const char *codecs;
int codec;
+ /* SRTP */
+ int secure_audio = FALSE;
+ int secure_video = FALSE;
+
/* Others */
int sendonly = -1;
int vsendonly = -1;
@@ -8520,6 +8549,7 @@
int video = FALSE;
int image = FALSE;
int text = FALSE;
+ char protocol[5] = {0,};
int x;
numberofports = 1;
@@ -8530,8 +8560,18 @@
nextm = get_sdp_iterate(&next, req, "m");
/* Search for audio media definition */
- if ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
- (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
+ if ((sscanf(m, "audio %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
+ (sscanf(m, "audio %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) {
+ if (!strcmp(protocol, "SAVP")) {
+ secure_audio = 1;
+ } else if (strcmp(protocol, "AVP")) {
+ ast_log(LOG_WARNING, "unknown SDP media protocol in offer: %s\n", protocol);
+ continue;
+ }
+ if (len < 0) {
+ ast_log(LOG_WARNING, "Unknown SDP media type in offer: %s\n", m);
+ continue;
+ }
audio = TRUE;
p->offered_media[SDP_AUDIO].offered = TRUE;
numberofmediastreams++;
@@ -8551,8 +8591,18 @@
ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
}
/* Search for video media definition */
- } else if ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
- (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
+ } else if ((sscanf(m, "video %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) ||
+ (sscanf(m, "video %30d RTP/%4s %n", &x, protocol, &len) == 2 && len >= 0)) {
+ if (!strcmp(protocol, "SAVP")) {
+ secure_video= 1;
+ } else if (strcmp(protocol, "AVP")) {
+ ast_log(LOG_WARNING, "unknown SDP media protocol in offer: %s\n", protocol);
+ continue;
+ }
+ if (len < 0) {
+ ast_log(LOG_WARNING, "Unknown SDP media type in offer: %s\n", m);
+ continue;
+ }
video = TRUE;
p->novideo = FALSE;
p->offered_media[SDP_VIDEO].offered = TRUE;
@@ -8649,6 +8699,8 @@
if (audio) {
if (process_sdp_a_sendonly(value, &sendonly))
processed = TRUE;
+ else if (!process_crypto(p, value))
+ processed = TRUE;
else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec))
processed = TRUE;
}
@@ -8696,10 +8748,30 @@
/* We have too many fax, audio and/or video and/or text media streams, fail this offer */
return -3;
+ if (secure_audio && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) {
+ ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n");
+ return -4;
+ }
+
+ if (!secure_audio && p->srtp) {
+ ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n");
+ return -4;
+ }
+
+ if (secure_video && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) {
+ ast_log(LOG_WARNING, "Can't provide secure video requested in SDP offer\n");
+ return -4;
+ }
+
+ if (!p->novideo && !secure_video && p->srtp) {
+ ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n");
+ return -4;
+ }
+
+
if (udptlportno == -1) {
change_t38_state(p, T38_DISABLED);
}
-
/* Now gather all of the codecs that we are asked for: */
ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability);
@@ -10557,6 +10629,7 @@
struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */
struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */
struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */
+ const char *a_crypto = NULL;
format_t x;
format_t capability = 0;
@@ -10571,6 +10644,7 @@
char codecbuf[SIPBUFSIZE];
char buf[SIPBUFSIZE];
char dummy_answer[256];
+ const char *protocol = NULL;
/* Set the SDP session name */
snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
@@ -10618,6 +10692,25 @@
get_our_media_address(p, needvideo, needtext, &sin, &vsin, &tsin, &dest, &vdest, &tdest);
+ /* Set encryption properties */
+ if (p->srtp) {
+ if (p->srtp->crypto) {
+ a_crypto = sdp_crypto_attrib(p->srtp->crypto);
+ } else {
+ p->srtp->crypto = sdp_crypto_setup();
+
+ if (p->srtp->crypto && (sdp_crypto_offer(p->srtp->crypto) >= 0)) {
+ a_crypto = sdp_crypto_attrib(p->srtp->crypto);
+ }
+ }
+
+ if (!a_crypto) {
+ ast_log(LOG_WARNING, "No SRTP key management enabled\n");
+ }
+ }
+
+ protocol = a_crypto ? "SAVP" : "AVP";
+
snprintf(owner, sizeof(owner), "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
@@ -10640,7 +10733,7 @@
/* Ok, we need video. Let's add what we need for video and set codecs.
Video is handled differently than audio since we can not transcode. */
if (needvideo) {
- ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
+ ast_str_append(&m_video, 0, "m=video %d RTP/%s", ntohs(vdest.sin_port), protocol);
/* Build max bitrate string */
if (p->maxcallbitrate)
@@ -10665,7 +10758,7 @@
/* We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us */
- ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
+ ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ntohs(dest.sin_port), protocol);
if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
hold = "a=recvonly\r\n";
@@ -10829,6 +10922,9 @@
len += m_text->used + a_text->used + strlen(hold);
if (add_t38)
len += m_modem->used + a_modem->used;
+ if (a_crypto) {
+ len += strlen(a_crypto);
+ }
add_header(resp, "Content-Type", "application/sdp");
add_header_contentLength(resp, len);
@@ -10868,6 +10964,9 @@
add_line(resp, a_modem->str);
} else if (p->offered_media[SDP_IMAGE].offered) {
add_line(resp, "m=image 0 udptl t38\r\n");
+ }
+ if (a_crypto) {
+ add_line(resp, a_crypto);
}
/* Update lastrtprx when we send our SDP */
@@ -18134,6 +18233,8 @@
ast_copy_string(buf, peer->cid_num, len);
} else if (!strcasecmp(colname, "codecs")) {
ast_getformatname_multiple(buf, len -1, peer->capability);
+ } else if (!strcasecmp(colname, "srtpcapable")) {
+ snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_SRTPCAPABLE));
} else if (!strncasecmp(colname, "chanvar[", 8)) {
char *chanvar=colname + 8;
struct ast_variable *v;
@@ -21480,8 +21581,12 @@
transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)));
} else if (p->t38.state == T38_DISABLED) {
/* If this is not a re-invite or something to ignore - it's critical */
- ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
- transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
+ if (p->srtp && !ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)) {
+ transmit_response_reliable(p, "488 Not Acceptable Here (crypto)", req);
+ } else {
+ ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+ transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
+ }
}
p->invitestate = INV_TERMINATED;
@@ -26901,6 +27006,50 @@
} while (0));
}
+/* SRTP */
+static int setup_srtp(struct sip_pvt *p)
+{
+ if (!ast_rtp_engine_srtp_is_registered()) {
+ ast_log(LOG_ERROR, "No SRTP module loaded, can't setup SRTP session.\n");
+ return -1;
+ }
+
+ if (!(p->srtp = sip_srtp_alloc())) { /* Allocate SRTP data structure */
+ return -1;
+ }
+
+ return 0;
+}
+
+static int process_crypto(struct sip_pvt *p, const char *a)
+{
+ if (strncasecmp(a, "crypto:", 7)) {
+ return -1;
+ }
+ if (!p->srtp) {
+ if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ ast_log(LOG_WARNING, "Ignoring unexpected crypto attribute in SDP answer\n");
+ return -1;
+ }
+
+ if (setup_srtp(p) < 0) {
+ return -1;
+ }
+ }
+
+ if (!p->srtp->crypto && !(p->srtp->crypto = sdp_crypto_setup())) {
+ return -1;
+ }
+
+ if (sdp_crypto_process(p->srtp->crypto, a, p->rtp) < 0) {
+ return -1;
+ }
+
+ ast_set_flag(p->srtp, SRTP_CRYPTO_OFFER_OK);
+
+ return 0;
+}
+
/*! \brief Reload module */
static int sip_do_reload(enum channelreloadreason reason)
{
Added: team/group/srtp_reboot/channels/sdp_crypto.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/sdp_crypto.c?view=auto&rev=244493
==============================================================================
--- team/group/srtp_reboot/channels/sdp_crypto.c (added)
+++ team/group/srtp_reboot/channels/sdp_crypto.c Tue Feb 2 17:32:41 2010
@@ -1,0 +1,292 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006 - 2007, Mikael Magnusson
+ *
+ * Mikael Magnusson <mikma at users.sourceforge.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file sdp_crypto.c
+ *
+ * \brief SDP Security descriptions
+ *
+ * Specified in RFC 4568
+ *
+ * \author Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/options.h"
+#include "asterisk/utils.h"
+#include "sdp_crypto.h"
+
+#define SRTP_MASTER_LEN 30
+#define SRTP_MASTERKEY_LEN 16
+#define SRTP_MASTERSALT_LEN ((SRTP_MASTER_LEN) - (SRTP_MASTERKEY_LEN))
+#define SRTP_MASTER_LEN64 (((SRTP_MASTER_LEN) * 8 + 5) / 6 + 1)
+
+struct sdp_crypto {
+ char *a_crypto;
+ unsigned char local_key[SRTP_MASTER_LEN];
+ char local_key64[SRTP_MASTER_LEN64];
+};
+
+static int set_crypto_policy(struct ast_srtp_policy *policy, int suite_val, const unsigned char *master_key, unsigned long ssrc, int inbound);
+
+static struct sdp_crypto *sdp_crypto_alloc(void)
+{
+ struct sdp_crypto *crypto;
+
+ if (!(crypto = ast_calloc(1, sizeof(*crypto)))) {
+ ast_log(LOG_ERROR, "Out of memory, can't allocate crypto structure\n");
+ }
+
+ return crypto;
+}
+
+void sdp_crypto_destroy(struct sdp_crypto *crypto)
+{
+ if (crypto->a_crypto) {
+ ast_free(crypto->a_crypto);
+ }
+ crypto->a_crypto = NULL;
+ ast_free(crypto);
+}
+
+struct sdp_crypto *sdp_crypto_setup(void)
+{
+ struct sdp_crypto *p;
+ int key_len;
+ unsigned char remote_key[SRTP_MASTER_LEN];
+
+ if (!(p = sdp_crypto_alloc())) {
+ return NULL;
+ }
+
+ if (ast_srtp_get_random(p->local_key, sizeof(p->local_key)) < 0) {
+ sdp_crypto_destroy(p);
+ return NULL;
+ }
+
+ ast_base64encode(p->local_key64, p->local_key, SRTP_MASTER_LEN, sizeof(p->local_key64));
+
+ key_len = ast_base64decode(remote_key, p->local_key64, sizeof(remote_key));
+
+ if (key_len != SRTP_MASTER_LEN) {
+ ast_log(LOG_ERROR, "base64 encode/decode bad len %d != %d\n", key_len, SRTP_MASTER_LEN);
+ }
+
+ if (memcmp(remote_key, p->local_key, SRTP_MASTER_LEN)) {
+ ast_log(LOG_ERROR, "base64 encode/decode bad key\n");
+ }
+
+ ast_debug(1 , "local_key64 %s len %zu\n", p->local_key64, strlen(p->local_key64));
+
+ return p;
+}
+
+static int set_crypto_policy(struct ast_srtp_policy *policy, int suite_val, const unsigned char *master_key, unsigned long ssrc, int inbound)
+{
+ const unsigned char *master_salt = NULL;
+
+ master_salt = master_key + SRTP_MASTERKEY_LEN;
+ if (ast_srtp_policy_set_master_key(policy, master_key, SRTP_MASTERKEY_LEN, master_salt, SRTP_MASTERSALT_LEN) < 0) {
+ return -1;
+ }
+
+ if (ast_srtp_policy_set_suite(policy, suite_val)) {
+ ast_log(LOG_WARNING, "Could not set remote SRTP suite\n");
+ return -1;
+ }
+
+ ast_srtp_policy_set_ssrc(policy, ssrc, inbound);
+
+ return 0;
+}
+
+static int sdp_crypto_activate(struct sdp_crypto *p, int suite_val, unsigned char *remote_key, struct ast_rtp_instance *rtp)
+{
+ struct ast_srtp_policy *local_policy = NULL;
+ struct ast_srtp_policy *remote_policy = NULL;
+ struct ast_rtp_instance_stats stats = {0,};
+ int res = -1;
+
+ if (!p) {
+ return -1;
+ }
+
+ if (!(local_policy = ast_srtp_policy_alloc())) {
+ return -1;
+ }
+
+ if (!(remote_policy = ast_srtp_policy_alloc())) {
+ goto err;
+ }
+
+ if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_LOCAL_SSRC)) {
+ goto err;
+ }
+
+ if (set_crypto_policy(local_policy, suite_val, p->local_key, stats.local_ssrc, 0) < 0) {
+ goto err;
+ }
+
+ if (set_crypto_policy(remote_policy, suite_val, remote_key, 0, 1) < 0) {
+ goto err;
+ }
+
+ /* FIXME MIKMA */
+ /* ^^^ I wish I knew what needed fixing... */
+ if (ast_rtp_instance_add_srtp_policy(rtp, local_policy)) {
+ ast_log(LOG_WARNING, "Could not set local SRTP policy\n");
+ goto err;
+ }
+
+ if (ast_rtp_instance_add_srtp_policy(rtp, remote_policy)) {
+ ast_log(LOG_WARNING, "Could not set remote SRTP policy\n");
+ goto err;
+ }
+
+ ast_debug(1 , "SRTP policy activated\n");
+ res = 0;
+
+err:
+ if (local_policy) {
+ ast_srtp_policy_destroy(local_policy);
+ }
+
+ if (remote_policy) {
+ ast_srtp_policy_destroy(remote_policy);
+ }
+
+ return res;
+}
+
+int sdp_crypto_process(struct sdp_crypto *p, const char *attr, struct ast_rtp_instance *rtp)
+{
+ char *str = NULL;
+ char *name = NULL;
+ char *tag = NULL;
+ char *suite = NULL;
+ char *key_params = NULL;
+ char *key_param = NULL;
+ char *session_params = NULL;
+ char *key_salt = NULL;
+ char *lifetime = NULL;
+ int found = 0;
+ int attr_len = strlen(attr);
+ int key_len = 0;
+ int suite_val = 0;
+ unsigned char remote_key[SRTP_MASTER_LEN];
+
+ if (!ast_rtp_engine_srtp_is_registered()) {
+ return -1;
+ }
+
+ str = ast_strdupa(attr);
+
+ name = strsep(&str, ":");
+ tag = strsep(&str, " ");
+ suite = strsep(&str, " ");
+ key_params = strsep(&str, " ");
+ session_params = strsep(&str, " ");
+
+ if (!tag || !suite) {
+ ast_log(LOG_WARNING, "Unrecognized a=%s", attr);
+ return -1;
+ }
+
+ if (session_params) {
+ ast_log(LOG_WARNING, "Unsupported crypto parameters: %s", session_params);
+ return -1;
+ }
+
+ if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80")) {
+ suite_val = AST_AES_CM_128_HMAC_SHA1_80;
+ } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
+ suite_val = AST_AES_CM_128_HMAC_SHA1_32;
+ } else {
+ ast_log(LOG_WARNING, "Unsupported crypto suite: %s\n", suite);
+ return -1;
+ }
+
+ while ((key_param = strsep(&key_params, ";"))) {
+ char *method = NULL;
+ char *info = NULL;
+
+ method = strsep(&key_param, ":");
+ info = strsep(&key_param, ";");
+
+ if (!strcmp(method, "inline")) {
+ key_salt = strsep(&info, "|");
+ lifetime = strsep(&info, "|");
+
+ if (lifetime) {
+ ast_log(LOG_NOTICE, "Crypto life time unsupported: %s\n", attr);
+ continue;
+ }
+
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ ast_log(LOG_NOTICE, "SRTP crypto offer not acceptable\n");
+ return -1;
+ }
+
+
+ if ((key_len = ast_base64decode(remote_key, key_salt, sizeof(remote_key))) != SRTP_MASTER_LEN) {
+ ast_log(LOG_WARNING, "SRTP sdescriptions key %d != %d\n", key_len, SRTP_MASTER_LEN);
+ return -1;
+ }
+
+ if (sdp_crypto_activate(p, suite_val, remote_key, rtp) < 0) {
+ return -1;
+ }
+
+ if (!p->a_crypto) {
+ if (!(p->a_crypto = ast_calloc(1, attr_len + 11))) {
+ ast_log(LOG_ERROR, "Could not allocate memory for a_crypto\n");
+ return -1;
+ }
+
+ snprintf(p->a_crypto, attr_len + 10, "a=crypto:%s %s inline:%s\r\n", tag, suite, p->local_key64);
+ }
+
+ return 0;
+}
+
+int sdp_crypto_offer(struct sdp_crypto *p)
+{
+ char crypto_buf[128];
+ const char *crypto_suite = "AES_CM_128_HMAC_SHA1_80"; /* Crypto offer */
+
+ if (p->a_crypto) {
+ ast_free(p->a_crypto);
+ }
+
+ snprintf(crypto_buf, sizeof(crypto_buf), "a=crypto:1 %s inline:%s\r\n", crypto_suite, p->local_key64);
+ p->a_crypto = ast_strdup(crypto_buf);
+
+ return 0;
+}
+
+const char *sdp_crypto_attrib(struct sdp_crypto *p)
+{
+ return p->a_crypto;
+}
Propchange: team/group/srtp_reboot/channels/sdp_crypto.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/srtp_reboot/channels/sdp_crypto.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/srtp_reboot/channels/sdp_crypto.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/srtp_reboot/channels/sdp_crypto.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/sdp_crypto.h?view=auto&rev=244493
==============================================================================
--- team/group/srtp_reboot/channels/sdp_crypto.h (added)
+++ team/group/srtp_reboot/channels/sdp_crypto.h Tue Feb 2 17:32:41 2010
@@ -1,0 +1,42 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006 - 2007, Mikael Magnusson
+ *
+ * Mikael Magnusson <mikma at users.sourceforge.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file sdp_crypto.h
+ *
+ * \brief SDP Security descriptions
+ *
+ * Specified in RFC 4568
+ *
+ * \author Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#ifndef _SDP_CRYPTO_H
+#define _SDP_CRYPTO_H
+
+#include <asterisk/rtp_engine.h>
+
+struct sdp_crypto;
+
+struct sdp_crypto *sdp_crypto_setup(void);
+void sdp_crypto_destroy(struct sdp_crypto *crypto);
+
+int sdp_crypto_process(struct sdp_crypto *p, const char *attr, struct ast_rtp_instance *rtp);
+int sdp_crypto_offer(struct sdp_crypto *p);
+const char *sdp_crypto_attrib(struct sdp_crypto *p);
+
+#endif /* _SDP_CRYPTO_H */
Propchange: team/group/srtp_reboot/channels/sdp_crypto.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/srtp_reboot/channels/sdp_crypto.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/srtp_reboot/channels/sdp_crypto.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/srtp_reboot/channels/sip_srtp.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/sip_srtp.c?view=auto&rev=244493
==============================================================================
--- team/group/srtp_reboot/channels/sip_srtp.c (added)
+++ team/group/srtp_reboot/channels/sip_srtp.c Tue Feb 2 17:32:41 2010
@@ -1,0 +1,53 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006 - 2007, Mikael Magnusson
+ *
+ * Mikael Magnusson <mikma at users.sourceforge.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file sip_srtp.c
+ *
+ * \brief SIP Secure RTP (SRTP)
+ *
+ * Specified in RFC 3711
+ *
+ * \author Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/utils.h"
+#include "sip_srtp.h"
+
+struct sip_srtp *sip_srtp_alloc(void)
+{
+ struct sip_srtp *srtp;
+
+ if (!(srtp = ast_calloc(1, sizeof(*srtp)))) {
+ ast_log(LOG_ERROR, "Out of memory, can't allocate srtp structure\n");
+ }
+
+ return srtp;
+}
+
+void sip_srtp_destroy(struct sip_srtp *srtp)
+{
+ if (srtp->crypto) {
+ sdp_crypto_destroy(srtp->crypto);
+ }
+ srtp->crypto = NULL;
+ ast_free(srtp);
+}
Propchange: team/group/srtp_reboot/channels/sip_srtp.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/srtp_reboot/channels/sip_srtp.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/srtp_reboot/channels/sip_srtp.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/srtp_reboot/channels/sip_srtp.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/sip_srtp.h?view=auto&rev=244493
==============================================================================
--- team/group/srtp_reboot/channels/sip_srtp.h (added)
+++ team/group/srtp_reboot/channels/sip_srtp.h Tue Feb 2 17:32:41 2010
@@ -1,0 +1,57 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006 - 2007, Mikael Magnusson
+ *
+ * Mikael Magnusson <mikma at users.sourceforge.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file sip_srtp.h
+ *
+ * \brief SIP Secure RTP (SRTP)
+ *
+ * Specified in RFC 3711
+ *
+ * \author Mikael Magnusson <mikma at users.sourceforge.net>
+ */
+
+#ifndef _SIP_SRTP_H
+#define _SIP_SRTP_H
+
+#include "sdp_crypto.h"
+
+/* SRTP flags */
+#define SRTP_ENCR_OPTIONAL (1<<1) /* SRTP encryption optional */
+#define SRTP_CRYPTO_ENABLE (1<<2)
+#define SRTP_CRYPTO_OFFER_OK (1<<3)
+
+/*! \brief structure for secure RTP audio */
+struct sip_srtp {
+ unsigned int flags;
+ struct sdp_crypto *crypto;
+};
+
+/*!
+ * \brief allocate a sip_srtp structure
+ * \retval a new malloc'd sip_srtp structure on success
+ * \retval NULL on failure
+*/
+struct sip_srtp *sip_srtp_alloc(void);
+
+/*!
+ * \brief free a sip_srtp structure
+ * \param srtp a sip_srtp structure
+*/
+void sip_srtp_destroy(struct sip_srtp *srtp);
+
+#endif /* _SIP_SRTP_H */
Propchange: team/group/srtp_reboot/channels/sip_srtp.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/srtp_reboot/channels/sip_srtp.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/srtp_reboot/channels/sip_srtp.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/srtp_reboot/configure.ac
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/configure.ac?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/configure.ac (original)
+++ team/group/srtp_reboot/configure.ac Tue Feb 2 17:32:41 2010
@@ -365,6 +365,7 @@
AST_EXT_LIB_SETUP_DEPENDENT([SPEEX_PREPROCESS], [speex_preprocess_ctl], [], [speex])
AST_EXT_LIB_SETUP([SQLITE], [SQLite], [sqlite])
AST_EXT_LIB_SETUP([SQLITE3], [SQLite], [sqlite3])
+AST_EXT_LIB_SETUP([SRTP], [Secure RTP], [srtp])
AST_EXT_LIB_SETUP([SUPPSERV], [mISDN Supplemental Services], [suppserv])
AST_EXT_LIB_SETUP([OPENSSL], [OpenSSL Secure Sockets Layer support], [ssl])
AST_EXT_LIB_SETUP([FREETDS], [FreeTDS], [tds])
@@ -1657,6 +1658,8 @@
AST_CHECK_OSPTK([3], [6], [0])
fi
+AST_EXT_LIB_CHECK([SRTP], [srtp], [srtp_init], [srtp/srtp.h])
+
AST_EXT_TOOL_CHECK([GMIME], [gmime-config], [], [], [#include <gmime/gmime.h>], [gboolean q = g_mime_check_version(0,0,0);])
AST_EXT_LIB_CHECK([HOARD], [hoard], [malloc], [])
Modified: team/group/srtp_reboot/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/include/asterisk/autoconfig.h.in?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/include/asterisk/autoconfig.h.in (original)
+++ team/group/srtp_reboot/include/asterisk/autoconfig.h.in Tue Feb 2 17:32:41 2010
@@ -861,6 +861,12 @@
/* Define to 1 if you have the `sqrtl' function. */
#undef HAVE_SQRTL
+/* Define to 1 if you have the Secure RTP library. */
+#undef HAVE_SRTP
+
+/* Define to the version of the Secure RTP library. */
+#undef HAVE_SRTP_VERSION
+
/* Define to 1 if you have the ISDN SS7 library. */
#undef HAVE_SS7
@@ -1287,9 +1293,6 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
-/* Define to 1 if the C compiler supports function prototypes. */
-#undef PROTOTYPES
-
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
@@ -1308,11 +1311,6 @@
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
-
-/* Define to 1 if the `setvbuf' function takes the buffering type as its
- second argument and the buffer pointer as the third, as on System V before
- release 3. */
-#undef SETVBUF_REVERSED
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
@@ -1334,20 +1332,30 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
-/* Define to 1 if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
+/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE
@@ -1364,20 +1372,6 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
-
-/* Enable extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-
-/* Define like PROTOTYPES; this can be used by system headers. */
-#undef __PROTOTYPES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
Added: team/group/srtp_reboot/include/asterisk/res_srtp.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/include/asterisk/res_srtp.h?view=auto&rev=244493
==============================================================================
--- team/group/srtp_reboot/include/asterisk/res_srtp.h (added)
+++ team/group/srtp_reboot/include/asterisk/res_srtp.h Tue Feb 2 17:32:41 2010
@@ -1,0 +1,67 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010 FIXME
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief SRTP resource
+ */
+
+#ifndef _ASTERISK_RES_SRTP_H
+#define _ASTERISK_RES_SRTP_H
+
+struct ast_srtp;
+struct ast_srtp_policy;
+struct ast_rtp_instance;
+
+struct ast_srtp_cb {
+ int (*no_ctx)(struct ast_rtp_instance *rtp, unsigned long ssrc, void *data);
+};
+
+struct ast_srtp_res {
+ int (*create)(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy);
+ void (*destroy)(struct ast_srtp *srtp);
+ int (*add_stream)(struct ast_srtp *srtp, struct ast_srtp_policy *policy);
+ void (*set_cb)(struct ast_srtp *srtp, const struct ast_srtp_cb *cb, void *data);
+ int (*unprotect)(struct ast_srtp *srtp, void *buf, int *size);
+ int (*protect)(struct ast_srtp *srtp, void **buf, int *size);
+ int (*get_random)(unsigned char *key, size_t len);
+};
+
+/* Crypto suites */
+enum ast_srtp_suite {
+ AST_AES_CM_128_HMAC_SHA1_80 = 1,
+ AST_AES_CM_128_HMAC_SHA1_32 = 2,
+ AST_F8_128_HMAC_SHA1_80 = 3
+};
+
+struct ast_srtp_policy_res {
+ struct ast_srtp_policy *(*alloc)(void);
+ void (*destroy)(struct ast_srtp_policy *policy);
+ int (*set_suite)(struct ast_srtp_policy *policy, enum ast_srtp_suite suite);
+ int (*set_master_key)(struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len);
+ void (*set_ssrc)(struct ast_srtp_policy *policy, unsigned long ssrc, int inbound);
+};
+
+void ast_srtp_set_srtp_cb(struct ast_rtp_instance *rtp, const struct ast_srtp_cb *cb, void *data);
+int ast_rtp_add_srtp_policy(struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy);
+struct ast_srtp_policy *ast_srtp_policy_alloc(void);
+int ast_srtp_policy_set_suite(struct ast_srtp_policy *policy, enum ast_srtp_suite suite);
+int ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy, const unsigned char *key, size_t key_len, const unsigned char *salt, size_t salt_len);
+void ast_srtp_policy_set_ssrc(struct ast_srtp_policy *policy, unsigned long ssrc, int inbound);
+
+void ast_srtp_policy_destroy(struct ast_srtp_policy *policy);
+int ast_srtp_get_random(unsigned char *key, size_t len);
+
+#endif /* _ASTERISK_RES_SRTP_H */
Propchange: team/group/srtp_reboot/include/asterisk/res_srtp.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/srtp_reboot/include/asterisk/res_srtp.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/srtp_reboot/include/asterisk/res_srtp.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/srtp_reboot/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/include/asterisk/rtp_engine.h?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/include/asterisk/rtp_engine.h (original)
+++ team/group/srtp_reboot/include/asterisk/rtp_engine.h Tue Feb 2 17:32:41 2010
@@ -70,6 +70,10 @@
#endif
#include "asterisk/astobj2.h"
+#include "asterisk/frame.h"
+#include "asterisk/netsock.h"
+#include "asterisk/sched.h"
+#include "asterisk/res_srtp.h"
/* Maximum number of payloads supported */
#define AST_RTP_MAX_PT 256
@@ -454,6 +458,11 @@
*/
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine);
+int ast_rtp_engine_register_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res);
+
+void ast_rtp_engine_unregister_srtp(void);
+int ast_rtp_engine_srtp_is_registered(void);
+
#define ast_rtp_glue_register(glue) ast_rtp_glue_register2(glue, ast_module_info->self)
/*!
@@ -1702,6 +1711,9 @@
*/
struct ast_channel *ast_rtp_instance_get_chan(struct ast_rtp_instance *instance);
+int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *policy);
+struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/group/srtp_reboot/main/asterisk.exports
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/main/asterisk.exports?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/main/asterisk.exports (original)
+++ team/group/srtp_reboot/main/asterisk.exports Tue Feb 2 17:32:41 2010
@@ -40,6 +40,7 @@
getloadavg;
ntohll;
htonll;
+ res_srtp;
local:
*;
};
Modified: team/group/srtp_reboot/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/main/rtp_engine.c?view=diff&rev=244493&r1=244492&r2=244493
==============================================================================
--- team/group/srtp_reboot/main/rtp_engine.c (original)
+++ team/group/srtp_reboot/main/rtp_engine.c Tue Feb 2 17:32:41 2010
@@ -38,6 +38,9 @@
#include "asterisk/astobj2.h"
#include "asterisk/pbx.h"
#include "asterisk/translate.h"
+
+struct ast_srtp_res *res_srtp;
+struct ast_srtp_policy_res *res_srtp_policy;
/*! Structure that represents an RTP session (instance) */
struct ast_rtp_instance {
@@ -67,6 +70,8 @@
struct ast_rtp_glue *glue;
/*! Channel associated with the instance */
struct ast_channel *chan;
+ /*! SRTP info associated with the instance */
+ struct ast_srtp *srtp;
};
/*! List of RTP engines that are currently registered */
@@ -1643,3 +1648,47 @@
{
[... 629 lines stripped ...]
More information about the asterisk-commits
mailing list