Example #1
0
/**
 * Returns the Private Identity extracted from the Authorization header.
 * If none found there takes the SIP URI in To without the "sip:" prefix
 * \todo - remove the fallback case to the To header
 * @param msg - the SIP message
 * @param realm - the realm to match in an Authorization header
 * @returns the str containing the private id, no mem dup
 */
str cscf_get_private_identity_no_realm(struct sip_msg *msg, str realm)
{
	str pi={0,0};
	struct hdr_field* h=0;
	int i;

	if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
		return pi;
	}

	if (!msg->authorization){
		goto fallback;
	}

        h = msg->authorization;
        if (h) pi=((auth_body_t*)h->parsed)->digest.username.whole;

	goto done;

	fallback:
	pi = cscf_get_public_identity(msg);
	if (pi.len>4&&strncasecmp(pi.s,"sip:",4)==0) {pi.s+=4;pi.len-=4;}
	for(i=0;i<pi.len;i++)
		if (pi.s[i]==';') {
			pi.len=i;
			break;
		}
	done:
	return pi;	
}
Example #2
0
/*! \brief the impu_registered() function
 * Return true if the AOR in the To Header is registered
 */
int impu_registered(struct sip_msg* _m, char* _t, char* _s)
{
	impurecord_t* r;
	int res, ret=-1;

	str impu;
	impu = cscf_get_public_identity(_m);

	LM_DBG("Looking for IMPU <%.*s>\n", impu.len, impu.s);

	ul.lock_udomain((udomain_t*)_t, &impu);
	res = ul.get_impurecord((udomain_t*)_t, &impu, &r);

	if (res < 0) {
		ul.unlock_udomain((udomain_t*)_t, &impu);
		LM_ERR("failed to query usrloc for IMPU <%.*s>\n", impu.len, impu.s);
		return ret;
	}

	if (res == 0) {
		if (r->reg_state == IMPU_REGISTERED ) ret = 1;
		ul.unlock_udomain((udomain_t*) _t, &impu);
		LM_DBG("'%.*s' found in usrloc\n", impu.len, ZSW(impu.s));
		return ret;
	}

	ul.unlock_udomain((udomain_t*)_t, &impu);
	LM_DBG("'%.*s' not found in usrloc\n", impu.len, ZSW(impu.s));
	return ret;
}
Example #3
0
/**
 * Returns the Private Identity extracted from the Authorization header.
 * If none found there takes the SIP URI in To without the "sip:" prefix
 * \todo - remove the fallback case to the To header
 * @param msg - the SIP message
 * @param realm - the realm to match in an Authorization header
 * @returns the str containing the private id, no mem dup
 */
str cscf_get_private_identity(struct sip_msg *msg, str realm) {
	str pi = {0, 0};
	struct hdr_field* h = 0;
	int ret, i, res;

	if ((parse_headers(msg, HDR_AUTHORIZATION_F, 0) != 0) && (parse_headers(msg, HDR_PROXYAUTH_F, 0) != 0)) {
		return pi;
	}

	h = msg->authorization;
	if (!msg->authorization) {
		goto fallback;
	}
		
	if (realm.len && realm.s) {
		ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_F, &h);
		if (ret < 0) {
			ret = find_credentials(msg, &realm, HDR_PROXYAUTH_F, &h);
			if (ret < 0) {
				goto fallback;
			} else {
				if (ret >0) {
					goto fallback;
				}
				h = msg->proxy_auth;
			}
		} else {
			if (ret > 0) {
				goto fallback;
			}
		}
	}
	
	if (!h)
		goto fallback;

	res = parse_credentials(h);
	if (res != 0) {
		LOG(L_ERR, "Error while parsing credentials\n");
		return pi;
	}

	if (h) pi = ((auth_body_t*) h->parsed)->digest.username.whole;

	goto done;

fallback:
	pi = cscf_get_public_identity(msg);
	if (pi.len > 4 && strncasecmp(pi.s, "sip:", 4) == 0) {
		pi.s += 4;
		pi.len -= 4;
	}
	for (i = 0; i < pi.len; i++)
		if (pi.s[i] == ';') {
			pi.len = i;
			break;
		}
