2
0
Эх сурвалжийг харах

siputils: functions to encode/decode contact address in a uri param

Daniel-Constantin Mierla 5 жил өмнө
parent
commit
e2fd3c3e85

+ 249 - 0
src/modules/siputils/contact_ops.c

@@ -33,9 +33,11 @@
 #include "utils.h"
 #include "../../core/mem/mem.h"
 #include "../../core/data_lump.h"
+#include "../../core/basex.h"
 #include "../../core/parser/hf.h"
 #include "../../core/parser/parse_uri.h"
 #include "../../core/parser/contact/parse_contact.h"
+#include "../../core/dset.h"
 #include "../../core/ut.h"
 
 #include <stdio.h>
@@ -628,3 +630,250 @@ int decode_uri(str uri, char separator, str *result)
 
 	return 0;
 }
+
+int ki_contact_param_encode(sip_msg_t *msg, str *nparam, str *saddr)
+{
+	contact_body_t *cb;
+	contact_t *c;
+	str nuri;
+	char bval[MAX_URI_SIZE];
+	str pval;
+
+	if((msg->contact == NULL)
+			&& ((parse_headers(msg, HDR_CONTACT_F, 0) == -1)
+					|| (msg->contact == NULL))) {
+		LM_DBG("no Contact header present\n");
+		return 1;
+	}
+
+	cb = (contact_body_t *)msg->contact->parsed;
+	c = cb->contacts;
+	/* we visit each contact */
+	while(c != NULL) {
+		if(c->uri.len>4) {
+			pval.len = base64url_enc(c->uri.s, c->uri.len, bval, MAX_URI_SIZE-1);
+			if (pval.len < 0) {
+				LM_ERR("failed to encode contact uri [%.*s]\n",
+						c->uri.len, c->uri.s);
+				return -1;
+			}
+			if (pval.len>1 && bval[pval.len-1] == '=') {
+				pval.len--;
+				if (pval.len>1 && bval[pval.len-1] == '=') {
+					pval.len--;
+				}
+			}
+			bval[pval.len] = '\0';
+			pval.s = bval;
+			nuri.s = (char*)pkg_malloc(MAX_URI_SIZE * sizeof(char));
+			if(nuri.s==NULL) {
+				PKG_MEM_ERROR;
+				return -1;
+			}
+			nuri.len = snprintf(nuri.s, MAX_URI_SIZE-1, "sip:%.*s;%.*s=%.*s",
+					saddr->len, saddr->s, nparam->len, nparam->s,
+					pval.len, pval.s);
+			if(nuri.len<=0 || nuri.len>=MAX_URI_SIZE) {
+				LM_ERR("failed to build the new contact for [%.*s] uri (%d)\n",
+						c->uri.len, c->uri.s, nuri.len);
+				pkg_free(nuri.s);
+				return -2;
+			}
+			if(patch(msg, c->uri.s, c->uri.len, nuri.s, nuri.len) < 0) {
+				LM_ERR("failed to update contact uri [%.*s]\n",
+						c->uri.len, c->uri.s);
+				pkg_free(nuri.s);
+				return -3;
+			}
+		}
+		c = c->next;
+	}
+
+	return 1;
+}
+
+int ki_contact_param_decode(sip_msg_t *msg, str *nparam)
+{
+	contact_body_t *cb;
+	contact_t *c;
+	param_t* pit;
+	char boval[MAX_URI_SIZE];
+	char bnval[MAX_URI_SIZE];
+	str oval;
+	str nval;
+	int i;
+
+	if((msg->contact == NULL)
+			&& ((parse_headers(msg, HDR_CONTACT_F, 0) == -1)
+					|| (msg->contact == NULL))) {
+		LM_DBG("no Contact header present\n");
+		return 1;
+	}
+
+	if(msg->contact->parsed == NULL) {
+		if(parse_contact(msg->contact) < 0 || msg->contact->parsed == NULL) {
+			LM_ERR("contact parsing failed\n");
+			return -1;
+		}
+	}
+
+	cb = (contact_body_t *)msg->contact->parsed;
+	c = cb->contacts;
+	while(c != NULL) {
+		pit = c->params;
+		while(pit!=NULL) {
+			if(pit->name.len==nparam->len
+					&& strncasecmp(pit->name.s, nparam->s, nparam->len)==0) {
+				break;
+			}
+			pit=pit->next;
+		}
+		if(pit!=NULL && pit->body.len>0) {
+			oval = pit->body;
+			if(oval.len % 4) {
+				if(oval.len + 4 >= MAX_URI_SIZE-1) {
+					LM_ERR("not enough space to insert padding [%.*s]\n",
+							c->uri.len, c->uri.s);
+					return -1;
+				}
+				memcpy(boval, oval.s, oval.len);
+				for(i=0; i < (4 - (oval.len % 4)); i++) {
+					boval[oval.len + i] = '=';
+				}
+				oval.s = boval;
+				oval.len += (4 - (oval.len % 4));
+				/* move to next buffer */
+			}
+			nval.len = base64url_dec(oval.s, oval.len, bnval, MAX_URI_SIZE-1);
+			if (nval.len <= 0) {
+				LM_ERR("failed to decode contact uri [%.*s]\n",
+							c->uri.len, c->uri.s);
+				return -1;
+			}
+			nval.s = (char*)pkg_malloc((nval.len+1)*sizeof(char));
+			if(nval.s==NULL) {
+				PKG_MEM_ERROR;
+				return -1;
+			}
+			memcpy(nval.s, bnval, nval.len);
+			nval.s[nval.len] = '\0';
+
+			LM_DBG("new uri [%.*s]\n", nval.len, nval.s);
+			if(patch(msg, c->uri.s, c->uri.len, nval.s, nval.len) < 0) {
+				LM_ERR("failed to update contact uri [%.*s]\n",
+						c->uri.len, c->uri.s);
+				pkg_free(nval.s);
+				return -2;
+			}
+		}
+
+		c = c->next;
+	}
+
+	return 1;
+}
+
+/**
+ *
+ */
+int ki_contact_param_decode_ruri(sip_msg_t *msg, str *nparam)
+{
+	str uri;
+	sip_uri_t puri;
+	str sparams;
+	param_t* params = NULL;
+	param_hooks_t phooks;
+	param_t *pit=NULL;
+	char boval[MAX_URI_SIZE];
+	char bnval[MAX_URI_SIZE];
+	str oval;
+	str nval;
+	int i;
+
+	if((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
+		uri = msg->first_line.u.request.uri;
+		if(uri.s == NULL) {
+			LM_ERR("r-uri not found\n");
+			return -1;
+		}
+	} else {
+		uri = msg->new_uri;
+	}
+
+	if (parse_uri (uri.s, uri.len, &puri) < 0) {
+		LM_ERR("failed to parse r-uri [%.*s]\n", uri.len, uri.s);
+		return -1;
+	}
+	if(puri.sip_params.len>0) {
+		sparams = puri.sip_params;
+	} else if(puri.params.len>0) {
+		sparams = puri.params;
+	} else {
+		LM_DBG("no uri params [%.*s]\n", uri.len, uri.s);
+		return 1;
+	}
+
+	if (parse_params2(&sparams, CLASS_ANY, &phooks, &params, ';')<0) {
+		LM_ERR("failed to parse uri params [%.*s]\n", uri.len, uri.s);
+		return -1;
+	}
+
+	pit = params;
+	while(pit!=NULL) {
+		if(pit->name.len==nparam->len
+				&& strncasecmp(pit->name.s, nparam->s, nparam->len)==0) {
+			break;
+		}
+		pit=pit->next;
+	}
+	if(pit==NULL || pit->body.len<=0) {
+		free_params(params);
+		LM_DBG("no uri param value [%.*s]\n", uri.len, uri.s);
+		return 1;
+	}
+
+	oval = pit->body;
+	if(oval.len % 4) {
+		if(oval.len + 4 >= MAX_URI_SIZE-1) {
+			LM_ERR("not enough space to insert padding [%.*s]\n",
+					uri.len, uri.s);
+			free_params(params);
+			return -1;
+		}
+		memcpy(boval, oval.s, oval.len);
+		for(i=0; i < (4 - (oval.len % 4)); i++) {
+			boval[oval.len + i] = '=';
+		}
+		oval.s = boval;
+		oval.len += (4 - (oval.len % 4));
+		/* move to next buffer */
+	}
+	nval.len = base64url_dec(oval.s, oval.len, bnval, MAX_URI_SIZE-1);
+	if (nval.len <= 0) {
+		free_params(params);
+		LM_ERR("failed to decode uri [%.*s]\n", uri.len, uri.s);
+		return -1;
+	}
+	nval.s = (char*)pkg_malloc((nval.len+1)*sizeof(char));
+	if(nval.s==NULL) {
+		free_params(params);
+		PKG_MEM_ERROR;
+		return -1;
+	}
+	memcpy(nval.s, bnval, nval.len);
+	nval.s[nval.len] = '\0';
+
+	LM_DBG("new uri [%.*s]\n", nval.len, nval.s);
+
+	if((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
+		msg->new_uri = nval;
+	} else {
+		pkg_free(msg->new_uri.s);
+		msg->new_uri = nval;
+	}
+	ruri_mark_new(); /* re-use uri for serial forking */
+
+	free_params(params);
+
+	return 1;
+}

+ 4 - 0
src/modules/siputils/contact_ops.h

@@ -72,4 +72,8 @@ int encode_uri(str uri, char *encoding_prefix, char *public_ip, char separator,
 		str *result);
 int decode_uri(str uri, char separator, str *result);
 
+int ki_contact_param_encode(sip_msg_t *msg, str *nparam, str *saddr);
+int ki_contact_param_decode(sip_msg_t *msg, str *nparam);
+int ki_contact_param_decode_ruri(sip_msg_t *msg, str *nparam);
+
 #endif

+ 67 - 0
src/modules/siputils/siputils.c

@@ -108,6 +108,10 @@ sl_api_t opt_slb;
 static int mod_init(void);
 static void mod_destroy(void);
 
+static int w_contact_param_encode(sip_msg_t *msg, char *pnparam, char *psaddr);
+static int w_contact_param_decode(sip_msg_t *msg, char *pnparam, char *p2);
+static int w_contact_param_decode_ruri(sip_msg_t *msg, char *pnparam, char *p2);
+
 /* Fixup functions to be defined later */
 static int fixup_set_uri(void** param, int param_no);
 static int fixup_free_set_uri(void** param, int param_no);
@@ -186,6 +190,12 @@ static cmd_export_t cmds[]={
 		0, ANY_ROUTE},
 	{"sip_p_charging_vector", (cmd_function)sip_handle_pcv,  1, fixup_spve_null,
 		fixup_free_spve_null, ANY_ROUTE},
+	{"contact_param_encode",      (cmd_function)w_contact_param_encode,    2,
+		fixup_spve_spve, fixup_free_spve_spve, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{"contact_param_decode",      (cmd_function)w_contact_param_decode,    1,
+		fixup_spve_null, fixup_free_spve_null, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{"contact_param_decode_ruri", (cmd_function)w_contact_param_decode_ruri, 1,
+		fixup_spve_null, fixup_free_spve_null, REQUEST_ROUTE},
 
 	{"bind_siputils",       (cmd_function)bind_siputils,           1, 0,
 		0, 0},
@@ -460,6 +470,47 @@ static int fixup_option(void** param, int param_no) {
 	return 0;
 }
 
+static int w_contact_param_encode(sip_msg_t *msg, char *pnparam, char *psaddr)
+{
+	str nparam = STR_NULL;
+	str saddr = STR_NULL;
+
+	if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) {
+		LM_ERR("failed to get p1\n");
+		return -1;
+	}
+
+	if(fixup_get_svalue(msg, (gparam_t*)psaddr, &saddr)<0) {
+		LM_ERR("failed to get p1\n");
+		return -1;
+	}
+	return ki_contact_param_encode(msg, &nparam, &saddr);
+}
+
+static int w_contact_param_decode(sip_msg_t *msg, char *pnparam, char *p2)
+{
+	str nparam = STR_NULL;
+
+	if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) {
+		LM_ERR("failed to get p1\n");
+		return -1;
+	}
+
+	return ki_contact_param_decode(msg, &nparam);
+}
+
+static int w_contact_param_decode_ruri(sip_msg_t *msg, char *pnparam, char *p3)
+{
+	str nparam = STR_NULL;
+
+	if(fixup_get_svalue(msg, (gparam_t*)pnparam, &nparam)<0) {
+		LM_ERR("failed to get p1\n");
+		return -1;
+	}
+
+	return ki_contact_param_decode_ruri(msg, &nparam);
+}
+
 /*
  * Check if pseudo variable contains a valid uri
  */
@@ -561,6 +612,22 @@ static sr_kemi_t sr_kemi_siputils_exports[] = {
 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
+	{ str_init("siputils"), str_init("contact_param_encode"),
+		SR_KEMIP_INT, ki_contact_param_encode,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("siputils"), str_init("contact_param_decode"),
+		SR_KEMIP_INT, ki_contact_param_decode,
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("siputils"), str_init("contact_param_decode_ruri"),
+		SR_KEMIP_INT, ki_contact_param_decode_ruri,
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+
 
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
 };