Esempio n. 1
0
/**
 * Checks if Session-Expires value is over Min_SE local policy
 * @param msg - the initial request
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not
*/
int S_check_session_expires(struct sip_msg* msg, char* str1, char* str2)
{
	time_t t_time;
	time_t min_se_time = 0;
	str ses_exp = {0,0};
 	str min_se = {0,0};
	str new_min_se = {0,0};
	str new_ses_exp = {0,0};
	struct hdr_field *h_se, *h_min_se;
	str refresher;

	ses_exp = cscf_get_session_expires_body(msg, &h_se);
	t_time = cscf_get_session_expires(ses_exp, &refresher);
	
	if (!t_time || t_time >= scscf_min_se)
		return CSCF_RETURN_TRUE;
	if (!supports_extension(msg, &str_ext_timer)) //does not suports timer extension
	{
		//add Min-SE header with its minimum interval
		min_se = cscf_get_min_se(msg, &h_min_se);
		if (min_se.len) {
			strtotime(min_se, min_se_time);
			if (min_se_time < scscf_min_se)
				cscf_del_header(msg, h_min_se);
			else
				return CSCF_RETURN_TRUE;
		}
		new_min_se.len = 11/*int value*/ + str_min_se.len+3;
		new_min_se.s = pkg_malloc(new_min_se.len+1);
		if (!new_min_se.s) {
			LOG(L_ERR,"ERR:"M_NAME":S_check_session_expires: Error allocating %d bytes\n",new_min_se.len);
			goto error;
		}
		new_min_se.len = snprintf(new_min_se.s, new_min_se.len, "%.*s %d\r\n",str_min_se.len, str_min_se.s, scscf_min_se);
		min_se_time = scscf_min_se;
		cscf_add_header(msg, &new_min_se, HDR_OTHER_T);
		if (t_time < scscf_min_se) {
			cscf_del_header(msg, h_se);
			new_ses_exp.len = 11 + str_se.len+3;
			new_ses_exp.s = pkg_malloc(new_ses_exp.len+1);
			if (!new_ses_exp.s) {
				LOG(L_ERR,"ERR:"M_NAME":S_check_session_expires: Error allocating %d bytes\n",new_ses_exp.len);
				goto error;
			}
			new_ses_exp.len = snprintf(new_ses_exp.s, new_ses_exp.len, "%.*s %d\r\n",str_se.len, str_se.s, scscf_min_se);
			t_time = scscf_min_se;
			cscf_add_header(msg, &new_ses_exp, HDR_OTHER_T);
		}
		return CSCF_RETURN_TRUE;
	}
error:
	if (new_min_se.s) pkg_free(new_min_se.s);
	if (new_ses_exp.s) pkg_free(new_ses_exp.s);
	return CSCF_RETURN_FALSE;
}		
Esempio n. 2
0
int add_supported_secagree_header(struct sip_msg* m)
{
    // Add sec-agree header in the reply
    const char* supported_sec_agree = "Supported: sec-agree\r\n";
    const int supported_sec_agree_len = 22;

    str* supported = NULL;
    if((supported = pkg_malloc(sizeof(str))) == NULL) {
        LM_ERR("Error allocating pkg memory for supported header\n");
        return -1;
    }

    if((supported->s = pkg_malloc(supported_sec_agree_len)) == NULL) {
        LM_ERR("Error allcationg pkg memory for supported header str\n");
        return -1;
    }
    memcpy(supported->s, supported_sec_agree, supported_sec_agree_len);
    supported->len = supported_sec_agree_len;

    if(cscf_add_header(m, supported, HDR_SUPPORTED_T) != 1) {
        LM_ERR("Error adding security header to reply!\n");
        return -1;
    }

    return 0;
}
Esempio n. 3
0
int assert_called_identity(struct sip_msg* _m, udomain_t* _d) {
	
	int ret=CSCF_RETURN_FALSE;
	str called_party_id={0,0},x={0,0};
	struct sip_msg* req;
	struct hdr_field *h=0;
		
	//get request from reply
	req = get_request_from_reply(_m);
	if (!req) {
		LM_ERR("Unable to get request from reply for REGISTER. No transaction\n");
		goto error;
	}
	
	called_party_id = cscf_get_public_identity_from_called_party_id(req, &h);
	
		
	if (!called_party_id.len){
		goto error;	
	}else{
		LM_DBG("Called Party ID from request: %.*s\n", called_party_id.len, called_party_id.s);	
		x.len = p_asserted_identity_s.len+p_asserted_identity_m.len+called_party_id.len+p_asserted_identity_e.len;
		x.s = pkg_malloc(x.len);
		if (!x.s){
			LM_ERR("P_assert_called_identity: Error allocating %d bytes\n",	x.len);
			x.len=0;
			goto error;		
		}
		x.len=0;
		STR_APPEND(x,p_asserted_identity_s);
		STR_APPEND(x,p_asserted_identity_m);
		STR_APPEND(x,called_party_id);
		STR_APPEND(x,p_asserted_identity_e);
		
		if (cscf_add_header(_m,&x,HDR_OTHER_T))
			ret = CSCF_RETURN_TRUE;
		else
		    goto error;
	}
	
	return ret;
	
error:
	ret=CSCF_RETURN_FALSE;
	return ret;
}
Esempio n. 4
0
int add_security_server_header(struct sip_msg* m, ipsec_t* s)
{
    // allocate memory for the header itself
    str* sec_header = NULL;
    if((sec_header = pkg_malloc(sizeof(str))) == NULL) {
        LM_ERR("Error allocating pkg memory for security header\n");
        return -1;
    }
    memset(sec_header, 0, sizeof(str));

    // create a temporary buffer and set the value in it
    char sec_hdr_buf[1024];
    memset(sec_hdr_buf, 0, sizeof(sec_hdr_buf));
    sec_header->len = snprintf(sec_hdr_buf, sizeof(sec_hdr_buf) - 1,
                                "Security-Server: ipsec-3gpp;prot=esp;mod=trans;spi-c=%d;spi-s=%d;port-c=%d;port-s=%d;alg=%.*s;ealg=%.*s\r\n",
                                s->spi_pc, s->spi_ps, ipsec_client_port, ipsec_server_port,
                                s->r_alg.len, s->r_alg.s,
                                s->r_ealg.len, s->r_ealg.s
                              );

    // copy to the header and add
    if((sec_header->s = pkg_malloc(sec_header->len)) == NULL) {
        LM_ERR("Error allocating pkg memory for security header payload\n");
        pkg_free(sec_header);
        return -1;
    }
    memcpy(sec_header->s, sec_hdr_buf, sec_header->len);

    // add security-server header in reply
    if(cscf_add_header(m, sec_header, HDR_OTHER_T) != 1) {
        LM_ERR("Error adding security header to reply!\n");
        pkg_free(sec_header->s);
        pkg_free(sec_header);
        return -1;
    }

    return 0;
}
Esempio n. 5
0
/**
 * 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. 
 * @param rpl - the 401 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_security_401(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	struct hdr_field *hdr;	
	str sec_hdr,sec_srv={0,0};
	r_security_type sec_type;
	char cmd[256];
	r_contact *c;
	r_ipsec *ipsec;
	float sec_q=-1;
	str auth;

	if (!pcscf_use_ipsec &&!pcscf_use_tls) goto	ret_false;
	
	req = cscf_get_request_from_reply(rpl);
	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_security_401: No transactional request found.\n");
		goto error;
	}
	auth = cscf_get_authenticate(rpl,&hdr);
	if (!auth.len){
		LOG(L_ERR,"ERR:"M_NAME":P_security_401: No WWW-Authenticate header found.\n");
		goto ret_false; 
	}
	
	sec_hdr = cscf_get_pref_security_header(req,s_security_client, &sec_type,&sec_q);
	if (!sec_hdr.len) {	
		LOG(L_DBG,"DBG:"M_NAME":P_security_401: No Security-Client header found.\n");
		goto ret_false;
	}
	LOG(L_INFO,"DBG:"M_NAME":P_security_401: Security-Client header found : <%.*s>.\n", sec_hdr.len, sec_hdr.s);	


	/* save data into registrar */
	c = save_contact_security(req, auth, sec_hdr, sec_type, sec_q);	
	if (!c) goto error;
	switch(sec_type){
		case SEC_NONE:
			break;
		case SEC_TLS:			
			/* try to add the Security-Server header */		
			sec_srv.len = s_security_server_s.len+sec_hdr.len+s_security_server_e.len;
			sec_srv.s = pkg_malloc(sec_srv.len);
			if (!sec_srv.s){
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len);
				goto error;
			}
			sec_srv.len=0;
			STR_APPEND(sec_srv,s_security_server_s);
			STR_APPEND(sec_srv,sec_hdr);
			STR_APPEND(sec_srv,s_security_server_e);

			if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) {
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s);
				pkg_free(sec_srv.s);
				goto error;
			}
			break;
		case SEC_IPSEC:
			ipsec = c->security_temp->data.ipsec;
			/* try to add the Security-Server header */
			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",
				ipsec->r_ealg.len,ipsec->r_ealg.s,
				ipsec->r_alg.len,ipsec->r_alg.s,
				ipsec->spi_pc,ipsec->spi_ps,
				pcscf_ipsec_port_c,pcscf_ipsec_port_s);
			
			sec_srv.len = strlen(cmd);
			sec_srv.s = pkg_malloc(sec_srv.len);
			if (!sec_srv.s){
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len);
				goto error;
			}
			memcpy(sec_srv.s,cmd,sec_srv.len);
			if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) {
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s);
				pkg_free(sec_srv.s);
				goto error;
			}
	
			/* run the IPSec script */	
			/* P_Inc_Req */
			sprintf(cmd,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Inc_Req,
				c->host.len,c->host.s,
				ipsec->port_uc,
				pcscf_ipsec_host,
				pcscf_ipsec_port_s,
				ipsec->spi_ps,
				ipsec->ealg.len,ipsec->ealg.s,
				ipsec->ck.len,ipsec->ck.s,
				ipsec->alg.len,ipsec->alg.s,
				ipsec->ik.len,ipsec->ik.s);

			r_unlock(c->hash);
				
			execute_cmd(cmd);
			break;						
	}
	
	return CSCF_RETURN_TRUE;
