[Pkg-privacy-commits] [libotr] 59/225: 2009-04-28:
Ximin Luo
infinity0 at moszumanska.debian.org
Sat Aug 22 12:44:54 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch master
in repository libotr.
commit f6a3018ff353e65e345f3135efbe3dbe0be87e75
Author: cypherpunk <cypherpunk>
Date: Tue Apr 28 13:32:12 2009 +0000
2009-04-28:
* src/auth.c: pubkey_type should be shifted by 8, not 16. It
doesn't matter right now, because it's always 0, but still.
(Thanks to Can Tang.)
2008-08-15:
* src/Makefile.am:
* src/context.c:
* src/context.h:
* src/context_priv.c:
* src/context_priv.h:
* src/message.c:
* src/message.h:
* src/proto.c:
* src/proto.h: Willy Lew's updates of the libotr API
2008-08-06:
* src/proto.c: gcc 4.2 with -O2 assumes that integer overflow
---
AUTHORS | 3 +-
ChangeLog | 18 ++
README | 3 +-
src/Makefile.am | 5 +-
src/auth.c | 11 +-
src/auth.h | 3 +-
src/b64.c | 3 +-
src/b64.h | 3 +-
src/context.c | 77 +----
src/context.h | 58 +---
src/context_priv.c | 94 ++++++
src/context_priv.h | 91 ++++++
src/dh.c | 3 +-
src/dh.h | 3 +-
src/mem.c | 3 +-
src/mem.h | 3 +-
src/message.c | 848 ++++++++++++++++++++++++++---------------------------
src/message.h | 202 ++++++++++---
src/privkey-t.h | 3 +-
src/privkey.c | 3 +-
src/privkey.h | 3 +-
src/proto.c | 270 ++++++++---------
src/proto.h | 6 +-
src/serial.h | 3 +-
src/sm.c | 3 +-
src/sm.h | 3 +-
src/tlv.c | 3 +-
src/tlv.h | 3 +-
src/userstate.c | 3 +-
src/userstate.h | 3 +-
src/version.h | 3 +-
31 files changed, 972 insertions(+), 768 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index 50a839d..ef73f85 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,6 +2,7 @@ Off-the-Record Messaging Library and Toolkit
Authors:
- Ian Goldberg, Chris Alexander, Nikita Borisov <otr at cypherpunks.ca>
+ Ian Goldberg, Chris Alexander, Willy Lew, Nikita Borisov
+ <otr at cypherpunks.ca>
See the README file for mailing list information
diff --git a/ChangeLog b/ChangeLog
index 4077cfa..e492c21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-04-28:
+
+ * src/auth.c: pubkey_type should be shifted by 8, not 16. It
+ doesn't matter right now, because it's always 0, but still.
+ (Thanks to Can Tang.)
+
+2008-08-15:
+
+ * src/Makefile.am:
+ * src/context.c:
+ * src/context.h:
+ * src/context_priv.c:
+ * src/context_priv.h:
+ * src/message.c:
+ * src/message.h:
+ * src/proto.c:
+ * src/proto.h: Willy Lew's updates of the libotr API
+
2008-08-06:
* src/proto.c: gcc 4.2 with -O2 assumes that integer overflow
diff --git a/README b/README
index 0b87bcc..04e5092 100644
--- a/README
+++ b/README
@@ -267,7 +267,8 @@ The Off-the-Record Messaging library (in the src directory) is
covered by the following (LGPL) license:
Off-the-Record Messaging library
- Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ Nikita Borisov
<otr at cypherpunks.ca>
This library is free software; you can redistribute it and/or
diff --git a/src/Makefile.am b/src/Makefile.am
index c75fcbe..cc4d26f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,11 +3,12 @@ INCLUDES = @LIBGCRYPT_CFLAGS@
lib_LTLIBRARIES = libotr.la
libotr_la_SOURCES = privkey.c context.c proto.c b64.c dh.c mem.c message.c \
- userstate.c tlv.c auth.c sm.c
+ userstate.c tlv.c auth.c sm.c context_priv.c
libotr_la_LDFLAGS = -version-info @LIBOTR_LIBTOOL_VERSION@ @LIBS@ @LIBGCRYPT_LIBS@
otrincdir = $(includedir)/libotr
otrinc_HEADERS = b64.h context.h dh.h mem.h message.h privkey.h proto.h \
- version.h userstate.h tlv.h serial.h auth.h sm.h privkey-t.h
+ version.h userstate.h tlv.h serial.h auth.h sm.h privkey-t.h \
+ context_priv.h
diff --git a/src/auth.c b/src/auth.c
index a6752c3..36267b5 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -382,7 +383,7 @@ static gcry_error_t calculate_pubkey_auth(unsigned char **authbufp,
/* Write the data to be MAC'd */
write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
- bufp[0] = ((privkey->pubkey_type) >> 16) & 0xff;
+ bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
bufp[1] = (privkey->pubkey_type) & 0xff;
bufp += 2; lenp -= 2;
memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
@@ -413,7 +414,7 @@ static gcry_error_t calculate_pubkey_auth(unsigned char **authbufp,
lenp = totallen;
/* Write the data to be encrypted */
- bufp[0] = ((privkey->pubkey_type) >> 16) & 0xff;
+ bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
bufp[1] = (privkey->pubkey_type) & 0xff;
bufp += 2; lenp -= 2;
memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
@@ -520,7 +521,7 @@ static gcry_error_t check_pubkey_auth(unsigned char fingerprintbufp[20],
write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
- bufp[0] = (pubkey_type >> 16) & 0xff;
+ bufp[0] = (pubkey_type >> 8) & 0xff;
bufp[1] = pubkey_type & 0xff;
bufp += 2; lenp -= 2;
memmove(bufp, fingerprintstart, fingerprintend - fingerprintstart);
@@ -1030,7 +1031,7 @@ gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
if (auth_succeeded) err = auth_succeeded(auth, asdata);
free(auth->lastauthmsg);
auth->lastauthmsg = NULL;
- *havemsgp = 1;
+ *havemsgp = 0;
auth->our_keyid = 0;
auth->authstate = OTRL_AUTHSTATE_NONE;
diff --git a/src/auth.h b/src/auth.h
index 6de75dd..4ca5aa3 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/b64.c b/src/b64.c
index b8736da..bfe163a 100644
--- a/src/b64.c
+++ b/src/b64.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/b64.h b/src/b64.h
index 34ef03f..9a4e636 100644
--- a/src/b64.h
+++ b/src/b64.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/context.c b/src/context.c
index dd5536f..e584769 100644
--- a/src/context.c
+++ b/src/context.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -38,10 +39,6 @@ static ConnContext * new_context(const char * user, const char * accountname,
context->username = strdup(user);
context->accountname = strdup(accountname);
context->protocol = strdup(protocol);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
otrl_auth_new(&(context->auth));
@@ -55,34 +52,14 @@ static ConnContext * new_context(const char * user, const char * accountname,
context->fingerprint_root.next = NULL;
context->fingerprint_root.tous = NULL;
context->active_fingerprint = NULL;
- context->their_keyid = 0;
- context->their_y = NULL;
- context->their_old_y = NULL;
- context->our_keyid = 0;
- context->our_dh_key.groupid = 0;
- context->our_dh_key.priv = NULL;
- context->our_dh_key.pub = NULL;
- context->our_old_dh_key.groupid = 0;
- context->our_old_dh_key.priv = NULL;
- context->our_old_dh_key.pub = NULL;
- otrl_dh_session_blank(&(context->sesskeys[0][0]));
- otrl_dh_session_blank(&(context->sesskeys[0][1]));
- otrl_dh_session_blank(&(context->sesskeys[1][0]));
- otrl_dh_session_blank(&(context->sesskeys[1][1]));
memset(context->sessionid, 0, 20);
context->sessionid_len = 0;
context->protocol_version = 0;
- context->numsavedkeys = 0;
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
- context->saved_mac_keys = NULL;
- context->generation = 0;
- context->lastsent = 0;
- context->lastmessage = NULL;
- context->may_retransmit = 0;
context->otr_offer = OFFER_NOT;
context->app_data = NULL;
context->app_data_free = NULL;
+ context->context_priv = context_priv_new();
+ assert(context->context_priv != NULL);
context->next = NULL;
return context;
}
@@ -174,61 +151,17 @@ void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
fprint->trust = trust ? strdup(trust) : NULL;
}
-/* Set the preshared secret for a given fingerprint. Note that this
- * currently only stores the secret in the ConnContext structure, but
- * doesn't yet do anything with it. */
-void otrl_context_set_preshared_secret(ConnContext *context,
- const unsigned char *secret, size_t secret_len)
-{
- free(context->preshared_secret);
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
-
- if (secret_len) {
- context->preshared_secret = malloc(secret_len);
- if (context->preshared_secret) {
- memmove(context->preshared_secret, secret, secret_len);
- context->preshared_secret_len = secret_len;
- }
- }
-}
-
/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
void otrl_context_force_finished(ConnContext *context)
{
context->msgstate = OTRL_MSGSTATE_FINISHED;
otrl_auth_clear(&(context->auth));
- free(context->fragment);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
context->active_fingerprint = NULL;
- context->their_keyid = 0;
- gcry_mpi_release(context->their_y);
- context->their_y = NULL;
- gcry_mpi_release(context->their_old_y);
- context->their_old_y = NULL;
- context->our_keyid = 0;
- otrl_dh_keypair_free(&(context->our_dh_key));
- otrl_dh_keypair_free(&(context->our_old_dh_key));
- otrl_dh_session_free(&(context->sesskeys[0][0]));
- otrl_dh_session_free(&(context->sesskeys[0][1]));
- otrl_dh_session_free(&(context->sesskeys[1][0]));
- otrl_dh_session_free(&(context->sesskeys[1][1]));
memset(context->sessionid, 0, 20);
context->sessionid_len = 0;
- free(context->preshared_secret);
- context->preshared_secret = NULL;
- context->preshared_secret_len = 0;
context->protocol_version = 0;
- context->numsavedkeys = 0;
- free(context->saved_mac_keys);
- context->saved_mac_keys = NULL;
- gcry_free(context->lastmessage);
- context->lastmessage = NULL;
- context->may_retransmit = 0;
otrl_sm_state_free(context->smstate);
+ context_priv_force_finished(context->context_priv);
}
/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
diff --git a/src/context.h b/src/context.h
index e722c56..1ae658a 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -20,6 +21,8 @@
#ifndef __CONTEXT_H__
#define __CONTEXT_H__
+#include "context_priv.h"
+
#include <gcrypt.h>
#include "dh.h"
@@ -51,20 +54,17 @@ typedef struct context {
struct context * next; /* Linked list pointer */
struct context ** tous; /* A pointer to the pointer to us */
+ /* Context information that is meant for internal use */
+
+ ConnContextPriv *context_priv;
+
+ /* Context information that is meant for application use */
+
char * username; /* The user this context is for */
char * accountname; /* The username is relative to
this account... */
char * protocol; /* ... and this protocol */
- char *fragment; /* The part of the fragmented message
- we've seen so far */
- size_t fragment_len; /* The length of fragment */
- unsigned short fragment_n; /* The total number of fragments
- in this message */
- unsigned short fragment_k; /* The highest fragment number
- we've seen so far for this
- message */
-
OtrlMessageState msgstate; /* The state of message disposition
with this user */
OtrlAuthInfo auth; /* The state of ongoing
@@ -74,20 +74,6 @@ typedef struct context {
Fingerprints entries */
Fingerprint *active_fingerprint; /* Which fingerprint is in use now?
A pointer into the above list */
- unsigned int their_keyid; /* current keyid used by other side;
- this is set to 0 if we get a
- OTRL_TLV_DISCONNECTED message from
- them. */
- gcry_mpi_t their_y; /* Y[their_keyid] (their DH pubkey) */
- gcry_mpi_t their_old_y; /* Y[their_keyid-1] (their prev DH
- pubkey) */
- unsigned int our_keyid; /* current keyid used by us */
- DH_keypair our_dh_key; /* DH key[our_keyid] */
- DH_keypair our_old_dh_key; /* DH key[our_keyid-1] */
-
- DH_sesskeys sesskeys[2][2]; /* sesskeys[i][j] are the session keys
- derived from DH key[our_keyid-i]
- and mpi Y[their_keyid-j] */
unsigned char sessionid[20]; /* The sessionid and bold half */
size_t sessionid_len; /* determined when this private */
@@ -95,24 +81,6 @@ typedef struct context {
unsigned int protocol_version; /* The version of OTR in use */
- unsigned char *preshared_secret; /* A secret you share with this
- user, in order to do
- authentication. */
- size_t preshared_secret_len; /* The length of the above secret. */
-
- /* saved mac keys to be revealed later */
- unsigned int numsavedkeys;
- unsigned char *saved_mac_keys;
-
- /* generation number: increment every time we go private, and never
- * reset to 0 (unless we remove the context entirely) */
- unsigned int generation;
-
- time_t lastsent; /* The last time a Data Message was sent */
- char *lastmessage; /* The plaintext of the last Data Message sent */
- int may_retransmit; /* Is the last message eligible for
- retransmission? */
-
enum {
OFFER_NOT,
OFFER_SENT,
@@ -150,12 +118,6 @@ Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
/* Set the trust level for a given fingerprint */
void otrl_context_set_trust(Fingerprint *fprint, const char *trust);
-/* Set the preshared secret for a given fingerprint. Note that this
- * currently only stores the secret in the ConnContext structure, but
- * doesn't yet do anything with it. */
-void otrl_context_set_preshared_secret(ConnContext *context,
- const unsigned char *secret, size_t secret_len);
-
/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
void otrl_context_force_finished(ConnContext *context);
diff --git a/src/context_priv.c b/src/context_priv.c
new file mode 100644
index 0000000..62ea68b
--- /dev/null
+++ b/src/context_priv.c
@@ -0,0 +1,94 @@
+/*
+ * Off-the-Record Messaging library
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
+ * <otr at cypherpunks.ca>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General
+ * Public License as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* system headers */
+#include <stdlib.h>
+#include <assert.h>
+
+/* libgcrypt headers */
+#include <gcrypt.h>
+
+/* libotr headers */
+#include "context_priv.h"
+
+/* Create a new private connection context */
+ConnContextPriv *context_priv_new()
+{
+ ConnContextPriv *context_priv;
+ context_priv = malloc(sizeof(*context_priv));
+ assert(context_priv != NULL);
+
+ context_priv->fragment = NULL;
+ context_priv->fragment_len = 0;
+ context_priv->fragment_n = 0;
+ context_priv->fragment_k = 0;
+ context_priv->numsavedkeys = 0;
+ context_priv->saved_mac_keys = NULL;
+ context_priv->generation = 0;
+ context_priv->lastsent = 0;
+ context_priv->lastmessage = NULL;
+ context_priv->may_retransmit = 0;
+ context_priv->their_keyid = 0;
+ context_priv->their_y = NULL;
+ context_priv->their_old_y = NULL;
+ context_priv->our_keyid = 0;
+ context_priv->our_dh_key.groupid = 0;
+ context_priv->our_dh_key.priv = NULL;
+ context_priv->our_dh_key.pub = NULL;
+ context_priv->our_old_dh_key.groupid = 0;
+ context_priv->our_old_dh_key.priv = NULL;
+ context_priv->our_old_dh_key.pub = NULL;
+ otrl_dh_session_blank(&(context_priv->sesskeys[0][0]));
+ otrl_dh_session_blank(&(context_priv->sesskeys[0][1]));
+ otrl_dh_session_blank(&(context_priv->sesskeys[1][0]));
+ otrl_dh_session_blank(&(context_priv->sesskeys[1][1]));
+
+ return context_priv;
+}
+
+/* Resets the appropriate variables when a context
+ * is being force finished
+ */
+void context_priv_force_finished(ConnContextPriv *context_priv)
+{
+ free(context_priv->fragment);
+ context_priv->fragment = NULL;
+ context_priv->fragment_len = 0;
+ context_priv->fragment_n = 0;
+ context_priv->fragment_k = 0;
+ context_priv->numsavedkeys = 0;
+ free(context_priv->saved_mac_keys);
+ context_priv->saved_mac_keys = NULL;
+ gcry_free(context_priv->lastmessage);
+ context_priv->lastmessage = NULL;
+ context_priv->may_retransmit = 0;
+ context_priv->their_keyid = 0;
+ gcry_mpi_release(context_priv->their_y);
+ context_priv->their_y = NULL;
+ gcry_mpi_release(context_priv->their_old_y);
+ context_priv->their_old_y = NULL;
+ context_priv->our_keyid = 0;
+ otrl_dh_keypair_free(&(context_priv->our_dh_key));
+ otrl_dh_keypair_free(&(context_priv->our_old_dh_key));
+ otrl_dh_session_free(&(context_priv->sesskeys[0][0]));
+ otrl_dh_session_free(&(context_priv->sesskeys[0][1]));
+ otrl_dh_session_free(&(context_priv->sesskeys[1][0]));
+ otrl_dh_session_free(&(context_priv->sesskeys[1][1]));
+}
diff --git a/src/context_priv.h b/src/context_priv.h
new file mode 100644
index 0000000..b05b5ff
--- /dev/null
+++ b/src/context_priv.h
@@ -0,0 +1,91 @@
+/*
+ * Off-the-Record Messaging library
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
+ * <otr at cypherpunks.ca>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General
+ * Public License as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __CONTEXT_PRIV_H__
+#define __CONTEXT_PRIV_H__
+
+#include <gcrypt.h>
+
+#include "dh.h"
+#include "auth.h"
+#include "sm.h"
+
+typedef struct context_priv {
+ /* The part of the fragmented message we've seen so far */
+ char *fragment;
+
+ /* The length of fragment */
+ size_t fragment_len;
+
+ /* The total number of fragments in this message */
+ unsigned short fragment_n;
+
+ /* The highest fragment number we've seen so far for this message */
+ unsigned short fragment_k;
+
+ /* current keyid used by other side; this is set to 0 if we get
+ * a OTRL_TLV_DISCONNECTED message from them. */
+ unsigned int their_keyid;
+
+ /* Y[their_keyid] (their DH pubkey) */
+ gcry_mpi_t their_y;
+
+ /* Y[their_keyid-1] (their prev DH pubkey) */
+ gcry_mpi_t their_old_y;
+
+ /* current keyid used by us */
+ unsigned int our_keyid;
+
+ /* DH key[our_keyid] */
+ DH_keypair our_dh_key;
+
+ /* DH key[our_keyid-1] */
+ DH_keypair our_old_dh_key;
+
+ /* sesskeys[i][j] are the session keys derived from DH
+ * key[our_keyid-i] and mpi Y[their_keyid-j] */
+ DH_sesskeys sesskeys[2][2];
+
+ /* saved mac keys to be revealed later */
+ unsigned int numsavedkeys;
+ unsigned char *saved_mac_keys;
+
+ /* generation number: increment every time we go private, and never
+ * reset to 0 (unless we remove the context entirely) */
+ unsigned int generation;
+
+ /* The last time a Data Message was sent */
+ time_t lastsent;
+
+ /* The plaintext of the last Data Message sent */
+ char *lastmessage;
+
+ /* Is the last message eligible for retransmission? */
+ int may_retransmit;
+
+} ConnContextPriv;
+
+/* Create a new private connection context. */
+ConnContextPriv *context_priv_new();
+
+/* Frees up memory that was used in context_priv_new */
+void context_priv_force_finished(ConnContextPriv *context_priv);
+
+#endif
diff --git a/src/dh.c b/src/dh.c
index 8ffe1ba..a28d376 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/dh.h b/src/dh.h
index facf043..788b20f 100644
--- a/src/dh.h
+++ b/src/dh.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/mem.c b/src/mem.c
index b2a2191..075f3c0 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/mem.h b/src/mem.h
index 19e00cf..e1f5a1e 100644
--- a/src/mem.h
+++ b/src/mem.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/message.c b/src/message.c
index c61cd13..dcc18db 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -42,6 +43,76 @@ extern unsigned int otrl_api_version;
* resending in response to a rekey? */
#define RESEND_INTERVAL 60
+/* Send a message to the network, fragmenting first if necessary.
+ * All messages to be sent to the network should go through this
+ * method immediately before they are sent, ie after encryption. */
+static gcry_error_t fragment_and_send(const OtrlMessageAppOps *ops,
+ void *opdata, ConnContext *context, const char *message,
+ OtrlFragmentPolicy fragPolicy, char **returnFragment)
+{
+ int mms = 0;
+ if (message && ops->inject_message) {
+ int msglen;
+
+ if (otrl_api_version >= 0x030100 && ops->max_message_size) {
+ mms = ops->max_message_size(opdata, context);
+ }
+ msglen = strlen(message);
+
+ /* Don't incur overhead of fragmentation unless necessary */
+ if(mms != 0 && msglen > mms) {
+ char **fragments;
+ gcry_error_t err;
+ int i;
+ int fragment_count = ((msglen - 1) / (mms -19)) + 1;
+ /* like ceil(msglen/(mms - 19)) */
+
+ err = otrl_proto_fragment_create(mms, fragment_count, &fragments,
+ message);
+ if (err) {
+ return err;
+ }
+
+ /* Determine which fragments to send and which to return
+ * based on given Fragment Policy. If the first fragment
+ * should be returned instead of sent, store it. */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_FIRST) {
+ *returnFragment = strdup(fragments[0]);
+ } else {
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username, fragments[0]);
+ }
+ for (i=1; i<fragment_count-1; i++) {
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username, fragments[i]);
+ }
+ /* If the last fragment should be stored instead of sent,
+ * store it */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_LAST) {
+ *returnFragment = strdup(fragments[fragment_count-1]);
+ } else {
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username, fragments[fragment_count-1]);
+ }
+ /* Now free all fragment memory */
+ otrl_proto_fragment_free(&fragments, fragment_count);
+
+ } else {
+ /* No fragmentation necessary */
+ if (fragPolicy == OTRL_FRAGMENT_SEND_ALL) {
+ ops->inject_message(opdata, context->accountname,
+ context->protocol, context->username, message);
+ } else {
+ /* Copy and return the entire given message. */
+ int l = strlen(message) + 1;
+ *returnFragment = malloc(sizeof(char)*l);
+ strcpy(*returnFragment, message);
+ }
+ }
+ }
+ return gcry_error(GPG_ERR_NO_ERROR);
+}
+
/* Deallocate a message allocated by other otrl_message_* routines. */
void otrl_message_free(char *message)
{
@@ -55,37 +126,51 @@ void otrl_message_free(char *message)
* pointer to the new ConnContext. You can use this to add
* application-specific information to the ConnContext using the
* "context->app" field, for example. If you don't need to do this, you
- * can pass NULL for the last two arguments of otrl_message_sending.
+ * can pass NULL for the last two arguments of otrl_message_sending.
*
* tlvs is a chain of OtrlTLVs to append to the private message. It is
* usually correct to just pass NULL here.
*
- * If this routine returns non-zero, then the library tried to encrypt
- * the message, but for some reason failed. DO NOT send the message in
- * the clear in that case.
- *
- * If *messagep gets set by the call to something non-NULL, then you
- * should replace your message with the contents of *messagep, and
- * send that instead. Call otrl_message_free(*messagep) when you're
+ * If no fragmentation or msg injection is wanted, use OTRL_FRAGMENT_SEND_SKIP
+ * as the OtrlFragmentPolicy. In this case, this function will assign *messagep
+ * with the encrypted msg. If the routine returns non-zero, then the library
+ * tried to encrypt the message, but for some reason failed. DO NOT send the
+ * message in the clear in that case. If *messagep gets set by the call to
+ * something non-NULL, then you should replace your message with the contents
+ * of *messagep, and send that instead.
+ *
+ * Other fragmentation policies are OTRL_FRAGMENT_SEND_ALL,
+ * OTRL_FRAGMENT_SEND_ALL_BUT_LAST, or OTRL_FRAGMENT_SEND_ALL_BUT_FIRST. In these
+ * cases, the appropriate fragments will be automatically sent. For the last two
+ * policies, the remaining fragment will be passed in *original_msg.
+ *
+ * Call otrl_message_free(*messagep) if you don't need *messagep or if you're
* done with it. */
gcry_error_t otrl_message_sending(OtrlUserState us,
const OtrlMessageAppOps *ops,
void *opdata, const char *accountname, const char *protocol,
- const char *recipient, const char *message, OtrlTLV *tlvs,
- char **messagep,
+ const char *recipient, char **original_msgp, OtrlTLV *tlvs,
+ char **messagep, OtrlFragmentPolicy fragPolicy,
+ void (*convert_msg)(void *convert_data, const char *source, char **target),
+ void *convert_data,
void (*add_appdata)(void *data, ConnContext *context),
void *data)
{
struct context * context;
char * msgtosend;
- gcry_error_t err;
+ const char * err_msg;
+ gcry_error_t err_code, err;
OtrlPolicy policy = OTRL_POLICY_DEFAULT;
int context_added = 0;
*messagep = NULL;
+ err = gcry_error(GPG_ERR_NO_ERROR); /* Default to no error */
- if (!accountname || !protocol || !recipient || !message || !messagep)
- return gcry_error(GPG_ERR_NO_ERROR);
+ if (!accountname || !protocol || !recipient ||
+ !original_msgp || !*original_msgp || !messagep) {
+ err = gcry_error(GPG_ERR_NO_ERROR);
+ goto fragment;
+ }
/* See if we have a fingerprint for this user */
context = otrl_context_find(us, recipient, accountname, protocol,
@@ -103,7 +188,8 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
/* Should we go on at all? */
if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
- return gcry_error(GPG_ERR_NO_ERROR);
+ err = gcry_error(GPG_ERR_NO_ERROR);
+ goto fragment;
}
/* XXX: Add flags to the policy specifying whether to treat a typed
@@ -111,13 +197,14 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
* for (1) unencrypted conversations, (2) encrypted conversations. */
/* If this is an OTR Query message, don't encrypt it. */
- if (otrl_proto_message_type(message) == OTRL_MSGTYPE_QUERY) {
+ if (otrl_proto_message_type(*original_msgp) == OTRL_MSGTYPE_QUERY) {
/* Replace the "?OTR?" with a custom message */
char *bettermsg = otrl_proto_default_query_msg(accountname, policy);
if (bettermsg) {
*messagep = bettermsg;
}
- return gcry_error(GPG_ERR_NO_ERROR);
+ err = gcry_error(GPG_ERR_NO_ERROR);
+ goto fragment;
}
/* What is the current message disposition? */
@@ -127,38 +214,25 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
/* We're trying to send an unencrypted message with a policy
* that disallows that. Don't do that, but try to start
* up OTR instead. */
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata, accountname,
- protocol, recipient, "Attempting to start a "
- "private conversation...")) && ops->notify) {
- const char *format = "You attempted to send an "
- "unencrypted message to %s";
- char *primary = malloc(strlen(format) +
- strlen(recipient) - 1);
- if (primary) {
- sprintf(primary, format, recipient);
- ops->notify(opdata, OTRL_NOTIFY_WARNING, accountname,
- protocol, recipient, "OTR Policy Violation",
- primary,
- "Unencrypted messages to this recipient are "
- "not allowed. Attempting to start a private "
- "conversation.\n\nYour message will be "
- "retransmitted when the private conversation "
- "starts.");
- free(primary);
- }
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_ENCRYPTION_REQUIRED,
+ context, NULL, (gcry_error_t)NULL);
}
- context->lastmessage = gcry_malloc_secure(strlen(message) + 1);
- if (context->lastmessage) {
+
+ context->context_priv->lastmessage =
+ gcry_malloc_secure(strlen(*original_msgp) + 1);
+ if (context->context_priv->lastmessage) {
char *bettermsg = otrl_proto_default_query_msg(accountname,
policy);
- strcpy(context->lastmessage, message);
- context->lastsent = time(NULL);
- context->may_retransmit = 2;
+ strcpy(context->context_priv->lastmessage, *original_msgp);
+ context->context_priv->lastsent = time(NULL);
+ context->context_priv->may_retransmit = 2;
if (bettermsg) {
*messagep = bettermsg;
} else {
- return gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
+ goto fragment;
}
}
} else {
@@ -167,7 +241,7 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
/* See if this user can speak OTR. Append the
* OTR_MESSAGE_TAG to the plaintext message, and see
* if he responds. */
- size_t msglen = strlen(message);
+ size_t msglen = strlen(*original_msgp);
size_t basetaglen = strlen(OTRL_MESSAGE_TAG_BASE);
size_t v1taglen = (policy & OTRL_POLICY_ALLOW_V1) ?
strlen(OTRL_MESSAGE_TAG_V1) : 0;
@@ -176,7 +250,7 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
char *taggedmsg = malloc(msglen + basetaglen + v1taglen
+v2taglen + 1);
if (taggedmsg) {
- strcpy(taggedmsg, message);
+ strcpy(taggedmsg, *original_msgp);
strcpy(taggedmsg + msglen, OTRL_MESSAGE_TAG_BASE);
if (v1taglen) {
strcpy(taggedmsg + msglen + basetaglen,
@@ -195,59 +269,83 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
}
break;
case OTRL_MSGSTATE_ENCRYPTED:
+ /* convert the original message if necessary */
+ if (convert_msg) {
+ /* using msgtosend as a temporary placeholder */
+ msgtosend = *original_msgp;
+ convert_msg(convert_data, msgtosend, original_msgp);
+ free(msgtosend);
+ msgtosend = NULL;
+ }
+
/* Create the new, encrypted message */
- err = otrl_proto_create_data(&msgtosend, context, message, tlvs,
- 0, NULL);
- if (!err) {
- context->lastsent = time(NULL);
+ err_code = otrl_proto_create_data(&msgtosend, context,
+ *original_msgp, tlvs, 0, NULL);
+ if (!err_code) {
+ context->context_priv->lastsent = time(NULL);
*messagep = msgtosend;
} else {
/* Uh, oh. Whatever we do, *don't* send the message in the
* clear. */
- *messagep = strdup("?OTR Error: Error occurred encrypting "
- "message");
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata, accountname,
- protocol, recipient, "An error occurred when "
- "encrypting your message. The message was not "
- "sent.")) && ops->notify) {
- ops->notify(opdata, OTRL_NOTIFY_ERROR,
- accountname, protocol, recipient,
- "Error encrypting message",
- "An error occurred when encrypting your message",
- "The message was not sent.");
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata, OTRL_MSGEVENT_ENCRYPTION_ERROR,
+ context, NULL, (gcry_error_t)NULL);
}
- if (!(*messagep)) {
- return gcry_error(GPG_ERR_ENOMEM);
+ if (ops->otr_error_message) {
+ err_msg = ops->otr_error_message(opdata, context,
+ OTRL_ERRCODE_ENCRYPTION_ERROR);
+ *messagep = malloc(strlen(OTR_ERROR_PREFIX) +
+ strlen(err_msg) + 1);
+ if (*messagep) {
+ strcpy(*messagep, OTR_ERROR_PREFIX);
+ strcat(*messagep, err_msg);
+ }
+ if (ops->otr_error_message_free) {
+ ops->otr_error_message_free(opdata, err_msg);
+ }
+ if (!(*messagep)) {
+ err = gcry_error(GPG_ERR_ENOMEM);
+ goto fragment;
+ }
}
}
break;
case OTRL_MSGSTATE_FINISHED:
- *messagep = strdup("");
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata, accountname,
- protocol, recipient, "Your message was not sent. "
- "Either end your private conversation, or restart "
- "it.")) && ops->notify) {
- const char *fmt = "%s has already closed his/her private "
- "connection to you";
- char *primary = malloc(strlen(fmt) + strlen(recipient) - 1);
- if (primary) {
- sprintf(primary, fmt, recipient);
- ops->notify(opdata, OTRL_NOTIFY_ERROR,
- accountname, protocol, recipient,
- "Private connection closed", primary,
- "Your message was not sent. Either close your "
- "private connection to him, or refresh it.");
- }
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata, OTRL_MSGEVENT_CONNECTION_ENDED,
+ context, NULL, (gcry_error_t)NULL);
}
+ *messagep = strdup("");
if (!(*messagep)) {
- return gcry_error(GPG_ERR_ENOMEM);
+ err = gcry_error(GPG_ERR_ENOMEM);
+ goto fragment;
}
break;
}
- return gcry_error(GPG_ERR_NO_ERROR);
+fragment:
+ if (fragPolicy == OTRL_FRAGMENT_SEND_SKIP ) {
+ /* Do not fragment/inject. Default behaviour of libotr3.2.0 */
+ return err;
+ } else {
+ /* Fragment and send according to policy */
+ if (err && *messagep == NULL) {
+ /* Do not send plaintext */
+ char *ourm = strdup("");
+ free(*original_msgp);
+ *original_msgp = ourm;
+ } else if (*messagep) {
+ ConnContext *conncontext = otrl_context_find(us, recipient,
+ accountname, protocol, 0, NULL, NULL, NULL);
+ free(*original_msgp);
+ *original_msgp = NULL;
+ if (conncontext) {
+ err = fragment_and_send(ops, NULL, conncontext, *messagep,
+ fragPolicy, original_msgp);
+ }
+ }
+ return err;
+ }
}
/* If err == 0, send the last auth message for the given context to the
@@ -259,38 +357,15 @@ static gcry_error_t send_or_error_auth(const OtrlMessageAppOps *ops,
if (!err) {
const char *msg = context->auth.lastauthmsg;
if (msg && *msg) {
- otrl_message_fragment_and_send(ops, opdata, context, msg, OTRL_FRAGMENT_SEND_ALL, NULL);
- /*if (ops->inject_message) {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, msg);
- }*/
+ fragment_and_send(ops, opdata, context, msg,
+ OTRL_FRAGMENT_SEND_ALL, NULL);
+ context->context_priv->lastsent = time(NULL);
}
} else {
- const char *buf_format = "Error setting up private conversation: %s";
- const char *strerr;
- char *buf;
-
- switch(gcry_err_code(err)) {
- case GPG_ERR_INV_VALUE:
- strerr = "Malformed message received";
- break;
- default:
- strerr = gcry_strerror(err);
- break;
- }
- buf = malloc(strlen(buf_format) + strlen(strerr) - 1);
- if (buf) {
- sprintf(buf, buf_format, strerr);
- }
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata, context->accountname,
- context->protocol, context->username, buf))
- && ops->notify) {
- ops->notify(opdata, OTRL_NOTIFY_ERROR, context->accountname,
- context->protocol, context->username, "OTR error",
- buf, NULL);
- }
- free(buf);
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata, OTRL_MSGEVENT_SETUP_ERROR,
+ context, NULL, err);
+ }
}
return err;
}
@@ -316,23 +391,12 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
/* See if we're talking to ourselves */
if (!gcry_mpi_cmp(auth->their_pub, auth->our_dh.pub)) {
- /* Yes, we are. */
- if ((!(edata->ops->display_otr_message) ||
- edata->ops->display_otr_message(edata->opdata,
- edata->context->accountname, edata->context->protocol,
- edata->context->username,
- "We are receiving our own OTR messages. "
- "You are either trying to talk to yourself, "
- "or someone is reflecting your messages back "
- "at you.")) && edata->ops->notify) {
- edata->ops->notify(edata->opdata, OTRL_NOTIFY_ERROR,
- edata->context->accountname, edata->context->protocol,
- edata->context->username, "OTR Error",
- "We are receiving our own OTR messages.",
- "You are either trying to talk to yourself, "
- "or someone is reflecting your messages back "
- "at you.");
- }
+ /* Yes, we are. */
+ if (edata->ops->handle_msg_event) {
+ edata->ops->handle_msg_event(edata->opdata,
+ OTRL_MSGEVENT_MSG_REFLECTED, edata->context,
+ NULL, (gcry_error_t)NULL);
+ }
edata->ignore_message = 1;
return gcry_error(GPG_ERR_NO_ERROR);
}
@@ -357,19 +421,19 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
/* Is this a new session or just a refresh of an existing one? */
if (edata->context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
oldprint == found_print &&
- edata->context->our_keyid - 1 == edata->context->auth.our_keyid &&
- !gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
+ edata->context->context_priv->our_keyid - 1 == edata->context->auth.our_keyid &&
+ !gcry_mpi_cmp(edata->context->context_priv->our_old_dh_key.pub,
edata->context->auth.our_dh.pub) &&
- ((edata->context->their_keyid > 0 &&
- edata->context->their_keyid ==
+ ((edata->context->context_priv->their_keyid > 0 &&
+ edata->context->context_priv->their_keyid ==
edata->context->auth.their_keyid &&
- !gcry_mpi_cmp(edata->context->their_y,
+ !gcry_mpi_cmp(edata->context->context_priv->their_y,
edata->context->auth.their_pub)) ||
- (edata->context->their_keyid > 1 &&
- edata->context->their_keyid - 1 ==
+ (edata->context->context_priv->their_keyid > 1 &&
+ edata->context->context_priv->their_keyid - 1 ==
edata->context->auth.their_keyid &&
- edata->context->their_old_y != NULL &&
- !gcry_mpi_cmp(edata->context->their_old_y,
+ edata->context->context_priv->their_old_y != NULL &&
+ !gcry_mpi_cmp(edata->context->context_priv->their_old_y,
edata->context->auth.their_pub)))) {
/* This is just a refresh of the existing session. */
if (edata->ops->still_secure) {
@@ -390,35 +454,35 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
edata->context->protocol_version =
edata->context->auth.protocol_version;
- edata->context->their_keyid = edata->context->auth.their_keyid;
- gcry_mpi_release(edata->context->their_y);
- gcry_mpi_release(edata->context->their_old_y);
- edata->context->their_y = gcry_mpi_copy(edata->context->auth.their_pub);
- edata->context->their_old_y = NULL;
+ edata->context->context_priv->their_keyid = edata->context->auth.their_keyid;
+ gcry_mpi_release(edata->context->context_priv->their_y);
+ gcry_mpi_release(edata->context->context_priv->their_old_y);
+ edata->context->context_priv->their_y = gcry_mpi_copy(edata->context->auth.their_pub);
+ edata->context->context_priv->their_old_y = NULL;
- if (edata->context->our_keyid - 1 != edata->context->auth.our_keyid ||
- gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
+ if (edata->context->context_priv->our_keyid - 1 != edata->context->auth.our_keyid ||
+ gcry_mpi_cmp(edata->context->context_priv->our_old_dh_key.pub,
edata->context->auth.our_dh.pub)) {
- otrl_dh_keypair_free(&(edata->context->our_dh_key));
- otrl_dh_keypair_free(&(edata->context->our_old_dh_key));
- otrl_dh_keypair_copy(&(edata->context->our_old_dh_key),
+ otrl_dh_keypair_free(&(edata->context->context_priv->our_dh_key));
+ otrl_dh_keypair_free(&(edata->context->context_priv->our_old_dh_key));
+ otrl_dh_keypair_copy(&(edata->context->context_priv->our_old_dh_key),
&(edata->context->auth.our_dh));
- otrl_dh_gen_keypair(edata->context->our_old_dh_key.groupid,
- &(edata->context->our_dh_key));
- edata->context->our_keyid = edata->context->auth.our_keyid + 1;
+ otrl_dh_gen_keypair(edata->context->context_priv->our_old_dh_key.groupid,
+ &(edata->context->context_priv->our_dh_key));
+ edata->context->context_priv->our_keyid = edata->context->auth.our_keyid + 1;
}
/* Create the session keys from the DH keys */
- otrl_dh_session_free(&(edata->context->sesskeys[0][0]));
- err = otrl_dh_session(&(edata->context->sesskeys[0][0]),
- &(edata->context->our_dh_key), edata->context->their_y);
+ otrl_dh_session_free(&(edata->context->context_priv->sesskeys[0][0]));
+ err = otrl_dh_session(&(edata->context->context_priv->sesskeys[0][0]),
+ &(edata->context->context_priv->our_dh_key), edata->context->context_priv->their_y);
if (err) return err;
- otrl_dh_session_free(&(edata->context->sesskeys[1][0]));
- err = otrl_dh_session(&(edata->context->sesskeys[1][0]),
- &(edata->context->our_old_dh_key), edata->context->their_y);
+ otrl_dh_session_free(&(edata->context->context_priv->sesskeys[1][0]));
+ err = otrl_dh_session(&(edata->context->context_priv->sesskeys[1][0]),
+ &(edata->context->context_priv->our_old_dh_key), edata->context->context_priv->their_y);
if (err) return err;
- edata->context->generation++;
+ edata->context->context_priv->generation++;
edata->context->active_fingerprint = found_print;
edata->context->msgstate = OTRL_MSGSTATE_ENCRYPTED;
@@ -450,51 +514,62 @@ static void maybe_resend(EncrData *edata)
/* See if there's a message we sent recently that should be resent. */
now = time(NULL);
- if (edata->context->lastmessage != NULL &&
- edata->context->may_retransmit &&
- edata->context->lastsent >= (now - RESEND_INTERVAL)) {
+ if (edata->context->context_priv->lastmessage != NULL &&
+ edata->context->context_priv->may_retransmit &&
+ edata->context->context_priv->lastsent >= (now - RESEND_INTERVAL)) {
char *resendmsg;
- int resending = (edata->context->may_retransmit == 1);
+ char *msg_to_send;
+ int resending = (edata->context->context_priv->may_retransmit == 1);
+
+ /* Initialize msg_to_send */
+ if (resending) {
+ const char *resent_prefix;
+ int used_ops_resentmp = 1;
+ resent_prefix = edata->ops->resent_msg_prefix ?
+ edata->ops->resent_msg_prefix(edata->opdata,
+ edata->context) : NULL;
+ if (!resent_prefix) {
+ resent_prefix = "[resent]"; /* Assign default prefix */
+ used_ops_resentmp = 0;
+ }
+ msg_to_send = malloc(
+ strlen(edata->context->context_priv->lastmessage) +
+ strlen(resent_prefix) + 2);
+ if (msg_to_send) {
+ strcpy(msg_to_send, resent_prefix);
+ strcat(msg_to_send, " ");
+ strcat(msg_to_send, edata->context->context_priv->lastmessage);
+ }
+ if (used_ops_resentmp) {
+ edata->ops->resent_msg_prefix_free(edata->opdata,
+ resent_prefix);
+ }
+ } else {
+ msg_to_send = edata->context->context_priv->lastmessage;
+ }
/* Re-encrypt the message with the new keys */
err = otrl_proto_create_data(&resendmsg,
- edata->context, edata->context->lastmessage, NULL, 0, NULL);
+ edata->context, msg_to_send, NULL, 0, NULL);
+ if (resending && msg_to_send) {
+ free(msg_to_send);
+ }
if (!err) {
- const char *format = "<b>The last message "
- "to %s was resent.</b>";
- char *buf;
-
/* Resend the message */
- otrl_message_fragment_and_send(edata->ops, edata->opdata, edata->context, resendmsg, OTRL_FRAGMENT_SEND_ALL, NULL);
+ fragment_and_send(edata->ops, edata->opdata, edata->context,
+ resendmsg, OTRL_FRAGMENT_SEND_ALL, NULL);
free(resendmsg);
- edata->context->lastsent = now;
-
- if (!resending) {
- /* We're actually just sending it
- * for the first time. */
- edata->ignore_message = 1;
- } else {
- /* Let the user know we resent it */
- buf = malloc(strlen(format) +
- strlen(edata->context->username) - 1);
- if (buf) {
- sprintf(buf, format, edata->context->username);
- if (edata->ops->display_otr_message) {
- if (!edata->ops->display_otr_message(
- edata->opdata, edata->context->accountname,
- edata->context->protocol,
- edata->context->username, buf)) {
- edata->ignore_message = 1;
- }
- }
- if (edata->ignore_message != 1) {
- *(edata->messagep) = buf;
- edata->ignore_message = 0;
- } else {
- free(buf);
- }
+ edata->context->context_priv->lastsent = now;
+ if (resending) {
+ /* We're not sending it for the first time; let the user
+ * know we resent it */
+ if (edata->ops->handle_msg_event) {
+ edata->ops->handle_msg_event(edata->opdata,
+ OTRL_MSGEVENT_MSG_RESENT, edata->context,
+ NULL, (gcry_error_t)NULL);
}
}
+ edata->ignore_message = 1;
}
}
}
@@ -589,7 +664,7 @@ static void init_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
if (!err) {
/* Send it, and set the next expected message to the
* logical response */
- err = otrl_message_fragment_and_send(ops, opdata, context,
+ err = fragment_and_send(ops, opdata, context,
sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
context->smstate->nextExpected =
initiating ? OTRL_SMP_EXPECT2 : OTRL_SMP_EXPECT3;
@@ -633,7 +708,7 @@ void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
(const unsigned char *)"");
char *sendsmp = NULL;
gcry_error_t err;
-
+
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
err = otrl_proto_create_data(&sendsmp,
@@ -641,7 +716,7 @@ void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_MSGFLAGS_IGNORE_UNREADABLE, NULL);
if (!err) {
/* Send the abort signal so our buddy knows we've stopped */
- err = otrl_message_fragment_and_send(ops, opdata, context,
+ err = fragment_and_send(ops, opdata, context,
sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
}
free(sendsmp);
@@ -655,7 +730,10 @@ void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
* a pointer to the new ConnContext. You can use this to add
* application-specific information to the ConnContext using the
* "context->app" field, for example. If you don't need to do this, you
- * can pass NULL for the last two arguments of otrl_message_receiving.
+ * can pass NULL for the last two arguments of otrl_message_receiving.
+ *
+ * convert_msg is a function that will be called on each msg that is received.
+ * You can use it to perform some tweaks on your incoming messages.
*
* If otrl_message_receiving returns 1, then the message you received
* was an internal protocol message, and no message should be delivered
@@ -676,6 +754,8 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, const char *accountname, const char *protocol,
const char *sender, const char *message, char **newmessagep,
OtrlTLV **tlvsp,
+ void (*convert_msg)(void *convert_data, const char *source, char **target),
+ void *convert_data,
void (*add_appdata)(void *data, ConnContext *context),
void *data)
{
@@ -763,8 +843,8 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
/* See if we should use an existing DH keypair, or generate
* a fresh one. */
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
- our_dh = &(context->our_old_dh_key);
- our_keyid = context->our_keyid - 1;
+ our_dh = &(context->context_priv->our_old_dh_key);
+ our_keyid = context->context_priv->our_keyid - 1;
} else {
our_dh = NULL;
our_keyid = 0;
@@ -875,7 +955,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
maybe_resend(&edata);
}
}
-
+
if (edata.ignore_message == -1) edata.ignore_message = 1;
break;
@@ -884,8 +964,8 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
/* See if we should use an existing DH keypair, or generate
* a fresh one. */
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
- our_dh = &(context->our_old_dh_key);
- our_keyid = context->our_keyid - 1;
+ our_dh = &(context->context_priv->our_old_dh_key);
+ our_keyid = context->context_priv->our_keyid - 1;
} else {
our_dh = NULL;
our_keyid = 0;
@@ -913,7 +993,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
}
}
}
-
+
if (edata.ignore_message == -1) edata.ignore_message = 1;
break;
@@ -923,8 +1003,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OtrlTLV *tlvs, *tlv;
char *plaintext;
char *buf;
- const char *format;
- const char *displayaccountname;
+ const char *err_msg;
unsigned char *extrakey;
unsigned char flags;
NextExpectedSMP nextMsg;
@@ -938,92 +1017,76 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
edata.ignore_message = 1;
break;
}
-
- /* Don't use g_strdup_printf here, because someone
- * (not us) is going to free() the *newmessagep pointer,
- * not g_free() it. */
- format = "<b>The encrypted message received from %s is "
- "unreadable, as you are not currently communicating "
- "privately.</b>";
- buf = malloc(strlen(format) + strlen(context->username)
- - 1); /* Remove "%s", add username + '\0' */
- if (buf) {
- sprintf(buf, format, context->username);
- if (ops->display_otr_message) {
- if (!ops->display_otr_message(opdata, accountname,
- protocol, sender, buf)) {
- edata.ignore_message = 1;
- }
- }
- if (edata.ignore_message != 1) {
- *newmessagep = buf;
- edata.ignore_message = 0;
- } else {
- free(buf);
- }
- }
- format = "?OTR Error: You sent encrypted "
- "data to %s, who wasn't expecting it.";
- if (otrl_api_version >= 0x00030100 &&
- ops->account_name) {
- displayaccountname = ops->account_name(opdata,
- context->accountname, protocol);
- } else {
- displayaccountname = NULL;
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE,
+ context, NULL, (gcry_error_t)NULL);
}
- buf = malloc(strlen(format) + strlen(displayaccountname ?
- displayaccountname : context->accountname)
- - 1);
- if (buf) {
- sprintf(buf, format, displayaccountname ?
- displayaccountname : context->accountname);
- if (ops->inject_message) {
+ edata.ignore_message = 1;
+ if (ops->inject_message && ops->otr_error_message) {
+ err_msg = ops->otr_error_message(opdata, context,
+ OTRL_ERRCODE_MSG_NOT_IN_PRIVATE);
+ buf = malloc(strlen(OTR_ERROR_PREFIX) +
+ strlen(err_msg) + 1);
+ if (buf) {
+ strcpy(buf, OTR_ERROR_PREFIX);
+ strcat(buf, err_msg);
ops->inject_message(opdata, accountname, protocol,
sender, buf);
- }
- free(buf);
- }
- if (displayaccountname && otrl_api_version >= 0x00030100 &&
- ops->account_name_free) {
- ops->account_name_free(opdata, displayaccountname);
+ free(buf);
+ }
+ if (ops->otr_error_message_free) {
+ ops->otr_error_message_free(opdata, err_msg);
+ }
}
-
break;
case OTRL_MSGSTATE_ENCRYPTED:
extrakey = gcry_malloc_secure(OTRL_EXTRAKEY_BYTES);
err = otrl_proto_accept_data(&plaintext, &tlvs, context,
- message, &flags, extrakey);
+ message, &flags, extrakey);
if (err) {
int is_conflict =
- (gpg_err_code(err) == GPG_ERR_CONFLICT);
+ (gpg_err_code(err) == GPG_ERR_CONFLICT);
if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
edata.ignore_message = 1;
break;
}
- format = is_conflict ? "We received an unreadable "
- "encrypted message from %s." :
- "We received a malformed data message from %s.";
- buf = malloc(strlen(format) + strlen(sender) - 1);
- if (buf) {
- sprintf(buf, format, sender);
- if ((!(ops->display_otr_message) ||
- ops->display_otr_message(opdata,
- accountname, protocol, sender,
- buf)) && ops->notify) {
- ops->notify(opdata, OTRL_NOTIFY_ERROR,
- accountname, protocol, sender,
- "OTR Error", buf, NULL);
+ if (is_conflict) {
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_UNREADABLE,
+ context, NULL, (gcry_error_t)NULL);
+ }
+ } else {
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_MALFORMED,
+ context, NULL, (gcry_error_t)NULL);
}
- free(buf);
}
- if (ops->inject_message) {
- ops->inject_message(opdata, accountname, protocol,
- sender, is_conflict ? "?OTR Error: "
- "You transmitted an unreadable "
- "encrypted message." :
- "?OTR Error: You transmitted "
- "a malformed data message");
+ if (ops->inject_message && ops->otr_error_message) {
+ err_msg = ops->otr_error_message(opdata,
+ context,
+ is_conflict ?
+ OTRL_ERRCODE_MSG_UNREADABLE :
+ OTRL_ERRCODE_MSG_MALFORMED);
+ if (err_msg) {
+ buf = malloc(strlen(OTR_ERROR_PREFIX) +
+ strlen(err_msg) + 1);
+ if (buf) {
+ strcpy(buf, OTR_ERROR_PREFIX);
+ strcat(buf, err_msg);
+ ops->inject_message(opdata,
+ accountname, protocol,
+ sender, buf);
+ free(buf);
+ }
+ }
+ if (ops->otr_error_message_free) {
+ ops->otr_error_message_free(opdata,
+ err_msg);
+ }
}
edata.ignore_message = 1;
break;
@@ -1094,7 +1157,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
}
}
}
-
+
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
if (tlv) {
if (nextMsg == OTRL_SMP_EXPECT1) {
@@ -1129,7 +1192,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
}
}
}
-
+
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
if (tlv) {
if (nextMsg == OTRL_SMP_EXPECT2) {
@@ -1139,7 +1202,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
char *sendsmp;
otrl_sm_step3(context->smstate, tlv->data,
tlv->len, &nextmsg, &nextmsglen);
-
+
if (context->smstate->sm_prog_state !=
OTRL_SMP_PROG_CHEATED) {
/* Send msg with next smp msg content */
@@ -1150,7 +1213,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_MSGFLAGS_IGNORE_UNREADABLE,
NULL);
if (!err) {
- err = otrl_message_fragment_and_send(ops,
+ err = fragment_and_send(ops,
opdata, context, sendsmp,
OTRL_FRAGMENT_SEND_ALL, NULL);
}
@@ -1182,9 +1245,9 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_SMPEVENT_ERROR, context,
0, NULL);
}
- }
+ }
}
-
+
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
if (tlv) {
if (nextMsg == OTRL_SMP_EXPECT3) {
@@ -1199,7 +1262,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
set_smp_trust(ops, opdata, context,
(err == gcry_error(GPG_ERR_NO_ERROR)));
}
-
+
if (context->smstate->sm_prog_state !=
OTRL_SMP_PROG_CHEATED) {
/* Send msg with next smp msg content */
@@ -1210,7 +1273,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_MSGFLAGS_IGNORE_UNREADABLE,
NULL);
if (!err) {
- err = otrl_message_fragment_and_send(ops,
+ err = fragment_and_send(ops,
opdata, context, sendsmp,
OTRL_FRAGMENT_SEND_ALL, NULL);
}
@@ -1246,9 +1309,9 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_SMPEVENT_ERROR, context,
0, NULL);
}
- }
+ }
}
-
+
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
if (tlv) {
if (nextMsg == OTRL_SMP_EXPECT4) {
@@ -1288,9 +1351,9 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
OTRL_SMPEVENT_ERROR, context,
0, NULL);
}
- }
+ }
}
-
+
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
if (tlv) {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
@@ -1303,23 +1366,20 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
if (plaintext[0] == '\0') {
/* If it's a heartbeat (an empty message), don't
* display it to the user, but log a debug message. */
- format = "Heartbeat received from %s.\n";
- buf = malloc(strlen(format) + strlen(sender) - 1);
- if (buf) {
- sprintf(buf, format, sender);
- if (ops->log_message) {
- ops->log_message(opdata, buf);
- }
- free(buf);
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD,
+ context, NULL, (gcry_error_t)NULL);
}
edata.ignore_message = 1;
- } else if (edata.ignore_message == 0 &&
- context->their_keyid > 0) {
+ } else if (edata.ignore_message != 1 &&
+ context->context_priv->their_keyid > 0) {
/* If it's *not* a heartbeat, and we haven't
* sent anything in a while, also send a
* heartbeat. */
time_t now = time(NULL);
- if (context->lastsent < (now - HEARTBEAT_INTERVAL)) {
+ if (context->context_priv->lastsent <
+ (now - HEARTBEAT_INTERVAL)) {
char *heartbeat;
/* Create the heartbeat message */
@@ -1335,18 +1395,13 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
}
free(heartbeat);
- context->lastsent = now;
+ context->context_priv->lastsent = now;
- /* Log a debug message */
- format = "Heartbeat sent to %s.\n";
- buf = malloc(strlen(format) + strlen(sender)
- - 1);
- if (buf) {
- sprintf(buf, format, sender);
- if (ops->log_message) {
- ops->log_message(opdata, buf);
- }
- free(buf);
+ /* Log the heartbeat message */
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_LOG_HEARTBEAT_SENT,
+ context, NULL, (gcry_error_t)NULL);
}
}
}
@@ -1361,8 +1416,17 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
}
if (edata.ignore_message != 1) {
- *newmessagep = plaintext;
- edata.ignore_message = 0;
+ *newmessagep = plaintext;
+ edata.ignore_message = 0;
+ /* convert the original message if necessary */
+ if (convert_msg && *newmessagep) {
+ char *original_msg;
+ original_msg = *newmessagep;
+ convert_msg(convert_data, original_msg,
+ newmessagep);
+ free(original_msg);
+ original_msg = NULL;
+ }
} else {
free(plaintext);
}
@@ -1382,27 +1446,31 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
free(msgtosend);
}
- if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
- /* Mark the last message we sent as eligible for
- * retransmission */
- context->may_retransmit = 1;
- }
+ if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
+ /* Mark the last message we sent as eligible for
+ * retransmission */
+ context->context_priv->may_retransmit = 1;
+ }
- /* In any event, display the error message, with the
- * display_otr_message callback, if possible */
- if (ops->display_otr_message) {
- const char *otrerror = strstr(message, "?OTR Error:");
- if (otrerror) {
- /* Skip the leading '?' */
- ++otrerror;
- } else {
- otrerror = message;
- }
- if (!ops->display_otr_message(opdata, accountname, protocol,
- sender, otrerror)) {
- edata.ignore_message = 1;
- }
+ /* In any event, display the error message, with the
+ * display_otr_message callback, if possible */
+ if (ops->handle_msg_event) {
+ /* Remove the OTR error prefix and pass the msg */
+ const char *just_err_msg = strstr(message, OTR_ERROR_PREFIX);
+ if (!just_err_msg) {
+ just_err_msg = message;
+ } else {
+ just_err_msg += (strlen(OTR_ERROR_PREFIX));
+ if (*just_err_msg == ' ') {
+ /* Advance pointer to skip the space character */
+ just_err_msg++;
+ }
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR,
+ context, just_err_msg, (gcry_error_t)NULL);
+ }
}
+ edata.ignore_message = 1;
break;
case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
@@ -1459,49 +1527,25 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
(policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
/* Not fine. Let the user know. */
-
- /* Don't use g_strdup_printf here, because someone
- * (not us) is going to free() the *message pointer,
- * not g_free() it. */
const char *plainmsg = (*newmessagep) ? *newmessagep : message;
- const char *format = "<b>The following message received "
- "from %s was <i>not</i> encrypted: [</b>%s<b>]</b>";
- char *buf = malloc(strlen(format) + strlen(context->username)
- + strlen(plainmsg) - 3);
- /* Remove "%s%s", add username + message + '\0' */
- if (buf) {
- sprintf(buf, format, context->username, plainmsg);
- if (ops->display_otr_message) {
- if (!ops->display_otr_message(opdata, accountname,
- protocol, sender, buf)) {
- free(*newmessagep);
- *newmessagep = NULL;
- edata.ignore_message = 1;
- }
- }
- if (edata.ignore_message != 1) {
- free(*newmessagep);
- *newmessagep = buf;
- edata.ignore_message = 0;
- } else {
- free(buf);
- }
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED,
+ context, plainmsg, (gcry_error_t)NULL);
}
+ free(*newmessagep);
+ *newmessagep = NULL;
+ edata.ignore_message = 1;
}
break;
case OTRL_MSGTYPE_UNKNOWN:
/* We received an OTR message we didn't recognize. Ignore
* it, but make a log entry. */
- if (ops->log_message) {
- const char *format = "Unrecognized OTR message received "
- "from %s.\n";
- char *buf = malloc(strlen(format) + strlen(sender) - 1);
- if (buf) {
- sprintf(buf, format, sender);
- ops->log_message(opdata, buf);
- free(buf);
- }
+ if (ops->handle_msg_event) {
+ ops->handle_msg_event(opdata,
+ OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED,
+ context, NULL, (gcry_error_t)NULL);
}
if (edata.ignore_message == -1) edata.ignore_message = 1;
break;
@@ -1517,76 +1561,6 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
return edata.ignore_message;
}
-/* Send a message to the network, fragmenting first if necessary.
- * All messages to be sent to the network should go through this
- * method immediately before they are sent, ie after encryption. */
-gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
- void *opdata, ConnContext *context, const char *message,
- OtrlFragmentPolicy fragPolicy, char **returnFragment)
-{
- int mms = 0;
- if (message && ops->inject_message) {
- int msglen;
-
- if (otrl_api_version >= 0x030100 && ops->max_message_size) {
- mms = ops->max_message_size(opdata, context);
- }
- msglen = strlen(message);
-
- /* Don't incur overhead of fragmentation unless necessary */
- if(mms != 0 && msglen > mms) {
- char **fragments;
- gcry_error_t err;
- int i;
- int fragment_count = ((msglen - 1) / (mms -19)) + 1;
- /* like ceil(msglen/(mms - 19)) */
-
- err = otrl_proto_fragment_create(mms, fragment_count, &fragments,
- message);
- if (err) {
- return err;
- }
-
- /* Determine which fragments to send and which to return
- * based on given Fragment Policy. If the first fragment
- * should be returned instead of sent, store it. */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_FIRST) {
- *returnFragment = strdup(fragments[0]);
- } else {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, fragments[0]);
- }
- for (i=1; i<fragment_count-1; i++) {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, fragments[i]);
- }
- /* If the last fragment should be stored instead of sent,
- * store it */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_LAST) {
- *returnFragment = strdup(fragments[fragment_count-1]);
- } else {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, fragments[fragment_count-1]);
- }
- /* Now free all fragment memory */
- otrl_proto_fragment_free(&fragments, fragment_count);
-
- } else {
- /* No fragmentation necessary */
- if (fragPolicy == OTRL_FRAGMENT_SEND_ALL) {
- ops->inject_message(opdata, context->accountname,
- context->protocol, context->username, message);
- } else {
- /* Copy and return the entire given message. */
- int l = strlen(message) + 1;
- *returnFragment = malloc(sizeof(char)*l);
- strcpy(*returnFragment, message);
- }
- }
- }
- return gcry_error(GPG_ERR_NO_ERROR);
-}
-
/* Put a connection into the PLAINTEXT state, first sending the
* other side a notice that we're doing so if we're currently ENCRYPTED,
* and we think he's logged in. */
@@ -1600,7 +1574,7 @@ void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops,
if (!context) return;
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
- context->their_keyid > 0 &&
+ context->context_priv->their_keyid > 0 &&
ops->is_logged_in &&
ops->is_logged_in(opdata, accountname, protocol, username) == 1) {
if (ops->inject_message) {
@@ -1638,7 +1612,7 @@ gcry_error_t otrl_message_symkey(OtrlUserState us,
}
if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
- context->their_keyid > 0) {
+ context->context_priv->their_keyid > 0) {
unsigned char *tlvdata = malloc(usedatalen+4);
char *encmsg = NULL;
gcry_error_t err;
diff --git a/src/message.h b/src/message.h
index c3b60e1..f2d1c7a 100644
--- a/src/message.h
+++ b/src/message.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -20,8 +21,19 @@
#ifndef __MESSAGE_H__
#define __MESSAGE_H__
+#define OTR_ERROR_PREFIX "?OTR Error: "
+
+typedef enum {
+ OTRL_ERRCODE_NONE,
+ OTRL_ERRCODE_ENCRYPTION_ERROR,
+ OTRL_ERRCODE_MSG_NOT_IN_PRIVATE,
+ OTRL_ERRCODE_MSG_UNREADABLE,
+ OTRL_ERRCODE_MSG_MALFORMED,
+} OtrlErrorCode;
+
/* These define the events used to indicate status of SMP to the UI */
typedef enum {
+ OTRL_SMPEVENT_NONE,
OTRL_SMPEVENT_ERROR,
OTRL_SMPEVENT_ABORT,
OTRL_SMPEVENT_CHEATED,
@@ -32,6 +44,26 @@ typedef enum {
OTRL_SMPEVENT_FAILURE
} OtrlSMPEvent;
+/* These define the events used to indicate the messages that need
+ * to be sent */
+typedef enum {
+ OTRL_MSGEVENT_NONE,
+ OTRL_MSGEVENT_ENCRYPTION_REQUIRED,
+ OTRL_MSGEVENT_ENCRYPTION_ERROR,
+ OTRL_MSGEVENT_CONNECTION_ENDED,
+ OTRL_MSGEVENT_SETUP_ERROR,
+ OTRL_MSGEVENT_MSG_REFLECTED,
+ OTRL_MSGEVENT_MSG_RESENT,
+ OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE,
+ OTRL_MSGEVENT_RCVDMSG_UNREADABLE,
+ OTRL_MSGEVENT_RCVDMSG_MALFORMED,
+ OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD,
+ OTRL_MSGEVENT_LOG_HEARTBEAT_SENT,
+ OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR,
+ OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED,
+ OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED
+} OtrlMessageEvent;
+
typedef enum {
OTRL_NOTIFY_ERROR,
OTRL_NOTIFY_WARNING,
@@ -61,33 +93,10 @@ typedef struct s_OtrlMessageAppOps {
void (*inject_message)(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message);
- /* Display a notification message for a particular accountname /
- * protocol / username conversation. */
- void (*notify)(void *opdata, OtrlNotifyLevel level,
- const char *accountname, const char *protocol,
- const char *username, const char *title,
- const char *primary, const char *secondary);
-
- /* Display an OTR control message for a particular accountname /
- * protocol / username conversation. Return 0 if you are able to
- * successfully display it. If you return non-0 (or if this
- * function is NULL), the control message will be displayed inline,
- * as a received message, or else by using the above notify()
- * callback. */
- int (*display_otr_message)(void *opdata, const char *accountname,
- const char *protocol, const char *username, const char *msg);
-
/* When the list of ConnContexts changes (including a change in
* state), this is called so the UI can be updated. */
void (*update_context_list)(void *opdata);
- /* Return a newly allocated string containing a human-friendly name
- * for the given protocol id */
- const char *(*protocol_name)(void *opdata, const char *protocol);
-
- /* Deallocate a string allocated by protocol_name */
- void (*protocol_name_free)(void *opdata, const char *protocol_name);
-
/* A new fingerprint for the given user has been received. */
void (*new_fingerprint)(void *opdata, OtrlUserState us,
const char *accountname, const char *protocol,
@@ -106,9 +115,6 @@ typedef struct s_OtrlMessageAppOps {
* already knew. is_reply indicates whether we initiated the AKE. */
void (*still_secure)(void *opdata, ConnContext *context, int is_reply);
- /* Log a message. The passed message will end in "\n". */
- void (*log_message)(void *opdata, const char *message);
-
/* Find the maximum message size supported by this protocol. */
int (*max_message_size)(void *opdata, ConnContext *context);
@@ -128,12 +134,104 @@ typedef struct s_OtrlMessageAppOps {
void (*received_symkey)(void *opdata, ConnContext *context,
unsigned int use, const unsigned char *usedata,
size_t usedatalen, const unsigned char *symkey);
-
- /* Update the auth UI with respect to SMP events */
+
+ /* Return a string according to the error event. This string will then
+ * be concatenated to an OTR header to produce an OTR protocol error
+ * message. The following are the possible error events:
+ * - OTRL_ERRCODE_ENCRYPTION_ERROR
+ * occured while encrypting a message
+ * - OTRL_ERRCODE_MSG_NOT_IN_PRIVATE
+ * sent encrypted message to somebody who is not in
+ * a mutual OTR session
+ * - OTRL_ERRCODE_MSG_UNREADABLE
+ * sent an unreadable encrypted message
+ * - OTRL_ERRCODE_MSG_MALFORMED
+ * message sent is malformed */
+ const char *(*otr_error_message)(void *opdata, ConnContext *context,
+ OtrlErrorCode err_code);
+
+ /* Deallocate a string returned by otr_error_message */
+ void (*otr_error_message_free)(void *opdata, const char *err_msg);
+
+ /* Return a string that will be prefixed to any resent message. If this
+ * function is not provided by the application then the default prefix,
+ * "[resent]", will be used.
+ * */
+ const char *(*resent_msg_prefix)(void *opdata, ConnContext *context);
+
+ /* Deallocate a string returned by resent_msg_prefix */
+ void (*resent_msg_prefix_free)(void *opdata, const char *prefix);
+
+ /* Update the authentication UI with respect to SMP events
+ * These are the possible events:
+ * - OTRL_SMPEVENT_ASK_FOR_SECRET
+ * prompt the user to enter a shared secret. The sender application
+ * should call otrl_message_initiate_smp, passing NULL as the question.
+ * When the receiver application resumes the SM protocol by calling
+ * otrl_message_respond_smp with the secret answer.
+ * - OTRL_SMPEVENT_ASK_FOR_ANSWER
+ * (same as OTRL_SMPEVENT_ASK_FOR_SECRET but sender calls
+ * otrl_message_initiate_smp_q instead)
+ * - OTRL_SMPEVENT_CHEATED
+ * abort the current auth and update the auth progress dialog
+ * with progress_percent. otrl_message_abort_smp should be called to
+ * stop the SM protocol.
+ * - OTRL_SMPEVENT_INPROGRESS and
+ * OTRL_SMPEVENT_SUCCESS and
+ * OTRL_SMPEVENT_FAILURE and
+ * OTRL_SMPEVENT_ABORT
+ * update the auth progress dialog with progress_percent
+ * - OTRL_SMPEVENT_ERROR
+ * (same as OTRL_SMPEVENT_CHEATED)
+ * */
void (*handle_smp_event)(void *opdata, OtrlSMPEvent smp_event,
ConnContext *context, unsigned short progress_percent,
char *question);
+ /* Handle and send the appropriate message(s) to the sender/recipient
+ * depending on the message events. All the events only require an opdata,
+ * the event, and the context. The message and err will be NULL except for
+ * some events (see below). The possible events are:
+ * - OTRL_MSGEVENT_ENCRYPTION_REQUIRED
+ * Our policy requires encryption but we are trying to send
+ * an unencrypted message out.
+ * - OTRL_MSGEVENT_ENCRYPTION_ERROR
+ * An error occured while encrypting a message and the message
+ * was not sent.
+ * - OTRL_MSGEVENT_CONNECTION_ENDED
+ * Message has not been sent because our buddy has ended the
+ * private conversation. We should either close the connection,
+ * or refresh it.
+ * - OTRL_MSGEVENT_SETUP_ERROR
+ * A private conversation could not be set up. A gcry_error_t
+ * will be passed.
+ * - OTRL_MSGEVENT_MSG_REFLECTED
+ * Received our own OTR messages.
+ * - OTRL_MSGEVENT_MSG_RESENT
+ * The previous message was resent.
+ * - OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE
+ * Received an encrypted message but cannot read
+ * it because no private connection is established yet.
+ * - OTRL_MSGEVENT_RCVDMSG_UNREADABLE
+ * Cannot read the received message.
+ * - OTRL_MSGEVENT_RCVDMSG_MALFORMED
+ * The message received contains malformed data.
+ * - OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD
+ * Received a heartbeat.
+ * - OTRL_MSGEVENT_LOG_HEARTBEAT_SENT
+ * Sent a heartbeat.
+ * - OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR
+ * Received a general OTR error. The argument 'message' will
+ * also be passed and it will contain the OTR error message.
+ * - OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED
+ * Received an unencrypted message. The argument 'smessage' will
+ * also be passed and it will contain the plaintext message.
+ * - OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED
+ * Cannot recognize the type of OTR message received.
+ * */
+ void (*handle_msg_event)(void *opdata, OtrlMessageEvent msg_event,
+ ConnContext *context, const char *message,
+ gcry_error_t err);
} OtrlMessageAppOps;
/* Deallocate a message allocated by other otrl_message_* routines. */
@@ -146,24 +244,36 @@ void otrl_message_free(char *message);
* pointer to the new ConnContext. You can use this to add
* application-specific information to the ConnContext using the
* "context->app" field, for example. If you don't need to do this, you
- * can pass NULL for the last two arguments of otrl_message_sending.
+ * can pass NULL for the last two arguments of otrl_message_sending.
*
* tlvs is a chain of OtrlTLVs to append to the private message. It is
* usually correct to just pass NULL here.
*
- * If this routine returns non-zero, then the library tried to encrypt
- * the message, but for some reason failed. DO NOT send the message in
- * the clear in that case.
- *
- * If *messagep gets set by the call to something non-NULL, then you
- * should replace your message with the contents of *messagep, and
- * send that instead. Call otrl_message_free(*messagep) when you're
+ * convert_msg is a function that will be called on each msg to be sent. You
+ * can use it to perform some tweaks on your outgoing messages.
+ *
+ * If no fragmentation or msg injection is wanted, use OTRL_FRAGMENT_SEND_SKIP
+ * as the OtrlFragmentPolicy. In this case, this function will assign *messagep
+ * with the encrypted msg. If the routine returns non-zero, then the library
+ * tried to encrypt the message, but for some reason failed. DO NOT send the
+ * message in the clear in that case. If *messagep gets set by the call to
+ * something non-NULL, then you should replace your message with the contents
+ * of *messagep, and send that instead.
+ *
+ * Other fragmentation policies are OTRL_FRAGMENT_SEND_ALL,
+ * OTRL_FRAGMENT_SEND_ALL_BUT_LAST, or OTRL_FRAGMENT_SEND_ALL_BUT_FIRST. In these
+ * cases, the appropriate fragments will be automatically sent. For the last two
+ * policies, the remaining fragment will be passed in *original_msg.
+ *
+ * Call otrl_message_free(*messagep) if you don't need *messagep or when you're
* done with it. */
gcry_error_t otrl_message_sending(OtrlUserState us,
const OtrlMessageAppOps *ops,
void *opdata, const char *accountname, const char *protocol,
- const char *recipient, const char *message, OtrlTLV *tlvs,
- char **messagep,
+ const char *recipient, char **original_msgp, OtrlTLV *tlvs,
+ char **messagep, OtrlFragmentPolicy fragPolicy,
+ void (*convert_msg)(void *convert_data, const char *source, char **target),
+ void *convert_data,
void (*add_appdata)(void *data, ConnContext *context),
void *data);
@@ -174,7 +284,10 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
* a pointer to the new ConnContext. You can use this to add
* application-specific information to the ConnContext using the
* "context->app" field, for example. If you don't need to do this, you
- * can pass NULL for the last two arguments of otrl_message_receiving.
+ * can pass NULL for the last two arguments of otrl_message_receiving.
+ *
+ * convert_msg is a function that will be called on each msg that is received.
+ * You can use it to perform some tweaks on your incoming messages.
*
* If otrl_message_receiving returns 1, then the message you received
* was an internal protocol message, and no message should be delivered
@@ -195,16 +308,11 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
void *opdata, const char *accountname, const char *protocol,
const char *sender, const char *message, char **newmessagep,
OtrlTLV **tlvsp,
+ void (*convert_msg)(void *convert_data, const char *source, char **target),
+ void *convert_data,
void (*add_appdata)(void *data, ConnContext *context),
void *data);
-/* Send a message to the network, fragmenting first if necessary.
- * All messages to be sent to the network should go through this
- * method immediately before they are sent, ie after encryption. */
-gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
- void *opdata, ConnContext *context, const char *message,
- OtrlFragmentPolicy fragPolicy, char **returnFragment);
-
/* Put a connection into the PLAINTEXT state, first sending the
* other side a notice that we're doing so if we're currently ENCRYPTED,
* and we think he's logged in. */
diff --git a/src/privkey-t.h b/src/privkey-t.h
index 92f23e6..bda064e 100644
--- a/src/privkey-t.h
+++ b/src/privkey-t.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/privkey.c b/src/privkey.c
index b25cbc0..6e58f80 100644
--- a/src/privkey.c
+++ b/src/privkey.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/privkey.h b/src/privkey.h
index 686f04a..200168e 100644
--- a/src/privkey.h
+++ b/src/privkey.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/proto.c b/src/proto.c
index 561fd95..f5e3980 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -90,33 +91,33 @@ static gcry_error_t reveal_macs(ConnContext *context,
sess2->rcvmacused + sess2->sendmacused;
unsigned int newnumsaved;
unsigned char *newmacs;
-
+
/* Is there anything to do? */
if (numnew == 0) return gcry_error(GPG_ERR_NO_ERROR);
- newnumsaved = context->numsavedkeys + numnew;
- newmacs = realloc(context->saved_mac_keys,
+ newnumsaved = context->context_priv->numsavedkeys + numnew;
+ newmacs = realloc(context->context_priv->saved_mac_keys,
newnumsaved * 20);
if (!newmacs) {
return gcry_error(GPG_ERR_ENOMEM);
}
if (sess1->rcvmacused) {
- memmove(newmacs + context->numsavedkeys * 20, sess1->rcvmackey, 20);
- context->numsavedkeys++;
+ memmove(newmacs + context->context_priv->numsavedkeys * 20, sess1->rcvmackey, 20);
+ context->context_priv->numsavedkeys++;
}
if (sess1->sendmacused) {
- memmove(newmacs + context->numsavedkeys * 20, sess1->sendmackey, 20);
- context->numsavedkeys++;
+ memmove(newmacs + context->context_priv->numsavedkeys * 20, sess1->sendmackey, 20);
+ context->context_priv->numsavedkeys++;
}
if (sess2->rcvmacused) {
- memmove(newmacs + context->numsavedkeys * 20, sess2->rcvmackey, 20);
- context->numsavedkeys++;
+ memmove(newmacs + context->context_priv->numsavedkeys * 20, sess2->rcvmackey, 20);
+ context->context_priv->numsavedkeys++;
}
if (sess2->sendmacused) {
- memmove(newmacs + context->numsavedkeys * 20, sess2->sendmackey, 20);
- context->numsavedkeys++;
+ memmove(newmacs + context->context_priv->numsavedkeys * 20, sess2->sendmackey, 20);
+ context->context_priv->numsavedkeys++;
}
- context->saved_mac_keys = newmacs;
+ context->context_priv->saved_mac_keys = newmacs;
return gcry_error(GPG_ERR_NO_ERROR);
}
@@ -128,39 +129,43 @@ static gcry_error_t rotate_dh_keys(ConnContext *context)
gcry_error_t err;
/* Rotate the keypair */
- otrl_dh_keypair_free(&(context->our_old_dh_key));
- memmove(&(context->our_old_dh_key), &(context->our_dh_key),
- sizeof(DH_keypair));
+ otrl_dh_keypair_free(&(context->context_priv->our_old_dh_key));
+ memmove(&(context->context_priv->our_old_dh_key),
+ &(context->context_priv->our_dh_key),
+ sizeof(DH_keypair));
/* Rotate the session keys */
- err = reveal_macs(context, &(context->sesskeys[1][0]),
- &(context->sesskeys[1][1]));
+ err = reveal_macs(context, &(context->context_priv->sesskeys[1][0]),
+ &(context->context_priv->sesskeys[1][1]));
if (err) return err;
- otrl_dh_session_free(&(context->sesskeys[1][0]));
- otrl_dh_session_free(&(context->sesskeys[1][1]));
- memmove(&(context->sesskeys[1][0]), &(context->sesskeys[0][0]),
- sizeof(DH_sesskeys));
- memmove(&(context->sesskeys[1][1]), &(context->sesskeys[0][1]),
- sizeof(DH_sesskeys));
+ otrl_dh_session_free(&(context->context_priv->sesskeys[1][0]));
+ otrl_dh_session_free(&(context->context_priv->sesskeys[1][1]));
+ memmove(&(context->context_priv->sesskeys[1][0]),
+ &(context->context_priv->sesskeys[0][0]),
+ sizeof(DH_sesskeys));
+ memmove(&(context->context_priv->sesskeys[1][1]),
+ &(context->context_priv->sesskeys[0][1]),
+ sizeof(DH_sesskeys));
/* Create a new DH key */
- otrl_dh_gen_keypair(DH1536_GROUP_ID, &(context->our_dh_key));
- context->our_keyid++;
+ otrl_dh_gen_keypair(DH1536_GROUP_ID, &(context->context_priv->our_dh_key));
+ context->context_priv->our_keyid++;
/* Make the session keys */
- if (context->their_y) {
- err = otrl_dh_session(&(context->sesskeys[0][0]),
- &(context->our_dh_key), context->their_y);
+ if (context->context_priv->their_y) {
+ err = otrl_dh_session(&(context->context_priv->sesskeys[0][0]),
+ &(context->context_priv->our_dh_key), context->context_priv->their_y);
if (err) return err;
} else {
- otrl_dh_session_blank(&(context->sesskeys[0][0]));
+ otrl_dh_session_blank(&(context->context_priv->sesskeys[0][0]));
}
- if (context->their_old_y) {
- err = otrl_dh_session(&(context->sesskeys[0][1]),
- &(context->our_dh_key), context->their_old_y);
+ if (context->context_priv->their_old_y) {
+ err = otrl_dh_session(&(context->context_priv->sesskeys[0][1]),
+ &(context->context_priv->our_dh_key),
+ context->context_priv->their_old_y);
if (err) return err;
} else {
- otrl_dh_session_blank(&(context->sesskeys[0][1]));
+ otrl_dh_session_blank(&(context->context_priv->sesskeys[0][1]));
}
return gcry_error(GPG_ERR_NO_ERROR);
}
@@ -172,30 +177,32 @@ static gcry_error_t rotate_y_keys(ConnContext *context, gcry_mpi_t new_y)
gcry_error_t err;
/* Rotate the public key */
- gcry_mpi_release(context->their_old_y);
- context->their_old_y = context->their_y;
+ gcry_mpi_release(context->context_priv->their_old_y);
+ context->context_priv->their_old_y = context->context_priv->their_y;
/* Rotate the session keys */
- err = reveal_macs(context, &(context->sesskeys[0][1]),
- &(context->sesskeys[1][1]));
+ err = reveal_macs(context, &(context->context_priv->sesskeys[0][1]),
+ &(context->context_priv->sesskeys[1][1]));
if (err) return err;
- otrl_dh_session_free(&(context->sesskeys[0][1]));
- otrl_dh_session_free(&(context->sesskeys[1][1]));
- memmove(&(context->sesskeys[0][1]), &(context->sesskeys[0][0]),
- sizeof(DH_sesskeys));
- memmove(&(context->sesskeys[1][1]), &(context->sesskeys[1][0]),
- sizeof(DH_sesskeys));
+ otrl_dh_session_free(&(context->context_priv->sesskeys[0][1]));
+ otrl_dh_session_free(&(context->context_priv->sesskeys[1][1]));
+ memmove(&(context->context_priv->sesskeys[0][1]),
+ &(context->context_priv->sesskeys[0][0]),
+ sizeof(DH_sesskeys));
+ memmove(&(context->context_priv->sesskeys[1][1]),
+ &(context->context_priv->sesskeys[1][0]),
+ sizeof(DH_sesskeys));
/* Copy in the new public key */
- context->their_y = gcry_mpi_copy(new_y);
- context->their_keyid++;
+ context->context_priv->their_y = gcry_mpi_copy(new_y);
+ context->context_priv->their_keyid++;
/* Make the session keys */
- err = otrl_dh_session(&(context->sesskeys[0][0]),
- &(context->our_dh_key), context->their_y);
+ err = otrl_dh_session(&(context->context_priv->sesskeys[0][0]),
+ &(context->context_priv->our_dh_key), context->context_priv->their_y);
if (err) return err;
- err = otrl_dh_session(&(context->sesskeys[1][0]),
- &(context->our_old_dh_key), context->their_y);
+ err = otrl_dh_session(&(context->context_priv->sesskeys[1][0]),
+ &(context->context_priv->our_old_dh_key), context->context_priv->their_y);
if (err) return err;
return gcry_error(GPG_ERR_NO_ERROR);
@@ -373,9 +380,9 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
unsigned char *buf = NULL;
unsigned char *bufp;
size_t lenp;
- DH_sesskeys *sess = &(context->sesskeys[1][0]);
+ DH_sesskeys *sess = &(context->context_priv->sesskeys[1][0]);
gcry_error_t err;
- size_t reveallen = 20 * context->numsavedkeys;
+ size_t reveallen = 20 * context->context_priv->numsavedkeys;
size_t base64len;
char *base64buf = NULL;
unsigned char *msgbuf = NULL;
@@ -385,7 +392,7 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
/* Make sure we're actually supposed to be able to encrypt */
if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED ||
- context->their_keyid == 0) {
+ context->context_priv->their_keyid == 0) {
return gcry_error(GPG_ERR_CONFLICT);
}
@@ -403,7 +410,8 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
* len of revealed mac keys, revealed mac keys, MAC */
buflen = 3 + (version == 2 ? 1 : 0) + 4 + 4 + 8 + 4 + msglen +
4 + reveallen + 20;
- gcry_mpi_print(format, NULL, 0, &pubkeylen, context->our_dh_key.pub);
+ gcry_mpi_print(format, NULL, 0, &pubkeylen,
+ context->context_priv->our_dh_key.pub);
buflen += pubkeylen + 4;
buf = malloc(buflen);
msgbuf = gcry_malloc_secure(msglen);
@@ -429,12 +437,12 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
bufp[0] = flags;
bufp += 1; lenp -= 1;
}
- write_int(context->our_keyid-1); /* sender keyid */
+ write_int(context->context_priv->our_keyid-1); /* sender keyid */
debug_int("Sender keyid", bufp-4);
- write_int(context->their_keyid); /* recipient keyid */
+ write_int(context->context_priv->their_keyid); /* recipient keyid */
debug_int("Recipient keyid", bufp-4);
- write_mpi(context->our_dh_key.pub, pubkeylen, "Y"); /* Y */
+ write_mpi(context->context_priv->our_dh_key.pub, pubkeylen, "Y"); /* Y */
otrl_dh_incctr(sess->sendctr);
memmove(bufp, sess->sendctr, 8); /* Counter (top 8 bytes only) */
@@ -465,12 +473,12 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
debug_int("Revealed MAC length", bufp-4);
if (reveallen > 0) {
- memmove(bufp, context->saved_mac_keys, reveallen);
+ memmove(bufp, context->context_priv->saved_mac_keys, reveallen);
debug_data("Revealed MAC data", bufp, reveallen);
bufp += reveallen; lenp -= reveallen;
- free(context->saved_mac_keys);
- context->saved_mac_keys = NULL;
- context->numsavedkeys = 0;
+ free(context->context_priv->saved_mac_keys);
+ context->context_priv->saved_mac_keys = NULL;
+ context->context_priv->numsavedkeys = 0;
}
assert(lenp == 0);
@@ -490,21 +498,13 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
free(buf);
gcry_free(msgbuf);
*encmessagep = base64buf;
- gcry_free(context->lastmessage);
- context->lastmessage = NULL;
- context->may_retransmit = 0;
+ gcry_free(context->context_priv->lastmessage);
+ context->context_priv->lastmessage = NULL;
+ context->context_priv->may_retransmit = 0;
if (msglen > 0) {
- const char *prefix = "[resent] ";
- size_t prefixlen = strlen(prefix);
- if (!strncmp(prefix, msgdup, prefixlen)) {
- /* The prefix is already there. Don't add it again. */
- prefix = "";
- prefixlen = 0;
- }
- context->lastmessage = gcry_malloc_secure(prefixlen + justmsglen + 1);
- if (context->lastmessage) {
- strcpy(context->lastmessage, prefix);
- strcat(context->lastmessage, msgdup);
+ context->context_priv->lastmessage = gcry_malloc_secure(justmsglen + 1);
+ if (context->context_priv->lastmessage) {
+ strcpy(context->context_priv->lastmessage, msgdup);
}
}
gcry_free(msgdup);
@@ -674,24 +674,24 @@ gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
/* We don't take any action on this message (especially rotating
* keys) until we've verified the MAC on this message. To that end,
* we need to know which keys this message is claiming to use. */
- if (context->their_keyid == 0 ||
- (sender_keyid != context->their_keyid &&
- sender_keyid != context->their_keyid - 1) ||
- (recipient_keyid != context->our_keyid &&
- recipient_keyid != context->our_keyid - 1) ||
+ if (context->context_priv->their_keyid == 0 ||
+ (sender_keyid != context->context_priv->their_keyid &&
+ sender_keyid != context->context_priv->their_keyid - 1) ||
+ (recipient_keyid != context->context_priv->our_keyid &&
+ recipient_keyid != context->context_priv->our_keyid - 1) ||
sender_keyid == 0 || recipient_keyid == 0) {
goto conflict;
}
- if (sender_keyid == context->their_keyid - 1 &&
- context->their_old_y == NULL) {
+ if (sender_keyid == context->context_priv->their_keyid - 1 &&
+ context->context_priv->their_old_y == NULL) {
goto conflict;
}
/* These are the session keys this message is claiming to use. */
- sess = &(context->sesskeys
- [context->our_keyid - recipient_keyid]
- [context->their_keyid - sender_keyid]);
+ sess = &(context->context_priv->sesskeys
+ [context->context_priv->our_keyid - recipient_keyid]
+ [context->context_priv->their_keyid - sender_keyid]);
gcry_md_reset(sess->rcvmac);
gcry_md_write(sess->rcvmac, macstart, macend-macstart);
@@ -723,13 +723,13 @@ gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
/* See if either set of keys needs rotating */
- if (recipient_keyid == context->our_keyid) {
+ if (recipient_keyid == context->context_priv->our_keyid) {
/* They're using our most recent key, so generate a new one */
err = rotate_dh_keys(context);
if (err) goto err;
}
- if (sender_keyid == context->their_keyid) {
+ if (sender_keyid == context->context_priv->their_keyid) {
/* They've sent us a new public key */
err = rotate_y_keys(context, sender_next_y);
if (err) goto err;
@@ -778,70 +778,70 @@ OtrlFragmentResult otrl_proto_fragment_accumulate(char **unfragmessagep,
if (k == 1) {
int fraglen = end - start - 1;
size_t newsize = fraglen + 1;
- free(context->fragment);
- context->fragment = NULL;
+ free(context->context_priv->fragment);
+ context->context_priv->fragment = NULL;
if (newsize > fraglen) { /* Check for overflow */
- context->fragment = malloc(newsize);
+ context->context_priv->fragment = malloc(newsize);
}
- if (context->fragment) {
- memmove(context->fragment, tag + start, fraglen);
- context->fragment_len = fraglen;
- context->fragment[context->fragment_len] = '\0';
- context->fragment_n = n;
- context->fragment_k = k;
+ if (context->context_priv->fragment) {
+ memmove(context->context_priv->fragment, tag + start, fraglen);
+ context->context_priv->fragment_len = fraglen;
+ context->context_priv->fragment[context->context_priv->fragment_len] = '\0';
+ context->context_priv->fragment_n = n;
+ context->context_priv->fragment_k = k;
} else {
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
+ context->context_priv->fragment_len = 0;
+ context->context_priv->fragment_n = 0;
+ context->context_priv->fragment_k = 0;
}
- } else if (n == context->fragment_n &&
- k == context->fragment_k + 1) {
+ } else if (n == context->context_priv->fragment_n &&
+ k == context->context_priv->fragment_k + 1) {
int fraglen = end - start - 1;
char *newfrag = NULL;
- size_t newsize = context->fragment_len + fraglen + 1;
+ size_t newsize = context->context_priv->fragment_len + fraglen + 1;
if (newsize > fraglen) { /* Check for overflow */
- newfrag = realloc(context->fragment, newsize);
+ newfrag = realloc(context->context_priv->fragment, newsize);
}
if (newfrag) {
- context->fragment = newfrag;
- memmove(context->fragment + context->fragment_len,
+ context->context_priv->fragment = newfrag;
+ memmove(context->context_priv->fragment + context->context_priv->fragment_len,
tag + start, fraglen);
- context->fragment_len += fraglen;
- context->fragment[context->fragment_len] = '\0';
- context->fragment_k = k;
+ context->context_priv->fragment_len += fraglen;
+ context->context_priv->fragment[context->context_priv->fragment_len] = '\0';
+ context->context_priv->fragment_k = k;
} else {
- free(context->fragment);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
+ free(context->context_priv->fragment);
+ context->context_priv->fragment = NULL;
+ context->context_priv->fragment_len = 0;
+ context->context_priv->fragment_n = 0;
+ context->context_priv->fragment_k = 0;
}
} else {
- free(context->fragment);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
+ free(context->context_priv->fragment);
+ context->context_priv->fragment = NULL;
+ context->context_priv->fragment_len = 0;
+ context->context_priv->fragment_n = 0;
+ context->context_priv->fragment_k = 0;
}
}
- if (context->fragment_n > 0 &&
- context->fragment_n == context->fragment_k) {
+ if (context->context_priv->fragment_n > 0 &&
+ context->context_priv->fragment_n == context->context_priv->fragment_k) {
/* We've got a complete message */
- *unfragmessagep = context->fragment;
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
+ *unfragmessagep = context->context_priv->fragment;
+ context->context_priv->fragment = NULL;
+ context->context_priv->fragment_len = 0;
+ context->context_priv->fragment_n = 0;
+ context->context_priv->fragment_k = 0;
res = OTRL_FRAGMENT_COMPLETE;
}
} else {
/* Unfragmented message, so discard any fragment we may have */
- free(context->fragment);
- context->fragment = NULL;
- context->fragment_len = 0;
- context->fragment_n = 0;
- context->fragment_k = 0;
+ free(context->context_priv->fragment);
+ context->context_priv->fragment = NULL;
+ context->context_priv->fragment_len = 0;
+ context->context_priv->fragment_n = 0;
+ context->context_priv->fragment_k = 0;
res = OTRL_FRAGMENT_UNFRAGMENTED;
}
@@ -861,7 +861,7 @@ gcry_error_t otrl_proto_fragment_create(int mms, int fragment_count,
char **fragmentarray = malloc(fragment_count * sizeof(char*));
if(!fragmentarray) return gcry_error(GPG_ERR_ENOMEM);
-
+
/*
* Find the next message fragment and store it in the array.
*/
@@ -882,7 +882,7 @@ gcry_error_t otrl_proto_fragment_create(int mms, int fragment_count,
}
strncpy(fragdata, message, fragdatalen);
fragdata[fragdatalen] = 0;
-
+
fragmentmsg = malloc(fragdatalen+headerlen+1);
if(!fragmentmsg) {
for (i=0; i<curfrag-1; free(fragmentarray[i++])) {}
@@ -891,19 +891,19 @@ gcry_error_t otrl_proto_fragment_create(int mms, int fragment_count,
return gcry_error(GPG_ERR_ENOMEM);
}
- /*
+ /*
* Create the actual fragment and store it in the array
*/
snprintf(fragmentmsg, fragdatalen + headerlen, "?OTR,%05hu,%05hu,%s,", curfrag, fragment_count, fragdata);
fragmentmsg[fragdatalen + headerlen] = 0;
fragmentarray[curfrag-1] = fragmentmsg;
-
+
free(fragdata);
index += fragdatalen;
message += fragdatalen;
}
-
+
*fragments = fragmentarray;
return gcry_error(GPG_ERR_NO_ERROR);
}
diff --git a/src/proto.h b/src/proto.h
index 4a60098..afd74fe 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
@@ -87,7 +88,8 @@ typedef enum {
typedef enum {
OTRL_FRAGMENT_SEND_ALL,
OTRL_FRAGMENT_SEND_ALL_BUT_FIRST,
- OTRL_FRAGMENT_SEND_ALL_BUT_LAST
+ OTRL_FRAGMENT_SEND_ALL_BUT_LAST,
+ OTRL_FRAGMENT_SEND_SKIP
} OtrlFragmentPolicy;
/* Initialize the OTR library. Pass the version of the API you are
diff --git a/src/serial.h b/src/serial.h
index edc3184..439a271 100644
--- a/src/serial.h
+++ b/src/serial.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/sm.c b/src/sm.c
index 535ae22..f3bcbd0 100644
--- a/src/sm.c
+++ b/src/sm.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/sm.h b/src/sm.h
index 2e94f07..2e44b46 100644
--- a/src/sm.h
+++ b/src/sm.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/tlv.c b/src/tlv.c
index 0cea7b5..687051b 100644
--- a/src/tlv.c
+++ b/src/tlv.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/tlv.h b/src/tlv.h
index b5822b5..f1c3436 100644
--- a/src/tlv.h
+++ b/src/tlv.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/userstate.c b/src/userstate.c
index 5ce5f5a..51d543c 100644
--- a/src/userstate.c
+++ b/src/userstate.c
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/userstate.h b/src/userstate.h
index 9815714..2f0106a 100644
--- a/src/userstate.h
+++ b/src/userstate.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/version.h b/src/version.h
index 78acf17..d755018 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,6 +1,7 @@
/*
* Off-the-Record Messaging library
- * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * Copyright (C) 2004-2009 Ian Goldberg, Chris Alexander, Willy Lew,
+ * Nikita Borisov
* <otr at cypherpunks.ca>
*
* This library is free software; you can redistribute it and/or
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/libotr.git
More information about the Pkg-privacy-commits
mailing list