]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
ZRTP Support please download your SDK from http://www.zfone.com and use build/buildz...
authorBrian West <brian@freeswitch.org>
Wed, 20 May 2009 23:04:05 +0000 (23:04 +0000)
committerBrian West <brian@freeswitch.org>
Wed, 20 May 2009 23:04:05 +0000 (23:04 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13406 d0543943-73ff-0310-b7d9-9358b9ac24b2

Makefile.am
build/buildzrtp.sh [new file with mode: 0644]
configure.in
patches/zrtp_bnlib_pic.diff [new file with mode: 0644]
src/include/switch_types.h
src/switch_core.c
src/switch_rtp.c

index 59846b562445892ce981eee3f272390f4a2770fc..61e4120b0aff2111070637ff93ee0f472d7042b3 100644 (file)
@@ -198,6 +198,10 @@ libfreeswitch_la_SOURCES += src/switch_odbc.c
 libfreeswitch_la_LDFLAGS     += $(ODBC_LIB_FLAGS)
 endif
 
+if ENABLE_ZRTP
+libfreeswitch_la_LDFLAGS  += -lzrtp -lbn
+endif
+
 bin_SCRIPTS = scripts/gentls_cert scripts/fsxs
 
 src/include/switch_swigable_cpp.h: src/include/switch_cpp.h
diff --git a/build/buildzrtp.sh b/build/buildzrtp.sh
new file mode 100644 (file)
index 0000000..9df8fff
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+tar zxf libzrtp-0.81.514.tar.gz
+cd libzrtp-0.81.514
+patch -p1 < ../patches/zrtp_bnlib_pic.diff
+cd projects/gnu/
+./configure CFLAGS="-fPIC"
+make
+make install
index 834603f4e9e969135ba6d336718051410f80a301..f6afd157d560cc9d2a83a89eff17a0de921df90a 100644 (file)
@@ -264,6 +264,21 @@ if test "${enable_debug}" = "yes"; then
 
 fi
 
+AC_ARG_ENABLE(zrtp,
+       [AS_HELP_STRING([--enable-zrtp], [Compile with zrtp Support])],,[enable_zrtp="no"])
+if test "x$enable_zrtp" = "xyes" ; then
+   saved_LIBS=$LIBS
+   LIBS="$saved_LIBS -L/usr/local/lib -lbn -lpthread"
+   AC_CHECK_LIB(zrtp, zrtp_init, [has_zrtp="yes"], [has_zrtp="no"])
+   LIBS=$saved_LIBS
+   if test "x$has_zrtp" = "xno"; then
+      AC_ERROR([Cannot locate zrtp libraries])
+   fi
+   APR_ADDTO(SWITCH_AM_CFLAGS, -DENABLE_ZRTP)
+fi
+AM_CONDITIONAL([ENABLE_ZRTP],[test "x$enable_zrtp" != "xno"])
+
+
 AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"])
 
 AC_ARG_ENABLE(core-odbc-support,     
diff --git a/patches/zrtp_bnlib_pic.diff b/patches/zrtp_bnlib_pic.diff
new file mode 100644 (file)
index 0000000..d9b98f4
--- /dev/null
@@ -0,0 +1,5 @@
+--- libzrtp-0.81.514.orig/third_party/bnlib/cfg.debug  2009-03-22 08:26:34.000000000 -0500
++++ libzrtp-0.81.514.patched/third_party/bnlib/cfg.debug       2009-05-20 11:42:52.000000000 -0500
+@@ -1 +1 @@
+-./configure CFLAGS="-O0 -g3"
++./configure CFLAGS="-O0 -g3 -fPIC"
index ae9b2a49b315276d808e5e78a62ecd63f8714b3a..f4d92e83df1e8c697da0fd87c91526cc512a4353 100644 (file)
@@ -496,7 +496,9 @@ typedef enum {
        SWITCH_RTP_FLAG_SHUTDOWN = (1 << 19),
        SWITCH_RTP_FLAG_FLUSH = (1 << 20),
        SWITCH_RTP_FLAG_AUTOFLUSH = (1 << 21),
-       SWITCH_RTP_FLAG_STICKY_FLUSH = (1 << 22)
+       SWITCH_RTP_FLAG_STICKY_FLUSH = (1 << 22),
+       SWITCH_ZRTP_FLAG_SECURE_SEND = (1 << 23),
+       SWITCH_ZRTP_FLAG_SECURE_RECV = (1 << 24)
 } switch_rtp_flag_enum_t;
 typedef uint32_t switch_rtp_flag_t;
 
index 54805839b274d268ffca09d8368820dd7ccdf387..79daffe07e5aa3f082000befb38eea1ecc4a78e5 100644 (file)
@@ -36,6 +36,7 @@
 
 
 #include <switch.h>
+#include <switch_stun.h>
 #include <switch_version.h>
 #include "private/switch_core_pvt.h"
 #ifndef WIN32
@@ -1026,6 +1027,48 @@ SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration)
        return runtime.default_dtmf_duration;
 }
 