ret_false:
	return CSCF_RETURN_FALSE;
error:
	return CSCF_RETURN_ERROR;
}
Esempio n. 6
0
/**
 * Process the 401 response for REGISTER and creates the first Security-Associations.
 * Only the SA for P_Inc_Req - Incoming Requests is set now as the next REGISTER
 * could come over that one. 
 * @param rpl - the 401 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_IPSec_401(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	str auth;
	struct hdr_field *hdr;	
	str sec_cli,sec_srv={0,0};
	str ck,ik;
	char ck_c[64],ik_c[64];
	str ck_esp={ck_c,0},ik_esp={ik_c,0};
	str alg,ealg;
	str alg_setkey,ealg_setkey;
	str tmp;
	unsigned int spi_uc,spi_us;
	unsigned int spi_pc,spi_ps;
	int port_uc,port_us;
	char cmd[256];
	str ue;
	

	contact_body_t *contact;
	struct sip_uri uri;
	
	req = cscf_get_request_from_reply(rpl);
	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: No transactional request found.\n");
		goto error;
	}
	auth = cscf_get_authenticate(rpl,&hdr);
	if (!auth.len){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: No authorization header found.\n");
		goto error; 
	}
	sec_cli = cscf_get_security_client(req,&hdr);
	if (!sec_cli.len){
		LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: No Security-Client header found.\n");
		goto error; 
	}
	
	/* first we look for CK, IK */
	get_qparam(auth,s_ck,ck);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: CK: <%.*s>\n",
		ck.len,ck.s);
	get_qparam(auth,s_ik,ik);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: IK: <%.*s>\n",
		ik.len,ik.s);
	
	/* then for algorithms */
	get_param(sec_cli,s_ealg,ealg);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: Enc Algorithm: <%.*s>\n",
		ealg.len,ealg.s);
	get_param(sec_cli,s_alg,alg);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: Int Algorithm: <%.*s>\n",
		alg.len,alg.s);
	/* and for spis */
	get_param(sec_cli,s_spi_c,tmp);
	strtoint(tmp,spi_uc);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: SPI-C: %d\n",
		spi_uc);
	get_param(sec_cli,s_spi_s,tmp);
	strtoint(tmp,spi_us);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: SPI-S: %d\n",
		spi_us);
	/* and for ports */
	get_param(sec_cli,s_port_c,tmp);
	strtoint(tmp,port_uc);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: Port-C: %d\n",
		port_uc);
	get_param(sec_cli,s_port_s,tmp);
	strtoint(tmp,port_us);
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: Port-S: %d\n",
		port_us);
	
	
	contact = cscf_parse_contacts(req);
	if (!contact) {		
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: Message contains no Contact!\n");
		goto error;
	}
	if (contact->contacts){
		ue = contact->contacts->uri;
		if (parse_uri(ue.s,ue.len,&uri)){
			LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: Error parsing uri <%.*s>\n",ue.len,ue.s);
			goto error;
		}
		ue = uri.host;
		if (uri.port_no==0) port_uc=5060;
	}else
		ue = req->via1->host;
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_401: UE IP: <%.*s> \n",ue.len,ue.s);
	
	spi_pc=get_next_spi();	
	spi_ps=get_next_spi();	

	ck_esp.s[ck_esp.len++]='0';
	ck_esp.s[ck_esp.len++]='x';	
	if (ealg.len == s_des_in.len && strncasecmp(ealg.s,s_des_in.s,ealg.len)==0) {
		memcpy(ck_esp.s+ck_esp.len,ck.s,32);ck_esp.len+=32;
		memcpy(ck_esp.s+ck_esp.len,ck.s,16);ck_esp.len+=16;
		ealg_setkey = s_des_out;
	}
	else
	if (ealg.len == s_aes_in.len && strncasecmp(ealg.s,s_aes_in.s,ealg.len)==0) {
		memcpy(ck_esp.s+ck_esp.len,ck.s,ck.len);ck_esp.len+=ck.len;
		ealg_setkey = s_aes_out;
	}else {
		memcpy(ck_esp.s+ck_esp.len,ck.s,ck.len);ck_esp.len+=ck.len;
		ealg_setkey = s_null_out;
		ealg = s_null_out;
	}

	ik_esp.s[ik_esp.len++]='0';
	ik_esp.s[ik_esp.len++]='x';		
	if (alg.len == s_md5_in.len && strncasecmp(alg.s,s_md5_in.s,alg.len)==0) {
		memcpy(ik_esp.s+ik_esp.len,ik.s,ik.len);ik_esp.len+=ik.len;
		alg_setkey = s_md5_out;
	}
	else
	if (alg.len == s_sha_in.len && strncasecmp(alg.s,s_sha_in.s,alg.len)==0) {		
		memcpy(ik_esp.s+ik_esp.len,ik.s,ik.len);ik_esp.len+=ik.len;
		memcpy(ik_esp.s+ik_esp.len,"00000000",8);ik_esp.len+=8;
		alg_setkey = s_sha_out;
	}else{
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: Unknown Integrity algorithm <%.*s>\n",alg.len,alg.s);
		goto error;
	}

	/* try to add the Security-Server header */
	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",
		ealg.len,ealg.s,
		alg.len,alg.s,
		spi_pc,spi_ps,
		pcscf_ipsec_port_c,pcscf_ipsec_port_s);
		
	sec_srv.len = strlen(cmd);
	sec_srv.s = pkg_malloc(sec_srv.len);
	if (!sec_srv.s){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: Error allocating %d pkg bytes \n",sec_srv.len);
		goto error;
	}
	memcpy(sec_srv.s,cmd,sec_srv.len);
	if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) {
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s);
		pkg_free(sec_srv.s);
		goto error;
	}

	/* run the IPSec script */	
	/* P_Inc_Req */
	sprintf(cmd,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Inc_Req,
		ue.len,ue.s,
		port_uc,
		pcscf_ipsec_host,
		pcscf_ipsec_port_s,
		spi_ps,
		ealg_setkey.len,ealg_setkey.s,
		ck_esp.len,ck_esp.s,
		alg_setkey.len,alg_setkey.s,
		ik_esp.len,ik_esp.s);
	execute_cmd(cmd);
			
	/* save data into registrar */
	save_contact_ipsec(req,rpl,
		spi_uc,spi_us,spi_pc,spi_ps,port_uc,port_us,
		ealg_setkey,ck_esp,alg_setkey,ik_esp);
	
	
	return 1;	
