Ejemplo n.º 1
0
/**
 * Returns the expires value from the message.
 * First it searches into the Expires header and if not found it also looks 
 * into the expires parameter in the contact header
 * @param msg - the SIP message
 * @param is_shm - msg from shared memory
 * @returns the value of the expire or the default 3600 if none found
 */
int cscf_get_max_expires(struct sip_msg *msg, int is_shm)
{
	unsigned int exp;
	int max_expires = -1;
	struct hdr_field *h;
	contact_t *c;
	/*first search in Expires header */
	max_expires = cscf_get_expires_hdr(msg, is_shm);

	cscf_parse_contacts(msg);
	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){
				if(c->expires){
					if (!str2int(&(c->expires->body), (unsigned int*)&exp) && (int)exp>max_expires) max_expires = exp;
				}
			}
		}	
	}

	if(is_shm){
		for(h=msg->contact;h;h=h->next){
			if (h->type==HDR_CONTACT_T && h->parsed) {
				free_contact((contact_body_t**)&(h->parsed));
				h->parsed = 0;
			}
		}
	}

	return max_expires;
}
Ejemplo n.º 2
0
/**
 * Saves the IPSec information into the P-CSCF registrar for this contact.
 * @param req - REGISTER request
 * @param rpl - REGISTER respons
 * @param spi_uc - SPI for UE client
 * @param spi_us - SPI for UE server
 * @param spi_pc - SPI for PCSCF client
 * @param spi_ps - SPI for PCSCF server
 * @param port_uc - port for UE client
 * @param port_us - port for UE server
 * @param ealg_setkey - Chypher algorithm
 * @param ck_esp - Cypher Key
 * @param alg_setkey - Integrity algorithm
 * @param ik_esp - Integrity Key
 */
void save_contact_ipsec(struct sip_msg *req,struct sip_msg *rpl,
	int spi_uc,int spi_us,int spi_pc,int spi_ps,int port_uc,int port_us,
	str ealg_setkey,str ck_esp,str alg_setkey,str ik_esp)
{
	contact_t* c=0;
	contact_body_t* b=0;	
	r_contact *rc;
	enum Reg_States reg_state=REG_PENDING;
	int expires,pending_expires=60;
	struct sip_uri puri;
	r_ipsec *ipsec;

	
	if (parse_headers(rpl, HDR_EOH_F, 0) <0) {
		LOG(L_ERR,"ERR:"M_NAME":save_contact_ipsec: error parsing headers\n");
		return ;
	}	
	
	b = cscf_parse_contacts(req);
	
	if (!b||!b->contacts) {
		LOG(L_ERR,"ERR:"M_NAME":save_contact_ipsec: No contacts found\n");
		return;
	}
	
	if (b) c = b->contacts;
			
	r_act_time();
	while(c){
		LOG(L_DBG,"DBG:"M_NAME":save_contact_ipsec: <%.*s>\n",c->uri.len,c->uri.s);
		
		expires = time_now+pending_expires;
		
		if (parse_uri(c->uri.s,c->uri.len,&puri)<0){
			LOG(L_DBG,"DBG:"M_NAME":save_contact_ipsec: Error parsing Contact URI <%.*s>\n",c->uri.len,c->uri.s);
			goto next;			
		}
		if (puri.port_no==0) puri.port_no=5060;
		LOG(L_DBG,"DBG:"M_NAME":save_contact_ipsec: %d %.*s : %d\n",
			puri.proto, puri.host.len,puri.host.s,puri.port_no);

		ipsec = new_r_ipsec(spi_uc,spi_us,spi_pc,spi_ps,port_uc,port_us,
			ealg_setkey,ck_esp,alg_setkey,ik_esp);
			
		rc = update_r_contact_sec(puri.host,ipsec->port_us,puri.proto,
			&(c->uri),&reg_state,&expires,
			ipsec);

next:		
		c = c->next;
	}
	
	//print_r(L_CRIT);
}
Ejemplo n.º 3
0
/**
 * Subscribe to the reg event to the S-CSCF.
 * @param rpl - 200 OK response to REGISTER containing contacts and Service-Route header
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if subscribed, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_ERROR on error
 */
int P_subscribe(struct sip_msg *rpl, char* str1, char* str2)
{
	int expires_hdr=0,r,max_expires;
	str public_id={0,0};
	contact_t* c=0;
	contact_body_t* b=0;	
	
	cscf_get_first_p_associated_uri(rpl,&public_id);
	
	expires_hdr = cscf_get_expires_hdr(rpl);
	
	if (parse_headers(rpl, HDR_EOH_F, 0) <0) {
		LOG(L_ERR,"ERR:"M_NAME":P_subscribe: error parsing headers\n");
		return CSCF_RETURN_ERROR;
	}	
	
	b = cscf_parse_contacts(rpl);
	
	if (!b||!b->contacts) {
		LOG(L_DBG,"DBG:"M_NAME":P_subscribe: No contacts found\n");
		return CSCF_RETURN_FALSE;
	}
	
	if (b) c = b->contacts;
	
	max_expires = expires_hdr;
	while(c){
		r = expires_hdr;
		if (str2int(&(c->expires->body), (unsigned int*)&r) < 0) {
			r = 0;
		}
		if (r>max_expires) max_expires = r;
		c = c->next;
	}
	if (max_expires<=0){
		LOG(L_INFO,"DBG:"M_NAME":P_subscribe: skipped because de-register\n");		
		return CSCF_RETURN_FALSE;		
	}
	
	if (public_id.s){
//		if (max_expires==0)
//			r_subscribe(public_id,0);
//		else
		r_subscribe(public_id,max_expires+30);
		return CSCF_RETURN_TRUE;
	}else{
		return CSCF_RETURN_FALSE;
	}
}
Ejemplo n.º 4
0
/*
 * sends an AAR for every registered contact
 * returns CSCF_RETURN_TRUE on ok and CSCF_RETURN_FALSE on error
 * TODO:on error: if any AAR was sent, STR will be sent by the authstatemachine
 */
int P_AAR_register(struct sip_msg *req, struct sip_msg * rpl) {

    AAAMessage* resp;
    unsigned int result = AAA_SUCCESS;
    contact_body_t * aor_list;
    contact_t * crt_aor = NULL;
    str pcc_session_id = {0,0};

    if (parse_headers(rpl, HDR_EOH_F, 0) <0) {
        LOG(L_ERR,"ERR:"M_NAME":P_Rx_register: error parsing headers\n");
        return CSCF_RETURN_FALSE;
    }

    aor_list = cscf_parse_contacts(req);
    if (!aor_list || (!aor_list->contacts && !aor_list->star)) {
        LOG(L_ERR,"ERR:"M_NAME":P_Rx_register: no contacts found in the Contact header\n");
        return CSCF_RETURN_FALSE;
    }

    for(crt_aor = aor_list->contacts; crt_aor!=NULL; crt_aor= crt_aor->next) {
        resp = PCC_AAR(req, rpl, "reg", crt_aor, &pcc_session_id, 0);
        if(!resp)
            goto error;
        if(PCC_AAA(resp, &result, pcc_session_id) > 0) {
            LOG(L_INFO,"INFO:"M_NAME":P_Rx_register:recieved an AAA with result code %u\n",result);
            if(result<2000 || result >= 3000) {
                cdpb.AAAFreeMessage(&resp);
                goto error;
            }

        }
        cdpb.AAAFreeMessage(&resp);
    }

    return CSCF_RETURN_TRUE;

error:
    LOG(L_INFO,"INFO:"M_NAME":P_Rx_register:recieved an AAA with error code or null AAA\n");
    return CSCF_RETURN_FALSE;
}
Ejemplo n.º 5
0
Archivo: sip.c Proyecto: asyn/openvims
/**
 * Returns the expires value from the message.
 * First it searches into the Expires header and if not found it also looks 
 * into the expires parameter in the contact header
 * @param msg - the SIP message
 * @returns the value of the expire or the default 3600 if none found
 */
int cscf_get_max_expires(struct sip_msg *msg)
{
	unsigned int exp;
	int max_expires = -1;
	struct hdr_field *h;
	contact_t *c;
	/*first search in Expires header */
	max_expires = cscf_get_expires_hdr(msg);
	
	cscf_parse_contacts(msg);
	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){
				if(c->expires){
					if (!str2int(&(c->expires->body), (unsigned int*)&exp) && (int)exp>max_expires) max_expires = exp;
				}
			}
		}	
	}
	LOG(L_DBG,"DBG:"M_NAME":cscf_get_max_expires: <%d> \n",max_expires);
	return max_expires;
}
Ejemplo n.º 6
0
/**
 * P_STR() will be called, if PCSCF receives BYE, CANCEL, 3xx, 4xx, 5xx or 6xx.
 * It terminates the created auth session with the PDF.
 *
 */
int P_STR(struct sip_msg* msg, char* str1, char* str2)
{
    // get session id from sip msg
    // Gq_STR(session_id) terminate the session
    AAAMessage* sta=0;
    contact_t * crt_cnt = NULL;
    contact_body_t * cnt_list;

    if (!pcscf_use_pcc) return CSCF_RETURN_TRUE;

    LOG(L_INFO, ANSI_WHITE"INF:"M_NAME":P_STR:\n");

    int is_register=(str1 && (str1[0]=='r' || str1[0]=='R'));

    if(is_register) {
        if (parse_headers(msg, HDR_EOH_F, 0) <0) {
            LOG(L_ERR,"ERR:"M_NAME":P_STR: error parsing headers\n");
            return CSCF_RETURN_FALSE;
        }

        cnt_list = cscf_parse_contacts(msg);
        if (!cnt_list || (!cnt_list->contacts && !cnt_list->star)) {
            LOG(L_ERR,"ERR:"M_NAME":P_STR: no contacts found in the Contact header\n");
            return CSCF_RETURN_FALSE;
        }

        for(crt_cnt = cnt_list->contacts; crt_cnt!=NULL; crt_cnt= crt_cnt->next) {
            sta = PCC_STR(msg,str1, crt_cnt);
            // if you really want the STA just declare a ResponseHandler for it because its never going
            // to arrive here.. or never again
            if (sta) cdpb.AAAFreeMessage(&sta);
        }
    } else {
        sta = PCC_STR(msg,str1, NULL);
    }

    return CSCF_RETURN_TRUE;
}
Ejemplo n.º 7
0
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state, char service_routes[][MAXROUTESIZE], int num_service_routes) {
	ppublic_t * p;
	contact_body_t *b = 0;
	contact_t *ct;
	pcontact_info_t search_ci;
	str received_host = {0, 0};
	char srcip[50];
	struct via_body *vb;
	unsigned short port, proto;
	str host;
	sip_uri_t contact_uri;
	int mustRetryViaSearch = 0;
	int mustRetryReceivedSearch = 0;

	LM_DBG("number of service routes to look for is %d\n", num_service_routes);
    b = cscf_parse_contacts(_m);

    if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) {
		mustRetryViaSearch = 1;
		mustRetryReceivedSearch = 1;
        LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n");
        ct = b->contacts;
        host = ct->uri;
        if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) {
            LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s);
            return NULL;
        }
        host = contact_uri.host;
        port = contact_uri.port_no ? contact_uri.port_no : 5060;
        proto = contact_uri.proto;
        if (proto == 0) {
            LM_DBG("Contact protocol not specified - using received\n");
            proto = _m->rcv.proto;
        }
    } else {
        if (_m->first_line.type == SIP_REPLY)
            LM_DBG("This is a reply but we are forced to use the via header\n");
        else
            LM_DBG("This is a request - using first via to find contact\n");

        vb = cscf_get_ue_via(_m);
        host = vb->host;
        port = vb->port ? vb->port : 5060;
        proto = vb->proto;
    }

    LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port);

    received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip));
    received_host.s = srcip;

//    if (_m->id != current_msg_id) {
        current_msg_id = _m->id;
        c = NULL;
	//search_ci.reg_state = PCONTACT_REGISTERED;          //we can do this because this function is always called expecting a REGISTERED contact
	memset(&search_ci, 0, sizeof(struct pcontact_info));
    search_ci.reg_state = reg_state;
	search_ci.received_host.s = received_host.s;
	search_ci.received_host.len = received_host.len;
	search_ci.received_port = _m->rcv.src_port;
	search_ci.received_proto = _m->rcv.proto;
	search_ci.searchflag = SEARCH_RECEIVED;
	search_ci.num_service_routes = 0;
	if (is_registered_fallback2ip == 1) {
		search_ci.searchflag = SEARCH_NORMAL;
	} 
	search_ci.via_host = host;
	search_ci.via_port = port;
	search_ci.via_prot = proto;
	search_ci.aor.s = 0;
	search_ci.aor.len = 0;
	
	int size = num_service_routes==0?1:num_service_routes;
	str s_service_routes[size];
	int i;
	for (i=0;i<num_service_routes;i++) {
		s_service_routes[i].s = service_routes[i];
		s_service_routes[i].len = strlen(service_routes[i]);
		LM_DBG("Setting service routes str for pos %d to %.*s", i, s_service_routes[i].len, s_service_routes[i].s);
	}
	if (num_service_routes > 0) {
		LM_DBG("asked to search for specific service routes...\n");
		search_ci.service_routes = s_service_routes;
		search_ci.num_service_routes = num_service_routes;
		search_ci.extra_search_criteria = SEARCH_SERVICE_ROUTES;
	}

//	b = cscf_parse_contacts(_m);
tryagain:
	if (b && b->contacts) {
		for (ct = b->contacts; ct; ct = ct->next) {
			search_ci.aor = ct->uri;
			if (ul.get_pcontact(_d, &search_ci, &c) == 0) {
				if (checkcontact(_m, c) != 0) {
					c = NULL;
				} else {
					break;
				}
			}
		}
	} else {
		LM_WARN("No contact-header found...\n");
	}

	if ((c == NULL) && (is_registered_fallback2ip == 1)) {
		LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n");
		//			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
		//			received_host.s = srcip;
		search_ci.searchflag = SEARCH_RECEIVED;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
			LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	if ((c == NULL) && (is_registered_fallback2ip == 2)) {
		LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n");
		search_ci.searchflag = SEARCH_NORMAL;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	asserted_identity = NULL;
	registration_contact = NULL;
	if (c) {
                LM_DBG("Trying to set asserted identity field");
		registration_contact = &c->contact_user;
		p = c->head;
		while (p) {
                        LM_DBG("Checking through contact users");
			if (p->is_default == 1) {
                            LM_DBG("Found default contact user so setting asserted identity");
                            asserted_identity = &p->public_identity;
                        }
			p = p->next;
		}
	}
        if (asserted_identity != NULL && asserted_identity->len > 0) {
            LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s);
        } else {
            LM_DBG("Asserted identity not set");
        }
            
    
//    LM_DBG("pcontact flag is [%d]\n", c->flags);
//    if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) {
//        LM_DBG("we have a contact that was read fresh from the DB....\n");
//    }
	if (!c && mustRetryViaSearch) {
		LM_DBG("This is a reply so we will search using the last via once more...\n");
		vb = cscf_get_ue_via(_m);
		search_ci.via_host = vb->host;
		search_ci.via_port = vb->port ? vb->port : 5060;
		search_ci.via_prot = vb->proto;
		mustRetryViaSearch = 0;
		goto tryagain;
	}
	
	if (!c && mustRetryReceivedSearch) {
		LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n");
		search_ci.via_host = received_host;
		search_ci.via_port = _m->rcv.src_port;
		search_ci.via_prot = _m->rcv.proto;
		mustRetryReceivedSearch = 0;
		goto tryagain;
	}

    return c;
}
Ejemplo n.º 8
0
/**
 * 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;
}
Ejemplo n.º 9
0
/**
 * get PContact-Structure for message
 * (search only once per Request)
 */
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) {
	ppublic_t * p;
	contact_body_t *b = 0;
	str received_host = {0, 0};
	contact_t *ct;
	char srcip[50];	
	int security_server_port = -1;

	if (_m->id != current_msg_id) {
		current_msg_id = _m->id;
		c = NULL;

		b = cscf_parse_contacts(_m);

		if (b && b->contacts) {
			for (ct = b->contacts; ct; ct = ct->next) {
				if (ul.get_pcontact(_d, &ct->uri, &c) == 0) {
					if (c->security) {
						switch (c->security->type) {
						case SECURITY_IPSEC:
							security_server_port = c->security->data.ipsec->port_uc;
							break;
						case SECURITY_TLS:
						case SECURITY_NONE:
							break;
						}
					} else if (c->security_temp) {
						switch (c->security->type) {
						case SECURITY_IPSEC:
							security_server_port = c->security->data.ipsec->port_uc;
							break;
						case SECURITY_TLS:
						case SECURITY_NONE:
							break;
						}
					}

					if ((c->reg_state == PCONTACT_REGISTERED) && ((c->received_port == _m->rcv.src_port) || (security_server_port == _m->rcv.src_port)) && (c->received_proto == _m->rcv.proto)) {
						received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
						received_host.s = srcip;
						LM_DBG("Received host len %d (search %d)\n", c->received_host.len, received_host.len);
						// Then check the length:
						if (c->received_host.len == received_host.len) {
							LM_DBG("Received host %.*s (search %.*s)\n",
								c->received_host.len, c->received_host.s,
								received_host.len, received_host.s);

							// Finally really compare the "received_host"
							if (!memcmp(c->received_host.s, received_host.s, received_host.len))
								break;
							c = NULL;
						}
					} else {
						c = NULL;
					}
				}
			}
		} else {
			LM_WARN("No contact-header found\n");
		}

		if ((c == NULL) && (is_registered_fallback2ip > 0)) {
			LM_WARN("Contact not found based on Contact-header, trying IP/Port/Proto\n");
			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
			received_host.s = srcip;
			if (ul.get_pcontact_by_src(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &c) == 1)
				LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
		}
	}
	asserted_identity = NULL;
	if (c) {
		p = c->head;
		while (p) {
			if (p->is_default == 1)
				asserted_identity = &p->public_identity;
			p = p->next;
		}
	}

	return c;
}
Ejemplo n.º 10
0
/**
 * Saves the Contact Security information into the P-CSCF registrar for this contact.
 * @param req - REGISTER request
 * @param auth - WWW-Authenticate header
 * @param sec_hdr - Security header
 * @param type - Security Type
 * @param q - Preference Value
 */
