registration.c

Go to the documentation of this file.
00001 /*
00002  * $Id: registration.c 582 2008-09-05 16:15:51Z vingarzan $
00003  *  
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * It has to be noted that this Open Source IMS Core System is not 
00026  * intended to become or act as a product in a commercial context! Its 
00027  * sole purpose is to provide an IMS core reference implementation for 
00028  * IMS technology testing and IMS application prototyping for research 
00029  * purposes, typically performed in IMS test-beds.
00030  * 
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being 
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this 
00035  * fact and have to agree to check out carefully before installing, 
00036  * using and extending the Open Source IMS Core System, if related 
00037  * patents and licences may become applicable to the intended usage 
00038  * context.  
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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     //int i;
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 //      for(i=0;i<ainfo->ai_addrlen;i++)
00466 //          LOG(L_CRIT,">> %2d. \t %3d \t %.02x\n",i,ainfo->ai_addr->sa_data[i],ainfo->ai_addr->sa_data[i]);
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     /* First check the parameters */
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     /* check for Early-IMS case */
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             /* if match, return authorized */
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                 /* try and do MAR */
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                     /* on fail, return not authorized */
00566 //                  if (p && p->early_ims_ip.s){
00567 //                      shm_free(p->early_ims_ip.s);
00568 //                      p->early_ims_ip.s=0;p->early_ims_ip.len=0;
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     /* NASS-Bundled */  
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                 /* try and do MAR */
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                     /* on fail, return not authorized */
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 //          LOG(L_CRIT,"A1: %.*s:%.*s:%.*s\n",private_identity.len,private_identity.s,
00687 //              realm.len,realm.s,av->authorization.len,av->authorization.s);
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,/*av->authorization.len,av->authorization.s,*/32,expected,32,ha1);
00698             break;      
00699         case AUTH_DIGEST:
00700         case AUTH_HTTP_DIGEST_MD5:
00701 //          LOG(L_CRIT,"A1: %.*s:%.*s:%.*s\n",private_identity.len,private_identity.s,
00702 //              realm.len,realm.s,av->authorization.len,av->authorization.s);
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,/*av->authorization.len,av->authorization.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;/* first mistake, you're out! (but maybe it's synchronization) */
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 //  str algo={0,0};
00756     int algo_type;
00757     
00758     LOG(L_DBG,"DBG:"M_NAME":S_challenge: Challenging the REGISTER...\n");
00759 
00760     /* First check the parameters */
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     /* get the private_identity */
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     /* get the public_identity */
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     /* get the requested algorithm */
00788 //  algo = cscf_get_algorithm(msg,realm);
00789 //  if (algo.len==0)
00790 //      algo = registration_default_algorithm_s;
00791 //  algo_type = get_algorithm_type(algo);
00792     algo_type = registration_default_algorithm_type;    
00793     
00794     /* check if it is a synchronization request */
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         /* if synchronization - force MAR - if MAR ok, old avs will be droped*/
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     /* loop because some other process might steal the auth_vector that we just retrieved */
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         /* do sync just once */
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     //S_REGISTER_reply(msg,401,MSG_401_CHALLENGE);
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             /* AKA */
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             /* ETSI HTTP_DIGEST MD5 */
00902             /* this one continues into the next one */          
00903         case AUTH_DIGEST:
00904             /* Cable-Labs MD5 */
00905             /* this one continues into the next one */          
00906         case AUTH_MD5:
00907             /* FOKUS MD5 */
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         //TODO - add the warning code 99 in the reply   
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     /* if HSS accepted the synchronization, drop old auth vectors */
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