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