Mercurial > hg
annotate mcabber/src/otr.c @ 1461:8fa24a6d1a93
Improve Remote Controlling Clients
The XEP recommends adding the node to the IQ response.
Some clients seem not to understand the answer when it is omitted.
Problem reported by Rhaamo and js (thanks to js for spotting the
node issue!).
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sat, 12 Apr 2008 13:35:03 +0200 |
parents | 08f641e91f94 |
children | a8b924b5474c |
rev | line source |
---|---|
1299 | 1 /* |
1303
b6fdbfa6b219
Minor whitespace change
Mikael Berthe <mikael@lilotux.net>
parents:
1301
diff
changeset
|
2 * otr.c -- Off-The-Record Messaging for mcabber |
1299 | 3 * |
4 * Copyright (C) 2007 Frank Zschockelt <mcabber_otr@freakysoft.de> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or (at | |
9 * your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
19 * USA | |
20 */ | |
21 | |
22 #include <config.h> | |
23 | |
24 #ifdef HAVE_LIBOTR | |
25 | |
26 #include "otr.h" | |
27 #include "logprint.h" | |
28 #include "hbuf.h" | |
29 #include "jab_priv.h" | |
30 #include "roster.h" | |
31 #include "utils.h" | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
32 #include "screen.h" |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
33 #include "settings.h" |
1299 | 34 |
35 | |
36 static OtrlUserState userstate = NULL; | |
37 static char * account = NULL; | |
38 static char * keyfile = NULL; | |
39 static char * fprfile = NULL; | |
40 | |
1347
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
41 static int otr_is_enabled = FALSE; |
1299 | 42 |
43 static OtrlPolicy cb_policy (void *opdata, ConnContext *ctx); | |
44 static void cb_create_privkey (void *opdata, | |
45 const char *accountname, | |
46 const char *protocol); | |
47 static int cb_is_logged_in (void *opdata, | |
48 const char *accountname, | |
49 const char *protocol, | |
50 const char *recipient); | |
51 static void cb_inject_message (void *opdata, | |
52 const char *accountname, | |
53 const char *protocol, | |
54 const char *recipient, | |
55 const char *message); | |
56 static void cb_notify (void *opdata, | |
57 OtrlNotifyLevel level, | |
58 const char *accountname, | |
59 const char *protocol, | |
60 const char *username, | |
61 const char *title, | |
62 const char *primary, | |
63 const char *secondary); | |
64 static int cb_display_otr_message(void *opdata, | |
65 const char *accountname, | |
66 const char *protocol, | |
67 const char *username, | |
68 const char *msg); | |
69 static void cb_update_context_list(void *opdata); | |
70 static const char *cb_protocol_name (void *opdata, const char *protocol); | |
71 static void cb_protocol_name_free (void *opdata, | |
72 const char *protocol_name); | |
73 static void cb_new_fingerprint (void *opdata, OtrlUserState us, | |
74 const char *accountname, | |
75 const char *protocol, | |
76 const char *username, | |
77 unsigned char fingerprint[20]); | |
78 static void cb_write_fingerprints (void *opdata); | |
79 static void cb_gone_secure (void *opdata, ConnContext *context); | |
80 static void cb_gone_insecure (void *opdata, ConnContext *context); | |
81 static void cb_still_secure (void *opdata, ConnContext *context, | |
82 int is_reply); | |
83 static void cb_log_message (void *opdata, const char *message); | |
84 static int cb_max_message_size (void *opdata, ConnContext *context); | |
85 | |
86 static OtrlMessageAppOps ops = | |
87 { | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
88 cb_policy, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
89 cb_create_privkey, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
90 cb_is_logged_in, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
91 cb_inject_message, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
92 cb_notify, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
93 cb_display_otr_message, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
94 cb_update_context_list, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
95 cb_protocol_name, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
96 cb_protocol_name_free, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
97 cb_new_fingerprint, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
98 cb_write_fingerprints, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
99 cb_gone_secure, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
100 cb_gone_insecure, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
101 cb_still_secure, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
102 cb_log_message, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
103 cb_max_message_size, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
104 NULL, /*account_name*/ |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
105 NULL /*account_name_free*/ |
1299 | 106 }; |
107 | |
108 static void otr_message_disconnect(ConnContext *ctx); | |
109 static ConnContext * otr_get_context(const char *buddy); | |
110 static void otr_startstop(const char * buddy, int start); | |
111 static void otr_handle_smp_tlvs(OtrlTLV * tlvs, ConnContext * ctx); | |
112 | |
1320 | 113 static char * otr_get_dir(void); |
1299 | 114 |
1420
08f641e91f94
Do not use "jid" as a variable name
Mikael Berthe <mikael@lilotux.net>
parents:
1347
diff
changeset
|
115 void otr_init(const char *fjid) |
1299 | 116 { |
1347
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
117 char *root; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
118 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
119 otr_is_enabled = !!settings_opt_get_int("otr"); |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
120 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
121 if (!otr_is_enabled) |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
122 return; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
123 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
124 OTRL_INIT; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
125 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
126 userstate = otrl_userstate_create (); |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
127 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
128 root = otr_get_dir(); |
1420
08f641e91f94
Do not use "jid" as a variable name
Mikael Berthe <mikael@lilotux.net>
parents:
1347
diff
changeset
|
129 account = jidtodisp(fjid); |
1299 | 130 keyfile = g_strdup_printf("%s%s.key", root, account); |
131 fprfile = g_strdup_printf("%s%s.fpr", root, account); | |
132 g_free(root); | |
133 | |
134 if (otrl_privkey_read(userstate, keyfile)){ | |
135 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR key from %s", keyfile); | |
136 cb_create_privkey(NULL, account, "jabber"); | |
137 } | |
138 if (otrl_privkey_read_fingerprints(userstate, fprfile, NULL, NULL)){ | |
139 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR fingerprints from %s", | |
140 fprfile); | |
141 } | |
142 } | |
143 | |
144 void otr_terminate(void) | |
145 { | |
146 ConnContext * ctx; | |
147 | |
1347
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
148 if (!otr_is_enabled) |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
149 return; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
150 |
1320 | 151 for (ctx = userstate->context_root; ctx; ctx = ctx->next) |
1299 | 152 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) |
153 otr_message_disconnect(ctx); | |
154 | |
155 g_free(account); | |
156 account = NULL; | |
1307
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
157 |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
158 /* XXX This #ifdef is a quick workaround: when mcabber |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
159 * is linked to both gnutls and libotr, libgcrypt will |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
160 * segfault when we call otrl_userstate_free(). |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
161 * This is reported to be a bug in libgcrypt :-/ |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
162 * Mikael |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
163 */ |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
164 #if defined(HAVE_GNUTLS) && !defined(HAVE_OPENSSL) |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
165 if (!settings_opt_get_int("ssl")) |
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
166 #endif |
1299 | 167 otrl_userstate_free(userstate); |
1307
6c116207ab2e
Work around segfault in otrl_userstate_free()
Mikael Berthe <mikael@lilotux.net>
parents:
1306
diff
changeset
|
168 |
1299 | 169 userstate = NULL; |
170 g_free(keyfile); | |
171 keyfile = NULL; | |
172 } | |
173 | |
1320 | 174 static char * otr_get_dir(void) |
175 { | |
1346 | 176 const char *configured_dir = settings_opt_get("otr_dir"); |
1320 | 177 |
1335
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
178 if (configured_dir && *configured_dir) { |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
179 char *xp_conf_dir; |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
180 int l; |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
181 xp_conf_dir = expand_filename(configured_dir); |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
182 // The path must be slash-terminated |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
183 l = strlen(xp_conf_dir); |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
184 if (xp_conf_dir[l-1] != '/') { |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
185 char *xp_conf_dir_tmp = xp_conf_dir; |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
186 xp_conf_dir = g_strdup_printf("%s/", xp_conf_dir_tmp); |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
187 g_free(xp_conf_dir_tmp); |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
188 } |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
189 return xp_conf_dir; |
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
190 } else { |
1320 | 191 return expand_filename("~/.mcabber/otr/"); |
1335
ab1b7f7a682e
Make sure the otr_dir is always slash-terminated
Mikael Berthe <mikael@lilotux.net>
parents:
1320
diff
changeset
|
192 } |
1320 | 193 } |
194 | |
1299 | 195 static ConnContext * otr_get_context(const char *buddy) |
196 { | |
197 int null = 0; | |
198 return otrl_context_find(userstate, buddy, account, "jabber", 1, &null, | |
199 NULL, NULL); | |
200 } | |
201 | |
202 static void otr_message_disconnect(ConnContext *ctx) | |
203 { | |
204 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) | |
205 cb_gone_insecure(NULL, ctx); | |
206 otrl_message_disconnect(userstate, &ops, NULL, ctx->accountname, | |
207 ctx->protocol, ctx->username); | |
208 } | |
209 | |
210 static void otr_startstop(const char * buddy, int start) | |
211 { | |
212 char * msg = NULL; | |
213 ConnContext *ctx = otr_get_context(buddy); | |
214 | |
215 if (!userstate || !ctx) | |
216 return; | |
217 | |
218 if (start && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) | |
219 otr_message_disconnect(ctx); | |
220 | |
221 if (start) { | |
222 OtrlPolicy policy = cb_policy(NULL, ctx); | |
1308
b17754d9221b
Show a warning for /otr start|stop, if policy == plain
franky@veqlargh.fs
parents:
1307
diff
changeset
|
223 if (policy == plain) { |
b17754d9221b
Show a warning for /otr start|stop, if policy == plain
franky@veqlargh.fs
parents:
1307
diff
changeset
|
224 scr_LogPrint(LPRINT_LOGNORM, "The OTR policy for this user is set to" |
b17754d9221b
Show a warning for /otr start|stop, if policy == plain
franky@veqlargh.fs
parents:
1307
diff
changeset
|
225 " plain. You have to change it first."); |
b17754d9221b
Show a warning for /otr start|stop, if policy == plain
franky@veqlargh.fs
parents:
1307
diff
changeset
|
226 return; |
b17754d9221b
Show a warning for /otr start|stop, if policy == plain
franky@veqlargh.fs
parents:
1307
diff
changeset
|
227 } |
1299 | 228 msg = otrl_proto_default_query_msg(ctx->accountname, policy); |
229 cb_inject_message(NULL, ctx->accountname, ctx->protocol, ctx->username, | |
230 msg); | |
231 free (msg); | |
232 } | |
233 else | |
234 otr_message_disconnect(ctx); | |
235 } | |
236 | |
237 void otr_establish(const char *buddy) | |
238 { | |
239 otr_startstop(buddy, 1); | |
240 } | |
241 | |
242 void otr_disconnect(const char * buddy) | |
243 { | |
244 otr_startstop(buddy, 0); | |
245 } | |
246 | |
247 void otr_fingerprint(const char * buddy, const char * trust) | |
248 { | |
249 char fpr[45], *tr; | |
250 ConnContext *ctx = otr_get_context(buddy); | |
251 if (!userstate || !ctx) | |
252 return; | |
253 | |
254 if (!ctx->active_fingerprint || !ctx->active_fingerprint->fingerprint) { | |
255 scr_LogPrint(LPRINT_LOGNORM, | |
256 "No active fingerprint - start OTR for this buddy first."); | |
257 return; | |
258 } | |
259 | |
260 otrl_privkey_hash_to_human(fpr, ctx->active_fingerprint->fingerprint); | |
261 if (trust) { | |
262 if (strcmp(fpr, trust) == 0) | |
263 otrl_context_set_trust(ctx->active_fingerprint, "trust"); | |
264 else | |
265 otrl_context_set_trust(ctx->active_fingerprint, NULL); | |
266 } | |
267 | |
268 tr = ctx->active_fingerprint->trust; | |
269 scr_LogPrint(LPRINT_LOGNORM, "%s [%44s]: %s", ctx->username, fpr, | |
270 tr && *tr ? "trusted" : "untrusted"); | |
271 cb_write_fingerprints(NULL); | |
272 } | |
273 | |
274 static void otr_handle_smp_tlvs(OtrlTLV * tlvs, ConnContext * ctx) | |
275 { | |
276 OtrlTLV *tlv = NULL; | |
277 char *sbuf = NULL; | |
278 NextExpectedSMP nextMsg = ctx->smstate->nextExpected; | |
279 | |
280 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); | |
281 if (tlv) { | |
282 if (nextMsg != OTRL_SMP_EXPECT1) | |
283 otr_smp_abort(ctx->username); | |
284 else { | |
285 sbuf = g_strdup_printf("OTR: Received SMP Initiation. " | |
286 "Answer with /otr smpr %s $secret", | |
287 ctx->username); | |
288 } | |
289 } | |
290 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); | |
291 if (tlv) { | |
292 if (nextMsg != OTRL_SMP_EXPECT2) | |
293 otr_smp_abort(ctx->username); | |
294 else { | |
295 sbuf = g_strdup("OTR: Received SMP Response."); | |
296 /* If we received TLV2, we will send TLV3 and expect TLV4 */ | |
297 ctx->smstate->nextExpected = OTRL_SMP_EXPECT4; | |
298 } | |
299 } | |
300 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); | |
301 if (tlv) { | |
302 if (nextMsg != OTRL_SMP_EXPECT3) | |
303 otr_smp_abort(ctx->username); | |
304 else { | |
305 /* If we received TLV3, we will send TLV4 | |
306 * We will not expect more messages, so prepare for next SMP */ | |
307 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
308 /* Report result to user */ | |
309 if (ctx->active_fingerprint && ctx->active_fingerprint->trust && | |
310 *ctx->active_fingerprint->trust != '\0') | |
311 sbuf = g_strdup("OTR: SMP succeeded"); | |
312 else | |
313 sbuf = g_strdup("OTR: SMP failed"); | |
314 } | |
315 } | |
316 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); | |
317 if (tlv) { | |
318 if (nextMsg != OTRL_SMP_EXPECT4) | |
319 otr_smp_abort(ctx->username); | |
320 else { | |
321 /* We will not expect more messages, so prepare for next SMP */ | |
322 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
323 /* Report result to user */ | |
324 if (ctx->active_fingerprint && ctx->active_fingerprint->trust && | |
325 *ctx->active_fingerprint->trust != '\0') | |
326 sbuf = g_strdup("OTR: SMP succeeded"); | |
327 else | |
328 sbuf = g_strdup("OTR: SMP failed"); | |
329 } | |
330 } | |
331 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); | |
332 if (tlv) { | |
333 /* The message we are waiting for will not arrive, so reset | |
334 * and prepare for the next SMP */ | |
335 sbuf = g_strdup("OTR: SMP aborted by your buddy"); | |
336 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; | |
337 } | |
338 | |
339 if (sbuf) { | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
340 scr_WriteIncomingMessage(ctx->username, sbuf, 0, HBB_PREFIX_INFO, 0); |
1299 | 341 g_free(sbuf); |
342 } | |
343 } | |
344 | |
345 /* | |
346 * returns whether a otr_message was received | |
347 * sets *otr_data to NULL, when it was an internal otr message | |
348 */ | |
349 int otr_receive(char **otr_data, const char * buddy, int * free_msg) | |
350 { | |
351 int ignore_message; | |
352 char *newmessage = NULL; | |
353 OtrlTLV *tlvs = NULL; | |
354 OtrlTLV *tlv = NULL; | |
355 ConnContext * ctx; | |
356 | |
357 *free_msg = 0; | |
358 ignore_message = otrl_message_receiving(userstate, &ops, NULL, account, | |
359 "jabber", buddy, *otr_data, &newmessage, &tlvs, NULL, NULL); | |
360 | |
361 ctx = otr_get_context(buddy); | |
362 | |
363 tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); | |
364 if (tlv) { | |
365 /* Notify the user that the other side disconnected. */ | |
366 if (ctx) { | |
367 cb_gone_insecure(NULL, ctx); | |
368 otr_disconnect(buddy); | |
369 } | |
370 } | |
371 | |
372 otr_handle_smp_tlvs(tlvs, ctx); | |
373 | |
374 if (tlvs != NULL) | |
375 otrl_tlv_free(tlvs); | |
376 | |
377 if (ignore_message) | |
378 *otr_data = NULL; | |
379 | |
380 if (!ignore_message && newmessage) { | |
381 *free_msg = 1; | |
382 *otr_data = g_strdup(newmessage); | |
383 otrl_message_free(newmessage); | |
384 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) | |
385 return 1; | |
386 } | |
387 return 0; | |
388 } | |
389 | |
390 int otr_send(char **msg, const char *buddy) | |
391 { | |
392 gcry_error_t err; | |
393 char *newmessage = NULL; | |
394 ConnContext * ctx = otr_get_context(buddy); | |
395 | |
396 err = otrl_message_sending(userstate, &ops, NULL, account, "jabber", buddy, | |
397 *msg, NULL, &newmessage, NULL, NULL); | |
398 | |
399 if (err) | |
400 *msg = NULL; /*something went wrong, don't send the plain-message! */ | |
401 | |
402 if (!err && newmessage) { | |
403 *msg = g_strdup(newmessage); | |
404 otrl_message_free(newmessage); | |
405 if (cb_policy(NULL, ctx) & OTRL_POLICY_REQUIRE_ENCRYPTION || | |
406 ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) | |
407 return 1; | |
408 } | |
409 return 0; | |
410 } | |
411 | |
412 /* Prints OTR connection state */ | |
413 void otr_print_info(const char * buddy) | |
414 { | |
415 const char *state, *auth, *policy; | |
416 ConnContext * ctx = otr_get_context(buddy); | |
417 OtrlPolicy p = cb_policy (ctx->app_data, ctx); | |
418 | |
419 if (!userstate || !ctx) | |
420 return; | |
421 | |
422 switch (ctx->msgstate) { | |
423 case OTRL_MSGSTATE_PLAINTEXT: state = "plaintext"; break; | |
424 case OTRL_MSGSTATE_ENCRYPTED: | |
425 switch (ctx->protocol_version) { | |
426 case 1: state = "encrypted V1"; break; | |
427 case 2: state = "encrypted V2"; break; | |
428 default:state = "encrypted"; | |
429 }; | |
430 break; | |
431 case OTRL_MSGSTATE_FINISHED: state = "finished"; break; | |
432 default: state = "unknown state"; | |
433 } | |
434 switch (ctx->auth.authstate) { | |
435 case OTRL_AUTHSTATE_NONE: | |
436 switch (ctx->otr_offer) { | |
437 case OFFER_NOT: auth = "no offer sent"; break; | |
438 case OFFER_SENT: auth = "offer sent"; break; | |
439 case OFFER_ACCEPTED: auth = "offer accepted"; break; | |
440 case OFFER_REJECTED: auth = "offer rejected"; break; | |
441 default: auth = "unknown auth"; | |
442 } | |
443 break; | |
444 case OTRL_AUTHSTATE_AWAITING_DHKEY: | |
445 auth = "awaiting D-H key"; break; | |
446 case OTRL_AUTHSTATE_AWAITING_REVEALSIG: | |
447 auth = "awaiting reveal signature"; break; | |
448 case OTRL_AUTHSTATE_AWAITING_SIG: | |
449 auth = "awaiting signature"; break; | |
450 case OTRL_AUTHSTATE_V1_SETUP: | |
451 auth = "v1 setup"; break; | |
452 default: | |
453 auth = "unknown auth"; | |
454 } | |
455 if (p == OTRL_POLICY_NEVER) | |
456 policy = "plain"; | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
457 else if (p == (OTRL_POLICY_OPPORTUNISTIC & ~OTRL_POLICY_ALLOW_V1)) |
1299 | 458 policy = "opportunistic"; |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
459 else if (p == (OTRL_POLICY_MANUAL & ~OTRL_POLICY_ALLOW_V1)) |
1299 | 460 policy = "manual"; |
461 else if (p == (OTRL_POLICY_ALWAYS & ~OTRL_POLICY_ALLOW_V1)) | |
462 policy = "always"; | |
463 else | |
464 policy = "unknown"; | |
465 | |
466 scr_LogPrint(LPRINT_LOGNORM, "%s: %s (%s) [%s]", | |
467 ctx->username, state, auth, policy); | |
468 } | |
469 | |
470 static ConnContext * otr_context_encrypted(const char * buddy) | |
471 { | |
472 ConnContext * ctx = otr_get_context(buddy); | |
473 | |
474 if (!userstate || !ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED){ | |
475 scr_LogPrint(LPRINT_LOGNORM, | |
476 "You have to start an OTR channel with %s before you can " | |
477 "use SMP.", buddy); | |
478 return NULL; | |
479 } | |
480 | |
481 return ctx; | |
482 } | |
483 | |
484 void otr_smp_query(const char * buddy, const char * secret) | |
485 { | |
486 ConnContext * ctx = otr_context_encrypted(buddy); | |
487 | |
488 if (!secret) { | |
489 scr_LogPrint(LPRINT_LOGNORM, | |
490 "Using SMP without a secret isn't a good idea."); | |
491 return; | |
492 } | |
493 | |
494 if (ctx) { | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
495 otrl_message_initiate_smp(userstate, &ops, NULL, ctx, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
496 (const unsigned char *)secret, |
1299 | 497 strlen(secret)); |
498 scr_WriteIncomingMessage(ctx->username, | |
499 "OTR: Socialist Millionaires' Protocol " | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
500 "initiated.", 0, HBB_PREFIX_INFO, 0); |
1299 | 501 } |
502 } | |
503 | |
504 void otr_smp_respond(const char * buddy, const char * secret) | |
505 { | |
506 ConnContext * ctx = otr_context_encrypted(buddy); | |
507 | |
508 if (!secret) { | |
509 scr_LogPrint(LPRINT_LOGNORM, | |
510 "Using SMP without a secret isn't a good idea."); | |
511 return; | |
512 } | |
513 | |
514 if (ctx) { | |
515 if (!ctx->smstate->secret) { | |
516 scr_LogPrint(LPRINT_LOGNORM, | |
517 "Don't call smpr before you haven't received an SMP " | |
518 "Initiation!"); | |
519 return; | |
520 } | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
521 otrl_message_respond_smp(userstate, &ops, NULL, ctx, |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
522 (const unsigned char *)secret, |
1299 | 523 strlen(secret)); |
524 scr_WriteIncomingMessage(ctx->username, | |
525 "OTR: Socialist Millionaires' Protocol: " | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
526 "response sent", 0, HBB_PREFIX_INFO, 0); |
1299 | 527 } |
528 } | |
529 | |
530 void otr_smp_abort(const char * buddy) | |
531 { | |
532 ConnContext * ctx = otr_context_encrypted(buddy); | |
533 | |
534 if (ctx) { | |
535 otrl_message_abort_smp(userstate, &ops, NULL, ctx); | |
536 scr_WriteIncomingMessage(ctx->username, | |
537 "OTR: Socialist Millionaires' Protocol aborted.", | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
538 0, HBB_PREFIX_INFO, 0); |
1299 | 539 } |
540 } | |
541 | |
542 void otr_key(void) | |
543 { | |
544 OtrlPrivKey * key; | |
545 char readable[45] = ""; | |
546 | |
547 if(!userstate) | |
548 return; | |
549 for (key = userstate->privkey_root; key; key = key->next) { | |
550 otrl_privkey_fingerprint(userstate, readable, key->accountname, | |
551 key->protocol); | |
552 scr_LogPrint(LPRINT_LOGNORM, "%s: %s", key->accountname, readable); | |
553 } | |
554 } | |
555 | |
556 /* Return the OTR policy for the given context. */ | |
557 static OtrlPolicy cb_policy(void *opdata, ConnContext *ctx) | |
558 { | |
559 enum otr_policy p = settings_otr_getpolicy(NULL); | |
560 | |
561 if(ctx) | |
562 if(settings_otr_getpolicy(ctx->username)) | |
563 p = settings_otr_getpolicy(ctx->username); | |
564 | |
565 switch (p) { | |
566 case plain: | |
567 return OTRL_POLICY_NEVER; | |
568 case opportunistic: | |
569 return OTRL_POLICY_OPPORTUNISTIC & ~OTRL_POLICY_ALLOW_V1; | |
570 case manual: | |
571 return OTRL_POLICY_MANUAL & ~OTRL_POLICY_ALLOW_V1; | |
572 case always: | |
573 return OTRL_POLICY_ALWAYS & ~OTRL_POLICY_ALLOW_V1; | |
574 } | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
575 |
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
576 return OTRL_POLICY_MANUAL & ~OTRL_POLICY_ALLOW_V1; |
1299 | 577 } |
578 | |
579 /* Create a private key for the given accountname/protocol if | |
580 * desired. */ | |
581 static void cb_create_privkey(void *opdata, const char *accountname, | |
582 const char *protocol) | |
583 { | |
584 gcry_error_t e; | |
1320 | 585 char * root; |
1299 | 586 |
587 scr_LogPrint(LPRINT_LOGNORM, | |
588 "Generating new OTR key for %s. This may take a while...", | |
589 accountname); | |
590 scr_DoUpdate(); | |
591 | |
592 e = otrl_privkey_generate(userstate, keyfile, accountname, protocol); | |
593 | |
1320 | 594 if (e) { |
595 root = otr_get_dir(); | |
596 scr_LogPrint(LPRINT_LOGNORM, "OTR key generation failed! Please mkdir " | |
597 "%s if you want to use otr encryption.", root); | |
598 g_free(root); | |
599 } | |
1299 | 600 else |
601 scr_LogPrint(LPRINT_LOGNORM, "OTR key generated."); | |
602 } | |
603 | |
604 /* Report whether you think the given user is online. Return 1 if | |
605 * you think he is, 0 if you think he isn't, -1 if you're not sure. | |
606 * If you return 1, messages such as heartbeats or other | |
607 * notifications may be sent to the user, which could result in "not | |
608 * logged in" errors if you're wrong. */ | |
609 static int cb_is_logged_in(void *opdata, const char *accountname, | |
610 const char *protocol, const char *recipient) | |
611 { | |
1346 | 612 int ret = (roster_getstatus(recipient, NULL) != offline); |
1299 | 613 return ret; |
614 } | |
615 | |
616 /* Send the given IM to the given recipient from the given | |
617 * accountname/protocol. */ | |
618 static void cb_inject_message(void *opdata, const char *accountname, | |
619 const char *protocol, const char *recipient, | |
620 const char *message) | |
621 { | |
622 char * id = g_strdup("otrinject"); | |
1343 | 623 if (roster_gettype(recipient) == ROSTER_TYPE_USER) |
624 jb_send_msg(recipient, message, ROSTER_TYPE_USER, "", id, NULL, NULL); | |
1299 | 625 g_free(id); |
626 } | |
627 | |
628 /* Display a notification message for a particular | |
629 * accountname / protocol / username conversation. */ | |
630 static void cb_notify(void *opdata, OtrlNotifyLevel level, | |
631 const char *accountname, const char *protocol, | |
632 const char *username, const char *title, | |
633 const char *primary, const char *secondary) | |
634 { | |
635 char * type; | |
636 char *sbuf = NULL; | |
637 switch (level) { | |
638 case OTRL_NOTIFY_ERROR: type = "error"; break; | |
639 case OTRL_NOTIFY_WARNING: type = "warning"; break; | |
640 case OTRL_NOTIFY_INFO: type = "info"; break; | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
641 default: type = "unknown"; |
1299 | 642 } |
643 sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary); | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
644 scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0); |
1299 | 645 g_free(sbuf); |
646 } | |
647 | |
648 /* Display an OTR control message for a particular | |
649 * accountname / protocol / username conversation. Return 0 if you are able | |
650 * to successfully display it. If you return non-0 (or if this | |
651 * function is NULL), the control message will be displayed inline, | |
652 * as a received message, or else by using the above notify() | |
653 * callback. */ | |
654 static int cb_display_otr_message(void *opdata, const char *accountname, | |
655 const char *protocol, const char *username, | |
656 const char *msg) | |
657 { | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
658 scr_WriteIncomingMessage(username, msg, 0, HBB_PREFIX_INFO, 0); |
1299 | 659 return 0; |
660 } | |
661 | |
662 /* When the list of ConnContexts changes (including a change in | |
663 * state), this is called so the UI can be updated. */ | |
664 static void cb_update_context_list(void *opdata) | |
665 { | |
666 /*maybe introduce new status characters for mcabber, | |
667 * then use this function (?!)*/ | |
668 } | |
669 | |
670 /* Return a newly allocated string containing a human-friendly name | |
671 * for the given protocol id */ | |
672 static const char *cb_protocol_name(void *opdata, const char *protocol) | |
673 { | |
674 return protocol; | |
675 } | |
676 | |
677 /* Deallocate a string allocated by protocol_name */ | |
678 static void cb_protocol_name_free (void *opdata, const char *protocol_name) | |
679 { | |
680 /* We didn't allocated memory, so we don't have to free anything :p */ | |
681 } | |
682 | |
683 /* A new fingerprint for the given user has been received. */ | |
684 static void cb_new_fingerprint(void *opdata, OtrlUserState us, | |
685 const char *accountname, const char *protocol, | |
686 const char *username, | |
687 unsigned char fingerprint[20]) | |
688 { | |
689 char *sbuf = NULL; | |
690 char readable[45]; | |
691 | |
692 otrl_privkey_hash_to_human(readable, fingerprint); | |
693 sbuf = g_strdup_printf("OTR: new fingerprint: %s", readable); | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
694 scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0); |
1299 | 695 g_free(sbuf); |
696 } | |
697 | |
698 /* The list of known fingerprints has changed. Write them to disk. */ | |
699 static void cb_write_fingerprints(void *opdata) | |
700 { | |
701 otrl_privkey_write_fingerprints(userstate, fprfile); | |
702 } | |
703 | |
704 /* A ConnContext has entered a secure state. */ | |
705 static void cb_gone_secure(void *opdata, ConnContext *context) | |
706 { | |
707 scr_WriteIncomingMessage(context->username, "OTR: channel established", 0, | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
708 HBB_PREFIX_INFO, 0); |
1299 | 709 } |
710 | |
711 /* A ConnContext has left a secure state. */ | |
712 static void cb_gone_insecure(void *opdata, ConnContext *context) | |
713 { | |
714 scr_WriteIncomingMessage(context->username, "OTR: channel closed", 0, | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
715 HBB_PREFIX_INFO, 0); |
1299 | 716 } |
717 | |
718 /* We have completed an authentication, using the D-H keys we | |
719 * already knew. is_reply indicates whether we initiated the AKE. */ | |
720 static void cb_still_secure(void *opdata, ConnContext *context, int is_reply) | |
721 { | |
722 scr_WriteIncomingMessage(context->username, "OTR: channel reestablished", 0, | |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
723 HBB_PREFIX_INFO, 0); |
1299 | 724 } |
725 | |
726 /* Log a message. The passed message will end in "\n". */ | |
727 static void cb_log_message(void *opdata, const char *message) | |
728 { | |
729 scr_LogPrint(LPRINT_DEBUG, "OTR: %s", message); | |
730 } | |
731 | |
732 /* Find the maximum message size supported by this protocol. */ | |
733 static int cb_max_message_size(void *opdata, ConnContext *context) | |
734 { | |
735 return 8192; | |
736 } | |
737 | |
1347
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
738 int otr_enabled(void) |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
739 { |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
740 return otr_is_enabled; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
741 } |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
742 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
743 #else /* !HAVE_LIBOTR */ |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
744 |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
745 int otr_enabled(void) |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
746 { |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
747 return FALSE; |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
748 } |
07816313073b
Add an option 'otr' to enable OTR support in the configuration file
Mikael Berthe <mikael@lilotux.net>
parents:
1346
diff
changeset
|
749 |
1299 | 750 #endif /* HAVE_LIBOTR */ |
751 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ |