[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