Definition in file registration.h.
#include "mod.h"
#include "../../locking.h"
Go to the source code of this file.
Data Structures | |
| struct | _auth_vector |
| Authorization Vector storage structure. More... | |
| struct | _auth_userdata |
| Set of auth_vectors used by a private id. More... | |
| struct | auth_hash_slot_t |
| Authorization user data hash slot. More... | |
Defines | |
| #define | NONCE_LEN 16 |
| #define | RAND_LEN 16 |
| #define | AUTH_TYPE_MAX AUTH_NASS_BUNDLED |
Typedefs | |
| typedef _auth_vector | auth_vector |
| Authorization Vector storage structure. | |
| typedef _auth_userdata | auth_userdata |
| Set of auth_vectors used by a private id. | |
Enumerations | |
| enum | authorization_types { AUTH_UNKNOWN = 0, AUTH_AKAV1_MD5 = 1, AUTH_AKAV2_MD5 = 2, AUTH_EARLY_IMS = 3, AUTH_MD5 = 4, AUTH_DIGEST = 5, AUTH_HTTP_DIGEST_MD5 = 6, AUTH_NASS_BUNDLED = 7 } |
| enum | auth_vector_status { AUTH_VECTOR_UNUSED = 0, AUTH_VECTOR_SENT = 1, AUTH_VECTOR_USED = 2, AUTH_VECTOR_USELESS = 3 } |
| Enumeration for the Authorization Vector status. More... | |
Functions | |
| unsigned char | get_algorithm_type (str algorithm) |
| Convert the SIP Algorithm to its type. | |
| unsigned char | get_auth_scheme_type (str algorithm) |
| 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_check_visited_network_id (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the P-Visited-Network-Id matches a regexp. | |
| 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_is_integrity_protected (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the message is integrity protected. | |
| 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. | |
| 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. | |
| #define NONCE_LEN 16 |
| #define RAND_LEN 16 |
| #define AUTH_TYPE_MAX AUTH_NASS_BUNDLED |
| typedef struct _auth_vector auth_vector |
Authorization Vector storage structure.
| typedef struct _auth_userdata auth_userdata |
Set of auth_vectors used by a private id.
| enum authorization_types |
| AUTH_UNKNOWN | |
| AUTH_AKAV1_MD5 | |
| AUTH_AKAV2_MD5 | |
| AUTH_EARLY_IMS | |
| AUTH_MD5 | |
| AUTH_DIGEST | |
| AUTH_HTTP_DIGEST_MD5 | |
| AUTH_NASS_BUNDLED |
Definition at line 87 of file registration.h.
00087 { 00088 AUTH_UNKNOWN = 0, 00089 /* 3GPP */ 00090 AUTH_AKAV1_MD5 = 1, 00091 AUTH_AKAV2_MD5 = 2, 00092 AUTH_EARLY_IMS = 3, 00093 /* FOKUS */ 00094 AUTH_MD5 = 4, 00095 /* CableLabs */ 00096 AUTH_DIGEST = 5, 00097 /* TISPAN */ 00098 AUTH_HTTP_DIGEST_MD5 = 6, 00099 AUTH_NASS_BUNDLED = 7 00100 };
| enum auth_vector_status |
Enumeration for the Authorization Vector status.
Definition at line 105 of file registration.h.
00105 { 00106 AUTH_VECTOR_UNUSED = 0, 00107 AUTH_VECTOR_SENT = 1, 00108 AUTH_VECTOR_USED = 2, 00109 AUTH_VECTOR_USELESS = 3 00110 } ;
| 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_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_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_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 }
| 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 | - not used |
Definition at line 749 of file registration.c.
References auth_data_unlock(), auth_scheme_types, AUTH_VECTOR_SENT, AUTH_VECTOR_UNUSED, AUTH_VECTOR_USED, AUTH_VECTOR_USELESS, av_request_at_once, av_request_at_sync, cscf_get_auts(), cscf_get_nonce(), cscf_get_private_identity(), cscf_get_public_identity(), CSCF_RETURN_BREAK, CSCF_RETURN_FALSE, get_auth_vector(), M_NAME, MSG_403_NO_NONCE, MSG_403_NO_PRIVATE, MSG_403_NO_PUBLIC, MSG_500_PACK_AV, pack_challenge(), registration_default_algorithm_type, S_MAR(), S_REGISTER_reply(), scscf_name_str, start_reg_await_timer(), and _auth_vector::status.
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