Exemplo n.º 1
0
/* copies the Origin-Host AVP from the src message in a Destination-Host AVP in the dest message
 * copies the Origin-Realm AVP from the src message in a Destination-Realm AVP in the dest message
 *
 */
int dup_routing_avps(AAAMessage* src, AAAMessage *dest){

	AAA_AVP * avp;
	str dest_host, dest_realm;

	if(!src)
		return 1;

	avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Host,0,AAA_FORWARD_SEARCH);
	if(avp && avp->data.s && avp->data.len) {
		LOG(L_DBG,"DBG:dup_routing_avps: Origin Host AVP present, duplicating %.*s\n",
				avp->data.len, avp->data.s);
		dest_host = avp->data;
		avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
			dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
		if (!avp) {
			LOG(L_ERR,"ERR:dup_routing_avps: Failed creating Destination Host avp\n");
			goto error;
		}
		if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) {
			LOG(L_ERR,"ERR:dup_routing_avps: Failed adding Destination Host avp to message\n");
			AAAFreeAVP(&avp);
			goto error;
		}
	}

	avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Realm,0,AAA_FORWARD_SEARCH);
	if(avp && avp->data.s && avp->data.len) {
		LOG(L_DBG,"DBG:dup_routing_avps: Origin Realm AVP present, duplicating %.*s\n",
				avp->data.len, avp->data.s);
		dest_realm = avp->data;
		avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
			dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
		if (!avp) {
			LOG(L_ERR,"ERR:dup_routing_avps: Failed creating Destination Host avp\n");
			goto error;
		}
		if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) {
			LOG(L_ERR,"ERR:dup_routing_avps: Failed adding Destination Host avp to message\n");
			AAAFreeAVP(&avp);
			goto error;
		}
	}

	return 1;
error:
	return 0;

}
Exemplo n.º 2
0
int count_Supported_Vendor_Id_AVPS(AAAMessage *msg)
{
	AAA_AVP* avp_vendor;
	int avp_vendor_cnt;

	avp_vendor = AAAFindMatchingAVP(msg,0,AVP_Supported_Vendor_Id,0,0);
	avp_vendor_cnt = 0;
	while (avp_vendor) {
		avp_vendor_cnt++;
		if (!avp_vendor->next)
			break;
		avp_vendor = AAAFindMatchingAVP(msg,avp_vendor->next,AVP_Supported_Vendor_Id,0,0);
	}
	LM_DBG("Found %i Supported_Vendor AVPS", avp_vendor_cnt);
	return avp_vendor_cnt;
}
Exemplo n.º 3
0
/**
 * Perform the Election mechanism.
 * When 2 peers connect to each-other at the same moment, an election is triggered.
 * That means that based on the alphabetical relation between the FQDNs, one peer is
 * kept as winner on Initiator and that connection is kept, while the other keeps the same
 * connection as Receiver and drops its Initiator connection.
 * \note Must be called with a lock on the peer.
 * @param p - peer identification
 * @param cer - the CER message
 * @returns 1 if winning, 0 if loosing
 */  
int Elect(peer *p,AAAMessage *cer)
{
	/* returns if we win the election */
	AAA_AVP *avp;
	str remote,local;
	int i,d;

	if(!cer){
		LM_ERR("Elect cer is NULL \n");
		// return lose
		return 0;
	}
	
	local = config->fqdn;

	avp = AAAFindMatchingAVP(cer,cer->avpList.head,AVP_Origin_Host,0,0);
	if (!avp) {
		return 1;
	}else{
		remote = avp->data;
		for(i=0;i<remote.len&&i<local.len;i++){
			d = ((unsigned char) local.s[i])-((unsigned char) remote.s[i]);
			if (d>0) return 1;
			if (d<0) return 0;
		}
		if (local.len>remote.len) return 1;
		return 0;
	}
}
Exemplo n.º 4
0
/**
 * update Granted Service Unit timers based on CCR
 */
inline void update_gsu_request_timers(cdp_cc_acc_session_t* session, AAAMessage* msg) {
	AAA_AVP *avp;

	avp = AAAFindMatchingAVP(msg, 0, AVP_Event_Timestamp, 0, 0);
	if (avp && avp->data.len == 4) {
		session->last_reservation_request_time = ntohl(*((uint32_t*)avp->data.s))-EPOCH_UNIX_TO_EPOCH_NTP;
	}
}
Exemplo n.º 5
0
/**
 * Sends a message to the peer.
 * \note Must be called with a lock on the peer.
 * @param p - peer to send to
 * @param msg - message to send
 */
void Snd_Message(peer *p, AAAMessage *msg)
{
	AAASession *session=0;
	int rcode;
	int send_message_before_session_sm=0;
	touch_peer(p);
	if (msg->sessionId) session = get_session(msg->sessionId->data);
	
	if (session){
		switch (session->type){
			case AUTH_CLIENT_STATEFULL:
				if (is_req(msg))
					auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
				else {
					if (msg->commandCode == IMS_ASA){
						if (!msg->res_code){
							msg->res_code = AAAFindMatchingAVP(msg,0,AVP_Result_Code,0,0);
						}
						if (!msg->res_code) auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
						else {
							rcode = get_4bytes(msg->res_code->data.s);
							if (rcode>=2000 && rcode<3000) {
								peer_send_msg(p,msg);
								send_message_before_session_sm=1;
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_SUCCESS,msg);
							}
							else auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
						}
						
					}else
						auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
				}
				break;
			case AUTH_SERVER_STATEFULL:
				if (is_req(msg))
				{
					if (msg->commandCode== IMS_ASR)
					{
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg);
					} else {
						//would be a RAR but ok!
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
					}
				} else {
					if (msg->commandCode == IMS_STR)
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg);
					else
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
				}
				break;				 
			default:
				break;
		}
		sessions_unlock(session->hash);
	}
	if (!send_message_before_session_sm) peer_send_msg(p,msg);
	
}
Exemplo n.º 6
0
/**
 * Process a Capability Exchange Answer.
 * \note Must be called with a lock on the peer.
 * @param p - the peer that the CEA was received from
 * @param cea - the CEA message
 * @returns the result-code from CEA or AAA_UNABLE_TO_COMPLY if no result-code found
 */	
int Process_CEA(peer *p,AAAMessage *cea)
{
	AAA_AVP *avp;
	avp = AAAFindMatchingAVP(cea,cea->avpList.head,AVP_Result_Code,0,0);
	save_peer_applications(p,cea);
	AAAFreeMessage(&cea);
	if (!avp) return AAA_UNABLE_TO_COMPLY;
	else return get_4bytes(avp->data.s);
}	
Exemplo n.º 7
0
int get_auth_session_state(AAAMessage* msg) {
    if (!msg) goto error;
    AAA_AVP* rc = AAAFindMatchingAVP(msg, 0, AVP_Auth_Session_State, 0, 0);
    if (!rc) goto error;
    return get_4bytes(rc->data.s);

error:
    LM_DBG("get_auth_session_state(): no AAAMessage or Auth Session State not found\n");
    return STATE_MAINTAINED;
}
Exemplo n.º 8
0
/**
 * update Granted Service Unit timers based on CCA, for onw we assume on one MSCC per session and only TIME based supported
 */