done:
	return pi;
}
Example #4
0
/**
 * 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;
	}	
}
Example #5
0
int rx_send_aar_register(struct sip_msg *msg, AAASession* auth, saved_transaction_local_t* saved_t_data) {
    AAAMessage* aar = 0;
    int ret = 0;
    AAA_AVP* avp = 0;
    char x[4];
    str identifier;
    
    str ip;
    uint16_t ip_version;

    //we get ip and identifier for the auth session data 
    rx_authsessiondata_t* p_session_data = 0;
    p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
    identifier = p_session_data->identifier;
    ip = p_session_data->ip;
    ip_version = p_session_data->ip_version;

    LM_DBG("Send AAR register\n");

    aar = cdpb.AAACreateRequest(IMS_Rx, IMS_AAR, Flag_Proxyable, auth);

    if (!aar)
        goto error;

    /*Add AVPs*/

    /* Add Auth-Application-Id AVP */
    if (!rx_add_auth_application_id_avp(aar, IMS_Rx))
        goto error;
    if (!rx_add_vendor_specific_application_id_group(aar, IMS_vendor_id_3GPP,
            IMS_Rx))
        goto error;

    /* Add Destination-Realm AVP, if not already there */
    avp = cdpb.AAAFindMatchingAVP(aar, aar->avpList.head, AVP_Destination_Realm,
            0, AAA_FORWARD_SEARCH);
    if (!avp) {
        str realm = rx_dest_realm;
        if (realm.len && !rx_add_destination_realm_avp(aar, realm))
            goto error;
    }

    /* Add Subscription ID AVP*/
    
    identifier = cscf_get_public_identity(msg);
    
    int identifier_type = AVP_Subscription_Id_Type_SIP_URI; //we only do IMPU now
    rx_add_subscription_id_avp(aar, identifier, identifier_type);

    /* Add media component description avp for register*/
    rx_add_media_component_description_avp_register(aar);

    /* Add specific action AVP's */
    rx_add_specific_action_avp(aar, 1); // CHARGING_CORRELATION_EXCHANGE
    rx_add_specific_action_avp(aar, 2); // INDICATION_OF_LOSS_OF_BEARER
    rx_add_specific_action_avp(aar, 3); // INDICATION_RECOVERY_OF_BEARER
    rx_add_specific_action_avp(aar, 4); // INDICATION_RELEASE_OF_BEARER
    rx_add_specific_action_avp(aar, 5); // INDICATION_ESTABLISHMENT_OF_BEARER (now void)
    rx_add_specific_action_avp(aar, 6); // IP-CAN_CHANGE
    rx_add_specific_action_avp(aar, 12); // ACCESS_NETWORK_INFO_REPORT

    /* Add Framed IP address AVP*/
    if (!rx_add_framed_ip_avp(&aar->avpList, ip, ip_version)) {
        LM_ERR("Unable to add framed IP AVP\n");
        goto error;
    }

    /* Add Auth lifetime AVP */LM_DBG("auth_lifetime %u\n", rx_auth_expiry); //TODO check why this is 0 all the time
    if (rx_auth_expiry) {
        set_4bytes(x, rx_auth_expiry);
        if (!rx_add_avp(aar, x, 4, AVP_Authorization_Lifetime,
                AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__))
            goto error;
    }

    if (auth)
        cdpb.AAASessionsUnlock(auth->hash);

    LM_DBG("sending AAR to PCRF\n");
    if (rx_forced_peer.len)
        ret = cdpb.AAASendMessageToPeer(aar, &rx_forced_peer,
            (void*) async_aar_reg_callback, (void*) saved_t_data);
    else
        ret = cdpb.AAASendMessage(aar, (void*) async_aar_reg_callback,
            (void*) saved_t_data);

    return ret;

error:
    LM_ERR("unexpected error\n");
    if (aar)
        cdpb.AAAFreeMessage(&aar);
    if (auth) {
        cdpb.AAASessionsUnlock(auth->hash);
        cdpb.AAADropAuthSession(auth);
        auth = 0;
    }
    return ret;
}
Example #6
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;
}
Example #7
0
/**
 * 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;
    }
}