[svn-commits] twilson: branch group/srtp_reboot r245817 - in /team/group/srtp_reboot: chann...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Feb 9 17:22:11 CST 2010


Author: twilson
Date: Tue Feb  9 17:22:06 2010
New Revision: 245817

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=245817
Log:
Add the ability to control whether outbound calls offer SRTP

Adds the ENCRYPT() dialplan function (which will probably be renamed at some
point). Options are signalling or media. So Set(ENCRYPT(media)=1) would indicate
that encrypted media is a requirement for the call.

Also, sip.conf has the "encryption" option. It currently acts to force encryption
on a particular peer. If it is set, and a call from that peer comes in w/o an
SRTP offer, the call will be dropped.

Under most circumstances, the dialplan ENCRYPT() function will override the
sip.conf setting, but not on an incoming SIP call (since a PBX hasn't been
started at the time of the negotiation).

The idea is that any channel tech that supports encryption would be able to
check the encrypt_call_info datastore set by ENCRYPT and react accordingly.

An example dialplan that would first try an encrypted call, and if it failed
would attempt an unencrypted call would look something like:

exten => _600X,1,Set(ENCRYPT(signalling)=1)
exten => _600X,n,Set(ENCRYPT(media)=1)
exten => _600X,n,Dial(SIP/${EXTEN})
exten => _600X,n,GotoIf($["${HANGUPCAUSE}" = "58"]?encrypt_fail)
exten => _600X,n,Hangup
exten => _600X,n(encrypt_fail),Set(ENCRYPT(signalling)=0)
exten => _600X,n,Set(ENCRYPT(signalling)=0)
exten => _600X,n,Set(ENCRYPT(media)=0)
exten => _600X,n,Dial(SIP/${EXTEN})
exten => _600X,n,Hangup

After looking at that, I'll probably add ENCRYPT(all) as well.

This is still a work in progress. For one, I don't think there is currently
any encryption on RTCP and I'd like to add in-dial notification ability so
that you can have "Call is secure!"/"Call is insecure!" notifications play
alerting each side as to the security of the call (with the caveat that
Asterisk is a "man in the middle")


Added:
    team/group/srtp_reboot/funcs/func_encrypt.c   (with props)
Modified:
    team/group/srtp_reboot/channels/chan_sip.c
    team/group/srtp_reboot/channels/sip/include/sip.h
    team/group/srtp_reboot/include/asterisk/global_datastores.h
    team/group/srtp_reboot/main/asterisk.exports
    team/group/srtp_reboot/main/global_datastores.c

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=245817&r1=245816&r2=245817
==============================================================================
--- team/group/srtp_reboot/channels/chan_sip.c (original)
+++ team/group/srtp_reboot/channels/chan_sip.c Tue Feb  9 17:22:06 2010
@@ -262,6 +262,7 @@
 #include "asterisk/event.h"
 #include "asterisk/stun.h"
 #include "asterisk/cel.h"
+#include "asterisk/global_datastores.h"
 #include "sip/include/sip.h"
 #include "sip/include/config_parser.h"
 #include "sip/include/reqresp_parser.h"
@@ -4216,6 +4217,7 @@
 	struct varshead *headp;
 	struct ast_var_t *current;
 	const char *referer = NULL;   /* SIP referrer */
+	struct ast_datastore *ds;
 
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name);
@@ -4244,17 +4246,35 @@
 		} 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;
-			}
-
+		}
+		
+	}
+
+	/* Check to see if we should try to force encryption */
+	if ((ds = ast_channel_datastore_find(ast, &encrypt_call_info, NULL))) {
+		struct ast_encrypt_call_store *encrypt = ds->data;
+		if (encrypt->signalling && p->socket.type != SIP_TRANSPORT_TLS) {
+		   ast_log(LOG_WARNING, "Encrypted signalling is required\n");
+		   ast->hangupcause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+		   return -1;
+		}
+		if (encrypt->media) {
+			/* Allow the dialplan to override whether we offer SRTP */
+			ast_set_flag(&p->flags[1], SIP_PAGE2_USE_SRTP);
+		} else {
+			ast_clear_flag(&p->flags[1], SIP_PAGE2_USE_SRTP);
+		}
+	}
+
+	if (ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) {
+		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;
 		}
 	}
 
