[Pkg-privacy-commits] [libotr] 19/225: * src/auth.h: * src/auth.c: * src/message.c: Ensure version 2 AKEs are always done with fresh D-H parameters.

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 12:44:46 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 2248483f4877893c2b975a32ddc561771066677d
Author: cypherpunk <cypherpunk>
Date:   Thu Oct 27 16:01:04 2005 +0000

    	* src/auth.h:
    	* src/auth.c:
    	* src/message.c: Ensure version 2 AKEs are always done with
    	fresh D-H parameters.
    
    	* src/proto.h:
    	* src/proto.c:
    	* src/message.c: Add a "flags" field to the version 2 Data
    	Message, which can indicate that the Data Message should be
    	ignored if unreadable (as opposed to displaying an error).
    
    	* toolkit/parse.h:
    	* toolkit/parse.c:
    	* toolkit/otr_parse.c:
    	* toolkit/otr_remac.c: Deal with the new kind of Data Message.
---
 ChangeLog           | 18 +++++++++++
 src/auth.c          | 47 +++++++++--------------------
 src/auth.h          | 19 +++++-------
 src/message.c       | 56 ++++++++++++++++++++--------------
 src/proto.c         | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----
 src/proto.h         | 15 ++++++---
 src/tests.c         | 18 ++++++++++-
 toolkit/otr_parse.c |  3 ++
 toolkit/otr_remac.c | 28 ++++++++++-------
 toolkit/parse.c     | 36 +++++++++++++++++-----
 toolkit/parse.h     |  9 +++---
 11 files changed, 235 insertions(+), 101 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6c6f8ac..cfa462a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2005-10-27
+
+	* src/auth.h:
+	* src/auth.c:
+	* src/message.c: Ensure version 2 AKEs are always done with
+	fresh D-H parameters.
+
+	* src/proto.h:
+	* src/proto.c:
+	* src/message.c: Add a "flags" field to the version 2 Data
+	Message, which can indicate that the Data Message should be
+	ignored if unreadable (as opposed to displaying an error).
+
+	* toolkit/parse.h:
+	* toolkit/parse.c:
+	* toolkit/otr_parse.c:
+	* toolkit/otr_remac.c: Deal with the new kind of Data Message.
+
 2005-10-19
 
 	* src/context.h:
diff --git a/src/auth.c b/src/auth.c
index 067beb7..f40f018 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -94,14 +94,11 @@ void otrl_auth_clear(OtrlAuthInfo *auth)
 }
 
 /*
- * Start a fresh AKE (version 2) using the given OtrlAuthInfo.  If
- * our_dh is NULL, generate a fresh DH keypair to use.  Otherwise, use a
- * copy of the one passed (with the given keyid).  If no error is
- * returned, the message to transmit will be contained in
- * auth->lastauthmsg.
+ * Start a fresh AKE (version 2) using the given OtrlAuthInfo.  Generate
+ * a fresh DH keypair to use.  If no error is returned, the message to
+ * transmit will be contained in auth->lastauthmsg.
  */
-gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth, DH_keypair *our_dh,
-	unsigned int our_keyid)
+gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth)
 {
     gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
     const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
@@ -115,14 +112,8 @@ gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth, DH_keypair *our_dh,
     otrl_auth_clear(auth);
     auth->initiated = 1;
 
-    /* Import the given DH keypair, or else create a fresh one */
-    if (our_dh) {
-	otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
-	auth->our_keyid = our_keyid;
-    } else {
-	otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
-	auth->our_keyid = 1;
-    }
+    otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+    auth->our_keyid = 1;
 
     /* Pick an encryption key */
     gcry_randomize(auth->r, 16, GCRY_STRONG_RANDOM);
@@ -243,11 +234,11 @@ memerr:
 
 /*
  * Handle an incoming D-H Commit Message.  If no error is returned, the
- * message to send will be left in auth->lastauthmsg.  If non-NULL, use
- * a copy of the given D-H keypair, with the given keyid.
+ * message to send will be left in auth->lastauthmsg.  Generate a fresh
+ * keypair to use.
  */
-gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth, const char *commitmsg,
-	DH_keypair *our_dh, unsigned int our_keyid)
+gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
+	const char *commitmsg)
 {
     gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
     unsigned char *buf = NULL, *bufp = NULL, *encbuf = NULL;
@@ -293,13 +284,8 @@ gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth, const char *commitmsg,
 
 	    /* Store the incoming information */
 	    otrl_auth_clear(auth);
-	    if (our_dh) {
-		otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
-		auth->our_keyid = our_keyid;
-	    } else {
-		otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
-		auth->our_keyid = 1;
-	    }
+	    otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+	    auth->our_keyid = 1;
 	    auth->encgx = encbuf;
 	    encbuf = NULL;
 	    auth->encgx_len = enclen;
@@ -323,13 +309,8 @@ gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth, const char *commitmsg,
 	    } else {
 		/* Ours loses.  Use the incoming parameters instead. */
 		otrl_auth_clear(auth);
-		if (our_dh) {
-		    otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
-		    auth->our_keyid = our_keyid;
-		} else {
-		    otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
-		    auth->our_keyid = 1;
-		}
+		otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
+		auth->our_keyid = 1;
 		auth->encgx = encbuf;
 		encbuf = NULL;
 		auth->encgx_len = enclen;
diff --git a/src/auth.h b/src/auth.h
index 08744c0..8fa936c 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -85,22 +85,19 @@ void otrl_auth_new(OtrlAuthInfo *auth);
 void otrl_auth_clear(OtrlAuthInfo *auth);
 
 /*
- * Start a fresh AKE (version 2) using the given OtrlAuthInfo.  If
- * our_dh is NULL, generate a fresh DH keypair to use.  Otherwise, use a
- * copy of the one passed (with the given keyid).  If no error is
- * returned, the message to transmit will be contained in
- * auth->lastauthmsg.
+ * Start a fresh AKE (version 2) using the given OtrlAuthInfo.  Generate
+ * a fresh DH keypair to use.  If no error is returned, the message to
+ * transmit will be contained in auth->lastauthmsg.
  */
-gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth, DH_keypair *our_dh,
-	unsigned int our_keyid);
+gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth);
 
 /*
  * Handle an incoming D-H Commit Message.  If no error is returned, the
- * message to send will be left in auth->lastauthmsg.  If non-NULL, use
- * a copy of the given D-H keypair, with the given keyid.
+ * message to send will be left in auth->lastauthmsg.  Generate a fresh
+ * keypair to use.
  */
-gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth, const char *commitmsg,
-	DH_keypair *our_dh, unsigned int our_keyid);
+gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
+	const char *commitmsg);
 
 /*
  * Handle an incoming D-H Key Message.  If no error is returned, and
diff --git a/src/message.c b/src/message.c
index 8fa34b5..7b07756 100644
--- a/src/message.c
+++ b/src/message.c
@@ -188,7 +188,8 @@ gcry_error_t otrl_message_sending(OtrlUserState us,
 	    break;
 	case OTRL_MSGSTATE_ENCRYPTED:
 	    /* Create the new, encrypted message */
