From 81265e00081cd27e52bdb307eae63fe59193c75d Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" Date: Thu, 1 Aug 2013 17:47:48 +0200 Subject: make otr compile with libotr 4.0.0, minimal functionality --- otr.c | 81 ++++++++++++++++++++++++++++++++++++++++--------------------------- otr.h | 4 ++-- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/otr.c b/otr.c index 4417888a..88fdfc3c 100644 --- a/otr.c +++ b/otr.c @@ -7,8 +7,8 @@ /* OTR support (cf. http://www.cypherpunks.ca/otr/) - (c) 2008-2011 Sven Moritz Hallberg - (c) 2008 funded by stonedcoder.org + (c) 2008-2011,2013 Sven Moritz Hallberg + funded by stonedcoder.org files used to store OTR data: /.otr_keys @@ -207,21 +207,30 @@ void init_plugin(void) otr_ops.create_privkey = &op_create_privkey; otr_ops.is_logged_in = &op_is_logged_in; otr_ops.inject_message = &op_inject_message; - otr_ops.notify = NULL; - otr_ops.display_otr_message = &op_display_otr_message; + //XXX otr_ops.display_otr_message = &op_display_otr_message; otr_ops.update_context_list = NULL; - otr_ops.protocol_name = NULL; - otr_ops.protocol_name_free = NULL; otr_ops.new_fingerprint = &op_new_fingerprint; otr_ops.write_fingerprints = &op_write_fingerprints; otr_ops.gone_secure = &op_gone_secure; otr_ops.gone_insecure = &op_gone_insecure; otr_ops.still_secure = &op_still_secure; - otr_ops.log_message = &op_log_message; + //XXX otr_ops.log_message = &op_log_message; otr_ops.max_message_size = &op_max_message_size; otr_ops.account_name = &op_account_name; otr_ops.account_name_free = NULL; - + + /* stuff added with libotr 4.0.0 */ + otr_ops.received_symkey = NULL; /* we don't use the extra key */ + otr_ops.otr_error_message = NULL; // TODO? + otr_ops.otr_error_message_free = NULL; + otr_ops.resent_msg_prefix = NULL; // XXX don't need? + otr_ops.resent_msg_prefix_free = NULL; + otr_ops.handle_smp_event = NULL; // XXX replace smp state machine w/this + otr_ops.handle_msg_event = NULL; // XXX + otr_ops.create_instag = NULL; // XXX + otr_ops.convert_msg = NULL; // XXX other plugins? de/htmlize? + otr_ops.timer_control = NULL; // XXX call otrl_message_poll reg'ly + root_command_add( "otr", 1, cmd_otr, 0 ); register_irc_plugin( &otr_plugin ); } @@ -385,7 +394,7 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) ignore_msg = otrl_message_receiving(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg, - &tlvs, NULL, NULL); + &tlvs, NULL, NULL, NULL); otr_handle_smp(ic, iu->bu->handle, tlvs); @@ -396,9 +405,11 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) /* this was a non-OTR message */ return msg; } else { + /* XXX move this to convert callback */ + /* OTR has processed this message */ ConnContext *context = otrl_context_find(irc->otr->us, iu->bu->handle, - ic->acc->user, ic->acc->prpl->name, 0, NULL, NULL, NULL); + ic->acc->user, ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); /* we're done with the original msg, which will be caller-freed. */ /* NB: must not change the newmsg pointer, since we free it. */ @@ -458,6 +469,7 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) ConnContext *ctx = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; + otrl_instag_t instag = OTRL_INSTAG_MASTER; // XXX? /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ if(ic->acc->prpl->options & OPT_NOOTR) { @@ -466,7 +478,7 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) ctx = otrl_context_find(irc->otr->us, iu->bu->handle, ic->acc->user, ic->acc->prpl->name, - 1, NULL, NULL, NULL); + instag, 1, NULL, NULL, NULL); /* HTML encoding */ /* consider OTR plaintext to be HTML if otr_does_html is set */ @@ -477,8 +489,8 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) } st = otrl_message_sending(irc->otr->us, &otr_ops, ic, - ic->acc->user, ic->acc->prpl->name, iu->bu->handle, - emsg, NULL, &otrmsg, NULL, NULL); + ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, + emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); if(emsg != msg) { g_free(emsg); /* we're done with this one */ } @@ -491,8 +503,8 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) otrl_message_free(otrmsg); return NULL; } - st = otrl_message_fragment_and_send(&otr_ops, ic, ctx, - otrmsg, OTRL_FRAGMENT_SEND_ALL, NULL); + otr_ops.inject_message(ic, ctx->accountname, + ctx->protocol, ctx->username, otrmsg); otrl_message_free(otrmsg); } else { /* note: otrl_message_sending handles policy, so that if REQUIRE_ENCRYPTION is set, @@ -773,19 +785,24 @@ void cmd_otr_disconnect(irc_t *irc, char **args) return; } - otrl_message_disconnect(irc->otr->us, &otr_ops, + /* XXX we disconnect all instances; is that what we want? */ + otrl_message_disconnect_all_instances(irc->otr->us, &otr_ops, u->bu->ic, u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, u->bu->handle); - /* for some reason, libotr (3.1.0) doesn't do this itself: */ - if(u->flags & IRC_USER_OTR_ENCRYPTED) { - ConnContext *ctx; - ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); - if(ctx) - op_gone_insecure(u->bu->ic, ctx); - else /* huh? */ - u->flags &= ( IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED ); + /* for some reason, libotr (4.0.0) doesn't do this itself: */ + if(!(u->flags & IRC_USER_OTR_ENCRYPTED)) + return; + + ConnContext *ctx, *p; + ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); + if(!ctx) { /* huh? */ + u->flags &= ( IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED ); + return; } + + for(p=ctx; p && p->m_context == ctx->m_context; p=p->next) + op_gone_insecure(u->bu->ic, p); } void cmd_otr_connect(irc_t *irc, char **args) @@ -830,7 +847,7 @@ void cmd_otr_trust(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX if(!ctx) { irc_rootmsg(irc, "%s: no otr context with user", args[1]); return; @@ -894,7 +911,7 @@ void cmd_otr_info(irc_t *irc, char **args) if(protocol && myhandle) { *(myhandle++) = '\0'; handle = arg; - ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, NULL, NULL, NULL); + ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, OTRL_INSTAG_MASTER, NULL, NULL, NULL); // XXX if(!ctx) { irc_rootmsg(irc, "no such context"); g_free(arg); @@ -908,7 +925,7 @@ void cmd_otr_info(irc_t *irc, char **args) return; } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[1]); g_free(arg); @@ -1027,7 +1044,7 @@ void cmd_otr_forget(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; @@ -1070,7 +1087,7 @@ void cmd_otr_forget(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; @@ -1133,7 +1150,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) bu = bee_user_by_handle(ic->bee, ic, handle); if(!bu || !(u = bu->ui_data)) return; context = otrl_context_find(us, handle, - ic->acc->user, ic->acc->prpl->name, 1, NULL, NULL, NULL); + ic->acc->user, ic->acc->prpl->name, OTRL_INSTAG_MASTER, 1, NULL, NULL, NULL); if(!context) { /* huh? out of memory or what? */ irc_rootmsg(irc, "smp: failed to get otr context for %s", u->nick); @@ -1265,7 +1282,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, } ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" " %s\x02", nick, nick); diff --git a/otr.h b/otr.h index 41f54585..ace2c956 100644 --- a/otr.h +++ b/otr.h @@ -7,8 +7,8 @@ /* OTR support (cf. http://www.cypherpunks.ca/otr/) - 2008, Sven Moritz Hallberg - (c) and funded by stonedcoder.org + (c) 2008,2013 Sven Moritz Hallberg + funded by stonedcoder.org */ /* -- cgit v1.2.3 From 5d2bc9dfec01f717068b1a38e538c46c2f7e1e70 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Aug 2013 20:17:02 +0200 Subject: move html coding and coloring into convert callback --- otr.c | 161 ++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 78 insertions(+), 83 deletions(-) diff --git a/otr.c b/otr.c index 88fdfc3c..b6141183 100644 --- a/otr.c +++ b/otr.c @@ -79,6 +79,10 @@ int op_max_message_size(void *opdata, ConnContext *context); const char *op_account_name(void *opdata, const char *account, const char *protocol); +void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, + char **dst, const char *src); +void op_convert_free(void *opdata, ConnContext *ctx, char *msg); + /** otr sub-command handlers: **/ @@ -228,7 +232,8 @@ void init_plugin(void) otr_ops.handle_smp_event = NULL; // XXX replace smp state machine w/this otr_ops.handle_msg_event = NULL; // XXX otr_ops.create_instag = NULL; // XXX - otr_ops.convert_msg = NULL; // XXX other plugins? de/htmlize? + otr_ops.convert_msg = &op_convert_msg; + otr_ops.convert_free = &op_convert_free; otr_ops.timer_control = NULL; // XXX call otrl_message_poll reg'ly root_command_add( "otr", 1, cmd_otr, 0 ); @@ -405,59 +410,8 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) /* this was a non-OTR message */ return msg; } else { - /* XXX move this to convert callback */ - - /* OTR has processed this message */ - ConnContext *context = otrl_context_find(irc->otr->us, iu->bu->handle, - ic->acc->user, ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - /* we're done with the original msg, which will be caller-freed. */ - /* NB: must not change the newmsg pointer, since we free it. */ - msg = newmsg; - - if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { - /* HTML decoding */ - /* perform any necessary stripping that the top level would miss */ - if(set_getbool(&ic->bee->set, "otr_does_html") && - !(ic->flags & OPT_DOES_HTML) && - set_getbool(&ic->bee->set, "strip_html")) { - strip_html(msg); - } - - /* coloring */ - if(set_getbool(&ic->bee->set, "otr_color_encrypted")) { - int color; /* color according to f'print trust */ - char *pre="", *sep=""; /* optional parts */ - const char *trust = context->active_fingerprint->trust; - - if(trust && trust[0] != '\0') - color=3; /* green */ - else - color=5; /* red */ - - /* in a query window, keep "/me " uncolored at the beginning */ - if(g_strncasecmp(msg, "/me ", 4) == 0 - && irc_user_msgdest(iu) == irc->user->nick) { - msg += 4; /* skip */ - pre = "/me "; - } - - /* comma in first place could mess with the color code */ - if(msg[0] == ',') { - /* insert a space between color spec and message */ - sep = " "; - } - - msg = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, - color, sep, msg); - } - } - - if(msg == newmsg) { - msg = g_strdup(newmsg); - } - otrl_message_free(newmsg); - return msg; + return newmsg; } } @@ -476,43 +430,20 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) return msg; } - ctx = otrl_context_find(irc->otr->us, - iu->bu->handle, ic->acc->user, ic->acc->prpl->name, - instag, 1, NULL, NULL, NULL); - - /* HTML encoding */ - /* consider OTR plaintext to be HTML if otr_does_html is set */ - if(ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED && - set_getbool(&ic->bee->set, "otr_does_html") && - (g_strncasecmp(msg, "", 6) != 0)) { - emsg = escape_html(msg); - } - st = otrl_message_sending(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, - emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); + emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL, &ctx, NULL, NULL); + if(emsg != msg) { g_free(emsg); /* we're done with this one */ } - if(st) { - return NULL; - } - if(otrmsg) { - if(!ctx) { - otrl_message_free(otrmsg); - return NULL; - } - otr_ops.inject_message(ic, ctx->accountname, - ctx->protocol, ctx->username, otrmsg); - otrl_message_free(otrmsg); - } else { - /* note: otrl_message_sending handles policy, so that if REQUIRE_ENCRYPTION is set, - this case does not occur */ - return msg; + /* Is this ever reached!? */ + ic->acc->prpl->buddy_msg(ic, iu->bu->handle, otrmsg, 0); + } + if(st) { + /* TODO: Error reporting? */ } - - /* TODO: Error reporting should be done here now (if st!=0), probably. */ return NULL; } @@ -766,6 +697,70 @@ const char *op_account_name(void *opdata, const char *account, const char *proto return peernick(irc, account, protocol); } +void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, + char **dst, const char *src) +{ + struct im_connection *ic = + check_imc(opdata, ctx->accountname, ctx->protocol); + irc_t *irc = ic->bee->ui_data; + irc_user_t *iu = peeruser(irc, ctx->username, ctx->protocol); + + if(typ == OTRL_CONVERT_RECEIVING) { + char *msg = g_strdup(src); + + /* HTML decoding */ + if(set_getbool(&ic->bee->set, "otr_does_html") && + !(ic->flags & OPT_DOES_HTML) && + set_getbool(&ic->bee->set, "strip_html")) { + strip_html(msg); + *dst = msg; + } + + /* coloring */ + if(set_getbool(&ic->bee->set, "otr_color_encrypted")) { + int color; /* color according to f'print trust */ + char *pre="", *sep=""; /* optional parts */ + const char *trust = ctx->active_fingerprint->trust; + + if(trust && trust[0] != '\0') + color=3; /* green */ + else + color=5; /* red */ + + /* in a query window, keep "/me " uncolored at the beginning */ + if(g_strncasecmp(msg, "/me ", 4) == 0 + && irc_user_msgdest(iu) == irc->user->nick) { + msg += 4; /* skip */ + pre = "/me "; + } + + /* comma in first place could mess with the color code */ + if(msg[0] == ',') { + /* insert a space between color spec and message */ + sep = " "; + } + + *dst = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, + color, sep, msg); + g_free(msg); + } + } else { + /* HTML encoding */ + /* consider OTR plaintext to be HTML if otr_does_html is set */ + if(ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED && + set_getbool(&ic->bee->set, "otr_does_html") && + (g_strncasecmp(src, "", 6) != 0)) { + *dst = escape_html(src); + } + } +} + +void op_convert_free(void *opdata, ConnContext *ctx, char *msg) +{ + g_free(msg); +} + + /*** OTR sub-command handlers ***/ -- cgit v1.2.3 From 352a6b0bd8ecb0d6dcb32c4f4b767fcd315fdf06 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Aug 2013 21:32:24 +0200 Subject: update smp event handling --- otr.c | 209 +++++++++++++++++++++++------------------------------------------- 1 file changed, 72 insertions(+), 137 deletions(-) diff --git a/otr.c b/otr.c index b6141183..cbabd702 100644 --- a/otr.c +++ b/otr.c @@ -83,6 +83,8 @@ void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, char **dst, const char *src); void op_convert_free(void *opdata, ConnContext *ctx, char *msg); +void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, + unsigned short percent, char *question); /** otr sub-command handlers: **/ @@ -159,9 +161,6 @@ int hexval(char a); returns NULL if not found */ irc_user_t *peeruser(irc_t *irc, const char *handle, const char *protocol); -/* handle SMP TLVs from a received message */ -void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs); - /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, const char *secret); @@ -227,9 +226,9 @@ void init_plugin(void) otr_ops.received_symkey = NULL; /* we don't use the extra key */ otr_ops.otr_error_message = NULL; // TODO? otr_ops.otr_error_message_free = NULL; - otr_ops.resent_msg_prefix = NULL; // XXX don't need? + otr_ops.resent_msg_prefix = NULL; // don't need? otr_ops.resent_msg_prefix_free = NULL; - otr_ops.handle_smp_event = NULL; // XXX replace smp state machine w/this + otr_ops.handle_smp_event = &op_handle_smp_event; otr_ops.handle_msg_event = NULL; // XXX otr_ops.create_instag = NULL; // XXX otr_ops.convert_msg = &op_convert_msg; @@ -401,8 +400,6 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg, &tlvs, NULL, NULL, NULL); - otr_handle_smp(ic, iu->bu->handle, tlvs); - if(ignore_msg) { /* this was an internal OTR protocol message */ return NULL; @@ -760,6 +757,73 @@ void op_convert_free(void *opdata, ConnContext *ctx, char *msg) g_free(msg); } +/* Socialist Millionaires' Protocol */ +void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, + unsigned short percent, char *question) +{ + struct im_connection *ic = + check_imc(opdata, ctx->accountname, ctx->protocol); + irc_t *irc = ic->bee->ui_data; + OtrlUserState us = irc->otr->us; + irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); + + if(!u) return; + + switch(ev) { + case OTRL_SMPEVENT_ASK_FOR_SECRET: + irc_rootmsg(irc, "smp: initiated by %s" + " - respond with \x02otr smp %s \x02", + u->nick, u->nick); + break; + case OTRL_SMPEVENT_ASK_FOR_ANSWER: + irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, + question); + irc_rootmsg(irc, "smp: respond with \x02otr smp %s \x02", + u->nick); + break; + case OTRL_SMPEVENT_CHEATED: + irc_rootmsg(irc, "smp %s: opponent violated protocol, aborting", + u->nick); + otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); + otrl_sm_state_free(ctx->smstate); + break; + case OTRL_SMPEVENT_NONE: + break; + case OTRL_SMPEVENT_IN_PROGRESS: + break; + case OTRL_SMPEVENT_SUCCESS: + if(ctx->smstate->received_question) { + irc_rootmsg(irc, "smp %s: correct answer, you are trusted", + u->nick); + } else { + irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", + u->nick); + } + otrl_sm_state_free(ctx->smstate); + break; + case OTRL_SMPEVENT_FAILURE: + if(ctx->smstate->received_question) { + irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", + u->nick); + } else { + irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", + u->nick); + } + otrl_sm_state_free(ctx->smstate); + break; + case OTRL_SMPEVENT_ABORT: + irc_rootmsg(irc, "smp: received abort from %s", u->nick); + otrl_sm_state_free(ctx->smstate); + break; + case OTRL_SMPEVENT_ERROR: + irc_rootmsg(irc, "smp %s: protocol error, aborting", + u->nick); + otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); + otrl_sm_state_free(ctx->smstate); + break; + } +} + /*** OTR sub-command handlers ***/ @@ -1130,135 +1194,6 @@ void cmd_otr_forget(irc_t *irc, char **args) /*** local helpers / subroutines: ***/ -/* Socialist Millionaires' Protocol */ -void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) -{ - irc_t *irc = ic->bee->ui_data; - OtrlUserState us = irc->otr->us; - OtrlMessageAppOps *ops = &otr_ops; - OtrlTLV *tlv = NULL; - ConnContext *context; - NextExpectedSMP nextMsg; - irc_user_t *u; - bee_user_t *bu; - - bu = bee_user_by_handle(ic->bee, ic, handle); - if(!bu || !(u = bu->ui_data)) return; - context = otrl_context_find(us, handle, - ic->acc->user, ic->acc->prpl->name, OTRL_INSTAG_MASTER, 1, NULL, NULL, NULL); - if(!context) { - /* huh? out of memory or what? */ - irc_rootmsg(irc, "smp: failed to get otr context for %s", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - return; - } - nextMsg = context->smstate->nextExpected; - - if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { - irc_rootmsg(irc, "smp %s: opponent violated protocol, aborting", - u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - return; - } - - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT1) { - irc_rootmsg(irc, "smp %s: spurious SMP1Q received, aborting", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - } else { - char *question = g_strndup((char *)tlv->data, tlv->len); - irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, - question); - irc_rootmsg(irc, "smp: respond with \x02otr smp %s \x02", - u->nick); - g_free(question); - /* smp stays in EXPECT1 until user responds */ - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT1) { - irc_rootmsg(irc, "smp %s: spurious SMP1 received, aborting", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - } else { - irc_rootmsg(irc, "smp: initiated by %s" - " - respond with \x02otr smp %s \x02", - u->nick, u->nick); - /* smp stays in EXPECT1 until user responds */ - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT2) { - irc_rootmsg(irc, "smp %s: spurious SMP2 received, aborting", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - } else { - /* SMP2 received, otrl_message_receiving will have sent SMP3 */ - context->smstate->nextExpected = OTRL_SMP_EXPECT4; - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT3) { - irc_rootmsg(irc, "smp %s: spurious SMP3 received, aborting", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - } else { - /* SMP3 received, otrl_message_receiving will have sent SMP4 */ - if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { - if(context->smstate->received_question) { - irc_rootmsg(irc, "smp %s: correct answer, you are trusted", - u->nick); - } else { - irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", - u->nick); - } - } else { - if(context->smstate->received_question) { - irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", - u->nick); - } else { - irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", - u->nick); - } - } - otrl_sm_state_free(context->smstate); - /* smp is in back in EXPECT1 */ - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT4) { - irc_rootmsg(irc, "smp %s: spurious SMP4 received, aborting", u->nick); - otrl_message_abort_smp(us, ops, u->bu->ic, context); - otrl_sm_state_free(context->smstate); - } else { - /* SMP4 received, otrl_message_receiving will have set fp trust */ - if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { - irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", - u->nick); - } else { - irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", - u->nick); - } - otrl_sm_state_free(context->smstate); - /* smp is in back in EXPECT1 */ - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); - if (tlv) { - irc_rootmsg(irc, "smp: received abort from %s", u->nick); - otrl_sm_state_free(context->smstate); - /* smp is in back in EXPECT1 */ - } -} - /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, const char *secret) @@ -1277,7 +1212,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, } ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" " %s\x02", nick, nick); -- cgit v1.2.3 From 090c9b786284d1e2c6f37195aa56fd528f08b2f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Aug 2013 22:39:49 +0200 Subject: implement handle_msg_event --- otr.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 102 insertions(+), 35 deletions(-) diff --git a/otr.c b/otr.c index cbabd702..d3c4ee5f 100644 --- a/otr.c +++ b/otr.c @@ -59,9 +59,6 @@ int op_is_logged_in(void *opdata, const char *accountname, const char *protocol, void op_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message); -int op_display_otr_message(void *opdata, const char *accountname, const char *protocol, - const char *username, const char *msg); - void op_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]); @@ -86,6 +83,9 @@ void op_convert_free(void *opdata, ConnContext *ctx, char *msg); void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, unsigned short percent, char *question); +void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, + const char *message, gcry_error_t err); + /** otr sub-command handlers: **/ static void cmd_otr(irc_t *irc, char **args); @@ -161,6 +161,12 @@ int hexval(char a); returns NULL if not found */ irc_user_t *peeruser(irc_t *irc, const char *handle, const char *protocol); +/* show an otr-related message to the user */ +void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...); + +/* write an otr-related message to the system log */ +void log_otr_message(void *opdata, const char *fmt, ...); + /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, const char *secret); @@ -210,14 +216,12 @@ void init_plugin(void) otr_ops.create_privkey = &op_create_privkey; otr_ops.is_logged_in = &op_is_logged_in; otr_ops.inject_message = &op_inject_message; - //XXX otr_ops.display_otr_message = &op_display_otr_message; otr_ops.update_context_list = NULL; otr_ops.new_fingerprint = &op_new_fingerprint; otr_ops.write_fingerprints = &op_write_fingerprints; otr_ops.gone_secure = &op_gone_secure; otr_ops.gone_insecure = &op_gone_insecure; otr_ops.still_secure = &op_still_secure; - //XXX otr_ops.log_message = &op_log_message; otr_ops.max_message_size = &op_max_message_size; otr_ops.account_name = &op_account_name; otr_ops.account_name_free = NULL; @@ -229,7 +233,7 @@ void init_plugin(void) otr_ops.resent_msg_prefix = NULL; // don't need? otr_ops.resent_msg_prefix_free = NULL; otr_ops.handle_smp_event = &op_handle_smp_event; - otr_ops.handle_msg_event = NULL; // XXX + otr_ops.handle_msg_event = &op_handle_msg_event; otr_ops.create_instag = NULL; // XXX otr_ops.convert_msg = &op_convert_msg; otr_ops.convert_free = &op_convert_free; @@ -559,26 +563,6 @@ void op_inject_message(void *opdata, const char *accountname, } } -int op_display_otr_message(void *opdata, const char *accountname, - const char *protocol, const char *username, const char *message) -{ - struct im_connection *ic = check_imc(opdata, accountname, protocol); - char *msg = g_strdup(message); - irc_t *irc = ic->bee->ui_data; - irc_user_t *u = peeruser(irc, username, protocol); - - strip_html(msg); - if(u) { - /* display as a notice from this particular user */ - irc_usernotice(u, "%s", msg); - } else { - irc_rootmsg(irc, "[otr] %s", msg); - } - - g_free(msg); - return 0; -} - void op_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) @@ -669,15 +653,6 @@ void op_still_secure(void *opdata, ConnContext *context, int is_reply) } } -void op_log_message(void *opdata, const char *message) -{ - char *msg = g_strdup(message); - - strip_html(msg); - log_message(LOGLVL_INFO, "otr: %s", msg); - g_free(msg); -} - int op_max_message_size(void *opdata, ConnContext *context) { struct im_connection *ic = @@ -824,6 +799,65 @@ void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, } } +void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, + const char *message, gcry_error_t err) +{ + switch(ev) { + case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: + display_otr_message(opdata, ctx, + "policy requires encryption - message not sent"); + break; + case OTRL_MSGEVENT_ENCRYPTION_ERROR: + display_otr_message(opdata, ctx, + "error during encryption - message not sent"); + break; + case OTRL_MSGEVENT_CONNECTION_ENDED: + display_otr_message(opdata, ctx, + "other end has disconnected OTR - " + "close connection or reconnect!"); + break; + case OTRL_MSGEVENT_SETUP_ERROR: + display_otr_message(opdata, ctx, + "OTR connection failed: %s", gcry_strerror(err)); + break; + case OTRL_MSGEVENT_MSG_REFLECTED: + display_otr_message(opdata, ctx, + "received our own OTR message (!?)"); + break; + case OTRL_MSGEVENT_MSG_RESENT: + display_otr_message(opdata, ctx, + "the previous message was resent"); + break; + case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: + display_otr_message(opdata, ctx, + "unexpected encrypted message received"); + break; + case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: + display_otr_message(opdata, ctx, + "unreadable encrypted message received"); + break; + case OTRL_MSGEVENT_RCVDMSG_MALFORMED: + display_otr_message(opdata, ctx, + "malformed OTR message received"); + break; + case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: + display_otr_message(opdata, ctx, + "OTR error message received: %s", message); + break; + case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED: + display_otr_message(opdata, ctx, + "unencrypted message received: %s", message); + break; + case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: + display_otr_message(opdata, ctx, + "unrecognized OTR message received"); + break; + default: + /* ignore XXX log? */ + break; + } +} + /*** OTR sub-command handlers ***/ @@ -1194,6 +1228,39 @@ void cmd_otr_forget(irc_t *irc, char **args) /*** local helpers / subroutines: ***/ +void log_otr_message(void *opdata, const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + char *msg = g_strdup_vprintf(fmt, va); + va_end(va); + + log_message(LOGLVL_INFO, "otr: %s", msg); +} + +void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...) +{ + struct im_connection *ic = + check_imc(opdata, ctx->accountname, ctx->protocol); + irc_t *irc = ic->bee->ui_data; + irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); + va_list va; + + va_start(va, fmt); + char *msg = g_strdup_vprintf(fmt, va); + va_end(va); + + if(u) { + /* display as a notice from this particular user */ + irc_usernotice(u, "%s", msg); + } else { + irc_rootmsg(irc, "[otr] %s", msg); + } + + g_free(msg); +} + /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, const char *secret) -- cgit v1.2.3 From b939cff59bfd94243bcde994232c72e5b9e8e8c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 12:48:03 +0200 Subject: work around libotr bugs --- otr.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/otr.c b/otr.c index d3c4ee5f..eddb8ce6 100644 --- a/otr.c +++ b/otr.c @@ -434,14 +434,13 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) st = otrl_message_sending(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL, &ctx, NULL, NULL); + /* in libotr 4.0.0 with OTRL_FRAGMENT_SEND_ALL, otrmsg must be passed + * but the value it gets carries no meaning. it can be set even though + * the message has been injected. */ if(emsg != msg) { g_free(emsg); /* we're done with this one */ } - if(otrmsg) { - /* Is this ever reached!? */ - ic->acc->prpl->buddy_msg(ic, iu->bu->handle, otrmsg, 0); - } if(st) { /* TODO: Error reporting? */ } @@ -655,9 +654,15 @@ void op_still_secure(void *opdata, ConnContext *context, int is_reply) int op_max_message_size(void *opdata, ConnContext *context) { + /* libotr 4.0.0 has a bug where it doesn't set opdata */ + if(!opdata) { + /* crude fallback */ + return 800; + } + struct im_connection *ic = check_imc(opdata, context->accountname, context->protocol); - + return ic->acc->prpl->mms; } -- cgit v1.2.3 From 6d9f0ba48e127bbc9050d674772248b915f9fe35 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 13:15:21 +0200 Subject: implement otr_error_message callback --- otr.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/otr.c b/otr.c index eddb8ce6..3c14b751 100644 --- a/otr.c +++ b/otr.c @@ -86,6 +86,9 @@ void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, const char *message, gcry_error_t err); +const char *op_otr_error_message(void *opdata, ConnContext *ctx, + OtrlErrorCode err_code); + /** otr sub-command handlers: **/ static void cmd_otr(irc_t *irc, char **args); @@ -228,9 +231,9 @@ void init_plugin(void) /* stuff added with libotr 4.0.0 */ otr_ops.received_symkey = NULL; /* we don't use the extra key */ - otr_ops.otr_error_message = NULL; // TODO? + otr_ops.otr_error_message = &op_otr_error_message; otr_ops.otr_error_message_free = NULL; - otr_ops.resent_msg_prefix = NULL; // don't need? + otr_ops.resent_msg_prefix = NULL; /* default: [resent] */ otr_ops.resent_msg_prefix_free = NULL; otr_ops.handle_smp_event = &op_handle_smp_event; otr_ops.handle_msg_event = &op_handle_msg_event; @@ -863,6 +866,23 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, } } +const char *op_otr_error_message(void *opdata, ConnContext *ctx, + OtrlErrorCode err_code) +{ + switch(err_code) { + case OTRL_ERRCODE_ENCRYPTION_ERROR: + return "i failed to encrypt a message"; + case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE: + return "you sent an encrypted message i didn't expect"; + case OTRL_ERRCODE_MSG_UNREADABLE: + return "could not read encrypted message"; + case OTRL_ERRCODE_MSG_MALFORMED: + return "you sent a malformed OTR message"; + default: + return "i suffered an unexpected OTR error"; + } +} + /*** OTR sub-command handlers ***/ -- cgit v1.2.3 From 22ec21d76219508284af193d37cc4a2cbab65e7d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 13:52:22 +0200 Subject: regularly call otrl_message_poll --- otr.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/otr.c b/otr.c index 3c14b751..1637812a 100644 --- a/otr.c +++ b/otr.c @@ -149,6 +149,9 @@ void yes_forget_fingerprint(void *data); void yes_forget_context(void *data); void yes_forget_key(void *data); +/* timeout handler that calls otrl_message_poll */ +gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond); + /* helper to make sure accountname and protocol match the incoming "opdata" */ struct im_connection *check_imc(void *opdata, const char *accountname, const char *protocol); @@ -240,7 +243,7 @@ void init_plugin(void) otr_ops.create_instag = NULL; // XXX otr_ops.convert_msg = &op_convert_msg; otr_ops.convert_free = &op_convert_free; - otr_ops.timer_control = NULL; // XXX call otrl_message_poll reg'ly + otr_ops.timer_control = NULL; /* we just poll */ root_command_add( "otr", 1, cmd_otr, 0 ); register_irc_plugin( &otr_plugin ); @@ -265,6 +268,10 @@ gboolean otr_irc_new(irc_t *irc) s = set_add( &irc->b->set, "otr_does_html", "true", set_eval_bool, irc ); + /* regularly call otrl_message_poll */ + gint definterval = otrl_message_poll_get_default_interval(irc->otr->us); + b_timeout_add(definterval, ev_message_poll, irc->otr); + return TRUE; } @@ -1345,6 +1352,16 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, } } +/* timeout handler that calls otrl_message_poll */ +gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond) +{ + otr_t *otr = data; + + otrl_message_poll(otr->us, &otr_ops, NULL); + + return TRUE; /* cycle timer */ +} + /* helper to assert that account and protocol names given to ops below always match the im_connection passed through as opdata */ struct im_connection *check_imc(void *opdata, const char *accountname, -- cgit v1.2.3 From fa9478ea664824841c013615c0c4b324c8c78c0a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 17:30:11 +0200 Subject: better workaround for libotr's NULL opdata bug --- otr.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/otr.c b/otr.c index 1637812a..94b2134a 100644 --- a/otr.c +++ b/otr.c @@ -664,12 +664,6 @@ void op_still_secure(void *opdata, ConnContext *context, int is_reply) int op_max_message_size(void *opdata, ConnContext *context) { - /* libotr 4.0.0 has a bug where it doesn't set opdata */ - if(!opdata) { - /* crude fallback */ - return 800; - } - struct im_connection *ic = check_imc(opdata, context->accountname, context->protocol); @@ -1369,6 +1363,19 @@ struct im_connection *check_imc(void *opdata, const char *accountname, { struct im_connection *ic = (struct im_connection *)opdata; + /* libotr 4.0.0 has a bug where it doesn't set opdata, so we catch + * that and try to find the desired connection in the global list. */ + if(!ic) { + GSList *l; + for(l=get_connections(); l; l=l->next) { + ic = l->data; + if(strcmp(accountname, ic->acc->user) == 0 && + strcmp(protocol, ic->acc->prpl->name) == 0) + break; + } + assert(l != NULL); /* a match should always be found */ + } + if (strcmp(accountname, ic->acc->user) != 0) { log_message(LOGLVL_WARNING, "otr: internal account name mismatch: '%s' vs '%s'", -- cgit v1.2.3 From 37ed402c7c34c56f9a8d352a67dc15f48906adbf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 20:08:34 +0200 Subject: use INSTAG_RECENT for outgoing messages --- otr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/otr.c b/otr.c index 94b2134a..dc4ceb98 100644 --- a/otr.c +++ b/otr.c @@ -434,7 +434,7 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) ConnContext *ctx = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; - otrl_instag_t instag = OTRL_INSTAG_MASTER; // XXX? + otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX? /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ if(ic->acc->prpl->options & OPT_NOOTR) { @@ -1374,6 +1374,8 @@ struct im_connection *check_imc(void *opdata, const char *accountname, break; } assert(l != NULL); /* a match should always be found */ + if(!l) + return NULL; } if (strcmp(accountname, ic->acc->user) != 0) { -- cgit v1.2.3 From f93e01c92315427c2b8f8c7d03e0ce337e2e80b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 20:31:44 +0200 Subject: some more instag updates --- otr.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/otr.c b/otr.c index dc4ceb98..29bb6421 100644 --- a/otr.c +++ b/otr.c @@ -966,7 +966,7 @@ void cmd_otr_trust(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx) { irc_rootmsg(irc, "%s: no otr context with user", args[1]); return; @@ -1030,7 +1030,7 @@ void cmd_otr_info(irc_t *irc, char **args) if(protocol && myhandle) { *(myhandle++) = '\0'; handle = arg; - ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, OTRL_INSTAG_MASTER, NULL, NULL, NULL); // XXX + ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx) { irc_rootmsg(irc, "no such context"); g_free(arg); @@ -1044,7 +1044,7 @@ void cmd_otr_info(irc_t *irc, char **args) return; } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[1]); g_free(arg); @@ -1117,6 +1117,8 @@ void yes_forget_context(void *data) ConnContext *ctx = (ConnContext *)p->snd; g_free(p); + + // XXX forget all contexts if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "active otr connection with %s, terminate it first", @@ -1163,7 +1165,7 @@ void cmd_otr_forget(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; @@ -1206,7 +1208,7 @@ void cmd_otr_forget(irc_t *irc, char **args) } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); if(!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; @@ -1293,6 +1295,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, { irc_user_t *u; ConnContext *ctx; + otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX u = irc_user_by_name(irc, nick); if(!u || !u->bu || !u->bu->ic) { @@ -1305,7 +1308,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, } ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); // XXX + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, instag, 0, NULL, NULL, NULL); if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" " %s\x02", nick, nick); @@ -1686,6 +1689,8 @@ void show_general_otr_info(irc_t *irc) void show_otr_context_info(irc_t *irc, ConnContext *ctx) { + // XXX show all contexts + switch(ctx->otr_offer) { case OFFER_NOT: irc_rootmsg(irc, " otr offer status: none sent"); -- cgit v1.2.3 From c347a1225f8a114ff540a38fed31c5543b4d9fcc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 22:55:16 +0200 Subject: timer cleanup and "other instance" error message --- otr.c | 10 ++++++++-- otr.h | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/otr.c b/otr.c index 29bb6421..6fdaa43b 100644 --- a/otr.c +++ b/otr.c @@ -270,7 +270,7 @@ gboolean otr_irc_new(irc_t *irc) /* regularly call otrl_message_poll */ gint definterval = otrl_message_poll_get_default_interval(irc->otr->us); - b_timeout_add(definterval, ev_message_poll, irc->otr); + irc->otr->timer = b_timeout_add(definterval, ev_message_poll, irc->otr); return TRUE; } @@ -278,6 +278,7 @@ gboolean otr_irc_new(irc_t *irc) void otr_irc_free(irc_t *irc) { otr_t *otr = irc->otr; + b_event_remove(otr->timer); otrl_userstate_free(otr->us); if(otr->keygen) { kill(otr->keygen, SIGTERM); @@ -845,6 +846,10 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, display_otr_message(opdata, ctx, "unreadable encrypted message received"); break; + case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: + display_otr_message(opdata, ctx, + "OTR message for a different instance received"); + break; case OTRL_MSGEVENT_RCVDMSG_MALFORMED: display_otr_message(opdata, ctx, "malformed OTR message received"); @@ -1354,7 +1359,8 @@ gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond) { otr_t *otr = data; - otrl_message_poll(otr->us, &otr_ops, NULL); + if(otr && otr->us) + otrl_message_poll(otr->us, &otr_ops, NULL); return TRUE; /* cycle timer */ } diff --git a/otr.h b/otr.h index ace2c956..3962097e 100644 --- a/otr.h +++ b/otr.h @@ -65,6 +65,9 @@ typedef struct otr { /* keygen jobs waiting to be sent to slave */ kg_t *todo; + + /* event timer for otrl_message_poll */ + gint timer; } otr_t; /* called from main() */ -- cgit v1.2.3 From fbcb48126238e224ca0eef324136dc20868e428b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Aug 2013 23:59:43 +0200 Subject: do 'otr connect' with the proper query message (generated by libotr) --- otr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/otr.c b/otr.c index 6fdaa43b..c5b1d3a4 100644 --- a/otr.c +++ b/otr.c @@ -943,7 +943,9 @@ void cmd_otr_connect(irc_t *irc, char **args) return; } - bee_user_msg(irc->b, u->bu, "?OTR?v2?", 0); + /* passing this through the filter so it goes through libotr which + * will replace the simple query string with a proper one */ + otr_filter_msg_out(u, "?OTR?", 0); } void cmd_otr_smp(irc_t *irc, char **args) -- cgit v1.2.3 From e65039a9b52902758385a46f8baa4b2395d09636 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 Aug 2013 14:49:03 +0200 Subject: persist instags (also works around "malformed message" bug) --- otr.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/otr.c b/otr.c index c5b1d3a4..aaa04f4f 100644 --- a/otr.c +++ b/otr.c @@ -76,6 +76,8 @@ int op_max_message_size(void *opdata, ConnContext *context); const char *op_account_name(void *opdata, const char *account, const char *protocol); +void op_create_instag(void *opdata, const char *account, const char *protocol); + void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, char **dst, const char *src); void op_convert_free(void *opdata, ConnContext *ctx, char *msg); @@ -240,7 +242,7 @@ void init_plugin(void) otr_ops.resent_msg_prefix_free = NULL; otr_ops.handle_smp_event = &op_handle_smp_event; otr_ops.handle_msg_event = &op_handle_msg_event; - otr_ops.create_instag = NULL; // XXX + otr_ops.create_instag = &op_create_instag; otr_ops.convert_msg = &op_convert_msg; otr_ops.convert_free = &op_convert_free; otr_ops.timer_control = NULL; /* we just poll */ @@ -316,6 +318,11 @@ void otr_load(irc_t *irc) if(e && e!=enoent) { irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); } + g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, irc->user->nick); + e = otrl_instag_read(irc->otr->us, s); + if(e && e!=enoent) { + irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + } } /* check for otr keys on all accounts */ @@ -679,6 +686,23 @@ const char *op_account_name(void *opdata, const char *account, const char *proto return peernick(irc, account, protocol); } +void op_create_instag(void *opdata, const char *account, const char *protocol) +{ + struct im_connection *ic = + check_imc(opdata, account, protocol); + irc_t *irc = ic->bee->ui_data; + gcry_error_t e; + char s[512]; + + g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, + irc->user->nick); + e = otrl_instag_generate(irc->otr->us, s, account, protocol); + if(e) { + irc_rootmsg(irc, "otr: %s/%s: otrl_instag_generate failed: %s", + account, protocol, gcry_strerror(e)); + } +} + void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, char **dst, const char *src) { -- cgit v1.2.3 From e4752a6162d27e7292df912ab3bbf71f214e6cce Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 Aug 2013 15:06:30 +0200 Subject: cleanup and docs --- otr.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/otr.c b/otr.c index aaa04f4f..80f1786c 100644 --- a/otr.c +++ b/otr.c @@ -13,11 +13,13 @@ files used to store OTR data: /.otr_keys /.otr_fprints + /.otr_instags <- don't copy this one between hosts top-level todos: (search for TODO for more ;-)) integrate otr_load/otr_save with existing storage backends per-account policy settings per-user policy settings + add a way to select recipient instance */ /* @@ -631,6 +633,9 @@ void op_gone_secure(void *opdata, ConnContext *context) void op_gone_insecure(void *opdata, ConnContext *context) { + /* XXX on 'otr disconnect', this gets called for every instance and we + * get the message multiple times... */ + struct im_connection *ic = check_imc(opdata, context->accountname, context->protocol); irc_t *irc = ic->bee->ui_data; @@ -870,10 +875,6 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, display_otr_message(opdata, ctx, "unreadable encrypted message received"); break; - case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: - display_otr_message(opdata, ctx, - "OTR message for a different instance received"); - break; case OTRL_MSGEVENT_RCVDMSG_MALFORMED: display_otr_message(opdata, ctx, "malformed OTR message received"); @@ -890,6 +891,10 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, display_otr_message(opdata, ctx, "unrecognized OTR message received"); break; + case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: + display_otr_message(opdata, ctx, + "OTR message for a different instance received"); + break; default: /* ignore XXX log? */ break; @@ -1693,6 +1698,8 @@ void show_general_otr_info(irc_t *irc) irc_rootmsg(irc, " (none)"); /* list all contexts */ + /* XXX remove this, or split off as its own command */ + /* XXX show instags? */ irc_rootmsg(irc, "%s", ""); irc_rootmsg(irc, "\x1f" "connection contexts:\x1f (bold=currently encrypted)"); for(ctx=irc->otr->us->context_root; ctx; ctx=ctx->next) {\ @@ -1721,7 +1728,7 @@ void show_general_otr_info(irc_t *irc) void show_otr_context_info(irc_t *irc, ConnContext *ctx) { - // XXX show all contexts + // XXX show all instags/subcontexts switch(ctx->otr_offer) { case OFFER_NOT: -- cgit v1.2.3 From 51f937efd8653a3dc79ba1dbdb93fc2c69c78504 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 3 Aug 2013 15:36:53 +0200 Subject: log OTR heartbeats if set verbose --- otr.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/otr.c b/otr.c index 80f1786c..8af3add5 100644 --- a/otr.c +++ b/otr.c @@ -879,6 +879,18 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, display_otr_message(opdata, ctx, "malformed OTR message received"); break; + case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: + if(global.conf->verbose) { + log_otr_message(opdata, "%s/%s: heartbeat received", + ctx->accountname, ctx->protocol); + } + break; + case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: + if(global.conf->verbose) { + log_otr_message(opdata, "%s/%s: heartbeat sent", + ctx->accountname, ctx->protocol); + } + break; case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: display_otr_message(opdata, ctx, "OTR error message received: %s", message); @@ -896,7 +908,7 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, "OTR message for a different instance received"); break; default: - /* ignore XXX log? */ + /* shouldn't happen */ break; } } -- cgit v1.2.3