@@ -7079,6 +7099,8 @@
 				else if (video) {
 					if (process_sdp_a_sendonly(value, &vsendonly))
 						processed = TRUE;
+					else if (!process_crypto(p, value))
+						processed = TRUE;
 					else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec))
 						processed = TRUE;
 				}
@@ -7139,6 +7161,10 @@
 		return -4;
 	}
 
+	if (!(secure_audio || secure_video) && ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) {
+		ast_log(LOG_WARNING, "Matched device setup to use SRTP, but request was not!\n");
+		return -5;
+	}
 
 	if (udptlportno == -1) {
 		change_t38_state(p, T38_DISABLED);
@@ -16420,8 +16446,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 (!strcasecmp(colname, "encryption")) {
+		snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP));
 	} else  if (!strncasecmp(colname, "chanvar[", 8)) {
 		char *chanvar=colname + 8;
 		struct ast_variable *v;
@@ -19761,6 +19787,7 @@
 			} else if (p->t38.state == T38_DISABLED) {
 				/* If this is not a re-invite or something to ignore - it's critical */
 				if (p->srtp && !ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)) {
+					ast_log(LOG_WARNING, "Target does not support required crypto\n");
 					transmit_response_reliable(p, "488 Not Acceptable Here (crypto)", req);
 				} else {
 					ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
@@ -23516,6 +23543,8 @@
 				ast_string_field_set(peer, unsolicited_mailbox, v->value);
 			} else if (!strcasecmp(v->name, "use_q850_reason")) {
 				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON);
+			} else if (!strcasecmp(v->name, "encryption")) {
+				ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP);
 			}
 		}
 

Modified: team/group/srtp_reboot/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/channels/sip/include/sip.h?view=diff&rev=245817&r1=245816&r2=245817
==============================================================================
--- team/group/srtp_reboot/channels/sip/include/sip.h (original)
+++ team/group/srtp_reboot/channels/sip/include/sip.h Tue Feb  9 17:22:06 2010
@@ -308,7 +308,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: Whether we can handle SRTP */
+#define SIP_PAGE2_USE_SRTP              (1 << 6)    /*!< DP: Whether we should offer (only)  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 */
@@ -348,7 +348,7 @@
 	SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
 	SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
 	SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE | SIP_PAGE2_SYMMETRICRTP | SIP_PAGE2_CONSTANT_SSRC |\
-	SIP_PAGE2_Q850_REASON)
+	SIP_PAGE2_Q850_REASON | SIP_PAGE2_USE_SRTP)
 
 /*@}*/
 

