Commit b986af37 authored by johan's avatar johan

Add dtls srtp

parent 7e32b85f
......@@ -585,6 +585,16 @@ AC_ARG_ENABLE(zrtp,
[zrtp=false]
)
AC_ARG_ENABLE(dtls,
[AS_HELP_STRING([--enable-dtls], [Turn on dtls support - requires polarssl > 1.4])],
[case "${enableval}" in
yes) dtls=true ;;
no) dtls=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-dtls) ;;
esac],
[dtls=false]
)
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
......@@ -595,6 +605,7 @@ dnl compilation of gtk user interface
AM_CONDITIONAL(BUILD_GTK_UI, [test x$gtk_ui = xtrue ] )
AM_CONDITIONAL(BUILD_WIN32, test x$mingw_found = xyes )
AM_CONDITIONAL(BUILD_ZRTP, test x$zrtp = xtrue)
AM_CONDITIONAL(BUILD_DTLS, test x$dtls = xtrue)
dnl check getenv
AH_TEMPLATE([HAVE_GETENV])
......@@ -943,6 +954,7 @@ printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "zRTP encryption" $zrtp
printf "* %-30s %s\n" "DTLS encryption" $dtls
printf "* %-30s %s\n" "uPnP support" $build_upnp
printf "* %-30s %s\n" "LDAP support" $enable_ldap
......
......@@ -1060,6 +1060,42 @@ void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const
if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
}
/**
* Parse a directory to get a certificate with the given subject common name
*
*/
void sal_certificates_chain_parse_directory(unsigned char **certificate_pem, unsigned char **key_pem, unsigned char **fingerprint, const char* path, const char *subject, SalCertificateRawFormat format, bool_t generate_certificate, bool_t generate_dtls_fingerprint) {
belle_sip_certificates_chain_t *certificate = NULL;
belle_sip_signing_key_t *key = NULL;
*certificate_pem = NULL;
*key_pem = NULL;
if (belle_sip_get_certificate_and_pkey_in_dir(path, subject, &certificate, &key, (belle_sip_certificate_raw_format_t)format) == 0) {
*certificate_pem = belle_sip_get_certificates_pem(certificate);
*key_pem = belle_sip_get_key_pem(key);
ms_message("Retrieve certificate with CN=%s successful\n", subject);
} else {
if (generate_certificate == TRUE) {
if ( belle_sip_generate_self_signed_certificate(path, subject, &certificate, &key) == 0) {
*certificate_pem = belle_sip_get_certificates_pem(certificate);
*key_pem = belle_sip_get_key_pem(key);
ms_message("Generate self-signed certificate with CN=%s successful\n", subject);
}
}
}
/* generate the fingerprint as described in RFC4572 if needed */
if ((generate_dtls_fingerprint == TRUE) && (fingerprint != NULL)) {
*fingerprint = belle_sip_generate_certificate_fingerprint(certificate);
}
/* free key and certificate */
if ( certificate != NULL ) {
belle_sip_object_unref(certificate);
}
if ( key != NULL ) {
belle_sip_object_unref(key);
}
}
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
return belle_sip_random_bytes(ret,size);
}
......
......@@ -233,6 +233,26 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}else break;
}
}
/* insert DTLS session attribute if needed */
if ((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp)) {
if ((stream->dtls_role != SalDtlsRoleInvalid) && (strlen(stream->dtls_fingerprint)>0)) {
switch(stream->dtls_role) {
case SalDtlsRoleIsClient:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","active"));
break;
case SalDtlsRoleIsServer:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","passive"));
break;
case SalDtlsRoleUnset:
default:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","actpass"));
break;
}
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("fingerprint",stream->dtls_fingerprint));
}
}
switch ( stream->dir ) {
case SalStreamSendRecv:
/*dir="sendrecv";*/
......@@ -351,6 +371,23 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr
if (desc->ice_pwd[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-pwd",desc->ice_pwd));
if (desc->ice_ufrag[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-ufrag",desc->ice_ufrag));
/* insert DTLS session attribute if needed */
if ((desc->dtls_role != SalDtlsRoleInvalid) && (strlen(desc->dtls_fingerprint)>0)) {
switch(desc->dtls_role) {
case SalDtlsRoleIsClient:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","active"));
break;
case SalDtlsRoleIsServer:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","passive"));
break;
case SalDtlsRoleUnset:
default:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","actpass"));
break;
}
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("fingerprint",desc->dtls_fingerprint));
}
if (desc->rtcp_xr.enabled == TRUE) {
belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr));
}
......@@ -646,6 +683,10 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->proto = SalProtoRtpAvpf;
} else if (strcasecmp(proto, "RTP/SAVPF") == 0) {
stream->proto = SalProtoRtpSavpf;
} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVP") == 0) {
stream->proto = SalProtoUdpTlsRtpSavp;
} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVPF") == 0) {
stream->proto = SalProtoUdpTlsRtpSavpf;
} else {
strncpy(stream->proto_other,proto,sizeof(stream->proto_other)-1);
}
......@@ -701,6 +742,36 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
}
}
/* Read DTLS specific attributes : check is some are found in the stream description otherwise copy the session description one(which are at least set to Invalid) */
stream->dtls_role = SalDtlsRoleInvalid;
stream->dtls_fingerprint[0] = '\0';
if (((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp))) {
attribute=belle_sdp_media_description_get_attribute(media_desc,"setup");
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
if (strncmp(value, "actpass", 7) == 0) {
stream->dtls_role = SalDtlsRoleUnset;
} else if (strncmp(value, "active", 6) == 0) {
stream->dtls_role = SalDtlsRoleIsClient;
} else if (strncmp(value, "passive", 7) == 0) {
stream->dtls_role = SalDtlsRoleIsServer;
}
if (stream->dtls_role != SalDtlsRoleInvalid) {
attribute=belle_sdp_media_description_get_attribute(media_desc,"fingerprint");
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
strncpy(stream->dtls_fingerprint, value, strlen(value)+1);
} else {
/* no valid stream attributes, get them from session */
stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
}
} else { /* no setup attribute found in the stream, get the one from the session */
stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
}
/* Read crypto lines if any */
if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) {
sdp_parse_media_crypto_parameters(media_desc, stream);
......@@ -756,6 +827,33 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
desc->dir=SalStreamInactive;
}
/* Read dtls specific session attributes if any (setup and fingerprint - rfc5763) */
/* Presence of a valid dtls offer(setup and fingerprint attribute) is set in media Description by a dtls_fingerprint string longer than 0
* and a dtls_role != SalDtlsRoleInvalid */
desc->dtls_role = SalDtlsRoleInvalid;
desc->dtls_fingerprint[0] = '\0';
value=belle_sdp_session_description_get_attribute_value(session_desc,"setup");
if (value){
if (strncmp(value, "actpass", 7) == 0) {
desc->dtls_role = SalDtlsRoleUnset;
} else if (strncmp(value, "active", 6) == 0) {
desc->dtls_role = SalDtlsRoleIsClient;
} else if (strncmp(value, "passive", 7) == 0) {
desc->dtls_role = SalDtlsRoleIsServer;
}
}
if (desc->dtls_role != SalDtlsRoleInvalid) {
value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint");
if (value){
strncpy(desc->dtls_fingerprint, value, strlen(value)+1);
} else {
desc->dtls_role = SalDtlsRoleInvalid;
}
}
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1);
......
......@@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) {
if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf;
if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp;
if ((params->media_encryption == LinphoneMediaEncryptionDTLS) && params->avpf_enabled) return SalProtoUdpTlsRtpSavpf;
if (params->media_encryption == LinphoneMediaEncryptionDTLS) return SalProtoUdpTlsRtpSavp;
if (params->avpf_enabled) return SalProtoRtpAvpf;
return SalProtoRtpAvp;
}
......
This diff is collapsed.
......@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/stat.h>
#include <ortp/telephonyevents.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msvolume.h"
......@@ -1487,6 +1488,11 @@ static void misc_config_read(LinphoneCore *lc) {
lp_config_set_string(config,"misc","uuid",tmp);
}else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/
sal_set_uuid(lc->sal, uuid);
/* DTLS: if media_encryption is DTLS, get or create the certificate directory */
if (linphone_core_get_media_encryption(lc) == LinphoneMediaEncryptionDTLS) {
/* TODO*/
}
}
static void linphone_core_start(LinphoneCore * lc) {
......@@ -6253,6 +6259,9 @@ static void linphone_core_uninit(LinphoneCore *lc)
if(lc->zrtp_secrets_cache != NULL) {
ms_free(lc->zrtp_secrets_cache);
}
if(lc->user_certificates_path != NULL) {
ms_free(lc->user_certificates_path);
}
if(lc->play_file!=NULL){
ms_free(lc->play_file);
}
......@@ -6685,6 +6694,17 @@ const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc){
return lc->zrtp_secrets_cache;
}
void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path){
if (lc->user_certificates_path != NULL) {
ms_free(lc->user_certificates_path);
}
lc->user_certificates_path = path ? ms_strdup(path) : NULL;
}
const char *linphone_core_get_user_certificates_path(LinphoneCore *lc){
return lc->user_certificates_path;
}
LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCore *lc, const char *uri) {
MSList *calls;
LinphoneCall *c;
......@@ -6745,6 +6765,8 @@ const char *linphone_media_encryption_to_string(LinphoneMediaEncryption menc){
switch(menc){
case LinphoneMediaEncryptionSRTP:
return "LinphoneMediaEncryptionSRTP";
case LinphoneMediaEncryptionDTLS:
return "LinphoneMediaEncryptionDTLS";
case LinphoneMediaEncryptionZRTP:
return "LinphoneMediaEncryptionZRTP";
case LinphoneMediaEncryptionNone:
......@@ -6761,6 +6783,8 @@ bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, Linphone
switch(menc){
case LinphoneMediaEncryptionSRTP:
return media_stream_srtp_supported();
case LinphoneMediaEncryptionDTLS:
return ms_dtls_available();
case LinphoneMediaEncryptionZRTP:
return ms_zrtp_available();
case LinphoneMediaEncryptionNone:
......@@ -6784,7 +6808,14 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption
type="none";
ret=-1;
}else type="zrtp";
}else if (menc == LinphoneMediaEncryptionDTLS){
if (!ms_dtls_available()){
ms_warning("DTLS not supported by library.");
type="none";
ret=-1;
}else type="dtls";
}
lp_config_set_string(lc->config,"sip","media_encryption",type);
return ret;
}
......@@ -6796,6 +6827,8 @@ LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) {
return LinphoneMediaEncryptionNone;
else if (strcmp(menc, "srtp")==0)
return LinphoneMediaEncryptionSRTP;
else if (strcmp(menc, "dtls")==0)
return LinphoneMediaEncryptionDTLS;
else if (strcmp(menc, "zrtp")==0)
return LinphoneMediaEncryptionZRTP;
else
......
......@@ -287,7 +287,8 @@ typedef enum _LinphoneAVPFMode LinphoneAVPFMode;
enum _LinphoneMediaEncryption {
LinphoneMediaEncryptionNone, /**< No media encryption is used */
LinphoneMediaEncryptionSRTP, /**< Use SRTP media encryption */
LinphoneMediaEncryptionZRTP /**< Use ZRTP media encryption */
LinphoneMediaEncryptionZRTP, /**< Use ZRTP media encryption */
LinphoneMediaEncryptionDTLS /**< Use DTLS media encryption */
};
/**
......@@ -2908,6 +2909,22 @@ LINPHONE_PUBLIC void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const
*/
LINPHONE_PUBLIC const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
/**
* Set the path to the directory storing the user's x509 certificates (used by dtls)
* @param[in] lc #LinphoneCore object
* @param[in] path The path to the directory to use to store the user's certificates.
* @ingroup initializing
*/
LINPHONE_PUBLIC void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path);
/**
* Get the path to the directory storing the user's certificates.
* @param[in] lc #LinphoneCore object.
* @returns The path to the directory storing the user's certificates.
* @ingroup initializing
*/
LINPHONE_PUBLIC const char *linphone_core_get_user_certificates_path(LinphoneCore *lc);
/**
* Search from the list of current calls if a remote address match uri
* @ingroup call_control
......
......@@ -315,6 +315,21 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
result->rtcp_xr.enabled = FALSE;
}
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, get the remote fingerprint into the result
if ((local_offer->dtls_role!=SalDtlsRoleInvalid) && (remote_answer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_offer->dtls_fingerprint)>0) && (strlen(remote_answer->dtls_fingerprint)>0)) {
strcpy(result->dtls_fingerprint, remote_answer->dtls_fingerprint);
if (remote_answer->dtls_role==SalDtlsRoleIsClient) {
result->dtls_role = SalDtlsRoleIsServer;
} else {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
return 0;
}
......@@ -334,7 +349,9 @@ static bool_t local_stream_not_already_used(const SalMediaDescription *result, c
static bool_t proto_compatible(SalMediaProto local, SalMediaProto remote) {
if (local == remote) return TRUE;
if ((remote == SalProtoRtpAvp) && ((local == SalProtoRtpSavp) || (local == SalProtoRtpSavpf))) return TRUE;
if ((remote == SalProtoRtpAvp) && ((local == SalProtoUdpTlsRtpSavp) || (local == SalProtoUdpTlsRtpSavpf))) return TRUE;
if ((remote == SalProtoRtpAvpf) && (local == SalProtoRtpSavpf)) return TRUE;
if ((remote == SalProtoRtpAvpf) && (local == SalProtoUdpTlsRtpSavpf)) return TRUE;
return FALSE;
}
......@@ -368,6 +385,23 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
if (ls){
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
// Handle dtls stream attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
// Note: local description usually stores dtls config at session level which means it apply to all streams, check this too
if (((ls->dtls_role!=SalDtlsRoleInvalid) || (local_capabilities->dtls_role!=SalDtlsRoleInvalid)) && (rs->dtls_role!=SalDtlsRoleInvalid)
&& ((strlen(ls->dtls_fingerprint)>0) || (strlen(local_capabilities->dtls_fingerprint)>0)) && (strlen(rs->dtls_fingerprint)>0)) {
if (strlen(ls->dtls_fingerprint)>0) { /* get the fingerprint in stream description */
strcpy(result->streams[i].dtls_fingerprint, ls->dtls_fingerprint);
} else { /* get the fingerprint in session description */
strcpy(result->streams[i].dtls_fingerprint, local_capabilities->dtls_fingerprint);
}
if (rs->dtls_role==SalDtlsRoleUnset) {
result->streams[i].dtls_role = SalDtlsRoleIsClient;
}
} else {
result->streams[i].dtls_fingerprint[0] = '\0';
result->streams[i].dtls_role = SalDtlsRoleInvalid;
}
// Handle media RTCP XR attribute
memset(&result->streams[i].rtcp_xr, 0, sizeof(result->streams[i].rtcp_xr));
if (rs->rtcp_xr.enabled == TRUE) {
......@@ -408,6 +442,18 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
strcpy(result->name,local_capabilities->name);
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
if ((local_capabilities->dtls_role!=SalDtlsRoleInvalid) && (remote_offer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_capabilities->dtls_fingerprint)>0) && (strlen(remote_offer->dtls_fingerprint)>0)) {
strcpy(result->dtls_fingerprint, local_capabilities->dtls_fingerprint);
if (remote_offer->dtls_role==SalDtlsRoleUnset) {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
// Handle session RTCP XR attribute
memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr));
if (remote_offer->rtcp_xr.enabled == TRUE) {
......
......@@ -241,6 +241,7 @@ struct _LinphoneCall{
char *dtmf_sequence; /*DTMF sequence needed to be sent using #dtmfs_timer*/
belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/
unsigned char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */
bool_t refer_pending;
bool_t expect_media_in_ack;
bool_t audio_muted;
......@@ -734,6 +735,7 @@ struct _LinphoneCore
MSList *hooks;
LinphoneConference conf_ctx;
char* zrtp_secrets_cache;
char* user_certificates_path;
LinphoneVideoPolicy video_policy;
bool_t use_files;
bool_t apply_nat_settings;
......
......@@ -194,13 +194,17 @@ bool_t sal_stream_description_active(const SalStreamDescription *sd) {
}
bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd) {
return ((sd->proto == SalProtoRtpAvpf) || (sd->proto == SalProtoRtpSavpf));
return ((sd->proto == SalProtoRtpAvpf) || (sd->proto == SalProtoRtpSavpf) || (sd->proto == SalProtoUdpTlsRtpSavpf));
}
bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd) {
return ((sd->proto == SalProtoRtpSavp) || (sd->proto == SalProtoRtpSavpf));
}
bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd) {
return ((sd->proto == SalProtoUdpTlsRtpSavp) || (sd->proto == SalProtoUdpTlsRtpSavpf));
}
bool_t sal_media_description_has_avpf(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
......@@ -221,6 +225,16 @@ bool_t sal_media_description_has_srtp(const SalMediaDescription *md) {
return TRUE;
}
bool_t sal_media_description_has_dtls(const SalMediaDescription *md) {
int i;
if (md->nb_streams == 0) return FALSE;
for (i = 0; i < md->nb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_dtls(&md->streams[i]) != TRUE) return FALSE;
}
return TRUE;
}
/*
static bool_t fmtp_equals(const char *p1, const char *p2){
if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
......@@ -607,8 +621,10 @@ const char* sal_media_proto_to_string(SalMediaProto type) {
switch (type) {
case SalProtoRtpAvp:return "RTP/AVP";
case SalProtoRtpSavp:return "RTP/SAVP";
case SalProtoUdpTlsRtpSavp:return "UDP/TLS/RTP/SAVP";
case SalProtoRtpAvpf:return "RTP/AVPF";
case SalProtoRtpSavpf:return "RTP/SAVPF";
case SalProtoUdpTlsRtpSavpf:return "UDP/TLS/RTP/SAVPF";
default: return "unknown";
}
}
......
......@@ -680,6 +680,12 @@ void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){
gtk_widget_hide(status_icon);
gtk_widget_hide(verify_button);
break;
case LinphoneMediaEncryptionDTLS:
gtk_widget_show_all(encryption_box);
gtk_label_set_markup(GTK_LABEL(label),_("Secured by DTLS"));
gtk_widget_hide(status_icon);
gtk_widget_hide(verify_button);
break;
case LinphoneMediaEncryptionZRTP:
{
gchar *text=g_strdup_printf(_("Secured by ZRTP - [auth token: %s]"),linphone_call_get_authentication_token(call));
......
......@@ -172,9 +172,11 @@ static GOptionEntry linphone_options[]={
#ifndef WIN32
#define CONFIG_FILE ".linphonerc"
#define SECRETS_FILE ".linphone-zidcache"
#define CERTIFICATES_PATH ".linphone-usr-crt"
#else
#define CONFIG_FILE "linphonerc"
#define SECRETS_FILE "linphone-zidcache"
#define CERTIFICATES_PATH "linphone-usr-crt"
#endif
char *linphone_gtk_get_config_file(const char *filename){
......@@ -279,6 +281,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
const char *factory_config_file, const char *db_file) {
LinphoneCoreVTable vtable={0};
gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE);
gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH);
vtable.global_state_changed=linphone_gtk_global_state_changed;
vtable.call_state_changed=linphone_gtk_call_state_changed;
......@@ -316,6 +319,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
linphone_core_set_zrtp_secrets_file(the_core,secrets_file);
g_free(secrets_file);
linphone_core_set_user_certificates_path(the_core,user_certificates_dir);
g_free(user_certificates_dir);
linphone_core_enable_video_capture(the_core, TRUE);
linphone_core_enable_video_display(the_core, TRUE);
linphone_core_set_native_video_window_id(the_core,-1);/*don't create the window*/
......
......@@ -1199,11 +1199,13 @@ static void linphone_gtk_media_encryption_changed(GtkWidget *combo){
if (strcasecmp(selected,"SRTP")==0){
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionSRTP);
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,TRUE);
}else if (strcasecmp(selected,"DTLS")==0){
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionDTLS);
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
}else if (strcasecmp(selected,"ZRTP")==0){
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionZRTP);
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
}
else {
} else {
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionNone);
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
}
......@@ -1219,7 +1221,7 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
LinphoneCore *lc=linphone_gtk_get_core();
GtkWidget *combo=linphone_gtk_get_widget(pb,"media_encryption_combo");
bool_t no_enc=TRUE;
int srtp_id=-1,zrtp_id=-1;
int srtp_id=-1,zrtp_id=-1,dtls_id=-1;
GtkTreeModel *model;
GtkListStore *store;
GtkTreeIter iter;
......@@ -1239,12 +1241,26 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
srtp_id=1;
no_enc=FALSE;
}
if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionDTLS)){
gtk_list_store_append(store,&iter);
gtk_list_store_set(store,&iter,0,_("DTLS"),-1);
if (srtp_id!=-1) dtls_id=2;
else dtls_id=1;
no_enc=FALSE;
}
if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionZRTP)){
gtk_list_store_append(store,&iter);
gtk_list_store_set(store,&iter,0,_("ZRTP"),-1);
no_enc=FALSE;
if (srtp_id!=-1) zrtp_id=2;
else zrtp_id=1;
if (srtp_id!=-1) {
if (dtls_id!=-1)
zrtp_id=3;
else zrtp_id=2;
} else {
if (dtls_id!=-1)
zrtp_id=2;
else zrtp_id=1;
}
}
if (no_enc){
/*hide this setting*/
......@@ -1264,6 +1280,12 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE);
}
break;
case LinphoneMediaEncryptionDTLS:
if (dtls_id!=-1) {
gtk_combo_box_set_active(GTK_COMBO_BOX(combo),dtls_id);
linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE);
}
break;
case LinphoneMediaEncryptionZRTP:
if (zrtp_id!=-1) {
gtk_combo_box_set_active(GTK_COMBO_BOX(combo),zrtp_id);
......
......@@ -129,6 +129,8 @@ typedef enum{
SalProtoRtpSavp,
SalProtoRtpAvpf,
SalProtoRtpSavpf,
SalProtoUdpTlsRtpSavp,
SalProtoUdpTlsRtpSavpf,
SalProtoOther
}SalMediaProto;
const char* sal_media_proto_to_string(SalMediaProto type);
......@@ -182,6 +184,13 @@ typedef struct SalSrtpCryptoAlgo {
#define SAL_CRYPTO_ALGO_MAX 4
typedef enum {
SalDtlsRoleInvalid,
SalDtlsRoleIsServer,
SalDtlsRoleIsClient,
SalDtlsRoleUnset
} SalDtlsRole;
typedef struct SalStreamDescription{
char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/
SalMediaProto proto;
......@@ -207,6 +216,8 @@ typedef struct SalStreamDescription{
bool_t ice_mismatch;
bool_t ice_completed;
bool_t pad[2];
char dtls_fingerprint[256];
SalDtlsRole dtls_role;
} SalStreamDescription;
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc);
......@@ -231,6 +242,8 @@ typedef struct SalMediaDescription{
bool_t ice_lite;
bool_t ice_completed;
bool_t pad[2];
char dtls_fingerprint[256];
SalDtlsRole dtls_role;
} SalMediaDescription;
typedef struct SalMessage{
......@@ -265,8 +278,10 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_
bool_t sal_stream_description_active(const SalStreamDescription *sd);
bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd);
bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd);
bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd);
bool_t sal_media_description_has_avpf(const SalMediaDescription *md);
bool_t sal_media_description_has_srtp(const SalMediaDescription *md);
bool_t sal_media_description_has_dtls(const SalMediaDescription *md);
int sal_media_description_get_nb_active_streams(const SalMediaDescription *md);
......@@ -510,6 +525,18 @@ void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path,
*/
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd);
/**
* Parse a directory for files containing certificate with the given subject CNAME
* @param[out] certificate_pem the address of a string to store the certificate in PEM format. To be freed by caller
* @param[out] key_pem the address of a string to store the key in PEM format. To be freed by caller
* @param[in] path directory to parse
* @param[in] subject subject CNAME
* @param[in] format either PEM or DER
* @param[in] generate_certificate if true, if matching certificate and key can't be found, generate it and store it into the given dir, filename will be subject.pem
* @param[in] generate_dtls_fingerprint if true and we have a certificate, generate the dtls fingerprint as described in rfc4572
*/
void sal_certificates_chain_parse_directory(unsigned char **certificate_pem, unsigned char **key_pem, unsigned char **fingerprint, const char* path, const char *subject, SalCertificateRawFormat format, bool_t generate_certificate, bool_t generate_dtls_fingerprint);
void sal_certificates_chain_delete(SalCertificatesChain *chain);
void sal_signing_key_delete(SalSigningKey *key);
......
mediastreamer2 @ dd1d9394
Subproject commit 90bad6f9e48f7d18cba2d1a50c4e55fbc6b3c686
Subproject commit dd1d93944369d5e19808109ea94b51f28b0e5a92
oRTP @ 29802b08
Subproject commit 5333d998c8eaf3c43e66c4a5335c0606c8dea3df
Subproject commit 29802b08dac2de2f320db28249d5d459a47507e8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment