void Send_ASR(cdp_session_t* s, AAAMessage* msg) { AAAMessage *asr = 0; AAA_AVP *avp = 0; peer *p = 0; char x[4]; LM_DBG("Send_ASR() : sending ASR\n"); asr = AAACreateRequest(s->application_id, IMS_ASR, Flag_Proxyable, s); if (!asr) { LM_ERR("Send_ASR(): error creating ASR!\n"); return; } set_4bytes(x, s->application_id); avp = AAACreateAVP(AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA); AAAAddAVPToMessage(asr, avp, asr->avpList.tail); set_4bytes(x, 3); // Not specified avp = AAACreateAVP(AVP_IMS_Abort_Cause, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA); AAAAddAVPToMessage(asr, avp, asr->avpList.tail); //todo - add all the other avps p = get_routing_peer(s, asr); if (!p) { LM_ERR("unable to get routing peer in Send_ASR \n"); if (asr) AAAFreeMessage(&asr); //needed in frequency } if (!peer_send_msg(p, asr)) { if (asr) AAAFreeMessage(&asr); //needed in frequency } else LM_DBG("success sending ASR\n"); }
/** * Create a Diameter Request. * @param app_id - application id to be set * @param command_code - the command code for this message * @param flags - flags to be set * @param sessId - session id to be set * @returns the AAAMessage* or NULL on error */ AAAMessage *AAACreateRequest(AAAApplicationId app_id, AAACommandCode command_code, AAAMsgFlag flags, AAASession *session) { AAAMessage *msg; AAA_AVP *avp; msg = AAANewMessage(command_code,app_id,session,0); if (!msg) return 0; msg->hopbyhopId = next_hopbyhop(); msg->endtoendId = next_endtoend(); msg->flags |= flags; if(session){ /* add destination host and destination realm */ if(session->dest_host.s){ avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, session->dest_host.s,session->dest_host.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAACreateRequest: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAACreateRequest: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } } if(session->dest_realm.s){ avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0, session->dest_realm.s,session->dest_realm.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAACreateRequest: Failed creating Destination Realm avp\n"); goto error; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAACreateRequest: Failed adding Destination Realm avp to message\n"); AAAFreeAVP(&avp); goto error; } } } return msg; error: AAAFreeMessage(&msg); return NULL; }
void Send_STR(cdp_session_t* s, AAAMessage* msg) { AAAMessage *str=0; AAA_AVP *avp=0; peer *p=0; char x[4]; LOG(L_DBG, "sending STR\n"); //if (msg) LOG(L_DBG,"Send_STR() : sending STR for %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId); //else LOG(L_DBG,"Send_STR() called from AAATerminateAuthSession or some other event\n"); str = AAACreateRequest(s->application_id,IMS_STR,Flag_Proxyable,s); if (!str) { LOG(L_ERR,"ERR:Send_STR(): error creating STR!\n"); return; } if(!dup_routing_avps(msg, str)){ LOG(L_ERR,"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)){ LOG(L_ERR,"ERR:Send_STR(): error adding Vendor-Id-Specific-Application-Id Group!\n"); AAAFreeMessage(&str); return; } 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 p = get_routing_peer(str); if (!p) { LOG(L_ERR,"unable to get routing peer in Send_STR \n"); if (str) AAAFreeMessage(&str); //needed in frequency return; } //if (str) LOG(L_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)) { LOG(L_DBG,"Send_STR peer_send_msg return error!\n"); if (str) AAAFreeMessage(&str); //needed in frequency } else { LOG(L_DBG,"success sending STR\n"); } }
/* 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; }
/** * Accounting client: sends an ACR Event and returns answer * @param acr ACR with EVENT_RECORD Accounting-Record-Type * @param dlgid app-level session/dialog id * @param peer_fqdn FQDN of diameter peer to send message to * @return answer (ACA) or NULL if sending failed */ AAAMessage* AAAAcctCliEvent(AAAMessage* acr, str* dlgid, str* peer_fqdn) { // TODO: check acr has Accounting-Record-Type with EVENT_RECORD value AAAMessage* aca = 0; AAA_AVP *avp; AAAAcctSession* s = AAACreateAcctSession(peer_fqdn, dlgid); if (!s) return 0; // add Session-Id AVP avp = AAACreateAVP( 263, 0, 0, s->sID->s, s->sID->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(acr,avp,0)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAAAcctCliEvent: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } acr->sessionId = avp; acct_cli_sm_process(s, ACC_EV_EVENT, acr, aca, 0); AAADropAcctSession(s); // TODO: only drop if received successfull answer, otherwise need to buffer and follow Accounting client state machine... return aca; error: return 0; }
AAAMessage *send_unknown_request_answer(AAAMessage *req) { AAAMessage *ans=0; char x[4]; AAA_AVP *avp; /* UAA header is created based on the UAR */ ans = AAANewMessage(req->commandCode,req->applicationId,0,req); if (!ans) return 0; set_4bytes(x,(unsigned int) DIAMETER_UNABLE_TO_COMPLY); avp = AAACreateAVP(AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR: Failed creating avp for result code\n"); AAAFreeMessage(&ans); return 0; } if (AAAAddAVPToMessage(ans,avp,ans->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR: Failed adding avp to message\n"); AAAFreeAVP(&avp); AAAFreeMessage(&ans); return 0; } return ans; }
/** * 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); } }
int ServerConnection::addDataAVP(AAAMessage* msg, AAA_AVPCode avp_code, char* val, unsigned int len) { AAA_AVP *avp; if( (avp=AAACreateAVP(avp_code, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, val, len, AVP_DUPLICATE_DATA)) == 0) { ERROR( M_NAME ": addDataAVP() no more free memory!\n"); return -1; } if( AAAAddAVPToMessage(msg, avp, 0)!= AAA_ERR_SUCCESS) { ERROR( M_NAME ": addDataAVP(): AVP not added!\n"); return -1; } return 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; }
/** * Create and add an AVP to a Diameter message. * @param m - Diameter message to add to * @param d - the payload data * @param len - length of the payload data * @param avp_code - the code of the AVP * @param flags - flags for the AVP * @param vendorid - the value of the vendor id or 0 if none - Diameter base protocol * @param data_do - what to do with the data when done * @param func - the name of the calling function, for debugging purposes * @returns 1 on success or 0 on failure */ static inline int Rf_add_avp(AAAMessage *m,char *d,int len,int avp_code, int flags,int vendorid,int data_do,const char *func) { AAA_AVP *avp; if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; avp = AAACreateAVP(avp_code,flags,vendorid,d,len,data_do); if (!avp) { LOG(L_ERR,"ERR: Failed creating avp\n"); return 0; } if ( AAAAddAVPToMessage(m,avp,m->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR: Failed adding avp to message\n"); AAAFreeAVP(&avp); return 0; } return 1; }
int ServerConnection::addStringAVP(AAAMessage* msg, AAA_AVPCode avp_code, string& val, bool attail) { AAA_AVP *avp; if( (avp=AAACreateAVP(avp_code, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, val.c_str(), val.length(), AVP_DUPLICATE_DATA)) == 0) { ERROR( M_NAME ": addStringAVP() no more free memory!\n"); return -1; } AAA_AVP *pos = 0; if (attail) pos = msg->avpList.tail; if( AAAAddAVPToMessage(msg, avp, pos)!= AAA_ERR_SUCCESS) { ERROR( M_NAME ": addStringAVP(): AVP not added!\n"); return -1; } return 0; }
AAAMessage* ServerConnection::ReqEvent2AAAMessage(DiameterRequestEvent* re) { AAAMessage* req = AAAInMessage(re->command_code, re->app_id); if (req == NULL) { ERROR("creating new request message.\n"); return NULL; } for (int i=re->val.size()-1;i >= 0; i--) { //[int avp_id, int flags, int vendor, int len, blob data] AmArg& row = re->val.get(i); int avp_id = row.get(0).asInt(); int flags = row.get(1).asInt(); int vendor = row.get(2).asInt(); ArgBlob* data = row.get(3).asBlob(); #ifdef EXTRA_DEBUG DBG("adding avp id %d, flags %d, vendor %d\n", avp_id, flags, vendor); #endif if (!data->len) { #ifdef EXTRA_DEBUG DBG("skipping empty AVP id %d\n", avp_id); #endif continue; } AAA_AVP *avp; if( (avp=AAACreateAVP(avp_id, (AAA_AVPFlag)flags, vendor, (const char*)data->data, data->len, AVP_DUPLICATE_DATA)) == 0) { ERROR( M_NAME ": addDataAVP() no more free memory!\n"); continue; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { ERROR( M_NAME ": addDataAVP(): AVP not added!\n"); continue; } } return req; }
/** * Accounting client sends an ACR Stop and returns answer * @param acr ACR with STOP_RECORD Accounting-Record-Type * @param peer_fqdn FQDN of diameter peer * @param s pointer to existing session * @return answer (ACA) or NULL if sending failed */ AAAMessage* AAAAcctCliStop(AAAMessage* acr, str* peer_fqdn, AAAAcctSession *s) { // TODO: check acr has Accounting-Record-Type with STOP_RECORD value AAAMessage* aca = 0; AAA_AVP *avp; // add Session-Id AVP avp = AAACreateAVP( 263, 0, 0, s->sID->s, s->sID->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(acr,avp,0)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAAAcctCliEvent: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } acr->sessionId = avp; acct_cli_sm_process(s, ACC_EV_STOP, acr, aca, 0); return aca; error: return 0; }
int add_vendor_specific_application_id_group(AAAMessage * msg, unsigned int vendor_id, unsigned int auth_app_id) { char x[4]; AAA_AVP_LIST list_grp = {0, 0}; AAA_AVP *avp; str group = {0, 0}; set_4bytes(x, vendor_id); if (!(avp = AAACreateAVP(AVP_Vendor_Id, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA))) goto error; AAAAddAVPToList(&list_grp, avp); set_4bytes(x, auth_app_id); if (!(avp = AAACreateAVP(AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, x, 4, AVP_DUPLICATE_DATA))) goto error; AAAAddAVPToList(&list_grp, avp); group = AAAGroupAVPS(list_grp); if (!group.s || !group.len) goto error; if (!(avp = AAACreateAVP(AVP_Vendor_Specific_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, group.s, group.len, AVP_DUPLICATE_DATA))) goto error; if (AAAAddAVPToMessage(msg, avp, msg->avpList.tail) != AAA_ERR_SUCCESS) goto error; AAAFreeAVPList(&list_grp); shm_free(group.s); group.s = NULL; return 1; error: AAAFreeAVPList(&list_grp); if (group.s) shm_free(group.s); return 0; }
/* it checks if a user is member of a group */ int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain, uri; dig_cred_t* cred = 0; int hf_type; struct hdr_field* h; struct sip_uri puri; AAAMessage *req; AAA_AVP *avp; int ret; unsigned int tmp; grp = (str*)_group; /* via fixup */ hf_type = (int)(long)_hf; uri.s = 0; uri.len = 0; /* extract the uri according with the _hf parameter */ switch(hf_type) { case 1: /* Request-URI */ uri = *(GET_RURI(_m)); break; case 2: /* To */ if (get_to_uri(_m, &uri) < 0) { LM_ERR("failed to extract To\n"); return -2; } break; case 3: /* From */ if (get_from_uri(_m, &uri) < 0) { LM_ERR("failed to extract From URI\n"); return -3; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LM_ERR("no authorized credentials found " "(error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return -5; } user = puri.user; domain = puri.host; } else { user = cred->username.user; domain = cred->realm; } /* user@domain mode */ if (use_domain) { user_name.s = 0; user_name.len = user.len + domain.len; if(user_name.len>0) { user_name.len++; user_name.s = (char*)pkg_malloc(user_name.len); if (!user_name.s) { LM_ERR("no pkg memory left\n"); return -6; } memcpy(user_name.s, user.s, user.len); if(user.len>0) { user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else memcpy(user_name.s, domain.s, domain.len); } } else user_name = user; if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("can't create new AAA message!\n"); return -1; } /* Username AVP */ if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Usergroup AVP */ if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s, grp->len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* SIP_MSGID AVP */ LM_DBG("******* m_id=%d\n", _m->id); tmp = _m->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(tmp), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* ServiceType AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Destination-Realm AVP */ uri = *(GET_RURI(_m)); parse_uri(uri.s, uri.len, &puri); if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed." "It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != AAA_USER_IN_GROUP) { LM_ERR("message sending to the DIAMETER backend authorization server" "failed or user is not in group\n"); goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }
/* This function convert message to message structure */ 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) { ERROR("ERROR:AAATranslateMessage: invalid buffered received!\n"); goto error; } /* inits */ msg = 0; avp = 0; ptr = source; /* alloc a new message structure */ msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage)); if (!msg) { ERROR("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) { ERROR("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) { ERROR("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 = *((unsigned int*)ptr); ptr += HOP_BY_HOP_IDENTIFIER_SIZE; /* End-to-End-Id */ msg->endtoendId = *((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){ ERROR("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) { ERROR("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) { ERROR("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; } //AAAPrintMessage( msg ); return msg; error: ERROR("ERROR:AAATranslateMessage: message conversion droped!!\n"); AAAFreeMessage(&msg); return 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; } } } }
int acc_diam_request( struct sip_msg *rq, struct hdr_field *to, str *phrase ) { str* val_arr[ALL_LOG_FMT_LEN+1]; str atr_arr[ALL_LOG_FMT_LEN+1]; int attr_cnt; AAAMessage *send = NULL; AAA_AVP *avp; int i; int dummy_len; str* user; str* realm; str user_name; str value; str *uri; struct sip_uri puri; struct to_body* from; int ret, free_user_name; int status; char tmp[2]; unsigned int mid; if (skip_cancel(rq)) return 1; attr_cnt=fmt2strar( DIAM_ACC_FMT, rq, to, phrase, &dummy_len, &dummy_len, val_arr, atr_arr); if (attr_cnt!=(sizeof(DIAM_ACC_FMT)-1)) { LOG(L_ERR, "ERROR: acc_diam_request: fmt2strar failed\n"); return -1; } if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LOG(L_ERR, "ERROR: acc_diam_request: new AAA message not created\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(rq, phrase))<0) { LOG(L_ERR, "ERROR: acc_diam_request: status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ DBG("**ACC***** m_id=%d\n", rq->id); mid = rq->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_STATUS avp */ if( (avp=AAACreateAVP(AVP_SIP_STATUS, 0, 0, phrase->s, phrase->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_METHOD avp */ value = rq->first_line.u.request.method; if( (avp=AAACreateAVP(AVP_SIP_METHOD, 0, 0, value.s, value.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* Handle AVP_USER_NAME as a special case */ free_user_name = 0; user=cred_user(rq); /* try to take it from credentials */ if (user) { realm = cred_realm(rq); if (realm) { user_name.len = user->len+1+realm->len; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "ERROR: acc_diam_request: no memory\n"); goto error; } memcpy(user_name.s, user->s, user->len); user_name.s[user->len] = '@'; memcpy(user_name.s+user->len+1, realm->s, realm->len); free_user_name = 1; } else { user_name.len = user->len; user_name.s = user->s; } } else { /* from from uri */ if (rq->from && (from=get_from(rq)) && from->uri.len) { if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) { LOG(L_ERR, "ERROR: acc_diam_request: Bad From URI\n"); goto error; } user_name.len = puri.user.len+1+puri.host.len; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "ERROR: acc_diam_request: no memory\n"); goto error; } memcpy(user_name.s, puri.user.s, puri.user.len); user_name.s[puri.user.len] = '@'; memcpy(user_name.s+puri.user.len+1, puri.host.s, puri.host.len); free_user_name = 1; } else { user_name.len = na.len; user_name.s = na.s; } } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, free_user_name?AVP_FREE_DATA:AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); if(free_user_name) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* Remaining attributes from diam_attr vector */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attr[i], 0,0, val_arr[i]->s, val_arr[i]->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } } if (get_uri(rq, &uri) < 0) { LOG(L_ERR, "ERROR: acc_diam_request: From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "ERROR: acc_diam_request: Error parsing From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LOG(L_ERR, M_NAME":acc_diam_request: failed to reconnect" " to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, rq->id); if(ret == AAA_CONN_CLOSED) { LOG(L_NOTICE, M_NAME":acc_diam_request: connection to Diameter" " client closed.It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) /* a transmission error occurred */ { LOG(L_ERR, M_NAME":acc_diam_request: message sending to the" " DIAMETER backend authorization server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&send); return -1; }
int acc_diam_request( struct sip_msg *req ) { int attr_cnt; int cnt; AAAMessage *send = NULL; AAA_AVP *avp; struct sip_uri puri; str *uri; int ret; int i; int status; char tmp[2]; unsigned int mid; attr_cnt = core2strar( req, val_arr, int_arr, type_arr ); /* last value is not used */ attr_cnt--; if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("failed to create new AAA request\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(req, acc_env.code))<0) { LM_ERR("status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ mid = req->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* also the extra attributes */ attr_cnt += extra2strar( dia_extra, req, val_arr, int_arr, type_arr); /* add attributes */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } /* and the leg attributes */ if ( leg_info ) { cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1); do { for (i=0; i<cnt; i++) { if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } } while ( (cnt=legs2strar(leg_info,req,val_arr,int_arr, type_arr,0))!=0 ); } if (get_uri(req, &uri) < 0) { LM_ERR("failed to get uri, From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, req->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed.It will be " "reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) { /* a transmission error occurred */ LM_ERR("message sending to the DIAMETER backend authorization " "server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&send); return -1; }
/** * 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; }
void ServerConnection::openConnection() { DBG("init TCP connection\n"); if (conn.dia_conn) { ERROR("CRITICAL: trying to open new connection, while current one still" " opened.\n"); abort(); } conn.dia_conn = tcp_create_connection(server_name.c_str(), server_port, ca_file.c_str(), cert_file.c_str()); if (!conn.dia_conn) { ERROR("establishing connection to %s\n", server_name.c_str()); setRetryConnectLater(); return; } // send CER AAAMessage* cer; if ((cer=AAAInMessage(AAA_CC_CER, AAA_APP_DIAMETER_COMMON_MSG))==NULL) { ERROR(M_NAME":openConnection(): can't create new " "CER AAA message!\n"); conn.terminate(); setRetryConnectLater(); return; } if (addOrigin(cer) || addDataAVP(cer, AVP_Host_IP_Address, origin_ip_address, sizeof(origin_ip_address)) || addDataAVP(cer, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || addDataAVP(cer, AVP_Supported_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || addStringAVP(cer, AVP_Product_Name, product_name)) { ERROR("openConnection(): adding AVPs failed\n"); conn.terminate(); setRetryConnectLater(); return; } // supported applications AAA_AVP* vs_appid; if( (vs_appid=AAACreateAVP(AVP_Vendor_Specific_Application_Id, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, 0, 0, AVP_DONT_FREE_DATA)) == 0) { ERROR( M_NAME":openConnection(): creating AVP failed." " (no more free memory!)\n"); conn.terminate(); setRetryConnectLater(); return; } // feels like c coding... if (addGroupedAVP(vs_appid, AVP_Auth_Application_Id, (char*)&app_id, sizeof(app_id)) || addGroupedAVP(vs_appid, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || (AAAAddAVPToMessage(cer, vs_appid, 0) != AAA_ERR_SUCCESS) ) { ERROR( M_NAME":openConnection(): creating AVP failed." " (no more free memory!)\n"); conn.terminate(); setRetryConnectLater(); return; } #ifdef EXTRA_DEBUG AAAPrintMessage(cer); #endif conn.setIDs(cer); if(AAABuildMsgBuffer(cer) != AAA_ERR_SUCCESS) { ERROR( " openConnection(): message buffer not created\n"); AAAFreeMessage(&cer); return; } int ret = tcp_send(conn.dia_conn, cer->buf.s, cer->buf.len); if (ret) { ERROR( "openConnection(): could not send message\n"); conn.terminate(); setRetryConnectLater(); AAAFreeMessage(&cer); return; } AAAFreeMessage(&cer); unsigned int cea_receive_cnt = 3; while (true) { int res = tcp_recv_msg(conn.dia_conn, &conn.rb, CONNECT_CEA_REPLY_TIMEOUT, 0); if (res <= 0) { if (!res) { ERROR( " openConnection(): did not receive response (CEA).\n"); } else { ERROR( " openConnection(): error receiving response (CEA).\n"); } conn.terminate(); setRetryConnectLater(); return; } /* obtain the structure corresponding to the message */ AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); if(!cea) { ERROR( " openConnection(): could not decipher response (CEA).\n"); conn.terminate(); setRetryConnectLater(); return; } if (cea->commandCode == AAA_CC_CEA) { #ifdef EXTRA_DEBUG AAAPrintMessage(cea); #endif AAAFreeMessage(&cea); break; } AAAFreeMessage(&cea); if (!(cea_receive_cnt--)) { ERROR( " openConnection(): no CEA received.\n"); conn.terminate(); setRetryConnectLater(); return; } } DBG("Connection opened.\n"); open = true; }
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"); } }
/** * 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; }
/* * This function creates and submits diameter authentication request as per * draft-srinivas-aaa-basic-digest-00.txt. * Service type of the request is Authenticate-Only. * Returns: * 1 - success * -1 - error * */ int diameter_authorize(struct hdr_field* hdr, str* p_method, struct sip_uri uri, struct sip_uri ruri, unsigned int m_id, rd_buf_t* rb) { str method, user_name; AAAMessage *req; AAA_AVP *avp, *position; int name_flag, port_flag; dig_cred_t* cred; unsigned int tmp; user_name.s=0; /* fixes gcc 4.0 warning */ if ( !p_method ) { LOG(L_ERR, M_NAME":diameter_authorize(): Invalid parameter value\n"); return -1; } if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) return -1; if(hdr && hdr->parsed) cred = &(((auth_body_t*)hdr->parsed)->digest); else cred = NULL; method = *p_method; if(!cred) { /* Username AVP */ user_name.len = uri.user.len + uri.host.len; if(user_name.len>0) { user_name.len += 2; user_name.s = (char*)ad_malloc(user_name.len*sizeof(char)); memset(user_name.s, 0, user_name.len); memcpy(user_name.s, uri.user.s, uri.user.len); if(uri.user.len>0) { memcpy(user_name.s+uri.user.len, "@", 1); memcpy(user_name.s+uri.user.len+1, uri.host.s, uri.host.len); } else memcpy(user_name.s, uri.host.s, uri.host.len); } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR,M_NAME":diameter_authorize(): no more free memory!\n"); if(user_name.len>0) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } else /* it is a SIP message with credentials */ { /* Add Username AVP */ if (cred->username.domain.len>0) { if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, cred->username.whole.s, cred->username.whole.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } else { user_name.len = cred->username.user.len + cred->realm.len; if(user_name.len>0) { user_name.s = ad_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory\n"); goto error; } memcpy(user_name.s, cred->username.whole.s, cred->username.whole.len); if(cred->username.whole.len>0) { user_name.s[cred->username.whole.len] = '@'; memcpy(user_name.s + cred->username.whole.len + 1, cred->realm.s, cred->realm.len); } else memcpy(user_name.s, cred->realm.s, cred->realm.len); } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory!\n"); if(user_name.len>0) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } } /* SIP_MSGID AVP */ DBG("******* m_id=%d\n", m_id); tmp = m_id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(m_id), AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_AUTHENTICATION, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, uri.host.s, uri.host.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } #ifdef DEBUG DBG("Destination Realm: %.*s\n", uri.host.len, uri.host.s); #endif if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Resource AVP */ user_name.len = ruri.user.len + ruri.host.len + ruri.port.len + 2; user_name.s = (char*)ad_malloc(user_name.len*sizeof(char)); memset(user_name.s, 0, user_name.len); memcpy(user_name.s, ruri.user.s, ruri.user.len); name_flag= 0; if(ruri.user.s) { name_flag = 1; memcpy(user_name.s+ruri.user.len, "@", 1); } memcpy(user_name.s+ruri.user.len+name_flag, ruri.host.s, ruri.host.len); port_flag=0; if(ruri.port.s) { port_flag = 1; memcpy(user_name.s+ruri.user.len+ruri.host.len+1, ":", 1); } memcpy(user_name.s+ruri.user.len+ruri.host.len+name_flag+port_flag, ruri.port.s, ruri.port.len); #ifdef DEBUG DBG(M_NAME": AVP_Resource=%.*s\n", user_name.len, user_name.s); #endif if( (avp=AAACreateAVP(AVP_Resource, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); if(user_name.s) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } if(cred) /* it is a SIP message with credentials */ { /* Response AVP */ if( (avp=AAACreateAVP(AVP_Response, 0, 0, hdr->body.s, hdr->body.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } position = AAAGetLastAVP(&(req->avpList)); if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Method AVP */ if( (avp=AAACreateAVP(AVP_Method, 0, 0, p_method->s, p_method->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } position = AAAGetLastAVP(&(req->avpList)); if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LOG(L_ERR, M_NAME":diameter_authorize(): failed to reconnect" " to Diameter client\n"); goto error; } } /* send the message to the DIAMETER CLIENT */ switch( tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, m_id) ) { case AAA_ERROR: /* a transmission error occurred */ LOG(L_ERR, M_NAME":diameter_authorize(): message sending to the" " DIAMETER backend authorization server failed\n"); goto error; case AAA_CONN_CLOSED: LOG(L_NOTICE, M_NAME":diameter_authorize(): connection to Diameter" " client closed.It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; case AAA_TIMEOUT: LOG(L_NOTICE,M_NAME":diameter_authorize(): no response received\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }