1 /*
2  * Copyright (C) 2014 Stefan Sayer
3  *
4  * Parts of the development of this module was kindly sponsored by AMTEL Inc.
5  *
6  * This file is part of SEMS, a free SIP media server.
7  *
8  * SEMS is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version. This program is released under
12  * the GPL with the additional exemption that compiling, linking,
13  * and/or using OpenSSL is allowed.
14  *
15  * For a license to use the SEMS software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * SEMS is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29 #include "ModZrtp.h"
30 #include "log.h"
31 #include "AmUtils.h"
32 
33 #include "DSMSession.h"
34 #include "DSMCoreModule.h"
35 
36 SC_EXPORT(MOD_CLS_NAME);
37 
38 
MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME)39 MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
40 
41 #ifdef WITH_ZRTP
42   DEF_CMD("zrtp.setEnabled", ZRTPSetEnabledAction);
43   DEF_CMD("zrtp.setAllowclear", ZRTPSetAllowclearAction);
44   DEF_CMD("zrtp.setAutosecure", ZRTPSetAutosecureAction);
45   DEF_CMD("zrtp.setDisclosebit", ZRTPSetDisclosebitAction);
46   DEF_CMD("zrtp.getSAS", ZRTPGetSASAction);
47   DEF_CMD("zrtp.getSessionInfo", ZRTPGetSessionInfoAction);
48   DEF_CMD("zrtp.setVerified", ZRTPSetVerifiedAction);
49   DEF_CMD("zrtp.setUnverified", ZRTPSetUnverifiedAction);
50   DEF_CMD("zrtp.setSignalingHash", ZRTPSetSignalingHash);
51   DEF_CMD("zrtp.getSignalingHash", ZRTPGetSignalingHash);
52 #endif
53 
54 } MOD_ACTIONEXPORT_END;
55 
MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME)56 MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
57 #ifdef WITH_ZRTP
58 
59   if (cmd == "zrtp.protocolEvent")
60     return new TestDSMCondition(params, DSMCondition::ZRTPProtocolEvent);
61 
62   if (cmd == "zrtp.securityEvent")
63     return new TestDSMCondition(params, DSMCondition::ZRTPSecurityEvent);
64 
65 #endif
66 } MOD_CONDITIONEXPORT_END;
67 
68 #ifdef WITH_ZRTP
69 
EXEC_ACTION_START(ZRTPSetEnabledAction)70 EXEC_ACTION_START(ZRTPSetEnabledAction) {
71   bool b = resolveVars(arg, sess, sc_sess, event_params) == DSM_TRUE;
72   DBG("setting ZRTP to %sabled\n", b?"en":"dis");
73   sess->enable_zrtp = b;
74 } EXEC_ACTION_END;
75 
EXEC_ACTION_START(ZRTPSetAllowclearAction)76 EXEC_ACTION_START(ZRTPSetAllowclearAction) {
77   bool b = resolveVars(arg, sess, sc_sess, event_params) == DSM_TRUE;
78   DBG("setting ZRTP allowclear %sabled\n", b?"en":"dis");
79   sess->zrtp_session_state.zrtp_session->profile.allowclear = b;
80 } EXEC_ACTION_END;
81 
82 
EXEC_ACTION_START(ZRTPSetAutosecureAction)83 EXEC_ACTION_START(ZRTPSetAutosecureAction) {
84   bool b = resolveVars(arg, sess, sc_sess, event_params) == DSM_TRUE;
85   DBG("setting ZRTP autosecure %sabled\n", b?"en":"dis");
86   sess->zrtp_session_state.zrtp_session->profile.autosecure = b;
87 } EXEC_ACTION_END;
88 
89 
EXEC_ACTION_START(ZRTPSetDisclosebitAction)90 EXEC_ACTION_START(ZRTPSetDisclosebitAction) {
91   bool b = resolveVars(arg, sess, sc_sess, event_params) == DSM_TRUE;
92   DBG("setting ZRTP disclose_bit %sabled\n", b?"en":"dis");
93   sess->zrtp_session_state.zrtp_session->profile.disclose_bit = b;
94 } EXEC_ACTION_END;
95 
96 CONST_ACTION_2P(ZRTPGetSASAction, ',', true);
EXEC_ACTION_START(ZRTPGetSASAction)97 EXEC_ACTION_START(ZRTPGetSASAction) {
98   string varname = par1;
99   if (varname.size() && varname[0]=='$') varname = varname.substr(1);
100 
101   string sas2 = par2;
102   if (sas2.size() && sas2[0]=='$') sas2 = sas2.substr(1);
103 
104   if (varname.empty()) {
105     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
106     sc_sess->SET_STRERROR("need variable name for zrtp.getSAS");
107     EXEC_ACTION_STOP;
108   }
109 
110   if (NULL == sess->zrtp_session_state.zrtp_session) {
111     WARN("ZRTP not active on that session\n");
112     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
113     sc_sess->SET_STRERROR("ZRTP not active on that session");
114     EXEC_ACTION_STOP;
115   }
116 
117    zrtp_session_info_t zrtp_session_info;
118    zrtp_session_get(sess->zrtp_session_state.zrtp_session, &zrtp_session_info);
119 
120    if (!zrtp_session_info.sas_is_ready) {
121      sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
122      sc_sess->SET_STRERROR("ZRTP SAS not ready on that session");
123      EXEC_ACTION_STOP;
124    }
125 
126    sc_sess->var[varname] = string(zrtp_session_info.sas1.buffer, zrtp_session_info.sas1.length);
127    if (!sas2.empty())
128      sc_sess->var[sas2] = string(zrtp_session_info.sas2.buffer, zrtp_session_info.sas2.length);
129 
130    DBG("got SAS1 and SAS2: <%.*s> <%.*s>\n", zrtp_session_info.sas1.length, zrtp_session_info.sas1.buffer,
131        zrtp_session_info.sas2.length, zrtp_session_info.sas1.buffer);
132 } EXEC_ACTION_END;
133 
EXEC_ACTION_START(ZRTPGetSessionInfoAction)134 EXEC_ACTION_START(ZRTPGetSessionInfoAction) {
135   string varname = arg;
136   if (varname.size() && varname[0]=='$') varname = varname.substr(1);
137 
138   if (varname.empty()) {
139     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
140     sc_sess->SET_STRERROR("need variable name for zrtp.getSessionInfo");
141     EXEC_ACTION_STOP;
142   }
143 
144   if (NULL == sess->zrtp_session_state.zrtp_session) {
145     WARN("ZRTP not active on that session\n");
146     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
147     sc_sess->SET_STRERROR("ZRTP not active on that session");
148     EXEC_ACTION_STOP;
149   }
150 
151    zrtp_session_info_t zrtp_session_info;
152    zrtp_session_get(sess->zrtp_session_state.zrtp_session, &zrtp_session_info);
153 
154    sc_sess->var[varname+".sas_is_ready"] = zrtp_session_info.sas_is_ready ? "true":"false";
155 
156    if (zrtp_session_info.sas_is_ready) {
157      sc_sess->var[varname+".sas1"] = string(zrtp_session_info.sas1.buffer, zrtp_session_info.sas1.length);
158      sc_sess->var[varname+".sas2"] = string(zrtp_session_info.sas2.buffer, zrtp_session_info.sas2.length);
159    } else {
160      sc_sess->var[varname+".sas1"] = sc_sess->var[varname+".sas2"] = string();
161    }
162 
163    sc_sess->var[varname+".id"] = int2str(zrtp_session_info.id);
164    string zid_hex;
165 
166    sc_sess->var[varname+".zid"] = "";
167    for (size_t i=0;i<zrtp_session_info.zid.length;i++)
168      sc_sess->var[varname+".zid"]+=char2hex(zrtp_session_info.zid.buffer[i], true);
169 
170    sc_sess->var[varname+".peer_zid"] = "";
171    for (size_t i=0;i<zrtp_session_info.peer_zid.length;i++)
172      sc_sess->var[varname+".peer_zid"]+=char2hex(zrtp_session_info.peer_zid.buffer[i], true);
173 
174    sc_sess->var[varname+".peer_clientid"] = string(zrtp_session_info.peer_clientid.buffer, zrtp_session_info.peer_clientid.length);
175    sc_sess->var[varname+".peer_version"] = string(zrtp_session_info.peer_version.buffer, zrtp_session_info.peer_version.length);
176 
177    sc_sess->var[varname+".sas_is_verified"] = zrtp_session_info.sas_is_verified ? "true":"false";
178    // todo: cached_flags, matches_flags, wrongs_flags
179 
180 } EXEC_ACTION_END;
181 
182 CONST_ACTION_2P(ZRTPSetVerifiedAction, ',', false);
EXEC_ACTION_START(ZRTPSetVerifiedAction)183 EXEC_ACTION_START(ZRTPSetVerifiedAction) {
184   string zid1 = resolveVars(par1, sess, sc_sess, event_params);
185   string zid2 = resolveVars(par2, sess, sc_sess, event_params);
186   if (zid1.empty() || zid2.empty()) {
187     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
188     sc_sess->SET_STRERROR("zid1 and zid2 must be there for setVerified");
189     EXEC_ACTION_STOP;
190   }
191 
192   DBG("setting as verified zids <%s> and <%s>\n", zid1.c_str(), zid2.c_str());
193 
194   zrtp_string16_t _zid1 = ZSTR_INIT_EMPTY(_zid1);
195   zrtp_string16_t _zid2 = ZSTR_INIT_EMPTY(_zid2);
196 
197   str2hex(zid1.c_str(), zid1.length(), _zid1.buffer, _zid1.max_length);
198   _zid1.length = zid1.length() / 2;
199 
200   str2hex(zid2.c_str(), zid2.length(), _zid2.buffer, _zid2.max_length);
201   _zid2.length = zid2.length() / 2;
202 
203   if (zrtp_status_ok != zrtp_verified_set(AmZRTP::zrtp_global, &_zid1, &_zid2, 1)) {
204     DBG("zrtp_verified_set failed\n");
205     sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
206     sc_sess->SET_STRERROR("zrtp_verified_set failed");
207   }
208 } EXEC_ACTION_END;
209 
210 CONST_ACTION_2P(ZRTPSetUnverifiedAction, ',', false);
EXEC_ACTION_START(ZRTPSetUnverifiedAction)211 EXEC_ACTION_START(ZRTPSetUnverifiedAction) {
212   string zid1 = resolveVars(par1, sess, sc_sess, event_params);
213   string zid2 = resolveVars(par2, sess, sc_sess, event_params);
214   if (zid1.empty() || zid2.empty()) {
215     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
216     sc_sess->SET_STRERROR("zid1 and zid2 must be there for setUnverified");
217     EXEC_ACTION_STOP;
218   }
219 
220   DBG("setting as unverified zids <%s> and <%s>\n", zid1.c_str(), zid2.c_str());
221 
222   zrtp_string16_t _zid1 = ZSTR_INIT_EMPTY(_zid1);
223   zrtp_string16_t _zid2 = ZSTR_INIT_EMPTY(_zid2);
224 
225   str2hex(zid1.c_str(), zid1.length(), _zid1.buffer, _zid1.max_length);
226   _zid1.length = zid1.length() / 2;
227 
228   str2hex(zid2.c_str(), zid2.length(), _zid2.buffer, _zid2.max_length);
229   _zid2.length = zid2.length() / 2;
230 
231   if (zrtp_status_ok != zrtp_verified_set(AmZRTP::zrtp_global, &_zid1, &_zid2, 0)) {
232     DBG("zrtp_verified_set failed\n");
233     sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
234     sc_sess->SET_STRERROR("zrtp_verified_set failed");
235   }
236 } EXEC_ACTION_END;
237 
EXEC_ACTION_START(ZRTPSetSignalingHash)238 EXEC_ACTION_START(ZRTPSetSignalingHash) {
239   string h = resolveVars(arg, sess, sc_sess, event_params);
240   DBG("setting signaling hash to '%s'\n", h.c_str());
241 
242   if (NULL == sess->zrtp_session_state.zrtp_audio) {
243     WARN("ZRTP not active on that stream\n");
244     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
245     sc_sess->SET_STRERROR("ZRTP not active on that stream");
246     EXEC_ACTION_STOP;
247   }
248 
249   if (zrtp_status_ok != zrtp_signaling_hash_set(sess->zrtp_session_state.zrtp_audio,
250 						h.c_str(), h.length())) {
251     DBG("zrtp_signaling_hash_set failed\n");
252     sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
253     sc_sess->SET_STRERROR("zrtp_signaling_hash_set failed");
254   }
255 } EXEC_ACTION_END;
256 
EXEC_ACTION_START(ZRTPGetSignalingHash)257 EXEC_ACTION_START(ZRTPGetSignalingHash) {
258   string varname = arg;
259   if (varname.size() && varname[0]=='$') varname = varname.substr(1);
260 
261   if (NULL == sess->zrtp_session_state.zrtp_audio) {
262     WARN("ZRTP not active on that stream\n");
263     sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
264     sc_sess->SET_STRERROR("ZRTP not active on that stream");
265     EXEC_ACTION_STOP;
266   }
267 
268   char b[ZRTP_SIGN_ZRTP_HASH_LENGTH];
269   memset(b, 0, sizeof(b));
270   if (zrtp_status_ok != zrtp_signaling_hash_get(sess->zrtp_session_state.zrtp_audio,
271 						b, ZRTP_SIGN_ZRTP_HASH_LENGTH)) {
272     DBG("zrtp_signaling_hash_get failed\n");
273     sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
274     sc_sess->SET_STRERROR("zrtp_signaling_hash_get failed");
275   }
276   sc_sess->var[varname] = string(b);
277   DBG("got signaling hash '%s'\n", b);
278 } EXEC_ACTION_END;
279 
280 #endif
281