+static void switch_core_set_serial(void)
+{
+       char buf[13] = "";
+       char path[256];
+       
+       int fd = -1, write_fd = -1;
+       ssize_t bytes = 0;
+
+       switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR);
+
+
+       if ((fd = open(path, O_RDONLY, 0)) < 0) {
+               char *ip = switch_core_get_variable("local_ip_v4");
+               uint32_t ipi = 0;
+               switch_byte_t *byte;
+               int i = 0;
+
+               switch_inet_pton(AF_INET, ip, &ipi);
+               byte = (switch_byte_t *) &ipi;
+
+               for(i = 0; i < 8; i += 2) {
+                       switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte);
+                       byte++;
+               }
+
+               switch_stun_random_string(buf + 8, 4, "0123456789abcdef");
+
+               if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) {
+                       bytes = write(write_fd, buf, sizeof(buf));
+                       close(write_fd);
+                       write_fd = -1;
+               }
+       } else {
+               bytes = read(fd, buf, sizeof(buf));
+               close(fd);
+               fd = -1;
+       }
+       
+       switch_core_set_variable("switch_serial", buf);
+}
+
+
 SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)
 {
        switch_uuid_t uuid;
@@ -1084,12 +1127,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
        runtime.flags = flags;
        runtime.sps_total = 30;
 
+       
+
        switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET);
        switch_core_set_variable("local_ip_v4", guess_ip);
        switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET6);
        switch_core_set_variable("local_ip_v6", guess_ip);
        switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
-
+       switch_core_set_serial();
 
        switch_event_init(runtime.memory_pool);
 
@@ -1253,6 +1298,10 @@ static void switch_load_core_config(const char *file)
                                        switch_rtp_set_start_port((switch_port_t) atoi(val));
                                } else if (!strcasecmp(var, "rtp-end-port") && !switch_strlen_zero(val)) {
                                        switch_rtp_set_end_port((switch_port_t) atoi(val));
+#ifdef ENABLE_ZRTP
+                               } else if (!strcasecmp(var, "rtp-enable-zrtp")) {
+                                       switch_core_set_variable("zrtp_enabled", val);
+#endif
                                }
                        }
                }
index 41939c7d8b93dd9071ee66a47d3c3538bd9fd02a..500b52618dbad01591fdab40bd05df77e642ffdc 100644 (file)
@@ -59,6 +59,8 @@
 #define RTP_MAGIC_NUMBER 42
 #define MAX_SRTP_ERRS 10
 
+
+
 static switch_port_t START_PORT = RTP_START_PORT;
 static switch_port_t END_PORT = RTP_END_PORT;
 static switch_port_t NEXT_PORT = RTP_START_PORT;
@@ -66,6 +68,14 @@ static switch_mutex_t *port_lock = NULL;
 
 typedef srtp_hdr_t rtp_hdr_t;
 
