IPSec only is now supported and it is transparent in the sense that if the client does not employ it, the functionality is disabled.
The ipsec_P_*.sh scripts are used to control the IPSec and are give as an example for usage with the linux-2.6 kernel. ipsec_tools is required for this (setkey).
Added TLS support
Definition in file security.c.
#include <signal.h>
#include <stdlib.h>
#include "security.h"
#include "mod.h"
#include "sip.h"
#include "registration.h"
#include "registrar.h"
#include "registrar_subscribe.h"
#include "../../ip_addr.h"
#include "../../data_lump.h"
Go to the source code of this file.
Defines | |
| #define | get_qparam(src, name, dst) |
| #define | get_param(src, name, dst) |
| #define | strtoint(src, dest) |
Functions | |
| int | get_next_spi () |
| Returns the next unused SPI. | |
| unsigned long | tls_get_session_hash (struct sip_msg *req) |
| Looks for the tls session hash. | |
| static int | str_trim (str *s) |
| trims the str | |
| static r_security_type | cscf_get_security_type (str security_header_body) |
| Looks for the security type in the Security header . | |
| str | cscf_get_pref_security_header (struct sip_msg *req, str header_name, r_security_type *type, float *q) |
| Looks for the prefered Security header . | |
| r_contact * | save_contact_security (struct sip_msg *req, str auth, str sec_hdr, r_security_type type, float q) |
| Saves the Contact Security information into the P-CSCF registrar for this contact. | |
| int | execute_cmd (char *cmd) |
| Executes an external command. | |
| int | P_verify_security (struct sip_msg *req, char *str1, char *str2) |
| Process the REGISTER and verify Client-Security. | |
| int | P_security_401 (struct sip_msg *rpl, char *str1, char *str2) |
| Process the 401 response for REGISTER and creates the first Security-Associations. | |
| int | P_security_200 (struct sip_msg *rpl, char *str1, char *str2) |
| Process the 200 response for REGISTER and creates the first Security-Associations. | |
| void | P_security_drop (r_contact *c, r_security *s) |
| Drops the SAs for the given contact. | |
| int | P_check_via_sent_by (struct sip_msg *msg, char *str1, char *str2) |
| Checks if the sent-by parameter in the first Via header equals the source IP address of the message. | |
| int | P_follows_via_list (struct sip_msg *rpl, char *str1, char *str2) |
| Checks if a response coming from a UE contains the same Via headers sent in the corresponding request. | |
| int | P_enforce_via_list (struct sip_msg *rpl, char *str1, char *str2) |
| enforce a response coming from a UE to contain the same Via headers sent in the corresponding request | |
| int | P_add_via_received (struct sip_msg *msg, char *str1, char *str2) |
| Adds a received parameter to the first via with the source IP of the message. | |
| int | P_remove_header_tag (struct sip_msg *msg, char *str1, char *str2) |
| Remove from <str1> headers the <str2> tag. | |
| int | P_remove_security_client (struct sip_msg *msg, char *str1, char *str2) |
| Look for Security-Client and delete it if found. | |
| int | P_remove_security_verify (struct sip_msg *msg, char *str1, char *str2) |
| Look for Security-Verify and delete it if found. | |
| int | P_remove_security_headers (struct sip_msg *msg, char *str1, char *str2) |
| Removes the Security-Client,Security-Verify headers. | |
Variables | |
| int | pcscf_use_ipsec |
| whether to use or not ipsec | |
| char * | pcscf_ipsec_host |
| IP for protected server. | |
| int | pcscf_ipsec_port_c |
| PORT for protected client. | |
| int | pcscf_ipsec_port_s |
| PORT for protected server. | |
| char * | pcscf_ipsec_P_Inc_Req |
| Req E->P. | |
| char * | pcscf_ipsec_P_Out_Rpl |
| Rpl E<-P. | |
| char * | pcscf_ipsec_P_Out_Req |
| Req E<-P. | |
| char * | pcscf_ipsec_P_Inc_Rpl |
| Rpl E->P. | |
| char * | pcscf_ipsec_P_Drop |
| Drop. | |
| r_hash_slot * | registrar |
| the contacts | |
| int | r_hash_size |
| records tables parameters | |
| int | current_spi = 5000 |
| current SPI value | |
| int | pcscf_use_tls |
| whether to use or not tls | |
| int | pcscf_tls_port |
| PORT for TLS server. | |
| int | tls_disable |
| str | s_security_client = {"Security-Client",15} |
| str | s_security_verify = {"Security-Verify",15} |
| str | s_security_server_s = {"Security-Server: ",17} |
| str | s_security_server_e = {"\r\n",2} |
| static str | s_ck = {"ck=\"",4} |
| static str | s_ik = {"ik=\"",4} |
| static str | s_ealg = {"ealg=",5} |
| static str | s_alg = {"alg=",4} |
| static str | s_spi_c = {"spi-c=",6} |
| static str | s_spi_s = {"spi-s=",6} |
| static str | s_port_c = {"port-c=",7} |
| static str | s_port_s = {"port-s=",7} |
| static str | s_des_in = {"des-ede3-cbc",12} |
| static str | s_des_out = {"3des-cbc",8} |
| static str | s_aes_in = {"aes-cbc",7} |
| static str | s_aes_out = {"rijndael-cbc",12} |
| static str | s_null_out = {"null",4} |
| static str | s_md5_in = {"hmac-md5-96",11} |
| static str | s_md5_out = {"hmac-md5",8} |
| static str | s_sha_in = {"hmac-sha-1-96",13} |
| static str | s_sha_out = {"hmac-sha1",9} |
| time_t | time_now |
| current time | |
| static str | s_tls = {"tls", 3} |
| static str | s_ipsec = {"ipsec-3gpp", 10} |
| static str | s_q = {"q=", 2} |
| static str | via_hdr_s = {"Via: ",5} |
| static str | via_hdr_e = {"\r\n",2} |
| static str | s_received = {";received=",10} |
| static str | s_received2 = {"received",8} |
| #define get_qparam | ( | 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){\
j=i+(name).len;\
(dst).s = (src).s+j;\
(dst).len = 0;\
while(j<(src).len && (src).s[j]!='\"') \
j++; \
(dst).len = j-i-(name).len;\
break;\
} \
}
Definition at line 108 of file security.c.
| #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 124 of file security.c.
| #define strtoint | ( | src, | |||
| dest | ) |
Value:
{\
int i;\
(dest)=0;\
for(i=0;i<(src).len;i++)\
if ((src).s[i]>='0' && (src).s[i]<='9')\
(dest) = (dest)*10 + (src).s[i] -'0';\
}
Definition at line 141 of file security.c.
Referenced by P_verify_security(), and save_contact_security().
| int get_next_spi | ( | ) |
Returns the next unused SPI.
Definition at line 101 of file security.c.
References current_spi.
Referenced by save_contact_security().
00102 { 00103 return current_spi++; 00104 }
| unsigned long tls_get_session_hash | ( | struct sip_msg * | req | ) |
Looks for the tls session hash.
| req | - sip msg request |
Definition at line 189 of file security.c.
References get_tls_session_hash, M_NAME, and pcscf_use_tls.
Referenced by P_security_200().
00190 { 00191 unsigned long s_hash = 0; 00192 if (!pcscf_use_tls) return 0; 00193 s_hash = get_tls_session_hash(req); 00194 if (!s_hash){ 00195 LOG(L_ERR,"ERR:"M_NAME":tls_get_session_hash: Session Hash could not be obtained !\n"); 00196 return 0; 00197 } 00198 return s_hash; 00199 }
| static int str_trim | ( | str * | s | ) | [static] |
trims the str
| s | - str param to trim |
Definition at line 205 of file security.c.
00206 { 00207 int i; 00208 for (i = 0;i < s->len; i++) 00209 { 00210 if (s->s[i] != '\r' && s->s[i] != '\t' && s->s[i] != ' ') 00211 { 00212 break; 00213 } 00214 } 00215 s->s = s->s + i; 00216 s->len -= i; 00217 00218 for (i = s->len;i >=0; i--) 00219 { 00220 if (s->s[i] == '\r' && s->s[i] == '\t' && s->s[i] == ' ') 00221 { 00222 s->len--; 00223 } 00224 else 00225 { 00226 break; 00227 } 00228 } 00229 return 1; 00230 }
| static r_security_type cscf_get_security_type | ( | str | security_header_body | ) | [static] |
Looks for the security type in the Security header .
| security_header_body | - input security header |
Definition at line 237 of file security.c.
Referenced by cscf_get_pref_security_header().
00238 { 00239 str sec_type_s; 00240 int i; 00241 00242 sec_type_s.s = security_header_body.s; 00243 sec_type_s.len = security_header_body.len; 00244 for (i = 0; i< security_header_body.len; i++) 00245 if (security_header_body.s[i] == ';') { 00246 sec_type_s.len = i; 00247 break; 00248 } 00249 str_trim(&sec_type_s); 00250 if (sec_type_s.len==s_tls.len && 00251 !strncasecmp(sec_type_s.s, s_tls.s , s_tls.len)) 00252 return SEC_TLS; 00253 else if (sec_type_s.len==s_ipsec.len && 00254 !strncasecmp(sec_type_s.s, s_ipsec.s , s_ipsec.len)) 00255 return SEC_IPSEC; 00256 return SEC_NONE; 00257 }
| str cscf_get_pref_security_header | ( | struct sip_msg * | req, | |
| str | header_name, | |||
| r_security_type * | type, | |||
| float * | q | |||
| ) |
Looks for the prefered Security header .
| req | - the SIP message | |
| header_name | - SIP header name | |
| type | - output value of the security type | |
| q | - output preferate value |
Definition at line 267 of file security.c.
References cscf_get_next_header(), cscf_get_security_type(), get_param, M_NAME, pcscf_use_ipsec, pcscf_use_tls, s_q, SEC_IPSEC, SEC_NONE, and SEC_TLS.
Referenced by P_security_200(), P_security_401(), and P_verify_security().
00268 { 00269 str q_sec={0,0},t_sec; 00270 r_security_type q_type=SEC_NONE,t_type; 00271 float q_q=-1,t_q; 00272 struct hdr_field *hdr=0; 00273 str tmp={0,0}; 00274 char c; 00275 00276 00277 /* first find the highest q */ 00278 for(hdr = cscf_get_next_header(req,header_name,(void*)0);hdr;hdr = cscf_get_next_header(req,header_name,hdr)){ 00279 t_sec = hdr->body; 00280 /* if unknown type, skip */ 00281 t_type = cscf_get_security_type(t_sec); 00282 if (t_type==SEC_NONE || 00283 (!pcscf_use_ipsec&&t_type==SEC_IPSEC)|| 00284 (!pcscf_use_tls&&t_type==SEC_TLS)) continue; 00285 /* check if q is maximum */ 00286 get_param(t_sec,s_q,tmp); 00287 if (tmp.len) { 00288 c = tmp.s[tmp.len]; 00289 tmp.s[tmp.len]=0; 00290 t_q = atof(tmp.s); 00291 tmp.s[tmp.len]=c; 00292 } 00293 else t_q = -1; 00294 if (t_q > q_q || q_sec.len==0) { 00295 q_sec = t_sec; 00296 q_q = t_q; 00297 q_type = t_type; 00298 } 00299 } 00300 00301 if (!q_sec.len) { 00302 LOG(L_INFO,"DBG:"M_NAME":cscf_get_pref_security_header: No known Security header found.\n"); 00303 return q_sec; 00304 } 00305 00306 if (type) *type = q_type; 00307 if (q) *q = q_q; 00308 return q_sec; 00309 }
| r_contact* save_contact_security | ( | struct sip_msg * | req, | |
| str | auth, | |||
| str | sec_hdr, | |||
| r_security_type | type, | |||
| float | q | |||
| ) |
Saves the Contact Security information into the P-CSCF registrar for this contact.
| req | - REGISTER request | |
| auth | - WWW-Authenticate header | |
| sec_hdr | - Security header | |
| type | - Security Type | |
| q | - Preference Value |
Definition at line 320 of file security.c.
References ck, cscf_parse_contacts(), free_r_security(), get_next_spi(), get_param, get_qparam, ik, M_NAME, new_r_ipsec(), new_r_security(), _r_ipsec::port_us, r_act_time(), REG_PENDING, s_aes_in, s_aes_out, s_alg, s_ck, s_des_in, s_des_out, s_ealg, s_ik, s_md5_in, s_md5_out, s_null_out, s_port_c, s_port_s, s_sha_in, s_sha_out, s_spi_c, s_spi_s, SEC_IPSEC, SEC_NONE, SEC_TLS, strtoint, time_now, and update_r_contact_sec().
Referenced by P_security_401().
00321 { 00322 contact_t* c=0; 00323 contact_body_t* b=0; 00324 r_contact *rc; 00325 enum Reg_States reg_state=REG_PENDING; 00326 int expires,pending_expires=60; 00327 struct sip_uri puri; 00328 r_security *s=0; 00329 00330 b = cscf_parse_contacts(req); 00331 00332 if (!b||!b->contacts) { 00333 LOG(L_ERR,"ERR:"M_NAME":save_contact_security: No contacts found\n"); 00334 goto error; 00335 } 00336 00337 if (b) c = b->contacts; 00338 00339 r_act_time(); 00340 /* the Security works for just 1 contact/registration! */ 00341 if(c){ 00342 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: <%.*s>\n",c->uri.len,c->uri.s); 00343 00344 expires = time_now+pending_expires; 00345 00346 if (parse_uri(c->uri.s,c->uri.len,&puri)<0){ 00347 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Error parsing Contact URI <%.*s>\n",c->uri.len,c->uri.s); 00348 goto error; 00349 } 00350 if (puri.port_no==0) puri.port_no=5060; 00351 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: %d %.*s : %d\n", 00352 puri.proto, puri.host.len,puri.host.s,puri.port_no); 00353 00354 if (type == SEC_TLS) 00355 puri.proto = PROTO_TLS; 00356 00357 /* create the r_security structure */ 00358 s = new_r_security(sec_hdr,type,q); 00359 if (!s) goto error; 00360 00361 switch(type) { 00362 case SEC_NONE: 00363 break; 00364 case SEC_TLS: 00365 // r_tls creation happens on 200 00366 break; 00367 case SEC_IPSEC: 00368 { 00369 /* then parse the parameters */ 00370 r_ipsec *ipsec; 00371 str ck,ik,ealg,alg,tmp; 00372 str alg_setkey,ealg_setkey; 00373 unsigned int spi_uc,spi_us; 00374 unsigned int spi_pc,spi_ps; 00375 int port_uc,port_us; 00376 char ck_c[64],ik_c[64]; 00377 str ck_esp={ck_c,0},ik_esp={ik_c,0}; 00378 00379 get_qparam(auth,s_ck,ck); 00380 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: CK: <%.*s>\n", 00381 ck.len,ck.s); 00382 get_qparam(auth,s_ik,ik); 00383 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: IK: <%.*s>\n", 00384 ik.len,ik.s); 00385 get_param(sec_hdr,s_ealg,ealg); 00386 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Enc Algorithm: <%.*s>\n", 00387 ealg.len,ealg.s); 00388 get_param(sec_hdr,s_alg,alg); 00389 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Int Algorithm: <%.*s>\n", 00390 alg.len,alg.s); 00391 /* and for spis */ 00392 get_param(sec_hdr,s_spi_c,tmp); 00393 strtoint(tmp,spi_uc); 00394 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: SPI-C: %d\n", 00395 spi_uc); 00396 get_param(sec_hdr,s_spi_s,tmp); 00397 strtoint(tmp,spi_us); 00398 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: SPI-S: %d\n", 00399 spi_us); 00400 /* and for ports */ 00401 get_param(sec_hdr,s_port_c,tmp); 00402 strtoint(tmp,port_uc); 00403 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Port-C: %d\n", 00404 port_uc); 00405 get_param(sec_hdr,s_port_s,tmp); 00406 strtoint(tmp,port_us); 00407 LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Port-S: %d\n", 00408 port_us); 00409 00410 ck_esp.s[ck_esp.len++]='0'; 00411 ck_esp.s[ck_esp.len++]='x'; 00412 if (ealg.len == s_des_in.len && strncasecmp(ealg.s,s_des_in.s,ealg.len)==0) { 00413 memcpy(ck_esp.s+ck_esp.len,ck.s,32);ck_esp.len+=32; 00414 memcpy(ck_esp.s+ck_esp.len,ck.s,16);ck_esp.len+=16; 00415 ealg_setkey = s_des_out; 00416 } 00417 else 00418 if (ealg.len == s_aes_in.len && strncasecmp(ealg.s,s_aes_in.s,ealg.len)==0) { 00419 memcpy(ck_esp.s+ck_esp.len,ck.s,ck.len);ck_esp.len+=ck.len; 00420 ealg_setkey = s_aes_out; 00421 }else { 00422 memcpy(ck_esp.s+ck_esp.len,ck.s,ck.len);ck_esp.len+=ck.len; 00423 ealg_setkey = s_null_out; 00424 ealg = s_null_out; 00425 } 00426 00427 ik_esp.s[ik_esp.len++]='0'; 00428 ik_esp.s[ik_esp.len++]='x'; 00429 if (alg.len == s_md5_in.len && strncasecmp(alg.s,s_md5_in.s,alg.len)==0) { 00430 memcpy(ik_esp.s+ik_esp.len,ik.s,ik.len);ik_esp.len+=ik.len; 00431 alg_setkey = s_md5_out; 00432 } 00433 else 00434 if (alg.len == s_sha_in.len && strncasecmp(alg.s,s_sha_in.s,alg.len)==0) { 00435 memcpy(ik_esp.s+ik_esp.len,ik.s,ik.len);ik_esp.len+=ik.len; 00436 memcpy(ik_esp.s+ik_esp.len,"00000000",8);ik_esp.len+=8; 00437 alg_setkey = s_sha_out; 00438 }else{ 00439 LOG(L_ERR,"ERR:"M_NAME":save_contact_security: Unknown Integrity algorithm <%.*s>\n",alg.len,alg.s); 00440 goto error; 00441 } 00442 00443 spi_pc=get_next_spi(); 00444 spi_ps=get_next_spi(); 00445 00446 ipsec = new_r_ipsec(spi_uc,spi_us,spi_pc,spi_ps,port_uc,port_us, 00447 ealg_setkey,ealg, ck_esp,alg_setkey,alg, ik_esp); 00448 if (!ipsec) goto error; 00449 s->data.ipsec = ipsec; 00450 00451 puri.port_no = ipsec->port_us; 00452 /* 00453 * this should actually be port_uc... then the cscf_get_ue_via should be 00454 * changed to give rport and not the port in the via. but this would 00455 * break NATed clients... 00456 */ 00457 } 00458 break; 00459 } 00460 } 00461 00462 rc = update_r_contact_sec(puri.host,puri.port_no,puri.proto, 00463 &(c->uri),®_state,&expires,s); 00464 00465 return rc; 00466 error: 00467 if (s) free_r_security(s); 00468 return 0; 00469 }
| int execute_cmd | ( | char * | cmd | ) | [inline] |
Executes an external command.
Used to call the IPSec scripts/commands.
| cmd | - full command to execute, with parameters |
Definition at line 479 of file security.c.
Referenced by P_security_200(), P_security_401(), and P_security_drop().
00480 { 00481 FILE *p; 00482 void *prev; 00483 char out[256]; 00484 LOG(L_INFO,"INF:"M_NAME":execute_cmd: [%s]\n",cmd); 00485 /* because SER forked dies when a chield dies, SIGCHLD is masked temporary */ 00486 prev = signal(SIGCHLD,SIG_DFL); 00487 p = popen(cmd,"r"); 00488 if (!p) { 00489 LOG(L_ERR,"ERR:"M_NAME":execute_cmd: Error executing cmd> %s\n",cmd); 00490 signal(SIGCHLD,prev); 00491 return 0; 00492 } 00493 while(fgets(out,256,p)) 00494 LOG(L_DBG,"DBG:"M_NAME":execute_cmd: > %s",out); 00495 pclose(p); 00496 signal(SIGCHLD,prev); 00497 return 1; 00498 }
| int P_verify_security | ( | struct sip_msg * | req, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Process the REGISTER and verify Client-Security.
| req | - Register request | |
| str1 | - not used | |
| str2 | - not used |
Definition at line 507 of file security.c.
References cscf_get_first_via(), cscf_get_pref_security_header(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, _r_security::data, get_param, get_r_contact(), _r_contact::hash, _r_security::ipsec, M_NAME, pcscf_ipsec_port_c, pcscf_ipsec_port_s, pcscf_tls_port, r_act_time(), _r_ipsec::r_alg, _r_ipsec::r_ealg, r_unlock(), r_valid_contact(), s_alg, s_ealg, s_port_c, s_port_s, s_security_verify, s_spi_c, s_spi_s, SEC_IPSEC, SEC_NONE, SEC_TLS, _r_contact::security_temp, _r_ipsec::spi_pc, _r_ipsec::spi_ps, strtoint, and _r_security::type.
00508 { 00509 str sec_hdr; 00510 struct hdr_field *h; 00511 struct via_body *vb; 00512 r_contact *c; 00513 r_security *s; 00514 r_security_type sec_type; 00515 float sec_q; 00516 00517 str ealg,alg,tmp; 00518 unsigned int spi_pc,spi_ps;; 00519 int port_pc,port_ps; 00520 00521 vb = cscf_get_first_via(req,&h); 00522 00523 LOG(L_INFO,"DBG:"M_NAME":P_verify_security: Looking for <%d://%.*s:%d> \n", vb->proto,vb->host.len,vb->host.s,vb->port); 00524 00525 c = get_r_contact(vb->host,vb->port,vb->proto); 00526 00527 r_act_time(); 00528 if (!c){ 00529 //first register 00530 LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No Contact found ! \n"); 00531 return CSCF_RETURN_TRUE; 00532 } 00533 00534 if (!r_valid_contact(c) || !c->security_temp){ 00535 LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No security temp !.\n"); 00536 r_unlock(c->hash); 00537 return CSCF_RETURN_TRUE; 00538 } 00539 00540 sec_hdr = cscf_get_pref_security_header(req,s_security_verify, &sec_type,&sec_q); 00541 if (!sec_hdr.len) 00542 { 00543 LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No Security-Verify header found.\n"); 00544 r_unlock(c->hash); 00545 return CSCF_RETURN_TRUE; 00546 } 00547 00548 s = c->security_temp; 00549 00550 switch (s->type) 00551 { 00552 case SEC_NONE: 00553 break; 00554 case SEC_TLS: 00555 if (sec_type != SEC_TLS || req->rcv.dst_port != pcscf_tls_port) 00556 goto error; 00557 break; 00558 case SEC_IPSEC: 00559 if (sec_type != SEC_IPSEC || req->rcv.dst_port != pcscf_ipsec_port_s) 00560 { 00561 LOG(L_INFO,"DBG:"M_NAME":P_verify_security: Not IPSEC tunnel!.\n"); 00562 r_unlock(c->hash); 00563 goto error; 00564 } 00565 get_param(sec_hdr,s_ealg,ealg); 00566 get_param(sec_hdr,s_alg,alg); 00567 /* and for spis */ 00568 get_param(sec_hdr,s_spi_c,tmp); 00569 strtoint(tmp,spi_pc); 00570 get_param(sec_hdr,s_spi_s,tmp); 00571 strtoint(tmp,spi_ps); 00572 /* and for ports */ 00573 get_param(sec_hdr,s_port_c,tmp); 00574 strtoint(tmp,port_pc); 00575 get_param(sec_hdr,s_port_s,tmp); 00576 strtoint(tmp,port_ps); 00577 if ((s->data.ipsec->r_ealg.len != ealg.len || strncasecmp(s->data.ipsec->r_ealg.s, ealg.s, ealg.len)) || 00578 (s->data.ipsec->r_alg.len != alg.len || strncasecmp(s->data.ipsec->r_alg.s, alg.s, alg.len)) || 00579 (s->data.ipsec->spi_pc != spi_pc) || 00580 (s->data.ipsec->spi_ps != spi_ps) || 00581 (pcscf_ipsec_port_c != port_pc) || 00582 (pcscf_ipsec_port_s != port_ps)) 00583 { 00584 LOG(L_INFO,"DBG:"M_NAME":P_verify_security: No valid Security-Verify header!.\n"); 00585 r_unlock(c->hash); 00586 goto error; 00587 } 00588 break; 00589 } 00590 r_unlock(c->hash); 00591 00592 return CSCF_RETURN_TRUE; 00593 error: 00594 return CSCF_RETURN_FALSE; 00595 }
| int P_security_401 | ( | struct sip_msg * | rpl, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Process the 401 response for REGISTER and creates the first Security-Associations.
IPSEc: Only the SA for P_Inc_Req - Incoming Requests is set now as the next REGISTER could come over that one.
| rpl | - the 401 response | |
| str1 | - not used | |
| str2 | - not used |
Definition at line 606 of file security.c.
References _r_ipsec::alg, _r_ipsec::ck, cscf_add_header(), cscf_get_authenticate(), cscf_get_pref_security_header(), cscf_get_request_from_reply(), CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, _r_security::data, _r_ipsec::ealg, execute_cmd(), _r_contact::hash, _r_contact::host, _r_ipsec::ik, _r_security::ipsec, M_NAME, pcscf_ipsec_host, pcscf_ipsec_P_Inc_Req, pcscf_ipsec_port_c, pcscf_ipsec_port_s, pcscf_use_ipsec, pcscf_use_tls, _r_ipsec::port_uc, _r_ipsec::r_alg, _r_ipsec::r_ealg, r_unlock(), s_security_client, s_security_server_e, s_security_server_s, save_contact_security(), SEC_IPSEC, SEC_NONE, SEC_TLS, _r_contact::security_temp, _r_ipsec::spi_pc, _r_ipsec::spi_ps, and STR_APPEND.
00607 { 00608 struct sip_msg *req; 00609 struct hdr_field *hdr; 00610 str sec_hdr,sec_srv={0,0}; 00611 r_security_type sec_type; 00612 char cmd[256]; 00613 r_contact *c; 00614 r_ipsec *ipsec; 00615 float sec_q=-1; 00616 str auth; 00617 00618 if (!pcscf_use_ipsec &&!pcscf_use_tls) goto ret_false; 00619 00620 req = cscf_get_request_from_reply(rpl); 00621 if (!req){ 00622 LOG(L_ERR,"ERR:"M_NAME":P_security_401: No transactional request found.\n"); 00623 goto error; 00624 } 00625 auth = cscf_get_authenticate(rpl,&hdr); 00626 if (!auth.len){ 00627 LOG(L_ERR,"ERR:"M_NAME":P_security_401: No WWW-Authenticate header found.\n"); 00628 goto ret_false; 00629 } 00630 00631 sec_hdr = cscf_get_pref_security_header(req,s_security_client, &sec_type,&sec_q); 00632 if (!sec_hdr.len) { 00633 LOG(L_DBG,"DBG:"M_NAME":P_security_401: No Security-Client header found.\n"); 00634 goto ret_false; 00635 } 00636 LOG(L_INFO,"DBG:"M_NAME":P_security_401: Security-Client header found : <%.*s>.\n", sec_hdr.len, sec_hdr.s); 00637 00638 00639 /* save data into registrar */ 00640 c = save_contact_security(req, auth, sec_hdr, sec_type, sec_q); 00641 if (!c) goto error; 00642 switch(sec_type){ 00643 case SEC_NONE: 00644 break; 00645 case SEC_TLS: 00646 /* try to add the Security-Server header */ 00647 sec_srv.len = s_security_server_s.len+sec_hdr.len+s_security_server_e.len; 00648 sec_srv.s = pkg_malloc(sec_srv.len); 00649 if (!sec_srv.s){ 00650 LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len); 00651 goto error; 00652 } 00653 sec_srv.len=0; 00654 STR_APPEND(sec_srv,s_security_server_s); 00655 STR_APPEND(sec_srv,sec_hdr); 00656 STR_APPEND(sec_srv,s_security_server_e); 00657 00658 if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) { 00659 LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s); 00660 pkg_free(sec_srv.s); 00661 goto error; 00662 } 00663 break; 00664 case SEC_IPSEC: 00665 ipsec = c->security_temp->data.ipsec; 00666 /* try to add the Security-Server header */ 00667 sprintf(cmd,"Security-Server: ipsec-3gpp; ealg=%.*s; alg=%.*s; spi-c=%d; spi-s=%d; port-c=%d; port-s=%d; q=0.1\r\n", 00668 ipsec->r_ealg.len,ipsec->r_ealg.s, 00669 ipsec->r_alg.len,ipsec->r_alg.s, 00670 ipsec->spi_pc,ipsec->spi_ps, 00671 pcscf_ipsec_port_c,pcscf_ipsec_port_s); 00672 00673 sec_srv.len = strlen(cmd); 00674 sec_srv.s = pkg_malloc(sec_srv.len); 00675 if (!sec_srv.s){ 00676 LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len); 00677 goto error; 00678 } 00679 memcpy(sec_srv.s,cmd,sec_srv.len); 00680 if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) { 00681 LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s); 00682 pkg_free(sec_srv.s); 00683 goto error; 00684 } 00685 00686 /* run the IPSec script */ 00687 /* P_Inc_Req */ 00688 sprintf(cmd,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s", 00689 pcscf_ipsec_P_Inc_Req, 00690 c->host.len,c->host.s, 00691 ipsec->port_uc, 00692 pcscf_ipsec_host, 00693 pcscf_ipsec_port_s, 00694 ipsec->spi_ps, 00695 ipsec->ealg.len,ipsec->ealg.s, 00696 ipsec->ck.len,ipsec->ck.s, 00697 ipsec->alg.len,ipsec->alg.s, 00698 ipsec->ik.len,ipsec->ik.s); 00699 00700 r_unlock(c->hash); 00701 00702 execute_cmd(cmd); 00703 break; 00704 } 00705 00706 return CSCF_RETURN_TRUE; 00707 ret_false: 00708 return CSCF_RETURN_FALSE; 00709 error: 00710 return CSCF_RETURN_ERROR; 00711 }
| int P_security_200 | ( | struct sip_msg * | rpl, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Process the 200 response for REGISTER and creates the first Security-Associations.
The rest of the SA are not set. could come over that one.
| rpl | - the 200 response | |
| str1 | - not used | |
| str2 | - not used |
Definition at line 723 of file security.c.
References _r_ipsec::alg, _r_ipsec::ck, cscf_get_first_via(), cscf_get_max_expires(), cscf_get_pref_security_header(), cscf_get_request_from_reply(), CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, _r_security::data, DEREGISTERED, _r_ipsec::ealg, execute_cmd(), _r_contact::expires, free_r_security(), get_r_contact(), get_tls_session_hash, _r_contact::hash, _r_contact::host, _r_ipsec::ik, _r_security::ipsec, M_NAME, new_r_tls(), P_security_drop(), pcscf_ipsec_host, pcscf_ipsec_P_Inc_Rpl, pcscf_ipsec_P_Out_Req, pcscf_ipsec_P_Out_Rpl, pcscf_ipsec_port_c, pcscf_ipsec_port_s, pcscf_use_ipsec, pcscf_use_tls, _r_tls::port_tls, _r_ipsec::port_uc, _r_ipsec::port_us, r_act_time(), r_unlock(), r_valid_contact(), _r_contact::reg_state, s_security_client, SEC_IPSEC, SEC_NONE, SEC_TLS, _r_contact::security, _r_contact::security_temp, _r_tls::session_hash, _r_ipsec::spi_pc, _r_ipsec::spi_uc, _r_ipsec::spi_us, time_now, _r_security::tls, tls_get_session_hash(), and _r_security::type.
00724 { 00725 struct sip_msg *req; 00726 str sec_hdr; 00727 r_security_type sec_type; 00728 float sec_q; 00729 struct hdr_field *h; 00730 struct via_body *vb; 00731 r_contact *c; 00732 r_ipsec *i; 00733 int expires; 00734 unsigned long s_hash; 00735 char out_rpl[256],out_req[256],inc_rpl[256]; 00736 00737 if (!pcscf_use_ipsec &&!pcscf_use_tls) goto ret_false; 00738 00739 req = cscf_get_request_from_reply(rpl); 00740 if (!req){ 00741 LOG(L_ERR,"ERR:"M_NAME":P_security_200: No transactional request found.\n"); 00742 goto error; 00743 } 00744 00745 sec_hdr = cscf_get_pref_security_header(req,s_security_client, &sec_type,&sec_q); 00746 if (!sec_hdr.len) { 00747 LOG(L_DBG,"DBG:"M_NAME":P_security_200: No Security-Verify header found.\n"); 00748 goto error; 00749 } 00750 00751 /* find the expires (reg or dereg?) */ 00752 expires = cscf_get_max_expires(req); 00753 00754 /* get the IPSec info from the registrar */ 00755 00756 vb = cscf_get_first_via(req,&h); 00757 LOG(L_DBG,"DBG:"M_NAME":P_security_200: Looking for <%d://%.*s:%d> \n", 00758 vb->proto,vb->host.len,vb->host.s,vb->port); 00759 00760 c = get_r_contact(vb->host,vb->port,vb->proto); 00761 00762 r_act_time(); 00763 if (!c){ 00764 LOG(L_ERR,"ERR:"M_NAME":P_security_200: Contact not found\n"); 00765 goto error; 00766 } 00767 00768 if (c->security_temp){ 00769 if (c->security && c->security->type == SEC_TLS && 00770 (c->security->data.tls && c->security->