[sr-dev] git:pd/outbound: modules_k/outbound: Filled in functions to encode and decode flow tokens

Peter Dunkley peter.dunkley at crocodile-rcs.com
Sat Dec 22 14:08:23 CET 2012


Module: sip-router
Branch: pd/outbound
Commit: 1db38af24d8808a9a2045c7bac25581199717a2b
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1db38af24d8808a9a2045c7bac25581199717a2b

Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Date:   Sat Dec 22 13:07:58 2012 +0000

modules_k/outbound: Filled in functions to encode and decode flow tokens

---

 modules_k/outbound/Makefile |    2 +-
 modules_k/outbound/ob_mod.c |  108 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/modules_k/outbound/Makefile b/modules_k/outbound/Makefile
index 148a900..e877c04 100644
--- a/modules_k/outbound/Makefile
+++ b/modules_k/outbound/Makefile
@@ -18,7 +18,7 @@ else
 	LIBS=  $(shell pkg-config --libs libssl)
 endif
 
-DEFS+=-DOPENSER_MOD_INTERFACE
+DEFS+=-DKAMAILIO_MOD_INTERFACE
 
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
diff --git a/modules_k/outbound/ob_mod.c b/modules_k/outbound/ob_mod.c
index fbbee03..63e922f 100644
--- a/modules_k/outbound/ob_mod.c
+++ b/modules_k/outbound/ob_mod.c
@@ -20,7 +20,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
+#include <openssl/hmac.h>
 
+#include "../../basex.h"
 #include "../../dprint.h"
 #include "../../dset.h"
 #include "../../ip_addr.h"
@@ -90,14 +92,118 @@ static int mod_init(void)
 	return 0;
 }
 
+/* Structure of flow token
+
+   <HMAC-SHA1-80><protocol><dst_ip><dst_port><src_ip><src_port>
+          10     +    1    +  16   +    2    +  16   +    2
+	   = 47 bytes
+
+   IP addresses will always be 16 bytes. When an IPv4 address is used the
+   address will be encoded in the first four bytes and the last four bytes will
+   be ignored.
+
+   base64 encoded size: ceiling((47+2)/3)*4 = 68 bytes
+*/
+
+#define UNENC_FLOW_TOKEN_LENGTH	47
+#define SHA1_LENGTH		20
+#define SHA1_80_LENGTH		10
+#define FLOW_TOKEN_START_POS	(SHA1_80_LENGTH)
+static unsigned char unenc_flow_token[UNENC_FLOW_TOKEN_LENGTH];
+static unsigned char hmac_sha1[EVP_MAX_MD_SIZE];
+
 int encode_flow_token(str *flow_token, struct receive_info rcv)
 {
-	
+	int pos = FLOW_TOKEN_START_POS, i;
+
+	if (flow_token == NULL)
+	{
+		LM_ERR("bad string pointer\n");
+		return -1;
+	}
+
+	/* Encode protocol information */
+	unenc_flow_token[pos++] = rcv.proto;
+
+	/* Encode destination address */
+	for (i = 0; i < 16; i++)
+		unenc_flow_token[pos++] = rcv.dst_ip.u.addr[i];
+	unenc_flow_token[pos++] = (rcv.dst_port >> 8) & 0xff;
+	unenc_flow_token[pos++] =  rcv.dst_port       & 0xff;
+
+	/* Encode source address */
+	for (i = 0; i < 16; i++)
+		unenc_flow_token[pos++] = rcv.src_ip.u.addr[i];
+	unenc_flow_token[pos++] = (rcv.dst_port >> 8) & 0xff;
+	unenc_flow_token[pos++] =  rcv.dst_port       & 0xff;
+
+	/* HMAC-SHA1 the calculated flow token, truncate to 80 bits, and
+	   prepend onto the flow token */
+	HMAC(EVP_sha1(), ob_key.s, ob_key.len,
+		&unenc_flow_token[FLOW_TOKEN_START_POS],
+		UNENC_FLOW_TOKEN_LENGTH - FLOW_TOKEN_START_POS,
+		hmac_sha1, NULL);
+	memcpy(unenc_flow_token, &hmac_sha1[SHA1_LENGTH - SHA1_80_LENGTH],
+		SHA1_80_LENGTH);
+
+	/* base64 encode the entire flow token and store for the caller to
+ 	   use */
+	flow_token->s = pkg_malloc(base64_enc_len(UNENC_FLOW_TOKEN_LENGTH));
+	if (flow_token->s == NULL)
+	{
+		LM_ERR("allocating package memory\n");
+		return -1;
+	}
+	flow_token->len = base64_enc(unenc_flow_token, UNENC_FLOW_TOKEN_LENGTH,
+				(unsigned char *) flow_token->s,
+				base64_enc_len(UNENC_FLOW_TOKEN_LENGTH));
+
 	return 0;
 }
 
 int decode_flow_token(struct receive_info *rcv, str flow_token)
 {
+	int pos = FLOW_TOKEN_START_POS, i;
+
+	if (flow_token.len != base64_enc_len(UNENC_FLOW_TOKEN_LENGTH))
+	{
+		LM_ERR("bad flow token length.  Length is %d, expected %d\n",
+			flow_token.len, UNENC_FLOW_TOKEN_LENGTH);
+		return -1;
+	}
+
+	/* base64 decode the flow token */
+	base64_dec((unsigned char *) flow_token.s, flow_token.len,
+			unenc_flow_token, UNENC_FLOW_TOKEN_LENGTH);
+
+	/* HMAC-SHA1 the flow token (after the hash) and compare with the
+	   truncated hash at the start of the flow token. */
+	HMAC(EVP_sha1(), ob_key.s, ob_key.len,
+		&unenc_flow_token[FLOW_TOKEN_START_POS],
+		UNENC_FLOW_TOKEN_LENGTH - FLOW_TOKEN_START_POS,
+		hmac_sha1, NULL);
+	if (memcmp(unenc_flow_token, &hmac_sha1[SHA1_LENGTH - SHA1_80_LENGTH],
+		SHA1_80_LENGTH) != 0)
+	{
+		LM_ERR("flow token failed validation\n");
+		return -1;
+	}
+
+	/* Decode protocol information */
+	rcv->proto = unenc_flow_token[pos++];
+
+	/* Decode destination address */
+	for (i = 0; i < 16; i++)
+		rcv->dst_ip.u.addr[i] = unenc_flow_token[pos++];
+	rcv->dst_port = ((unenc_flow_token[pos++] << 8) & 0xff)
+				| (unenc_flow_token[pos++] & 0xff);
+
+	/* Decode source address */
+	for (i = 0; i < 16; i++)
+		rcv->src_ip.u.addr[i] = unenc_flow_token[pos++];
+	rcv->src_port = ((unenc_flow_token[pos++] << 8) & 0xff)
+				| (unenc_flow_token[pos++] & 0xff);
+
 	return 0;
 }
 




More information about the sr-dev mailing list