-	    err = otrl_proto_create_data(&msgtosend, context, message, tlvs);
+	    err = otrl_proto_create_data(&msgtosend, context, message, tlvs,
+		    0);
 	    if (!err) {
 		context->lastsent = time(NULL);
 		*messagep = msgtosend;
@@ -301,6 +302,7 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
     gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
     Fingerprint *found_print = NULL;
     int fprint_added = 0;
+    OtrlMessageState oldstate = edata->context->msgstate;
 
     /* See if we're talking to ourselves */
     if (!gcry_mpi_cmp(auth->their_pub, auth->our_dh.pub)) {
@@ -412,8 +414,15 @@ static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
     if (edata->ops->update_context_list) {
 	edata->ops->update_context_list(edata->opdata);
     }
-    if (edata->ops->gone_secure) {
-	edata->ops->gone_secure(edata->opdata, edata->context);
+    if (oldstate == OTRL_MSGSTATE_ENCRYPTED) {
+	if (edata->ops->still_secure) {
+	    edata->ops->still_secure(edata->opdata, edata->context,
+		    edata->context->auth.initiated);
+	}
+    } else {
+	if (edata->ops->gone_secure) {
+	    edata->ops->gone_secure(edata->opdata, edata->context);
+	}
     }
 
     edata->gone_encrypted = 1;
@@ -438,7 +447,7 @@ static void maybe_resend(EncrData *edata)
 
 	/* Re-encrypt the message with the new keys */
 	err = otrl_proto_create_data(&resendmsg,
-		edata->context, edata->context->lastmessage, NULL);
+		edata->context, edata->context->lastmessage, NULL, 0);
 	if (!err) {
 	    const char *format = "<b>The last message "
 		"to %s was resent.</b>";
@@ -608,8 +617,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 	    /* Find the best version of OTR that we both speak */
 	    switch(otrl_proto_query_bestversion(message, policy)) {
 		case 2:
-		    err = otrl_auth_start_v2(&(context->auth), our_dh,
-			    our_keyid);
+		    err = otrl_auth_start_v2(&(context->auth));
 		    send_or_error_auth(ops, opdata, err, context);
 		    break;
 		case 1:
@@ -641,18 +649,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 
 	case OTRL_MSGTYPE_DH_COMMIT:
 	    if ((policy & OTRL_POLICY_ALLOW_V2)) {
-		/* 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;
-		} else {
-		    our_dh = NULL;
-		    our_keyid = 0;
-		}
-
-		err = otrl_auth_handle_commit(&(context->auth), message,
-			our_dh, our_keyid);
+		err = otrl_auth_handle_commit(&(context->auth), message);
 		send_or_error_auth(ops, opdata, err, context);
 	    }
 
@@ -771,8 +768,17 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 		char *plaintext;
 		char *buf;
 		char *format;
+		unsigned char flags;
 		case OTRL_MSGSTATE_PLAINTEXT:
 		case OTRL_MSGSTATE_FINISHED:
+		    /* See if we're supposed to ignore this message in
+		     * the event it's unreadable. */
+		    err = otrl_proto_data_read_flags(message, &flags);
+		    if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
+			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. */
@@ -813,10 +819,14 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 
 		case OTRL_MSGSTATE_ENCRYPTED:
 		    err = otrl_proto_accept_data(&plaintext, &tlvs, context,
-			    message);
+			    message, &flags);
 		    if (err) {
 			int is_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 messahe from %s." :
 			    "We received a malformed data message from %s.";
@@ -876,7 +886,8 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 
 			    /* Create the heartbeat message */
 			    err = otrl_proto_create_data(&heartbeat,
-				    context, "", NULL);
+				    context, "", NULL,
+				    OTRL_MSGFLAGS_IGNORE_UNREADABLE);
 			    if (!err) {
 				/* Send it, and log a debug message */
 				if (ops->inject_message) {
@@ -974,7 +985,7 @@ int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
 		    && (policy & OTRL_POLICY_WHITESPACE_START_AKE)) {
 		switch(bestversion) {
 		    case 2:
-			err = otrl_auth_start_v2(&(context->auth), NULL, 0);
+			err = otrl_auth_start_v2(&(context->auth));
 			send_or_error_auth(ops, opdata, err, context);
 			break;
 		    case 1:
@@ -1088,7 +1099,8 @@ void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops,
 	    gcry_error_t err;
 	    OtrlTLV *tlv = otrl_tlv_new(OTRL_TLV_DISCONNECTED, 0, NULL);
 
-	    err = otrl_proto_create_data(&encmsg, context, "", tlv);
+	    err = otrl_proto_create_data(&encmsg, context, "", tlv,
+		    OTRL_MSGFLAGS_IGNORE_UNREADABLE);
 	    if (!err) {
 		ops->inject_message(opdata, accountname, protocol,
 			username, encmsg);
diff --git a/src/proto.c b/src/proto.c
index 5055ba5..fdd2a99 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -336,6 +336,7 @@ OtrlMessageType otrl_proto_message_type(const char *message)
     if (!strncmp(otrtag, "?OTR:AAIS", 9)) return OTRL_MSGTYPE_SIGNATURE;
     if (!strncmp(otrtag, "?OTR:AAEK", 9)) return OTRL_MSGTYPE_V1_KEYEXCH;
     if (!strncmp(otrtag, "?OTR:AAED", 9)) return OTRL_MSGTYPE_DATA;
+    if (!strncmp(otrtag, "?OTR:AAID", 9)) return OTRL_MSGTYPE_DATA;
     if (!strncmp(otrtag, "?OTR Error:", 11)) return OTRL_MSGTYPE_ERROR;
 
     return OTRL_MSGTYPE_UNKNOWN;
@@ -345,7 +346,7 @@ OtrlMessageType otrl_proto_message_type(const char *message)
  * optional chain of TLVs.  A newly-allocated string will be returned in
  * *encmessagep. */
 gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
-	const char *msg, const OtrlTLV *tlvs)
+	const char *msg, const OtrlTLV *tlvs, unsigned char flags)
 {
     size_t justmsglen = strlen(msg);
     size_t msglen = justmsglen + 1 + otrl_tlv_seriallen(tlvs);
@@ -362,6 +363,7 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
     char *msgbuf = NULL;
     enum gcry_mpi_format format = GCRYMPI_FMT_USG;
     char *msgdup;
+    int version = context->protocol_version;
 
     /* Make sure we're actually supposed to be able to encrypt */
     if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED ||
@@ -381,7 +383,8 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
 
     /* Header, send keyid, recv keyid, counter, msg len, msg
      * len of revealed mac keys, revealed mac keys, MAC */
-    buflen = 3 + 4 + 4 + 8 + 4 + msglen + 4 + reveallen + 20;
+    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);
     buflen += pubkeylen + 4;
     buf = malloc(buflen);
@@ -397,9 +400,17 @@ gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
     otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs);
     bufp = buf;
     lenp = buflen;
-    memmove(bufp, "\x00\x01\x03", 3);  /* header */
+    if (version == 1) {
+	memmove(bufp, "\x00\x01\x03", 3);  /* header */
+    } else {
+	memmove(bufp, "\x00\x02\x03", 3);  /* header */
+    }
     debug_data("Header", bufp, 3);
     bufp += 3; lenp -= 3;
+    if (version == 2) {
+	bufp[0] = flags;
+	bufp += 1; lenp -= 1;
+    }
     write_int(context->our_keyid-1);                    /* sender keyid */
     debug_int("Sender keyid", bufp-4);
     write_int(context->their_keyid);                    /* recipient keyid */
@@ -488,10 +499,66 @@ err:
     return err;
 }
 
+/* Extract the flags from an otherwise unreadable Data Message. */
+gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
+	unsigned char *flagsp)
+{
+    char *otrtag, *endtag;
+    unsigned char *rawmsg = NULL;
+    unsigned char *bufp;
+    size_t msglen, rawlen, lenp;
+    unsigned char version;
+
+    if (flagsp) *flagsp = 0;
+    otrtag = strstr(datamsg, "?OTR:");
+    if (!otrtag) {
+	goto invval;
+    }
+    endtag = strchr(otrtag, '.');
+    if (endtag) {
+	msglen = endtag-otrtag;
+    } else {
+	msglen = strlen(otrtag);
+    }
+
+    /* Base64-decode the message */
+    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
+    rawmsg = malloc(rawlen);
+    if (!rawmsg && rawlen > 0) {
+	return gcry_error(GPG_ERR_ENOMEM);
+    }
+    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */
+
+    bufp = rawmsg;
+    lenp = rawlen;
+
+    require_len(3);
+    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
+	/* Invalid header */
+	goto invval;
+    }
+    version = bufp[1];
+    bufp += 3; lenp -= 3;
+
+    if (version == 2) {
+	require_len(1);
+	if (flagsp) *flagsp = bufp[0];
+	bufp += 1; lenp -= 1;
+    }
+
+    free(rawmsg);
+    return gcry_error(GPG_ERR_NO_ERROR);
+
+invval:
+    free(rawmsg);
+    return gcry_error(GPG_ERR_INV_VALUE);
+}
+
 /* Accept an OTR Data Message in datamsg.  Decrypt it and put the
- * plaintext into *plaintextp, and any TLVs into tlvsp. */
+ * plaintext into *plaintextp, and any TLVs into tlvsp.  Put any
+ * received flags into *flagsp (if non-NULL). */
 gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
-	ConnContext *context, const char *datamsg)
+	ConnContext *context, const char *datamsg, unsigned char *flagsp)
 {
     char *otrtag, *endtag;
     gcry_error_t err;
@@ -507,9 +574,11 @@ gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
     unsigned char *nul = NULL;
     unsigned char givenmac[20];
     DH_sesskeys *sess;
+    unsigned char version;
 
     *plaintextp = NULL;
     *tlvsp = NULL;
+    if (flagsp) *flagsp = 0;
     otrtag = strstr(datamsg, "?OTR:");
     if (!otrtag) {
 	goto invval;
@@ -535,12 +604,18 @@ gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
 
     macstart = bufp;
     require_len(3);
-    if (memcmp(bufp, "\x00\x01\x03", 3)) {
+    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
 	/* Invalid header */
 	goto invval;
     }
+    version = bufp[1];
     bufp += 3; lenp -= 3;
 
+    if (version == 2) {
+	require_len(1);
+	if (flagsp) *flagsp = bufp[0];
+	bufp += 1; lenp -= 1;
+    }
     read_int(sender_keyid);
     read_int(recipient_keyid);
     read_mpi(sender_next_y);
diff --git a/src/proto.h b/src/proto.h
index 03adecf..5fd2d3a 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -31,8 +31,8 @@
 #define OTRL_MESSAGE_TAG_V1 " \t \t  \t "
 #define OTRL_MESSAGE_TAG_V2 "  \t\t  \t "
 
-    /* This is the bit sequence of the string "OTR", encoded in tabs and
-     * spaces. */
+/* The possible flags contained in a Data Message */
+#define OTRL_MSGFLAGS_IGNORE_UNREADABLE		0x01
 
 typedef unsigned int OtrlPolicy;
 
@@ -121,12 +121,17 @@ OtrlMessageType otrl_proto_message_type(const char *message);
  * optional chain of TLVs.  A newly-allocated string will be returned in
  * *encmessagep. */
 gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
-	const char *msg, const OtrlTLV *tlvs);
+	const char *msg, const OtrlTLV *tlvs, unsigned char flags);
+
+/* Extract the flags from an otherwise unreadable Data Message. */
+gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
+	unsigned char *flagsp);
 
 /* Accept an OTR Data Message in datamsg.  Decrypt it and put the
- * plaintext into *plaintextp, and any TLVs into tlvsp. */
+ * plaintext into *plaintextp, and any TLVs into tlvsp.  Put any
+ * received flags into *flagsp (if non-NULL). */
 gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
