コード例 #1
0
ファイル: third_party_reg.c プロジェクト: asyn/openvims
/**
 * Handle third party registration
 * @param msg - the SIP REGISTER message
 * @param m  - the isc_match that matched with info about where to forward it 
 * @param mark  - the isc_mark that should be used to mark the message
 * @returns #ISC_RETURN_TRUE if allowed, #ISC_RETURN_FALSE if not
 */
int isc_third_party_reg(struct sip_msg *msg, isc_match *m,isc_mark *mark)
{
	r_third_party_registration r;
	int expires=0;
	str req_uri ={0,0};
	str to ={0,0};
	str pvni ={0,0};
	str pani ={0,0};
	str cv ={0,0};

	struct hdr_field *hdr;

	LOG(L_INFO,"INFO:"M_NAME":isc_third_party_reg: Enter\n");

	/* Set Request Uri to IFC matching server name */
	req_uri.len = m->server_name.len;
	req_uri.s = m->server_name.s;

	/* Get To header*/
	to = cscf_get_public_identity(msg);


	/*TODO - check if the min/max expires is in the acceptable limits
	 * this does not work correctly if the user has multiple contacts
	 * and register/deregisters them individually!!!
	 */
	expires = cscf_get_max_expires(msg);
	
	/* Get P-Visited-Network-Id header */
	pvni = cscf_get_visited_network_id(msg, &hdr);
	/* Get P-Access-Network-Info header */
	pani = cscf_get_access_network_info(msg, &hdr);
	
	/* Get P-Charging-Vector header */
	/* Just forward the charging header received from P-CSCF */
	/* Todo: implement also according to TS 24.229, chap 5.4.1.7 */
	cv =   cscf_get_charging_vector(msg, &hdr);

	if (req_uri.s){
		
        memset(&r,0,sizeof(r_third_party_registration));

        r.req_uri = req_uri;
        r.to = to;
        r.from = isc_my_uri_sip;
        r.pvni = pvni;
        r.pani = pani;
		r.cv = cv;
        r.service_info = m->service_info;
         
		if (expires<=0) r_send_third_party_reg(&r,0);
		else r_send_third_party_reg(&r,expires+isc_expires_grace);
		return ISC_RETURN_TRUE;
	}else{
		return ISC_RETURN_FALSE;
	}	
}
コード例 #2
0
ファイル: registration.c プロジェクト: halan/kamailio
/**
 * Perform User Authorization Request.
 * creates and send the user authorization query
 * @param msg - the SIP message
 * @param str1 - the realm
 * @param str2 - if to do capabilities
 * @returns true if OK, false if not
 */