r_contact* save_contact_security(struct sip_msg *req, str auth, str sec_hdr,r_security_type type,float q)
{
	contact_t* c=0;
	contact_body_t* b=0;	
	r_contact *rc;
	enum Reg_States reg_state=REG_PENDING;
	int expires,pending_expires=60;
	struct sip_uri puri;
	r_security *s=0;
	
	b = cscf_parse_contacts(req);
	
	if (!b||!b->contacts) {
		LOG(L_ERR,"ERR:"M_NAME":save_contact_security: No contacts found\n");
		goto error; 
	}
	
	if (b) c = b->contacts;
			
	r_act_time();
	/* the Security works for just 1 contact/registration! */
	if(c){
		LOG(L_DBG,"DBG:"M_NAME":save_contact_security: <%.*s>\n",c->uri.len,c->uri.s);
		
		expires = time_now+pending_expires;
		
		if (parse_uri(c->uri.s,c->uri.len,&puri)<0){
			LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Error parsing Contact URI <%.*s>\n",c->uri.len,c->uri.s);
			goto error;			
		}
		if (puri.port_no==0) puri.port_no=5060;
		LOG(L_DBG,"DBG:"M_NAME":save_contact_security: %d %.*s : %d\n",
			puri.proto, puri.host.len,puri.host.s,puri.port_no);

		if (type == SEC_TLS) 
			puri.proto = PROTO_TLS;

		/* create the r_security structure */
		s = new_r_security(sec_hdr,type,q);
		if (!s) goto error;	

		switch(type) {
			case SEC_NONE:
				break;
			case SEC_TLS:
				// r_tls creation happens on 200
				break;
			case SEC_IPSEC:
			{
				/* then parse the parameters */
				r_ipsec *ipsec;	
				str ck,ik,ealg,alg,tmp;
				str alg_setkey,ealg_setkey;
				unsigned int spi_uc,spi_us;
        		unsigned int spi_pc,spi_ps;
				int port_uc,port_us;
				char ck_c[64],ik_c[64];
				str ck_esp={ck_c,0},ik_esp={ik_c,0};
									
				get_qparam(auth,s_ck,ck);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: CK: <%.*s>\n",
					ck.len,ck.s);
				get_qparam(auth,s_ik,ik);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: IK: <%.*s>\n",
					ik.len,ik.s);		
				get_param(sec_hdr,s_ealg,ealg);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Enc Algorithm: <%.*s>\n",
					ealg.len,ealg.s);
				get_param(sec_hdr,s_alg,alg);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Int Algorithm: <%.*s>\n",
					alg.len,alg.s);
				/* and for spis */
				get_param(sec_hdr,s_spi_c,tmp);
				strtoint(tmp,spi_uc);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: SPI-C: %d\n",
					spi_uc);
				get_param(sec_hdr,s_spi_s,tmp);
				strtoint(tmp,spi_us);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: SPI-S: %d\n",
					spi_us);
				/* and for ports */
				get_param(sec_hdr,s_port_c,tmp);
				strtoint(tmp,port_uc);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Port-C: %d\n",
					port_uc);
				get_param(sec_hdr,s_port_s,tmp);
				strtoint(tmp,port_us);
				LOG(L_DBG,"DBG:"M_NAME":save_contact_security: Port-S: %d\n",
					port_us);
		
				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":save_contact_security: Unknown Integrity algorithm <%.*s>\n",alg.len,alg.s);
					goto error;
				}
				
				spi_pc=get_next_spi();	
				spi_ps=get_next_spi();	

				ipsec = new_r_ipsec(spi_uc,spi_us,spi_pc,spi_ps,port_uc,port_us,
					ealg_setkey,ealg, ck_esp,alg_setkey,alg, ik_esp);
				if (!ipsec) goto error;
				s->data.ipsec = ipsec;
			}
				break;
		}
	}
	
	rc = update_r_contact_sec(puri.host,puri.port_no,puri.proto,
			&(c->uri),&reg_state,&expires,s);						

	return rc;	
error:
	if (s) free_r_security(s);
	return 0;	
}
Ejemplo n.º 11
0
static int fill_contact(struct pcontact_info* ci, struct sip_msg* m)
{
    contact_body_t* cb = NULL;
    struct via_body* vb = NULL;
    unsigned short port, proto = 0;
    struct sip_msg* req = NULL;


    if(!ci) {
        LM_ERR("fill_contact() called with null ptr\n");
        return -1;
    }

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


    if(m->first_line.type == SIP_REQUEST) {
        struct sip_uri uri;
        memset(&uri, 0, sizeof(struct sip_uri));

        if(parse_uri(m->first_line.u.request.uri.s, m->first_line.u.request.uri.len, &uri)) {
            LM_ERR("Can't parse the request URI from first line\n");
            return -1;
        }

        // populate host,port, aor in CI
        ci->via_host = uri.host;
        ci->via_port = uri.port_no ? uri.port_no : 5060;
        ci->via_prot = proto;
        ci->aor = m->first_line.u.request.uri;

        req = m;
    }
    else if(m->first_line.type == SIP_REPLY) {

        cb = cscf_parse_contacts(m);
        vb = cscf_get_ue_via(m);
        port = vb->port?vb->port:5060;
        proto = vb->proto;

        struct cell *t = tmb.t_gett();
        if (!t || t == (void*) -1) {
            LM_ERR("fill_contact(): Reply without transaction\n");
            return -1;
        }

        req = t->uas.request;

        cb = cscf_parse_contacts(req);
        if (!cb || (!cb->contacts)) {
            LM_ERR("fill_contact(): No contact headers\n");
            return -1;
        }

        // populate CI with bare minimum
        ci->via_host = vb->host;
        ci->via_port = port;
        ci->via_prot = proto;
        ci->aor = cb->contacts->uri;
    }


    char* srcip = NULL;
    if((srcip = pkg_malloc(50)) == NULL) {
        LM_ERR("Error allocating memory for source IP address\n");
        return -1;
    }

    ci->received_host.len = ip_addr2sbuf(&req->rcv.src_ip, srcip, 50);
    ci->received_host.s = srcip;
    ci->received_port = req->rcv.src_port;
    ci->received_proto = req->rcv.proto;

    // Set to default, if not set:
    if (ci->received_port == 0)
        ci->received_port = 5060;


    return 0;
}
Ejemplo n.º 12
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;	
}
Ejemplo n.º 13
0
/**
 * get PContact-Structure for message
 * (search only once per Request)
 */
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d) {
	ppublic_t * p;
	contact_body_t *b = 0;
	contact_t *ct;
	str received_host = {0, 0};
	char srcip[50];	

	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
			received_host.s = srcip;
			
	if (_m->id != current_msg_id) {
		current_msg_id = _m->id;
		c = NULL;

		if (is_registered_fallback2ip == 2) {
			LM_DBG("Searching in usrloc for %.*s:%i (Proto %i)\n",
				received_host.len, received_host.s,
				_m->rcv.src_port, _m->rcv.proto);

			if (ul.get_pcontact_by_src(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &c) == 1) {
				LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
			} else {
				if (checkcontact(_m, c) != 0) {
					c = NULL;
				}
			}
		}

		if (c == NULL) {
			b = cscf_parse_contacts(_m);

			if (b && b->contacts) {
				for (ct = b->contacts; ct; ct = ct->next) {
					if (ul.get_pcontact(_d, &ct->uri, &received_host, _m->rcv.src_port, &c) == 0) {
						if (checkcontact(_m, c) != 0) {
							c = NULL;
						} else {
							break;
						}
					}
				}
			} else {
				LM_WARN("No contact-header found?!?\n");
			}
		}

		if ((c == NULL) && (is_registered_fallback2ip == 1)) {
			LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n");
			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
			received_host.s = srcip;
			if (ul.get_pcontact_by_src(_d, &received_host, _m->rcv.src_port, _m->rcv.proto, &c) == 1) {
				LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
			} else {
				if (checkcontact(_m, c) != 0) {
					c = NULL;
				}
			}
		}
	}
	asserted_identity = NULL;
	registration_contact = NULL;
	if (c) {
		registration_contact = &c->contact_user;
		p = c->head;
		while (p) {
			if (p->is_default == 1)
				asserted_identity = &p->public_identity;
			p = p->next;
		}
	}

	return c;
}
Ejemplo n.º 14
0
/**
 * Save the contacts and their associated public ids.
 * @param rpl - the SIP Register 200 OK response that contains the Expire and Contact and P-associated-uri headers
 * @param _d - domain
 * @param _cflags - flags
 * @returns #CSCF_RETURN_TRUE if OK, #CSCF_RETURN_ERROR on error
 */
