1 /**
2 * Functions to force or check the service-routes
3 *
4 * Copyright (c) 2013 Carsten Bock, ng-voice GmbH
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 #include "service_routes.h"
24 #include "ims_registrar_pcscf_mod.h"
25 #include "save.h"
26 #include "../../core/parser/parse_via.h"
27 #include "../../core/parser/msg_parser.h"
28 #include "../../core/data_lump.h"
29 #include "../../lib/ims/ims_getters.h"
30
31 #define STR_APPEND(dst,src)\
32 {memcpy((dst).s+(dst).len,(src).s,(src).len);\
33 (dst).len = (dst).len + (src).len;}
34
35 // ID of current message
36 static unsigned int current_msg_id = 0;
37 // Pointer to current contact_t
38 static pcontact_t * c = NULL;
39
40 extern usrloc_api_t ul;
41 extern int ignore_contact_rxport_check;
42 static str * asserted_identity;
43 static str * registration_contact;
44
45 /*!
46 * \brief Parse the message and find first occurrence of Route header field.
47 * \param _m SIP message
48 * \return -1 or -2 on a parser error, 0 if there is a Route HF and 1 if there is no Route HF
49 */
find_first_route(struct sip_msg * _m)50 static inline int find_first_route(struct sip_msg* _m)
51 {
52 if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) {
53 LM_ERR("failed to parse headers\n");
54 return -1;
55 } else {
56 if (_m->route) {
57 if (parse_rr(_m->route) < 0) {
58 LM_ERR("failed to parse Route HF\n");
59 return -2;
60 }
61 return 0;
62 } else {
63 LM_DBG("No Route headers found\n");
64 return 1;
65 }
66 }
67 }
68
69 /*!
70 * \brief Find and parse next Route header field
71 * \param _m SIP message
72 * \param _hdr SIP header
73 * \return negative on failure, 0 if the Route header was already parsed, 1 if no next
74 * Route header could be found
75 */
find_next_route(struct sip_msg * _m,struct hdr_field ** _hdr)76 static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr)
77 {
78 struct hdr_field* ptr;
79
80 ptr = (*_hdr)->next;
81
82 /* Try to find already parsed Route headers */
83 while(ptr) {
84 if (ptr->type == HDR_ROUTE_T) goto found;
85 ptr = ptr->next;
86 }
87
88 /* There are no already parsed Route headers, try to find next
89 * occurrence of Route header
90 */
91 if (parse_headers(_m, HDR_ROUTE_F, 1) == -1) {
92 LM_ERR("failed to parse headers\n");
93 return -1;
94 }
95
96 if ((_m->last_header->type!=HDR_ROUTE_T) || (_m->last_header==*_hdr)) {
97 LM_DBG("No next Route HF found\n");
98 return 1;
99 }
100
101 ptr = _m->last_header;
102
103 found:
104 if (parse_rr(ptr) < 0) {
105 LM_ERR("failed to parse Route body\n");
106 return -2;
107 }
108
109 *_hdr = ptr;
110 return 0;
111 }
112
checkcontact(struct sip_msg * _m,pcontact_t * c)113 int checkcontact(struct sip_msg* _m, pcontact_t * c) {
114 int security_server_port = -1;
115 str received_host = {0, 0};
116 char srcip[50];
117
118 LM_DBG("Port %d (search %d), Proto %d (search %d), reg_state %s (search %s)\n",
119 c->received_port, _m->rcv.src_port, c->received_proto, _m->rcv.proto,
120 reg_state_to_string(c->reg_state), reg_state_to_string(PCONTACT_REGISTERED)
121 );
122
123 if (c->security) {
124 switch (c->security->type) {
125 case SECURITY_IPSEC:
126 security_server_port = c->security->data.ipsec->port_uc;
127 break;
128 case SECURITY_TLS:
129 case SECURITY_NONE:
130 break;
131 }
132 } else if (c->security_temp) {
133 switch (c->security_temp->type) {
134 case SECURITY_IPSEC:
135 security_server_port = c->security_temp->data.ipsec->port_uc;
136 break;
137 case SECURITY_TLS:
138 case SECURITY_NONE:
139 break;
140 }
141 }
142
143 if ((ignore_reg_state || (c->reg_state == PCONTACT_REGISTERED))
144 && (ignore_contact_rxport_check || (c->received_port == _m->rcv.src_port) || (security_server_port == _m->rcv.src_port))
145 && (ignore_contact_rxport_check||(c->received_proto == _m->rcv.proto))) {
146
147 received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
148 received_host.s = srcip;
149 LM_DBG("Received host len %d (search %d)\n", c->received_host.len, received_host.len);
150 // Then check the length:
151 if (c->received_host.len == received_host.len) {
152 LM_DBG("Received host %.*s (search %.*s)\n",
153 c->received_host.len, c->received_host.s,
154 received_host.len, received_host.s);
155
156 // Finally really compare the "received_host"
157 if (!memcmp(c->received_host.s, received_host.s, received_host.len)) {
158 LM_DBG("check contact passed\n");
159 return 0;
160 }
161 }
162 }
163 LM_DBG("check contact failed\n");
164 return 1;
165 }
166
167 /**
168 * get PContact-Structure for message
169 * (search only once per Request)
170 */
171
getContactP(struct sip_msg * _m,udomain_t * _d,enum pcontact_reg_states reg_state,char service_routes[][MAXROUTESIZE],int num_service_routes)172 pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state, char service_routes[][MAXROUTESIZE], int num_service_routes) {
173 ppublic_t * p;
174 contact_body_t *b = 0;
175 contact_t *ct;
176 pcontact_info_t search_ci;
177 str received_host = {0, 0};
178 char srcip[50];
179 struct via_body *vb;
180 unsigned short port, proto;
181 str host;
182 sip_uri_t contact_uri;
183 int mustRetryViaSearch = 0;
184 int mustRetryReceivedSearch = 0;
185
186 LM_DBG("number of service routes to look for is %d\n", num_service_routes);
187 b = cscf_parse_contacts(_m);
188
189 if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) {
190 mustRetryViaSearch = 1;
191 mustRetryReceivedSearch = 1;
192 LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n");
193 ct = b->contacts;
194 host = ct->uri;
195 if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) {
196 LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s);
197 return NULL;
198 }
199 host = contact_uri.host;
200 port = contact_uri.port_no ? contact_uri.port_no : 5060;
201 proto = contact_uri.proto;
202 if (proto == 0) {
203 LM_DBG("Contact protocol not specified - using received\n");
204 proto = _m->rcv.proto;
205 }
206 } else {
207 if (_m->first_line.type == SIP_REPLY)
208 LM_DBG("This is a reply but we are forced to use the via header\n");
209 else
210 LM_DBG("This is a request - using first via to find contact\n");
211
212 vb = cscf_get_ue_via(_m);
213 host = vb->host;
214 port = vb->port ? vb->port : 5060;
215 proto = vb->proto;
216 }
217
218 LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port);
219
220 received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip));
221 received_host.s = srcip;
222
223 // if (_m->id != current_msg_id) {
224 current_msg_id = _m->id;
225 c = NULL;
226 //search_ci.reg_state = PCONTACT_REGISTERED; //we can do this because this function is always called expecting a REGISTERED contact
227 memset(&search_ci, 0, sizeof(struct pcontact_info));
228 search_ci.reg_state = reg_state;
229 search_ci.received_host.s = received_host.s;
230 search_ci.received_host.len = received_host.len;
231 search_ci.received_port = _m->rcv.src_port;
232 search_ci.received_proto = _m->rcv.proto;
233 search_ci.searchflag = SEARCH_RECEIVED;
234 search_ci.num_service_routes = 0;
235 if (is_registered_fallback2ip == 1) {
236 search_ci.searchflag = SEARCH_NORMAL;
237 }
238 search_ci.via_host = host;
239 search_ci.via_port = port;
240 search_ci.via_prot = proto;
241 search_ci.aor.s = 0;
242 search_ci.aor.len = 0;
243
244 int size = num_service_routes==0?1:num_service_routes;
245 str s_service_routes[size];
246 int i;
247 for (i=0;i<num_service_routes;i++) {
248 s_service_routes[i].s = service_routes[i];
249 s_service_routes[i].len = strlen(service_routes[i]);
250 LM_DBG("Setting service routes str for pos %d to %.*s", i, s_service_routes[i].len, s_service_routes[i].s);
251 }
252 if (num_service_routes > 0) {
253 LM_DBG("asked to search for specific service routes...\n");
254 search_ci.service_routes = s_service_routes;
255 search_ci.num_service_routes = num_service_routes;
256 search_ci.extra_search_criteria = SEARCH_SERVICE_ROUTES;
257 }
258
259 // b = cscf_parse_contacts(_m);
260 tryagain:
261 if (b && b->contacts) {
262 for (ct = b->contacts; ct; ct = ct->next) {
263 search_ci.aor = ct->uri;
264 if (ul.get_pcontact(_d, &search_ci, &c) == 0) {
265 if (checkcontact(_m, c) != 0) {
266 c = NULL;
267 } else {
268 break;
269 }
270 }
271 }
272 } else {
273 LM_WARN("No contact-header found...\n");
274 }
275
276 if ((c == NULL) && (is_registered_fallback2ip == 1)) {
277 LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n");
278 // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
279 // received_host.s = srcip;
280 search_ci.searchflag = SEARCH_RECEIVED;
281 if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
282 LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
283 } else {
284 if (checkcontact(_m, c) != 0) {
285 c = NULL;
286 }
287 }
288 }
289
290 if ((c == NULL) && (is_registered_fallback2ip == 2)) {
291 LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n");
292 search_ci.searchflag = SEARCH_NORMAL;
293 if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
294 } else {
295 if (checkcontact(_m, c) != 0) {
296 c = NULL;
297 }
298 }
299 }
300
301 asserted_identity = NULL;
302 registration_contact = NULL;
303 if (c) {
304 LM_DBG("Trying to set asserted identity field");
305 registration_contact = &c->contact_user;
306 p = c->head;
307 while (p) {
308 LM_DBG("Checking through contact users");
309 if (p->is_default == 1) {
310 LM_DBG("Found default contact user so setting asserted identity");
311 asserted_identity = &p->public_identity;
312 }
313 p = p->next;
314 }
315 }
316 if (asserted_identity != NULL && asserted_identity->len > 0) {
317 LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s);
318 } else {
319 LM_DBG("Asserted identity not set");
320 }
321
322
323 // LM_DBG("pcontact flag is [%d]\n", c->flags);
324 // if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) {
325 // LM_DBG("we have a contact that was read fresh from the DB....\n");
326 // }
327 if (!c && mustRetryViaSearch) {
328 LM_DBG("This is a reply so we will search using the last via once more...\n");
329 vb = cscf_get_ue_via(_m);
330 search_ci.via_host = vb->host;
331 search_ci.via_port = vb->port ? vb->port : 5060;
332 search_ci.via_prot = vb->proto;
333 mustRetryViaSearch = 0;
334 goto tryagain;
335 }
336
337 if (!c && mustRetryReceivedSearch) {
338 LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n");
339 search_ci.via_host = received_host;
340 search_ci.via_port = _m->rcv.src_port;
341 search_ci.via_prot = _m->rcv.proto;
342 mustRetryReceivedSearch = 0;
343 goto tryagain;
344 }
345
346 return c;
347 }
348
349 /**
350 * Check, if a user-agent follows the indicated service-routes
351 */
check_service_routes(struct sip_msg * _m,udomain_t * _d)352 int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
353 struct sip_uri uri;
354 int i;
355 struct hdr_field *hdr;
356 rr_t *r;
357 char routes[MAXROUTES][MAXROUTESIZE];
358 unsigned int num_routes = 0;
359
360 struct via_body * vb;
361 unsigned short port;
362 unsigned short proto;
363 /* Contact not found => not following service-routes */
364 // if (c == NULL) return -1;
365
366 /* Search for the first Route-Header: */
367 if (find_first_route(_m) < 0) return -1;
368
369 // LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);
370
371 vb = cscf_get_ue_via(_m);
372 port = vb->port?vb->port:5060;
373 proto = vb->proto;
374
375 /* Lock this record while working with the data: */
376 ul.lock_udomain(_d, &vb->host, port, proto);
377
378 if (_m->route) {
379 hdr = _m->route;
380 r = (rr_t*)hdr->parsed;
381 //get rid of ourselves from route header
382 if (r) {
383 LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
384 while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
385 && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
386 LM_DBG("Self\n");
387 /* Check for more headers and fail, if it was the last one
388 Check, if service-routes are indicated.
389 If yes, request is not following service-routes */
390 if (find_next_route(_m, &hdr) != 0)
391 r = NULL;
392 else
393 r = (rr_t*)hdr->parsed;
394
395 LM_DBG("hdr is %p\n", hdr);
396 LM_DBG("r is %p\n", r);
397 if (r)
398 LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
399 }
400
401 int i = 0;
402 while (r) {
403 memset(routes[i],0,MAXROUTESIZE);
404 memcpy(routes[i], r->nameaddr.uri.s, r->nameaddr.uri.len);
405
406 if (find_next_route(_m, &hdr) != 0)
407 r = NULL;
408 else
409 r = (rr_t*)hdr->parsed;
410
411 i += 1;
412 num_routes += 1;
413 }
414
415 LM_DBG("num_routes is %d\n", num_routes);
416 if (num_routes == 0) {
417 LM_DBG("Request doesn't have any route headers (except those pointing here), to check service-route...ignoring\n");
418 goto error;
419 }
420 for (i=0; i<num_routes; i++) {
421 LM_DBG("route %d for checking is %s\n", i, routes[i]);
422 }
423 pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, routes, num_routes);
424 if (!c) {
425 LM_DBG("no contact found in usrloc when checking for service route\n");
426 goto error;
427 }
428
429 LM_DBG("we have a contact which satisifes the routes...\n");
430 ul.unlock_udomain(_d, &vb->host, port, proto);
431 return 1;
432 }
433 } else {
434 LM_DBG("Request doesn't have any route headers to check service-route...ignoring\n");
435 goto error;
436 }
437
438 pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, 0, 0);
439 if (!c) {
440 LM_DBG("no contact found in usrloc when checking for service route\n");
441 goto error;
442 }
443
444 /* Check the route-set: */
445 if (_m->route) {
446 hdr = _m->route;
447 LM_DBG("hdr is %p\n", hdr);
448 /* Check, if the first host is ourself: */
449 r = (rr_t*)hdr->parsed;
450 if (r) {
451 LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
452 /* Skip first headers containing myself: */
453 while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
454 && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
455 LM_DBG("Self\n");
456 /* Check for more headers and fail, if it was the last one
457 Check, if service-routes are indicated.
458 If yes, request is not following service-routes */
459 if (find_next_route(_m, &hdr) != 0) r = NULL;
460 else r = (rr_t*)hdr->parsed;
461
462 if (!r && (c->num_service_routes > 0)) {
463 LM_DBG("Not enough route-headers in Message\n");
464 goto error;
465 }
466 LM_DBG("hdr is %p\n", hdr);
467 LM_DBG("r is %p\n", r);
468 if (r)
469 LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
470 }
471 LM_DBG("We have %d service-routes\n", c->num_service_routes);
472 /* Then check the following headers: */
473 for (i=0; i< c->num_service_routes; i++) {
474 LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);
475
476 /* No more Route-Headers? Not following service-routes */
477 if (!r) {
478 LM_DBG("No more route headers in message.\n");
479 goto error;
480 }
481
482 LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
483
484 /* Check length: */
485 if (r->nameaddr.uri.len != c->service_routes[i].len) {
486 LM_DBG("Length does not match.\n");
487 goto error;
488 }
489 /* Check contents: */
490 if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) {
491 LM_DBG("String comparison failed.\n");
492 goto error;
493 }
494 if (find_next_route(_m, &hdr) != 0) r = NULL;
495 else r = (rr_t*)hdr->parsed;
496 }
497
498 /* Check, if it was the last route-header in the message: */
499 if (r) {
500 LM_DBG("Too many route headers in message.\n");
501 goto error;
502 }
503 } else {
504 LM_WARN("Strange: Route-Header is present, but not parsed?!?");
505 if (c->num_service_routes > 0) goto error;
506 }
507 } else {
508 LM_DBG("No route header in Message.\n");
509 /* No route-header? Check, if service-routes are indicated.
510 If yes, request is not following service-routes */
511 if (c->num_service_routes > 0) goto error;
512 }
513 /* Unlock domain */
514 ul.unlock_udomain(_d, &vb->host, port, proto);
515 return 1;
516 error:
517 /* Unlock domain */
518 ul.unlock_udomain(_d, &vb->host, port, proto);
519 return -1;
520 }
521
522 static str route_start={"Route: <",8};
523 static str route_sep={">, <",4};
524 static str route_end={">\r\n",3};
525
526 /**
527 * Force Service routes (upon request)
528 */
force_service_routes(struct sip_msg * _m,udomain_t * _d)529 int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
530 struct hdr_field *it;
531 int i;
532 str new_route_header;
533 struct lump* lmp = NULL;
534 char * buf;
535 pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED,0 ,0);
536 // char srcip[20];
537 // str received_host;
538 struct via_body* vb;
539 unsigned short port;
540 unsigned short proto;
541
542 // Contact not found => not following service-routes
543 if (c == NULL) return -1;
544
545 /* we need to be sure we have seen all HFs */
546 parse_headers(_m, HDR_EOH_F, 0);
547
548 vb = cscf_get_ue_via(_m);
549 port = vb->port?vb->port:5060;
550 proto = vb->proto;
551
552 /* Save current buffer */
553 buf = _m->buf;
554
555 // Delete old Route headers:
556 if (_m->route) {
557 for (it = _m->route; it; it = it->next) {
558 if (it->type == HDR_ROUTE_T) {
559 if ((lmp = del_lump(_m, it->name.s - buf, it->len, HDR_ROUTE_T)) == 0) {
560 LM_ERR("del_lump failed \n");
561 return -1;
562 }
563 }
564 }
565 }
566
567 /* Reset dst_uri if previously set either by loose route or manually */
568 if (_m->dst_uri.s && _m->dst_uri.len) {
569 pkg_free(_m->dst_uri.s);
570 _m->dst_uri.s = NULL;
571 _m->dst_uri.len = 0;
572 }
573
574 // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
575 // received_host.s = srcip;
576
577 /* Lock this record while working with the data: */
578 ul.lock_udomain(_d, &vb->host, port, proto);
579
580 if (c->num_service_routes > 0) {
581 /* Create anchor for new Route-Header: */
582 lmp = anchor_lump(_m, _m->headers->name.s - buf,0,0);
583 if (lmp == 0) {
584 LM_ERR("Failed to get anchor lump\n");
585 goto error;
586 }
587 /* Calculate the length: */
588 new_route_header.len = route_start.len +
589 route_end.len + (c->num_service_routes-1) * route_sep.len;
590
591 for(i=0; i< c->num_service_routes; i++)
592 new_route_header.len+=c->service_routes[i].len;
593 /* Allocate the memory for this new header: */
594 new_route_header.s = pkg_malloc(new_route_header.len);
595 if (!new_route_header.s) {
596 LM_ERR("Error allocating %d bytes\n", new_route_header.len);
597 goto error;
598 }
599
600 /* Construct new header */
601 new_route_header.len = 0;
602 STR_APPEND(new_route_header, route_start);
603 for(i=0; i < c->num_service_routes; i++) {
604 if (i) STR_APPEND(new_route_header, route_sep);
605 STR_APPEND(new_route_header, c->service_routes[i]);
606 }
607 STR_APPEND(new_route_header, route_end);
608
609 LM_DBG("Setting route header to <%.*s> \n", new_route_header.len, new_route_header.s);
610
611 if ((lmp = insert_new_lump_after(lmp, new_route_header.s, new_route_header.len, HDR_ROUTE_T)) == 0) {
612 LM_ERR("Error inserting new route set\n");
613 pkg_free(new_route_header.s);
614 goto error;
615 }
616
617 LM_DBG("Setting dst_uri to <%.*s> \n", c->service_routes[0].len,
618 c->service_routes[0].s);
619
620 if (set_dst_uri(_m, &c->service_routes[0]) !=0 ) {
621 LM_ERR("Error setting new dst uri\n");
622 goto error;
623 }
624 }
625 /* Unlock domain */
626 ul.unlock_udomain(_d, &vb->host, port, proto);
627 return 1;
628 error:
629 /* Unlock domain */
630 ul.unlock_udomain(_d, &vb->host, port, proto);
631 return -1;
632
633 return 1;
634 }
635
636 /**
637 * Check, if source is registered.
638 */
is_registered(struct sip_msg * _m,udomain_t * _d)639 int is_registered(struct sip_msg* _m, udomain_t* _d) {
640 if (getContactP(_m, _d, PCONTACT_REGISTERED, 0 ,0) != NULL) return 1;
641 return -1;
642 }
643
644 /**
645 * Get the current asserted identity for the user
646 */
get_asserted_identity(struct sip_msg * _m)647 str * get_asserted_identity(struct sip_msg* _m) {
648 if (_m->id != current_msg_id) {
649 LM_ERR("Unable to get asserted identity: Please call is_registered first!\n");
650 return NULL;
651 } else return asserted_identity;
652 }
653
654
655 /**
656 * Get the contact used during registration of this user
657 */
get_registration_contact(struct sip_msg * _m)658 str * get_registration_contact(struct sip_msg* _m) {
659 if (_m->id != current_msg_id) {
660 LM_ERR("Unable to get contact used during registration: Please call is_registered first!\n");
661 return NULL;
662 } else return registration_contact;
663 }
664
665
666 /**
667 * checked if passed identity is an asserted identity
668 */
assert_identity(struct sip_msg * _m,udomain_t * _d,str identity)669 int assert_identity(struct sip_msg* _m, udomain_t* _d, str identity) {
670 // Public identities of this contact
671 struct ppublic * p;
672 //remove <> braces if there are
673 if(identity.s[0]=='<' && identity.s[identity.len-1]=='>') {
674 identity.s++;
675 identity.len -= 2;
676 }
677 LM_DBG("Identity to assert: %.*s\n", identity.len, identity.s);
678
679 if (getContactP(_m, _d, PCONTACT_REGISTERED|PCONTACT_REG_PENDING_AAR|PCONTACT_REG_PENDING, 0, 0) != NULL) {
680 for (p = c->head; p; p = p->next) {
681 LM_DBG("Public identity: %.*s\n", p->public_identity.len, p->public_identity.s);
682 /* Check length: */
683 if (identity.len == p->public_identity.len) {
684 /* Check contents: */
685 if (strncasecmp(identity.s, p->public_identity.s, identity.len) == 0) {
686 LM_DBG("Match!\n");
687 return 1;
688 }
689 } else LM_DBG("Length does not match.\n");
690 }
691 }
692 LM_INFO("Contact not found based on Contact, trying IP/Port/Proto\n");
693 str received_host = {0, 0};
694 char srcip[50];
695
696 received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
697 received_host.s = srcip;
698 if (ul.assert_identity(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &identity) == 0)
699 return -1;
700 else
701 return 1;
702 }
703
704
705 /**
706 * Add proper asserted identities based on registration
707 */
708
709 static str p_asserted_identity_s={"P-Asserted-Identity: ",21};
710 static str p_asserted_identity_m={"<",1};
711 static str p_asserted_identity_e={">\r\n",3};
712
assert_called_identity(struct sip_msg * _m,udomain_t * _d)713 int assert_called_identity(struct sip_msg* _m, udomain_t* _d) {
714
715 int ret=CSCF_RETURN_FALSE;
716 str called_party_id={0,0},x={0,0};
717 struct sip_msg* req;
718 struct hdr_field *h=0;
719
720 //get request from reply
721 req = get_request_from_reply(_m);
722 if (!req) {
723 LM_ERR("Unable to get request from reply for REGISTER. No transaction\n");
724 goto error;
725 }
726
727 called_party_id = cscf_get_public_identity_from_called_party_id(req, &h);
728
729
730 if (!called_party_id.len){
731 goto error;
732 }else{
733 LM_DBG("Called Party ID from request: %.*s\n", called_party_id.len, called_party_id.s);
734 x.len = p_asserted_identity_s.len+p_asserted_identity_m.len+called_party_id.len+p_asserted_identity_e.len;
735 x.s = pkg_malloc(x.len);
736 if (!x.s){
737 LM_ERR("P_assert_called_identity: Error allocating %d bytes\n", x.len);
738 x.len=0;
739 goto error;
740 }
741 x.len=0;
742 STR_APPEND(x,p_asserted_identity_s);
743 STR_APPEND(x,p_asserted_identity_m);
744 STR_APPEND(x,called_party_id);
745 STR_APPEND(x,p_asserted_identity_e);
746
747 if (cscf_add_header(_m,&x,HDR_OTHER_T))
748 ret = CSCF_RETURN_TRUE;
749 else
750 goto error;
751 }
752
753 return ret;
754
755 error:
756 ret=CSCF_RETURN_FALSE;
757 return ret;
758 }
759
pcscf_unregister(udomain_t * _d,str * uri,str * received_host,int received_port)760 int pcscf_unregister(udomain_t* _d, str * uri, str * received_host, int received_port) {
761 int result = -1;
762 struct pcontact * pcontact;
763 struct pcontact_info ci;
764 memset(&ci, 0, sizeof (struct pcontact_info));
765
766 pcontact_info_t search_ci;
767 memset(&ci, 0, sizeof(struct pcontact_info));
768
769 sip_uri_t contact_uri;
770 if (parse_uri(uri->s, uri->len, &contact_uri) != 0) {
771 LM_WARN("Failed to parse aor [%.*s]\n", uri->len, uri->s);
772 return -1;
773 }
774
775 search_ci.received_host.s = received_host->s;
776 search_ci.received_host.len = received_host->len;
777 search_ci.received_port = received_port;
778 search_ci.received_proto = contact_uri.proto? contact_uri.proto : PROTO_UDP;
779 search_ci.searchflag = SEARCH_RECEIVED;
780 search_ci.via_host.s = received_host->s;
781 search_ci.via_host.len = received_host->len;
782 search_ci.via_port = received_port;
783 search_ci.via_prot = search_ci.received_proto;
784 search_ci.aor.s = uri->s;
785 search_ci.aor.len = uri->len;
786 search_ci.reg_state = PCONTACT_ANY;
787
788 if (ul.get_pcontact(_d, &search_ci, &pcontact) == 0) {
789 /* Lock this record while working with the data: */
790 ul.lock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto);
791
792 LM_DBG("Updating contact [%.*s]: setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
793
794 ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
795 ci.num_service_routes = 0;
796 if (ul.update_pcontact(_d, &ci, pcontact) == 0) result = 1;
797
798 /* Unlock domain */
799 ul.unlock_udomain(_d, &pcontact->via_host, pcontact->via_port, pcontact->via_proto);
800 }
801 return result;
802 }
803
804