int I_perform_user_authorization_request(struct sip_msg* msg, char* str1, char* str2) {
    str private_identity, public_identity, visited_network_id;
    int authorization_type = AVP_IMS_UAR_REGISTRATION;
    int expires = 3600;
    struct hdr_field *hdr;
    str realm;
    contact_t *c;
    int sos_reg = 0;
    contact_body_t *b = 0;
    str call_id;
    saved_uar_transaction_t* saved_t;
    tm_cell_t *t = 0;
    int intvalue_param;
    cfg_action_t* cfg_action;

    uar_param_t* ap = (uar_param_t*) str1;
    if (fixup_get_ivalue(msg, ap->ivalue, &intvalue_param) != 0) {
        LM_ERR("no int value param passed\n");
        return CSCF_RETURN_ERROR;
    }
    cfg_action = ap->paction->next;

    realm = cscf_get_realm_from_ruri(msg);

    //check if we received what we should, we do this even though it should be done in cfg file - double checking!
    if (msg->first_line.type != SIP_REQUEST) {
        LM_ERR("ERR:I_UAR: The message is not a request\n");
        return CSCF_RETURN_ERROR;
    }
    if (msg->first_line.u.request.method.len != 8 ||
            memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
        LM_ERR("ERR:I_UAR: The method is not a REGISTER\n");
        return CSCF_RETURN_ERROR;
    }

    private_identity = cscf_get_private_identity(msg, realm);
    if (!private_identity.len) {
        LM_ERR("ERR:I_UAR: Private Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_PRIVATE);
        return CSCF_RETURN_BREAK;
    }

    public_identity = cscf_get_public_identity(msg);
    if (!public_identity.len) {
        LM_ERR("ERR:I_UAR: Public Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_PUBLIC);
        return CSCF_RETURN_BREAK;

    }

    b = cscf_parse_contacts(msg);

    if (!b || (!b->contacts && !b->star)) {
        LM_DBG("DBG:I_UAR: No contacts found\n");
        return CSCF_RETURN_ERROR;
    }

    for (c = b->contacts; c; c = c->next) {

        sos_reg = cscf_get_sos_uri_param(c->uri);
        if (sos_reg == -1) {
            //error case
            LM_ERR("ERR:I_UAR: MSG_400_MALFORMED_CONTACT, responding with 400\n");
            cscf_reply_transactional(msg, 400, MSG_400_MALFORMED_CONTACT);
            return CSCF_RETURN_BREAK;
        } else if (sos_reg == -2) {
            LM_ERR("ERR:I_UAR: MSG_500_SERVER_ERROR_OUT_OF_MEMORY, responding with 500\n");
            cscf_reply_transactional(msg, 500, MSG_500_SERVER_ERROR_OUT_OF_MEMORY);
            return CSCF_RETURN_BREAK;
        }
    }

    visited_network_id = cscf_get_visited_network_id(msg, &hdr);
    if (!visited_network_id.len) {
        LM_ERR("ERR:I_UAR: Visited Network Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_VISITED);
        return CSCF_RETURN_BREAK;
    }

    if (atoi(str1)) authorization_type = AVP_IMS_UAR_REGISTRATION_AND_CAPABILITIES;
    else {
        expires = cscf_get_max_expires(msg, 0);
        if (expires == 0) authorization_type = AVP_IMS_UAR_DE_REGISTRATION;
    }

    LM_DBG("SENDING UAR: PI: [%.*s], PU: [%.*s], VNID: [%.*s]\n", private_identity.len, private_identity.s,
            public_identity.len, public_identity.s,
            visited_network_id.len, visited_network_id.s);

    //before we send lets suspend the transaction
    t = tmb.t_gett();
    if (t == NULL || t == T_UNDEFINED) {
        if (tmb.t_newtran(msg) < 0) {
            LM_ERR("cannot create the transaction for UAR async\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
        t = tmb.t_gett();
        if (t == NULL || t == T_UNDEFINED) {
            LM_ERR("cannot lookup the transaction\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
    }

    saved_t = shm_malloc(sizeof (saved_uar_transaction_t));
    if (!saved_t) {
        LM_ERR("no more memory trying to save transaction state\n");
        return CSCF_RETURN_ERROR;

    }
    memset(saved_t, 0, sizeof (saved_uar_transaction_t));
    saved_t->act = cfg_action;

    call_id = cscf_get_call_id(msg, 0);
    saved_t->callid.s = (char*) shm_malloc(call_id.len + 1);
    if (!saved_t->callid.s) {
    	LM_ERR("no more memory trying to save transaction state : callid\n");
    	shm_free(saved_t);
    	return CSCF_RETURN_ERROR;
    }
    memset(saved_t->callid.s, 0, call_id.len + 1);
    memcpy(saved_t->callid.s, call_id.s, call_id.len);
    saved_t->callid.len = call_id.len;

    LM_DBG("Setting default AVP return code used for async callbacks to default as ERROR \n");
    create_uaa_return_code(CSCF_RETURN_ERROR);
    
    LM_DBG("Suspending SIP TM transaction\n");
    if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) {
        LM_ERR("failed to suspend the TM processing\n");
        free_saved_uar_transaction_data(saved_t);

        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        return CSCF_RETURN_BREAK;
    }

    if (cxdx_send_uar(msg, private_identity, public_identity, visited_network_id, authorization_type, sos_reg, saved_t) != 0) {
        LM_ERR("ERR:I_UAR: Error sending UAR or UAR time-out\n");
        tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
        free_saved_uar_transaction_data(saved_t);
        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        return CSCF_RETURN_BREAK;

    }
    //we use async replies therefore we send break and not true when successful
    return CSCF_RETURN_BREAK;
}
コード例 #3
0
ファイル: security.c プロジェクト: asyn/openvims
/**
 * 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. 
 * @param rpl - the 200 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_security_200(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	str sec_hdr;
	r_security_type sec_type;
	float sec_q;
	struct hdr_field *h;
	struct via_body *vb;
	r_contact *c;
	r_ipsec *i;
	int expires;
	unsigned long s_hash;
	char out_rpl[256],out_req[256],inc_rpl[256];

	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_200: No transactional request found.\n");
		goto error;
	}	

	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_200: No Security-Verify header found.\n");
		goto error;
	}
	
	/* find the expires (reg or dereg?) */
	expires = cscf_get_max_expires(req);
	
	/* get the IPSec info from the registrar */
	
	vb = cscf_get_first_via(req,&h);	
	LOG(L_DBG,"DBG:"M_NAME":P_security_200: Looking for <%d://%.*s:%d> \n",
		vb->proto,vb->host.len,vb->host.s,vb->port);

	c = get_r_contact(vb->host,vb->port,vb->proto);
		
	r_act_time();
	if (!c){
		LOG(L_ERR,"ERR:"M_NAME":P_security_200: Contact not found\n");		
		goto error;
	}
	
	if (c->security_temp){
		if (c->security && c->security->type == SEC_TLS && 
				(c->security->data.tls && c->security->data.tls->port_tls==req->rcv.src_port&& 
				 c->security->data.tls->session_hash!=0 && c->security->data.tls->session_hash == tls_get_session_hash(req))){
			/* don't replace security when doing an integrity protected REGISTER with
			 *  possible attack-garbage from security_temp */
			P_security_drop(c,c->security_temp);
			free_r_security(c->security_temp);
			c->security_temp = 0;
		}
		else
		{	
			if (c->security) {
				P_security_drop(c,c->security);
				free_r_security(c->security);
			}
			
			c->security = c->security_temp;
			c->security_temp = 0;
		}
	}	
	
	switch(sec_type){
		case SEC_NONE:
			break;
		case SEC_TLS:
			if (c->security && pcscf_use_tls) {
				r_tls *tls;
				int port_tls = req->rcv.src_port;
				s_hash = get_tls_session_hash(req);
				if (!s_hash){
					LOG(L_ERR,"ERR:"M_NAME":P_security_200: Session Hash could not be obtained !\n");
					r_unlock(c->hash);
					goto error;
				}	
				tls = new_r_tls(port_tls, s_hash);
				if (!tls) goto error;
				c->security->data.tls = tls;
			} 		
			r_unlock(c->hash);
			break;
		case SEC_IPSEC:
			if (!r_valid_contact(c)||!c->security||!c->security->data.ipsec ){
				LOG(L_DBG,"DBG:"M_NAME":P_security_200: Contact expired or no IPSec info\n");
				r_unlock(c->hash);
				goto error;
			}
			i = c->security->data.ipsec;
			
			/* P_Out_Rpl */
			sprintf(out_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Out_Rpl,
				c->host.len,c->host.s,
				i->port_uc,
				pcscf_ipsec_host,
				pcscf_ipsec_port_s,
				i->spi_uc,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);					
	
			/* P_Out_Req */
			sprintf(out_req,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Out_Req,
				c->host.len,c->host.s,
				i->port_us,
				pcscf_ipsec_host,
				pcscf_ipsec_port_c,
				i->spi_us,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);								
			/* P_Out_Inc_Rpl */
			sprintf(inc_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Inc_Rpl,
				c->host.len,c->host.s,
				i->port_us,
				pcscf_ipsec_host,
				pcscf_ipsec_port_c,
				i->spi_pc,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);								
				
			if (expires<=0) {
				/* Deregister */
				c->reg_state = DEREGISTERED;
				r_act_time();
				c->expires = time_now + 60;
			}			
			r_unlock(c->hash);
		
			//print_r(L_CRIT);
			
			/* run the IPSec scripts */	
			/* Registration */
			execute_cmd(out_rpl);		
			execute_cmd(out_req);		
			execute_cmd(inc_rpl);
			break;
	}
	
	return CSCF_RETURN_TRUE;
ret_false:
	return CSCF_RETURN_FALSE;
error:
	return CSCF_RETURN_ERROR;
}
コード例 #4
0
ファイル: security.c プロジェクト: asyn/openvims
/**
 * 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. 
 * @param rpl - the 200 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_IPSec_200(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	struct hdr_field *hdr;	
	str sec_cli;
	struct hdr_field *h;
	struct via_body *vb;
	r_contact *c;
	r_ipsec *i;
	int expires;
	char out_rpl[256],out_req[256],inc_rpl[256];

	req = cscf_get_request_from_reply(rpl);
	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: No transactional request found.\n");
		goto error;
	}	
	/* just to jump out if no IPSec is employed - the info is already saved */
	sec_cli = cscf_get_security_client(req,&hdr);
	if (!sec_cli.len){
		LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: No Security-Client header found.\n");
		goto error; 
	}

	/* find the expires (reg or dereg?) */
	expires = cscf_get_max_expires(req);
	
	/* get the IPSec info from the registrar */
	
	vb = cscf_get_first_via(req,&h);
//	if (!h||!h->parsed){
//		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: Error extracting sender's id.\n");
//		goto error;
//	}		
//	vb = (struct via_body*) h->parsed;
	
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: Looking for <%d://%.*s:%d> \n",
		vb->proto,vb->host.len,vb->host.s,vb->port);

	c = get_r_contact(vb->host,vb->port,vb->proto);
		
	r_act_time();
	if (!c){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: Contact not found\n");		
		goto error;
	}
	if (!r_valid_contact(c)||!c->ipsec){
		LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: Contact expired or no IPSec info\n");
		r_unlock(c->hash);
		goto error;
	}
	
	i = c->ipsec;
		
	/* P_Out_Rpl */
	sprintf(out_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Out_Rpl,
		c->host.len,c->host.s,
		i->port_uc,
		pcscf_ipsec_host,
		pcscf_ipsec_port_s,
		i->spi_uc,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);					

	/* P_Out_Req */
	sprintf(out_req,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Out_Req,
		c->host.len,c->host.s,
		i->port_us,
		pcscf_ipsec_host,
		pcscf_ipsec_port_c,
		i->spi_us,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);								
	/* P_Out_Inc_Rpl */
	sprintf(inc_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Inc_Rpl,
		c->host.len,c->host.s,
		i->port_us,
		pcscf_ipsec_host,
		pcscf_ipsec_port_c,
		i->spi_pc,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);								
		
	if (expires<=0) {
		/* Deregister */
		c->reg_state = DEREGISTERED;
		r_act_time();
		c->expires = time_now + 60;
	}			
	r_unlock(c->hash);

	//print_r(L_CRIT);
	
	/* run the IPSec scripts */	
	/* Registration */
	execute_cmd(out_rpl);		
	execute_cmd(out_req);		
	execute_cmd(inc_rpl);
	return 1;	
error:
	return 0;	
}
コード例 #5
0
ファイル: mod.c プロジェクト: Jared-Prime/kamailio
/* Wrapper to send AAR from config file - only used for registration */
static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* bar) {

    int ret = CSCF_RETURN_ERROR;
    struct pcontact_info ci;
    struct cell *t;
    contact_t* c;
    struct hdr_field* h;
    pcontact_t* pcontact;
    contact_body_t* cb = 0;
    AAASession* auth;
    rx_authsessiondata_t* rx_regsession_data_p;
    cfg_action_t* cfg_action = 0;
    str route_name;
    char* p;
    int aar_sent = 0;
    saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
    saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
    
    if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
        LM_ERR("no async route block for assign_server_unreg\n");
        return -1;
    }
    
    LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
    int ri = route_get(&main_rt, route_name.s);
    if (ri < 0) {
        LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }
    cfg_action = main_rt.rlist[ri];
    if (cfg_action == NULL) {
        LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }
    
    udomain_t* domain_t = (udomain_t*) str1;
    
    int is_rereg = 0; //is this a reg/re-reg

    LM_DBG("Rx AAR Register called\n");

    //create the default return code AVP
    create_return_code(ret);

    memset(&ci, 0, sizeof (struct pcontact_info));

    /** If this is a response then let's check the status before we try and do an AAR.
     * We will only do AAR for register on success response and of course if message is register
     */
    if (msg->first_line.type == SIP_REPLY) {
        //check this is a response to a register
        /* Get the SIP request from this transaction */
        t = tmb.t_gett();
        if (!t) {
            LM_ERR("Cannot get transaction for AAR based on SIP Request\n");
            goto error;
        }
        if ((strncmp(t->method.s, "REGISTER", 8) != 0)) {
            LM_ERR("Method is not a response to a REGISTER\n");
            goto error;
        }
        if (msg->first_line.u.reply.statuscode < 200
                || msg->first_line.u.reply.statuscode >= 300) {
            LM_DBG("Message is not a 2xx OK response to a REGISTER\n");
            goto error;
        }
        tmb.t_release(msg);
    } else { //SIP Request
        /* in case of request make sure it is a REGISTER */
        if (msg->first_line.u.request.method_value != METHOD_REGISTER) {
            LM_DBG("This is not a register request\n");
            goto error;
        }

        if ((cscf_get_max_expires(msg, 0) == 0)) {
            //if ((cscf_get_expires(msg) == 0)) {
            LM_DBG("This is a de registration\n");
            LM_DBG("We ignore it as these are dealt with by usrloc callbacks \n");
            create_return_code(CSCF_RETURN_TRUE);
            return CSCF_RETURN_TRUE;
        }
    }

    //before we continue, make sure we have a transaction to work with (viz. cdp async)
    t = tmb.t_gett();
    if (t == NULL || t == T_UNDEFINED) {
        if (tmb.t_newtran(msg) < 0) {
            LM_ERR("cannot create the transaction for UAR async\n");
            return CSCF_RETURN_ERROR;
        }
        t = tmb.t_gett();
        if (t == NULL || t == T_UNDEFINED) {
            LM_ERR("cannot lookup the transaction\n");
            return CSCF_RETURN_ERROR;
        }
    }

    saved_t_data = (saved_transaction_t*) shm_malloc(sizeof (saved_transaction_t));
    if (!saved_t_data) {
        LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
        return CSCF_RETURN_ERROR;
    }
    memset(saved_t_data, 0, sizeof (saved_transaction_t));
    saved_t_data->act = cfg_action;
    saved_t_data->domain = domain_t;
    saved_t_data->lock = lock_alloc();
    if (saved_t_data->lock == NULL) {
        LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
        return CSCF_RETURN_ERROR;
    }
    if (lock_init(saved_t_data->lock) == NULL) {
        LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
        return CSCF_RETURN_ERROR;
    }

    LM_DBG("Suspending SIP TM transaction\n");
    if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) < 0) {
        LM_ERR("failed to suspend the TM processing\n");
        free_saved_transaction_global_data(saved_t_data);
        return CSCF_RETURN_ERROR;
    }

    LM_DBG("Successfully suspended transaction\n");

    //now get the contacts in the REGISTER and do AAR for each one.
    cb = cscf_parse_contacts(msg);
    if (!cb || (!cb->contacts && !cb->star)) {
        LM_DBG("No contact headers in Register message\n");
        goto error;
    }

    lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
    for (h = msg->contact; h; h = h->next) {
        if (h->type == HDR_CONTACT_T && h->parsed) {
            for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
                ul.lock_udomain(domain_t, &c->uri);
                if (ul.get_pcontact(domain_t, &c->uri, &pcontact) != 0) {
                    LM_DBG("This contact does not exist in PCSCF usrloc - error in cfg file\n");
                    ul.unlock_udomain(domain_t, &c->uri);
                    lock_release(saved_t_data->lock);
                    goto error;
                } else if (pcontact->reg_state == PCONTACT_REG_PENDING
                        || pcontact->reg_state == PCONTACT_REGISTERED) { //NEW reg request
                    LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
                            , pcontact->aor.len, pcontact->aor.s);

                    //get IP address from contact
                    struct sip_uri puri;
                    if (parse_uri(c->uri.s, c->uri.len, &puri) < 0) {
                        LM_ERR("failed to parse Contact\n");
                        ul.unlock_udomain(domain_t, &c->uri);
                        lock_release(saved_t_data->lock);
                        goto error;

                    }
                    LM_DBG("Parsed URI of from host is [%.*s]\n", puri.host.len, puri.host.s);
                    uint16_t ip_version = AF_INET; //TODO IPv6!!!?

                    //check for existing Rx session
                    if (pcontact->rx_session_id.len > 0
                            && pcontact->rx_session_id.s
                            && (auth = cdpb.AAAGetAuthSession(pcontact->rx_session_id))) {
                        LM_DBG("Rx session already exists for this user\n");
                        if (memcmp(pcontact->rx_session_id.s, auth->id.s, auth->id.len) != 0) {
                            LM_ERR("Rx session mismatch when URI is [%.*s].......Aborting\n", puri.host.len, puri.host.s);
                            if (auth) cdpb.AAASessionsUnlock(auth->hash);
                            lock_release(saved_t_data->lock);
                            goto error;
                        }
                        //re-registration - update auth lifetime
                        auth->u.auth.lifetime = time(NULL) + rx_auth_expiry;
                        is_rereg = 1;
                    } else {
                        LM_DBG("Creating new Rx session for contact <%.*s>\n", pcontact->aor.len, pcontact->aor.s);
                        int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &rx_regsession_data_p);
                        if (!ret) {
                            LM_ERR("Unable to create regsession data parcel when URI is [%.*s]...Aborting\n", puri.host.len, puri.host.s);
                            ul.unlock_udomain(domain_t, &c->uri);
                            if (rx_regsession_data_p) {
                                shm_free(rx_regsession_data_p);
                                rx_regsession_data_p = 0;
                            }
                            lock_release(saved_t_data->lock);
                            goto error;
                        }
                        auth = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_regsession_data_p); //returns with a lock
                        if (!auth) {
                            LM_ERR("Rx: unable to create new Rx Reg Session when URI is [%.*s]\n", puri.host.len, puri.host.s);
                            if (rx_regsession_data_p) {
                                shm_free(rx_regsession_data_p);
                                rx_regsession_data_p = 0;
                            }
                            ul.unlock_udomain(domain_t, &c->uri);
                            if (auth) cdpb.AAASessionsUnlock(auth->hash);
                            if (rx_regsession_data_p) {
                                shm_free(rx_regsession_data_p);
                                rx_regsession_data_p = 0;
                            }
                            lock_release(saved_t_data->lock);
                            goto error;
                        }
                    }

                    //we are ready to send the AAR async. lets save the local data data
                    int local_data_len = sizeof (saved_transaction_local_t) + c->uri.len + auth->id.len;
                    local_data = shm_malloc(local_data_len);
                    if (!local_data) {
                        LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
                        lock_release(saved_t_data->lock);
                        goto error;
                    }
                    memset(local_data, 0, local_data_len);

                    local_data->is_rereg = is_rereg;
                    local_data->global_data = saved_t_data;
                    p = (char*) (local_data + 1);

                    local_data->contact.s = p;
                    local_data->contact.len = c->uri.len;
                    memcpy(p, c->uri.s, c->uri.len);
                    p += c->uri.len;

                    local_data->auth_session_id.s = p;
                    local_data->auth_session_id.len = auth->id.len;
                    memcpy(p, auth->id.s, auth->id.len);
                    p += auth->id.len;

                    if (p != (((char*) local_data) + local_data_len)) {
                        LM_CRIT("buffer overflow\n");
                        free_saved_transaction_data(local_data);
                        goto error;
                    }

                    LM_DBG("Calling send aar register");

                    //TODOD remove - no longer user AOR parm
                    //ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
                    ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, local_data); //returns a locked rx auth object

                    ul.unlock_udomain(domain_t, &c->uri);

                    if (!ret) {
                        LM_ERR("Failed to send AAR\n");
                        lock_release(saved_t_data->lock);
                        free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
                        goto error;
                    } else {
                        aar_sent = 1;
                        //before we send - bump up the reply counter
                        saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
                    }
                } else {
                    //contact exists - this is a re-registration, for now we just ignore this
                    LM_DBG("This contact exists and is not in state REGISTER PENDING - we assume re (or de) registration and ignore\n");
                    ul.unlock_udomain(domain_t, &c->uri);
                    //now we loop for any other contacts.
                }
            }
        } else {
            if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
                LM_ERR("Failed to parse contact header\n");
                lock_release(saved_t_data->lock);
                goto error;
            }
        }
    }
    //all requests sent at this point - we can unlock the reply lock
    lock_release(saved_t_data->lock);

    /*if we get here, we have either:
     * 1. Successfully sent AAR's for ALL contacts, or
     * 2. haven't needed to send ANY AAR's for ANY contacts
     */
    if (aar_sent) {
        LM_DBG("Successful async send of AAR\n");
        return CSCF_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
    } else {
        create_return_code(CSCF_RETURN_TRUE);
        tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
        if (saved_t_data) {
            free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
        }
        //return CSCF_RETURN_ERROR;
        return CSCF_RETURN_TRUE;
    }
