00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00057 #include "registration.h"
00058
00059 #include "../tm/tm_load.h"
00060 #include "../cdp/cdp_load.h"
00061 #include "sip.h"
00062 #include "cx.h"
00063 #include "cx_avp.h"
00064 #include "conversion.h"
00065 #include "registrar.h"
00066 #include "sip_messages.h"
00067 #include "rfc2617.h"
00068 #include "s_persistency.h"
00069 #include "ims_pm.h"
00070
00071 extern struct tm_binds tmb;
00072 extern struct cdp_binds cdpb;
00074 unsigned char registration_default_algorithm_type;
00075 extern int registration_disable_early_ims;
00076 extern int registration_disable_nass_bundled;
00078 extern str scscf_name_str;
00079 extern str scscf_service_route;
00081 extern int auth_data_hash_size;
00082 extern int auth_vector_timeout;
00083 extern int auth_data_timeout;
00084 extern int av_request_at_once;
00085 extern int av_request_at_sync;
00087 extern str registration_qop_str;
00089 str algorithm_types[] = {
00090 {"unknown",7},
00091 {"AKAv1-MD5",9},
00092 {"AKAv2-MD5",9},
00093 {"Early-IMS",9},
00094 {"MD5",3},
00095 {"CableLabs-Digest",16},
00096 {"TISPAN-HTTP_DIGEST_MD5",22},
00097 {"NASS-Bundled",12},
00098 {0,0}
00099 };
00100
00101 str auth_scheme_types[] = {
00102 {"unknown",7},
00103 {"Digest-AKAv1-MD5",16},
00104 {"Digest-AKAv2-MD5",16},
00105 {"Early-IMS-Security",18},
00106 {"Digest-MD5",10},
00107 {"Digest",6},
00108 {"HTTP_DIGEST_MD5",15},
00109 {"NASS-Bundled",12},
00110 {0,0}
00111 };
00112
00113 #define get_param(src,name,dst) \
00114 {\
00115 int i,j;\
00116 (dst).s=0;(dst).len=0;\
00117 for(i=0;i<(src).len-(name).len;i++)\
00118 if (strncasecmp((src).s+i,(name).s,(name).len)==0 &&\
00119 ((src).s[i-1]==' ' ||(src).s[i-1]==';'||(src).s[i-1]=='\t')){\
00120 j=i+(name).len;\
00121 (dst).s = (src).s+j;\
00122 (dst).len = 0;\
00123 while(j<(src).len && (src).s[j]!=','&& (src).s[j]!=' '&& (src).s[j]!='\t'&& (src).s[j]!=';') \
00124 j++; \
00125 (dst).len = j-i-(name).len;\
00126 break;\
00127 } \
00128 }
00129
00135 unsigned char get_algorithm_type(str algorithm)
00136 {
00137 int i;
00138 for(i=0;algorithm_types[i].len>0;i++)
00139 if (algorithm_types[i].len == algorithm.len &&
00140 strncasecmp(algorithm_types[i].s,algorithm.s,algorithm.len)==0)
00141 return i;
00142 return AUTH_UNKNOWN;
00143 }
00144
00150 unsigned char get_auth_scheme_type(str scheme)
00151 {
00152 int i;
00153 for(i=0;auth_scheme_types[i].len>0;i++)
00154 if (auth_scheme_types[i].len == scheme.len &&
00155 strncasecmp(auth_scheme_types[i].s,scheme.s,scheme.len)==0)
00156 return i;
00157 return AUTH_UNKNOWN;
00158 }
00159
00160
00161
00169 int S_add_path_service_routes(struct sip_msg *msg,char *str1,char *str2 )
00170 {
00171 struct hdr_field *h;
00172 str t={0,0};
00173 if (parse_headers(msg,HDR_EOH_F,0)<0){
00174 LOG(L_ERR,"ERR:"M_NAME":S_add_path_service_routes: Error parsing headers\n");
00175 return CSCF_RETURN_FALSE;
00176 }
00177 h = msg->headers;
00178 while(h){
00179 if (h->name.len == 4 &&
00180 strncasecmp(h->name.s,"Path",4)==0)
00181 {
00182 t.s = h->name.s;
00183 t.len = h->len;
00184 if (!cscf_add_header_rpl(msg,&(t))) return CSCF_RETURN_FALSE;
00185 }
00186 h = h->next;
00187 }
00188
00189 if (!cscf_add_header_rpl(msg,&scscf_service_route)) return CSCF_RETURN_FALSE;
00190
00191 return CSCF_RETURN_TRUE;
00192 }
00193
00194 static str s_allow_s={"Allow: ",7};
00195 static str s_allow_e={"\r\n",2};
00203 int S_add_allow(struct sip_msg *msg,char *str1,char *str2 )
00204 {
00205 str hdr={0,0};
00206 str allow;
00207 allow.s = str1;
00208 allow.len = strlen(str1);
00209
00210 hdr.len = s_allow_s.len+allow.len+s_allow_e.len;
00211 hdr.s = pkg_malloc(hdr.len);
00212 if (!hdr.s){
00213 LOG(L_ERR,"ERR:"M_NAME":S_add_allow: Error allocating %d bytes\n",hdr.len);
00214 return CSCF_RETURN_FALSE;
00215 }
00216 hdr.len = 0;
00217 STR_APPEND(hdr,s_allow_s);
00218 STR_APPEND(hdr,allow);
00219 STR_APPEND(hdr,s_allow_e);
00220
00221 if (!cscf_add_header_rpl(msg,&hdr)) {
00222 if (hdr.s) pkg_free(hdr.s);
00223 return CSCF_RETURN_FALSE;
00224 }
00225
00226 if (hdr.s) pkg_free(hdr.s);
00227 return CSCF_RETURN_TRUE;
00228 }
00229
00230 static str s_service_route_s = {"Service-Route: <",16};
00231 static str s_service_route_e = {";lr>\r\n",6};
00239 int S_add_service_route(struct sip_msg *msg,char *str1,char *str2 )
00240 {
00241 str sr={0,0};
00242 str uri;
00243 uri.s = str1;
00244 uri.len = strlen(str1);
00245
00246 sr.len = s_service_route_s.len+uri.len+s_service_route_e.len;
00247 sr.s = pkg_malloc(sr.len);
00248 if (!sr.s){
00249 LOG(L_ERR,"ERR:"M_NAME":S_add_service_route: Error allocating %d bytes\n",sr.len);
00250 return CSCF_RETURN_FALSE;
00251 }
00252 sr.len = 0;
00253 STR_APPEND(sr,s_service_route_s);
00254 STR_APPEND(sr,uri);
00255 STR_APPEND(sr,s_service_route_e);
00256
00257 if (!cscf_add_header_rpl(msg,&sr)) {
00258 if (sr.s) pkg_free(sr.s);
00259 return CSCF_RETURN_FALSE;
00260 }
00261
00262 if (sr.s) pkg_free(sr.s);
00263 return CSCF_RETURN_TRUE;
00264 }
00265
00266 static str s_p_charging_function_addresses_s = {"P-Charging-Function-Addresses:",30};
00267 static str s_p_charging_function_addresses_1 = {" ccf=",5};
00268 static str s_p_charging_function_addresses_2 = {" ecf=",5};
00269 static str s_p_charging_function_addresses_3 = {";",1};
00270 static str s_p_charging_function_addresses_e = {"\r\n",2};
00278 int S_add_p_charging_function_addresses(struct sip_msg *msg,char *str1,char *str2 )
00279 {
00280 str hdr={0,0};
00281 int ccnt=0,ecnt=0;
00282 str public_identity;
00283 r_public *p=0;
00284 int ret = CSCF_RETURN_FALSE;
00285
00286 public_identity = cscf_get_public_identity(msg);
00287 LOG(L_INFO,"DBG:"M_NAME":S_add_p_charging_function_addresses: Looking for <%.*s>\n",public_identity.len,public_identity.s);
00288 p = get_r_public(public_identity);
00289
00290 if (!p) {
00291 LOG(L_INFO,"DBG:"M_NAME":S_add_p_charging_function_addresses: No entry in registrar for <%.*s>\n",public_identity.len,public_identity.s);
00292 goto done;
00293 }
00294
00295 ccnt = (p->ccf1.len!=0) + (p->ccf2.len!=0);
00296 ecnt = (p->ecf1.len!=0) + (p->ecf2.len!=0);
00297 if (!(ccnt+ecnt)){
00298 LOG(L_INFO,"DBG:"M_NAME":S_add_p_charging_function_addresses: <%.*s> has no charging functions storred \n",public_identity.len,public_identity.s);
00299 goto done;
00300 }
00301
00302 hdr.len = s_p_charging_function_addresses_s.len +
00303 s_p_charging_function_addresses_1.len * ccnt + p->ccf1.len + p->ccf2.len +
00304 s_p_charging_function_addresses_2.len * ecnt + p->ecf1.len + p->ecf2.len +
00305 s_p_charging_function_addresses_3.len * (ccnt+ecnt) +
00306 s_p_charging_function_addresses_e.len;
00307
00308 hdr.s = pkg_malloc(hdr.len);
00309 if (!hdr.s){
00310 LOG(L_ERR,"ERR:"M_NAME":S_add_p_charging_function_addresses: Error allocating %d bytes\n",hdr.len);
00311 goto done;
00312 }
00313 hdr.len = 0;
00314 STR_APPEND(hdr,s_p_charging_function_addresses_s);
00315 ccnt = 0;
00316 if (p->ccf1.len) {
00317 STR_APPEND(hdr,s_p_charging_function_addresses_1);
00318 STR_APPEND(hdr,p->ccf1);
00319 ccnt++;
00320 }
00321 if (p->ccf2.len) {
00322 if (ccnt) STR_APPEND(hdr,s_p_charging_function_addresses_3);
00323 STR_APPEND(hdr,s_p_charging_function_addresses_1);
00324 STR_APPEND(hdr,p->ccf2);
00325 ccnt++;
00326 }
00327 if (p->ecf1.len) {
00328 if (ccnt) STR_APPEND(hdr,s_p_charging_function_addresses_3);
00329 STR_APPEND(hdr,s_p_charging_function_addresses_2);
00330 STR_APPEND(hdr,p->ecf1);
00331 ccnt++;
00332 }
00333 if (p->ecf2.len) {
00334 if (ccnt) STR_APPEND(hdr,s_p_charging_function_addresses_3);
00335 STR_APPEND(hdr,s_p_charging_function_addresses_2);
00336 STR_APPEND(hdr,p->ecf2);
00337 ccnt++;
00338 }
00339
00340 STR_APPEND(hdr,s_p_charging_function_addresses_e);
00341
00342 if (!cscf_add_header_rpl(msg,&hdr)) {
00343 LOG(L_ERR,"ERR:"M_NAME":S_add_p_charging_function_addresses: Error adding header <%.*s>\n",hdr.len,hdr.s);
00344 goto done;
00345 }
00346 ret = CSCF_RETURN_TRUE;
00347
00348 done:
00349 if (hdr.s) pkg_free(hdr.s);
00350 if (p) r_unlock(p->hash);
00351 return ret;
00352 }
00353
00354
00363 int S_REGISTER_reply(struct sip_msg *msg, int code, char *text)
00364 {
00365 struct hdr_field *h;
00366 str t={0,0};
00367 if (parse_headers(msg,HDR_EOH_F,0)<0){
00368 LOG(L_ERR,"ERR:"M_NAME":S_REGISTER_reply: Error parsing headers\n");
00369 return -1;
00370 }
00371 h = msg->headers;
00372 while(h){
00373 if (h->name.len == 4 &&
00374 strncasecmp(h->name.s,"Path",4)==0)
00375 {
00376 t.s = h->name.s;
00377 t.len = h->len;
00378 cscf_add_header_rpl(msg,&(t));
00379 }
00380 h = h->next;
00381 }
00382
00383 if (code==200){
00384 cscf_add_header_rpl(msg,&scscf_service_route);
00385 }
00386 return cscf_reply_transactional(msg,code,text);
00387 }
00388
00396 int S_check_visited_network_id(struct sip_msg *msg,char *str1,char *str2 )
00397 {
00398 int ret = CSCF_RETURN_FALSE;
00399 char c;
00400 str v={0,0};
00401 regmatch_t pmatch;
00402 struct hdr_field *hdr;
00403 v = cscf_get_visited_network_id(msg,&hdr);
00404 c = v.s[v.len];
00405 v.s[v.len] = 0;
00406 if (regexec(((fparam_t*)str1)->v.regex, v.s, 1, &pmatch, 0)==0) ret = CSCF_RETURN_TRUE;
00407 v.s[v.len] = c;
00408 return ret;
00409 }
00410
00418 int S_is_integrity_protected(struct sip_msg *msg,char *str1,char *str2 )
00419 {
00420 str realm={0,0};
00421 int ret=0;
00422
00423 realm.s = str1;realm.len = strlen(str1);
00424 if (!realm.len) {
00425 LOG(L_ERR,"ERR:"M_NAME":S_is_integrity_protected: No realm found\n");
00426 return CSCF_RETURN_BREAK;
00427 }
00428 if (cscf_get_integrity_protected(msg,realm)) ret = 1;
00429
00430 LOG(L_DBG,"DBG:"M_NAME":S_is_integrity_protected: returns %d\n",ret);
00431
00432 return ret?CSCF_RETURN_TRUE:CSCF_RETURN_FALSE;
00433 }
00434
00441 static int matchesEarlyIMSIP(str ip,str sent_by)
00442 {
00443 struct addrinfo *ainfo,*res=0,hints;
00444 int error;
00445 char c;
00446
00447
00448 memset (&hints, 0, sizeof(hints));
00449
00450 c = sent_by.s[sent_by.len];
00451 sent_by.s[sent_by.len]=0;
00452
00453 error = getaddrinfo(sent_by.s, 0, &hints, &res);
00454
00455 sent_by.s[sent_by.len]=c;
00456
00457 if (error!=0){
00458 LOG(L_ERR,"ERROR:matchesEarlyIMSIP(): Error on getaddrinfo for sent_by = <%.*s> >%s\n",
00459 sent_by.len,sent_by.s,gai_strerror(error));
00460 goto error;
00461 }
00462
00463 for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
00464 {
00465
00466
00467 switch (ainfo->ai_family){
00468 case AF_INET:
00469 if (ip.len==4&&memcmp(ainfo->ai_addr->sa_data+2,ip.s,4)==0)
00470 goto success;
00471 break;
00472 case AF_INET6:
00473 if (ip.len==16&&memcmp(ainfo->ai_addr->sa_data+6,ip.s,16)==0)
00474 goto success;
00475 break;
00476 default:
00477 LOG(L_ERR,"ERROR:matchesEarlyIMSIP(): Invalid ai_family %d\n",ainfo->ai_family);
00478 }
00479 }
00480 error:
00481 if (res) freeaddrinfo(res);
00482 return 0;
00483 success:
00484 if (res) freeaddrinfo(res);
00485 return 1;
00486 }
00487
00488
00489 char *zero_padded="00000000000000000000000000000000";
00490 static str empty_s={0,0};
00491 static str cell_id = {"dsl-location=", 13};
00499 int S_is_authorized(struct sip_msg *msg,char *str1,char *str2 )
00500 {
00501 int ret=CSCF_RETURN_FALSE;
00502 unsigned int aud_hash=0;
00503 str realm;
00504 str private_identity,public_identity;
00505 str nonce,response16,nc,cnonce,qop_str={0,0},body;
00506 enum qop_type qop=QOP_UNSPEC;
00507 str uri={0,0};
00508 HASHHEX expected,ha1,hbody;
00509 int expected_len=32;
00510 auth_vector *av=0;
00511 r_public *p=0;
00512
00513
00514 LOG(L_DBG,"DBG:"M_NAME":S_is_authorized: Checking if REGISTER is authorized...\n");
00515
00516
00517 if (msg->first_line.type!=SIP_REQUEST||
00518 msg->first_line.u.request.method.len!=8||
00519 memcmp(msg->first_line.u.request.method.s,"REGISTER",8)!=0)
00520 {
00521 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: This message is not a REGISTER request\n");
00522 goto error;
00523 }
00524 realm.s = str1;realm.len = strlen(str1);
00525 if (!realm.len) {
00526 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: No realm found\n");
00527 return CSCF_RETURN_BREAK;
00528 }
00529
00530 private_identity = cscf_get_private_identity(msg,realm);
00531 if (!private_identity.len) {
00532 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: private identity missing\n");
00533 return ret;
00534 }
00535
00536 public_identity = cscf_get_public_identity(msg);
00537 if (!public_identity.len) {
00538 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: public identity missing\n");
00539 return ret;
00540 }
00541
00542
00543 if (!registration_disable_early_ims && !msg->authorization){
00544 str sent_by={0,0},received={0,0};
00545
00546 sent_by = cscf_get_last_via_sent_by(msg);
00547 if (sent_by.len){
00548 ret = CSCF_RETURN_FALSE;
00549
00550 LOG(L_INFO,"DBG:"M_NAME":S_is_authorized: Possible Early-IMS identified\n");
00551 received = cscf_get_last_via_received(msg);
00552 if (received.len) sent_by=received;
00553
00554 p = get_r_public(public_identity);
00555
00556 if (p && p->early_ims_ip.len!=0 &&
00557 matchesEarlyIMSIP(p->early_ims_ip,sent_by)){
00558 ret = CSCF_RETURN_TRUE;
00559 goto done_early_ims;
00560 }
00561 do {
00562
00563 if (!S_MAR(msg,public_identity,private_identity,1,
00564 auth_scheme_types[AUTH_EARLY_IMS],empty_s,empty_s,scscf_name_str,realm)){
00565
00566
00567
00568
00569
00570 goto done_early_ims;
00571 }
00572 av = get_auth_vector(private_identity,public_identity,AUTH_VECTOR_UNUSED,0,&aud_hash);
00573 } while(!av);
00574 switch (av->authorization.len){
00575 case 4:
00576 LOG(L_ERR,"DBG:"M_NAME":S_is_authorized: IP address in MAA was <%d.%d.%d.%d>\n",
00577 (unsigned char)av->authorization.s[0],
00578 (unsigned char)av->authorization.s[1],
00579 (unsigned char)av->authorization.s[2],
00580 (unsigned char)av->authorization.s[3]);
00581 break;
00582 case 16:
00583 LOG(L_ERR,"DBG:"M_NAME":S_is_authorized: IP address in MAA was <%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x>\n",
00584 (unsigned char)av->authorization.s[0],
00585 (unsigned char)av->authorization.s[1],
00586 (unsigned char)av->authorization.s[2],
00587 (unsigned char)av->authorization.s[3],
00588 (unsigned char)av->authorization.s[4],
00589 (unsigned char)av->authorization.s[5],
00590 (unsigned char)av->authorization.s[6],
00591 (unsigned char)av->authorization.s[7],
00592 (unsigned char)av->authorization.s[8],
00593 (unsigned char)av->authorization.s[9],
00594 (unsigned char)av->authorization.s[10],
00595 (unsigned char)av->authorization.s[11],
00596 (unsigned char)av->authorization.s[12],
00597 (unsigned char)av->authorization.s[13],
00598 (unsigned char)av->authorization.s[14],
00599 (unsigned char)av->authorization.s[15]
00600 );
00601 break;
00602 }
00603 if (av->authorization.len &&
00604 matchesEarlyIMSIP(av->authorization,sent_by)){
00605 ret = CSCF_RETURN_TRUE;
00606 if (p) STR_SHM_DUP(p->early_ims_ip,av->authorization,"IP Early IMS");
00607 }else
00608 ret = CSCF_RETURN_FALSE;
00609 done_early_ims:
00610 if (p) r_unlock(p->hash);
00611 if (av) {
00612 av->status = AUTH_VECTOR_USELESS;
00613 auth_data_unlock(aud_hash);
00614 }
00615 return ret;
00616 }
00617 }
00618
00619 if (!registration_disable_nass_bundled && !msg->authorization){
00620 str access_network_info={0,0};
00621 str dsl_location = {0,0};
00622 access_network_info = cscf_get_access_network_info(msg, 0);
00623 if (access_network_info.len)
00624 {
00625 get_param(access_network_info, cell_id, dsl_location);
00626 }
00627 if (dsl_location.len){
00628 int ret = CSCF_RETURN_FALSE;
00629 LOG(L_ERR,"DBG:"M_NAME":S_is_authorized: Possible NASS-Bundled Authentication identified\n");
00630 do {
00631
00632 if (!S_MAR(msg,public_identity,private_identity,1,
00633 auth_scheme_types[AUTH_NASS_BUNDLED],empty_s,empty_s,scscf_name_str,realm)){
00634
00635 goto done_nass_bundled;
00636 }
00637 av = get_auth_vector(private_identity,public_identity,AUTH_VECTOR_UNUSED,0,&aud_hash);
00638 } while(!av);
00639 LOG(L_DBG,"DBG:"M_NAME":S_is_authorized: HSS said : <%.*s>, P sent : <%.*s>\n",
00640 av->authorization.len,av->authorization.s, dsl_location.len, dsl_location.s);
00641 if (av->authorization.len == dsl_location.len &&
00642 strncasecmp(av->authorization.s, dsl_location.s, dsl_location.len)==0){
00643 ret = CSCF_RETURN_TRUE;
00644 }else
00645 ret = CSCF_RETURN_FALSE;
00646 done_nass_bundled:
00647 if (av) {
00648 av->status = AUTH_VECTOR_USELESS;
00649 auth_data_unlock(aud_hash);
00650 }
00651 return ret;
00652 }
00653 }
00654
00655 if (!cscf_get_nonce_response(msg,realm,&nonce,&response16,&qop,&qop_str,&nc,&cnonce,&uri)||
00656 !nonce.len || !response16.len)
00657 {
00658 LOG(L_DBG,"DBG:"M_NAME":S_is_authorized: Nonce or reponse missing\n");
00659 return ret;
00660 }
00661
00662 if (qop==QOP_AUTHINT){
00663 body = cscf_get_body(msg);
00664 calc_H(&body,hbody);
00665 }
00666
00667 av = get_auth_vector(private_identity,public_identity,AUTH_VECTOR_SENT,&nonce,&aud_hash);
00668
00669 LOG(L_INFO,"DBG:"M_NAME":S_is_authorized: uri=%.*s nonce=%.*s response=%.*s qop=%.*s nc=%.*s cnonce=%.*s hbody=%.*s\n",
00670 uri.len,uri.s,
00671 nonce.len,nonce.s,
00672 response16.len,response16.s,
00673 qop_str.len,qop_str.s,
00674 nc.len,nc.s,
00675 cnonce.len,cnonce.s,
00676 32,hbody);
00677
00678 if (!av) {
00679 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: no matching auth vector found - maybe timer expired\n");
00680 return ret;
00681 }
00682 switch (av->type){
00683 case AUTH_AKAV1_MD5:
00684 case AUTH_AKAV2_MD5:
00685 case AUTH_MD5:
00686
00687
00688
00689 calc_HA1(HA_MD5,&private_identity,&realm,&(av->authorization),&(av->authenticate),&cnonce,ha1);
00690 calc_response(ha1,&(av->authenticate),
00691 &nc,
00692 &cnonce,
00693 &qop_str,
00694 qop==QOP_AUTHINT,
00695 &msg->first_line.u.request.method,&uri,hbody,expected);
00696 LOG(L_INFO,"DBG:"M_NAME":S_is_authorized: UE said: %.*s and we expect %.*s ha1 %.*s\n",
00697 response16.len,response16.s,32,expected,32,ha1);
00698 break;
00699 case AUTH_DIGEST:
00700 case AUTH_HTTP_DIGEST_MD5:
00701
00702
00703
00704 memcpy(ha1,av->authorization.s,HASHHEXLEN);
00705 calc_response(ha1,&(av->authenticate),
00706 &nc,
00707 &cnonce,
00708 &qop_str,
00709 qop==QOP_AUTHINT,
00710 &msg->first_line.u.request.method,&uri,hbody,expected);
00711 LOG(L_INFO,"DBG:"M_NAME":S_is_authorized: UE said: %.*s and we expect %.*s ha1 %.*s\n",
00712 response16.len,response16.s,32,expected,32,ha1);
00713 break;
00714 default:
00715 LOG(L_ERR,"ERR:"M_NAME":S_is_authorized: algorithm %.*s is not handled.\n",
00716 algorithm_types[av->type].len,algorithm_types[av->type].s);
00717 goto error;
00718 }
00719
00720 if (response16.len==expected_len && strncasecmp(response16.s,expected,response16.len)==0){
00721 av->status = AUTH_VECTOR_USELESS;
00722 ret = CSCF_RETURN_TRUE;
00723 }else {
00724 av->status = AUTH_VECTOR_USED;
00725 LOG(L_DBG,"DBG:"M_NAME":S_is_authorized: UE said: %.*s, but we have %.*s and expect %.*s\n",
00726 response16.len,response16.s,av->authorization.len,av->authorization.s,32,expected);
00727 }
00728
00729
00730 auth_data_unlock(aud_hash);
00731 return ret;
00732 error:
00733 out_of_memory:
00734 if (p) r_unlock(p->hash);
00735 if (av) {
00736 auth_data_unlock(aud_hash);
00737 }
00738 ret = CSCF_RETURN_ERROR;
00739 return ret;
00740 }
00741
00749 int S_challenge(struct sip_msg *msg,char *str1,char *str2 )
00750 {
00751 int ret=CSCF_RETURN_FALSE;
00752 unsigned int aud_hash;
00753 str realm,private_identity,public_identity,auts={0,0},nonce={0,0};
00754 auth_vector *av=0;
00755
00756 int algo_type;
00757
00758 LOG(L_DBG,"DBG:"M_NAME":S_challenge: Challenging the REGISTER...\n");
00759
00760
00761 if (msg->first_line.type!=SIP_REQUEST||
00762 msg->first_line.u.request.method.len!=8||
00763 memcmp(msg->first_line.u.request.method.s,"REGISTER",8)!=0)
00764 {
00765 LOG(L_ERR,"ERR:"M_NAME":S_challenge: This message is not a REGISTER request\n");
00766 goto error;
00767 }
00768 realm.s = str1;realm.len = strlen(str1);
00769 if (!realm.len) {
00770 LOG(L_ERR,"ERR:"M_NAME":S_challenge: No realm found\n");
00771 return CSCF_RETURN_BREAK;
00772 }
00773
00774 private_identity = cscf_get_private_identity(msg,realm);
00775 if (!private_identity.len){
00776 LOG(L_ERR,"ERR:"M_NAME":S_challenge: No private identity specified (Authorization: username)\n");
00777 S_REGISTER_reply(msg,403,MSG_403_NO_PRIVATE);
00778 goto abort;
00779 }
00780
00781 public_identity = cscf_get_public_identity(msg);
00782 if (!public_identity.len){
00783 LOG(L_ERR,"ERR:"M_NAME":S_challenge: No public identity specified (To:)\n");
00784 S_REGISTER_reply(msg,403,MSG_403_NO_PUBLIC);
00785 goto abort;
00786 }
00787
00788
00789
00790
00791
00792 algo_type = registration_default_algorithm_type;
00793
00794
00795 auts = cscf_get_auts(msg,realm);
00796 if (auts.len){
00797 LOG(L_DBG,"DBG:"M_NAME":S_challenge: Syncronization requested <%.*s>\n",
00798 auts.len,auts.s);
00799
00800 nonce = cscf_get_nonce(msg,realm);
00801 if (nonce.len==0){
00802 LOG(L_DBG,"L_DBG:"M_NAME":S_challenge: Nonce not found (Authorization: nonce)\n");
00803 S_REGISTER_reply(msg,403,MSG_403_NO_NONCE);
00804 goto abort;
00805 }
00806 av = get_auth_vector(private_identity,public_identity,AUTH_VECTOR_USED,&nonce,&aud_hash);
00807 if (!av)
00808 av = get_auth_vector(private_identity,public_identity,AUTH_VECTOR_SENT,&nonce,&aud_hash);
00809
00810 if (!av){
00811 LOG(L_ERR,"DBG:"M_NAME":S_challenge: Nonce not regonized as sent, no sync!\n");
00812 auts.len = 0; auts.s=0;
00813 }else{
00814 av->status = AUTH_VECTOR_USELESS;
00815 auth_data_unlock(aud_hash);
00816 av =0;
00817 }
00818
00819 S_MAR(msg,public_identity,private_identity,av_request_at_sync,
00820 auth_scheme_types[algo_type],nonce,auts,scscf_name_str,realm);
00821 }
00822
00823
00824 while(!(av=get_auth_vector(private_identity,public_identity,AUTH_VECTOR_UNUSED,0,&aud_hash))){
00825 if (!S_MAR(msg,public_identity,private_identity,av_request_at_once,
00826 auth_scheme_types[algo_type],nonce,auts,scscf_name_str,realm)) break;
00827
00828 auts.len=0;auts.s=0;
00829 }
00830
00831 if (!av){
00832 LOG(L_ERR,"ERR:"M_NAME":S_challenge: Error retrieving an auth vector\n");
00833 goto abort;
00834 }
00835
00836 if (!pack_challenge(msg,realm,av)){
00837 S_REGISTER_reply(msg,500,MSG_500_PACK_AV);
00838 auth_data_unlock(aud_hash);
00839 goto error;
00840 }
00841 start_reg_await_timer(av);
00842
00843 auth_data_unlock(aud_hash);
00844 return ret;
00845 error:
00846 ret = CSCF_RETURN_BREAK;
00847 return ret;
00848 abort:
00849 ret = CSCF_RETURN_BREAK;
00850 return ret;
00851 }
00852
00853
00854 str S_WWW_Authorization_AKA={"WWW-Authenticate: Digest realm=\"%.*s\","
00855 " nonce=\"%.*s\", algorithm=%.*s, ck=\"%.*s\", ik=\"%.*s\"%.*s\r\n",106};
00856 str S_WWW_Authorization_MD5={"WWW-Authenticate: Digest realm=\"%.*s\","
00857 " nonce=\"%.*s\", algorithm=%.*s%.*s\r\n",101};
00858
00866 int pack_challenge(struct sip_msg *msg,str realm,auth_vector *av)
00867 {
00868 str x={0,0};
00869 char ck[32],ik[32];
00870 int ck_len,ik_len;
00871 switch (av->type){
00872 case AUTH_AKAV1_MD5:
00873 case AUTH_AKAV2_MD5:
00874
00875 ck_len = bin_to_base16(av->ck.s,16,ck);
00876 ik_len = bin_to_base16(av->ik.s,16,ik);
00877 x.len = S_WWW_Authorization_AKA.len +
00878 realm.len+
00879 av->authenticate.len+
00880 algorithm_types[av->type].len+
00881 ck_len+
00882 ik_len+
00883 registration_qop_str.len;
00884 x.s = pkg_malloc(x.len);
00885 if (!x.s) {
00886 LOG(L_ERR,"ERR:"M_NAME":pack_challenge: Error allocating %d bytes\n",
00887 x.len);
00888 goto error;
00889 }
00890 sprintf(x.s,S_WWW_Authorization_AKA.s,
00891 realm.len,realm.s,
00892 av->authenticate.len,av->authenticate.s,
00893 algorithm_types[av->type].len,algorithm_types[av->type].s,
00894 ck_len,ck,
00895 ik_len,ik,
00896 registration_qop_str.len,registration_qop_str.s);
00897 x.len = strlen(x.s);
00898 break;
00899
00900 case AUTH_HTTP_DIGEST_MD5:
00901
00902
00903 case AUTH_DIGEST:
00904
00905
00906 case AUTH_MD5:
00907
00908 x.len = S_WWW_Authorization_MD5.len +
00909 realm.len+
00910 av->authenticate.len+
00911 algorithm_types[av->type].len+
00912 registration_qop_str.len;
00913 x.s = pkg_malloc(x.len);
00914 if (!x.s) {
00915 LOG(L_ERR,"ERR:"M_NAME":pack_challenge: Error allocating %d bytes\n",
00916 x.len);
00917 goto error;
00918 }
00919 sprintf(x.s,S_WWW_Authorization_MD5.s,
00920 realm.len,realm.s,
00921 av->authenticate.len,av->authenticate.s,
00922 algorithm_types[AUTH_MD5].len,algorithm_types[AUTH_MD5].s,
00923 registration_qop_str.len,registration_qop_str.s);
00924 x.len = strlen(x.s);
00925 break;
00926 default:
00927 LOG(L_CRIT,"ERR:"M_NAME":pack_challenge: not implemented for algorithm %.*s\n",
00928 algorithm_types[av->type].len,algorithm_types[av->type].s);
00929 goto error;
00930 }
00931
00932 if (cscf_add_header_rpl(msg,&x)) {
00933 pkg_free(x.s);
00934 return 1;
00935 }
00936
00937 error:
00938 if (x.s) pkg_free(x.s);
00939 return 0;
00940 }
00941
00956 int S_MAR(struct sip_msg *msg, str public_identity, str private_identity,
00957 int count,str auth_scheme,str nonce,str auts,str server_name,str realm)
00958 {
00959 AAAMessage *maa;
00960 AAA_AVP *auth_data;
00961 int rc=-1,experimental_rc=-1;
00962 auth_vector *av=0, **avlist=0;
00963 int cnt,i,j;
00964 int item_number;
00965 int is_sync=0;
00966 str authenticate={0,0},authorization={0,0},ck={0,0},ik={0,0},ip={0,0},ha1={0,0};
00967 str line_identifier = {0,0};
00968 str response_auth = {0, 0}, etsi_nonce={0,0},digest_realm={0,0};
00969 HASHHEX ha1_hex;
00970 HASHHEX result;
00971
00972 if (auts.len){
00973 authorization.s = pkg_malloc(nonce.len*3/4+auts.len*3/4+8);
00974 if (!authorization.s) goto done;
00975 authorization.len = base64_to_bin(nonce.s,nonce.len,authorization.s);
00976 authorization.len = RAND_LEN;
00977 authorization.len += base64_to_bin(auts.s,auts.len,authorization.s+authorization.len);
00978 is_sync=1;
00979 }
00980
00981 maa = Cx_MAR(msg,public_identity,private_identity,count,auth_scheme,authorization,
00982 server_name,realm);
00983
00984 if (authorization.s) pkg_free(authorization.s);
00985
00986 if (!maa){
00987
00988 S_REGISTER_reply(msg,480,MSG_480_DIAMETER_TIMEOUT);
00989 goto done;
00990 }
00991
00992 if (!Cx_get_result_code(maa,&rc)&&
00993 !Cx_get_experimental_result_code(maa,&experimental_rc))
00994 {
00995 S_REGISTER_reply(msg,480,MSG_480_DIAMETER_MISSING_AVP);
00996 goto done;
00997 }
00998
00999 switch(rc){
01000 case -1:
01001 switch(experimental_rc){
01002 case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
01003 S_REGISTER_reply(msg,403,MSG_403_USER_UNKNOWN);
01004 break;
01005 case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
01006 S_REGISTER_reply(msg,403,MSG_403_IDENTITIES_DONT_MATCH);
01007 break;
01008 case RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED:
01009 S_REGISTER_reply(msg,403,MSG_403_AUTH_SCHEME_UNSOPPORTED);
01010 break;
01011
01012 default:
01013 S_REGISTER_reply(msg,403,MSG_403_UNKOWN_EXPERIMENTAL_RC);
01014 }
01015 break;
01016
01017 case AAA_UNABLE_TO_COMPLY:
01018 S_REGISTER_reply(msg,403,MSG_403_UNABLE_TO_COMPLY);
01019 break;
01020
01021 case AAA_SUCCESS:
01022 goto success;
01023 break;
01024
01025 default:
01026 S_REGISTER_reply(msg,403,MSG_403_UNKOWN_RC);
01027 }
01028
01029 goto done;
01030
01031 success:
01032
01033
01034 if (is_sync)
01035 drop_auth_userdata(private_identity,public_identity);
01036
01037 Cx_get_sip_number_auth_items(maa,&cnt);
01038 if (!cnt) {
01039 S_REGISTER_reply(msg,403,MSG_403_NO_AUTH_DATA);
01040 goto done;
01041 }
01042 avlist = shm_malloc(sizeof(auth_vector *)*cnt);
01043 if (!avlist) {
01044