[Pkg-privacy-commits] [irssi-plugin-otr] 122/267: Add /otr forget command
Ximin Luo
infinity0 at moszumanska.debian.org
Sat Aug 22 12:41:34 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch debian
in repository irssi-plugin-otr.
commit a2bb5bb136b729466fde6437c335bf5d7de05cb9
Author: David Goulet <dgoulet at ev0ke.net>
Date: Mon Nov 12 11:46:49 2012 -0500
Add /otr forget command
The command either takes a human readable OTR session fingerprint or can
be used inside a private message window where the fingerprint is looked
up in the current peer context.
Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
src/cmd.c | 26 ++++++++++++
src/otr-ops.c | 4 ++
src/otr.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
src/otr.h | 14 +++++++
src/utils.c | 66 ++++++++++++++++++++++++++-----
src/utils.h | 2 +
6 files changed, 215 insertions(+), 21 deletions(-)
diff --git a/src/cmd.c b/src/cmd.c
index 03a1dea..4d0a31c 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -238,6 +238,31 @@ end:
return;
}
+static void _cmd_forget(struct otr_user_state *ustate, SERVER_REC *irssi,
+ int argc, char *argv[], char *argv_eol[], char *target,
+ const char *orig_args)
+{
+ char str_fp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN], *fp = NULL;
+
+ if (argc == 5) {
+ utils_hash_parts_to_readable_hash((const char **) argv, str_fp);
+ fp = str_fp;
+ } else if (!irssi || (irssi && argc != 0)) {
+ /* If no IRSSI or some arguments (not 5), bad command. */
+ IRSSI_NOTICE(irssi, target, "%9OTR%9: Usage %9/otr forget [FP]%9 "
+ "where FP is the five part of the fingerprint listed by "
+ "%9/otr contexts%9 or do the command inside an OTR session "
+ "private message window");
+ goto error;
+ }
+
+ /* Trigger the forget action. */
+ otr_forget(irssi, target, fp, ustate);
+
+error:
+ return;
+}
+
static struct irssi_commands cmds[] = {
{ "version", _cmd_version },
{ "debug", _cmd_debug },
@@ -245,6 +270,7 @@ static struct irssi_commands cmds[] = {
{ "init", _cmd_init },
{ "finish", _cmd_finish },
{ "trust", _cmd_trust },
+ { "forget", _cmd_forget },
{ "authabort", _cmd_authabort },
{ "auth", _cmd_auth },
{ "authq", _cmd_authq },
diff --git a/src/otr-ops.c b/src/otr-ops.c
index 5cfb6f5..8048357 100644
--- a/src/otr-ops.c
+++ b/src/otr-ops.c
@@ -111,6 +111,7 @@ static void ops_secure(void *opdata, ConnContext *context)
char ownfp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN];
char peerfp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN];
SERVER_REC *irssi = opdata;
+ struct otr_peer_context *opc;
assert(context);
/* This should *really* not happened */
@@ -119,6 +120,9 @@ static void ops_secure(void *opdata, ConnContext *context)
IRSSI_NOTICE(irssi, context->username, "%9OTR%9: Gone %9secure%9");
otr_status_change(irssi, context->username, OTR_STATUS_GONE_SECURE);
+ opc = context->app_data;
+ opc->active_fingerprint = context->active_fingerprint;
+
ret = otrl_context_is_fingerprint_trusted(context->active_fingerprint);
if (ret) {
/* Secure and trusted */
diff --git a/src/otr.c b/src/otr.c
index 30b14af..3e7bbfb 100644
--- a/src/otr.c
+++ b/src/otr.c
@@ -119,6 +119,7 @@ static void add_peer_context_cb(void *data, ConnContext *context)
return;
}
+ context->active_fingerprint = context->active_fingerprint;
context->app_data = opc;
context->app_data_free = destroy_peer_context_cb;
@@ -128,7 +129,7 @@ static void add_peer_context_cb(void *data, ConnContext *context)
/*
* Get a context from a pair.
*/
-static ConnContext *get_otrl_context(const char *accname, const char *nick,
+ConnContext *otr_find_context(const char *accname, const char *nick,
int create, SERVER_REC *irssi)
{
ConnContext *ctx = otrl_context_find(user_state_global->otr_state,
@@ -259,9 +260,8 @@ struct ctxlist_ *otr_contexts(struct otr_user_state *ustate)
Fingerprint *fprint;
struct ctxlist_ *ctxlist = NULL, *ctxhead = NULL;
struct fplist_ *fplist, *fphead;
- char fp[41];
+ char fp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN];
char *trust;
- int i;
for (context = ustate->otr_state->context_root; context;
context = context->next) {
@@ -300,9 +300,8 @@ struct ctxlist_ *otr_contexts(struct otr_user_state *ustate)
trust = fprint->trust ? : "";
- for (i = 0; i < 20; ++i) {
- sprintf(fp + i * 2, "%02x", fprint->fingerprint[i]);
- }
+ otrl_privkey_hash_to_human(fp, fprint->fingerprint);
+
fplist->fp = g_strdup(fp);
if (*trust == '\0') {
fplist->authby = NOAUTH;
@@ -341,7 +340,7 @@ void otr_finish(SERVER_REC *irssi, char *nick, const char *peername, int inquery
goto end;
}
- if (!(co = get_otrl_context(accname, nick, FALSE, irssi))) {
+ if (!(co = otr_find_context(accname, nick, FALSE, irssi))) {
if (inquery) {
otr_noticest(TXT_CTX_NOT_FOUND, accname, nick);
}
@@ -421,7 +420,7 @@ void otr_trust(SERVER_REC *irssi, char *nick, const char *peername)
goto end;
}
- ctx = get_otrl_context(accname, nick, FALSE, irssi);
+ ctx = otr_find_context(accname, nick, FALSE, irssi);
if (!ctx) {
goto end;
}
@@ -474,7 +473,7 @@ void otr_authabort(SERVER_REC *irssi, char *nick, const char *peername)
IRSSI_ACCNAME(accname, irssi);
- if (!(co = get_otrl_context(accname, nick, FALSE, irssi))) {
+ if (!(co = otr_find_context(accname, nick, FALSE, irssi))) {
otr_noticest(TXT_CTX_NOT_FOUND, accname, nick);
goto end;
}
@@ -510,7 +509,7 @@ void otr_auth(SERVER_REC *irssi, char *nick, const char *peername,
goto end;
}
- ctx = get_otrl_context(accname, nick, 0, irssi);
+ ctx = otr_find_context(accname, nick, 0, irssi);
if (!ctx) {
otr_noticest(TXT_CTX_NOT_FOUND, accname, nick);
goto end;
@@ -700,7 +699,7 @@ int otr_getstatus(SERVER_REC *irssi, const char *nick)
goto end;
}
- ctx = get_otrl_context(accname, nick, FALSE, irssi);
+ ctx = otr_find_context(accname, nick, FALSE, irssi);
if (!ctx) {
code = IO_ST_PLAINTEXT;
goto end;
@@ -777,3 +776,106 @@ void otr_status_change(SERVER_REC *irssi, const char *nick,
statusbar_items_redraw("otr");
signal_emit("otr event", 3, irssi, nick, statusbar_txt[event]);
}
+
+/*
+ * Search for a OTR Fingerprint object from the given human readable string and
+ * return a pointer to the object if found else NULL.
+ */
+Fingerprint *otr_find_hash_fingerprint_from_human(const char *human_fp,
+ struct otr_user_state *ustate)
+{
+ char str_fp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN];
+ Fingerprint *fp = NULL, *fp_iter = NULL;
+ ConnContext *context;
+
+ /* Loop on all context of the user state */
+ for (context = ustate->otr_state->context_root; context != NULL;
+ context = context->next) {
+ /* Loop on all fingerprint of the context */
+ for (fp_iter = context->fingerprint_root.next; fp_iter;
+ fp_iter = fp_iter->next) {
+ otrl_privkey_hash_to_human(str_fp, fp_iter->fingerprint);
+ /* Compare human fingerprint given in argument to the current. */
+ if (strncmp(str_fp, human_fp, sizeof(str_fp)) == 0) {
+ fp = otrl_context_find_fingerprint(context,
+ fp_iter->fingerprint, 0, NULL);
+ goto end;
+ }
+ }
+ }
+
+end:
+ return fp;
+}
+
+/*
+ * Forget a fingerprint.
+ *
+ * If str_fp is not NULL, it must be on the OTR human format like this:
+ * "487FFADA 5073FEDD C5AB5C14 5BB6C1FF 6D40D48A". If str_fp is NULL, get the
+ * context of the target nickname, check for the OTR peer context active
+ * fingerprint and forget this one if possible.
+ */
+void otr_forget(SERVER_REC *irssi, const char *nick, char *str_fp,
+ struct otr_user_state *ustate)
+{
+ char fp[OTRL_PRIVKEY_FPRINT_HUMAN_LEN], *accname = NULL;
+ Fingerprint *fp_forget;
+ ConnContext *ctx;
+ struct otr_peer_context *opc;
+
+ if (!irssi && !str_fp) {
+ IRSSI_NOTICE(NULL, nick, "%9OTR%9: Need a fingerprint!");
+ goto error;
+ }
+
+ /* No human string fingerprint given. */
+ if (!str_fp) {
+ accname = create_account_name(irssi);
+ if (!accname) {
+ goto error;
+ }
+
+ ctx = otr_find_context(accname, nick, FALSE, irssi);
+ if (!ctx) {
+ goto error;
+ }
+
+ opc = ctx->app_data;
+ /* Always NEED a peer context or else code error. */
+ assert(opc);
+
+ fp_forget = opc->active_fingerprint;
+ } else {
+ fp_forget = otr_find_hash_fingerprint_from_human(str_fp, ustate);
+ }
+
+ IRSSI_DEBUG("%9OTR%9: Forgetting fingerprint: %s",
+ (str_fp != NULL) ? str_fp : fp);
+
+ if (fp_forget) {
+ /* Don't do anything if context is in encrypted state. */
+ if (fp_forget->context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
+ IRSSI_NOTICE(irssi, nick, "%9OTR%9: Fingerprint "
+ "context is still encrypted. Finish the OTR "
+ "session beforehands.");
+ goto end;
+ }
+
+ otrl_privkey_hash_to_human(fp, fp_forget->fingerprint);
+ /* Forget fp and context if it's the only one remaining. */
+ otrl_context_forget_fingerprint(fp_forget, 1);
+ /* Update fingerprints file. */
+ key_write_fingerprints(ustate);
+ IRSSI_NOTICE(irssi, nick, "%9OTR%9: Fingerprint %y%s%n forgotten.",
+ fp);
+ } else {
+ IRSSI_NOTICE(irssi, nick, "%9OTR%9: Fingerprint %y%s%n NOT found",
+ (str_fp != NULL) ? str_fp : fp);
+ }
+
+end:
+error:
+ free(accname);
+ return;
+}
diff --git a/src/otr.h b/src/otr.h
index 68fb338..3ecfe6a 100644
--- a/src/otr.h
+++ b/src/otr.h
@@ -79,8 +79,16 @@ struct otr_user_state {
* Peer OTR internal context.
*/
struct otr_peer_context {
+ /* The SMP event status. Used for the Irssi status bar. */
OtrlSMPEvent smp_event;
+ /* Did the SMP secret was asked so are we in a responder state? */
unsigned int ask_secret;
+ /*
+ * The fingerprint of the private message OTR session. This is useful for
+ * the forget command for which we can recover the fingerprint
+ * automatically.
+ */
+ Fingerprint *active_fingerprint;
};
/* these are returned by /otr contexts */
@@ -188,8 +196,14 @@ void otr_abort_auth(ConnContext *co, SERVER_REC *irssi,
const char *nick);
struct ctxlist_ *otr_contexts(struct otr_user_state *ustate);
void otr_finishall(struct otr_user_state *ustate);
+void otr_forget(SERVER_REC *irssi, const char *nick, char *str_fp,
+ struct otr_user_state *ustate);
int otr_getstatus_format(SERVER_REC *irssi, const char *nick);
struct otr_peer_context *otr_create_peer_context(void);
+ConnContext *otr_find_context(const char *accname, const char *nick,
+ int create, SERVER_REC *irssi);
+Fingerprint *otr_find_hash_fingerprint_from_human(const char *human_fp,
+ struct otr_user_state *ustate);
#endif /* IRSSI_OTR_OTR_H */
diff --git a/src/utils.c b/src/utils.c
index 0ea3cc8..1268aa5 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -4,20 +4,21 @@
* Copyright (C) 2008 Uli Meis <a.sporto+bee at gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
*/
+#include <assert.h>
#include <string.h>
#include "otr.h"
@@ -162,3 +163,48 @@ void otr_log(IRC_CTX *server, const char *nick, int lvl, const char *fmt, ...)
printtext(server, nick, MSGLEVEL_MSGS, msg);
}
+
+void utils_string_to_upper(char *string)
+{
+ int i = 0;
+ char c;
+
+ assert(string);
+
+ while (string[i]) {
+ c = string[i];
+ string[i] = toupper(c);
+ i++;
+ }
+}
+
+/*
+ * Convert a fingerprint string of this format contained in parts:
+ * d81d8363 f6d6090a c2632a53 352dadfa fd296a87
+ * to a privkey hash_to_human format of libotr:
+ * D81D8363 F6D6090A C2632A53 352DADFA FD296A87
+ *
+ * Stores the result in dst which is basically regroup the string and upper
+ * case it. The dst argument must be equal or larger than
+ * OTRL_PRIVKEY_FPRINT_HUMAN_LEN.
+ */
+void utils_hash_parts_to_readable_hash(const char **parts, char *dst)
+{
+ int ret;
+
+ /* Safety net. This is a code flow error. */
+ assert(parts && parts[0] && parts[1] && parts[2] && parts[3] && parts[4]);
+ assert(dst);
+
+ ret = snprintf(dst, OTRL_PRIVKEY_FPRINT_HUMAN_LEN, "%s %s %s %s %s",
+ parts[0], parts[1], parts[2], parts[3], parts[4]);
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* In place upper case full string. */
+ utils_string_to_upper(dst);
+
+error:
+ return;
+}
diff --git a/src/utils.h b/src/utils.h
index 1deaf40..2144f7f 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -37,5 +37,7 @@ void otr_log(IRC_CTX *server, const char *to, int lvl, const char *fmt, ...);
void utils_io_explode_args(const char *args, char ***argvp, char ***argv_eolp,
int *argcp);
int utils_io_extract_smp(const char *data, char **question, char **secret);
+void utils_string_to_upper(char *string);
+void utils_hash_parts_to_readable_hash(const char **parts, char *dst);
#endif /* IRSSI_OTR_UTILS_H */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/irssi-plugin-otr.git
More information about the Pkg-privacy-commits
mailing list