+#ifdef ENABLE_ZRTP
+#include <libzrtp/zrtp.h>
+static zrtp_global_t *zrtp_global;
+static zrtp_zid_t zid = { "FreeSWITCH01" };
+static int zrtp_on = 0;
+
+#endif
+
 #ifdef _MSC_VER
 #pragma pack(4)
 #endif
@@ -205,6 +215,12 @@ struct switch_rtp {
        switch_rtp_bug_flag_t rtp_bugs;
        switch_rtp_stats_t stats;
 
+#ifdef ENABLE_ZRTP
+       zrtp_session_t *zrtp_session;
+       zrtp_profile_t *zrtp_profile;
+       zrtp_stream_t *zrtp_ctx;
+#endif
+
 #ifdef RTP_DEBUG_WRITE_DELTA
        switch_time_t send_time;
 #endif
@@ -397,13 +413,114 @@ static void handle_ice(switch_rtp_t *rtp_session, void *data, switch_size_t len)
        WRITE_DEC(rtp_session);
 }
 
+#ifdef ENABLE_ZRTP
+static void zrtp_security_event_callback(zrtp_stream_t *stream, unsigned event)
+{
+       switch_rtp_t *rtp_session = zrtp_stream_get_userdata(stream);
+       zrtp_session_info_t zrtp_session_info;
+
+       switch (event) {
+       case ZRTP_EVENT_IS_SECURE:
+               zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info);
+               zrtp_log_print_sessioninfo(&zrtp_session_info);
+
+               break;
+       default:
+               break;
+       }
+}
+
+static int zrtp_send_rtp_callback(const zrtp_stream_t* stream, char* rtp_packet, unsigned int rtp_packet_length)
+{
+       switch_rtp_t *rtp_session = zrtp_stream_get_userdata(stream);
+       switch_size_t len = rtp_packet_length;
+       zrtp_status_t status = zrtp_status_ok;
+
+       switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, rtp_packet, &len);
+       return status;
+}
+
+static void zrtp_protocol_event_callback(zrtp_stream_t *stream, unsigned event)
+{
+       switch_rtp_t *rtp_session = zrtp_stream_get_userdata(stream);
+
+       switch (event) {
+       case ZRTP_EVENT_IS_SECURE_DONE:
+               break;
+       case ZRTP_EVENT_IS_SECURE:
+               switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND);
+               switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_RECV);
+               break;
+       case ZRTP_EVENT_IS_CLIENT_ENROLLMENT:
+       case ZRTP_EVENT_IS_CLEAR:
+       case ZRTP_EVENT_IS_INITIATINGSECURE:
+       case ZRTP_EVENT_IS_PENDINGSECURE:
+       case ZRTP_EVENT_IS_PENDINGCLEAR:
+       case ZRTP_EVENT_NO_ZRTP:
+       case ZRTP_EVENT_LOCAL_SAS_UPDATED:
+               break;
+       default:
+               break;
+       }
+}
+
+static void zrtp_logger(int level, const char *data, int len)
+{
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s", data);
+}
+
+static void zrtp_handler(switch_rtp_t *rtp_session, switch_socket_t *sock, void *data, switch_size_t datalen, switch_sockaddr_t *from_addr)
+{
+       zrtp_status_t status = zrtp_status_fail;
+       unsigned int len = datalen;
+
+       status = zrtp_process_srtp(rtp_session->zrtp_ctx, (char*)data, &len);
+       switch(status) {
+       case zrtp_status_ok:
+               break;
+       case zrtp_status_drop:
+               break;
+       case zrtp_status_fail:
+               break;
+       default:
+               break;
+       }
+}
+#endif
 
 SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool)
 {
+#ifdef ENABLE_ZRTP
+       const char *zid_string = switch_core_get_variable("switch_serial");
+       const char *zrtp_enabled = switch_core_get_variable("zrtp_enabled");
+       zrtp_on = zrtp_enabled ? switch_true(zrtp_enabled) : 0;
+       zrtp_config_t zrtp_config;
+       char zrtp_cache_path[256] = "";
+#endif
        if (global_init) {
                return;
        }
        switch_core_hash_init(&alloc_hash, pool);
+#ifdef ENABLE_ZRTP
+       if (zrtp_on) {
+               zrtp_config_defaults(&zrtp_config);
+               strcpy(zrtp_config.client_id, "FreeSWITCH");
+               zrtp_config.lic_mode = ZRTP_LICENSE_MODE_ACTIVE;
+               switch_snprintf(zrtp_cache_path, sizeof(zrtp_cache_path), "%s%szrtp.dat", SWITCH_GLOBAL_dirs.db_dir, SWITCH_PATH_SEPARATOR);
+               zrtp_zstrcpyc( ZSTR_GV(zrtp_config.def_cache_path), zrtp_cache_path);
+               zrtp_config.cb.event_cb.on_zrtp_protocol_event = zrtp_protocol_event_callback;
+               zrtp_config.cb.misc_cb.on_send_packet = zrtp_send_rtp_callback;
+               zrtp_config.cb.event_cb.on_zrtp_security_event = zrtp_security_event_callback;
+               
+               zrtp_log_set_log_engine(zrtp_logger);
+               zrtp_log_set_level(4);
+               if (zrtp_status_ok != zrtp_init(&zrtp_config, &zrtp_global)) {
+                       abort();
+               }
+               
+               memcpy(zid, zid_string, 12);
+       }
+#endif
        srtp_init();
        switch_mutex_init(&port_lock, SWITCH_MUTEX_NESTED, pool);
        global_init = 1;
@@ -435,6 +552,9 @@ SWITCH_DECLARE(void) switch_rtp_shutdown(void)
        switch_core_hash_destroy(&alloc_hash);
        switch_mutex_unlock(port_lock);
 
+#ifdef ENABLE_ZRTP
+       zrtp_down(zrtp_global);
+#endif
        crypto_kernel_shutdown();
 
 }
