Mercurial > hg
annotate mcabber/src/otr.c @ 1405:e21757606b5b
Update UK help files
author | Myhailo Danylenko <isbear@ukrpost.net> |
---|---|
date | Fri, 11 Jan 2008 12:06:50 +0100 |
parents | 07816313073b |
children | 08f641e91f94 |
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 |
1301
37b41ed9ed35
Fixed compiler warnings
Frank Zschockelt <mcabber_otr[at]freakysoft.de>
parents:
1299
diff
changeset
|
115 void otr_init(const char *jid) |
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(); |
1299 | 129 account = jidtodisp(jid); |
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... */ |