int save(struct sip_msg* _m, udomain_t* _d, int _cflags) {
	struct sip_msg* req;
	int expires_hdr = 0;
	contact_body_t* cb = 0;
	str *public_ids=0;
	int num_public_ids = 0;
	str *service_routes=0;
	int num_service_routes = 0;
	pv_elem_t *presentity_uri_pv;
	
	//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;
	}
	expires_hdr = cscf_get_expires_hdr(_m, 0);
	cb = cscf_parse_contacts(_m);
	if (!cb || (!cb->contacts && !cb->star)) {
		LM_DBG("No contact headers and not *\n");
		goto error;
	}
	cscf_get_p_associated_uri(_m, &public_ids, &num_public_ids, 1);
	service_routes = cscf_get_service_route(_m, &num_service_routes, 1);

	//update contacts
	if (!update_contacts(req, _m, _d, cb->star, expires_hdr, public_ids, num_public_ids, service_routes, num_service_routes, 0)) {
		LM_ERR("failed to update pcontact\n");
		goto error;
	}

	if(subscribe_to_reginfo == 1){
	    
	    //use the first p_associated_uri - i.e. the default IMPU
	    LM_DBG("Subscribe to reg event for primary p_associated_uri");
	    if(num_public_ids > 0){
		//find the first routable (not a tel: URI and use that that presentity)
		//if you can not find one then exit
		int i = 0;
		int found_presentity_uri=0;
		while (i < num_public_ids && found_presentity_uri == 0)
		{
		    //check if public_id[i] is NOT a tel URI - if it isn't then concert to pv format and set found presentity_uri to 1
		    if (strncasecmp(public_ids[i].s,"tel:",4)==0) {
			LM_DBG("This is a tel URI - it is not routable so we don't use it to subscribe");
			i++;
		    }
		    else {
			//convert primary p_associated_uri to pv_elem_t
			if(pv_parse_format(&public_ids[i], &presentity_uri_pv)<0) {
				LM_ERR("wrong format[%.*s]\n",public_ids[i].len, public_ids[i].s);
				goto error;
			}
			found_presentity_uri=1;
		    }
		}
		if(found_presentity_uri!=1){
		    LM_ERR("Could not find routable URI in p_assoiated_uri list - failed to subscribe");
		    goto error;
		}
	    }else{
		//Now some how check if there is a pua record and what the presentity uri is from there - if nothing there
		LM_DBG("No p_associated_uri in 200 OK this must be a de-register - we ignore this - will unsubscribe when the notify is received");
		goto done;
		
	    }
	    reginfo_subscribe_real(_m, presentity_uri_pv, service_routes, subscription_expires);
	    pv_elem_free_all(presentity_uri_pv);
	}
    
done:
	if (public_ids && public_ids->s) pkg_free(public_ids);
	if (service_routes && service_routes->s) pkg_free(service_routes);
	return 1;