error:
    LM_ERR("Error trying to send AAR\n");
    if (!aar_sent) {
        tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
        if (saved_t_data) {
            free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
            //otherwise the callback will segfault
        }
    }
    return CSCF_RETURN_ERROR;
    //return CSCF_RETURN_FALSE;
}
コード例 #6
0
ファイル: third_party_reg.c プロジェクト: adubovikov/kamailio
/**
 * Handle third party registration
 * @param msg - the SIP REGISTER message
 * @param m  - the isc_match that matched with info about where to forward it
 * @param mark  - the isc_mark that should be used to mark the message
 * @returns #ISC_RETURN_TRUE if allowed, #ISC_RETURN_FALSE if not
 */
int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark, udomain_t* d) {
    r_third_party_registration r;
    str path, path_received;
    int expires = 0;
    str req_uri = {0, 0};
    str to = {0, 0};
    str pvni = {0, 0};
    str pani = {0, 0};
    str cv = {0, 0};
	str s = {0, 0};

	impurecord_t *p;

    struct hdr_field *hdr;

    LM_DBG("isc_third_party_reg: Enter\n");

    /* Set Request Uri to IFC matching server name */
    req_uri.len = m->server_name.len;
    req_uri.s = m->server_name.s;

    /* Get To header*/
    to = cscf_get_public_identity(msg);

	if (cscf_get_originating_user(msg, &s)) {

		isc_ulb.lock_udomain(d, &s);
		if ( isc_ulb.get_impurecord(d,&s,&p) != 0) {
			isc_ulb.unlock_udomain(d, &s);
			LM_ERR("Failed to get IMPU domain from usrloc\n");
			goto no_pai;
		}
		if ( build_p_associated_uri(p->s) != 0) {
			isc_ulb.unlock_udomain(d, &s);
			LM_ERR("Failed to build P-Associated URI for 3rd party reg\n");
			goto no_pai;
		}
		isc_ulb.unlock_udomain(d, &s);
	}

    /*TODO - check if the min/max expires is in the acceptable limits
     * this does not work correctly if the user has multiple contacts
     * and register/deregisters them individually!!!
     */
no_pai:
    expires = cscf_get_max_expires(msg, 0);

    /* Get P-Visited-Network-Id header */
    pvni = cscf_get_visited_network_id(msg, &hdr);
    /* Get P-Access-Network-Info header */
    pani = cscf_get_access_network_info(msg, &hdr);

    if (build_path_vector(msg, &path, &path_received) < 0) {
	LM_ERR("Failed to parse PATH header for third-party reg\n");
	return ISC_RETURN_FALSE;
    }
    LM_DBG("PATH header in REGISTER is [%.*s]\n", path.len, path.s);

    /* Get P-Charging-Vector header */
    /* Just forward the charging header received from P-CSCF */
    /* Todo: implement also according to TS 24.229, chap 5.4.1.7 */
    cv = cscf_get_charging_vector(msg, &hdr);

    if (req_uri.s) {

	memset(&r, 0, sizeof (r_third_party_registration));

	r.req_uri = req_uri;
	r.to = to;
	r.from = isc_my_uri_sip;
	r.pvni = pvni;
	r.pani = pani;
	r.cv = cv;
	if (m->service_info.s && m->service_info.len) {
		r.body.content_type = CT_SERVICE_INFO;
		r.body.content = m->service_info;
	} else if (m->include_register_request) {
		r.body.content_type = CT_REGISTER_REQ;
                r.body.content.s = msg->first_line.u.request.method.s;
		r.body.content.len = msg->len;
	} else if (m->include_register_response) {
		struct bookmark dummy_bm;
		r.body.content_type = CT_REGISTER_RESP;
                r.body.content.s = build_res_buf_from_sip_req(200, &reg_resp_200OK, 0, msg, (unsigned int*)&r.body.content.len, &dummy_bm);
		if (!r.body.content.s) {
			LM_DBG("response building failed for body of third party register request");
			r.body.content_type = CT_NONE;
		}
	} else {
		r.body.content_type = CT_NONE;
	}
	r.path = path;

	if (expires <= 0)
	    r_send_third_party_reg(&r, 0);
	else
	    r_send_third_party_reg(&r, expires + isc_expires_grace);
	return ISC_RETURN_TRUE;
    } else {
	return ISC_RETURN_FALSE;
    }
}