@@ -918,6 +1038,29 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
 
        rtp_session->ready = 1;
        *new_rtp_session = rtp_session;
+#ifdef ENABLE_ZRTP
+       if (zrtp_on) {
+               rtp_session->zrtp_profile = switch_core_alloc(rtp_session->pool, sizeof(*rtp_session->zrtp_profile));
+               zrtp_profile_defaults(rtp_session->zrtp_profile, zrtp_global);
+       
+               if (zrtp_status_ok != zrtp_session_init(zrtp_global, rtp_session->zrtp_profile, zid, 1, &rtp_session->zrtp_session)) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! zRTP INIT Failed\n");
+                       zrtp_session_down(rtp_session->zrtp_session);
+                       rtp_session->zrtp_session = NULL;
+               }
+
+               zrtp_session_set_userdata(rtp_session->zrtp_session, rtp_session);
+       
+               if (zrtp_status_ok != zrtp_stream_attach(rtp_session->zrtp_session, &rtp_session->zrtp_ctx)) {
+                       abort();
+               }
+               zrtp_stream_set_userdata(rtp_session->zrtp_ctx, rtp_session);
+
+               zrtp_stream_start(rtp_session->zrtp_ctx, rtp_session->ssrc);
+
+               switch_rtp_set_invald_handler(rtp_session, zrtp_handler);
+       }
+#endif 
 
        return SWITCH_STATUS_SUCCESS;
 }
@@ -1169,7 +1312,23 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
                (*rtp_session)->recv_ctx = NULL;
                switch_clear_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE_RECV);
        }
+#ifdef ENABLE_ZRTP
+       /* ZRTP */
+       if (zrtp_on) {
+               if (switch_test_flag((*rtp_session), SWITCH_ZRTP_FLAG_SECURE_SEND)) {
+                       switch_clear_flag((*rtp_session), SWITCH_ZRTP_FLAG_SECURE_SEND);
+               }
 
+               if (switch_test_flag((*rtp_session), SWITCH_ZRTP_FLAG_SECURE_RECV)) {
+                       switch_clear_flag((*rtp_session), SWITCH_ZRTP_FLAG_SECURE_RECV);
+               }
+
+               if ((*rtp_session)->zrtp_session) {
+                       zrtp_session_down((*rtp_session)->zrtp_session);
+                       (*rtp_session)->zrtp_session = NULL;
+               }
+       }
+#endif
        if ((*rtp_session)->timer.timer_interface) {
                switch_core_timer_destroy(&(*rtp_session)->timer);
        }
@@ -1316,11 +1475,11 @@ static void do_2833(switch_rtp_t *rtp_session)
                                }
                        }
                        
-                       wrote =switch_rtp_write_manual(rtp_session,
-                                                                                  rtp_session->dtmf_data.out_digit_packet,
-                                                                                  4,
-                                                                                  rtp_session->rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833 ? 0 : 1,
-                                                                                  rtp_session->te, rtp_session->dtmf_data.timestamp_dtmf, &flags);
+                       wrote = switch_rtp_write_manual(rtp_session,
+                                                                                       rtp_session->dtmf_data.out_digit_packet,
+                                                                                       4,
+                                                                                       rtp_session->rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833 ? 0 : 1,
+                                                                                       rtp_session->te, rtp_session->dtmf_data.timestamp_dtmf, &flags);
                        
                        rtp_session->stats.outbound.raw_bytes += wrote;
                        rtp_session->stats.outbound.dtmf_packet_count++;
@@ -1592,7 +1751,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 
                if (!bytes && (io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
                        return_cng_frame();
-               }
+       }
 
                
                if (check && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
@@ -1670,6 +1829,30 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        bytes = sbytes;
                }
 
+#ifdef ENABLE_ZRTP
+               /* ZRTP Recv */
+
+               if (bytes && switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_RECV)) {
+                       unsigned int sbytes = (int) bytes;
+                       zrtp_status_t stat = 0;
+
+                       stat = zrtp_process_srtp(rtp_session->zrtp_ctx, (void *)&rtp_session->recv_msg, &sbytes);
+
+                       switch (stat) {
+                       case zrtp_status_ok:
+                               break;
+                       case zrtp_status_drop:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
+                       case zrtp_status_fail:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
+                               ret = -1;
+                               goto end;
+                       default:
+                               break;
+                       }
+                       bytes = sbytes;
+               }
+#endif
 
 #ifdef DEBUG_2833
                if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
@@ -2235,7 +2418,29 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 
                        bytes = sbytes;
                }
+#ifdef ENABLE_ZRTP
+               /* ZRTP Send */
 
+               if (switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND)) {
+                       unsigned int sbytes = (int) bytes;
+                       zrtp_status_t stat = zrtp_status_fail;
+
+                       stat = zrtp_process_rtp(rtp_session->zrtp_ctx, (void*)send_msg, &sbytes);
+
+                       switch (stat) {
+                       case zrtp_status_ok:
+                               break;
+                       case zrtp_status_drop:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
+                       case zrtp_status_fail:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
+                       default:
+                               break;
+                       }
+                       
+                       bytes = sbytes;
+               }
+#endif
 
 #ifdef RTP_DEBUG_WRITE_DELTA
                {
@@ -2477,7 +2682,29 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session,
                }
                bytes = sbytes;
        }
+#ifdef ENABLE_ZRTP
+               /* ZRTP Send */
 
+               if (switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND)) {
+                       unsigned int sbytes = (int) bytes;
+                       zrtp_status_t stat = zrtp_status_fail;
+
+                       stat = zrtp_process_rtp(rtp_session->zrtp_ctx, (void*)&rtp_session->write_msg, &sbytes);
+
+                       switch (stat) {
+                       case zrtp_status_ok:
+                               break;
+                       case zrtp_status_drop:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
+                       case zrtp_status_fail:
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
+                       default:
+                               break;
+                       }
+                       
+                       bytes = sbytes;
+               }
+#endif
        if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
                rtp_session->seq--;
                ret = -1;