-	ConnContext *context, const char *datamsg);
+	ConnContext *context, const char *datamsg, unsigned char *flagsp);
 
 /* Accumulate a potential fragment into the current context. */
 OtrlFragmentResult otrl_proto_fragment_accumulate(char **unfragmessagep,
diff --git a/src/tests.c b/src/tests.c
index 19e162e..b3455d0 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -204,7 +204,23 @@ void test_crash1(void)
     alicecontext->sesskeys[1][0].sendenc,
     alicecontext->sesskeys[1][1].sendenc);
     sending(BOB, ALICE, "then."); dispatch();
+}
+
+void test_refresh(void)
+{
+    printf("\n\n*** Testing refresh ***\n\n");
+
+    otrl_context_forget_all(us);
+    ALICEPOLICY = OTRL_POLICY_DEFAULT;
+    sending(ALICE, BOB, "?OTR?"); dispatch();
 
+    sending(ALICE, BOB, "Hi!"); dispatch();
+    sending(BOB, ALICE, "There!"); dispatch();
+    sending(ALICE, BOB, "You!"); dispatch();
+    sending(ALICE, BOB, "Guys!"); dispatch();
+    sending(BOB, ALICE, "?OTR?"); dispatch();
+    sending(ALICE, BOB, "Refreshed!"); dispatch();
+    sending(BOB, ALICE, "Also refreshed!"); dispatch();
 }
 
 int main(int argc, char **argv)
