1 /*
2  * Path handling for intermediate proxies.
3  *
4  * Copyright (C) 2006 Inode GmbH (Andreas Granig <andreas.granig@inode.info>)
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 /*! \file
25  * \brief Path :: Utilities
26  *
27  * \ingroup path
28  * - Module: path
29  */
30 
31 #include <string.h>
32 #include <stdio.h>
33 
34 #include "../../core/mem/mem.h"
35 #include "../../core/data_lump.h"
36 #include "../../core/parser/parse_param.h"
37 #include "../../core/parser/parse_uri.h"
38 #include "../../core/strutils.h"
39 #include "../../core/dset.h"
40 
41 #include "path.h"
42 #include "path_mod.h"
43 
44 typedef enum {
45 	PATH_PARAM_NONE = 0, PATH_PARAM_RECEIVED = 1, PATH_PARAM_OB = 2
46 } path_param_t;
47 
48 #define PATH_PREFIX		"Path: <sip:"
49 #define PATH_PREFIX_LEN		(sizeof(PATH_PREFIX)-1)
50 
51 const static char *proto_strings[] = {
52 	[PROTO_TCP] = "%3Btransport%3Dtcp",
53 	[PROTO_TLS] = "%3Btransport%3Dtls",
54 	[PROTO_SCTP] = "%3Btransport%3Dsctp",
55 	[PROTO_WS] = "%3Btransport%3Dws",
56 	[PROTO_WSS] = "%3Btransport%3Dws",
57 };
58 
59 extern int path_sockname_mode;
60 
path_strzdup(char * src,int len)61 static char *path_strzdup(char *src, int len)
62 {
63 	char *res;
64 
65 	if (!src)
66 		return NULL;
67 	if(len<0) {
68 		len = strlen(src);
69 	}
70 	if (!(res = (char *) pkg_malloc(len + 1)))
71 		return NULL;
72 	strncpy(res, src, len);
73 	res[len] = 0;
74 
75 	return res;
76 }
77 
handleOutbound(sip_msg_t * _m,str * user,path_param_t * param)78 static int handleOutbound(sip_msg_t* _m, str *user, path_param_t *param)
79 {
80 	if (path_obb.use_outbound != NULL && path_obb.use_outbound(_m)) {
81 		struct via_body *via;
82 
83 		if (path_obb.encode_flow_token(user, &_m->rcv) != 0) {
84 			LM_ERR("encoding outbound flow-token\n");
85 			return -1;
86 		}
87 
88 		/* Only include ;ob parameter if this is the first-hop
89 		 * (that means only one Via:) */
90 		if (parse_via_header(_m, 2, &via) < 0) {
91 			*param |= PATH_PARAM_OB;
92 		}
93 	}
94 
95 	return 1;
96 }
97 
prepend_path(sip_msg_t * _m,str * user,path_param_t param,str * add_params)98 static int prepend_path(sip_msg_t* _m, str *user, path_param_t param,
99 		str *add_params)
100 {
101 	struct lump *l;
102 	char *prefix, *suffix, *cp, *dp;
103 	const char *proto_str;
104 	int prefix_len, suffix_len;
105 	struct hdr_field *hf;
106 
107 	/* maximum possible length of suffix */
108 	suffix_len = sizeof(";lr;r2=on;received=sip::12345%3Btransport%3Dsctp;ob;>\r\n")
109 			+ IP_ADDR_MAX_STR_SIZE + 2 + (add_params ? add_params->len : 0) + 1;
110 
111 	cp = suffix = pkg_malloc(suffix_len);
112 	if (!suffix) {
113 		LM_ERR("no pkg memory left for suffix\n");
114 		goto out1;
115 	}
116 
117 	cp += sprintf(cp, ";lr");
118 
119 	if (param & PATH_PARAM_RECEIVED) {
120 		if(path_received_format==0) {
121 			if (_m->rcv.proto
122 						< (sizeof(proto_strings) / sizeof(*proto_strings))) {
123 				proto_str = proto_strings[(unsigned int) _m->rcv.proto];
124 			} else {
125 				proto_str = NULL;
126 			}
127 			if(_m->rcv.src_ip.af==AF_INET6) {
128 				cp += sprintf(cp, ";received=sip:[%s]:%hu%s",
129 						ip_addr2a(&_m->rcv.src_ip),
130 						_m->rcv.src_port, proto_str ? : "");
131 			} else {
132 				cp += sprintf(cp, ";received=sip:%s:%hu%s"
133 						, ip_addr2a(&_m->rcv.src_ip),
134 						_m->rcv.src_port, proto_str ? : "");
135 			}
136 		} else {
137 			if(_m->rcv.src_ip.af==AF_INET6) {
138 				cp += sprintf(cp, ";received=[%s]~%hu~%d",
139 						ip_addr2a(&_m->rcv.src_ip),
140 						_m->rcv.src_port, (int)_m->rcv.proto);
141 			} else {
142 				cp += sprintf(cp, ";received=%s~%hu~%d",
143 						ip_addr2a(&_m->rcv.src_ip),
144 						_m->rcv.src_port, (int)_m->rcv.proto);
145 			}
146 		}
147 	}
148 
149 	if (param & PATH_PARAM_OB) {
150 		cp += sprintf(cp, ";ob");
151 	}
152 
153 	if (add_params && add_params->len) {
154 		cp += sprintf(cp, ";%.*s", add_params->len, add_params->s);
155 	}
156 
157 	if(path_enable_r2==0) {
158 		cp += sprintf(cp, ">\r\n");
159 	} else {
160 		cp += sprintf(cp, ";r2=on>\r\n");
161 	}
162 
163 	prefix_len = PATH_PREFIX_LEN + (user ? user->len : 0) + 2;
164 	prefix = pkg_malloc(prefix_len);
165 	if (!prefix) {
166 		LM_ERR("no pkg memory left for prefix\n");
167 		goto out2;
168 	}
169 	if (user && user->len)
170 		prefix_len = sprintf(prefix, PATH_PREFIX "%.*s@", user->len, user->s);
171 	else
172 		prefix_len = sprintf(prefix, PATH_PREFIX);
173 
174 	if (parse_headers(_m, HDR_PATH_F, 0) < 0) {
175 		LM_ERR("failed to parse message for Path header\n");
176 		goto out3;
177 	}
178 	hf = get_hdr(_m, HDR_PATH_T);
179 	if (hf)
180 		/* path found, add ours in front of that */
181 		l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0);
182 	else
183 		/* no path, append to message */
184 		l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
185 	if (!l) {
186 		LM_ERR("failed to get anchor\n");
187 		goto out3;
188 	}
189 
190 	l = insert_new_lump_before(l, prefix, prefix_len, 0);
191 	if (!l) goto out3;
192 	l = insert_subst_lump_before(l,
193 			(path_sockname_mode)?SUBST_SND_ALL_EX:SUBST_SND_ALL, 0);
194 	if (!l) goto out2;
195 	l = insert_new_lump_before(l, suffix, cp - suffix, 0);
196 	if (!l) goto out2;
197 
198 	if(path_enable_r2!=0) {
199 		dp = path_strzdup(prefix, prefix_len);
200 		if(dp==NULL) goto out1;
201 		l = insert_new_lump_before(l, dp, prefix_len, 0);
202 		if (!l) goto out1;
203 		l = insert_subst_lump_before(l,
204 				(path_sockname_mode)?SUBST_RCV_ALL_EX:SUBST_RCV_ALL, 0);
205 		if (!l) goto out1;
206 		dp = path_strzdup(suffix, cp - suffix);
207 		if(dp==NULL) goto out1;
208 		l = insert_new_lump_before(l, dp, cp - suffix, 0);
209 		if (!l) goto out1;
210 	}
211 
212 	return 1;
213 
214 out3:
215 	pkg_free(prefix);
216 out2:
217 	pkg_free(suffix);
218 out1:
219 	LM_ERR("failed to insert Path header\n");
220 
221 	return -1;
222 }
223 
224 /*! \brief
225  * Prepend own uri to Path header
226  */
ki_add_path(struct sip_msg * _msg)227 int ki_add_path(struct sip_msg* _msg)
228 {
229 	str user = {0,0};
230 	int ret;
231 	path_param_t param = PATH_PARAM_NONE;
232 
233 	ret = handleOutbound(_msg, &user, &param);
234 
235 	if (ret > 0) {
236 		ret = prepend_path(_msg, &user, param, NULL);
237 	}
238 
239 	if (user.s != NULL) {
240 		pkg_free(user.s);
241 	}
242 
243 	return ret;
244 }
245 
add_path(sip_msg_t * _msg,char * _a,char * _b)246 int add_path(sip_msg_t* _msg, char* _a, char* _b)
247 {
248 	return ki_add_path(_msg);
249 }
250 
251 /*! \brief
252  * Prepend own uri to Path header and take care of given
253  * user.
254  */
add_path_usr(struct sip_msg * _msg,char * _usr,char * _parms)255 int add_path_usr(struct sip_msg* _msg, char* _usr, char* _parms)
256 {
257 	str user = {0,0};
258 	str parms = {0,0};
259 
260 	if (_usr) {
261 		if(get_str_fparam(&user, _msg, (fparam_t *) _usr)<0) {
262 			LM_ERR("failed to get user value\n");
263 			return -1;
264 		}
265 	}
266 	if (_parms) {
267 		if(get_str_fparam(&parms, _msg, (fparam_t *) _parms)<0) {
268 			LM_ERR("failed to get params value\n");
269 			return -1;
270 		}
271 	}
272 
273 	return prepend_path(_msg, &user, PATH_PARAM_NONE, &parms);
274 }
275 
276 /*! \brief
277  * Prepend own uri to Path header and take care of given
278  * user.
279  */
ki_add_path_user(sip_msg_t * _msg,str * _user)280 int ki_add_path_user(sip_msg_t* _msg, str* _user)
281 {
282 	str parms = {0,0};
283 	return prepend_path(_msg, _user, PATH_PARAM_NONE, &parms);
284 }
285 
286 /*! \brief
287  * Prepend own uri to Path header and take care of given
288  * user.
289  */
ki_add_path_user_params(sip_msg_t * _msg,str * _user,str * _params)290 int ki_add_path_user_params(sip_msg_t* _msg, str* _user, str* _params)
291 {
292 	return prepend_path(_msg, _user, PATH_PARAM_NONE, _params);
293 }
294 
295 /*! \brief
296  * Prepend own uri to Path header and append received address as
297  * "received"-param to that uri.
298  */
ki_add_path_received(sip_msg_t * _msg)299 int ki_add_path_received(sip_msg_t* _msg)
300 {
301 	str user = {0,0};
302 	int ret;
303 	path_param_t param = PATH_PARAM_RECEIVED;
304 
305 	ret = handleOutbound(_msg, &user, &param);
306 
307 	if (ret > 0) {
308 		ret = prepend_path(_msg, &user, param, NULL);
309 	}
310 
311 	if (user.s != NULL) {
312 		pkg_free(user.s);
313 	}
314 
315 	return ret;
316 }
317 
318 /*! \brief
319  * Prepend own uri to Path header and append received address as
320  * "received"-param to that uri.
321  */
add_path_received(struct sip_msg * _msg,char * _a,char * _b)322 int add_path_received(struct sip_msg* _msg, char* _a, char* _b)
323 {
324 	return ki_add_path_received(_msg);
325 }
326 
327 /*! \brief
328  * Prepend own uri to Path header and append received address as
329  * "received"-param to that uri and take care of given user.
330  */
add_path_received_usr(struct sip_msg * _msg,char * _usr,char * _parms)331 int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _parms)
332 {
333 	str user = {0,0};
334 	str parms = {0,0};
335 
336 	if (_usr) {
337 		if(get_str_fparam(&user, _msg, (fparam_t *) _usr)<0) {
338 			LM_ERR("failed to get user value\n");
339 			return -1;
340 		}
341 	}
342 	if (_parms) {
343 		if(get_str_fparam(&parms, _msg, (fparam_t *) _parms)<0) {
344 			LM_ERR("failed to get params value\n");
345 			return -1;
346 		}
347 	}
348 
349 	return prepend_path(_msg, &user, PATH_PARAM_RECEIVED, &parms);
350 }
351 
352 /*! \brief
353  * Prepend own uri to Path header and append received address as
354  * "received"-param to that uri and take care of given user.
355  */
ki_add_path_received_user(sip_msg_t * _msg,str * _user)356 int ki_add_path_received_user(sip_msg_t* _msg, str* _user)
357 {
358 	str parms = {0,0};
359 	return prepend_path(_msg, _user, PATH_PARAM_RECEIVED, &parms);
360 }
361 
362 /*! \brief
363  * Prepend own uri to Path header and append received address as
364  * "received"-param to that uri and take care of given user.
365  */
ki_add_path_received_user_params(sip_msg_t * _msg,str * _user,str * _params)366 int ki_add_path_received_user_params(sip_msg_t* _msg, str* _user, str* _params)
367 {
368 	return prepend_path(_msg, _user, PATH_PARAM_RECEIVED, _params);
369 }
370 
371 /*! \brief
372  * rr callback
373  */
path_rr_callback(struct sip_msg * _m,str * r_param,void * cb_param)374 void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
375 {
376 	param_hooks_t hooks;
377 	param_t *params;
378 	static char dst_uri_buf[MAX_URI_SIZE];
379 	static str dst_uri;
380 	char *p;
381 	int n;
382 	int nproto;
383 	str sproto;
384 
385 	if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
386 		LM_ERR("failed to parse route parameters\n");
387 		return;
388 	}
389 
390 	if (hooks.contact.received==NULL
391 			|| hooks.contact.received->body.len<=0) {
392 		LM_DBG("no received parameter in route header\n");
393 		free_params(params);
394 		return;
395 	}
396 
397 	/* 24 => sip:...;transport=sctp */
398 	if(hooks.contact.received->body.len + 24 >= MAX_URI_SIZE) {
399 		LM_ERR("received uri is too long\n");
400 		goto done;
401 	}
402 	dst_uri.s = dst_uri_buf;
403 	dst_uri.len = MAX_URI_SIZE;
404 	if(path_received_format==0) {
405 		/* received=sip:...;transport... */
406 		if (unescape_user(&(hooks.contact.received->body), &dst_uri) < 0) {
407 			LM_ERR("unescaping received failed\n");
408 			free_params(params);
409 			return;
410 		}
411 	} else {
412 		/* received=ip~port~proto */
413 		memcpy(dst_uri_buf, "sip:", 4);
414 		memcpy(dst_uri_buf+4, hooks.contact.received->body.s,
415 					hooks.contact.received->body.len);
416 		dst_uri_buf[4+hooks.contact.received->body.len] = '\0';
417 		p = dst_uri_buf + 4;
418 		n = 0;
419 		while(*p!='\0') {
420 			if(*p=='~') {
421 				n++;
422 				if(n==1) {
423 					/* port */
424 					*p = ':';
425 				} else if(n==2) {
426 					/* proto */
427 					*p = ';';
428 					p++;
429 					if(*p=='\0') {
430 						LM_ERR("invalid received format\n");
431 						goto done;
432 					}
433 					nproto = *p - '0';
434 					if (nproto != PROTO_UDP) {
435 						proto_type_to_str(nproto, &sproto);
436 						if (sproto.len == 0) {
437 							LM_ERR("unknown proto in received param\n");
438 							goto done;
439 						}
440 						memcpy(p, "transport=", 10);
441 						p += 10;
442 						memcpy(p, sproto.s, sproto.len);
443 						p += sproto.len;
444 					} else {
445 						/* go back one byte to overwrite ';' */
446 						p--;
447 					}
448 					*p = '\0';
449 					dst_uri.len = p - dst_uri_buf;
450 					break;
451 				} else {
452 					LM_ERR("invalid number of separators (%d)\n", n);
453 					goto done;
454 				}
455 			}
456 			p++;
457 		}
458 	}
459 
460 	LM_DBG("setting dst uri: %.*s\n", dst_uri.len, dst_uri.s);
461 	if (set_dst_uri(_m, &dst_uri) != 0) {
462 		LM_ERR("failed to set dst-uri\n");
463 		free_params(params);
464 		return;
465 	}
466 	/* dst_uri changed, so it makes sense to re-use the current uri
467 	 * for forking */
468 	ruri_mark_new(); /* re-use uri for serial forking */
469 
470 done:
471 	free_params(params);
472 }
473