diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-17 14:50:01 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-17 14:50:01 +0100 |
commit | 6e9ae727bcd95eb820fa28becaf9f79ac463de5f (patch) | |
tree | 2d1d2a0f511d1356caf4a3f7c29c1578f0583a95 /otr.c | |
parent | 87dddee3a14d7755204d6fc4b321729bad02ce4e (diff) | |
parent | 17f057d70b1513710e3d765969205625f0fc7b76 (diff) |
Mainline merge.
Diffstat (limited to 'otr.c')
-rw-r--r-- | otr.c | 448 |
1 files changed, 270 insertions, 178 deletions
@@ -7,7 +7,7 @@ /* OTR support (cf. http://www.cypherpunks.ca/otr/) - (c) 2008-2010 Sven Moritz Hallberg <pesco@khjk.org> + (c) 2008-2011 Sven Moritz Hallberg <pesco@khjk.org> (c) 2008 funded by stonedcoder.org files used to store OTR data: @@ -162,6 +162,9 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, const char *secret); +/* update flags within the irc_user structure to reflect OTR status of context */ +void otr_update_uflags(ConnContext *context, irc_user_t *u); + /* update op/voice flag of given user according to encryption state and settings returns 0 if neither op_buddies nor voice_buddies is set to "encrypted", i.e. msgstate should be announced seperately */ @@ -182,6 +185,9 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args); /* find a private key by fingerprint prefix (given as any number of hex strings) */ OtrlPrivKey *match_privkey(irc_t *irc, const char **args); +/* check whether a string is safe to use in a path component */ +int strsane(const char *s); + /* functions to be called for certain events */ static const struct irc_plugin otr_plugin; @@ -236,6 +242,8 @@ gboolean otr_irc_new(irc_t *irc) l = g_slist_prepend( l, "manual" ); l = g_slist_prepend( l, "always" ); s->eval_data = l; + + s = set_add( &irc->b->set, "otr_does_html", "true", set_eval_bool, irc ); return TRUE; } @@ -269,15 +277,17 @@ void otr_load(irc_t *irc) gcry_error_t enoent = gcry_error_from_errno(ENOENT); int kg=0; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->user->nick); - e = otrl_privkey_read(irc->otr->us, s); - if(e && e!=enoent) { - irc_usermsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); - } - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); - e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); - if(e && e!=enoent) { - irc_usermsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + if(strsane(irc->user->nick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->user->nick); + e = otrl_privkey_read(irc->otr->us, s); + if(e && e!=enoent) { + irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + } + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); + e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); + if(e && e!=enoent) { + irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + } } /* check for otr keys on all accounts */ @@ -285,7 +295,7 @@ void otr_load(irc_t *irc) kg = otr_check_for_key(a) || kg; } if(kg) { - irc_usermsg(irc, "Notice: " + irc_rootmsg(irc, "Notice: " "The accounts above do not have OTR encryption keys associated with them, yet. " "These keys are now being generated in the background. " "You will be notified as they are completed. " @@ -300,34 +310,40 @@ void otr_save(irc_t *irc) char s[512]; gcry_error_t e; - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); - e = otrl_privkey_write_fingerprints(irc->otr->us, s); - if(e) { - irc_usermsg(irc, "otr save: %s: %s", s, gcry_strerror(e)); + if(strsane(irc->user->nick)) { + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); + e = otrl_privkey_write_fingerprints(irc->otr->us, s); + if(e) { + irc_rootmsg(irc, "otr save: %s: %s", s, gcry_strerror(e)); + } + chmod(s, 0600); } - chmod(s, 0600); } void otr_remove(const char *nick) { char s[512]; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, nick); - unlink(s); - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, nick); - unlink(s); + if(strsane(nick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, nick); + unlink(s); + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, nick); + unlink(s); + } } void otr_rename(const char *onick, const char *nnick) { char s[512], t[512]; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, onick); - g_snprintf(t, 511, "%s%s.otr_keys", global.conf->configdir, nnick); - rename(s,t); - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, onick); - g_snprintf(t, 511, "%s%s.otr_fprints", global.conf->configdir, nnick); - rename(s,t); + if(strsane(nnick) && strsane(onick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, onick); + g_snprintf(t, 511, "%s%s.otr_keys", global.conf->configdir, nnick); + rename(s,t); + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, onick); + g_snprintf(t, 511, "%s%s.otr_fprints", global.conf->configdir, nnick); + rename(s,t); + } } int otr_check_for_key(account_t *a) @@ -342,13 +358,13 @@ int otr_check_for_key(account_t *a) k = otrl_privkey_find(irc->otr->us, a->user, a->prpl->name); if(k) { - irc_usermsg(irc, "otr: %s/%s ready", a->user, a->prpl->name); + irc_rootmsg(irc, "otr: %s/%s ready", a->user, a->prpl->name); return 0; } if(keygen_in_progress(irc, a->user, a->prpl->name)) { - irc_usermsg(irc, "otr: keygen for %s/%s already in progress", a->user, a->prpl->name); + irc_rootmsg(irc, "otr: keygen for %s/%s already in progress", a->user, a->prpl->name); return 0; } else { - irc_usermsg(irc, "otr: starting background keygen for %s/%s", a->user, a->prpl->name); + irc_rootmsg(irc, "otr: starting background keygen for %s/%s", a->user, a->prpl->name); otr_keygen(irc, a->user, a->prpl->name); return 1; } @@ -359,7 +375,6 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) int ignore_msg; char *newmsg = NULL; OtrlTLV *tlvs = NULL; - char *colormsg; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; @@ -379,33 +394,59 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) return NULL; } else if(!newmsg) { /* this was a non-OTR message */ - return g_strdup(msg); + return msg; } else { /* 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); - if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED && - set_getbool(&ic->bee->set, "otr_color_encrypted")) { - /* color according to f'print trust */ - int color; - const char *trust = context->active_fingerprint->trust; - if(trust && trust[0] != '\0') - color=3; /* green */ - else - color=5; /* red */ - - if(newmsg[0] == ',') { - /* could be a problem with the color code */ - /* insert a space between color spec and message */ - colormsg = g_strdup_printf("\x03%.2d %s\x0F", color, newmsg); - } else { - colormsg = g_strdup_printf("\x03%.2d%s\x0F", color, newmsg); + + /* 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); } - } else { - colormsg = g_strdup(newmsg); + + /* 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 colormsg; + return msg; } } @@ -413,6 +454,7 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) { int st; char *otrmsg = NULL; + char *emsg = msg; /* the message as we hand it to libotr */ ConnContext *ctx = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; @@ -421,18 +463,29 @@ char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) if(ic->acc->prpl->options & OPT_NOOTR) { return msg; } + + ctx = otrl_context_find(irc->otr->us, + iu->bu->handle, ic->acc->user, ic->acc->prpl->name, + 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, "<html>", 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, - msg, NULL, &otrmsg, NULL, NULL); + emsg, NULL, &otrmsg, NULL, NULL); + if(emsg != msg) { + g_free(emsg); /* we're done with this one */ + } if(st) { return NULL; } - ctx = otrl_context_find(irc->otr->us, - iu->bu->handle, ic->acc->user, ic->acc->prpl->name, - 1, NULL, NULL, NULL); - if(otrmsg) { if(!ctx) { otrl_message_free(otrmsg); @@ -479,13 +532,13 @@ static void cmd_otr(irc_t *irc, char **args) } if(!cmd->command) { - irc_usermsg(irc, "%s: unknown subcommand \"%s\", see \x02help otr\x02", + irc_rootmsg(irc, "%s: unknown subcommand \"%s\", see \x02help otr\x02", args[0], args[1]); return; } if(!args[cmd->required_parameters+1]) { - irc_usermsg(irc, "%s %s: not enough arguments (%d req.)", + irc_rootmsg(irc, "%s %s: not enough arguments (%d req.)", args[0], args[1], cmd->required_parameters); return; } @@ -557,7 +610,7 @@ void op_inject_message(void *opdata, const char *accountname, if (strcmp(accountname, recipient) == 0) { /* huh? injecting messages to myself? */ - irc_usermsg(irc, "note to self: %s", message); + irc_rootmsg(irc, "note to self: %s", message); } else { /* need to drop some consts here :-( */ /* TODO: get flags into op_inject_message?! */ @@ -572,9 +625,15 @@ int op_display_otr_message(void *opdata, const char *accountname, 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); - irc_usermsg(irc, "otr: %s", 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; @@ -586,11 +645,17 @@ void op_new_fingerprint(void *opdata, OtrlUserState us, { struct im_connection *ic = check_imc(opdata, accountname, protocol); irc_t *irc = ic->bee->ui_data; + irc_user_t *u = peeruser(irc, username, protocol); char hunam[45]; /* anybody looking? ;-) */ otrl_privkey_hash_to_human(hunam, fingerprint); - irc_usermsg(irc, "new fingerprint for %s: %s", - peernick(irc, username, protocol), hunam); + if(u) { + irc_usernotice(u, "new fingerprint: %s", hunam); + } else { + /* this case shouldn't normally happen */ + irc_rootmsg(irc, "new fingerprint for %s/%s: %s", + username, protocol, hunam); + } } void op_write_fingerprints(void *opdata) @@ -607,7 +672,6 @@ void op_gone_secure(void *opdata, ConnContext *context) check_imc(opdata, context->accountname, context->protocol); irc_user_t *u; irc_t *irc = ic->bee->ui_data; - const char *trust; u = peeruser(irc, context->username, context->protocol); if(!u) { @@ -617,13 +681,11 @@ void op_gone_secure(void *opdata, ConnContext *context) return; } - trust = context->active_fingerprint->trust; - if(trust && trust[0]) - u->flags |= IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED; - else - u->flags = ( u->flags & ~IRC_USER_OTR_TRUSTED ) | IRC_USER_OTR_ENCRYPTED; - if(!otr_update_modeflags(irc, u)) - irc_usermsg(irc, "conversation with %s is now off the record", u->nick); + otr_update_uflags(context, u); + if(!otr_update_modeflags(irc, u)) { + char *trust = u->flags & IRC_USER_OTR_TRUSTED ? "trusted" : "untrusted!"; + irc_usernotice(u, "conversation is now off the record (%s)", trust); + } } void op_gone_insecure(void *opdata, ConnContext *context) @@ -640,9 +702,9 @@ void op_gone_insecure(void *opdata, ConnContext *context) context->username, context->protocol, context->accountname); return; } - u->flags &= ~( IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED ); + otr_update_uflags(context, u); if(!otr_update_modeflags(irc, u)) - irc_usermsg(irc, "conversation with %s is now in the clear", u->nick); + irc_usernotice(u, "conversation is now in cleartext"); } void op_still_secure(void *opdata, ConnContext *context, int is_reply) @@ -659,12 +721,12 @@ void op_still_secure(void *opdata, ConnContext *context, int is_reply) context->username, context->protocol, context->accountname); return; } - if(context->active_fingerprint->trust[0]) - u->flags |= IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED; - else - u->flags = ( u->flags & ~IRC_USER_OTR_TRUSTED ) | IRC_USER_OTR_ENCRYPTED; - if(!otr_update_modeflags(irc, u)) - irc_usermsg(irc, "otr connection with %s has been refreshed", u->nick); + + otr_update_uflags(context, u); + if(!otr_update_modeflags(irc, u)) { + char *trust = u->flags & IRC_USER_OTR_TRUSTED ? "trusted" : "untrusted!"; + irc_usernotice(u, "otr connection has been refreshed (%s)", trust); + } } void op_log_message(void *opdata, const char *message) @@ -707,7 +769,7 @@ void cmd_otr_disconnect(irc_t *irc, char **args) u = irc_user_by_name(irc, args[1]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[1]); + irc_rootmsg(irc, "%s: unknown user", args[1]); return; } @@ -732,11 +794,11 @@ void cmd_otr_connect(irc_t *irc, char **args) u = irc_user_by_name(irc, args[1]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[1]); + irc_rootmsg(irc, "%s: unknown user", args[1]); return; } if(!(u->bu->flags & BEE_USER_ONLINE)) { - irc_usermsg(irc, "%s is offline", args[1]); + irc_rootmsg(irc, "%s is offline", args[1]); return; } @@ -763,14 +825,14 @@ void cmd_otr_trust(irc_t *irc, char **args) u = irc_user_by_name(irc, args[1]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[1]); + irc_rootmsg(irc, "%s: unknown user", args[1]); 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); if(!ctx) { - irc_usermsg(irc, "%s: no otr context with user", args[1]); + irc_rootmsg(irc, "%s: no otr context with user", args[1]); return; } @@ -782,18 +844,18 @@ void cmd_otr_trust(irc_t *irc, char **args) int x, y; if(!*p || !*q) { - irc_usermsg(irc, "failed: truncated fingerprint block %d", i+1); + irc_rootmsg(irc, "failed: truncated fingerprint block %d", i+1); return; } x = hexval(*p); y = hexval(*q); if(x<0) { - irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+1, i+1); + irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+1, i+1); return; } if(y<0) { - irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+2, i+1); + irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+2, i+1); return; } @@ -802,11 +864,11 @@ void cmd_otr_trust(irc_t *irc, char **args) } fp = otrl_context_find_fingerprint(ctx, raw, 0, NULL); if(!fp) { - irc_usermsg(irc, "failed: no such fingerprint for %s", args[1]); + irc_rootmsg(irc, "failed: no such fingerprint for %s", args[1]); } else { char *trust = args[7] ? args[7] : "affirmed"; otrl_context_set_trust(fp, trust); - irc_usermsg(irc, "fingerprint match, trust set to \"%s\"", trust); + irc_rootmsg(irc, "fingerprint match, trust set to \"%s\"", trust); if(u->flags & IRC_USER_OTR_ENCRYPTED) u->flags |= IRC_USER_OTR_TRUSTED; otr_update_modeflags(irc, u); @@ -834,21 +896,21 @@ void cmd_otr_info(irc_t *irc, char **args) handle = arg; ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, NULL, NULL, NULL); if(!ctx) { - irc_usermsg(irc, "no such context"); + irc_rootmsg(irc, "no such context"); g_free(arg); return; } } else { irc_user_t *u = irc_user_by_name(irc, args[1]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[1]); + irc_rootmsg(irc, "%s: unknown user", args[1]); g_free(arg); 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); if(!ctx) { - irc_usermsg(irc, "no otr context with %s", args[1]); + irc_rootmsg(irc, "no otr context with %s", args[1]); g_free(arg); return; } @@ -856,7 +918,7 @@ void cmd_otr_info(irc_t *irc, char **args) /* show how we resolved the (nick) argument, if we did */ if(handle!=arg) { - irc_usermsg(irc, "%s is %s/%s; we are %s/%s to them", args[1], + irc_rootmsg(irc, "%s is %s/%s; we are %s/%s to them", args[1], ctx->username, ctx->protocol, ctx->accountname, ctx->protocol); } show_otr_context_info(irc, ctx); @@ -871,19 +933,19 @@ void cmd_otr_keygen(irc_t *irc, char **args) n = atoi(args[1]); if(n<0 || (!n && strcmp(args[1], "0"))) { - irc_usermsg(irc, "%s: invalid account number", args[1]); + irc_rootmsg(irc, "%s: invalid account number", args[1]); return; } a = irc->b->accounts; for(i=0; i<n && a; i++, a=a->next); if(!a) { - irc_usermsg(irc, "%s: no such account", args[1]); + irc_rootmsg(irc, "%s: no such account", args[1]); return; } if(keygen_in_progress(irc, a->user, a->prpl->name)) { - irc_usermsg(irc, "keygen for account %d already in progress", n); + irc_rootmsg(irc, "keygen for account %d already in progress", n); return; } @@ -905,7 +967,7 @@ void yes_forget_fingerprint(void *data) g_free(p); if(fp == fp->context->active_fingerprint) { - irc_usermsg(irc, "that fingerprint is active, terminate otr connection first"); + irc_rootmsg(irc, "that fingerprint is active, terminate otr connection first"); return; } @@ -921,7 +983,7 @@ void yes_forget_context(void *data) g_free(p); if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { - irc_usermsg(irc, "active otr connection with %s, terminate it first", + irc_rootmsg(irc, "active otr connection with %s, terminate it first", peernick(irc, ctx->username, ctx->protocol)); return; } @@ -953,21 +1015,21 @@ void cmd_otr_forget(irc_t *irc, char **args) pair_t *p; if(!args[3]) { - irc_usermsg(irc, "otr %s %s: not enough arguments (2 req.)", args[0], args[1]); + irc_rootmsg(irc, "otr %s %s: not enough arguments (2 req.)", args[0], args[1]); return; } /* TODO: allow context specs ("user/proto/account") in 'otr forget fingerprint'? */ u = irc_user_by_name(irc, args[2]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[2]); + irc_rootmsg(irc, "%s: unknown user", args[2]); 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); if(!ctx) { - irc_usermsg(irc, "no otr context with %s", args[2]); + irc_rootmsg(irc, "no otr context with %s", args[2]); return; } @@ -978,7 +1040,7 @@ void cmd_otr_forget(irc_t *irc, char **args) } if(fp == ctx->active_fingerprint) { - irc_usermsg(irc, "that fingerprint is active, terminate otr connection first"); + irc_rootmsg(irc, "that fingerprint is active, terminate otr connection first"); return; } @@ -1003,19 +1065,19 @@ void cmd_otr_forget(irc_t *irc, char **args) /* TODO: allow context specs ("user/proto/account") in 'otr forget contex'? */ u = irc_user_by_name(irc, args[2]); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", args[2]); + irc_rootmsg(irc, "%s: unknown user", args[2]); 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); if(!ctx) { - irc_usermsg(irc, "no otr context with %s", args[2]); + irc_rootmsg(irc, "no otr context with %s", args[2]); return; } if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { - irc_usermsg(irc, "active otr connection with %s, terminate it first", args[2]); + irc_rootmsg(irc, "active otr connection with %s, terminate it first", args[2]); return; } @@ -1048,7 +1110,7 @@ void cmd_otr_forget(irc_t *irc, char **args) else { - irc_usermsg(irc, "otr %s: unknown subcommand \"%s\", see \x02help otr forget\x02", + irc_rootmsg(irc, "otr %s: unknown subcommand \"%s\", see \x02help otr forget\x02", args[0], args[1]); } } @@ -1074,7 +1136,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) ic->acc->user, ic->acc->prpl->name, 1, NULL, NULL, NULL); if(!context) { /* huh? out of memory or what? */ - irc_usermsg(irc, "smp: failed to get otr context for %s", u->nick); + 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; @@ -1082,7 +1144,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) nextMsg = context->smstate->nextExpected; if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { - irc_usermsg(irc, "smp %s: opponent violated protocol, aborting", + 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); @@ -1092,14 +1154,14 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT1) { - irc_usermsg(irc, "smp %s: spurious SMP1Q received, aborting", u->nick); + 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_usermsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, + irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, question); - irc_usermsg(irc, "smp: respond with \x02otr smp %s <answer>\x02", + irc_rootmsg(irc, "smp: respond with \x02otr smp %s <answer>\x02", u->nick); g_free(question); /* smp stays in EXPECT1 until user responds */ @@ -1108,11 +1170,11 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT1) { - irc_usermsg(irc, "smp %s: spurious SMP1 received, aborting", u->nick); + 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_usermsg(irc, "smp: initiated by %s" + irc_rootmsg(irc, "smp: initiated by %s" " - respond with \x02otr smp %s <secret>\x02", u->nick, u->nick); /* smp stays in EXPECT1 until user responds */ @@ -1121,7 +1183,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT2) { - irc_usermsg(irc, "smp %s: spurious SMP2 received, aborting", u->nick); + 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 { @@ -1132,25 +1194,25 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT3) { - irc_usermsg(irc, "smp %s: spurious SMP3 received, aborting", u->nick); + 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_usermsg(irc, "smp %s: correct answer, you are trusted", + irc_rootmsg(irc, "smp %s: correct answer, you are trusted", u->nick); } else { - irc_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted", + irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", u->nick); } } else { if(context->smstate->received_question) { - irc_usermsg(irc, "smp %s: wrong answer, you are not trusted", + irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", u->nick); } else { - irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted", + irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", u->nick); } } @@ -1161,16 +1223,16 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT4) { - irc_usermsg(irc, "smp %s: spurious SMP4 received, aborting", u->nick); + 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_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted", + irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", u->nick); } else { - irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted", + irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", u->nick); } otrl_sm_state_free(context->smstate); @@ -1179,7 +1241,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); if (tlv) { - irc_usermsg(irc, "smp: received abort from %s", u->nick); + irc_rootmsg(irc, "smp: received abort from %s", u->nick); otrl_sm_state_free(context->smstate); /* smp is in back in EXPECT1 */ } @@ -1194,18 +1256,18 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, u = irc_user_by_name(irc, nick); if(!u || !u->bu || !u->bu->ic) { - irc_usermsg(irc, "%s: unknown user", nick); + irc_rootmsg(irc, "%s: unknown user", nick); return; } if(!(u->bu->flags & BEE_USER_ONLINE)) { - irc_usermsg(irc, "%s is offline", nick); + irc_rootmsg(irc, "%s is offline", nick); 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); if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { - irc_usermsg(irc, "smp: otr inactive with %s, try \x02otr connect" + irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" " %s\x02", nick, nick); return; } @@ -1220,7 +1282,7 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, if(question) { /* this was 'otr smpq', just initiate */ - irc_usermsg(irc, "smp: initiating with %s...", u->nick); + irc_rootmsg(irc, "smp: initiating with %s...", u->nick); otrl_message_initiate_smp_q(irc->otr->us, &otr_ops, u->bu->ic, ctx, question, (unsigned char *)secret, strlen(secret)); /* smp is now in EXPECT2 */ @@ -1229,14 +1291,14 @@ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, /* warning: the following assumes that smstates are cleared whenever an SMP is completed or aborted! */ if(ctx->smstate->secret == NULL) { - irc_usermsg(irc, "smp: initiating with %s...", u->nick); + irc_rootmsg(irc, "smp: initiating with %s...", u->nick); otrl_message_initiate_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx, (unsigned char *)secret, strlen(secret)); /* smp is now in EXPECT2 */ } else { /* if we're still in EXPECT1 but smstate is initialized, we must have received the SMP1, so let's issue a response */ - irc_usermsg(irc, "smp: responding to %s...", u->nick); + irc_rootmsg(irc, "smp: responding to %s...", u->nick); otrl_message_respond_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx, (unsigned char *)secret, strlen(secret)); /* smp is now in EXPECT3 */ @@ -1311,9 +1373,26 @@ const char *peernick(irc_t *irc, const char *handle, const char *protocol) } } +void otr_update_uflags(ConnContext *context, irc_user_t *u) +{ + const char *trust; + + if(context->active_fingerprint) { + u->flags |= IRC_USER_OTR_ENCRYPTED; + + trust = context->active_fingerprint->trust; + if(trust && trust[0]) + u->flags |= IRC_USER_OTR_TRUSTED; + else + u->flags &= ~IRC_USER_OTR_TRUSTED; + } else { + u->flags &= ~IRC_USER_OTR_ENCRYPTED; + } +} + int otr_update_modeflags(irc_t *irc, irc_user_t *u) { - return 1; + return 0; } void show_fingerprints(irc_t *irc, ConnContext *ctx) @@ -1334,13 +1413,13 @@ void show_fingerprints(irc_t *irc, ConnContext *ctx) trust=fp->trust; } if(fp == ctx->active_fingerprint) { - irc_usermsg(irc, " \x02%s (%s)\x02", human, trust); + irc_rootmsg(irc, " \x02%s (%s)\x02", human, trust); } else { - irc_usermsg(irc, " %s (%s)", human, trust); + irc_rootmsg(irc, " %s (%s)", human, trust); } } if(count==0) - irc_usermsg(irc, " (none)"); + irc_rootmsg(irc, " (none)"); } Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) @@ -1359,14 +1438,14 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) char c = toupper(args[i][j]); if(n>=40) { - irc_usermsg(irc, "too many fingerprint digits given, expected at most 40"); + irc_rootmsg(irc, "too many fingerprint digits given, expected at most 40"); return NULL; } if( (c>='A' && c<='F') || (c>='0' && c<='9') ) { *(p++) = c; } else { - irc_usermsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); + irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); return NULL; } @@ -1387,7 +1466,7 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) break; } if(!fp) { - irc_usermsg(irc, "%s: no match", prefix); + irc_rootmsg(irc, "%s: no match", prefix); return NULL; } @@ -1400,7 +1479,7 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) break; } if(fp2) { - irc_usermsg(irc, "%s: multiple matches", prefix); + irc_rootmsg(irc, "%s: multiple matches", prefix); return NULL; } @@ -1423,14 +1502,14 @@ OtrlPrivKey *match_privkey(irc_t *irc, const char **args) char c = toupper(args[i][j]); if(n>=40) { - irc_usermsg(irc, "too many fingerprint digits given, expected at most 40"); + irc_rootmsg(irc, "too many fingerprint digits given, expected at most 40"); return NULL; } if( (c>='A' && c<='F') || (c>='0' && c<='9') ) { *(p++) = c; } else { - irc_usermsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); + irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); return NULL; } @@ -1451,7 +1530,7 @@ OtrlPrivKey *match_privkey(irc_t *irc, const char **args) break; } if(!k) { - irc_usermsg(irc, "%s: no match", prefix); + irc_rootmsg(irc, "%s: no match", prefix); return NULL; } @@ -1464,7 +1543,7 @@ OtrlPrivKey *match_privkey(irc_t *irc, const char **args) break; } if(k2) { - irc_usermsg(irc, "%s: multiple matches", prefix); + irc_rootmsg(irc, "%s: multiple matches", prefix); return NULL; } @@ -1479,16 +1558,16 @@ void show_general_otr_info(irc_t *irc) kg_t *kg; /* list all privkeys (including ones being generated) */ - irc_usermsg(irc, "\x1fprivate keys:\x1f"); + irc_rootmsg(irc, "\x1fprivate keys:\x1f"); for(key=irc->otr->us->privkey_root; key; key=key->next) { const char *hash; switch(key->pubkey_type) { case OTRL_PUBKEY_TYPE_DSA: - irc_usermsg(irc, " %s/%s - DSA", key->accountname, key->protocol); + irc_rootmsg(irc, " %s/%s - DSA", key->accountname, key->protocol); break; default: - irc_usermsg(irc, " %s/%s - type %d", key->accountname, key->protocol, + irc_rootmsg(irc, " %s/%s - type %d", key->accountname, key->protocol, key->pubkey_type); } @@ -1497,25 +1576,25 @@ void show_general_otr_info(irc_t *irc) for hashing a given 'OtrlPrivKey'... */ hash = otrl_privkey_fingerprint(irc->otr->us, human, key->accountname, key->protocol); if(hash) /* should always succeed */ - irc_usermsg(irc, " %s", human); + irc_rootmsg(irc, " %s", human); } if(irc->otr->sent_accountname) { - irc_usermsg(irc, " %s/%s - DSA", irc->otr->sent_accountname, + irc_rootmsg(irc, " %s/%s - DSA", irc->otr->sent_accountname, irc->otr->sent_protocol); - irc_usermsg(irc, " (being generated)"); + irc_rootmsg(irc, " (being generated)"); } for(kg=irc->otr->todo; kg; kg=kg->next) { - irc_usermsg(irc, " %s/%s - DSA", kg->accountname, kg->protocol); - irc_usermsg(irc, " (queued)"); + irc_rootmsg(irc, " %s/%s - DSA", kg->accountname, kg->protocol); + irc_rootmsg(irc, " (queued)"); } if(key == irc->otr->us->privkey_root && !irc->otr->sent_accountname && kg == irc->otr->todo) - irc_usermsg(irc, " (none)"); + irc_rootmsg(irc, " (none)"); /* list all contexts */ - irc_usermsg(irc, "%s", ""); - irc_usermsg(irc, "\x1f" "connection contexts:\x1f (bold=currently encrypted)"); + 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) {\ irc_user_t *u; char *userstring; @@ -1529,51 +1608,51 @@ void show_general_otr_info(irc_t *irc) ctx->username, ctx->protocol, ctx->accountname); if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { - irc_usermsg(irc, " \x02%s\x02", userstring); + irc_rootmsg(irc, " \x02%s\x02", userstring); } else { - irc_usermsg(irc, " %s", userstring); + irc_rootmsg(irc, " %s", userstring); } g_free(userstring); } if(ctx == irc->otr->us->context_root) - irc_usermsg(irc, " (none)"); + irc_rootmsg(irc, " (none)"); } void show_otr_context_info(irc_t *irc, ConnContext *ctx) { switch(ctx->otr_offer) { case OFFER_NOT: - irc_usermsg(irc, " otr offer status: none sent"); + irc_rootmsg(irc, " otr offer status: none sent"); break; case OFFER_SENT: - irc_usermsg(irc, " otr offer status: awaiting reply"); + irc_rootmsg(irc, " otr offer status: awaiting reply"); break; case OFFER_ACCEPTED: - irc_usermsg(irc, " otr offer status: accepted our offer"); + irc_rootmsg(irc, " otr offer status: accepted our offer"); break; case OFFER_REJECTED: - irc_usermsg(irc, " otr offer status: ignored our offer"); + irc_rootmsg(irc, " otr offer status: ignored our offer"); break; default: - irc_usermsg(irc, " otr offer status: %d", ctx->otr_offer); + irc_rootmsg(irc, " otr offer status: %d", ctx->otr_offer); } switch(ctx->msgstate) { case OTRL_MSGSTATE_PLAINTEXT: - irc_usermsg(irc, " connection state: cleartext"); + irc_rootmsg(irc, " connection state: cleartext"); break; case OTRL_MSGSTATE_ENCRYPTED: - irc_usermsg(irc, " connection state: encrypted (v%d)", ctx->protocol_version); + irc_rootmsg(irc, " connection state: encrypted (v%d)", ctx->protocol_version); break; case OTRL_MSGSTATE_FINISHED: - irc_usermsg(irc, " connection state: shut down"); + irc_rootmsg(irc, " connection state: shut down"); break; default: - irc_usermsg(irc, " connection state: %d", ctx->msgstate); + irc_rootmsg(irc, " connection state: %d", ctx->msgstate); } - irc_usermsg(irc, " fingerprints: (bold=active)"); + irc_rootmsg(irc, " fingerprints: (bold=active)"); show_fingerprints(irc, ctx); } @@ -1613,20 +1692,20 @@ void otr_keygen(irc_t *irc, const char *handle, const char *protocol) FILE *tof, *fromf; if(pipe(to) < 0 || pipe(from) < 0) { - irc_usermsg(irc, "otr keygen: couldn't create pipe: %s", strerror(errno)); + irc_rootmsg(irc, "otr keygen: couldn't create pipe: %s", strerror(errno)); return; } tof = fdopen(to[1], "w"); fromf = fdopen(from[0], "r"); if(!tof || !fromf) { - irc_usermsg(irc, "otr keygen: couldn't streamify pipe: %s", strerror(errno)); + irc_rootmsg(irc, "otr keygen: couldn't streamify pipe: %s", strerror(errno)); return; } p = fork(); if(p<0) { - irc_usermsg(irc, "otr keygen: couldn't fork: %s", strerror(errno)); + irc_rootmsg(irc, "otr keygen: couldn't fork: %s", strerror(errno)); return; } @@ -1706,16 +1785,21 @@ gboolean keygen_finish_handler(gpointer data, gint fd, b_input_condition cond) myfgets(filename, 512, irc->otr->from); myfgets(msg, 512, irc->otr->from); - irc_usermsg(irc, "%s", msg); + irc_rootmsg(irc, "%s", msg); if(filename[0]) { - char *kf = g_strdup_printf("%s%s.otr_keys", global.conf->configdir, irc->user->nick); - char *tmp = g_strdup_printf("%s.new", kf); - copyfile(filename, tmp); - unlink(filename); - rename(tmp,kf); - otrl_privkey_read(irc->otr->us, kf); - g_free(kf); - g_free(tmp); + if(strsane(irc->user->nick)) { + char *kf = g_strdup_printf("%s%s.otr_keys", global.conf->configdir, irc->user->nick); + char *tmp = g_strdup_printf("%s.new", kf); + copyfile(filename, tmp); + unlink(filename); + rename(tmp,kf); + otrl_privkey_read(irc->otr->us, kf); + g_free(kf); + g_free(tmp); + } else { + otrl_privkey_read(irc->otr->us, filename); + unlink(filename); + } } /* forget this job */ @@ -1780,12 +1864,20 @@ void yes_keygen(void *data) irc_t *irc = acc->bee->ui_data; if(keygen_in_progress(irc, acc->user, acc->prpl->name)) { - irc_usermsg(irc, "keygen for %s/%s already in progress", + irc_rootmsg(irc, "keygen for %s/%s already in progress", acc->user, acc->prpl->name); } else { - irc_usermsg(irc, "starting background keygen for %s/%s", + irc_rootmsg(irc, "starting background keygen for %s/%s", acc->user, acc->prpl->name); - irc_usermsg(irc, "you will be notified when it completes"); + irc_rootmsg(irc, "you will be notified when it completes"); otr_keygen(irc, acc->user, acc->prpl->name); } } + +/* check whether a string is safe to use in a path component */ +int strsane(const char *s) +{ + return strpbrk(s, "/\\") == NULL; +} + +/* vim: set noet ts=4 sw=4: */ |