1 /*
2  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
3  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
4  * Copyright (C) 2019 Aleksandar Yosifov
5  *
6  * The initial version of this code was written by Dragos Vingarzan
7  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
8  * Fruanhofer Institute. It was and still is maintained in a separate
9  * branch of the original SER. We are therefore migrating it to
10  * Kamailio/SR and look forward to maintaining it from here on out.
11  * 2011/2012 Smile Communications, Pty. Ltd.
12  * ported/maintained/improved by
13  * Jason Penton (jason(dot)penton(at)smilecoms.com and
14  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
15  * effort to add full IMS support to Kamailio/SR using a new and
16  * improved architecture
17  *
18  * NB: Alot of this code was originally part of OpenIMSCore,
19  * FhG Fokus.
20  * Copyright (C) 2004-2006 FhG Fokus
21  * Thanks for great work! This is an effort to
22  * break apart the various CSCF functions into logically separate
23  * components. We hope this will drive wider use. We also feel
24  * that in this way the architecture is more complete and thereby easier
25  * to manage in the Kamailio/SR environment
26  *
27  * This file is part of Kamailio, a free SIP server.
28  *
29  * Kamailio is free software; you can redistribute it and/or modify
30  * it under the terms of the GNU General Public License as published by
31  * the Free Software Foundation; either version 2 of the License, or
32  * (at your option) any later version
33  *
34  * Kamailio is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
42  *
43  */
44 
45 
46 #include <stdio.h>
47 #include "../../core/data_lump.h"
48 #include "../../core/ip_addr.h"
49 #include "../../core/ut.h"
50 #include "../../core/sr_module.h"
51 #include "../../core/timer.h"
52 #include "../../core/dprint.h"
53 #include "../../core/error.h"
54 #include "../../core/socket_info.h"
55 #include "../../core/pvar.h"
56 #include "../ims_usrloc_pcscf/usrloc.h"
57 #include "../../core/counters.h"
58 #include "../../modules/sl/sl.h"
59 #include "../../core/mod_fix.h"
60 #include "../../core/cfg/cfg_struct.h"
61 #include "../ims_ipsec_pcscf/cmd.h"
62 
63 /* Bindings to PUA */
64 #include "../pua/pua_bind.h"
65 #include "notify.h"
66 
67 #include "async_reginfo.h"
68 
69 #include "ims_registrar_pcscf_mod.h"
70 #include "save.h"
71 #include "service_routes.h"
72 MODULE_VERSION
73 
74 usrloc_api_t ul;						/**!< Structure containing pointers to usrloc functions*/
75 sl_api_t slb;							/**!< SL API structure */
76 struct tm_binds tmb;					/**!< TM API structure */
77 pua_api_t pua; 							/**!< PUA API structure */
78 ipsec_pcscf_api_t ipsec_pcscf;			/**!< Structure containing pointers to ipsec pcscf functions*/
79 
80 int publish_reginfo = 0;
81 int subscribe_to_reginfo = 0;
82 int subscription_expires = 3600;
83 int ignore_reg_state = 0;
84 /**!< ignore port checks between received port on message and registration received port.
85  * this is useful for example if you register with UDP but possibly send invite over TCP (message too big) */
86 int ignore_contact_rxport_check = 0;
87 
88 time_t time_now;
89 
90 str pcscf_uri = str_init("sip:pcscf.ims.smilecoms.com:4060");
91 str force_icscf_uri = str_init("");
92 
93 unsigned int pending_reg_expires = 30;			/**!< parameter for expiry time of a pending registration before receiving confirmation from SCSCF */
94 
95 int is_registered_fallback2ip = 0;
96 
97 int reginfo_queue_size_threshold = 0;			/**Threshold for size of reginfo queue after which a warning is logged */
98 
99 
100 char* rcv_avp_param = 0;
101 unsigned short rcv_avp_type = 0;
102 int_str rcv_avp_name;
103 
104 // static str orig_prefix = {"sip:orig@",9};
105 
106 /*! \brief Module init & destroy function */
107 static int  mod_init(void);
108 static int  child_init(int);
109 static void mod_destroy(void);
110 static int w_save(struct sip_msg* _m, char* _d, char* _cflags);
111 static int w_save_pending(struct sip_msg* _m, char* _d, char* _cflags);
112 
113 static int w_follows_service_routes(struct sip_msg* _m, char* _d, char* _foo);
114 static int w_force_service_routes(struct sip_msg* _m, char* _d, char* _foo);
115 static int w_is_registered(struct sip_msg* _m, char* _d, char* _foo);
116 static int w_reginfo_handle_notify(struct sip_msg* _m, char* _d, char* _foo);
117 
118 static int w_assert_identity(struct sip_msg* _m, char* _d, char* _preferred_uri);
119 static int w_assert_called_identity(struct sip_msg* _m, char* _d, char* _foo);
120 
121 static int w_unregister(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port);
122 
123 /*! \brief Fixup functions */
124 static int domain_fixup(void** param, int param_no);
125 static int save_fixup2(void** param, int param_no);
126 static int assert_identity_fixup(void ** param, int param_no);
127 
128 /* Pseudo-Variables */
129 static int pv_get_asserted_identity_f(struct sip_msg *, pv_param_t *, pv_value_t *);
130 static int pv_get_registration_contact_f(struct sip_msg *, pv_param_t *, pv_value_t *);
131 static int unregister_fixup(void ** param, int param_no);
132 
133 /**
134  * Update the time.
135  */
pcscf_act_time()136 inline void pcscf_act_time()
137 {
138         time_now=time(0);
139 }
140 
141 /*! \brief
142  * Exported functions
143  */
144 static cmd_export_t cmds[] = {
145 	{"pcscf_save",     		(cmd_function)w_save,                   1,  	save_fixup2,            0,ONREPLY_ROUTE },
146 	{"pcscf_save_pending",          (cmd_function)w_save_pending,       	1,  	save_fixup2,            0,REQUEST_ROUTE },
147 	{"pcscf_follows_service_routes",(cmd_function)w_follows_service_routes, 1,  	save_fixup2,            0,REQUEST_ROUTE },
148 	{"pcscf_force_service_routes",  (cmd_function)w_force_service_routes,   1,  	save_fixup2,            0,REQUEST_ROUTE },
149 	{"pcscf_is_registered",         (cmd_function)w_is_registered,          1,  	save_fixup2,            0,REQUEST_ROUTE|ONREPLY_ROUTE },
150 	{"pcscf_assert_identity",       (cmd_function)w_assert_identity,        2,  	assert_identity_fixup,  0,REQUEST_ROUTE },
151 	{"pcscf_assert_called_identity",(cmd_function)w_assert_called_identity, 1,      assert_identity_fixup,  0,ONREPLY_ROUTE },
152 	{"reginfo_handle_notify",       (cmd_function)w_reginfo_handle_notify,  1,      domain_fixup,           0,REQUEST_ROUTE},
153 	{"pcscf_unregister",		(cmd_function)w_unregister,		4,      unregister_fixup,       0,ANY_ROUTE},
154 	{0, 0, 0, 0, 0, 0}
155 };
156 
157 
158 /*! \brief
159  * Exported parameters
160  */
161 static param_export_t params[] = {
162 	{"pcscf_uri",                   PARAM_STR, &pcscf_uri                           },
163 	{"pending_reg_expires",         INT_PARAM, &pending_reg_expires			},
164 	{"received_avp",                PARAM_STR, &rcv_avp_param       		},
165 	{"is_registered_fallback2ip",	INT_PARAM, &is_registered_fallback2ip           },
166 	{"publish_reginfo",             INT_PARAM, &publish_reginfo                     },
167 	{"subscribe_to_reginfo",        INT_PARAM, &subscribe_to_reginfo                },
168 	{"subscription_expires",        INT_PARAM, &subscription_expires                },
169 	{"ignore_contact_rxport_check", INT_PARAM, &ignore_contact_rxport_check         },
170 	{"ignore_reg_state",		INT_PARAM, &ignore_reg_state			},
171 	{"force_icscf_uri",		PARAM_STR, &force_icscf_uri			},
172 	{"reginfo_queue_size_threshold",	INT_PARAM, &reginfo_queue_size_threshold		},
173 //	{"store_profile_dereg",	INT_PARAM, &store_data_on_dereg},
174 	{0, 0, 0}
175 };
176 
177 
178 
179 static pv_export_t mod_pvs[] = {
180 	{{"pcscf_asserted_identity", (sizeof("pcscf_asserted_identity")-1)}, /* The first identity of the contact. */
181 	PVT_OTHER, pv_get_asserted_identity_f, 0, 0, 0, 0, 0},
182 	{{"pcscf_registration_contact", (sizeof("pcscf_registration_contact")-1)}, /* The contact used during REGISTER */
183 	PVT_OTHER, pv_get_registration_contact_f, 0, 0, 0, 0, 0},
184 	{{0, 0}, 0, 0, 0, 0, 0, 0, 0}
185 };
186 
187 /*! \brief
188  * Module exports structure
189  */
190 struct module_exports exports = {
191 	"ims_registrar_pcscf",
192 	DEFAULT_DLFLAGS, /* dlopen flags */
193 	cmds,        	/* Exported functions */
194 	params,      	/* Exported parameters */
195 	0,           	/* exported RPC methods */
196 	mod_pvs,     	/* exported pseudo-variables */
197 	0,           	/* response handling function */
198 	mod_init,    	/* module initialization function */
199 	child_init,  	/* Per-child init function */
200 	mod_destroy 	/* destroy function */
201 };
202 
fix_parameters()203 int fix_parameters() {
204 	str s;
205 	pv_spec_t avp_spec;
206 
207 	if (rcv_avp_param && *rcv_avp_param) {
208 		s.s = rcv_avp_param; s.len = strlen(s.s);
209 		if (pv_parse_spec(&s, &avp_spec)==0
210 				|| avp_spec.type!=PVT_AVP) {
211 			LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
212 			return -1;
213 		}
214 
215 		if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
216 		{
217 			LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
218 			return -1;
219 		}
220 	} else {
221 		rcv_avp_name.n = 0;
222 		rcv_avp_type = 0;
223 	}
224 
225 	return 1;
226 }
227 
228 /*! \brief
229  * Initialize parent
230  */
mod_init(void)231 static int mod_init(void) {
232 	bind_usrloc_t bind_usrloc;
233 	bind_pua_t bind_pua;
234 	bind_ipsec_pcscf_t bind_ipsec_pcscf;
235 
236 	/*register space for event processor*/
237 	register_procs(1);
238 
239 	if (!fix_parameters()) goto error;
240 
241 	/* bind the SL API */
242 	if (sl_load_api(&slb) != 0) {
243 		LM_ERR("cannot bind to SL API\n");
244 		return -1;
245 	}
246 	LM_DBG("Successfully bound to SL module\n");
247 
248 	/* load the TM API */
249 	if (load_tm_api(&tmb) != 0) {
250 		LM_ERR("can't load TM API\n");
251 		return -1;
252 	}
253 	LM_DBG("Successfully bound to TM module\n");
254 
255 	bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
256 	if (!bind_usrloc) {
257 		LM_ERR("can't bind ims_usrloc_pcscf\n");
258 		return -1;
259 	}
260 
261 	if (bind_usrloc(&ul) < 0) {
262 		return -1;
263 	}
264 	LM_DBG("Successfully bound to PCSCF Usrloc module\n");
265 
266 	bind_ipsec_pcscf = (bind_ipsec_pcscf_t) find_export("bind_ims_ipsec_pcscf", 1, 0);
267 	if (!bind_ipsec_pcscf) {
268 		LM_ERR("can't bind ims_ipsec_pcscf\n");
269 		return -1;
270 	}
271 
272 	if (bind_ipsec_pcscf(&ipsec_pcscf) < 0) {
273 		return -1;
274 	}
275 	LM_INFO("Successfully bound to PCSCF IPSEC module\n");
276 
277 	if(subscribe_to_reginfo == 1){
278 		/* Bind to PUA: */
279 		bind_pua = (bind_pua_t) find_export("bind_pua", 1, 0);
280 		if (!bind_pua) {
281 			LM_ERR("Can't bind pua\n");
282 			return -1;
283 		}
284 		if (bind_pua(&pua) < 0) {
285 			LM_ERR("Can't bind pua\n");
286 			return -1;
287 		}
288 		/* Check for Publish/Subscribe methods */
289 		if (pua.send_publish == NULL) {
290 			LM_ERR("Could not import send_publish\n");
291 			return -1;
292 		}
293 		if (pua.send_subscribe == NULL) {
294 			LM_ERR("Could not import send_subscribe\n");
295 			return -1;
296 		}
297 		if (pua.get_subs_list == NULL) {
298 			LM_ERR("Could not import get_subs_list\n");
299 			return -1;
300 		}
301 		LM_DBG("Successfully bound to PUA module\n");
302 
303 		/*init cdb cb event list*/
304 		if (!init_reginfo_event_list()) {
305 		    LM_ERR("unable to initialise reginfo_event_list\n");
306 		    return -1;
307 		}
308 		LM_DBG("Successfully initialised reginfo_event_list\n");
309 	}
310 
311 	return 0;
312 
313 error:
314 	return -1;
315 }
316 
mod_destroy(void)317 static void mod_destroy(void)
318 {
319 
320 }
321 
child_init(int rank)322 static int child_init(int rank)
323 {
324 
325 	LM_DBG("Initialization of module in child [%d] \n", rank);
326 	if ((subscribe_to_reginfo == 1) && (rank == PROC_MAIN)) {
327 		LM_DBG("Creating RegInfo Event Processor process\n");
328 	    int pid = fork_process(PROC_SIPINIT, "RegInfo Event Processor", 1);
329 	    if (pid < 0)
330 			return -1; //error
331 	    if (pid == 0) {
332 			if (cfg_child_init())
333 				return -1; //error
334 			reginfo_event_process();
335 	    }
336 	}
337 
338 	if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
339 		return 0;
340 	if (rank == 1) {
341 		/* init stats */
342 		//TODO if parameters are modified via cfg framework do i change them?
343 		//update_stat( max_expires_stat, default_registrar_cfg.max_expires ); update_stat( max_contacts_stat, default_registrar_cfg.max_contacts ); update_stat( default_expire_stat, default_registrar_cfg.default_expires );
344 	}
345 
346 	/* don't do anything for main process and TCP manager process */
347 	if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
348 		return 0;
349 
350 	return 0;
351 }
352 
353 /* fixups */
domain_fixup(void ** param,int param_no)354 static int domain_fixup(void** param, int param_no)
355 {
356 	udomain_t* d;
357 
358 	if (param_no == 1) {
359 		if (ul.register_udomain((char*)*param, &d) < 0) {
360 			LM_ERR("failed to register domain\n");
361 			return E_UNSPEC;
362 		}
363 		*param = (void*)d;
364 	}
365 	return 0;
366 }
367 
368 /*! \brief
369  * Fixup for "save" function - both domain and flags
370  */
save_fixup2(void ** param,int param_no)371 static int save_fixup2(void** param, int param_no)
372 {
373 	if (param_no == 1) {
374 		return domain_fixup(param,param_no);
375 	}
376 	return 0;
377 }
378 
379 /*! \brief
380  * Fixup for "assert_identity" function - both domain and URI to be asserted
381  */
assert_identity_fixup(void ** param,int param_no)382 static int assert_identity_fixup(void ** param, int param_no) {
383 	if (param_no == 1) {
384 		return domain_fixup(param,param_no);
385 	}
386 	if (param_no == 2) {
387 		pv_elem_t *model=NULL;
388 		str s;
389 
390 		/* convert to str */
391 		s.s = (char*)*param;
392 		s.len = strlen(s.s);
393 
394 		model = NULL;
395 		if(s.len==0) {
396 			LM_ERR("no param!\n");
397 			return E_CFG;
398 		}
399 		if(pv_parse_format(&s, &model)<0 || model==NULL) {
400 			LM_ERR("wrong format [%s]!\n", s.s);
401 			return E_CFG;
402 		}
403 		*param = (void*)model;
404 		return 0;
405 	}
406 	return E_CFG;
407 }
408 
409 /*! \brief
410  * Wrapper to save(location)
411  */
w_save(struct sip_msg * _m,char * _d,char * _cflags)412 static int w_save(struct sip_msg* _m, char* _d, char* _cflags)
413 {
414 	return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags));
415 }
416 
w_save_pending(struct sip_msg * _m,char * _d,char * _cflags)417 static int w_save_pending(struct sip_msg* _m, char* _d, char* _cflags)
418 {
419 	return save_pending(_m, (udomain_t*)_d);
420 }
421 
w_follows_service_routes(struct sip_msg * _m,char * _d,char * _foo)422 static int w_follows_service_routes(struct sip_msg* _m, char* _d, char* _foo)
423 {
424 	return check_service_routes(_m, (udomain_t*)_d);
425 }
426 
w_force_service_routes(struct sip_msg * _m,char * _d,char * _foo)427 static int w_force_service_routes(struct sip_msg* _m, char* _d, char* _foo)
428 {
429 	return force_service_routes(_m, (udomain_t*)_d);
430 }
431 
w_is_registered(struct sip_msg * _m,char * _d,char * _foo)432 static int w_is_registered(struct sip_msg* _m, char* _d, char* _foo)
433 {
434 	return is_registered(_m, (udomain_t*)_d);
435 }
436 
w_reginfo_handle_notify(struct sip_msg * _m,char * _d,char * _foo)437 static int w_reginfo_handle_notify(struct sip_msg* _m, char* _d, char* _foo)
438 {
439        return reginfo_handle_notify(_m, _d, _foo);
440 }
441 
w_assert_identity(struct sip_msg * _m,char * _d,char * _preferred_uri)442 static int w_assert_identity(struct sip_msg* _m, char* _d, char* _preferred_uri) {
443 	pv_elem_t *model;
444 	str identity;
445 
446 	if(_preferred_uri == NULL) {
447 		LM_ERR("error - bad parameters\n");
448 		return -1;
449 	}
450 
451 	model = (pv_elem_t*)_preferred_uri;
452 	if (pv_printf_s(_m, model, &identity)<0) {
453 		LM_ERR("error - cannot print the format\n");
454 		return -1;
455 	}
456 
457 	return assert_identity( _m, (udomain_t*)_d, identity);
458 }
459 
w_assert_called_identity(struct sip_msg * _m,char * _d,char * _foo)460 static int w_assert_called_identity(struct sip_msg* _m, char* _d, char* _foo) {
461 	return assert_called_identity( _m, (udomain_t*)_d);
462 }
463 
464 /*
465  * Get the asserted Identity for the current user
466  */
467 static int
pv_get_asserted_identity_f(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)468 pv_get_asserted_identity_f(struct sip_msg *msg, pv_param_t *param,
469 		  pv_value_t *res)
470 {
471 	str * ret_val = get_asserted_identity(msg);
472 	if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
473 	else return -1;
474 }
475 
476 
477 /*
478  * Get the asserted Identity for the current user
479  */
480 static int
pv_get_registration_contact_f(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)481 pv_get_registration_contact_f(struct sip_msg *msg, pv_param_t *param,
482 		  pv_value_t *res)
483 {
484 	str * ret_val = get_registration_contact(msg);
485 	if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
486 	else return -1;
487 }
488 
489 
490 /*! \brief
491  * Fixup for "assert_identity" function - both domain and URI to be asserted
492  */
unregister_fixup(void ** param,int param_no)493 static int unregister_fixup(void ** param, int param_no) {
494 	if (param_no == 1) {
495 		return domain_fixup(param,param_no);
496 	} else {
497 		pv_elem_t *model=NULL;
498 		str s;
499 
500 		/* convert to str */
501 		s.s = (char*)*param;
502 		s.len = strlen(s.s);
503 
504 		model = NULL;
505 		if(s.len==0) {
506 			LM_ERR("no param!\n");
507 			return E_CFG;
508 		}
509 		if(pv_parse_format(&s, &model)<0 || model==NULL) {
510 			LM_ERR("wrong format [%s]!\n", s.s);
511 			return E_CFG;
512 		}
513 		*param = (void*)model;
514 		return 0;
515 	}
516 	return E_CFG;
517 }
518 
519 
w_unregister(struct sip_msg * _m,char * _d,char * _aor,char * _received_host,char * _received_port)520 static int w_unregister(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port) {
521 	pv_elem_t *model;
522 	str aor;
523 	str received_host;
524 	str received_port;
525 	int port = 0;
526 
527 	if ((_aor == NULL) || (_received_host == NULL) || (_received_port == NULL)) {
528 		LM_ERR("error - bad parameters\n");
529 		return -1;
530 	}
531 
532 	model = (pv_elem_t*)_aor;
533 	if (pv_printf_s(_m, model, &aor)<0) {
534 		LM_ERR("error - cannot print the format\n");
535 		return -1;
536 	}
537 	LM_DBG("URI: %.*s\n", aor.len, aor.s);
538 
539 	model = (pv_elem_t*)_received_host;
540 	if (pv_printf_s(_m, model, &received_host)<0) {
541 		LM_ERR("error - cannot print the format\n");
542 		return -1;
543 	}
544 	LM_DBG("Received-Host: %.*s\n", received_host.len, received_host.s);
545 
546 	model = (pv_elem_t*)_received_port;
547 	if (pv_printf_s(_m, model, &received_port)<0) {
548 		LM_ERR("error - cannot print the format\n");
549 		return -1;
550 	}
551 	LM_DBG("Received-Port: %.*s\n", received_port.len, received_port.s);
552 	if (str2sint(&received_port, &port) != 0) {
553 		LM_ERR("error - cannot convert %.*s to an int!\n", received_port.len, received_port.s);
554 		return -1;
555 	}
556 
557 	return pcscf_unregister((udomain_t*)_d, &aor, &received_host, port);
558 }
559 
560