Added: team/group/srtp_reboot/funcs/func_encrypt.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/funcs/func_encrypt.c?view=auto&rev=245817
==============================================================================
--- team/group/srtp_reboot/funcs/func_encrypt.c (added)
+++ team/group/srtp_reboot/funcs/func_encrypt.c Tue Feb  9 17:22:06 2010
@@ -1,0 +1,125 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2005-2006, Digium, Inc.
+ *
+ * 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 MD5 digest related dialplan functions
+ * 
+ * \author Terry Wilson <twilson at digium.com>
+ *
+ * \ingroup functions
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/module.h"
+#include "asterisk/pbx.h"
+#include "asterisk/global_datastores.h"
+
+/*** DOCUMENTATION
+	<function name="ENCRYPT" language="en_US">
+		<synopsis>
+			Set whether a call's signalling or media should be encrypted.
+		</synopsis>
+		<syntax>
+			<parameter name="signalling" />
+			<parameter name="media" />
+		</syntax>
+		<description>
+			<para>Set whether a call should be encrypted (if supported by the channel type)</para>
+		</description>
+	</function>
+ ***/
+
+static int encrypt_read(struct ast_channel *chan, const char *cmd,
+				 char *data, struct ast_str **buf, ssize_t len)
+{
+	struct ast_datastore *ds;
+	struct ast_encrypt_call_store *store;
+	ast_channel_lock(chan);
+	if (!(ds = ast_channel_datastore_find(chan, &encrypt_call_info, NULL))) {
+		ast_channel_unlock(chan);
+		return 0;
+	}
+	store = ds->data;
+	if (!strcasecmp(data, "signalling")) {
+		ast_str_set(buf, 0, "%u", store->signalling);
+	} else if (!strcasecmp(data, "media")) {
+		ast_str_set(buf, 0, "%u", store->media);
+	}
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
+static int encrypt_write(struct ast_channel *chan, const char *cmd, char *data,
+	const char *value)
+{
+	struct ast_datastore *ds;
+	struct ast_encrypt_call_store *store;
+
+	if (!chan || !value) {
+		return -1;
+	}
+
+	ast_channel_lock(chan);
+	if (!(ds = ast_channel_datastore_find(chan, &encrypt_call_info, NULL))) {
+		if (!(ds = ast_datastore_alloc(&encrypt_call_info, NULL))) {
+			return -1;
+		}
+		if (!(store = ast_calloc(1, sizeof(*store)))) {
+			ast_free(ds);
+			return -1;
+		}
+		ds->data = store;
+		ds->inheritance = DATASTORE_INHERIT_FOREVER;
+		ast_channel_datastore_add(chan, ds);
+	} else {
+		store = ds->data;
+	}
+	ast_channel_unlock(chan);
+
+	if (!strcasecmp(data, "signalling")) {
+		store->signalling = ast_true(value) ? 1 : 0;
+	} else if (!strcasecmp(data, "media")) {
+		store->media = ast_true(value) ? 1 : 0;
+	} else {
+		ast_log(LOG_WARNING, "Invalid option '%s'\n", data);
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct ast_custom_function encrypt_function = {
+	.name = "ENCRYPT",
+	.read2 = encrypt_read,
+	.write = encrypt_write,
+};
+
+static int unload_module(void)
+{
+	return ast_custom_function_unregister(&encrypt_function);
+}
+
+static int load_module(void)
+{
+	return ast_custom_function_register(&encrypt_function);
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ENCRYPT dialplan functions");

Propchange: team/group/srtp_reboot/funcs/func_encrypt.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/group/srtp_reboot/funcs/func_encrypt.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/group/srtp_reboot/funcs/func_encrypt.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/group/srtp_reboot/include/asterisk/global_datastores.h
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/include/asterisk/global_datastores.h?view=diff&rev=245817&r1=245816&r2=245817
==============================================================================
--- team/group/srtp_reboot/include/asterisk/global_datastores.h (original)
+++ team/group/srtp_reboot/include/asterisk/global_datastores.h Tue Feb  9 17:22:06 2010
@@ -27,10 +27,15 @@
 #include "asterisk/channel.h"
 
 extern const struct ast_datastore_info dialed_interface_info;
+extern const struct ast_datastore_info encrypt_call_info;
 
 struct ast_dialed_interface {
 	AST_LIST_ENTRY(ast_dialed_interface) list;
 	char interface[1];
 };
 
+struct ast_encrypt_call_store {
+	unsigned int signalling:1;
+	unsigned int media:1;
+};
 #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=245817&r1=245816&r2=245817
==============================================================================
--- team/group/srtp_reboot/main/asterisk.exports (original)
+++ team/group/srtp_reboot/main/asterisk.exports Tue Feb  9 17:22:06 2010
@@ -28,6 +28,7 @@
 		devstate2str;
 		__manager_event;
 		dialed_interface_info;
+		encrypt_call_info;
 		strsep;
 		setenv;
 		unsetenv;

Modified: team/group/srtp_reboot/main/global_datastores.c
URL: http://svnview.digium.com/svn/asterisk/team/group/srtp_reboot/main/global_datastores.c?view=diff&rev=245817&r1=245816&r2=245817
==============================================================================
--- team/group/srtp_reboot/main/global_datastores.c (original)
+++ team/group/srtp_reboot/main/global_datastores.c Tue Feb  9 17:22:06 2010
@@ -84,3 +84,29 @@
 	.destroy = dialed_interface_destroy,
 	.duplicate = dialed_interface_duplicate,
 };
+
+static void encrypt_call_store_destroy(void *data)
+{
+	struct ast_encrypt_call_store *store = data;
+
+	ast_free(store);
+}
+
+static void *encrypt_call_store_duplicate(void *data)
+{
+	struct ast_encrypt_call_store *old = data;
+	struct ast_encrypt_call_store *new;
+
+	if (!(new = ast_calloc(1, sizeof(*new)))) {
+		return NULL;
+	}
+	new->signalling = old->signalling;
+	new->media = old->media;
+
+	return new;
+}
+const struct ast_datastore_info encrypt_call_info = {
+	.type = "encrypt-call",
+	.destroy = encrypt_call_store_destroy,
+	.duplicate = encrypt_call_store_duplicate,
+};




More information about the svn-commits mailing list