error:
	return 0;	
}
Esempio n. 7
0
/**
 * Updates dialog on reply message
 * @param msg - the SIP message 
 * @param d - dialog to modify
 * @returns 1 on success or 0 on error
 */
int update_dialog_on_reply(struct sip_msg *msg, s_dialog *d)
{
	struct hdr_field *h_req;
	struct hdr_field *h=0;
	int res=0;
	time_t t_time=0;
	str ses_exp = {0,0};
	str refresher = {0,0};
	str new_ses_exp = {0,0};
	str new_ext = {0,0};
	int expires = 0;

	ses_exp = cscf_get_session_expires_body(msg, &h);
	t_time = cscf_get_session_expires(ses_exp, &refresher);
	if (!t_time) //i.e not session-expires header in response
	{
		if (!d->uac_supp_timer || !d->lr_session_expires)
		{
			expires = cscf_get_expires_hdr(msg,0);
			if (expires >= 0)
			{
			     d->expires = d_act_time()+expires;
			}
			else
			{
			     d->expires = d_act_time()+scscf_dialogs_expiration_time;
			}
		}
		else// uac supports timer, but no session-expires header found in response
		{
			d->expires = d_act_time()+d->lr_session_expires;
			
			new_ses_exp.len = 11/*int value*/ + str_se.len+s_refresher.len+8;
			new_ses_exp.s = pkg_malloc(new_ses_exp.len+1);
			if (!new_ses_exp.s) {
				LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ses_exp.len);
				goto error;
			}
			new_ses_exp.len = snprintf(new_ses_exp.s, new_ses_exp.len, "%.*s %d; %.*suac\r\n",str_se.len, str_se.s, (int)d->lr_session_expires ,s_refresher.len, s_refresher.s);
			cscf_add_header(msg, &new_ses_exp, HDR_OTHER_T);
			if (!requires_extension(msg, &str_ext_timer)) //must have require timer extenstion
			{
				/* walk through all Require headers to find first require header*/
				res = parse_headers(msg, HDR_EOH_F, 0);
				if (res == -1) {
					ERR("Error while parsing headers (%d)\n", res);
					return 0; /* what to return here ? */
				}
				
				h_req = msg->require;
				while (h_req) {
					if (h_req->type == HDR_REQUIRE_T) {
						if (h_req->body.s[new_ext.len-1]=='\n')
						{
							new_ext.len = str_require.len + 1/* */+h_req->body.len + 7;/*, timer*/
							new_ext.s = pkg_malloc(new_ext.len);
							if (!new_ext.s) {
								LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ext.len);
								goto error;
							}			
							new_ext.len = snprintf(new_ext.s, str_require.len, "%.*s %.*s, timer\r\n", str_require.len, str_require.s, h_req->body.len-2, h_req->body.s);
						}
						else
						{
							new_ext.len = str_require.len + 1/*space*/ + h_req->body.len + 9;/*, timer\r\n*/
							new_ext.s = pkg_malloc(new_ext.len);
							if (!new_ext.s) {
								LOG(L_ERR,"ERR:"M_NAME":update_dialog_on_reply: Error allocating %d bytes\n",new_ext.len);
								goto error;
							}			
							new_ext.len = snprintf(new_ext.s, str_require.len, "%.*s %.*s, timer\r\n", str_require.len, str_require.s, h_req->body.len, h_req->body.s);
						}
						cscf_del_header(msg, h_req);
						cscf_add_header(msg, &new_ext, HDR_REQUIRE_T);
						break;
					}
					h_req = h_req->next;
				}
			}
		}
	}
	else{
		d->expires = d_act_time() + t_time;
		d->lr_session_expires = t_time;
	}
	return 1;
error:
	if (new_ses_exp.s) pkg_free(new_ses_exp.s);
	if (new_ext.s) pkg_free(new_ext.s);
	return 0;	
}