From c74f85f7ab6c7b3712d1a2c279f950530fb4def7 Mon Sep 17 00:00:00 2001 From: Viktor Krikun Date: Sat, 19 Nov 2011 13:40:00 +0000 Subject: [PATCH] Recheck and implement missing features in Acive-Passive logs (closes #23) --- include/zrtp.h | 42 ++++++++++----- include/zrtp_engine.h | 8 +-- include/zrtp_log.h | 8 +++ include/zrtp_pbx.h | 13 +++++ include/zrtp_protocol.h | 9 ++-- include/zrtp_types.h | 33 ++++++++---- .../xcode/libzrtp.xcodeproj/project.pbxproj | 2 +- src/zrtp.c | 23 +++++--- src/zrtp_engine.c | 42 ++++++++++++++- src/zrtp_log.c | 15 ++++++ src/zrtp_pbx.c | 52 +++++++++++++++++++ src/zrtp_protocol.c | 29 ++++++++++- 12 files changed, 233 insertions(+), 43 deletions(-) diff --git a/include/zrtp.h b/include/zrtp.h index 2927b2a4aa..37595ab735 100644 --- a/include/zrtp.h +++ b/include/zrtp.h @@ -115,6 +115,24 @@ typedef enum zrtp_license_mode_t ZRTP_LICENSE_MODE_UNLIMITED } zrtp_license_mode_t; +/** + * @brief Enumeration to define Signaling initiator/responder roles. + * + * Used by libzrtp to optimize some internal processes and protocol handshake. + * + * @sas zrtp_stream_start(). + */ +typedef enum zrtp_signaling_role_t +{ + /** @brief Unknown Signaling role, should be used when the app can't determine the role. */ + ZRTP_SIGNALING_ROLE_UNKNOWN = 0, + /** @brief Signaling Initiator. */ + ZRTP_SIGNALING_ROLE_INITIATOR, + /** @brief Signaling Responder. */ + ZRTP_SIGNALING_ROLE_RESPONDER, + ZRTP_SIGNALING_ROLE_COUNT +} zrtp_signaling_role_t; + /** @brief 12-byte ZID for unique ZRTP endpoint identification. */ typedef unsigned char zrtp_zid_t[12]; @@ -123,9 +141,9 @@ typedef unsigned char zrtp_zid_t[12]; typedef char zrtp_client_id_t[16]; /** - * \brief ZRTP global configuration options - * \ingroup zrtp_main_init - * \warning Use \ref zrtp_config_defaults() before start configuring this structure. + * @brief ZRTP global configuration options + * @ingroup zrtp_main_init + * @warning Use \ref zrtp_config_defaults() before start configuring this structure. */ typedef struct zrtp_config_t { @@ -431,10 +449,9 @@ zrtp_status_t zrtp_down(zrtp_global_t* zrtp); * \param profile - the session configuration profile. If value of this parameter is NULL, default * profile will be used. NULL profile usage is equivalent to calling zrtp_profile_defaults(). * \param zid - ZRTP peer identificator. - * \param is_initiator - identifies if the endpoint was the signaling initiator of the call. Used to + * \param role - identifies if the endpoint was the signaling initiator of the call. Used to * provide Passive Mode options to the developer. If your application doesn't control signaling - * or you don't want to support Passive Mode features - set this flag to 1. Check \ref XXX for - * more information. + * or you don't want to support Passive Mode features - set it to ZRTP_SIGNALING_ROLE_UNKNOWN. * \param session - allocated session structure. * \return * - zrtp_status_ok if initialization is successful; @@ -444,7 +461,7 @@ zrtp_status_t zrtp_down(zrtp_global_t* zrtp); zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp, zrtp_profile_t* profile, zrtp_zid_t zid, - uint8_t is_initiator, + zrtp_signaling_role_t role, zrtp_session_t **session); /** * \brief ZRTP Session context deinitialization @@ -461,8 +478,8 @@ void zrtp_session_down(zrtp_session_t *session); /** * \brief Obtain information about ZRTP session * - * Function initialize and fills all fields of zrtp_session_info_t structure accordint to - * current state of ZRTP session. + * Function initialize and fills all fields of zrtp_session_info_t structure according to + * the current state of ZRTP session. * * \param session - zrtp session which parameters should be extracted; * \param info - out structure to be initialized. @@ -530,7 +547,8 @@ zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream * - \ref XXX_GUIDE_CB \ref XXX_GUIDE_MANAGEMENT * - zrtp_stream_stop() zrtp_stream_secure() zrtp_stream_clear() */ -zrtp_status_t zrtp_stream_start(zrtp_stream_t* stream, uint32_t ssrc); +zrtp_status_t zrtp_stream_start(zrtp_stream_t* stream, + uint32_t ssrc); /** * \brief ZRTP protocol stopping @@ -751,7 +769,7 @@ zrtp_status_t zrtp_process_srtcp( zrtp_stream_t *stream, /* \} */ /** - * \defgroup zrtp_main_utils Utilites + * \defgroup zrtp_main_utils Utilities * \ingroup zrtp_api * \{ */ @@ -768,7 +786,7 @@ zrtp_status_t zrtp_process_srtcp( zrtp_stream_t *stream, * starting the protocol from the ZRTP_STATE_ACTIVE state. * * \param stream - stream for operating with; - * \param hash_buff - signaling hash buffer. Function accpt string, not a binary value!; + * \param hash_buff - signaling hash buffer. Function accepts string, not a binary value!; * \param hash_buff_length - signaling hash length in bytes (must be 64 bytes); * \return: * - zrtp_status_ok if the operation finished successfully diff --git a/include/zrtp_engine.h b/include/zrtp_engine.h index 8b818dee2d..a2c7e05de5 100644 --- a/include/zrtp_engine.h +++ b/include/zrtp_engine.h @@ -58,7 +58,7 @@ extern "C" */ #define ZRTP_PASSIVE2_TEST(stream) \ ( !((ZRTP_LICENSE_MODE_PASSIVE == stream->zrtp->lic_mode) && \ - stream->session->is_initiator) ) + (stream->session->signaling_role == ZRTP_SIGNALING_ROLE_INITIATOR)) ) /** * @brief Test Passive Rule N3 @@ -128,7 +128,7 @@ zrtp_status_t _zrtp_protocol_decrypt( zrtp_protocol_t *self, /*===========================================================================*/ -/* CRTPTO Utilites */ +/* CRTPTO Utilities */ /*===========================================================================*/ /** @@ -237,7 +237,7 @@ int _zrtp_can_start_stream( zrtp_stream_t* stream, zrtp_stream_t** conc, zrtp_stream_mode_t mode); -/** Return ZRTP Stream mode which sould be used for current stream. */ +/** Return ZRTP Stream mode which should be used for current stream. */ zrtp_stream_mode_t _zrtp_define_stream_mode(zrtp_stream_t* stream); /*! @@ -257,7 +257,7 @@ uint8_t _zrtp_choose_best_comp( zrtp_profile_t* profile, /*! * \brief Computes replay timeouts - * This function computes messages replays schedule. There are some recomended + * This function computes messages replays schedule. There are some recommended * values by ZRTP specification, but in some network environments values may be * sligh different */ diff --git a/include/zrtp_log.h b/include/zrtp_log.h index 75193ac1d5..ca2213eca4 100644 --- a/include/zrtp_log.h +++ b/include/zrtp_log.h @@ -143,6 +143,14 @@ const char* zrtp_log_mode2str(zrtp_stream_mode_t mode); /** Returns symbolical name of the protocol and security events. */ const char* zrtp_log_event2str(uint8_t event); +/** + * Returns character name of the Signaling role. + * + * @param role One of zrtp_signaling_role_t values. + * @return character name of the \c role. + */ +const char* zrtp_log_sign_role2str(unsigned role); + /** Print out ZRTP environment configuration setting to log level 3. */ void zrtp_print_env_settings(); diff --git a/include/zrtp_pbx.h b/include/zrtp_pbx.h index 94ce80cce1..485ec74670 100644 --- a/include/zrtp_pbx.h +++ b/include/zrtp_pbx.h @@ -91,6 +91,19 @@ zrtp_status_t zrtp_register_with_trusted_mitm(zrtp_stream_t* stream); * \ref XXX_DRAFT, XXX_GUIDE */ zrtp_status_t zrtp_resolve_mitm_call(zrtp_stream_t* stream1, zrtp_stream_t* stream2); + +/** + * @brief Links two lags of Trusted ZRTP MiTM call together. + * + * This function allows libzrtp2 to optimize protocol behavior of one leg depending on the state and + * parameters of the other lag. MitM boxes should use this API whenever possible. + * + * @param stream1 - one leg of the trusted MiTM call; + * @param stream2 - another leg of the trusted MiTM call. + * + * @return zrtp_status_ok in case of success. + */ +zrtp_status_t zrtp_link_mitm_calls(zrtp_stream_t* stream1, zrtp_stream_t* stream2); /** * \brief Updates remote-side SAS value and rendering scheme diff --git a/include/zrtp_protocol.h b/include/zrtp_protocol.h index 7e8986ff55..fbc157dfa7 100644 --- a/include/zrtp_protocol.h +++ b/include/zrtp_protocol.h @@ -282,7 +282,8 @@ typedef struct zrtp_packet_Hello /** Signature support flag */ uint8_t sigflag:1; - uint8_t padding1:1; + + uint8_t uflag:1; /** Hash scheme count */ uint8_t hc:4; @@ -300,7 +301,7 @@ typedef struct zrtp_packet_Hello /** PK Type count */ uint8_t kc:4; #elif ZRTP_BYTE_ORDER == ZBO_BIG_ENDIAN - uint8_t padding1:1; + uint8_t uflag:1; uint8_t sigflag:1; uint8_t mitmflag:1; uint8_t pasive:1; @@ -400,7 +401,7 @@ typedef struct zrtp_packet_Confirm /** Unused (Set to zero and ignored) */ uint8_t pad[2]; - /** Length of optionas signature field */ + /** Length of optional signature field */ uint8_t sig_length; /** boolean flags for allowclear, SAS verified and disclose */ @@ -478,7 +479,7 @@ typedef struct zrtp_msg_hdr_t hdr; zrtp_uchar4_t version; /** Zfone discovery protocol version */ zrtp_uchar8_t endpointhash; /** Zfone endpoint unique identifier */ - zrtp_uchar8_t peerendpointhash; /** EndpointHash copied from Ping message */ + zrtp_uchar8_t peerendpointhash; /** EndpointHash copied from Ping message */ uint32_t peerssrc; } zrtp_packet_zfonepingack_t; diff --git a/include/zrtp_types.h b/include/zrtp_types.h index 817caafa1d..fa7b0f1034 100644 --- a/include/zrtp_types.h +++ b/include/zrtp_types.h @@ -51,7 +51,7 @@ typedef enum zrtp_state_t ZRTP_STATE_PENDINGCLEAR, /** CLEAR request have been received */ ZRTP_STATE_INITIATINGERROR, /** Protocol ERROR detected on local side */ ZRTP_STATE_PENDINGERROR, /** Protocol ERROR received from the remote peer */ - ZRTP_STATE_ERROR, /** Protcol ERROR state. Check zrtp_stream_info#last_error*/ + ZRTP_STATE_ERROR, /** Protocol ERROR state. Check zrtp_stream_info#last_error*/ #if (defined(ZRTP_BUILD_FOR_CSD) && (ZRTP_BUILD_FOR_CSD == 1)) ZRTP_STATE_DRIVEN_INITIATOR, ZRTP_STATE_DRIVEN_RESPONDER, @@ -404,7 +404,7 @@ struct zrtp_global_t /** This object is used to synchronize sessions list operations */ zrtp_mutex_t* sessions_protector; - /** Set of feedback callbacks used by libzrtp to interact witrh the user-space.*/ + /** Set of feedback callbacks used by libzrtp to interact with the user-space.*/ zrtp_callback_t cb; }; @@ -471,7 +471,7 @@ typedef struct zrtp_secrets_t uint32_t wrongs; uint32_t wrongs_curr; - /** This flag equals one iff the secrets have been uploaded from the cache. */ + /** This flag equals one if the secrets have been uploaded from the cache. */ uint8_t is_ready; } zrtp_secrets_t; @@ -543,7 +543,7 @@ typedef struct zrtp_dh_crypto_context_t /** DH public value */ struct BigNum pv; - /** DH public value precalculated for remote side */ + /** DH public value recalculated for remote side */ struct BigNum peer_pv; /** DH shared secret. DHSS = hash(DHResult) */ @@ -742,7 +742,7 @@ struct zrtp_stream_t uint8_t allowclear; /*! - * This flag shows when remote side is "pasice" (has license mode PASSIVE) + * This flag shows when remote side is "passive" (has license mode PASSIVE) * Available for reading in CLEAR state. */ uint8_t peer_passive; @@ -780,6 +780,11 @@ struct zrtp_stream_t */ uint8_t peer_mitm_flag; + /** + * Duplicates U flag from peer Hello message + */ + uint8_t peer_super_flag; + /*! * \brief Pointer to the concurrent DH stream * If Commit messages are sent by both ZRTP endpoints at the same time, but @@ -796,7 +801,7 @@ struct zrtp_stream_t /** Back-pointer to the ZRTP global data */ zrtp_global_t *zrtp; - /** Pointer to paren t-session context. Used for back capability */ + /** Pointer to parent session context. Used for back capability */ zrtp_session_t *session; /*!< Public key exchange component used within current stream */ @@ -808,6 +813,12 @@ struct zrtp_stream_t */ void *usr_data; + /*! + * Pointer to the peer stream during a trusted MiTM call. + * @sa zrtp_link_mitm_calls() + */ + zrtp_stream_t *linked_mitm; + /*! * \brief Stream data protector * A mutex is used to avoid race conditions during asynchronous calls @@ -846,11 +857,13 @@ struct zrtp_session_t */ zrtp_string16_t peer_zid; - /*!< ZRTP profile, defined crypto options and behavior for every stream within cirrent session */ + /*!< ZRTP profile, defined crypto options and behavior for every stream within current session */ zrtp_profile_t profile; - /** Define endpoint Signaling role. Different from ZRTP Initiator/Responder role */ - uint8_t is_initiator; + /* + * Signaling Role which protocol was started with, one of zrtp_signaling_role_t values. + */ + unsigned signaling_role; /*! * \brief Set of retained secrets and flags for the current ZRTP session. @@ -859,7 +872,7 @@ struct zrtp_session_t */ zrtp_secrets_t secrets; - /*!< ZRTP session key used to extand ZRTP session without additional DH exchange */ + /*!< ZRTP session key used to extend ZRTP session without additional DH exchange */ zrtp_string64_t zrtpsess; /** First SAS base32/256 string */ diff --git a/projects/xcode/libzrtp.xcodeproj/project.pbxproj b/projects/xcode/libzrtp.xcodeproj/project.pbxproj index 5eec2ac3f5..d6410e978d 100644 --- a/projects/xcode/libzrtp.xcodeproj/project.pbxproj +++ b/projects/xcode/libzrtp.xcodeproj/project.pbxproj @@ -413,7 +413,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0410; + LastUpgradeCheck = 0420; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libzrtp" */; compatibilityVersion = "Xcode 3.2"; diff --git a/src/zrtp.c b/src/zrtp.c index 6c5470cca8..d5a228150d 100644 --- a/src/zrtp.c +++ b/src/zrtp.c @@ -72,7 +72,7 @@ zrtp_status_t zrtp_init(zrtp_config_t* config, zrtp_global_t** zrtp) return zrtp_status_alloc_fail; } zrtp_memset(new_zrtp, 0, sizeof(zrtp_global_t)); - + /* * Apply configuration according to the config */ @@ -188,7 +188,7 @@ zrtp_status_t zrtp_down(zrtp_global_t* zrtp) zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp, zrtp_profile_t* profile, zrtp_zid_t zid, - uint8_t is_initiator, + zrtp_signaling_role_t role, zrtp_session_t **session) { uint32_t i = 0; @@ -243,6 +243,7 @@ zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp, ZRTP_LOG(3, (_ZTU_," allowclear: %s\n", profile->allowclear?"ON":"OFF")); ZRTP_LOG(3, (_ZTU_," autosecure: %s\n", profile->autosecure?"ON":"OFF")); ZRTP_LOG(3, (_ZTU_," disclose_bit: %s\n", profile->disclose_bit?"ON":"OFF")); + ZRTP_LOG(3, (_ZTU_," signal. role: %s\n", zrtp_log_sign_role2str(role))); ZRTP_LOG(3, (_ZTU_," TTL: %u\n", profile->cache_ttl)); ZRTP_LOG(3, (_ZTU_," SAS schemes: ")); @@ -280,7 +281,7 @@ zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp, zrtp_zstrncpyc(ZSTR_GV(new_session->zid), (const char*)zid, sizeof(zrtp_zid_t)); new_session->zrtp = zrtp; - new_session->is_initiator = is_initiator; + new_session->signaling_role = role; new_session->mitm_alert_detected = 0; /* @@ -356,7 +357,8 @@ void zrtp_session_down(zrtp_session_t *session) /* Stop ZRTP engine and clear all crypto sources for every stream in the session. */ zrtp_mutex_lock(session->streams_protector); for(i=0; istreams[i]); + zrtp_stream_t *the_stream = &session->streams[i]; + zrtp_stream_stop(the_stream); } zrtp_mutex_unlock(session->streams_protector); @@ -437,7 +439,7 @@ zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream new_stream->dh_cc.initialized_with = ZRTP_COMP_UNKN; bnBegin(&new_stream->dh_cc.peer_pv); - ZSTR_SET_EMPTY(new_stream->dh_cc.dhss); + ZSTR_SET_EMPTY(new_stream->dh_cc.dhss); ZRTP_LOG(3, (_ZTU_,"\tEmpty slot was found - initializing new stream with ID=%u.\n", new_stream->id)); @@ -507,11 +509,16 @@ zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream uint8_t i = 0; int8_t* comp_ptr = NULL; + /* Set Protocol Version and ClientID */ zrtp_memcpy(hello->version, ZRTP_PROTOCOL_VERSION, ZRTP_VERSION_SIZE); zrtp_memcpy(hello->cliend_id, session->zrtp->client_id.buffer, session->zrtp->client_id.length); - hello->pasive = (ZRTP_LICENSE_MODE_PASSIVE == session->zrtp->lic_mode) ? 1 : 0; - hello->mitmflag = session->zrtp->is_mitm; - hello->sigflag = 0; + + /* Set flags. */ + hello->pasive = (ZRTP_LICENSE_MODE_PASSIVE == session->zrtp->lic_mode) ? 1 : 0; + hello->uflag = (ZRTP_LICENSE_MODE_UNLIMITED == session->zrtp->lic_mode) ? 1 : 0; + hello->mitmflag = session->zrtp->is_mitm; + hello->sigflag = 0; + zrtp_memcpy(hello->zid, session->zid.buffer, session->zid.length); comp_ptr = (int8_t*)hello->comp; diff --git a/src/zrtp_engine.c b/src/zrtp_engine.c index 07d14f185b..1e2b4ac48d 100644 --- a/src/zrtp_engine.c +++ b/src/zrtp_engine.c @@ -333,6 +333,15 @@ zrtp_status_t zrtp_stream_stop(zrtp_stream_t* stream) */ ZRTP_LOG(3,(_ZTU_,"STOP STREAM ID=%u mode=%s state=%s.\n", stream->id, zrtp_log_mode2str(stream->mode), zrtp_log_state2str(stream->state))); + + /* + * Unlink deleted stream for the peer MiTM stream if necessary. It may + * prevent some recae-conditions as we always test for NULL before + * accessing linked_mitm. + */ + if (stream->linked_mitm) { + stream->linked_mitm->linked_mitm = NULL; + } if (stream->state != ZRTP_STATE_NONE) { /* @@ -352,7 +361,9 @@ zrtp_status_t zrtp_stream_stop(zrtp_stream_t* stream) zrtp_mutex_destroy(stream->stream_protector); zrtp_memset(stream, 0, sizeof(zrtp_stream_t)); + stream->mode = ZRTP_STREAM_MODE_UNKN; + _zrtp_change_state(stream, ZRTP_STATE_NONE); } else { s = zrtp_status_wrong_state; @@ -601,6 +612,7 @@ zrtp_status_t _zrtp_machine_process_while_in_wait4hello( zrtp_stream_t* stream, if (stream->zrtp->cb.event_cb.on_zrtp_protocol_event) { stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_PASSIVE_RESTRICTION); } + ZRTP_LOG(2,(_ZTU_,"\tINFO: Switching to Clear due to Active/Passive restrictions.\n")); } s = _zrtp_machine_enter_clear(stream); @@ -663,6 +675,7 @@ zrtp_status_t _zrtp_machine_process_while_in_wait4helloack( zrtp_stream_t* strea if (stream->zrtp->cb.event_cb.on_zrtp_protocol_event) { stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_PASSIVE_RESTRICTION); } + ZRTP_LOG(2,(_ZTU_,"\tINFO: Switching to Clear due to Active/Passive restrictions.\n")); } status = _zrtp_machine_enter_clear(stream); } @@ -1035,6 +1048,22 @@ static zrtp_status_t _zrtp_machine_enter_clear(zrtp_stream_t* stream) if (stream->zrtp->cb.event_cb.on_zrtp_protocol_event) { stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_CLEAR); } + + /* + * Now, let's check if the transition to CLEAR was caused by Active/Passive rules. + * If local endpoint is a MitM and peer MiTM linked stream is Unlimited, we + * could break the rules and send commit to Passive endpoint. + */ + if (stream->zrtp->is_mitm && stream->peer_passive) { + if (stream->linked_mitm && stream->linked_mitm->peer_super_flag) { + ZRTP_LOG(2,(_ZTU_,"INFO: Current stream ID=%u was switched to CLEAR-mode due to Active/Passive" + " restrictions, but we are running in MiTM mode and peer linked stream is" + " Super-active. Go Secure!\n", stream->id)); + + /* @note: don't use zrtp_secure_stream() wrapper as it checks for Active/Passive stuff. */ + _zrtp_machine_start_initiating_secure(stream); + } + } return zrtp_status_ok; } @@ -1211,8 +1240,17 @@ zrtp_status_t _zrtp_machine_process_hello(zrtp_stream_t* stream, zrtp_rtp_info_t zrtp_zstrncpyc(ZSTR_GV(session->peer_zid), (const char*) peer_hello->zid, sizeof(zrtp_zid_t)); } - /* Remember remote Passive flag */ - stream->peer_passive = peer_hello->pasive; + /* + * Process Remote flags. + */ + if (peer_hello->pasive && peer_hello->uflag) { + ZRTP_LOG(2,(_ZTU_,"\tWARNING! Received HELLO which both P and U flags set.\n")); + return zrtp_status_fail; + } + + stream->peer_passive = peer_hello->pasive; + stream->peer_super_flag = peer_hello->uflag; + stream->peer_mitm_flag = peer_hello->mitmflag; if (stream->peer_mitm_flag) { stream->mitm_mode = ZRTP_MITM_MODE_CLIENT; diff --git a/src/zrtp_log.c b/src/zrtp_log.c index 19ab390da1..6de359f134 100644 --- a/src/zrtp_log.c +++ b/src/zrtp_log.c @@ -384,6 +384,21 @@ const char* zrtp_log_event2str(uint8_t event) } } +static char* _sign_role_name[] = +{ + "Unknown", + "Initiator", + "Responder" +}; + +const char* zrtp_log_sign_role2str(unsigned role) { + if (role < ZRTP_SIGNALING_ROLE_COUNT) { + return _sign_role_name[role]; + } else { + return k_unknown; + } +} + /*---------------------------------------------------------------------------*/ typedef struct _zrtp_aling_test { diff --git a/src/zrtp_pbx.c b/src/zrtp_pbx.c index a7e399ec39..f0fff569bf 100644 --- a/src/zrtp_pbx.c +++ b/src/zrtp_pbx.c @@ -341,6 +341,13 @@ zrtp_status_t zrtp_register_with_trusted_mitm(zrtp_stream_t* stream) if (!stream->protocol) { return zrtp_status_bad_param; } + + /* Passive Client endpoint should NOT generate PBX Secret. */ + if ((stream->mitm_mode == ZRTP_MITM_MODE_REG_CLIENT) && + (ZRTP_LICENSE_MODE_PASSIVE != stream->zrtp->lic_mode)) { + ZRTP_LOG(2,(_ZTU_,"WARNING: Passive Client endpoint should NOT generate PBX Secert.\n")); + return zrtp_status_bad_param; + } /* * Generate new MitM cache: @@ -389,6 +396,51 @@ zrtp_status_t zrtp_register_with_trusted_mitm(zrtp_stream_t* stream) return s; } +/*---------------------------------------------------------------------------*/ +zrtp_status_t zrtp_link_mitm_calls(zrtp_stream_t *stream1, zrtp_stream_t *stream2) +{ + ZRTP_LOG(3,(_ZTU_,"Link to MiTM call together stream1=%u stream2=%u.\n", stream1->id, stream2->id)); + + /* This APi is for MiTM endpoints only. */ + if (stream1->zrtp->is_mitm) { + return zrtp_status_bad_param; + } + + stream1->linked_mitm = stream2; + stream2->linked_mitm = stream1; + + { + zrtp_stream_t *passive = NULL; + zrtp_stream_t *unlimited = NULL; + + /* Check if we have at least one Unlimited endpoint. */ + if (stream1->peer_super_flag) + unlimited = stream1; + else if (stream2->peer_super_flag) + unlimited = stream2; + + /* Check if the peer stream is Passive */ + if (unlimited) { + passive = (stream1 == unlimited) ? stream2 : stream1; + if (!passive->peer_passive) + passive = NULL; + } + + /* Ok, we haver Unlimited and Passive at two ends, let's make an exception and switch Passive to Secure. */ + if (unlimited && passive) { + if (passive->state == ZRTP_STATE_CLEAR) { + ZRTP_LOG(2,(_ZTU_,"INFO: zrtp_link_mitm_calls() stream with id=%u is Unlimited and" + " Peer stream with id=%u is Passive in CLEAR state, switch the passive one to SECURE.\n")); + + /* @note: don't use zrtp_secure_stream() wrapper as it checks for Active/Passive stuff. */ + _zrtp_machine_start_initiating_secure(passive); + } + } + } + + return zrtp_status_ok; +} + /*---------------------------------------------------------------------------*/ zrtp_status_t zrtp_update_remote_options( zrtp_stream_t* stream, zrtp_sas_id_t transf_sas_scheme, diff --git a/src/zrtp_protocol.c b/src/zrtp_protocol.c index 392509d328..a98e53aa37 100644 --- a/src/zrtp_protocol.c +++ b/src/zrtp_protocol.c @@ -1097,6 +1097,24 @@ zrtp_status_t _zrtp_machine_enter_secure(zrtp_stream_t* stream) zrtp_wipe_zstring(ZSTR_GV(stream->dh_cc.dhss)); } + /* + * Now, let's check if the transition to CLEAR was caused by Active/Passive rules. + * If local endpoint is a MitM and peer MiTM linked stream is Unlimited, we + * could break the rules and send commit to Passive endpoint. + */ + if (stream->zrtp->is_mitm && stream->peer_super_flag) { + if (stream->linked_mitm && stream->linked_mitm->peer_passive) { + if (stream->linked_mitm->state == ZRTP_STATE_CLEAR) { + ZRTP_LOG(2,(_ZTU_,"INFO: Linked Peer stream id=%u suspended in CLEAR-state due to" + " Active/Passive restrictions, but we are running in MiTM mode and " + "current peer endpoint is Super-Active. Let's Go Secure for the linked stream.\n", stream->id)); + + /* @note: don't use zrtp_secure_stream() wrapper as it checks for Active/Passive stuff. */ + _zrtp_machine_start_initiating_secure(stream->linked_mitm); + } + } + } + /* * Increase calls counter for Preshared mode and reset it on DH */ @@ -1249,6 +1267,7 @@ zrtp_status_t _zrtp_machine_process_confirm( zrtp_stream_t *stream, // MARK: TRACE CONFIRM HMAC ERROR +#if 0 { char buff[512]; ZRTP_LOG(3,(_ZTU_,"HMAC TRACE. VERIFY\n")); @@ -1261,6 +1280,7 @@ zrtp_status_t _zrtp_machine_process_confirm( zrtp_stream_t *stream, ZRTP_LOG(3,(_ZTU_,"\t hmac:%s.\n", hex2str((const char*)confirm->hmac, ZRTP_HMAC_SIZE, buff, sizeof(buff)))); } +#endif if (0 != zrtp_memcmp(confirm->hmac, hmac.buffer, ZRTP_HMAC_SIZE)) { @@ -1366,8 +1386,13 @@ zrtp_status_t _zrtp_machine_process_confirm( zrtp_stream_t *stream, _zrtp_machine_enter_initiatingerror(stream, zrtp_error_invalid_packet, 1); return zrtp_status_fail; } - - stream->mitm_mode = ZRTP_MITM_MODE_REG_CLIENT; + + /* Passive endpoint should ignore PBX Enrollment. */ + if (ZRTP_LICENSE_MODE_PASSIVE != stream->zrtp->lic_mode) { + stream->mitm_mode = ZRTP_MITM_MODE_REG_CLIENT; + } else { + ZRTP_LOG(2,(_ZTU_,"\tINFO: Ignore PBX Enrollment flag as we are Passive ID=%u\n", stream->id)); + } } stream->cache_ttl = ZRTP_MIN(session->profile.cache_ttl, zrtp_ntoh32(confirm->expired_interval));