1 /*
2 * $Id$
3 *
4 * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
5 * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
6 *
7 * The initial version of this code was written by Dragos Vingarzan
8 * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
9 * Fruanhofer Institute. It was and still is maintained in a separate
10 * branch of the original SER. We are therefore migrating it to
11 * Kamailio/SR and look forward to maintaining it from here on out.
12 * 2011/2012 Smile Communications, Pty. Ltd.
13 * ported/maintained/improved by
14 * Jason Penton (jason(dot)penton(at)smilecoms.com and
15 * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
16 * effort to add full IMS support to Kamailio/SR using a new and
17 * improved architecture
18 *
19 * NB: Alot of this code was originally part of OpenIMSCore,
20 * FhG Fokus.
21 * Copyright (C) 2004-2006 FhG Fokus
22 * Thanks for great work! This is an effort to
23 * break apart the various CSCF functions into logically separate
24 * components. We hope this will drive wider use. We also feel
25 * that in this way the architecture is more complete and thereby easier
26 * to manage in the Kamailio/SR environment
27 *
28 * This file is part of Kamailio, a free SIP server.
29 *
30 * Kamailio is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version
34 *
35 * Kamailio is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
43 *
44 */
45
46
47 #include "../cdp/cdp_load.h"
48 #include "../../modules/tm/tm_load.h"
49 #include "cxdx_avp.h"
50
51
52
53 static str s_empty = {0, 0};
54
55 /**
56 * Create and add an AVP to a Diameter message.
57 * @param m - Diameter message to add to
58 * @param d - the payload data
59 * @param len - length of the payload data
60 * @param avp_code - the code of the AVP
61 * @param flags - flags for the AVP
62 * @param vendorid - the value of the vendor id or 0 if none
63 * @param data_do - what to do with the data when done
64 * @param func - the name of the calling function, for debugging purposes
65 * @returns 1 on success or 0 on failure
66 */
cxdx_add_avp(AAAMessage * m,char * d,int len,int avp_code,int flags,int vendorid,int data_do,const char * func)67 static int cxdx_add_avp(AAAMessage *m,char *d,int len,int avp_code,
68 int flags,int vendorid,int data_do,const char *func)
69 {
70 AAA_AVP *avp;
71 if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
72 avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do);
73 if (!avp) {
74 LM_ERR("%s: Failed creating avp\n",func);
75 return 0;
76 }
77 if (cdpb.AAAAddAVPToMessage(m,avp,m->avpList.tail)!=AAA_ERR_SUCCESS) {
78 LM_ERR("%s: Failed adding avp to message\n",func);
79 cdpb.AAAFreeAVP(&avp);
80 return 0;
81 }
82 return 1;
83 }
84
85 /**
86 * Create and add an AVP to a list of AVPs.
87 * @param list - the AVP list to add to
88 * @param d - the payload data
89 * @param len - length of the payload data
90 * @param avp_code - the code of the AVP
91 * @param flags - flags for the AVP
92 * @param vendorid - the value of the vendor id or 0 if none
93 * @param data_do - what to do with the data when done
94 * @param func - the name of the calling function, for debugging purposes
95 * @returns 1 on success or 0 on failure
96 */
cxdx_add_avp_list(AAA_AVP_LIST * list,char * d,int len,int avp_code,int flags,int vendorid,int data_do,const char * func)97 static int cxdx_add_avp_list(AAA_AVP_LIST *list,char *d,int len,int avp_code,
98 int flags,int vendorid,int data_do,const char *func)
99 {
100 AAA_AVP *avp;
101 if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
102 avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do);
103 if (!avp) {
104 LM_ERR("%s: Failed creating avp\n",func);
105 return 0;
106 }
107 if (list->tail) {
108 avp->prev=list->tail;
109 avp->next=0;
110 list->tail->next = avp;
111 list->tail=avp;
112 } else {
113 list->head = avp;
114 list->tail = avp;
115 avp->next=0;
116 avp->prev=0;
117 }
118
119 return 1;
120 }
121
122 /**
123 * Returns the value of a certain AVP from a Diameter message.
124 * @param m - Diameter message to look into
125 * @param avp_code - the code to search for
126 * @param vendorid - the value of the vendor id to look for or 0 if none
127 * @param func - the name of the calling function, for debugging purposes
128 * @returns the str with the payload on success or an empty string on failure
129 */
cxdx_get_avp(AAAMessage * msg,int avp_code,int vendor_id,const char * func)130 static str cxdx_get_avp(AAAMessage *msg,int avp_code,int vendor_id,
131 const char *func)
132 {
133 AAA_AVP *avp;
134 str r={0,0};
135
136 avp = cdpb.AAAFindMatchingAVP(msg,0,avp_code,vendor_id,0);
137 if (avp==0){
138 LM_INFO("%s: Failed finding avp\n",func);
139 return r;
140 }
141 else
142 return avp->data;
143 }
144
cxdx_add_call_id(AAAMessage * msg,str data)145 int cxdx_add_call_id(AAAMessage *msg, str data)
146 {
147 return
148 cxdx_add_avp(msg,data.s,data.len,
149 AVP_Call_Id,
150 AAA_AVP_FLAG_VENDOR_SPECIFIC,
151 50,
152 AVP_DUPLICATE_DATA,
153 __FUNCTION__);
154 }
155
156 /**
157 * Creates and adds a Destination-Realm AVP.
158 * @param msg - the Diameter message to add to.
159 * @param data - the value for the AVP payload
160 * @returns 1 on success or 0 on error
161 */
cxdx_add_destination_realm(AAAMessage * msg,str data)162 int cxdx_add_destination_realm(AAAMessage *msg,str data)
163 {
164 return
165 cxdx_add_avp(msg,data.s,data.len,
166 AVP_Destination_Realm,
167 AAA_AVP_FLAG_MANDATORY,
168 0,
169 AVP_DUPLICATE_DATA,
170 __FUNCTION__);
171 }
172
173
174 /**
175 * Creates and adds a Vendor-Specifig-Application-ID AVP.
176 * @param msg - the Diameter message to add to.
177 * @param vendor_id - the value of the vendor_id,
178 * @param auth_id - the authorization application id
179 * @param acct_id - the accounting application id
180 * @returns 1 on success or 0 on error
181 */
cxdx_add_vendor_specific_appid(AAAMessage * msg,unsigned int vendor_id,unsigned int auth_id,unsigned int acct_id)182 int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id,
183 unsigned int auth_id,unsigned int acct_id)
184 {
185 AAA_AVP_LIST list;
186 str group;
187 char x[4];
188
189 list.head=0;list.tail=0;
190
191 set_4bytes(x,vendor_id);
192 cxdx_add_avp_list(&list,
193 x,4,
194 AVP_Vendor_Id,
195 AAA_AVP_FLAG_MANDATORY,
196 0,
197 AVP_DUPLICATE_DATA,
198 __FUNCTION__);
199
200 if (auth_id) {
201 set_4bytes(x,auth_id);
202 cxdx_add_avp_list(&list,
203 x,4,
204 AVP_Auth_Application_Id,
205 AAA_AVP_FLAG_MANDATORY,
206 0,
207 AVP_DUPLICATE_DATA,
208 __FUNCTION__);
209 }
210 if (acct_id) {
211 set_4bytes(x,acct_id);
212 cxdx_add_avp_list(&list,
213 x,4,
214 AVP_Acct_Application_Id,
215 AAA_AVP_FLAG_MANDATORY,
216 0,
217 AVP_DUPLICATE_DATA,
218 __FUNCTION__);
219 }
220
221 group = cdpb.AAAGroupAVPS(list);
222
223 cdpb.AAAFreeAVPList(&list);
224
225 return
226 cxdx_add_avp(msg,group.s,group.len,
227 AVP_Vendor_Specific_Application_Id,
228 AAA_AVP_FLAG_MANDATORY,
229 0,
230 AVP_FREE_DATA,
231 __FUNCTION__);
232 }
233
234 /**
235 * Creates and adds a Auth-Session-State AVP.
236 * @param msg - the Diameter message to add to.
237 * @param data - the value for the AVP payload
238 * @returns 1 on success or 0 on error
239 */
cxdx_add_auth_session_state(AAAMessage * msg,unsigned int data)240 int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data)
241 {
242 char x[4];
243 set_4bytes(x,data);
244 return
245 cxdx_add_avp(msg,x,4,
246 AVP_Auth_Session_State,
247 AAA_AVP_FLAG_MANDATORY,
248 0,
249 AVP_DUPLICATE_DATA,
250 __FUNCTION__);
251 }
252
253 /**
254 * Creates and adds a User-Name AVP.
255 * @param msg - the Diameter message to add to.
256 * @param data - the value for the AVP payload
257 * @returns 1 on success or 0 on error
258 */
cxdx_add_user_name(AAAMessage * msg,str data)259 int cxdx_add_user_name(AAAMessage *msg,str data)
260 {
261 return
262 cxdx_add_avp(msg,data.s,data.len,
263 AVP_User_Name,
264 AAA_AVP_FLAG_MANDATORY,
265 0,
266 AVP_DUPLICATE_DATA,
267 __FUNCTION__);
268 }
269
270 /**
271 * Creates and adds a Public Identity AVP.
272 * @param msg - the Diameter message to add to.
273 * @param data - the value for the AVP payload
274 * @returns 1 on success or 0 on error
275 */
cxdx_add_public_identity(AAAMessage * msg,str data)276 int cxdx_add_public_identity(AAAMessage *msg,str data)
277 {
278 return
279 cxdx_add_avp(msg,data.s,data.len,
280 AVP_IMS_Public_Identity,
281 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
282 IMS_vendor_id_3GPP,
283 AVP_DUPLICATE_DATA,
284 __FUNCTION__);
285 }
286
287 /**
288 * Creates and adds a Visited-Network-ID AVP.
289 * @param msg - the Diameter message to add to.
290 * @param data - the value for the AVP payload
291 * @returns 1 on success or 0 on error
292 */
cxdx_add_visited_network_id(AAAMessage * msg,str data)293 int cxdx_add_visited_network_id(AAAMessage *msg,str data)
294 {
295 return
296 cxdx_add_avp(msg,data.s,data.len,
297 AVP_IMS_Visited_Network_Identifier,
298 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
299 IMS_vendor_id_3GPP,
300 AVP_DUPLICATE_DATA,
301 __FUNCTION__);
302 }
303
304 /**
305 * Creates and adds a UAR-Flags AVP.
306 * @param msg - the Diameter message to add to.
307 * @param data - the value for the AVP payload
308 * @returns 1 on success or 0 on error
309 */
cxdx_add_UAR_flags(AAAMessage * msg,unsigned int sos_reg)310 int cxdx_add_UAR_flags(AAAMessage *msg, unsigned int sos_reg)
311 {
312
313 char x[4];
314 /* optional AVP*/
315 if(!sos_reg)
316 return 1;
317
318 set_4bytes(x, AVP_IMS_UAR_Flags_Emergency_Registration);
319 return
320 cxdx_add_avp(msg,x,4,
321 AVP_IMS_UAR_Flags,
322 AAA_AVP_FLAG_VENDOR_SPECIFIC,
323 IMS_vendor_id_3GPP,
324 AVP_DUPLICATE_DATA,
325 __FUNCTION__);
326
327 }
328 /**
329 * Creates and adds a Authorization-Type AVP.
330 * @param msg - the Diameter message to add to.
331 * @param data - the value for the AVP payload
332 * @returns 1 on success or 0 on error
333 */
cxdx_add_authorization_type(AAAMessage * msg,unsigned int data)334 int cxdx_add_authorization_type(AAAMessage *msg,unsigned int data)
335 {
336 char x[4];
337 set_4bytes(x,data);
338 return
339 cxdx_add_avp(msg,x,4,
340 AVP_IMS_User_Authorization_Type,
341 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
342 IMS_vendor_id_3GPP,
343 AVP_DUPLICATE_DATA,
344 __FUNCTION__);
345 }
346
347 /**
348 * Returns the Result-Code AVP from a Diameter message.
349 * @param msg - the Diameter message
350 * @returns the AVP payload on success or an empty string on error
351 */
cxdx_get_result_code(AAAMessage * msg,int * data)352 int cxdx_get_result_code(AAAMessage *msg, int *data)
353 {
354 str s;
355 s = cxdx_get_avp(msg,
356 AVP_Result_Code,
357 0,
358 __FUNCTION__);
359 if (!s.s) return 0;
360 *data = get_4bytes(s.s);
361 return 1;
362 }
363
364 /**
365 * Returns the Experimental-Result-Code AVP from a Diameter message.
366 * @param msg - the Diameter message
367 * @returns the AVP payload on success or an empty string on error
368 */
cxdx_get_experimental_result_code(AAAMessage * msg,int * data)369 int cxdx_get_experimental_result_code(AAAMessage *msg, int *data)
370 {
371 AAA_AVP_LIST list;
372 AAA_AVP *avp;
373 str grp;
374 grp = cxdx_get_avp(msg,
375 AVP_IMS_Experimental_Result,
376 0,
377 __FUNCTION__);
378 if (!grp.s) return 0;
379
380 list = cdpb.AAAUngroupAVPS(grp);
381
382 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Experimental_Result_Code,0,0);
383 if (!avp||!avp->data.s) {
384 cdpb.AAAFreeAVPList(&list);
385 return 0;
386 }
387
388 *data = get_4bytes(avp->data.s);
389 cdpb.AAAFreeAVPList(&list);
390
391 return 1;
392 }
393
394 /**
395 * Returns the Server-Name AVP from a Diameter message.
396 * @param msg - the Diameter message
397 * @returns the AVP payload on success or an empty string on error
398 */
cxdx_get_server_name(AAAMessage * msg)399 str cxdx_get_server_name(AAAMessage *msg)
400 {
401 return cxdx_get_avp(msg,
402 AVP_IMS_Server_Name,
403 IMS_vendor_id_3GPP,
404 __FUNCTION__);
405 }
406
407 /**
408 * Returns the Capabilities from the grouped AVP from a Diameter message.
409 * @param msg - the Diameter message
410 * @param m - array to be filled with the retrieved mandatory capabilities
411 * @param m_cnt - size of the array above to be filled
412 * @param o - array to be filled with the retrieved optional capabilities
413 * @param o_cnt - size of the array above to be filled
414 * @returns 1 on success 0 on fail
415 */
cxdx_get_capabilities(AAAMessage * msg,int ** m,int * m_cnt,int ** o,int * o_cnt,str ** p,int * p_cnt)416 int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt,
417 str **p,int *p_cnt)
418 {
419 AAA_AVP_LIST list;
420 AAA_AVP *avp;
421 str grp;
422 grp = cxdx_get_avp(msg,
423 AVP_IMS_Server_Capabilities,
424 IMS_vendor_id_3GPP,
425 __FUNCTION__);
426 if (!grp.s) return 0;
427
428 list = cdpb.AAAUngroupAVPS(grp);
429
430 avp = list.head;
431 *m_cnt=0;
432 *o_cnt=0;
433 *p_cnt=0;
434 while(avp){
435 if (avp->code == AVP_IMS_Mandatory_Capability) (*m_cnt)++;
436 if (avp->code == AVP_IMS_Optional_Capability) (*o_cnt)++;
437 if (avp->code == AVP_IMS_Server_Name) (*p_cnt)++;
438 avp = avp->next;
439 }
440 avp = list.head;
441 *m=shm_malloc(sizeof(int)*(*m_cnt));
442 if (!*m){
443 LM_ERR("cannot allocated %lx bytes of shm.\n",
444 sizeof(int)*(*m_cnt));
445 goto error;
446 }
447 *o=shm_malloc(sizeof(int)*(*o_cnt));
448 if (!*o){
449 LM_ERR("cannot allocated %lx bytes of shm.\n",
450 sizeof(int)*(*o_cnt));
451 goto error;
452 }
453 *p=shm_malloc(sizeof(str)*(*p_cnt));
454 if (!*p){
455 LM_ERR("cannot allocated %lx bytes of shm.\n",
456 sizeof(str)*(*p_cnt));
457 goto error;
458 }
459
460 *m_cnt=0;
461 *o_cnt=0;
462 *p_cnt=0;
463 while(avp){
464 if (avp->code == AVP_IMS_Mandatory_Capability)
465 (*m)[(*m_cnt)++]=get_4bytes(avp->data.s);
466 if (avp->code == AVP_IMS_Optional_Capability)
467 (*o)[(*o_cnt)++]=get_4bytes(avp->data.s);
468 if (avp->code == AVP_IMS_Server_Name)
469 (*p)[(*p_cnt)++]=avp->data;
470 avp = avp->next;
471 }
472 cdpb.AAAFreeAVPList(&list);
473 return 1;
474
475 error:
476 cdpb.AAAFreeAVPList(&list);
477 if (*m) shm_free(*m);
478 if (*o) shm_free(*o);
479 if (*p) shm_free(*p);
480 *m_cnt=0;
481 *o_cnt=0;
482 *p_cnt=0;
483 return 0;
484 }
485
486 /**
487 * Transactional SIP response - tries to create a transaction if none found.
488 * @param msg - message to reply to
489 * @param code - the Status-code for the response
490 * @param text - the Reason-Phrase for the response
491 * @returns the tmb.t_reply() result
492 */
cscf_reply_transactional(struct sip_msg * msg,int code,char * text)493 int cscf_reply_transactional(struct sip_msg *msg, int code, char *text)
494 {
495 unsigned int hash,label;
496 if (tmb.t_get_trans_ident(msg,&hash,&label)<0){
497
498 if (tmb.t_newtran(msg)<0)
499 LM_ERR("Failed creating SIP transaction\n");
500 }
501 return tmb.t_reply(msg,code,text);
502 }
503
504 /**
505 * Creates and adds a SIP-Number-Auth-Items AVP.
506 * @param msg - the Diameter message to add to.
507 * @param data - the value for the AVP payload
508 * @returns 1 on success or 0 on error
509 */
cxdx_add_sip_number_auth_items(AAAMessage * msg,unsigned int data)510 int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data)
511 {
512 char x[4];
513 set_4bytes(x,data);
514 return
515 cxdx_add_avp(msg,x,4,
516 AVP_IMS_SIP_Number_Auth_Items,
517 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
518 IMS_vendor_id_3GPP,
519 AVP_DUPLICATE_DATA,
520 __FUNCTION__);
521 }
522
523 /**
524 * Creates and adds a SIP-Auth-Data-Item AVP.
525 * @param msg - the Diameter message to add to.
526 * @param auth_scheme - the value for the authorization scheme AVP
527 * @param auth - the value for the authorization AVP
528 * @returns 1 on success or 0 on error
529 */
cxdx_add_sip_auth_data_item_request(AAAMessage * msg,str auth_scheme,str auth,str username,str realm,str method,str server_name)530 int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str auth, str username, str realm,str method, str server_name)
531 {
532 AAA_AVP_LIST list;
533 str group;
534 str etsi_authorization = {0, 0};
535 list.head=0;list.tail=0;
536
537 if (auth_scheme.len){
538 cxdx_add_avp_list(&list,
539 auth_scheme.s,auth_scheme.len,
540 AVP_IMS_SIP_Authentication_Scheme,
541 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
542 IMS_vendor_id_3GPP,
543 AVP_DONT_FREE_DATA,
544 __FUNCTION__);
545 }
546 if (auth.len){
547 cxdx_add_avp_list(&list,
548 auth.s,auth.len,
549 AVP_IMS_SIP_Authorization,
550 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
551 IMS_vendor_id_3GPP,
552 AVP_DONT_FREE_DATA,
553 __FUNCTION__);
554 }
555
556 if (server_name.len)
557 {
558 etsi_authorization = cxdx_ETSI_sip_authorization(username, realm, s_empty, server_name, s_empty, s_empty, method, s_empty);
559
560 if (etsi_authorization.len){
561 cxdx_add_avp_list(&list,
562 etsi_authorization.s,etsi_authorization.len,
563 AVP_ETSI_SIP_Authorization,
564 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
565 IMS_vendor_id_ETSI,
566 AVP_FREE_DATA,
567 __FUNCTION__);
568 }
569 }
570
571 if (!list.head) return 1;
572 group = cdpb.AAAGroupAVPS(list);
573
574 cdpb.AAAFreeAVPList(&list);
575
576 return
577 cxdx_add_avp(msg,group.s,group.len,
578 AVP_IMS_SIP_Auth_Data_Item,
579 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
580 IMS_vendor_id_3GPP,
581 AVP_FREE_DATA,
582 __FUNCTION__);
583 }
584
585 /**
586 * Creates and adds a Server-Name AVP.
587 * @param msg - the Diameter message to add to.
588 * @param data - the value for the AVP payload
589 * @returns 1 on success or 0 on error
590 */
cxdx_add_server_name(AAAMessage * msg,str data)591 int cxdx_add_server_name(AAAMessage *msg,str data)
592 {
593 return
594 cxdx_add_avp(msg,data.s,data.len,
595 AVP_IMS_Server_Name,
596 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
597 IMS_vendor_id_3GPP,
598 AVP_DUPLICATE_DATA,
599 __FUNCTION__);
600 }
601
602 /**
603 * Returns the SIP-Number-Auth-Items AVP from a Diameter message.
604 * @param msg - the Diameter message
605 * @returns the number or 0 on error
606 */
cxdx_get_sip_number_auth_items(AAAMessage * msg,int * data)607 int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data)
608 {
609 str s;
610 s = cxdx_get_avp(msg,
611 AVP_IMS_SIP_Number_Auth_Items,
612 IMS_vendor_id_3GPP,
613 __FUNCTION__);
614 if (!s.s) return 0;
615 *data = get_4bytes(s.s);
616 return 1;
617 }
618
619 /**
620 * Returns the Auth-Data-Item from a Diameter answer message.
621 * @param msg - the Diameter message
622 * @param auth_date - the string to fill with the authorization data
623 * @param item_number - the int to fill with the item number
624 * @param auth_scheme - the string to fill with the authentication scheme data
625 * @param authenticate - the string to fill with the authenticate data
626 * @param authorization - the string to fill with the authorization data
627 * @param ck - the string to fill with the cipher key
628 * @param ik - the string to fill with the integrity key
629 * @returns the AVP payload on success or an empty string on error
630 */
cxdx_get_auth_data_item_answer(AAAMessage * msg,AAA_AVP ** auth_data,int * item_number,str * auth_scheme,str * authenticate,str * authorization,str * ck,str * ik,str * ip,str * ha1,str * response_auth,str * digest_realm,str * line_identifier)631 int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data,
632 int *item_number,str *auth_scheme,str *authenticate,str *authorization,
633 str *ck,str *ik,
634 str *ip,
635 str *ha1, str *response_auth, str *digest_realm,
636 str *line_identifier)
637 {
638 AAA_AVP_LIST list;
639 AAA_AVP_LIST list2;
640 AAA_AVP *avp;
641 AAA_AVP *avp2;
642 str grp;
643 ha1->s = 0; ha1->len = 0;
644 *auth_data = cdpb.AAAFindMatchingAVP(msg,*auth_data,AVP_IMS_SIP_Auth_Data_Item,
645 IMS_vendor_id_3GPP,0);
646 if (!*auth_data) return 0;
647
648 grp = (*auth_data)->data;
649 if (!grp.len) return 0;
650
651 list = cdpb.AAAUngroupAVPS(grp);
652
653 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Item_Number,
654 IMS_vendor_id_3GPP,0);
655 if (!avp||avp->data.len!=4) *item_number=0;
656 else *item_number = get_4bytes(avp->data.s);
657
658 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authentication_Scheme,
659 IMS_vendor_id_3GPP,0);
660 if (!avp||!avp->data.s) {auth_scheme->s=0;auth_scheme->len=0;}
661 else *auth_scheme = avp->data;
662
663 /* Early-IMS */
664 ip->s=0;ip->len=0;
665 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IP_Address,0,0);
666 if (avp && avp->data.s){
667 if (avp->data.len!=4){
668 LM_ERR("Invalid length of AVP Framed IP Address (should be 4 for AVP_Framed_IP_Address) >%d.\n",
669 avp->data.len);
670 }
671 ip->len = 4;
672 ip->s = avp->data.s;
673 } else {
674 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IPv6_Prefix,0,0);
675 if (avp && avp->data.s){
676 if (avp->data.len==0){
677 LM_ERR("Invalid length of AVP Framed IPv6 Prefix (should be >0 for AVP_Framed_IPv6_Prefix) >%d.\n",
678 avp->data.len);
679 }
680 ip->len = avp->data.len;
681 ip->s = avp->data.s;
682 }
683 }
684
685 /* Digest */
686
687 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_CableLabs_SIP_Digest_Authenticate,IMS_vendor_id_CableLabs,0);
688 if (avp && avp->data.s)
689 {
690 list2 = cdpb.AAAUngroupAVPS(avp->data);
691
692 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_CableLabs_Digest_HA1,IMS_vendor_id_CableLabs,0);
693 if (!avp2||!avp2->data.s) {
694 ha1->s = 0; ha1->len = 0;
695 cdpb.AAAFreeAVPList(&list2);
696 return 0;
697 }
698 *ha1 = avp2->data;
699 cdpb.AAAFreeAVPList(&list2);
700 }
701
702
703 /* SIP Digest */
704
705 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Digest_Authenticate,IMS_vendor_id_3GPP,0);
706 if (avp && avp->data.s)
707 {
708 list2 = cdpb.AAAUngroupAVPS(avp->data);
709
710 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_IMS_Digest_HA1,0,0);
711 if (!avp2||!avp2->data.s) {
712 ha1->s = 0; ha1->len = 0;
713 cdpb.AAAFreeAVPList(&list2);
714 return 0;
715 }
716 *ha1 = avp2->data;
717 cdpb.AAAFreeAVPList(&list2);
718 }
719
720
721 /* AKA, MD5 */
722 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authenticate,
723 IMS_vendor_id_3GPP,0);
724 if (!avp||!avp->data.s) {authenticate->s=0;authenticate->len=0;}
725 else *authenticate = avp->data;
726
727 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authorization,
728 IMS_vendor_id_3GPP,0);
729 if (!avp||!avp->data.s) {authorization->s=0;authorization->len=0;}
730 else *authorization = avp->data;
731
732 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Confidentiality_Key,
733 IMS_vendor_id_3GPP,0);
734 if (!avp||!avp->data.s) {ck->s=0;ck->len=0;}
735 else *ck = avp->data;
736
737 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Integrity_Key,
738 IMS_vendor_id_3GPP,0);
739 if (!avp||!avp->data.s) {ik->s=0;ik->len=0;}
740 else *ik = avp->data;
741
742 /* ETSI HTTP Digest */
743
744 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authenticate,IMS_vendor_id_ETSI,0);
745 if (avp && avp->data.s)
746 {
747 list2 = cdpb.AAAUngroupAVPS(avp->data);
748
749 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Realm, IMS_vendor_id_ETSI,0);
750 if (!avp2||!avp2->data.s) {
751 digest_realm->s=0;digest_realm->len=0;
752 cdpb.AAAFreeAVPList(&list2);
753 return 0;
754 }
755 *digest_realm = avp2->data;
756
757 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Nonce, IMS_vendor_id_ETSI,0);
758 if (!avp2||!avp2->data.s) {
759 authenticate->s=0;authenticate->len=0;
760 cdpb.AAAFreeAVPList(&list2);
761 return 0;
762 }
763 *authenticate = avp2->data;
764
765 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_HA1, IMS_vendor_id_ETSI,0);
766 if (!avp2||!avp2->data.s) {
767 ha1->s = 0; ha1->len = 0;
768 cdpb.AAAFreeAVPList(&list2);
769 return 0;
770 }
771 *ha1 = avp2->data;
772
773 cdpb.AAAFreeAVPList(&list2);
774 }
775
776 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authentication_Info,IMS_vendor_id_ETSI,0);
777 if (avp && avp->data.s)
778 {
779 list2 = cdpb.AAAUngroupAVPS(avp->data);
780
781 avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Response_Auth, IMS_vendor_id_ETSI,0);
782 if (!avp2||!avp2->data.s) {
783 response_auth->s=0;response_auth->len=0;
784 cdpb.AAAFreeAVPList(&list2);
785 return 0;
786 }
787 *response_auth = avp2->data;
788 cdpb.AAAFreeAVPList(&list2);
789 }
790 else
791 {
792 response_auth->s=0;response_auth->len=0;
793 }
794
795 /* NASS Bundled */
796 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_Line_Identifier, IMS_vendor_id_ETSI,0);
797 if (!avp||!avp->data.s) {line_identifier->s=0;line_identifier->len=0;}
798 else *line_identifier = avp->data;
799
800 cdpb.AAAFreeAVPList(&list);
801 return 1;
802 }
803
804 /**
805 * Creates and adds a ETSI_sip_authorization AVP.
806 * @param username - UserName
807 * @param realm - Realm
808 * @param nonce - Nonce
809 * @param URI - URI
810 * @param response - Response
811 * @param algoritm - Algorithm
812 * @param method - Method
813 * @param hash - Enitity-Body-Hash
814 * @returns grouped str on success
815 */
cxdx_ETSI_sip_authorization(str username,str realm,str nonce,str URI,str response,str algorithm,str method,str hash)816 str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, str response, str algorithm, str method, str hash)
817 {
818 AAA_AVP_LIST list;
819 str group = {0, 0};
820 list.head=0;list.tail=0;
821
822 if (username.len){
823 cxdx_add_avp_list(&list,
824 username.s,username.len,
825 AVP_ETSI_Digest_Username,
826 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
827 IMS_vendor_id_ETSI,
828 AVP_DONT_FREE_DATA,
829 __FUNCTION__);
830 }
831
832 if (realm.len){
833 cxdx_add_avp_list(&list,
834 realm.s,realm.len,
835 AVP_ETSI_Digest_Realm,
836 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
837 IMS_vendor_id_ETSI,
838 AVP_DONT_FREE_DATA,
839 __FUNCTION__);
840 }
841
842 if (nonce.len){
843 cxdx_add_avp_list(&list,
844 nonce.s,nonce.len,
845 AVP_ETSI_Digest_Nonce,
846 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
847 IMS_vendor_id_ETSI,
848 AVP_DONT_FREE_DATA,
849 __FUNCTION__);
850 }
851
852 if (URI.len){
853 cxdx_add_avp_list(&list,
854 URI.s,URI.len,
855 AVP_ETSI_Digest_URI,
856 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
857 IMS_vendor_id_ETSI,
858 AVP_DONT_FREE_DATA,
859 __FUNCTION__);
860 }
861
862 if (response.len){
863 cxdx_add_avp_list(&list,
864 response.s,response.len,
865 AVP_ETSI_Digest_Response,
866 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
867 IMS_vendor_id_ETSI,
868 AVP_DONT_FREE_DATA,
869 __FUNCTION__);
870 }
871
872 if (algorithm.len){
873 cxdx_add_avp_list(&list,
874 algorithm.s,algorithm.len,
875 AVP_ETSI_Digest_Algorithm,
876 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
877 IMS_vendor_id_ETSI,
878 AVP_DONT_FREE_DATA,
879 __FUNCTION__);
880 }
881
882 if (method.len){
883 cxdx_add_avp_list(&list,
884 method.s,method.len,
885 AVP_ETSI_Digest_Method,
886 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
887 IMS_vendor_id_ETSI,
888 AVP_DONT_FREE_DATA,
889 __FUNCTION__);
890 }
891
892 if (hash.len){
893 cxdx_add_avp_list(&list,
894 hash.s,hash.len,
895 AVP_ETSI_Digest_Entity_Body_Hash,
896 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
897 IMS_vendor_id_ETSI,
898 AVP_DONT_FREE_DATA,
899 __FUNCTION__);
900 }
901
902 if (!list.head) return group;
903 group = cdpb.AAAGroupAVPS(list);
904
905 cdpb.AAAFreeAVPList(&list);
906
907 return group;
908 }
909
910 /**
911 * Returns the User-Data from a Diameter message.
912 * @param msg - the Diameter message
913 * @returns the AVP payload on success or an empty string on error
914 */
915
cxdx_get_user_data(AAAMessage * msg)916 str cxdx_get_user_data(AAAMessage *msg)
917 {
918 return cxdx_get_avp(msg,
919 AVP_IMS_User_Data_Cx,
920 IMS_vendor_id_3GPP,
921 __FUNCTION__);
922 }
923
924 /**
925 * Returns the Charging-Information from a Diameter message.
926 * @param msg - the Diameter message
927 * @returns the AVP payload on success or an empty string on error
928 */
cxdx_get_charging_info(AAAMessage * msg,str * ccf1,str * ccf2,str * ecf1,str * ecf2)929 int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ecf2)
930 {
931 AAA_AVP_LIST list;
932 AAA_AVP *avp;
933 str grp;
934 grp = cxdx_get_avp(msg,
935 AVP_IMS_Charging_Information,
936 IMS_vendor_id_3GPP,
937 __FUNCTION__);
938 if (!grp.s) return 0;
939
940 list = cdpb.AAAUngroupAVPS(grp);
941
942 if (ccf1){
943 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Charging_Collection_Function_Name,
944 IMS_vendor_id_3GPP,0);
945 if (avp) *ccf1 = avp->data;
946 }
947 if (ccf2){
948 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Charging_Collection_Function_Name,
949 IMS_vendor_id_3GPP,0);
950 if (avp) *ccf2 = avp->data;
951 }
952 if (ecf1){
953 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Event_Charging_Function_Name,
954 IMS_vendor_id_3GPP,0);
955 if (avp) *ecf1 = avp->data;
956 }
957 if (ecf2){
958 avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Event_Charging_Function_Name,
959 IMS_vendor_id_3GPP,0);
960 if (avp) *ecf2 = avp->data;
961 }
962
963 cdpb.AAAFreeAVPList(&list);
964 return 1;
965
966 }
967
968 /**
969 * Creates and adds a Server-Assignment-Type AVP.
970 * @param msg - the Diameter message to add to.
971 * @param data - the value for the AVP payload
972 * @returns 1 on success or 0 on error
973 */
cxdx_add_server_assignment_type(AAAMessage * msg,unsigned int data)974 int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data)
975 {
976 char x[4];
977 set_4bytes(x,data);
978 return
979 cxdx_add_avp(msg,x,4,
980 AVP_IMS_Server_Assignment_Type,
981 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
982 IMS_vendor_id_3GPP,
983 AVP_DUPLICATE_DATA,
984 __FUNCTION__);
985 }
986
987 /**
988 * Creates and adds Userdata-Available AVP.
989 * @param msg - the Diameter message to add to.
990 * @param data - the value for the AVP payload
991 * @returns 1 on success or 0 on error
992 */
cxdx_add_userdata_available(AAAMessage * msg,unsigned int data)993 int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data)
994 {
995 char x[4];
996 set_4bytes(x,data);
997 return
998 cxdx_add_avp(msg,x,4,
999 AVP_IMS_User_Data_Already_Available,
1000 AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
1001 IMS_vendor_id_3GPP,
1002 AVP_DUPLICATE_DATA,
1003 __FUNCTION__);
1004 }
1005
1006 /**
1007 * Finds out the next Public-Identity AVP from a Diameter message.
1008 * @param msg - the Diameter message
1009 * @param pos - position to resume search or NULL if to start from the first AVP
1010 * @param avp_code - the code of the AVP to look for
1011 * @param vendor_id - the vendor id of the AVP to look for
1012 * @param func - the name of the calling function for debugging purposes
1013 * @returns the AVP payload on success or an empty string on error
1014 */
cxdx_get_next_public_identity(AAAMessage * msg,AAA_AVP * pos,int avp_code,int vendor_id,const char * func)1015 AAA_AVP* cxdx_get_next_public_identity(AAAMessage *msg,AAA_AVP* pos,int avp_code,int vendor_id,const char *func)
1016 {
1017 AAA_AVP *avp;
1018
1019 avp = cdpb.AAAFindMatchingAVP(msg,pos,avp_code,vendor_id,0);
1020 if (avp==0){
1021 LM_DBG("INFO:%s: Failed finding avp\n",func);
1022 return avp;
1023 }
1024 else
1025 return avp;
1026 }
1027
1028 /**
1029 * Returns the User-Name AVP from a Diameter message.
1030 * @param msg - the Diameter message
1031 * @returns the AVP payload on success or an empty string on error
1032 */
cxdx_get_user_name(AAAMessage * msg)1033 str cxdx_get_user_name(AAAMessage *msg)
1034 {
1035 return cxdx_get_avp(msg,
1036 AVP_User_Name,
1037 0,
1038 __FUNCTION__);
1039 }
1040
1041 /**
1042 * Creates and adds a Result-Code AVP.
1043 * @param msg - the Diameter message to add to.
1044 * @param data - the value for the AVP payload
1045 * @returns 1 on success or 0 on error
1046 */
cxdx_add_result_code(AAAMessage * msg,unsigned int data)1047 int cxdx_add_result_code(AAAMessage *msg,unsigned int data)
1048 {
1049 char x[4];
1050 set_4bytes(x,data);
1051 return
1052 cxdx_add_avp(msg,x,4,
1053 AVP_Result_Code,
1054 AAA_AVP_FLAG_MANDATORY,
1055 0,
1056 AVP_DUPLICATE_DATA,
1057 __FUNCTION__);
1058 }
1059