36 |
36 |
37 static OtrlUserState userstate = NULL; |
37 static OtrlUserState userstate = NULL; |
38 static char *account = NULL; |
38 static char *account = NULL; |
39 static char *keyfile = NULL; |
39 static char *keyfile = NULL; |
40 static char *fprfile = NULL; |
40 static char *fprfile = NULL; |
|
41 static char *tagfile = NULL; |
|
42 static guint otr_timer_source = 0; |
41 |
43 |
42 static int otr_is_enabled = FALSE; |
44 static int otr_is_enabled = FALSE; |
43 |
45 |
44 static OtrlPolicy cb_policy (void *opdata, ConnContext *ctx); |
46 static OtrlPolicy cb_policy (void *opdata, ConnContext *ctx); |
45 static void cb_create_privkey (void *opdata, |
47 static void cb_create_privkey (void *opdata, |
65 static void cb_gone_insecure (void *opdata, ConnContext *context); |
67 static void cb_gone_insecure (void *opdata, ConnContext *context); |
66 static void cb_still_secure (void *opdata, ConnContext *context, |
68 static void cb_still_secure (void *opdata, ConnContext *context, |
67 int is_reply); |
69 int is_reply); |
68 static int cb_max_message_size (void *opdata, ConnContext *context); |
70 static int cb_max_message_size (void *opdata, ConnContext *context); |
69 |
71 |
70 #ifdef HAVE_LIBOTR3 |
|
71 static void cb_notify (void *opdata, |
|
72 OtrlNotifyLevel level, |
|
73 const char *accountname, |
|
74 const char *protocol, |
|
75 const char *username, |
|
76 const char *title, |
|
77 const char *primary, |
|
78 const char *secondary); |
|
79 static int cb_display_otr_message(void *opdata, |
|
80 const char *accountname, |
|
81 const char *protocol, |
|
82 const char *username, |
|
83 const char *msg); |
|
84 static const char *cb_protocol_name (void *opdata, const char *protocol); |
|
85 static void cb_protocol_name_free (void *opdata, |
|
86 const char *protocol_name); |
|
87 static void cb_log_message (void *opdata, const char *message); |
|
88 |
|
89 static void otr_handle_smp_tlvs (OtrlTLV *tlvs, ConnContext *ctx); |
|
90 #else /* HAVE_LIBOTR3 */ |
|
91 static char *tagfile = NULL; |
|
92 static guint otr_timer_source = 0; |
|
93 |
|
94 static void cb_handle_smp_event (void *opdata, OtrlSMPEvent event, |
72 static void cb_handle_smp_event (void *opdata, OtrlSMPEvent event, |
95 ConnContext *context, unsigned short percent, |
73 ConnContext *context, unsigned short percent, |
96 char *question); |
74 char *question); |
97 static void cb_handle_msg_event (void *opdata, OtrlMessageEvent event, |
75 static void cb_handle_msg_event (void *opdata, OtrlMessageEvent event, |
98 ConnContext *context, const char *message, |
76 ConnContext *context, const char *message, |
99 gcry_error_t err); |
77 gcry_error_t err); |
100 static void cb_create_instag (void *opdata, const char *accountname, |
78 static void cb_create_instag (void *opdata, const char *accountname, |
101 const char *protocol); |
79 const char *protocol); |
102 static void cb_timer_control (void *opdata, unsigned int interval); |
80 static void cb_timer_control (void *opdata, unsigned int interval); |
103 #endif /* HAVE_LIBOTR3 */ |
|
104 |
81 |
105 static OtrlMessageAppOps ops = |
82 static OtrlMessageAppOps ops = |
106 { |
83 { |
107 cb_policy, |
84 cb_policy, |
108 cb_create_privkey, |
85 cb_create_privkey, |
109 cb_is_logged_in, |
86 cb_is_logged_in, |
110 cb_inject_message, |
87 cb_inject_message, |
111 #ifdef HAVE_LIBOTR3 |
|
112 cb_notify, |
|
113 cb_display_otr_message, |
|
114 #endif |
|
115 cb_update_context_list, |
88 cb_update_context_list, |
116 #ifdef HAVE_LIBOTR3 |
|
117 cb_protocol_name, |
|
118 cb_protocol_name_free, |
|
119 #endif |
|
120 cb_new_fingerprint, |
89 cb_new_fingerprint, |
121 cb_write_fingerprints, |
90 cb_write_fingerprints, |
122 cb_gone_secure, |
91 cb_gone_secure, |
123 cb_gone_insecure, |
92 cb_gone_insecure, |
124 cb_still_secure, |
93 cb_still_secure, |
125 #ifdef HAVE_LIBOTR3 |
|
126 cb_log_message, |
|
127 #endif |
|
128 cb_max_message_size, |
94 cb_max_message_size, |
129 NULL, /* account_name */ |
95 NULL, /* account_name */ |
130 NULL, /* account_name_free */ |
96 NULL, /* account_name_free */ |
131 #ifndef HAVE_LIBOTR3 |
|
132 NULL, /* received_symkey */ |
97 NULL, /* received_symkey */ |
133 NULL, /* otr_error_message */ |
98 NULL, /* otr_error_message */ |
134 NULL, /* otr_error_message_free */ |
99 NULL, /* otr_error_message_free */ |
135 NULL, /* resent_msg_prefix */ |
100 NULL, /* resent_msg_prefix */ |
136 NULL, /* resent_msg_prefix_free */ |
101 NULL, /* resent_msg_prefix_free */ |
172 |
136 |
173 if (otrl_privkey_read(userstate, keyfile)){ |
137 if (otrl_privkey_read(userstate, keyfile)){ |
174 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR key from %s", keyfile); |
138 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR key from %s", keyfile); |
175 cb_create_privkey(NULL, account, OTR_PROTOCOL_NAME); |
139 cb_create_privkey(NULL, account, OTR_PROTOCOL_NAME); |
176 } |
140 } |
|
141 |
177 if (otrl_privkey_read_fingerprints(userstate, fprfile, NULL, NULL)){ |
142 if (otrl_privkey_read_fingerprints(userstate, fprfile, NULL, NULL)){ |
178 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR fingerprints from %s", |
143 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR fingerprints from %s", |
179 fprfile); |
144 fprfile); |
180 } |
145 } |
181 #ifndef HAVE_LIBOTR3 |
146 |
182 tagfile = g_strdup_printf("%s%s.tag", root, account); |
147 tagfile = g_strdup_printf("%s%s.tag", root, account); |
183 if (otrl_instag_read(userstate, tagfile)) { |
148 if (otrl_instag_read(userstate, tagfile)) { |
184 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR instance tag from %s", tagfile); |
149 scr_LogPrint(LPRINT_LOGNORM, "Could not read OTR instance tag from %s", tagfile); |
185 cb_create_instag(NULL, account, OTR_PROTOCOL_NAME); |
150 cb_create_instag(NULL, account, OTR_PROTOCOL_NAME); |
186 } |
151 } |
187 #endif |
152 |
188 g_free(root); |
153 g_free(root); |
189 } |
154 } |
190 |
155 |
191 void otr_terminate(void) |
156 void otr_terminate(void) |
192 { |
157 { |
193 ConnContext *ctx; |
158 ConnContext *ctx; |
194 |
159 |
195 if (!otr_is_enabled) |
160 if (!otr_is_enabled) |
196 return; |
161 return; |
197 |
162 |
198 #ifndef HAVE_LIBOTR3 |
|
199 if (otr_timer_source > 0) { |
163 if (otr_timer_source > 0) { |
200 g_source_remove (otr_timer_source); |
164 g_source_remove (otr_timer_source); |
201 otr_timer_source = 0; |
165 otr_timer_source = 0; |
202 } |
166 } |
203 #endif |
|
204 |
167 |
205 for (ctx = userstate->context_root; ctx; ctx = ctx->next) |
168 for (ctx = userstate->context_root; ctx; ctx = ctx->next) |
206 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) |
169 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) |
207 otr_message_disconnect(ctx); |
170 otr_message_disconnect(ctx); |
208 |
171 |
258 ConnContext *ctx; |
219 ConnContext *ctx; |
259 char *lowcasebuddy = g_strdup(buddy); |
220 char *lowcasebuddy = g_strdup(buddy); |
260 |
221 |
261 mc_strtolower(lowcasebuddy); |
222 mc_strtolower(lowcasebuddy); |
262 ctx = otrl_context_find(userstate, lowcasebuddy, account, OTR_PROTOCOL_NAME, |
223 ctx = otrl_context_find(userstate, lowcasebuddy, account, OTR_PROTOCOL_NAME, |
263 #ifdef HAVE_LIBOTR3 |
|
264 1, &null, NULL, NULL); |
|
265 #else |
|
266 // INSTAG XXX |
224 // INSTAG XXX |
267 OTRL_INSTAG_BEST, 1, &null, NULL, NULL); |
225 OTRL_INSTAG_BEST, 1, &null, NULL, NULL); |
268 #endif |
|
269 g_free(lowcasebuddy); |
226 g_free(lowcasebuddy); |
270 return ctx; |
227 return ctx; |
271 } |
228 } |
272 |
229 |
273 static void otr_message_disconnect(ConnContext *ctx) |
230 static void otr_message_disconnect(ConnContext *ctx) |
274 { |
231 { |
275 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) |
232 if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) |
276 cb_gone_insecure(NULL, ctx); |
233 cb_gone_insecure(NULL, ctx); |
277 otrl_message_disconnect(userstate, &ops, NULL, ctx->accountname, |
234 otrl_message_disconnect(userstate, &ops, NULL, ctx->accountname, |
278 #ifdef HAVE_LIBOTR3 |
|
279 ctx->protocol, ctx->username); |
|
280 #else |
|
281 // INSTAG XXX |
235 // INSTAG XXX |
282 ctx->protocol, ctx->username, OTRL_INSTAG_BEST); |
236 ctx->protocol, ctx->username, OTRL_INSTAG_BEST); |
283 #endif |
|
284 } |
237 } |
285 |
238 |
286 static void otr_startstop(const char *buddy, int start) |
239 static void otr_startstop(const char *buddy, int start) |
287 { |
240 { |
288 char *msg = NULL; |
241 char *msg = NULL; |
345 scr_LogPrint(LPRINT_LOGNORM, "%s [%44s]: %s", ctx->username, fpr, |
298 scr_LogPrint(LPRINT_LOGNORM, "%s [%44s]: %s", ctx->username, fpr, |
346 tr && *tr ? "trusted" : "untrusted"); |
299 tr && *tr ? "trusted" : "untrusted"); |
347 cb_write_fingerprints(NULL); |
300 cb_write_fingerprints(NULL); |
348 } |
301 } |
349 |
302 |
350 #ifdef HAVE_LIBOTR3 |
|
351 |
|
352 static void otr_handle_smp_tlvs(OtrlTLV *tlvs, ConnContext *ctx) |
|
353 { |
|
354 OtrlTLV *tlv = NULL; |
|
355 char *sbuf = NULL; |
|
356 NextExpectedSMP nextMsg = ctx->smstate->nextExpected; |
|
357 |
|
358 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); |
|
359 if (tlv) { |
|
360 if (nextMsg != OTRL_SMP_EXPECT1) |
|
361 otr_smp_abort(ctx->username); |
|
362 else { |
|
363 sbuf = g_strdup_printf("OTR: Received SMP Initiation. " |
|
364 "Answer with /otr smpr %s $secret", |
|
365 ctx->username); |
|
366 } |
|
367 } |
|
368 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); |
|
369 if (tlv) { |
|
370 if (nextMsg != OTRL_SMP_EXPECT2) |
|
371 otr_smp_abort(ctx->username); |
|
372 else { |
|
373 sbuf = g_strdup("OTR: Received SMP Response."); |
|
374 /* If we received TLV2, we will send TLV3 and expect TLV4 */ |
|
375 ctx->smstate->nextExpected = OTRL_SMP_EXPECT4; |
|
376 } |
|
377 } |
|
378 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); |
|
379 if (tlv) { |
|
380 if (nextMsg != OTRL_SMP_EXPECT3) |
|
381 otr_smp_abort(ctx->username); |
|
382 else { |
|
383 /* If we received TLV3, we will send TLV4 |
|
384 * We will not expect more messages, so prepare for next SMP */ |
|
385 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; |
|
386 /* Report result to user */ |
|
387 if (ctx->active_fingerprint && ctx->active_fingerprint->trust && |
|
388 *ctx->active_fingerprint->trust != '\0') |
|
389 sbuf = g_strdup("OTR: SMP succeeded"); |
|
390 else |
|
391 sbuf = g_strdup("OTR: SMP failed"); |
|
392 } |
|
393 } |
|
394 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); |
|
395 if (tlv) { |
|
396 if (nextMsg != OTRL_SMP_EXPECT4) |
|
397 otr_smp_abort(ctx->username); |
|
398 else { |
|
399 /* We will not expect more messages, so prepare for next SMP */ |
|
400 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; |
|
401 /* Report result to user */ |
|
402 if (ctx->active_fingerprint && ctx->active_fingerprint->trust && |
|
403 *ctx->active_fingerprint->trust != '\0') |
|
404 sbuf = g_strdup("OTR: SMP succeeded"); |
|
405 else |
|
406 sbuf = g_strdup("OTR: SMP failed"); |
|
407 } |
|
408 } |
|
409 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); |
|
410 if (tlv) { |
|
411 /* The message we are waiting for will not arrive, so reset |
|
412 * and prepare for the next SMP */ |
|
413 sbuf = g_strdup("OTR: SMP aborted by your buddy"); |
|
414 ctx->smstate->nextExpected = OTRL_SMP_EXPECT1; |
|
415 } |
|
416 |
|
417 if (sbuf) { |
|
418 scr_WriteIncomingMessage(ctx->username, sbuf, 0, HBB_PREFIX_INFO, 0); |
|
419 g_free(sbuf); |
|
420 } |
|
421 } |
|
422 |
|
423 #else /* HAVE_LIBOTR3 */ |
|
424 |
|
425 static void cb_handle_smp_event(void *opdata, OtrlSMPEvent event, |
303 static void cb_handle_smp_event(void *opdata, OtrlSMPEvent event, |
426 ConnContext *context, unsigned short percent, |
304 ConnContext *context, unsigned short percent, |
427 char *question) |
305 char *question) |
428 { |
306 { |
429 const char *msg = NULL; |
307 const char *msg = NULL; |
563 return 0; |
440 return 0; |
564 |
441 |
565 ignore_message = otrl_message_receiving(userstate, &ops, NULL, |
442 ignore_message = otrl_message_receiving(userstate, &ops, NULL, |
566 ctx->accountname, ctx->protocol, |
443 ctx->accountname, ctx->protocol, |
567 ctx->username, *otr_data, |
444 ctx->username, *otr_data, |
568 #ifdef HAVE_LIBOTR3 |
|
569 &newmessage, &tlvs, NULL, NULL); |
|
570 otr_handle_smp_tlvs(tlvs, ctx); |
|
571 #else |
|
572 &newmessage, &tlvs, NULL, NULL, NULL); |
445 &newmessage, &tlvs, NULL, NULL, NULL); |
573 #endif |
|
574 |
446 |
575 tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); |
447 tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); |
576 if (tlv) { |
448 if (tlv) { |
577 /* Notify the user that the other side disconnected. */ |
449 /* Notify the user that the other side disconnected. */ |
578 cb_gone_insecure(NULL, ctx); |
450 cb_gone_insecure(NULL, ctx); |
617 if (!buddy || !msg || !msg[0]) |
489 if (!buddy || !msg || !msg[0]) |
618 return NULL; |
490 return NULL; |
619 |
491 |
620 if (ctx->msgstate == OTRL_MSGSTATE_PLAINTEXT) |
492 if (ctx->msgstate == OTRL_MSGSTATE_PLAINTEXT) |
621 err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname, |
493 err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname, |
622 #ifdef HAVE_LIBOTR3 |
|
623 ctx->protocol, ctx->username, msg, NULL, |
|
624 &newmessage, NULL, NULL); |
|
625 #else |
|
626 // INSTAG XXX |
494 // INSTAG XXX |
627 ctx->protocol, ctx->username, OTRL_INSTAG_BEST, |
495 ctx->protocol, ctx->username, OTRL_INSTAG_BEST, |
628 msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP, |
496 msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP, |
629 NULL, NULL, NULL); |
497 NULL, NULL, NULL); |
630 #endif |
|
631 else { |
498 else { |
632 err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname, |
499 err = otrl_message_sending(userstate, &ops, NULL, ctx->accountname, |
633 #ifdef HAVE_LIBOTR3 |
|
634 ctx->protocol, ctx->username, msg, NULL, |
|
635 &newmessage, NULL, NULL); |
|
636 #else |
|
637 // INSTAG XXX |
500 // INSTAG XXX |
638 ctx->protocol, ctx->username, OTRL_INSTAG_BEST, |
501 ctx->protocol, ctx->username, OTRL_INSTAG_BEST, |
639 msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP, |
502 msg, NULL, &newmessage, OTRL_FRAGMENT_SEND_SKIP, |
640 NULL, NULL, NULL); |
503 NULL, NULL, NULL); |
641 #endif |
|
642 } |
504 } |
643 |
505 |
644 if (err) |
506 if (err) |
645 return NULL; /* something went wrong, don't send the plain-message! */ |
507 return NULL; /* something went wrong, don't send the plain-message! */ |
646 |
508 |
932 { |
794 { |
933 scr_WriteIncomingMessage(context->username, "OTR: channel reestablished", 0, |
795 scr_WriteIncomingMessage(context->username, "OTR: channel reestablished", 0, |
934 HBB_PREFIX_INFO, 0); |
796 HBB_PREFIX_INFO, 0); |
935 } |
797 } |
936 |
798 |
937 #ifdef HAVE_LIBOTR3 |
|
938 |
|
939 /* Display a notification message for a particular |
|
940 * accountname / protocol / username conversation. */ |
|
941 static void cb_notify(void *opdata, OtrlNotifyLevel level, |
|
942 const char *accountname, const char *protocol, |
|
943 const char *username, const char *title, |
|
944 const char *primary, const char *secondary) |
|
945 { |
|
946 char *type; |
|
947 char *sbuf = NULL; |
|
948 switch (level) { |
|
949 case OTRL_NOTIFY_ERROR: type = "error"; break; |
|
950 case OTRL_NOTIFY_WARNING: type = "warning"; break; |
|
951 case OTRL_NOTIFY_INFO: type = "info"; break; |
|
952 default: type = "unknown"; |
|
953 } |
|
954 sbuf = g_strdup_printf("OTR %s:%s\n%s\n%s",type,title, primary, secondary); |
|
955 scr_WriteIncomingMessage(username, sbuf, 0, HBB_PREFIX_INFO, 0); |
|
956 g_free(sbuf); |
|
957 } |
|
958 |
|
959 /* Display an OTR control message for a particular |
|
960 * accountname / protocol / username conversation. Return 0 if you are able |
|
961 * to successfully display it. If you return non-0 (or if this |
|
962 * function is NULL), the control message will be displayed inline, |
|
963 * as a received message, or else by using the above notify() |
|
964 * callback. */ |
|
965 static int cb_display_otr_message(void *opdata, const char *accountname, |
|
966 const char *protocol, const char *username, |
|
967 const char *msg) |
|
968 { |
|
969 char *strippedmsg = html_strip(msg); |
|
970 scr_WriteIncomingMessage(username, strippedmsg, 0, HBB_PREFIX_INFO, 0); |
|
971 g_free(strippedmsg); |
|
972 return 0; |
|
973 } |
|
974 |
|
975 /* Return a newly allocated string containing a human-friendly name |
|
976 * for the given protocol id */ |
|
977 static const char *cb_protocol_name(void *opdata, const char *protocol) |
|
978 { |
|
979 return protocol; |
|
980 } |
|
981 |
|
982 /* Deallocate a string allocated by protocol_name */ |
|
983 static void cb_protocol_name_free (void *opdata, const char *protocol_name) |
|
984 { |
|
985 /* We didn't allocated memory, so we don't have to free anything :p */ |
|
986 } |
|
987 |
|
988 /* Log a message. The passed message will end in "\n". */ |
|
989 static void cb_log_message(void *opdata, const char *message) |
|
990 { |
|
991 scr_LogPrint(LPRINT_DEBUG, "OTR: %s", message); |
|
992 } |
|
993 |
|
994 #else /* HAVE_LIBOTR3 */ |
|
995 |
|
996 /* Generate unique instance tag for account. */ |
799 /* Generate unique instance tag for account. */ |
997 static void cb_create_instag(void *opdata, const char *accountname, |
800 static void cb_create_instag(void *opdata, const char *accountname, |
998 const char *protocol) |
801 const char *protocol) |
999 { |
802 { |
1000 if (otrl_instag_generate(userstate, tagfile, accountname, protocol)) { |
803 if (otrl_instag_generate(userstate, tagfile, accountname, protocol)) { |