Definition in file registration.c.
#include "registration.h"
#include "../tm/tm_load.h"
#include "../cdp/cdp_load.h"
#include "sip.h"
#include "cx.h"
#include "cx_avp.h"
#include "conversion.h"
#include "registrar.h"
#include "sip_messages.h"
#include "rfc2617.h"
#include "s_persistency.h"
#include "ims_pm.h"
Go to the source code of this file.
Defines | |
| #define | get_param(src, name, dst) |
| #define | h_inc h+=v^(v>>3) |
Functions | |
| unsigned char | get_algorithm_type (str algorithm) |
| Convert the SIP Algorithm to its type. | |
| unsigned char | get_auth_scheme_type (str scheme) |
| Convert the Diameter Authorization Scheme to its type. | |
| int | S_add_path_service_routes (struct sip_msg *msg, char *str1, char *str2) |
| Copies the Path header from REGISTER request to reply, inserts the Service-Route. | |
| int | S_add_allow (struct sip_msg *msg, char *str1, char *str2) |
| Inserts an Allow header with the given value. | |
| int | S_add_service_route (struct sip_msg *msg, char *str1, char *str2) |
| Inserts a Service-Route header with the given value. | |
| int | S_add_p_charging_function_addresses (struct sip_msg *msg, char *str1, char *str2) |
| Copies the P-Charging-Function-Addresses header with the saved CF values in the registrar. | |
| int | S_REGISTER_reply (struct sip_msg *msg, int code, char *text) |
| Replies to a REGISTER and also adds the need headers Path and Service-Route are added. | |
| int | S_check_visited_network_id (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the P-Visited-Network-Id matches a regexp. | |
| int | S_is_integrity_protected (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the message is integrity protected. | |
| static int | matchesEarlyIMSIP (str ip, str sent_by) |
| Check if the sent_by ip address matches the storred ip addreses for Early-IMS. | |
| int | S_is_authorized (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the message contains a valid response to a valid challenge. | |
| int | S_challenge (struct sip_msg *msg, char *str1, char *str2) |
| Responds with a 401 Unauthorized containing the (new) challenge. | |
| int | pack_challenge (struct sip_msg *msg, str realm, auth_vector *av) |
| Adds the WWW-Authenticate header for challenge, based on the authentication vector. | |
| int | S_MAR (struct sip_msg *msg, str public_identity, str private_identity, int count, str auth_scheme, str nonce, str auts, str server_name, str realm) |
| Sends a Multimedia-Authentication-Response to retrieve some authentication vectors and maybe synchronize. | |
| void | auth_data_lock (unsigned int hash) |
| Locks the required slot of the auth_data. | |
| void | auth_data_unlock (unsigned int hash) |
| UnLocks the required slot of the auth_data. | |
| int | auth_data_init (int size) |
| Initializes the Authorization Data structures. | |
| void | auth_data_destroy () |
| Destroy the Authorization Data structures. | |
| auth_vector * | new_auth_vector (int item_number, str auth_scheme, str authenticate, str authorization, str ck, str ik) |
| Create new authorization vector. | |
| void | free_auth_vector (auth_vector *av) |
| Frees the memory taken by a authentication vector. | |
| auth_userdata * | new_auth_userdata (str private_identity, str public_identity) |
| Creates a new Authorization Userdata structure. | |
| void | free_auth_userdata (auth_userdata *aud) |
| Deallocates the auth_userdata. | |
| unsigned int | get_hash_auth (str private_identity, str public_identity) |
| Computes a hash based on the private and public identities. | |
| auth_userdata * | get_auth_userdata (str private_identity, str public_identity) |
| Retrieve the auth_userdata for a user. | |
| int | add_auth_vector (str private_identity, str public_identity, auth_vector *av) |
| Add an authentication vector to the authentication userdata storage. | |
| auth_vector * | get_auth_vector (str private_identity, str public_identity, int status, str *nonce, unsigned int *hash) |
| Retrieve an authentication vector. | |
| int | drop_auth_userdata (str private_identity, str public_identity) |
| Declares all auth vectors as useless when we do a synchronization. | |
| void | start_reg_await_timer (auth_vector *av) |
| Starts the reg_await_timer for an authentication vector. | |
| void | reg_await_timer (unsigned int ticks, void *param) |
| Timer callback for reg await timers. | |
Variables | |
| tm_binds | tmb |
| Structure with pointers to tm funcs. | |
| cdp_binds | cdpb |
| Structure with pointers to cdp funcs. | |
| unsigned char | registration_default_algorithm_type |
| fixed default algorithm for registration (if none present) | |
| int | registration_disable_early_ims |
| if to disable the Early-IMS checks | |
| int | registration_disable_nass_bundled |
| if to disable the NASS-Bundled checks | |
| str | scscf_name_str |
| fixed name of the S-CSCF | |
| str | scscf_service_route |
| the service route header | |
| int | auth_data_hash_size |
| the size of the hash table | |
| int | auth_vector_timeout |
| timeout for a sent auth vector to expire in sec | |
| int | auth_data_timeout |
| timeout for a hash entry to expire when empty in sec | |
| int | av_request_at_once |
| how many auth vectors to request in a MAR | |
| int | av_request_at_sync |
| how many auth vectors to request in a sync MAR | |
| str | registration_qop_str |
| the qop options to put in the authorization challenges | |
| str | algorithm_types [] |
| str | auth_scheme_types [] |
| static str | s_allow_s = {"Allow: ",7} |
| static str | s_allow_e = {"\r\n",2} |
| static str | s_service_route_s = {"Service-Route: <",16} |
| static str | s_service_route_e = {";lr>\r\n",6} |
| static str | s_p_charging_function_addresses_s = {"P-Charging-Function-Addresses:",30} |
| static str | s_p_charging_function_addresses_1 = {" ccf=",5} |
| static str | s_p_charging_function_addresses_2 = {" ecf=",5} |
| static str | s_p_charging_function_addresses_3 = {";",1} |
| static str | s_p_charging_function_addresses_e = {"\r\n",2} |
| char * | zero_padded = "00000000000000000000000000000000" |
| static str | empty_s = {0,0} |
| static str | cell_id = {"dsl-location=", 13} |
| str | S_WWW_Authorization_AKA |
| str | S_WWW_Authorization_MD5 |
| auth_hash_slot_t * | auth_data |
| Authentication vector hash table. | |
| int | auth_data_hash_size |
| authentication vector hash table size | |
| #define get_param | ( | src, | |||
| name, | |||||
| dst | ) |
Value:
{\
int i,j;\
(dst).s=0;(dst).len=0;\
for(i=0;i<(src).len-(name).len;i++)\
if (strncasecmp((src).s+i,(name).s,(name).len)==0 &&\
((src).s[i-1]==' ' ||(src).s[i-1]==';'||(src).s[i-1]=='\t')){\
j=i+(name).len;\
(dst).s = (src).s+j;\
(dst).len = 0;\
while(j<(src).len && (src).s[j]!=','&& (src).s[j]!=' '&& (src).s[j]!='\t'&& (src).s[j]!=';') \
j++; \
(dst).len = j-i-(name).len;\
break;\
} \
}
Definition at line 113 of file registration.c.
| #define h_inc h+=v^(v>>3) |
| unsigned char get_algorithm_type | ( | str | algorithm | ) |
Convert the SIP Algorithm to its type.
| algorithm | - the SIP Algorithm |
Definition at line 135 of file registration.c.
References algorithm_types, and AUTH_UNKNOWN.
Referenced by mod_init().
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 }
| unsigned char get_auth_scheme_type | ( | str | scheme | ) |
Convert the Diameter Authorization Scheme to its type.
| scheme | - the Diameter Authorization Scheme |
Definition at line 150 of file registration.c.
References auth_scheme_types, and AUTH_UNKNOWN.
Referenced by new_auth_vector().
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 }
| int S_add_path_service_routes | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Copies the Path header from REGISTER request to reply, inserts the Service-Route.
| msg | - the SIP message to operator on | |
| str1 | - no used | |
| str2 | - no used |
Definition at line 169 of file registration.c.
References cscf_add_header_rpl(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, M_NAME, and scscf_service_route.
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 }
| int S_add_allow | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Inserts an Allow header with the given value.
| msg | - the SIP message to operator on | |
| str1 | - the value to be inserted | |
| str2 | - no used |
Definition at line 203 of file registration.c.
References cscf_add_header_rpl(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, M_NAME, s_allow_e, s_allow_s, and STR_APPEND.
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 }
| int S_add_service_route | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Inserts a Service-Route header with the given value.
| msg | - the SIP message to operator on | |
| str1 | - the value to be inserted | |
| str2 | - no used |
Definition at line 239 of file registration.c.
References cscf_add_header_rpl(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, M_NAME, s_service_route_e, s_service_route_s, and STR_APPEND.
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 }
| int S_add_p_charging_function_addresses | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Copies the P-Charging-Function-Addresses header with the saved CF values in the registrar.
| msg | - the SIP REGISTER message to which reply to append | |
| str1 | - no used | |
| str2 | - no used |
Definition at line 278 of file registration.c.
References _r_public::ccf1, _r_public::ccf2, cscf_add_header_rpl(), cscf_get_public_identity(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, _r_public::ecf1, _r_public::ecf2, get_r_public(), _r_public::hash, M_NAME, r_unlock(), s_p_charging_function_addresses_1, s_p_charging_function_addresses_2, s_p_charging_function_addresses_3, s_p_charging_function_addresses_e, s_p_charging_function_addresses_s, and STR_APPEND.
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 }
| int S_REGISTER_reply | ( | struct sip_msg * | msg, | |
| int | code, | |||
| char * | text | |||
| ) |
Replies to a REGISTER and also adds the need headers Path and Service-Route are added.
| msg | - the SIP message to operator on | |
| code | - Reason Code for the response | |
| text | - Reason Phrase for the response |
Definition at line 363 of file registration.c.
References cscf_add_header_rpl(), cscf_reply_transactional(), M_NAME, and scscf_service_route.
Referenced by S_challenge(), S_MAR(), SAR(), and save_location().
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 }
| int S_check_visited_network_id | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Checks if the P-Visited-Network-Id matches a regexp.
| msg | - the SIP message | |
| str1 | - the regexp to check with | |
| str2 | - not used |
Definition at line 396 of file registration.c.
References cscf_get_visited_network_id(), CSCF_RETURN_FALSE, and CSCF_RETURN_TRUE.
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 }
| int S_is_integrity_protected | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Checks if the message is integrity protected.
| msg | - the SIP message | |
| str1 | - the realm | |
| str2 | - not used |
Definition at line 418 of file registration.c.
References cscf_get_integrity_protected(), CSCF_RETURN_BREAK, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, and M_NAME.
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 }
| static int matchesEarlyIMSIP | ( | str | ip, | |
| str | sent_by | |||
| ) | [static] |
Check if the sent_by ip address matches the storred ip addreses for Early-IMS.
| ip | - the byte array containing the 4/16 bytes of the IP address | |
| sent_by | - the sent_by parameter from the Via header |
Definition at line 441 of file registration.c.
References if.
Referenced by S_is_authorized().
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 }
| int S_is_authorized | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Checks if the message contains a valid response to a valid challenge.
| msg | - the SIP message | |
| str1 | - the realm | |
| str2 | - not used |
Definition at line 499 of file registration.c.
References algorithm_types, AUTH_AKAV1_MD5, AUTH_AKAV2_MD5, auth_data_unlock(), AUTH_DIGEST, AUTH_EARLY_IMS, AUTH_HTTP_DIGEST_MD5, AUTH_MD5, AUTH_NASS_BUNDLED, auth_scheme_types, AUTH_VECTOR_SENT, AUTH_VECTOR_UNUSED, AUTH_VECTOR_USED, AUTH_VECTOR_USELESS, _auth_vector::authenticate, _auth_vector::authorization, calc_H(), calc_HA1(), calc_response(), cscf_get_access_network_info(), cscf_get_body(), cscf_get_last_via_received(), cscf_get_last_via_sent_by(), cscf_get_nonce_response(), cscf_get_private_identity(), cscf_get_public_identity(), CSCF_RETURN_BREAK, CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, _r_public::early_ims_ip, get_auth_vector(), get_param, get_r_public(), HA_MD5, _r_public::hash, HASHHEXLEN, M_NAME, matchesEarlyIMSIP(), r_unlock(), registration_disable_early_ims, registration_disable_nass_bundled, S_MAR(), scscf_name_str, _auth_vector::status, STR_SHM_DUP, and _auth_vector::type.
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 }
| int S_challenge | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Responds with a 401 Unauthorized containing the (new) challenge.
| msg | - the SIP message | |
| str1 | - the realm | |
| str2< |