error:
	if (public_ids && public_ids->s) pkg_free(public_ids);
	if (service_routes && service_routes->s) pkg_free(service_routes);
	return -1;

}
Ejemplo n.º 15
0
/**
 * Save contact based on REGISTER request. this will be a pending save, until we receive response
 * from SCSCF. If no response after pending_timeout seconds, the contacts is removed. Can only be used from REQUEST ROUTE
 */
int save_pending(struct sip_msg* _m, udomain_t* _d) {
	contact_body_t* cb = 0;
	int cexpires = 0;
	pcontact_t* pcontact;
	contact_t* c;
	struct pcontact_info ci;
        struct via_body* vb;
        unsigned short port, proto;
	int_str val;
	struct sip_uri parsed_received;
	char srcip[50];

	memset(&ci, 0, sizeof(struct pcontact_info));
        
        vb = cscf_get_ue_via(_m);
        port = vb->port?vb->port:5060;
        proto = vb->proto;

	cb = cscf_parse_contacts(_m);
	if (!cb || (!cb->contacts)) {
		LM_ERR("No contact headers\n");
		goto error;
	}
        
        c = cb->contacts;
	//TODO: need support for multiple contacts - currently assume one contact
	//make sure this is not a de-registration
	int expires_hdr = cscf_get_expires_hdr(_m, 0);
	if (expires_hdr < 0) {
		//no global header we have to check the contact expiry
		if (c && c->expires && c->expires->body.len) {
				str2int(&(c->expires->body), (unsigned int*) &cexpires);
		}
		if (!cexpires){ //assume de-registration
			LM_DBG("not doing pending reg on de-registration\n");
			return 1;
		}
	}
        
	pcscf_act_time();
	int local_time_now = time_now;
	int expires = calc_contact_expires(c, expires_hdr, local_time_now);
	if (expires <= 0) {
		LM_DBG("not doing pending reg on de-registration\n");
		return 1;
	}
        LM_DBG("Save Pending");
	LM_DBG("contact requesting to expire in %d seconds\n", expires-local_time_now);

	/*populate CI with bare minimum*/
        ci.via_host = vb->host;
        ci.via_port = port;
        ci.via_prot = proto;
        ci.aor = c->uri;
	ci.num_public_ids=0;
	ci.num_service_routes=0;
	ci.expires=local_time_now + pending_reg_expires;
	ci.reg_state=PCONTACT_ANY;
        ci.searchflag=SEARCH_RECEIVED;  //we want to make sure we are very specific with this search to make sure we get the correct contact to put into reg_pending.

	// Received Info: First try AVP, otherwise simply take the source of the request:
	memset(&val, 0, sizeof(int_str));
	if (rcv_avp_name.n != 0
			&& search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0)
			&& val.s.len > 0) {
		if (val.s.len > RECEIVED_MAX_SIZE) {
			LM_ERR("received too long\n");
			goto error;
		}
		if (parse_uri(val.s.s, val.s.len, &parsed_received) < 0) {
			LM_DBG("Error parsing Received URI <%.*s>\n", val.s.len, val.s.s);
			goto error;
		}
		ci.received_host = parsed_received.host;
		ci.received_port = parsed_received.port_no;
		ci.received_proto = parsed_received.proto;
	} else {
		ci.received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip,
				sizeof(srcip));
		ci.received_host.s = srcip;
		ci.received_port = _m->rcv.src_port;
		ci.received_proto = _m->rcv.proto;
                
	}
	// Set to default, if not set:
	if (ci.received_port == 0)
		ci.received_port = 5060;

	ul.lock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot);
	if (ul.get_pcontact(_d, &ci, &pcontact) != 0) { //need to insert new contact
		LM_DBG("Adding pending pcontact: <%.*s>\n", c->uri.len, c->uri.s);
		ci.reg_state=PCONTACT_REG_PENDING;
		if (ul.insert_pcontact(_d, &c->uri, &ci, &pcontact) != 0) {
			LM_ERR("Failed inserting new pcontact\n");
		} else {
			LM_DBG("registering for UL callback\n");
			ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE | PCSCF_CONTACT_UPDATE, callback_pcscf_contact_cb, NULL);
		}
	} else { //contact already exists - update
		LM_DBG("Contact already exists - not doing anything for now\n");
	}
	ul.unlock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot);

	return 1;

error:
	LM_DBG("Error saving pending contact\n");
	return -1;
}
Ejemplo n.º 16
0
/* 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;
}