Module: sip-router
Branch: pd/outbound
Commit: 1db38af24d8808a9a2045c7bac25581199717a2b
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1db38af…
Author: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley(a)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;
}