blob: b1edb8dd7038636fc422a7fb71588fa897a58ac2 [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/********************************************************************************************************
2* Software License Agreement (BSD License) *
3* Author: Alexandre Westfahl <awestfahl@freediameter.net> *
4* *
5* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. *
6* *
7* All rights reserved. *
8* *
9* Redistribution and use of this software in source and binary forms, with or without modification, are *
10* permitted provided that the following conditions are met: *
11* *
12* * Redistributions of source code must retain the above *
13* copyright notice, this list of conditions and the *
14* following disclaimer. *
15* *
16* * Redistributions in binary form must reproduce the above *
17* copyright notice, this list of conditions and the *
18* following disclaimer in the documentation and/or other *
19* materials provided with the distribution. *
20* *
21* * Neither the name of the Teraoka Laboratory nor the *
22* names of its contributors may be used to endorse or *
23* promote products derived from this software without *
24* specific prior written permission of Teraoka Laboratory *
25* *
26* *
27* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
28* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
29* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
30* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
31* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
32* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
33* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
34* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
35********************************************************************************************************/
36#include "test_sip.h"
37
38
39int test_sip_MAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
40{
41/*
42 struct msg *ans, *qry;
43 struct avp *avp, *a2, *authdataitem;
44 struct msg_hdr * header = NULL;
45 struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
46 union avp_value val;
47 int found_cnonce=0;
48 struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
49 char * result;
50 char password[51];
51 int idx=0, idx2=0, number_of_auth_items=0,i=0;
52 //Flags and variables for Database
53 int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
54 char *query=NULL,*username=NULL;
55
56 //The nonce we will store and retrieve in session
57 struct ds_nonce *storednonce=NULL;
58
59
60 TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
61
62 if (msg == NULL)
63 return EINVAL;
64
65
66 // Create answer header
67 qry = *msg;
68 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
69 ans = *msg;
70
71
72
73 // Add the appropriate command code & Auth-Application-Id
74 {
75
76 CHECK_FCT( fd_msg_hdr ( *msg, &header ) );
77 header->msg_flags = CMD_FLAG_PROXIABLE;
78 header->msg_code = 286;
79 header->msg_appl = 6;
80
81
82 // Add the Auth-Application-Id
83 {
84 CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
85 ASSERT(avp);
86 val.i32 = header->msg_appl;
87 CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
88 CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
89 }
90 }
91
92
93 // Add the Auth-Session-State AVP
94 {
95
96 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
97 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
98
99 CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
100 CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
101 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
102 }
103
104
105
106 // Check if method is REGISTER then User-Name must be present
107 {
108
109 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Method, &avp) );
110 CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ));
111
112
113 char *method=NULL;
114
115 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
116 if(avp!=NULL)
117 {
118
119 int not_found=1;
120 MYSQL_RES *res=NULL;
121 MYSQL_ROW row;
122
123 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
124
125 //We allocate the double size of username because at worst it can be all quotes
126 username=malloc(avphdr->avp_value->os.len*2+1);
127 //We purify username not to have forbidden characters
128 usernamelen=mysql_real_escape_string(conn, username, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
129
130
131 if((strncmp(avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0))
132 {
133 not_found=1;
134
135 //We copy username in query
136 querylen=SQL_GETPASSWORD_LEN + usernamelen;
137 query = malloc(querylen+2);
138 snprintf(query, querylen+1, SQL_GETPASSWORD, username);
139
140
141
142 //We make the query
143 request_mysql(query);
144 res=mysql_use_result(conn);
145 if(res==NULL)
146 {
147 //We couldn't make the request
148 result="DIAMETER_UNABLE_TO_COMPLY";
149 goto out;
150 }
151
152
153
154 while ((row = mysql_fetch_row(res)) != NULL)
155 {
156 if(row[0]!="")
157 {
158 strcpy(password,row[0]);
159 not_found=0;
160 break;
161 }
162 }
163 mysql_free_result(res);
164 free(query);
165
166 if(not_found)
167 {
168 TRACE_DEBUG(FULL,"The user %s doesn't exist!",username);
169 result="DIAMETER_ERROR_USER_UNKNOWN";
170 free(username);
171 goto out;
172 }
173
174
175
176 //Now that we know the user exist, we get the list of AOR owned by this user
177 querylen=SQL_GETSIPAOR_LEN + usernamelen;
178 query = malloc(querylen+2);
179 snprintf(query, querylen+1, SQL_GETSIPAOR, username);
180
181 //We make the query
182 request_mysql(query);
183 res=mysql_use_result(conn);
184 if(res==NULL)
185 {
186 //We couldn't make the request
187 result="DIAMETER_UNABLE_TO_COMPLY";
188 goto out;
189 }
190
191 //We retrieve the SIP-AOR from AVP to check if the user can us it
192 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
193 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
194
195 not_found=1;
196 while ((row = mysql_fetch_row(res)) != NULL)
197 {
198 if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
199 {
200 not_found=0;
201 break;
202 }
203 }
204 mysql_free_result(res);
205 free(query);
206
207 if(not_found)
208 {
209 TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username);
210 result="DIAMETER_ERROR_IDENTITIES_DONT_MATCH";
211 free(username);
212 goto out;
213 }
214
215 }
216
217 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
218 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
219
220 if(avphdr!=NULL)
221 {
222 char *sipuri=NULL;
223 int sipurilen=0;
224
225 //We allocate the double size of SIP-URI because at worst it can be all quotes
226 sipuri=malloc(avphdr->avp_value->os.len*2+1);
227 //We purify SIP-URI not to have forbidden characters
228 sipurilen=mysql_real_escape_string(conn, sipuri, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
229
230
231 //We get the SIP-URI assignated to the user
232 querylen=SQL_GETSIPURI_LEN + usernamelen;
233 query = malloc(querylen+2);
234 snprintf(query, querylen+1, SQL_GETSIPURI, username);
235
236 //We make the query
237 request_mysql(query);
238 res=mysql_use_result(conn);
239 if(res==NULL)
240 {
241 //We couldn't make the request
242 result="DIAMETER_UNABLE_TO_COMPLY";
243 goto out;
244 }
245 not_found=1;
246 while ((row = mysql_fetch_row(res)) != NULL)
247 {
248 if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
249 {
250 not_found=0;
251 break;
252 }
253 }
254 mysql_free_result(res);
255 free(query);
256
257 if(not_found)
258 {
259 //We update the SIP_URI for the user and we flag "authentication in progress"
260 querylen=SQL_SETSIPURI_LEN + usernamelen + sipurilen;
261 query = malloc(querylen+2);
262 snprintf(query, querylen+1, SQL_SETSIPURI, sipuri, username);
263
264 //We make the query
265 request_mysql(query);
266
267 free(query);
268 authenticationpending=1;
269 }
270 free(sipuri);
271
272 }
273 else
274 sipurinotstored=1;
275
276 }
277 else
278 {
279 result="DIAMETER_USER_NAME_REQUIRED";
280 goto out;
281 }
282
283
284 free(method);
285
286 }
287
288
289 //TODO: remove loop for authdataitem because RFC say only one (wait for answer from Garcia)
290 // How many Auth Data Items?
291 CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Number_Auth_Items, &avp) );
292 CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ) );
293
294
295 if(avp!=NULL)
296 {
297 CHECK_FCT(fd_msg_search_avp ( qry, sip_dict.SIP_Auth_Data_Item, &avp));
298 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
299
300 if(avp!=NULL)
301 {
302 //First is Authentication Scheme
303 CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &avp, NULL) );
304 CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ) );
305
306 //Digest-Authentication?
307 if(avphdr->avp_value->i32==0)
308 {
309
310 for(idx=0;idx<avpheader->avp_value->i32;idx++)
311 {
312 //We look for SIP Auth items
313 CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
314
315 if(avp!=NULL)
316 {
317
318 CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr ));
319
320 if(avphdr->avp_code==380) //We only create Auth-Data-Item to answer Auth-Data-Item
321 {
322 // Add the Auth-Data-Item AVP
323 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Auth_Data_Item, 0, &authdataitem ) );
324
325 // Add the Authentication Scheme AVP
326 {
327 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Scheme, 0, &a2 ) );
328 val.i32=0; //We only know Digest Authentication
329 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
330 CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, a2 ) );
331 }
332
333 //We need to know if there is a Cnonce attribute (only in the second MAR request)
334
335 //CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
336
337
338 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
339
340 if(a2!=NULL)
341 found_cnonce=1;
342 else
343 found_cnonce=0;
344
345 if(!found_cnonce)
346 {
347 //
348 We are in the case of first access request so we need to challenge the user.
349
350 TRACE_DEBUG(FULL,"First Authorization in progress...");
351
352 // Create a new session //this create a new session Id !!!
353 //CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, "test_sip", 7), goto out );
354
355
356 // Create the SIP-Authenticate AVP
357 {
358 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authenticate, 0, &sipAuthenticate ) );
359 }
360
361 // Add the Digest QOP AVP
362 {
363 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) );
364 val.os.data="auth";
365 val.os.len=strlen(val.os.data);
366 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
367 CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
368 }
369 // Add the Digest Nonce AVP
370 {
371 uint8_t buffer[NONCE_SIZE];
372 char nonce[NONCE_SIZE * 2 + 1];
373
374
375 gcry_create_nonce ((uint8_t *)buffer, sizeof(buffer));
376
377 for(i=0;i<NONCE_SIZE;i++)
378 sprintf(&nonce[2 * i], "%2.2hhx", buffer[i]);
379
380 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Nonce, 0, &a2 ) );
381
382
383 //We store the nonce (storednonce structure) inside the session
384 storednonce=malloc(sizeof(struct ds_nonce));
385 memset(storednonce,0,sizeof(struct ds_nonce));
386 CHECK_MALLOC(storednonce->nonce=malloc(NONCE_SIZE*2+1));
387 memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1);
388 CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce ));
389
390 val.os.data=nonce;
391 val.os.len=NONCE_SIZE * 2;
392
393 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
394 CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
395 }
396 // Add the Digest Algorithm AVP
397 {
398 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) );
399 val.os.data="MD5";
400 val.os.len=strlen(val.os.data);
401 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
402 CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
403
404 }
405 // Add the Digest Realm AVP
406 {
407 tempavp=avp;
408
409 avpheader_auth=walk_digest(tempavp, 104);
410 if(avpheader_auth!=NULL)
411 {
412 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Realm, 0, &a2 ) );
413 CHECK_FCT( fd_msg_avp_setvalue( a2, avpheader_auth->avp_value ) );
414 CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
415
416 }
417 }
418
419
420 //We add SIP Authenticate to Auth Data Item
421 CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthenticate ) );
422 //We add Auth Data Item to Answer
423 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
424
425 number_of_auth_items++;
426 if(sipurinotstored)
427 result="DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED";
428 else
429 result="DIAMETER_MULTI_ROUND_AUTH";
430 found_cnonce=0;
431 }
432 else
433 {
434 //
435 We are in the case of access request after challenge so we need to check credentials.
436
437 TRACE_DEBUG(FULL,"Authentication after challenge");
438
439 // Search the session, retrieve its data
440 {
441 //int new=0;
442
443 //TRACE_DEBUG(FULL,"new: *%d*",new);
444 //ASSERT( new == 0 );
445 CHECK_FCT( fd_sess_state_retrieve( ds_sess_hdl, sess, &storednonce ));
446 if(storednonce ==NULL)
447 {
448 result="DIAMETER_UNABLE_TO_COMPLY";
449
450 if(username!=NULL)
451 free(username);
452 goto out;
453 }
454 }
455
456 // Create the SIP-Authentication-Info AVP
457 {
458 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Info, 0, &sipAuthentication ) );
459 }
460
461
462
463 // Add the Digest response Auth AVP
464 {
465 //uint8_t bufferresp[DIGEST_LEN];
466 //char response[DIGEST_LEN*2+1];
467 int i=0;
468
469 //We extract all the data we need
470 tempavp=avp;
471
472 char * digest_username=NULL, *digest_uri=NULL, *digest_response=NULL, *digest_realm=NULL, *digest_nonce=NULL, *digest_method=NULL, *digest_qop=NULL, *digest_algorithm=NULL, *digest_cnonce=NULL, *digest_noncecount=NULL;
473
474
475 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce, &a2 ));
476 if(a2!=NULL)
477 {
478 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
479 if(digestheader!=NULL)
480 {
481
482 digest_nonce = malloc(digestheader->avp_value->os.len + 1);
483 memcpy(digest_nonce, digestheader->avp_value->os.data,
484 digestheader->avp_value->os.len);
485 digest_nonce[digestheader->avp_value->os.len]='\0';
486 TRACE_DEBUG(FULL,"Element:*%s*",digest_nonce);
487 TRACE_DEBUG(FULL,"Stored Nonce:*%s*",storednonce->nonce);
488
489 if(strcmp(digest_nonce,storednonce->nonce)!=0)
490 {
491 free(digest_nonce);
492 free(storednonce->nonce);
493 free(storednonce);
494 result="DIAMETER_UNABLE_TO_COMPLY";
495
496 if(username!=NULL)
497 free(username);
498 goto out;
499 }
500
501 }
502
503 }
504 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Response, &a2 ));
505 if(a2!=NULL)
506 {
507 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
508 if(digestheader!=NULL)
509 {
510 digest_response = malloc(digestheader->avp_value->os.len + 1);
511 memcpy(digest_response, digestheader->avp_value->os.data,
512 digestheader->avp_value->os.len);
513 digest_response[digestheader->avp_value->os.len]='\0';
514 TRACE_DEBUG(FULL,"Element:*%s*",digest_response);
515 }
516
517 }
518 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Realm, &a2 ));
519 if(a2!=NULL)
520 {
521 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
522 if(digestheader!=NULL)
523 {
524 digest_realm = malloc(digestheader->avp_value->os.len + 1);
525 memcpy(digest_realm, digestheader->avp_value->os.data,
526 digestheader->avp_value->os.len);
527 digest_realm[digestheader->avp_value->os.len]='\0';
528 TRACE_DEBUG(FULL,"Element:*%s*",digest_realm);
529 }
530 }
531
532 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Method, &a2 ));
533 if(a2!=NULL)
534 {
535 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
536 if(digestheader!=NULL)
537 {
538 digest_method = malloc(digestheader->avp_value->os.len + 1);
539 memcpy(digest_method, digestheader->avp_value->os.data,
540 digestheader->avp_value->os.len);
541 digest_method[digestheader->avp_value->os.len]='\0';
542 TRACE_DEBUG(FULL,"Element:*%s*",digest_method);
543 }
544 }
545 else
546 digest_method="";
547
548 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_URI, &a2 ));
549 if(a2!=NULL)
550 {
551 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
552 if(digestheader!=NULL)
553 {
554 digest_uri = malloc(digestheader->avp_value->os.len + 1);
555 memcpy(digest_uri, digestheader->avp_value->os.data,
556 digestheader->avp_value->os.len);
557 digest_uri[digestheader->avp_value->os.len]='\0';
558 TRACE_DEBUG(FULL,"Element:*%s*",digest_uri);
559 }
560 }
561
562 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_QOP, &a2 ));
563 if(a2!=NULL)
564 {
565 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
566 if(digestheader!=NULL)
567 {
568 digest_qop = malloc(digestheader->avp_value->os.len + 1);
569 memcpy(digest_qop, digestheader->avp_value->os.data,
570 digestheader->avp_value->os.len);
571 digest_qop[digestheader->avp_value->os.len]='\0';
572 TRACE_DEBUG(FULL,"Element:*%s*",digest_qop);
573 }
574 }
575 else
576 digest_qop=NULL;
577 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Algorithm, &a2 ));
578 if(a2!=NULL)
579 {
580 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
581 if(digestheader!=NULL)
582 {
583 digest_algorithm = malloc(digestheader->avp_value->os.len + 1);
584 memcpy(digest_algorithm, digestheader->avp_value->os.data,
585 digestheader->avp_value->os.len);
586 digest_algorithm[digestheader->avp_value->os.len]='\0';
587 TRACE_DEBUG(FULL,"Element:*%s*",digest_algorithm);
588 }
589 }
590 else
591 digest_algorithm=NULL;
592 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
593 if(a2!=NULL)
594 {
595 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
596 if(digestheader!=NULL)
597 {
598 digest_cnonce = malloc(digestheader->avp_value->os.len + 1);
599 memcpy(digest_cnonce, digestheader->avp_value->os.data,
600 digestheader->avp_value->os.len);
601 digest_cnonce[digestheader->avp_value->os.len]='\0';
602 TRACE_DEBUG(FULL,"Element:*%s*",digest_cnonce);
603 }
604 }
605 else
606 digest_cnonce="";
607 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce_Count, &a2 ));
608 if(a2!=NULL)
609 {
610 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
611 if(digestheader!=NULL)
612 {
613 digest_noncecount = malloc(digestheader->avp_value->os.len + 1);
614 memcpy(digest_noncecount, digestheader->avp_value->os.data,
615 digestheader->avp_value->os.len);
616 digest_noncecount[digestheader->avp_value->os.len]='\0';
617 TRACE_DEBUG(FULL,"Element:*%s*",digest_noncecount);
618 }
619 }
620 else
621 digest_noncecount="";
622 CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Username, &a2 ));
623 if(a2!=NULL)
624 {
625 CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader ) );
626 if(digestheader!=NULL)
627 {
628 digest_username = malloc(digestheader->avp_value->os.len + 1);
629 memcpy(digest_username, digestheader->avp_value->os.data,
630 digestheader->avp_value->os.len);
631 digest_username[digestheader->avp_value->os.len]='\0';
632 TRACE_DEBUG(FULL,"Element:*%s*",digest_username);
633 }
634 }
635 //TODO: replace by authentication function
636
637 HASHHEX HA1;
638 HASHHEX HA2 = "";
639 HASHHEX response, responseauth;
640
641
642 DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1);
643
644 DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response);
645
646
647 // We check that the Digest-Response is the same (UA, Diameter)
648 if(strcmp(response,digest_response)!=0)
649 {
650 TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
651 TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
652 TRACE_DEBUG(INFO,"Digest-Response does not match!");
653 result="DIAMETER_UNABLE_TO_COMPLY";
654 free(digest_algorithm);
655 free(digest_cnonce);
656 free(digest_nonce);
657 free(digest_noncecount);
658 free(digest_method);
659 free(digest_username);
660 free(digest_uri);
661 free(digest_qop);
662 free(digest_response);
663 free(digest_realm);
664 free(storednonce->nonce);
665 free(storednonce);
666 if(username!=NULL)
667 free(username);
668 goto out;
669
670 }
671 //We calculate Digest_Response_Auth
672 DigestCalcResponseAuth(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, responseauth);
673
674 TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
675 TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
676 if(strcmp(digest_qop,"auth-int")==0)
677 {
678 //Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'.
679 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) );
680 val.os.data=HA1;
681 val.os.len=HASHHEXLEN+1;
682 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
683 CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
684 }
685 else
686 {
687 //Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'.
688 CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) );
689 val.os.data=responseauth;
690 val.os.len=DIGEST_LEN*2;
691 CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
692 CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
693 }
694 free(digest_algorithm);
695 free(digest_cnonce);
696 free(digest_nonce);
697 free(digest_noncecount);
698 free(digest_method);
699 free(digest_username);
700 free(digest_uri);
701 free(digest_qop);
702 free(digest_response);
703 free(digest_realm);
704 free(storednonce->nonce);
705 free(storednonce);
706
707 number_of_auth_items++;
708 }
709
710
711 //We add SIP Authentication-Info to Auth Data Item
712 CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthentication ) );
713 //We add Auth Data Item to Answer
714 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
715
716
717 if(username!=NULL && authenticationpending)
718 {
719 //We clear the flag "authentication pending"
720 querylen=SQL_CLEARFLAG_LEN + usernamelen;
721 query = malloc(querylen+2);
722 snprintf(query, querylen+1, SQL_CLEARFLAG, username);
723
724 //We make the query
725 request_mysql(query);
726
727 free(query);
728 }
729
730 if(sipurinotstored)
731 result="DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED";
732 else
733 result="DIAMETER_SUCCESS";
734 found_cnonce=0;
735 }
736 }
737 }
738 else
739 TRACE_DEBUG(INFO,"No auth data items!");
740 }
741 //Add SIP_Number_Auth_Items AVP
742 {
743 CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Number_Auth_Items, 0, &avp ) );
744 val.i32 = number_of_auth_items;
745 CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
746 CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
747 }
748
749
750 }
751 else
752 {
753 TRACE_DEBUG(INFO,"We only support DIGEST for now, unable to comply");
754 result="DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED";
755 if(username!=NULL)
756 free(username);
757 goto out;
758 }
759 }
760 }
761 else
762 {
763 //TODO: remove this because Number_Auth_Items is not compulsory
764 TRACE_DEBUG(FULL,"Number-Auth-Items is not included.");
765 result="DIAMETER_UNABLE_TO_COMPLY";
766 if(username!=NULL)
767 free(username);
768 goto out;
769 }
770
771 if(username!=NULL)
772 free(username);
773
774
775out:
776 // Set the Origin-Host, Origin-Realm, Result-Code AVPs
777 CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
778
779
780 // Send the answer
781 CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
782
783*/
784 return 0;
785}
786