@@ -220,7 +236,7 @@ int main(int argc, char **argv)
     test(2,1);
     test_unreadable();
     test_crash1();
-
+    test_refresh();
 
     otrl_userstate_free(us);
 
diff --git a/toolkit/otr_parse.c b/toolkit/otr_parse.c
index 9a88659..afdac72 100644
--- a/toolkit/otr_parse.c
+++ b/toolkit/otr_parse.c
@@ -120,6 +120,9 @@ static void parse(const char *msg)
 		break;
 	    }
 	    printf("Data Message:\n");
+	    if (datamsg->flags >= 0) {
+		dump_int(stdout, "\tFlags", datamsg->flags);
+	    }
 	    dump_int(stdout, "\tSender keyid", datamsg->sender_keyid);
 	    dump_int(stdout, "\tRcpt keyid", datamsg->rcpt_keyid);
 	    dump_mpi(stdout, "\tDH y", datamsg->y);
diff --git a/toolkit/otr_remac.c b/toolkit/otr_remac.c
index e644c4d..0ffe90b 100644
--- a/toolkit/otr_remac.c
+++ b/toolkit/otr_remac.c
@@ -30,8 +30,8 @@
 
 static void usage(const char *progname)
 {
-    fprintf(stderr, "Usage: %s mackey snd_keyid rcp_keyid pubkey counter "
-	    "encdata revealed_mackeys\n"
+    fprintf(stderr, "Usage: %s mackey flags snd_keyid rcp_keyid pubkey "
+	    "counter encdata revealed_mackeys\n"
 "Make a new Data message, with the given pieces (note that the\n"
 "data part is already encrypted).  MAC it with the given mackey.\n"
 "mackey, pubkey, counter, encdata, and revealed_mackeys are given\n"
@@ -44,6 +44,7 @@ int main(int argc, char **argv)
     unsigned char *mackey;
     size_t mackeylen;
     unsigned int snd_keyid, rcp_keyid;
+    int flags;
     unsigned char *pubkey;
     size_t pubkeylen;
     gcry_mpi_t pubv;
@@ -55,7 +56,7 @@ int main(int argc, char **argv)
     size_t mackeyslen;
     char *newdatamsg;
 
-    if (argc != 8) {
+    if (argc != 9) {
 	usage(argv[0]);
     }
 
@@ -69,24 +70,29 @@ int main(int argc, char **argv)
 	usage(argv[0]);
     }
 
-    if (sscanf(argv[2], "%u", &snd_keyid) != 1) {
+    if (sscanf(argv[2], "%d", &flags) != 1) {
+	fprintf(stderr, "Unparseable flags given.\n");
+	usage(argv[0]);
+    }
+
+    if (sscanf(argv[3], "%u", &snd_keyid) != 1) {
 	fprintf(stderr, "Unparseable snd_keyid given.\n");
 	usage(argv[0]);
     }
 
-    if (sscanf(argv[3], "%u", &rcp_keyid) != 1) {
+    if (sscanf(argv[4], "%u", &rcp_keyid) != 1) {
 	fprintf(stderr, "Unparseable rcp_keyid given.\n");
 	usage(argv[0]);
     }
 
-    argv_to_buf(&pubkey, &pubkeylen, argv[4]);
+    argv_to_buf(&pubkey, &pubkeylen, argv[5]);
     if (!pubkey) {
 	usage(argv[0]);
     }
     gcry_mpi_scan(&pubv, GCRYMPI_FMT_USG, pubkey, pubkeylen, NULL);
     free(pubkey);
     
-    argv_to_buf(&ctr, &ctrlen, argv[5]);
+    argv_to_buf(&ctr, &ctrlen, argv[6]);
     if (!ctr) {
 	usage(argv[0]);
     }
@@ -96,18 +102,18 @@ int main(int argc, char **argv)
 	usage(argv[0]);
     }
 
-    argv_to_buf(&encdata, &encdatalen, argv[6]);
+    argv_to_buf(&encdata, &encdatalen, argv[7]);
     if (!encdata) {
 	usage(argv[0]);
     }
 
-    argv_to_buf(&mackeys, &mackeyslen, argv[7]);
+    argv_to_buf(&mackeys, &mackeyslen, argv[8]);
     if (!mackeys) {
 	usage(argv[0]);
     }
 
-    newdatamsg = assemble_datamsg(mackey, snd_keyid, rcp_keyid, pubv, ctr,
-	    encdata, encdatalen, mackeys, mackeyslen);
+    newdatamsg = assemble_datamsg(mackey, flags, snd_keyid, rcp_keyid,
+	    pubv, ctr, encdata, encdatalen, mackeys, mackeyslen);
     printf("%s\n", newdatamsg);
     free(newdatamsg);
 
diff --git a/toolkit/parse.c b/toolkit/parse.c
index 456754c..e07c86a 100644
--- a/toolkit/parse.c
+++ b/toolkit/parse.c
@@ -375,6 +375,7 @@ DataMsg parse_datamsg(const char *msg)
     size_t lenp;
     unsigned char *raw = decode(msg, &lenp);
     unsigned char *bufp = raw;
+    unsigned char version;
     if (!raw) goto inv;
 
     datam = calloc(1, sizeof(struct s_DataMsg));
@@ -388,9 +389,18 @@ DataMsg parse_datamsg(const char *msg)
     datam->macstart = bufp;
 
     require_len(3);
-    if (memcmp(bufp, "\x00\x01\x03", 3)) goto inv;
+    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3))
+	goto inv;
+    version = bufp[1];
     bufp += 3; lenp -= 3;
 
+    if (version == 2) {
+	require_len(1);
+	datam->flags = bufp[0];
+	bufp += 1; lenp -= 1;
+    } else {
+	datam->flags = -1;
+    }
     read_int(datam->sender_keyid);
     read_int(datam->rcpt_keyid);
     read_mpi(datam->y);
@@ -425,11 +435,12 @@ char *remac_datamsg(DataMsg datamsg, unsigned char mackey[20])
     size_t base64len;
     char *outmsg;
     unsigned char *raw, *bufp;
+    unsigned char version = (datamsg->flags >= 0 ? 2 : 1);
     
     /* Calculate the size of the message that will result */
     gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &ylen, datamsg->y);
-    rawlen = 3 + 4 + 4 + 4 + ylen + 8 + 4 + datamsg->encmsglen + 20 +
-	4 + datamsg->mackeyslen;
+    rawlen = 3 + (version == 2 ? 1 : 0) + 4 + 4 + 4 + ylen + 8 + 4 +
+	datamsg->encmsglen + 20 + 4 + datamsg->mackeyslen;
 
     /* Construct the new raw message (note that some of the pieces may
      * have been altered, so we construct it from scratch). */
@@ -446,8 +457,16 @@ char *remac_datamsg(DataMsg datamsg, unsigned char mackey[20])
     datamsg->raw = raw;
     datamsg->rawlen = rawlen;
 
-    memmove(bufp, "\x00\x01\x03", 3);
+    if (version == 1) {
+	memmove(bufp, "\x00\x01\x03", 3);
+    } else {
+	memmove(bufp, "\x00\x02\x03", 3);
+    }
     bufp += 3; lenp -= 3;
+    if (version == 2) {
+	bufp[0] = datamsg->flags;
+	bufp += 1; lenp -= 1;
+    }
     write_int(datamsg->sender_keyid);
     write_int(datamsg->rcpt_keyid);
     write_mpi(datamsg->y, ylen);
@@ -481,14 +500,15 @@ char *remac_datamsg(DataMsg datamsg, unsigned char mackey[20])
 
 /* Assemble a new Data Message from its pieces.  Return a
  * newly-allocated string containing the base64 representation. */
-char *assemble_datamsg(unsigned char mackey[20], unsigned int sender_keyid,
-	unsigned int rcpt_keyid, gcry_mpi_t y, unsigned char ctr[8],
-	unsigned char *encmsg, size_t encmsglen, unsigned char *mackeys,
-	size_t mackeyslen)
+char *assemble_datamsg(unsigned char mackey[20], int flags,
+	unsigned int sender_keyid, unsigned int rcpt_keyid, gcry_mpi_t y,
+	unsigned char ctr[8], unsigned char *encmsg, size_t encmsglen,
+	unsigned char *mackeys, size_t mackeyslen)
 {
     DataMsg datam = calloc(1, sizeof(struct s_DataMsg));
     char *newmsg = NULL;
     if (!datam) goto inv;
+    datam->flags = flags;
     datam->sender_keyid = sender_keyid;
     datam->rcpt_keyid = rcpt_keyid;
     datam->y = gcry_mpi_copy(y);
diff --git a/toolkit/parse.h b/toolkit/parse.h
index 9329289..1db65bc 100644
--- a/toolkit/parse.h
+++ b/toolkit/parse.h
@@ -36,6 +36,7 @@ typedef struct s_KeyExchMsg {
 typedef struct s_DataMsg {
     unsigned char *raw;         /* The base64-decoded data; must be free()d */
     size_t rawlen;
+    int flags;
     unsigned int sender_keyid;
     unsigned int rcpt_keyid;
     gcry_mpi_t y;
@@ -130,10 +131,10 @@ char *remac_datamsg(DataMsg datamsg, unsigned char mackey[20]);
 
 /* Assemble a new Data Message from its pieces.  Return a
  * newly-allocated string containing the base64 representation. */
-char *assemble_datamsg(unsigned char mackey[20], unsigned int sender_keyid,
-	unsigned int rcpt_keyid, gcry_mpi_t y, unsigned char ctr[8],
-	unsigned char *encmsg, size_t encmsglen, unsigned char *mackeys,
-	size_t mackeyslen);
+char *assemble_datamsg(unsigned char mackey[20], int flags,
+	unsigned int sender_keyid, unsigned int rcpt_keyid, gcry_mpi_t y,
+	unsigned char ctr[8], unsigned char *encmsg, size_t encmsglen,
+	unsigned char *mackeys, size_t mackeyslen);
 
 /* Deallocate a DataMsg and all of the data it points to */
 void free_datamsg(DataMsg datamsg);

-- 
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