inline void update_gsu_response_timers(cdp_cc_acc_session_t* session, AAAMessage* msg) {
	AAA_AVP *avp;
	AAA_AVP_LIST mscc_avp_list;
	AAA_AVP_LIST y;
	AAA_AVP *z;

	avp = AAAFindMatchingAVP(msg, 0, AVP_Multiple_Services_Credit_Control, 0, 0);
        if (!avp) {
            LM_WARN("Trying to update GSU timers but there is no MSCC AVP in the CCA response\n");
            return;
        }
	mscc_avp_list = AAAUngroupAVPS(avp->data);
	AAA_AVP *mscc_avp = mscc_avp_list.head;

	while (mscc_avp != NULL ) {
		LM_DBG("MSCC AVP code is [%i] and data length is [%i]", mscc_avp->code, mscc_avp->data.len);
		switch (mscc_avp->code) {
			case AVP_Granted_Service_Unit:
				y = AAAUngroupAVPS(mscc_avp->data);
				z = y.head;
				while (z) {
					switch (z->code) {
					case AVP_CC_Time:
						session->reserved_units = get_4bytes(z->data.s);
						break;
					default:
						LM_DBG("ignoring AVP in GSU group with code:[%d]\n", z->code);
					}
					z = z->next;
				}
				break;
			case AVP_Validity_Time:
				session->reserved_units_validity_time = get_4bytes(mscc_avp->data.s);
				break;
			case AVP_Final_Unit_Indication:
				y = AAAUngroupAVPS(mscc_avp->data);
				z = y.head;
				while (z) {
					switch (z->code) {
						case AVP_Final_Unit_Action:
							session->fua = get_4bytes(z->data.s);
							break;
						default:
							LM_DBG("ignoring AVP in FUI group with code:[%d]\n", z->code);
					}
					z = z->next;
				}
				break;
		}
		mscc_avp = mscc_avp->next;
	}

	AAAFreeAVPList(&mscc_avp_list);
	AAAFreeAVPList(&y);
}
Exemplo n.º 9
0
Arquivo: auth.c Projeto: asyn/openvims
int get_result_code(AAAMessage* msg)
{
	if (!msg) goto error;
	AAA_AVP* rc = AAAFindMatchingAVP(msg, 0, AVP_Result_Code, 0, 0);
	if (!rc) goto error;
	return get_4bytes(rc->data.s);

error:
	LOG(L_INFO, "INF: no AAAMessage or Result Code not found\n");
	return 0;
}
Exemplo n.º 10
0
/**
 * Retrieve the Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs and update the session timers accordingly
 * @param x
 * @param msg
 */
void update_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg)
{
	AAA_AVP *avp;
	uint32_t session_timeout=0,grace_period=0,auth_lifetime=0;
	
	avp = AAAFindMatchingAVP(msg,0,AVP_Auth_Grace_Period,0,0);
	if (avp &&avp->data.len==4){ 
		grace_period = get_4bytes(avp->data.s);
		x->grace_period = grace_period;
	}
	avp = AAAFindMatchingAVP(msg,0,AVP_Authorization_Lifetime,0,0);
	if (avp &&avp->data.len==4) {
		auth_lifetime = get_4bytes(avp->data.s);
		switch(auth_lifetime){
			case 0:
				x->lifetime = time(0);
				break;
			case 0xFFFFFFFF:
				x->lifetime = -1;
				break;
			default:
				x->lifetime = time(0)+auth_lifetime;
		}
		if (x->timeout!=-1 && x->timeout<x->lifetime) x->timeout = x->lifetime+x->grace_period;
	}
	avp = AAAFindMatchingAVP(msg,0,AVP_Session_Timeout,0,0);
	if (avp &&avp->data.len==4) {
		session_timeout = get_4bytes(avp->data.s);
		switch(session_timeout){
			case 0:
				x->timeout = time(0)+config->default_auth_session_timeout;
				break;
			case 0xFFFFFFFF:
				x->timeout = -1;
				break;
			default:
				x->timeout = time(0)+session_timeout;
		}
		if (!x->lifetime) x->lifetime = x->timeout;
	}
}
Exemplo n.º 11
0
/**
 * Add Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs to outgoing messages in case they are missing
 * @param x
 * @param msg
 */
void add_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg)
{
	AAA_AVP *avp;
	char data[4];
	uint32_t v;
	
	avp = AAAFindMatchingAVP(msg,0,AVP_Authorization_Lifetime,0,0);
	if (!avp){ 
		if (x->lifetime==-1) v=0xFFFFFFFF;
		else {
			v = x->lifetime-time(0);
			if (v<0) v = 0;
		}
		set_4bytes(data,v);
		avp = AAACreateAVP(AVP_Authorization_Lifetime,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
		if (avp) AAAAddAVPToMessage(msg,avp,0);
	}
	if (x->lifetime!=-1){
		avp = AAAFindMatchingAVP(msg,0,AVP_Auth_Grace_Period,0,0);
		if (!avp){ 
			v = x->grace_period;
			set_4bytes(data,v);
			avp = AAACreateAVP(AVP_Auth_Grace_Period,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
			if (avp) AAAAddAVPToMessage(msg,avp,0);
		}
	}
	avp = AAAFindMatchingAVP(msg,0,AVP_Session_Timeout,0,0);
	if (!avp){ 
		if (x->timeout==-1) v=0xFFFFFFFF;
		else {
			v = x->timeout-time(0);
			if (v<0) v = 0;
		}
		set_4bytes(data,v);
		avp = AAACreateAVP(AVP_Session_Timeout,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
		if (avp) AAAAddAVPToMessage(msg,avp,0);
	}
}
Exemplo n.º 12
0
/* copies the Origin-Host AVP from the src message in a Destination-Host AVP in the dest message
 * copies the Origin-Realm AVP from the src message in a Destination-Realm AVP in the dest message
 *
 */
int dup_routing_avps(AAAMessage* src, AAAMessage *dest) {

    AAA_AVP * avp;
    str dest_realm;

    if (!src)
        return 1;

    /* Removed By Jason to facilitate use of Diameter clustering (MUX) in SLEE architecture (Realm-routing only) - TODO - check spec */
    /*avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Host,0,AAA_FORWARD_SEARCH);
    if(avp && avp->data.s && avp->data.len) {
            LM_DBG("dup_routing_avps: Origin Host AVP present, duplicating %.*s\n",
                            avp->data.len, avp->data.s);
            dest_host = avp->data;
            avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
                    dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
            if (!avp) {
                    LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n");
                    goto error;
            }
            if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) {
                    LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n");
                    AAAFreeAVP(&avp);
                    goto error;
            }
    }*/

    avp = AAAFindMatchingAVP(src, src->avpList.head, AVP_Origin_Realm, 0, AAA_FORWARD_SEARCH);
    if (avp && avp->data.s && avp->data.len) {
        LM_DBG("dup_routing_avps: Origin Realm AVP present, duplicating %.*s\n",
                avp->data.len, avp->data.s);
        dest_realm = avp->data;
        avp = AAACreateAVP(AVP_Destination_Realm, AAA_AVP_FLAG_MANDATORY, 0,
                dest_realm.s, dest_realm.len, AVP_DUPLICATE_DATA);
        if (!avp) {
            LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n");
            goto error;
        }
        if (AAAAddAVPToMessage(dest, avp, dest->avpList.tail) != AAA_ERR_SUCCESS) {
            LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n");
            AAAFreeAVP(&avp);
            goto error;
        }
    }

    return 1;
error:
    return 0;

}
Exemplo n.º 13
0
/**
 * Returns the value of a certain AVP from a Diameter message.
 * @param m - Diameter message to look into
 * @param avp_code - the code to search for
 * @param vendorid - the value of the vendor id to look for or 0 if none
 * @param func - the name of the calling function, for debugging purposes
 * @returns the str with the payload on success or an empty string on failure
 */
static inline str get_avp(AAAMessage *msg,int avp_code,int vendor_id,
							const char *func)
{
	AAA_AVP *avp;
	str r={0,0};
	
	avp = AAAFindMatchingAVP(msg,0,avp_code,vendor_id,0);
	if (avp==0){
		LOG(L_INFO,"INFO: Failed finding avp\n");
		return r;
	}
	else 
		return avp->data;
}
Exemplo n.º 14
0
/**
 * Returns the value of a certain AVP from a Diameter message.
 * westart searching from the beginning 0
 * @param msg - Diameter message to look into
 * @param avp_code - the code to search for
 * @param vendorid - the value of the vendor id to look for or 0 if none
 * * @returns the AAA_AVP* if found, NULL if not 
 */
AAA_AVP  *Rf_get_avp(AAAMessage *msg,int avp_code,int vendor_id)
{
	AAA_AVP *avp;
	/* param checking */
	if (!msg) {
		LOG(L_ERR,"ERR:Rf_get_avp: param msg passed null !!\n");
		return 0;
	}
	
	avp =  AAAFindMatchingAVP(msg,0,avp_code,vendor_id,0);
	if (avp==0){
		LOG(L_ERR,"ERR: Rf_get_avp: Failed finding avp\n");
		return 0;
	}
	else 
	return avp;
}
Exemplo n.º 15
0
void Send_ASA(cdp_session_t* s, AAAMessage* msg)
{
	AAAMessage *asa;
	char x[4];
	AAA_AVP *avp;	
	LOG(L_INFO,"Send_ASA():  sending ASA\n");
	if (!s) {
	//send an ASA for UNKNOWN_SESSION_ID - use AAASendMessage()
	// msg is the ASR received
		asa = AAANewMessage(IMS_ASA,0,0,msg);
		if (!asa) return;	
	
		set_4bytes(x,AAA_SUCCESS);
		AAACreateAndAddAVPToMessage(asa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
	
		AAASendMessage(asa,0,0);
	}else{
		// send... many cases... maybe not needed.
		// for now we do the same
		asa = AAANewMessage(IMS_ASA,0,0,msg);
		if (!asa) return;	
	
		set_4bytes(x,AAA_SUCCESS);
		AAACreateAndAddAVPToMessage(asa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
				
		avp = AAAFindMatchingAVP(msg,0,AVP_Origin_Host,0,0);	
		if (avp) {
				// This is because AAASendMessage is not going to find a route to the 
				// the PCRF because TS 29.214 says no Destination-Host and no Auth-Application-Id
				// in the ASA
			LOG(L_INFO,"sending ASA to peer %.*s\n",avp->data.len,avp->data.s); 
			peer *p;
			p = get_peer_by_fqdn(&avp->data);
			if (!peer_send_msg(p,asa)) {
				if (asa) AAAFreeMessage(&asa);	//needed in frequency
			} else  
				LOG(L_INFO,"success sending ASA\n");
		}else if (!AAASendMessage(asa,0,0)) {
			LOG(L_ERR,"Send_ASA() : error sending ASA\n");
		}	
	}	
}
Exemplo n.º 16
0
/**
 *  Allocates a new AAAMessage.
 * @param commandCode - the command code for this message
 * @param applicationId - application id to be set
 * @param sessionId - session id to be set
 * @param request - if you want to create a response, put the request here. If you want a 
 * request, call with NULL
 * @returns the AAAMessage* or NULL on error
 * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
 */
AAAMessage *AAANewMessage(
	AAACommandCode commandCode,
	AAAApplicationId applicationId,
	AAASessionId *sessionId,
	AAAMessage *request)
{
	AAAMessage   *msg;
	AAA_AVP      *avp;
	AAA_AVP      *avp_t;
#if 0
	unsigned int code;
#endif
	str dest_host={"?",1};
	str dest_realm={"?",1};

	msg = 0;

	if (!sessionId||!sessionId->s) {
		if (request && request->sessionId){
			/* copy old session id */
			avp = request->sessionId;
			if (avp) {
				sessionId = &(avp->data);
			}
		}else{
//because of diameter base messages etc
//			LOG(L_ERR,"ERROR:AAANewMessage: param session-ID received null and it's a request!!\n");
//			goto error;
		}
	}

	/* allocated a new AAAMessage structure and set it to 0 */
	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
	if (!msg) {
		LOG(L_ERR,"ERROR:AAANewMessage: no more free memory!!\n");
		goto error;
	}
	memset(msg,0,sizeof(AAAMessage));

	/* command code */
	msg->commandCode = commandCode;
	/* application ID */
	msg->applicationId = applicationId;

	/* add session ID */
	if (sessionId){
		avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
			AVP_DUPLICATE_DATA);
		if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
			LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Session-Id avp\n");
			if (avp) AAAFreeAVP( &avp );
			goto error;
		}
		msg->sessionId = avp;
	}
	

	/* add origin host AVP */
	/* changed by cristian to comply with rfc3588: 
	 * 6.3.  Origin-Host AVP
	 *
	 *    The Origin-Host AVP (AVP Code 264) is of type
	 *    DiameterIdentity... */
	avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Host avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_host = avp;
	/* add origin realm AVP */
	avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Realm avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_realm = avp;

	if (!request) {
		/* it's a new request -> set the flag */
		msg->flags = 0x80;
		/* keep track of the session -> SendMessage will need it! */
		msg->sId = sessionId;
	} else {
		/* it'a an answer -> it will have the same session Id */
		msg->sId = request->sId;
		/* link the incoming peer to the answer */
		msg->in_peer = request->in_peer;
		/* set the P flag as in request */
		msg->flags |= request->flags&0x40;
		/**/
		msg->endtoendId = request->endtoendId;
		msg->hopbyhopId = request->hopbyhopId;

	/* Mirror the old originhost/realm to destinationhost/realm*/
	avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
	if (avp) dest_host = avp->data;
	/* add destination host and destination realm */
	avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
		dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
	if (!avp) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Host avp\n");
		return 0;
	}
	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
		AAAFreeAVP(&avp);
		return 0;
	}
	avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
	if (avp) dest_realm = avp->data;

	avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
		dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
	if (!avp) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Realm avp\n");
		return 0;
	}
	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
		AAAFreeAVP(&avp);
		return 0;
	}		


		msg->res_code=0;
		/* mirror all the proxy-info avp in the same order */
		avp_t = request->avpList.head;
		while ( (avp_t=AAAFindMatchingAVP
		(request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
			if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
			msg->avpList.tail)!=AAA_ERR_SUCCESS )
				goto error;
		}
	}

	return msg;
error:
	LOG(L_ERR,"ERROR:AAANewMessage: failed to create a new AAA message!\n");
	AAAFreeMessage(&msg);
	return 0;
}
Exemplo n.º 17
0
/**
 * Add Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs to outgoing messages in case they are missing
 * @param x
 * @param msg
 */
void add_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
    AAA_AVP *avp;
    char data[4];
    uint32_t v;
    uint32_t lifetime, timeout, grace;

    avp = AAAFindMatchingAVP(msg, 0, AVP_Authorization_Lifetime, 0, 0);
    if (!avp) {
        if (x->lifetime == -1) v = 0xFFFFFFFF;
        else {
            v = x->lifetime - time(0);
            if (v < 0) v = 0;
        }
        x->last_requested_lifetime = v;
        set_4bytes(data, v);
        avp = AAACreateAVP(AVP_Authorization_Lifetime, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
    } else {
        if (avp->data.len == 4) {
            lifetime = get_4bytes(avp->data.s);
            switch (lifetime) {
                case 0:
                    x->last_requested_lifetime = 0;
                    break;
                case 0xFFFFFFFF:
                    x->last_requested_lifetime = -1;
                    break;
                default:
                    x->last_requested_lifetime = lifetime;
            }
        }
    }
    if (x->lifetime != -1) {
        avp = AAAFindMatchingAVP(msg, 0, AVP_Auth_Grace_Period, 0, 0);
        if (!avp) {
            v = x->grace_period;
            set_4bytes(data, v);
            avp = AAACreateAVP(AVP_Auth_Grace_Period, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
            if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
            x->last_requested_grace = v;
        } else {
            if (avp->data.len == 4) {
                grace = get_4bytes(avp->data.s);
                switch (grace) {
                    case 0:
                        x->last_requested_grace = 0;
                        break;
                    case 0xFFFFFFFF:
                        x->last_requested_grace = -1;
                        break;
                    default:
                        x->last_requested_grace = grace;
                }
            }
        }
    }
    avp = AAAFindMatchingAVP(msg, 0, AVP_Session_Timeout, 0, 0);
    if (!avp) {
        if (x->timeout == -1) v = 0xFFFFFFFF;
        else {
            v = x->timeout - time(0);
            if (v < 0) v = 0;
        }
        set_4bytes(data, v);
        avp = AAACreateAVP(AVP_Session_Timeout, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
        x->last_requested_timeout = v;
    } else {
        if (avp->data.len == 4) {
            timeout = get_4bytes(avp->data.s);
            switch (timeout) {
                case 0:
                    x->last_requested_timeout = 0;
                    break;
                case 0xFFFFFFFF:
                    x->last_requested_timeout = -1;
                    break;
                default:
                    x->last_requested_timeout = lifetime;
            }
        }
    }

}
Exemplo n.º 18
0
/**
 * Receives a mesasge and does basic processing or call the sm_process().
 * This gets called from the receive_loop for every message that is received.
 * @param msg - the message received
 * @param sock - socket received on
 */
void receive_message(AAAMessage *msg,int sock)
{
	AAA_AVP *avp1,*avp2;
	LOG(L_DBG,"DBG:receive_message(): [%d] Recv msg %d\n",sock,msg->commandCode);

	if (!this_peer) {
		this_peer = get_peer_from_sock(sock);
		set_peer_pipe();
	}
	
	if (!this_peer){
		switch (msg->commandCode){
			case Code_CE:
				if (is_req(msg)){
					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
					if (avp1&&avp2){
						this_peer = get_peer_from_fqdn(avp1->data,avp2->data);
					}
					if (!this_peer) {
						LOG(L_ERR,"ERROR:receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
							config->accept_unknown_peers);
						AAAFreeMessage(&msg);
					}else{
						set_peer_pipe();						
						sm_process(this_peer,R_Conn_CER,msg,0,sock);
					}
				}
				else{
					LOG(L_ERR,"ERROR:receive_msg(): Received CEA from an unknown peer -ignored\n");
					AAAFreeMessage(&msg);
				}
				break;
			default:
				LOG(L_ERR,"ERROR:receive_msg(): Received non-CE from an unknown peer -ignored\n");
				AAAFreeMessage(&msg);				
		}
	}else{
		touch_peer(this_peer);
		switch (this_peer->state){
			case Wait_I_CEA:
				if (msg->commandCode!=Code_CE||is_req(msg)){
					sm_process(this_peer,I_Rcv_Non_CEA,msg,0,sock);
				}else
					sm_process(this_peer,I_Rcv_CEA,msg,0,sock);
				break;
			case I_Open:			
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_CER,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_CEA,msg,0,sock);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_DWR,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_DWA,msg,0,sock);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_DPR,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_DPA,msg,0,sock);
						break;
					default:
						sm_process(this_peer,I_Rcv_Message,msg,0,sock);
				}				
				break;				
			case R_Open:			
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_CER,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_CEA,msg,0,sock);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_DWR,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_DWA,msg,0,sock);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_DPR,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_DPA,msg,0,sock);
						break;
					default:
						sm_process(this_peer,R_Rcv_Message,msg,0,sock);
				}				
				break;				
			default:
				LOG(L_ERR,"ERROR:receive_msg(): Received msg while peer in state %d -ignored\n",this_peer->state);
				AAAFreeMessage(&msg);								
		}
	}
}
Exemplo n.º 19
0
/*! \brief send a message over an already opened TCP connection */
int tcp_send_recv(int sockfd, char* buf, int len, rd_buf_t* rb, 
					unsigned int waited_id)
{
	int n, number_of_tries;
	fd_set active_fd_set, read_fd_set;
	struct timeval tv;
	unsigned long int result_code;
	AAAMessage *msg;
	AAA_AVP	*avp;
	char serviceType;
	unsigned int m_id;

	/* try to write the message to the Diameter client */
	while( (n=write(sockfd, buf, len))==-1 ) 
	{
		if (errno==EINTR)
			continue;
		LM_ERR("write returned error: %s\n", strerror(errno));
		return AAA_ERROR;
	}

	if (n!=len) 
	{
		LM_ERR("write gave no error but wrote less than asked\n");
		return AAA_ERROR;
	}
	/* wait for the answer a limited amount of time */
	tv.tv_sec = MAX_WAIT_SEC;
	tv.tv_usec = MAX_WAIT_USEC;

	/* Initialize the set of active sockets. */
	FD_ZERO (&active_fd_set);
	FD_SET (sockfd, &active_fd_set);
	number_of_tries = 0;

	while(number_of_tries<MAX_TRIES)
	{
		read_fd_set = active_fd_set;
		if (select (sockfd+1, &read_fd_set, NULL, NULL, &tv) < 0)
		{
			LM_ERR("select function failed\n");
			return AAA_ERROR;
		}

/*		if (!FD_ISSET (sockfd, &read_fd_set))
		{
			LM_ERR("no response received\n");
//			return AAA_ERROR;
		}
*/		/* Data arriving on a already-connected socket. */
		reset_read_buffer(rb);
		switch( do_read(sockfd, rb) )
		{
			case CONN_ERROR:
				LM_ERR("failed to read from socket\n");
				return AAA_CONN_CLOSED;
			case CONN_CLOSED:
				LM_ERR("failed to read from socket\n");
				return AAA_CONN_CLOSED;
		}
		
		/* obtain the structure corresponding to the message */
		msg = AAATranslateMessage(rb->buf, rb->buf_len, 0);	
		if(!msg)
		{
			LM_ERR("message structure not obtained\n");	
			return AAA_ERROR;
		}
		avp = AAAFindMatchingAVP(msg, NULL, AVP_SIP_MSGID,
								vendorID, AAA_FORWARD_SEARCH);
		if(!avp)
		{
			LM_ERR("AVP_SIP_MSGID not found\n");
			return AAA_ERROR;
		}
		m_id = *((unsigned int*)(avp->data.s));
		LM_DBG("######## m_id=%d\n", m_id);
		if(m_id!=waited_id)
		{
			number_of_tries ++;
			LM_NOTICE("old message received\n");
			continue;
		}
		goto next;
	}

	LM_ERR("too many old messages received\n");
	return AAA_TIMEOUT;
next:

	/* Finally die correct answer */
	avp = AAAFindMatchingAVP(msg, NULL, AVP_Service_Type,
							vendorID, AAA_FORWARD_SEARCH);
	if(!avp)
	{
		LM_ERR("AVP_Service_Type not found\n");
		return AAA_ERROR;
	}
	serviceType = avp->data.s[0];

	result_code = ntohl(*((unsigned long int*)(msg->res_code->data.s)));
	switch(result_code)
	{
		case AAA_SUCCESS:					/* 2001 */
			return ACC_SUCCESS;
		default:							/* error */
			return ACC_FAILURE;
	}
}
Exemplo n.º 20
0
/**
 * Receives a message and does basic processing or call the sm_process().
 * This gets called from the do_receive() for every message that is received.
 * Basic processing, before the state machine, is done here.
 * @param msg - the message received
 * @param sp - the serviced peer that it was receiver on
 */
void receive_message(AAAMessage *msg,serviced_peer_t *sp)
{
	AAA_AVP *avp1,*avp2;
	LM_DBG("receive_message(): [%.*s] Recv msg %d\n",
			sp->p?sp->p->fqdn.len:0,
			sp->p?sp->p->fqdn.s:0,
			msg->commandCode);

	if (!sp->p){
		switch (msg->commandCode){
			case Code_CE:
				if (is_req(msg)){
					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
					if (avp1&&avp2){
						sp->p = get_peer_from_fqdn(avp1->data,avp2->data);
					}
					if (!sp->p) {
						LM_ERR("receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
							config->accept_unknown_peers);
						AAAFreeMessage(&msg);
					}else{
						LM_DBG("receive_message(): [%.*s] This receiver has no peer associated\n",
								sp->p?sp->p->fqdn.len:0,
								sp->p?sp->p->fqdn.s:0	);
						//set_peer_pipe();
						make_send_pipe(sp);
						sm_process(sp->p,R_Conn_CER,msg,0,sp->tcp_socket);
					}
				}
				else{
					LM_ERR("receive_msg(): Received CEA from an unknown peer -ignored\n");
					AAAFreeMessage(&msg);
				}
				break;
			default:
				LM_ERR("receive_msg(): Received non-CE from an unknown peer -ignored\n");
				AAAFreeMessage(&msg);
		}
	}else{
		touch_peer(sp->p);
		switch (sp->p->state){
			case Wait_I_CEA:
				if (msg->commandCode!=Code_CE||is_req(msg)){
					sm_process(sp->p,I_Rcv_Non_CEA,msg,0,sp->tcp_socket);
				}else
					sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
				break;
			case I_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_CER,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DWR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DPR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,I_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			case R_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_CER,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DWR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DPR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,R_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			default:
				LM_ERR("receive_msg(): [%.*s] Received msg while peer in state %d -ignored\n",
						sp->p->fqdn.len,
						sp->p->fqdn.s,
						sp->p->state);
				AAAFreeMessage(&msg);
		}
	}
}
Exemplo n.º 21
0
void save_peer_applications(peer *p,AAAMessage *msg)
{
	int total_cnt=0;
	int supported_vendor_id_avp_cnt = 0;
	AAA_AVP *avp,*avp_vendor,*avp2;
	AAA_AVP_LIST group;
	int id,vendor;

	if (p->applications) {
		shm_free(p->applications);
		p->applications = 0;
		p->applications_cnt = 0;
	}

	supported_vendor_id_avp_cnt = count_Supported_Vendor_Id_AVPS(msg);

	for(avp=msg->avpList.head;avp;avp = avp->next)

		switch (avp->code){
			case AVP_Auth_Application_Id:
				total_cnt += supported_vendor_id_avp_cnt;
				break;
			case AVP_Acct_Application_Id:
				total_cnt += supported_vendor_id_avp_cnt;
				break;
			case AVP_Vendor_Specific_Application_Id:
				total_cnt+=2;/* wasteful, but let's skip decoding */
				break;
		}
	p->applications_cnt = 0;
	p->applications = shm_malloc(sizeof(app_config)*total_cnt);
	if (!p->applications){
		LM_ERR("save_peer_applications(): Error allocating %ld bytes! No applications saved...\n",
				(long int)(sizeof(app_config)*total_cnt));
		return;
	}
	for(avp=msg->avpList.head;avp;avp = avp->next)
	{

		switch (avp->code){
			case AVP_Auth_Application_Id:
				id = get_4bytes(avp->data.s);
				add_peer_application(p,id,0,DP_AUTHORIZATION);
				avp_vendor = AAAFindMatchingAVP(msg,0,AVP_Supported_Vendor_Id,0,0);
				while (avp_vendor) {

					vendor = get_4bytes(avp_vendor->data.s);
					LM_DBG("Found Supported Vendor for Application %i: %i\n", DP_AUTHORIZATION, vendor);
					add_peer_application(p,id,vendor,DP_AUTHORIZATION);
					if (!avp_vendor->next)
						break;
					avp_vendor = AAAFindMatchingAVP(msg,avp_vendor->next,AVP_Supported_Vendor_Id,0,AAA_FORWARD_SEARCH);
				}
				break;
			case AVP_Acct_Application_Id:
				id = get_4bytes(avp->data.s);
				add_peer_application(p,id,0,DP_ACCOUNTING);
				avp_vendor = AAAFindMatchingAVP(msg,0,AVP_Supported_Vendor_Id,0,0);
				while (avp_vendor) {
					vendor = get_4bytes(avp_vendor->data.s);
					LM_DBG("Found Supported Vendor for Application %i: %i\n", DP_ACCOUNTING, vendor);
					add_peer_application(p,id,vendor,DP_ACCOUNTING);
					if (!avp_vendor->next)
						break;
					avp_vendor = AAAFindMatchingAVP(msg,avp_vendor->next,AVP_Supported_Vendor_Id,0,AAA_FORWARD_SEARCH);
				}
				break;
			case AVP_Vendor_Specific_Application_Id:
				group = AAAUngroupAVPS(avp->data);
				avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,AAA_FORWARD_SEARCH);
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					add_peer_application(p,id,vendor,DP_AUTHORIZATION);
				}
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,AAA_FORWARD_SEARCH);
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					add_peer_application(p,id,vendor,DP_ACCOUNTING);
				}
				AAAFreeAVPList(&group);
				break;

		}
	}
}
Exemplo n.º 22
0
/**
 *  This function convert message from the network format to the AAAMessage structure (decoder).
 * @param source - the source char buffer
 * @param sourceLen - the length of the input buffer
 * @param attach_buf - whether to attach the input buffer to the message
 * @returns the AAAMessage* or NULL on error
 * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
 */
AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
															int attach_buf)
{
	unsigned char *ptr;
	AAAMessage    *msg;
	unsigned char version;
	unsigned int  msg_len;
	AAA_AVP       *avp;
	unsigned int  avp_code;
	unsigned char avp_flags;
	unsigned int  avp_len;
	unsigned int  avp_vendorID;
	unsigned int  avp_data_len;

	/* check the params */
	if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
		LOG(L_ERR,"ERROR:AAATranslateMessage: invalid buffered received!\n");
		goto error;
	}

	/* inits */
	msg = 0;
	avp = 0;
	ptr = source;

	/* alloc a new message structure */
	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
	if (!msg) {
		LOG(L_ERR,"ERROR:AAATranslateMessage: no more free memory!!\n");
		goto error;
	}
	memset(msg,0,sizeof(AAAMessage));

	/* get the version */
	version = (unsigned char)*ptr;
	ptr += VER_SIZE;
	if (version!=1) {
		LOG(L_ERR,"ERROR:AAATranslateMessage: invalid version [%d]in "
			"AAA msg\n",version);
		goto error;
	}

	/* message length */
	msg_len = get_3bytes( ptr );
	ptr += MESSAGE_LENGTH_SIZE;
	if (msg_len>sourceLen) {
		LOG(L_ERR,"ERROR:AAATranslateMessage: AAA message len [%d] bigger then"
			" buffer len [%d]\n",msg_len,sourceLen);
		goto error;
	}

	/* command flags */
	msg->flags = *ptr;
	ptr += FLAGS_SIZE;

	/* command code */
	msg->commandCode = get_3bytes( ptr );
	ptr += COMMAND_CODE_SIZE;

	/* application-Id */
	msg->applicationId = get_4bytes( ptr );
	ptr += APPLICATION_ID_SIZE;

	/* Hop-by-Hop-Id */
	msg->hopbyhopId = ntohl(*((unsigned int*)ptr));
	ptr += HOP_BY_HOP_IDENTIFIER_SIZE;

	/* End-to-End-Id */
	msg->endtoendId = ntohl(*((unsigned int*)ptr));
	ptr += END_TO_END_IDENTIFIER_SIZE;

	/* start decoding the AVPS */
	while (ptr < source+msg_len) {
		if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
			LOG(L_ERR,"ERROR:AAATranslateMessage: source buffer to short!! "
				"Cannot read the whole AVP header!\n");
			goto error;
		}
		/* avp code */
		avp_code = get_4bytes( ptr );
		ptr += AVP_CODE_SIZE;
		/* avp flags */
		avp_flags = (unsigned char)*ptr;
		ptr += AVP_FLAGS_SIZE;
		/* avp length */
		avp_len = get_3bytes( ptr );
		ptr += AVP_LENGTH_SIZE;
		if (avp_len<1) {
			LOG(L_ERR,"ERROR:AAATranslateMessage: invalid AVP len [%d]\n",
				avp_len);
			goto error;
		}
		/* avp vendor-ID */
		avp_vendorID = 0;
		if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
			avp_vendorID = get_4bytes( ptr );
			ptr += AVP_VENDOR_ID_SIZE;
		}
		/* data length */
		avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
		/*check the data length */
		if ( source+msg_len<ptr+avp_data_len) {
			LOG(L_ERR,"ERROR:AAATranslateMessage: source buffer to short!! "
				"Cannot read a whole data for AVP!\n");
			goto error;
		}

		/* create the AVP */
		avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*) ptr,
			avp_data_len, AVP_DONT_FREE_DATA);
		if (!avp)
			goto error;

		/* link the avp into aaa message to the end */
		AAAAddAVPToMessage( msg, avp, msg->avpList.tail);

		ptr += to_32x_len( avp_data_len );
	}

	/* link the buffer to the message */
	if (attach_buf) {
		msg->buf.s = (char*) source;
		msg->buf.len = msg_len;
	}

	msg->sessionId = AAAFindMatchingAVP(msg,0,AVP_Session_Id,0,0);

	//AAAPrintMessage( msg );
	return  msg;
error:
	LOG(L_ERR,"ERROR:AAATranslateMessage: message conversion droped!!\n");
	AAAFreeMessage(&msg);
	return 0;
}
Exemplo n.º 23
0
/**
 * Retrieve the Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs and update the session timers accordingly
 * @param x
 * @param msg
 */
void update_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
    AAA_AVP *avp;
    uint32_t session_timeout = 0, grace_period = 0, auth_lifetime = 0;
    int update_grace = 0, update_lifetime = 0;

    avp = AAAFindMatchingAVP(msg, 0, AVP_Auth_Grace_Period, 0, 0);
    if (avp && avp->data.len == 4) {
        grace_period = get_4bytes(avp->data.s);
        update_grace = 1;
    } else {
        if (!avp) {
            grace_period = x->last_requested_grace;
        }
    }
    if (update_grace)
        x->grace_period = grace_period;


    avp = AAAFindMatchingAVP(msg, 0, AVP_Authorization_Lifetime, 0, 0);
    if (avp && avp->data.len == 4) {
        auth_lifetime = get_4bytes(avp->data.s);
        update_lifetime = 1;
        
    } else {
        if (!avp) {
            LM_DBG("using timers from our request as there is nothing in the response (lifetime) - last requested lifetime was [%d]\n", x->last_requested_lifetime);
            if (x->last_requested_lifetime > 0) {
                update_lifetime = 1;
                auth_lifetime = x->last_requested_lifetime;
            }
        }
    }
    if (update_lifetime) {
        switch (auth_lifetime) {
            case 0:
                x->lifetime = time(0);
                break;
            case 0xFFFFFFFF:
                x->lifetime = -1;
                break;
            default:
                x->lifetime = time(0) + auth_lifetime;
        }
        if (x->timeout != -1 && x->timeout < x->lifetime) {
            x->timeout = x->lifetime + x->grace_period;
        }
    }
    
    avp = AAAFindMatchingAVP(msg, 0, AVP_Session_Timeout, 0, 0);
    if (avp && avp->data.len == 4) {
        session_timeout = get_4bytes(avp->data.s);
        switch (session_timeout) {
            case 0:
                x->timeout = time(0) + config->default_auth_session_timeout;
                break;
            case 0xFFFFFFFF:
                x->timeout = -1;
                break;
            default:
                x->timeout = time(0) + session_timeout;
        }
        if (!x->lifetime) x->lifetime = x->timeout;
    }
}
Exemplo n.º 24
0
void Send_STR(cdp_session_t* s, AAAMessage* msg) {
    AAAMessage *str = 0;
    AAA_AVP *avp = 0;
    peer *p = 0;
    char x[4];
    LM_DBG("sending STR\n");
    //if (msg) LM_DBG("Send_STR() : sending STR for %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId);
    //else LM_DBG("Send_STR() called from AAATerminateAuthSession or some other event\n");
    str = AAACreateRequest(s->application_id, IMS_STR, Flag_Proxyable, s);

    if (!str) {
        LM_ERR("Send_STR(): error creating STR!\n");
        return;
    }
    if (!dup_routing_avps(msg, str)) {
        LM_ERR("Send_STR(): error duplicating routing AVPs!\n");
        AAAFreeMessage(&str);
        return;
    }
    if (s->vendor_id != 0 && !add_vendor_specific_application_id_group(str, s->vendor_id, s->application_id)) {
        LM_ERR("Send_STR(): error adding Vendor-Id-Specific-Application-Id Group!\n");
        AAAFreeMessage(&str);
        return;
    }

    //Richard added this - if timers expire dest realm is not here!
    LM_DBG("Adding dest realm if not there already...\n");
    LM_DBG("Destination realm: [%.*s] \n", s->dest_realm.len, s->dest_realm.s);
    /* Add Destination-Realm AVP, if not already there */
    avp = AAAFindMatchingAVP(str, str->avpList.head, AVP_Destination_Realm, 0, AAA_FORWARD_SEARCH);
    if (!avp) {
        avp = AAACreateAVP(AVP_Destination_Realm, AAA_AVP_FLAG_MANDATORY, 0,
                s->dest_realm.s, s->dest_realm.len, AVP_DUPLICATE_DATA);
        AAAAddAVPToMessage(str, avp, str->avpList.tail);
    }




    set_4bytes(x, s->application_id);
    avp = AAACreateAVP(AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA);
    AAAAddAVPToMessage(str, avp, str->avpList.tail);

    set_4bytes(x, 4); // Diameter_administrative
    avp = AAACreateAVP(AVP_Termination_Cause, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA);
    AAAAddAVPToMessage(str, avp, str->avpList.tail);
    //todo - add all the other avps

    /* we are already locked on the auth session*/
    p = get_routing_peer(s, str);

    if (!p) {
        LM_ERR("unable to get routing peer in Send_STR \n");
        if (str) AAAFreeMessage(&str); //needed in frequency
        return;
    }
    //if (str) LM_CRIT("Send_STR() : sending STR  %d, flags %#1x endtoend %u hopbyhop %u\n",str->commandCode,str->flags,str->endtoendId,str->hopbyhopId);
    if (!peer_send_msg(p, str)) {
        LM_DBG("Send_STR peer_send_msg return error!\n");
        if (str) AAAFreeMessage(&str); //needed in frequency
    } else {
        LM_DBG("success sending STR\n");
    }
}
Exemplo n.º 25
0
/**
 * Sends a message to the peer.
 * \note Must be called with a lock on the peer.
 * @param p - peer to send to
 * @param msg - message to send
 */
void Snd_Message(peer *p, AAAMessage *msg)
{
	AAASession *session=0;
	int rcode;
	int send_message_before_session_sm=0;
	LM_DBG("Snd_Message called to peer [%.*s] for %s with code %d \n",
		p->fqdn.len,p->fqdn.s,is_req(msg)?"request":"response",msg->commandCode);
	touch_peer(p);
	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);
	
	if (session){
		LM_DBG("There is a session of type %d\n",session->type);
		switch (session->type){
			case AUTH_CLIENT_STATEFULL:
				if (is_req(msg)) {
					auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
					session = 0;
				}
				else {
					if (msg->commandCode == IMS_ASA){
						if (!msg->res_code){
							msg->res_code = AAAFindMatchingAVP(msg,0,AVP_Result_Code,0,0);
						}
						if (!msg->res_code) {
							auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
							session = 0;
						}
						else {
							rcode = get_4bytes(msg->res_code->data.s);
							if (rcode>=2000 && rcode<3000) {
								peer_send_msg(p,msg);
								send_message_before_session_sm=1;
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_SUCCESS,msg);
								session = 0;
							}
							else {
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
								session = 0;
							}
						}
						
					}else {
						auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;
			case AUTH_SERVER_STATEFULL:
				LM_DBG("this message is matched here to see what request or reply it is\n");
				if (is_req(msg))
				{
					if (msg->commandCode== IMS_ASR)
					{
						LM_DBG("ASR\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg);
						session = 0;
					} else {
						//would be a RAR but ok!
						LM_DBG("other request\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
						session = 0;
					}
				} else {
					if (msg->commandCode == IMS_STR)
					{
						LM_DBG("STA\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg);
						session = 0;
					} else {
						LM_DBG("other reply\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;				 
			default:
				break;
		}
		if (session) AAASessionsUnlock(session->hash);
	}
	if (!send_message_before_session_sm) peer_send_msg(p,msg);
	
}
Exemplo n.º 26
0
/**
 * Get the first connect peer that matches the routing mechanisms.
 * - First the Destination-Host AVP value is tried if connected (the peer does not have to
 * be in the routing table at all).
 * - Then we look for a connected peer in the specific realm for the Destination-Realm AVP
 * - Then we look for the first connected peer in the default routes
 * @param m - the Diameter message to find the destination peer for
 * @returns - the connected peer or null if none connected found
 */
peer* get_routing_peer(cdp_session_t* cdp_session, AAAMessage *m) {
	str destination_realm = {0, 0}, destination_host = {0, 0};
	AAA_AVP *avp, *avp_vendor, *avp2;
	AAA_AVP_LIST group;
	peer *p;
	routing_realm *rr;
	int app_id = 0, vendor_id = 0;

	LM_DBG("getting diameter routing peer for realm: [%.*s]\n", m->dest_realm->data.len, m->dest_realm->data.s);

	app_id = m->applicationId;
	avp = AAAFindMatchingAVP(m, 0, AVP_Vendor_Specific_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp) {
		group = AAAUngroupAVPS(avp->data);
		avp_vendor = AAAFindMatchingAVPList(group, group.head, AVP_Vendor_Id, 0, 0);
		avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Auth_Application_Id, 0, 0);
		if (avp_vendor && avp2) {
			vendor_id = get_4bytes(avp_vendor->data.s);
			app_id = get_4bytes(avp2->data.s);
		}
		avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Acct_Application_Id, 0, 0);
		if (avp_vendor && avp2) {
			vendor_id = get_4bytes(avp_vendor->data.s);
			app_id = get_4bytes(avp2->data.s);
		}
		AAAFreeAVPList(&group);
	}

	avp_vendor = AAAFindMatchingAVP(m, 0, AVP_Vendor_Id, 0, AAA_FORWARD_SEARCH);
	avp = AAAFindMatchingAVP(m, 0, AVP_Auth_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp && avp_vendor) {
		vendor_id = get_4bytes(avp_vendor->data.s);
		app_id = get_4bytes(avp->data.s);
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Acct_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp && avp_vendor) {
		vendor_id = get_4bytes(avp_vendor->data.s);
		app_id = get_4bytes(avp->data.s);
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Host, 0, AAA_FORWARD_SEARCH);
	if (avp) destination_host = avp->data;

	if (destination_host.len) {
		/* There is a destination host present in the message try and route directly there */
		p = get_peer_by_fqdn(&destination_host);
		if (p && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) {
			p->last_selected = time(NULL);
			return p;
		}
		/* the destination host peer is not connected at the moment, try a normal route then */
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Realm, 0, AAA_FORWARD_SEARCH);
	if (avp) destination_realm = avp->data;

	if (!config->r_table) {
		LM_ERR("get_routing_peer(): Empty routing table.\n");
		return 0;
	}

	if (destination_realm.len) {
		/* first search for the destination realm */
		for (rr = config->r_table->realms; rr; rr = rr->next)
			if (rr->realm.len == destination_realm.len &&
					strncasecmp(rr->realm.s, destination_realm.s, destination_realm.len) == 0)
				break;
		if (rr) {
			p = get_first_connected_route(cdp_session, rr->routes, app_id, vendor_id);
			if (p) return p;
			else LM_ERR("get_routing_peer(): No connected Route peer found for Realm <%.*s>. Trying DefaultRoutes next...\n",
					destination_realm.len, destination_realm.s);
		}
	}
	/* if not found in the realms or no destination_realm,
	 * get the first connected host in default routes */
	LM_DBG("no routing peer found, trying default route\n");
	p = get_first_connected_route(cdp_session, config->r_table->routes, app_id, vendor_id);
	if (!p) {
		LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",
				app_id, vendor_id);
	}
	return p;
}
Exemplo n.º 27
0
/**
 *  Allocates a new AAAMessage.
 * @param commandCode - the command code for this message
 * @param applicationId - application id to be set
 * @param sessionId - session id to be set
 * @param request - if you want to create a response, put the request here. If you want a 
 * request, call with NULL
 * @returns the AAAMessage* or NULL on error
 * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
 */
AAAMessage *AAANewMessage(
	AAACommandCode commandCode,
	AAAApplicationId applicationId,
	AAASession *session,
	AAAMessage *request)
{
	AAAMessage   *msg;
	AAA_AVP      *avp;
	AAA_AVP      *avp_t;
	str *sessionId=0;
#if 0
	unsigned int code;
#endif
	// str dest_host={"?",1};
	str dest_realm={"?",1};

	msg = 0;
	if (!session||!session->id.s) {
		if (request){
			/* copy old session id from AVP */
			if (request->sessionId) 
				sessionId = &(request->sessionId->data);
		}else{
			if (commandCode!=Code_DW)
				LM_DBG("AAANewMessage: param session received null and it's a request!!\n");
		}
	}else{
		sessionId = &(session->id);
	}

	/* allocated a new AAAMessage structure and set it to 0 */
	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
	if (!msg) {
		LM_ERR("AAANewMessage: no more free memory!!\n");
		goto error;
	}
	memset(msg,0,sizeof(AAAMessage));

	/* command code */
	msg->commandCode = commandCode;
	/* application ID */
	msg->applicationId = applicationId;

	/*add session ID */
	if (sessionId){
		avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
			AVP_DUPLICATE_DATA);
		if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
			LM_ERR("AAANewMessage: cannot create/add Session-Id avp\n");
			if (avp) AAAFreeAVP( &avp );
			goto error;
		}
		msg->sessionId = avp;
	}

	/* add origin host AVP */
	/* changed by cristian to comply with rfc3588: 
	 * 6.3.  Origin-Host AVP
	 *
	 *    The Origin-Host AVP (AVP Code 264) is of type
	 *    DiameterIdentity... */
	avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LM_ERR("AAANewMessage: cannot create/add Origin-Host avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_host = avp;
	/* add origin realm AVP */
	avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LM_ERR("AAANewMessage: cannot create/add Origin-Realm avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_realm = avp;

	if (!request) {
		/* it's a new request -> set the flag */
		msg->flags = 0x80;
	} else {
		/* link the incoming peer to the answer */
		msg->in_peer = request->in_peer;
		/* set the P flag as in request */
		msg->flags |= request->flags&0x40;
		/**/
		msg->endtoendId = request->endtoendId;
		msg->hopbyhopId = request->hopbyhopId;

		
		//TODO: aon:move this information in the AAASession structure, do not add these fields for
		
	    if (msg->commandCode==Code_CE||msg->commandCode==Code_DP||msg->commandCode==Code_DW ||
			    msg->commandCode==Diameter_CCR || msg->commandCode==Diameter_RAR){
	    	// Don't add Destination Host/Realm because some stacks are way to picky and will just refuse it
	    }else{

			/* Mirror the old originhost/realm to destinationhost/realm*/
			//avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
			//if (avp) dest_host = avp->data;
			/* add destination host and destination realm */
			//avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
			//	dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
			//if (!avp) {
		//		LM_ERR("ERR:AAANewMessage: Failed creating Destination Host avp\n");
		//		goto error;
		//	}
		//	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		//		LM_ERR("ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
		//		AAAFreeAVP(&avp);
		//		goto error;
		//	}
	
			avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
			if (avp) dest_realm = avp->data;
			avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
				dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
			if (!avp) {
				LM_ERR("ERR:AAANewMessage: Failed creating Destination Realm avp\n");
				goto error;
			}
			if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
				LM_ERR("ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
				AAAFreeAVP(&avp);
				goto error;
			}
	    }

		msg->res_code=0;
		/* mirror all the proxy-info avp in the same order */
		avp_t = request->avpList.head;
		while ( (avp_t=AAAFindMatchingAVP
		(request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
			if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
			msg->avpList.tail)!=AAA_ERR_SUCCESS )
				goto error;
		}
	}

	return msg;
error:
	LM_ERR("AAANewMessage: failed to create a new AAA message!\n");
	AAAFreeMessage(&msg);
	return 0;
}