Mercurial > hg > freeDiameter
view extensions/app_diameap/diameap_server.c @ 1328:81af4f5a517a
Improve shutdown.
Should generate less messages that can not get sent out.
author | Thomas Klausner <tk@giga.or.at> |
---|---|
date | Mon, 27 Nov 2017 15:22:42 +0100 |
parents | 100a0925f809 |
children | 3cbe458fbfa9 |
line wrap: on
line source
/***************************************************************************************************** * Software License Agreement (BSD License) * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp> * * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project * All rights reserved. * * Redistribution and use of this software in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>. * * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************************************/ #include "diameap_common.h" /* handler for DiamEAP server callback */ static struct disp_hdl * handle; /* session handler for DiamEAP sessions state machine */ static struct session_handler * diameap_server_reg = NULL; struct avp_max_occurences auth_avps[] = { { "Service-Type", 1 }, { "Callback-Number", 1 }, { "Callback-Id", 1 }, { "Idle-Timeout", 1 }, { "Port-Limit", 1 }, { "NAS-Filter-Rule" - 1 }, { "Filter-Id", -1 }, { "Configuration-Token", -1 }, { "QoS-Filter-Rule", -1 }, { "Framed-Protocol", 1 }, { "Framed-Routing", 1 }, { "Framed-MTU", 1 }, { "Framed-Compression", -1 }, { "Framed-IP-Address", 1 }, { "Framed-IP-Netmask", 1 }, { "Framed-Route", -1 }, { "Framed-Pool", 1 }, { "Framed-Interface-Id", 1 }, { "Framed-IPv6-Prefix", -1 }, { "Framed-IPv6-Pool", 1 }, { "Framed-IPv6-Route", -1 }, { "Framed-IPX-Network", 1 }, { "Framed-Appletalk-Link", 1 }, { "Framed-Appletalk-Network", -1 }, { "Framed-Appletalk-Zone", 1 }, { "NAS-IPv6-Address", 0 }, { "NAS-Identifier", 0 }, { "NAS-IP-Address", 0 }, { "NAS-Port", 0 }, { "NAS-Port-Id", 0 }, { "NAS-Port-Type", 0 }, { "Called-Station-Id", 0 }, { "Calling-Station-Id", 0 }, { "Connect-Info", 0 }, { "Originating-Line-Info", 0 } }; void diameap_cli_sess_cleanup(struct sess_state * diameap_sess_data, os0_t sid, void * opaque) { CHECK_PARAMS_DO( diameap_sess_data, return ); if (diameap_sess_data != NULL) { if (diameap_sess_data->methodData != NULL) { struct plugin * cplugin; if (diameap_plugin_get(diameap_sess_data->currentVendor, diameap_sess_data->currentMethod, &cplugin)) { TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sess_data->currentMethod,diameap_sess_data->currentVendor); } if (cplugin->eap_method_free) { (*cplugin->eap_method_free)(diameap_sess_data->methodData); diameap_sess_data->methodData = NULL; } else { TRACE_DEBUG(FULL+1,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname); if (diameap_sess_data->methodData != NULL) { free(diameap_sess_data->methodData); diameap_sess_data->methodData = NULL; } } if (diameap_sess_data->methodData) { TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION); } } if (diameap_sess_data->user.password != NULL) { free(diameap_sess_data->user.password); diameap_sess_data->user.password = NULL; } if (diameap_sess_data->user.userid != NULL) { free(diameap_sess_data->user.userid); diameap_sess_data->user.userid = NULL; } free(diameap_sess_data); diameap_sess_data = NULL; } } static int diameap_initialize_diameap_sm( struct diameap_state_machine * diameap_sm, struct sess_state * diameap_sess_data) { TRACE_ENTRY("%p %p", diameap_sm, diameap_sess_data); int i; /* Initialize Long Term Variables */ if (diameap_sess_data != NULL) { diameap_sm->invalid_eappackets = diameap_sess_data->invalid_eappackets; /* Initialize eap state machine variables */ /*User*/ diameap_sm->eap_sm.user.id = diameap_sess_data->user.id; if ((diameap_sess_data->user.userid != NULL) && (diameap_sess_data->user.useridLength > 0)) { diameap_sm->eap_sm.user.useridLength = diameap_sess_data->user.useridLength; CHECK_MALLOC(diameap_sm->eap_sm.user.userid= malloc(diameap_sm->eap_sm.user.useridLength+1)); U8COPY(diameap_sm->eap_sm.user.userid,0,diameap_sm->eap_sm.user.useridLength+1,diameap_sess_data->user.userid); free(diameap_sess_data->user.userid); diameap_sess_data->user.userid = NULL; } else { TRACE_DEBUG(INFO,"%s user not identified yet.",DIAMEAP_EXTENSION); diameap_sm->eap_sm.user.useridLength = 0; diameap_sm->eap_sm.user.userid = NULL; } if ((diameap_sess_data->user.password != NULL) && (diameap_sess_data->user.passwordLength > 0)) { diameap_sm->eap_sm.user.passwordLength = diameap_sess_data->user.passwordLength; CHECK_MALLOC(diameap_sm->eap_sm.user.password = malloc(diameap_sm->eap_sm.user.passwordLength+1)); U8COPY(diameap_sm->eap_sm.user.password,0,diameap_sm->eap_sm.user.passwordLength+1, diameap_sess_data->user.password); free(diameap_sess_data->user.password); diameap_sess_data->user.password = NULL; } else { diameap_sm->eap_sm.user.passwordLength = 0; diameap_sm->eap_sm.user.password = NULL; } diameap_sm->eap_sm.user.methodId = diameap_sess_data->user.methodId; for (i = 0; i < MAXMETHODS; i++) { diameap_sm->eap_sm.user.methods[i].method = diameap_sess_data->user.methods[i].method; diameap_sm->eap_sm.user.methods[i].vendor = diameap_sess_data->user.methods[i].vendor; } for (i = 0; i < MAXPROPOSEDMETHODS; i++) { diameap_sm->eap_sm.user.proposedmethods[i].method = diameap_sess_data->user.proposedmethods[i].method; diameap_sm->eap_sm.user.proposedmethods[i].vendor = diameap_sess_data->user.proposedmethods[i].vendor; } diameap_sm->eap_sm.user.pmethods = diameap_sess_data->user.pmethods; diameap_sm->eap_sm.user.proposed_eap_method = diameap_sess_data->user.proposed_eap_method; diameap_sm->eap_sm.user.proposed_eap_method_vendor = diameap_sess_data->user.proposed_eap_method_vendor; diameap_sm->eap_sm.user.success = diameap_sess_data->user.success; diameap_sm->eap_sm.currentId = diameap_sess_data->currentId; diameap_sm->eap_sm.currentVendor = diameap_sess_data->currentVendor; diameap_sm->eap_sm.lastId = diameap_sess_data->lastId; diameap_sm->eap_sm.methodState = diameap_sess_data->methodState; diameap_sm->eap_sm.currentMethod = diameap_sess_data->currentMethod; diameap_sm->eap_sm.methodData = diameap_sess_data->methodData; diameap_sess_data->methodData = NULL; if (diameap_sm->eap_sm.currentMethod != TYPE_NONE) { diameap_plugin_get(diameap_sm->eap_sm.currentVendor, diameap_sm->eap_sm.currentMethod, &diameap_sm->eap_sm.selectedMethod); } /* free session data*/ free(diameap_sess_data); diameap_sess_data = NULL; } else { diameap_sm->invalid_eappackets = 0; /* Initialize eap state machine variables */ /*User*/ diameap_sm->eap_sm.user.id = 0; diameap_sm->eap_sm.user.userid = NULL; diameap_sm->eap_sm.user.useridLength = 0; diameap_sm->eap_sm.user.password = NULL; diameap_sm->eap_sm.user.passwordLength = 0; diameap_sm->eap_sm.user.methodId = -1; for (i = 0; i < MAXMETHODS; i++) { diameap_sm->eap_sm.user.methods[i].method = TYPE_NONE; diameap_sm->eap_sm.user.methods[i].vendor = VENDOR_IETF; } for (i = 0; i < MAXPROPOSEDMETHODS; i++) { diameap_sm->eap_sm.user.proposedmethods[i].method = TYPE_NONE; diameap_sm->eap_sm.user.proposedmethods[i].vendor = VENDOR_IETF; } diameap_sm->eap_sm.user.pmethods = -1; diameap_sm->eap_sm.user.proposed_eap_method = TYPE_NONE; diameap_sm->eap_sm.user.proposed_eap_method_vendor = VENDOR_IETF; diameap_sm->eap_sm.user.success = FALSE; diameap_sm->eap_sm.currentId = -1; diameap_sm->eap_sm.currentVendor = VENDOR_IETF; diameap_sm->eap_sm.lastId = -1; diameap_sm->eap_sm.methodState = EAP_M_PROPOSED; diameap_sm->eap_sm.currentMethod = TYPE_NONE; diameap_sm->eap_sm.methodData = NULL; } diameap_sm->result_code = 0; fd_list_init(&diameap_sm->attributes, NULL); fd_list_init(&diameap_sm->req_attributes, NULL); fd_list_init(&diameap_sm->ans_attributes, NULL); diameap_sm->failedavp = NULL; diameap_sm->auth_request_val = AUTHENTICATE_ONLY; diameap_sm->verify_authorization = FALSE; diameap_sm->authSuccess = FALSE; diameap_sm->authFailure = FALSE; diameap_sm->lastReqEAPavp = NULL; diameap_sm->privateUser = FALSE; diameap_sm->authorized = FALSE; diameap_sm->eap_sm.rxResp = FALSE; diameap_sm->eap_sm.respId = -1; diameap_sm->eap_sm.respMethod = TYPE_NONE; diameap_sm->eap_sm.respVendor = VENDOR_IETF; diameap_sm->eap_sm.respVendorMethod = TYPE_NONE; return 0; } static int diameap_initialize_diameap_eap_interface( struct diameap_eap_interface * eap_i) { TRACE_ENTRY("%p", eap_i); //Initialize AAA-EAP Interface eap_i->aaaEapResp = FALSE; eap_i->aaaEapRespData.data = NULL; //Initialize EAP-AAA Interface eap_i->aaaEapReq = FALSE; eap_i->aaaEapNoReq = FALSE; eap_i->aaaSuccess = FALSE; eap_i->aaaFail = FALSE; eap_i->aaaEapReqData.data = NULL; eap_i->aaaEapMSKData = NULL; eap_i->aaaEapEMSKData = NULL; eap_i->aaaEapKeyAvailable = FALSE; eap_i->aaaMethodTimeout = 0; return 0; } static int diameap_failed_avp(struct diameap_state_machine * diameap_sm, struct avp * invalidavp) { TRACE_ENTRY("%p %p",diameap_sm,invalidavp); if (!invalidavp) return EINVAL; if (!diameap_sm) return EINVAL; if (diameap_sm->failedavp == NULL) { CHECK_FCT( fd_msg_avp_new( dataobj_failed_avp, 0, &diameap_sm->failedavp) ); CHECK_FCT( fd_msg_avp_add( diameap_sm->failedavp, MSG_BRW_LAST_CHILD, invalidavp ) ); } else { //add multiple AVPs in Failed-AVP } return 0; } static int diameap_parse_eap_resp(struct eap_state_machine * eap_sm, struct eap_packet *eappacket) { TRACE_ENTRY("%p %p",eap_sm, eappacket) eap_sm->rxResp = FALSE; eap_sm->respId = -1; eap_sm->respMethod = TYPE_NONE; eap_sm->respVendor = VENDOR_IETF; eap_sm->respVendorMethod = TYPE_NONE; if (eappacket->data == NULL) { TRACE_DEBUG(INFO,"%s Empty EAP packet",DIAMEAP_EXTENSION); return 0; } u16 plength; CHECK_FCT(diameap_eap_get_packetlength(eappacket,&plength)); if ((int) plength < EAP_HEADER) { TRACE_DEBUG(INFO,"%s EAP packet length less than EAP header.",DIAMEAP_EXTENSION); return 0; } u16 length; CHECK_FCT(diameap_eap_get_length(eappacket,&length)); if ((int) length < EAP_HEADER) { TRACE_DEBUG(INFO,"%sEAP packet length field less than EAP header.",DIAMEAP_EXTENSION); return 0; } if (plength < length) { TRACE_DEBUG(INFO,"%sLength of received EAP packet is less than the value of the length field.",DIAMEAP_EXTENSION); return 0; } eap_code code; CHECK_FCT(diameap_eap_get_code(eappacket,&code)); if (code == EAP_REQUEST || code == EAP_SUCCESS || code == EAP_FAILURE) { TRACE_DEBUG(INFO,"%sOnly EAP Responses are accepted at EAP server side.",DIAMEAP_EXTENSION); return 0; } u8 id; CHECK_FCT(diameap_eap_get_identifier(eappacket,&id)); eap_sm->respId = id; CHECK_FCT(diameap_eap_get_type(eappacket,&eap_sm->respMethod)); if ((eap_sm->methodState != EAP_M_PROPOSED) && (eap_sm->respMethod == TYPE_NAK || eap_sm->respMethod == TYPE_EXPANDED_TYPES)) { TRACE_DEBUG(INFO,"%sNAK or EXPANDED_NAK received after an EAP TYPE been selected",DIAMEAP_EXTENSION); return 0; } if ((eap_sm->respMethod == TYPE_EXPANDED_TYPES) && (length < 20)) { TRACE_DEBUG(INFO,"%s Truncated EAP Packet received.",DIAMEAP_EXTENSION); return 0; } if ((eap_sm->respMethod == TYPE_NAK) && (eap_sm->currentMethod < 4)) { TRACE_DEBUG(INFO,"%sNAK response not expected at this step (Only EAP type = 4 and above are accepted).",DIAMEAP_EXTENSION); return 0; } if (eap_sm->respMethod == TYPE_EXPANDED_TYPES) { u8 *data = (u8 *) eappacket->data; //int len = 0; //u32 respVendor, respVendorMethod; data += 5; eap_sm->respVendor = G24BIGE(data); data += 3; eap_sm->respVendorMethod = G32BIGE(data); data += 4; /* while ((length - 12) > (len * 8)) { if (((eap_type) G8(data)) != TYPE_EXPANDED_TYPES) { return FALSE; } data += 1; respVendor = G24BIGE(data); data += 3; respVendorMethod = G32BIGE(data); eap_sm->user.proposedmethods[len].method = respVendor; eap_sm->user.proposedmethods[len].vendor = respVendorMethod; len++; data += 4; } eap_sm->user.methodId = 0;*/ } if((eap_sm->respMethod == TYPE_IDENTITY) && (length < 6)){ TRACE_DEBUG(INFO,"%sUser Identity missing",DIAMEAP_EXTENSION); return 0; } eap_sm->rxResp = TRUE; return 0; } static int diameap_eappacket_new(struct eap_packet * eappacket, struct avp_hdr * avpdata) { TRACE_ENTRY("%p %p",eappacket,avpdata); eappacket->ulength = (u16) avpdata->avp_value->os.len; eappacket->data = (u8 *) avpdata->avp_value->os.data; diameap_eap_get_packetlength(eappacket, &eappacket->length); return 0; } static int diameap_parse_avps(struct diameap_state_machine * diameap_sm, struct msg * req, struct diameap_eap_interface * eap_i) { TRACE_ENTRY("%p %p %p",diameap_sm,req,eap_i); struct avp * avp, *avp2; struct avp_hdr * avpdata; int ret; int depth; /* EAP-Payload data*/ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); CHECK_FCT(diameap_eappacket_new(&eap_i->aaaEapRespData, avpdata)); eap_i->aaaEapResp = TRUE; u16 length; diameap_eap_get_length(&eap_i->aaaEapRespData, &length); if (length >= 4) { eap_code code; CHECK_FCT(diameap_eap_get_code(&eap_i->aaaEapRespData,&code)); if (code != EAP_RESPONSE) { diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */ struct avp * invalidavp; union avp_value val; CHECK_FCT( fd_msg_avp_new ( dataobj_eap_payload, 0, &invalidavp)); val.os.data = eap_i->aaaEapRespData.data; val.os.len = eap_i->aaaEapRespData.length; CHECK_FCT( fd_msg_avp_setvalue( invalidavp, &val )) CHECK_FCT( diameap_failed_avp(diameap_sm, invalidavp)); TRACE_DEBUG(INFO,"%sIncorrect EAP Packet. EAP Code != Response.",DIAMEAP_EXTENSION); return 0; } else { CHECK_FCT(diameap_parse_eap_resp(&diameap_sm->eap_sm, &eap_i->aaaEapRespData)); if (diameap_sm->eap_sm.rxResp == FALSE) { diameap_sm->result_code = 1001; /*DIAMETER_MULTI_ROUND_AUTH*/ eap_i->aaaEapNoReq = TRUE; eap_i->aaaEapResp = FALSE; } } } else { if (diameap_sm->eap_sm.currentMethod != TYPE_NONE) { diameap_sm->result_code = 5004; /* DIAMETER_INVALID_AVP_VALUE 5004 */ CHECK_FCT(diameap_failed_avp(diameap_sm, avp)); TRACE_DEBUG(INFO,"%sEAP packet length < Minimum EAP packet length.",DIAMEAP_EXTENSION); return 1; } //EAP start received } } /* User-Name AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_user_name, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "User-Name"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* EAP-Key-Name AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_key_name, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "EAP-Key-Name"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Auth-Request-Type AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_request_type, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); diameap_sm->auth_request_val = avpdata->avp_value->i32; } /* Authorization-Lifetime AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_authorization_lifetime, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Authorization-Lifetime"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Auth-Grace-Period AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_grace_period, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Auth-Grace-Period"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Auth-Session-State AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_auth_session_state, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Auth-Session-State"; attribute->value.i32 = avpdata->avp_value->i32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Origin-state-Id AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_origin_state_id, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Origin-state-Id AVP"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* NAS-Port AVP*/ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-Port"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* NAS-Port-Id AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_id, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-Port-Id"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* NAS-Port-Type AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_port_type, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-Port-Type"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Called-Station-Id AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_called_station_id, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Called-Station-Id"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Calling-Station-Id AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_calling_station_id, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Calling-Station-Id"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Connect-Info AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_connect_info, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Connect-Info"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Originating-Line-Info AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_originating_line_info, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Originating-Line-Info"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Service-Type AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_service_type, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Service-Type"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Callback-Number AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_callback_number, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Callback-Number"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Port-Limit AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_port_limit, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Port-Limit"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-Protocol AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_protocol, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-Protocol"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-MTU AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_mtu, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-MTU"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-Compression AVP */ avp = NULL; avp2 = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_compression, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); u32 Pi_Code = avpdata->avp_code; int depth; do { struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-Compression"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); ret = 0; depth = 0; ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth); if (avp2 != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata)); } avp = avp2; } while ((avp2 != NULL) && (ret == 0) && (ret == 0) && (avpdata->avp_code == Pi_Code)); } /* Framed-IP-Address AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_address, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-IP-Address"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-IP-Netmask AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ip_netmask, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-IP-Netmask"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-Interface-Id AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_interface_id, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-Interface-Id"; attribute->value.u64 = avpdata->avp_value->u64; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* Framed-IPv6-Prefix AVP */ avp = NULL; avp2 = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_framed_ipv6_prefix, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); u32 Pi_Code = avpdata->avp_code; do { struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Framed-IPv6-Prefix"; attribute->value.u32 = avpdata->avp_value->u32; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); ret = 0; depth = 0; ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth); if (avp2 != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata)); } avp = avp2; } while ((avp2 != NULL) && (ret == 0) && (ret == 0) && (avpdata->avp_code == Pi_Code)); } /* Tunneling AVP */ avp = NULL; avp2 = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_tunneling, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); u32 Pi_Code = avpdata->avp_code; int depth; do { struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "Tunneling"; //grouped AVP fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); ret = 0; depth = 0; ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth); if (avp2 != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp2, &avpdata)); } avp = avp2; } while ((avp2 != NULL) && (ret == 0) && (ret == 0) && (avpdata->avp_code == Pi_Code)); } /* NAS-Identifier AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_identifier, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-Identifier"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* NAS-IP-Address AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ip_address, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-IP-Address"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* NAS-IPv6-Address AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_nas_ipv6_address, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "NAS-IPv6-Address"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } /* State AVP */ avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_state, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata)); struct avp_attribute * attribute; CHECK_MALLOC(attribute = malloc(sizeof(struct avp_attribute))); memset(attribute, 0, sizeof(struct avp_attribute)); fd_list_init(&attribute->chain, attribute); attribute->attrib = "State"; attribute->value.os.data = avpdata->avp_value->os.data; attribute->value.os.len = avpdata->avp_value->os.len; fd_list_insert_before(&diameap_sm->req_attributes, &attribute->chain); } return 0; } static int diameap_sess_data_new( struct sess_state *diameap_sess_data, struct diameap_state_machine *diameap_sm) { if (!diameap_sm) return EINVAL; int i; diameap_sess_data->invalid_eappackets = diameap_sm->invalid_eappackets; diameap_sess_data->user.id = diameap_sm->eap_sm.user.id; if ((diameap_sm->eap_sm.user.userid != NULL) && (diameap_sm->eap_sm.user.useridLength > 0)) { diameap_sess_data->user.useridLength = diameap_sm->eap_sm.user.useridLength; CHECK_MALLOC(diameap_sess_data->user.userid= malloc(diameap_sess_data->user.useridLength+1)); U8COPY(diameap_sess_data->user.userid,0,diameap_sess_data->user.useridLength+1,diameap_sm->eap_sm.user.userid); free(diameap_sm->eap_sm.user.userid); diameap_sm->eap_sm.user.userid = NULL; } else { diameap_sess_data->user.useridLength = 0; diameap_sess_data->user.userid = NULL; } if ((diameap_sm->eap_sm.user.password != NULL) && (diameap_sm->eap_sm.user.passwordLength > 0)) { diameap_sess_data->user.passwordLength = diameap_sm->eap_sm.user.passwordLength; CHECK_MALLOC(diameap_sess_data->user.password = malloc(diameap_sess_data->user.passwordLength+1)); U8COPY(diameap_sess_data->user.password,0,diameap_sess_data->user.passwordLength+1,diameap_sm->eap_sm.user.password); free(diameap_sm->eap_sm.user.password); diameap_sm->eap_sm.user.password = NULL; } else { diameap_sess_data->user.passwordLength = 0; diameap_sess_data->user.password = NULL; } diameap_sess_data->user.methodId = diameap_sm->eap_sm.user.methodId; for (i = 0; i < MAXMETHODS; i++) { diameap_sess_data->user.methods[i].method = diameap_sm->eap_sm.user.methods[i].method; diameap_sess_data->user.methods[i].vendor = diameap_sm->eap_sm.user.methods[i].vendor; } for (i = 0; i < MAXPROPOSEDMETHODS; i++) { diameap_sess_data->user.proposedmethods[i].method = diameap_sm->eap_sm.user.proposedmethods[i].method; diameap_sess_data->user.proposedmethods[i].vendor = diameap_sm->eap_sm.user.proposedmethods[i].vendor; } diameap_sess_data->user.pmethods = diameap_sm->eap_sm.user.pmethods; diameap_sess_data->user.proposed_eap_method = diameap_sm->eap_sm.user.proposed_eap_method; diameap_sess_data->user.proposed_eap_method_vendor = diameap_sm->eap_sm.user.proposed_eap_method_vendor; diameap_sess_data->user.success = diameap_sm->eap_sm.user.success; diameap_sess_data->currentId = diameap_sm->eap_sm.currentId; diameap_sess_data->currentMethod = diameap_sm->eap_sm.currentMethod; diameap_sess_data->currentVendor = diameap_sm->eap_sm.currentVendor; diameap_sess_data->lastId = diameap_sm->eap_sm.lastId; diameap_sess_data->methodState = diameap_sm->eap_sm.methodState; diameap_sess_data->methodData = diameap_sm->eap_sm.methodData; diameap_sm->eap_sm.methodData = NULL; return 0; } static void free_attrib(struct auth_attribute * auth_attrib) { if (auth_attrib == NULL) { return; } if (auth_attrib->attrib != NULL) { free(auth_attrib->attrib); auth_attrib->attrib = NULL; } if (auth_attrib->op != NULL) { free(auth_attrib->op); auth_attrib->op = NULL; } if (auth_attrib->value != NULL) { free(auth_attrib->value); auth_attrib->value = NULL; } free(auth_attrib); auth_attrib = NULL; } static void free_avp_attrib(struct avp_attribute * avp_attrib) { if(avp_attrib){ free(avp_attrib); avp_attrib = NULL; } } static void free_ans_attrib(struct avp_attribute * ans_attrib) { if(ans_attrib){ if (ans_attrib->tofree == 1) { if(ans_attrib->value.os.data){ free(ans_attrib->value.os.data); ans_attrib->value.os.data = NULL; } } free(ans_attrib); ans_attrib = NULL; } } static int diameap_unlink_attributes_lists( struct diameap_state_machine * diameap_sm) { TRACE_ENTRY("%p ", diameap_sm); if (diameap_sm == NULL) { return EINVAL; } while (!FD_IS_LIST_EMPTY(&diameap_sm->attributes)) { struct fd_list * item = (struct fd_list *) diameap_sm->attributes.next; struct auth_attribute * auth = (struct auth_attribute *) item; fd_list_unlink(item); free_attrib(auth); } while (!FD_IS_LIST_EMPTY(&diameap_sm->req_attributes)) { struct fd_list * item = (struct fd_list *) diameap_sm->req_attributes.next; struct avp_attribute * avp = (struct avp_attribute *) item; fd_list_unlink(item); free_avp_attrib(avp); } while (!FD_IS_LIST_EMPTY(&diameap_sm->ans_attributes)) { struct fd_list * item = (struct fd_list *) diameap_sm->ans_attributes.next; struct avp_attribute * avp_ans = (struct avp_attribute *) item; fd_list_unlink(item); free_ans_attrib(avp_ans); } return 0; } static void diameap_free(struct diameap_state_machine * diameap_sm) { if (diameap_sm != NULL) { if (diameap_sm->eap_sm.user.userid != NULL) { free(diameap_sm->eap_sm.user.userid); diameap_sm->eap_sm.user.userid = NULL; } if (diameap_sm->eap_sm.user.password != NULL) { free(diameap_sm->eap_sm.user.password); diameap_sm->eap_sm.user.password = NULL; } diameap_sm->eap_sm.selectedMethod = NULL; if (diameap_sm->eap_sm.methodData != NULL) { struct plugin * cplugin; if (diameap_plugin_get(diameap_sm->eap_sm.currentVendor, diameap_sm->eap_sm.currentMethod, &cplugin)) { TRACE_DEBUG(INFO,"%sUnable to access EAP Method plugin {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,diameap_sm->eap_sm.currentMethod,diameap_sm->eap_sm.currentVendor); } if (cplugin->eap_method_free) { (*cplugin->eap_method_free)(diameap_sm->eap_sm.methodData); diameap_sm->eap_sm.methodData = NULL; } else { TRACE_DEBUG(INFO,"%s[%s plugin] datafree function not available.",DIAMEAP_EXTENSION,cplugin->methodname); if (diameap_sm->eap_sm.methodData != NULL) { free(diameap_sm->eap_sm.methodData); diameap_sm->eap_sm.methodData = NULL; } } if (diameap_sm->eap_sm.methodData) { TRACE_DEBUG(INFO,"%sSession state was not been freed correctly!!!",DIAMEAP_EXTENSION); } } if (diameap_sm->failedavp != NULL) { CHECK_FCT_DO(fd_msg_free(diameap_sm->failedavp), ); } if (diameap_sm->lastReqEAPavp != NULL) { CHECK_FCT_DO(fd_msg_free(diameap_sm->lastReqEAPavp), ); } CHECK_FCT_DO(diameap_unlink_attributes_lists(diameap_sm), ); free(diameap_sm); diameap_sm = NULL; } } static int diameap_get_avp_attribute(struct fd_list * avp_attributes, char * attribute, struct avp_attribute ** avp_attrib, int unlink, int *ret) { TRACE_ENTRY("%p %p %p %d %p", avp_attributes, attribute, avp_attrib, unlink, ret); if (avp_attributes == NULL) { return EINVAL; } if (attribute == NULL) { return EINVAL; } struct fd_list * attrib; for (attrib = avp_attributes->next; attrib != avp_attributes; attrib = attrib->next) { *avp_attrib = (struct avp_attribute *) attrib; if (strcmp((*avp_attrib)->attrib, attribute) == 0) { *ret = 0; if (unlink == 1) { fd_list_unlink(&(*avp_attrib)->chain); } return 0; } } *avp_attrib = NULL; *ret = 1; return 0; } static int diameap_get_auth_attribute(struct fd_list * auth_attributes, char * attribute, struct auth_attribute ** auth_attrib, int unlink, int *ret) { TRACE_ENTRY("%p %p %p %d %p", auth_attributes, attribute, auth_attrib, unlink, ret); if (auth_attributes == NULL) { return EINVAL; } if (attribute == NULL) { return EINVAL; } struct fd_list * attrib; for (attrib = auth_attributes->next; attrib != auth_attributes; attrib = attrib->next) { *auth_attrib = (struct auth_attribute *) attrib; if (strcmp((*auth_attrib)->attrib, attribute) == 0) { *ret = 0; if (unlink == 1) { fd_list_unlink(&(*auth_attrib)->chain); } return 0; } } *auth_attrib = NULL; *ret = 1; return 0; } static int diameap_get_ans_attribute(struct fd_list * ans_attributes, char * attribute, struct avp_attribute ** ans_attrib, int unlink, int *ret) { TRACE_ENTRY("%p %p %p %d %p", ans_attributes, attribute, ans_attrib, unlink, ret); if (ans_attributes == NULL) { return EINVAL; } if (attribute == NULL) { return EINVAL; } struct fd_list * attrib; for (attrib = ans_attributes->next; attrib != ans_attributes; attrib = attrib->next) { *ans_attrib = (struct avp_attribute *) attrib; if (strcmp((*ans_attrib)->attrib, attribute) == 0) { *ret = 0; if (unlink == 1) { fd_list_unlink(&(*ans_attrib)->chain); } return 0; } } *ans_attrib = NULL; *ret = 1; return 0; } static int diameap_answer_avp_attributes( struct diameap_state_machine * diameap_sm) { TRACE_ENTRY("%p",diameap_sm); if (diameap_sm == NULL) { return EINVAL; } int ret1, ret2; struct avp_attribute * avp_attrib; struct avp_attribute * ans_attrib; struct auth_attribute * auth_attrib; /* Authorization-Lifetime */ { CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Authorization-Lifetime", &avp_attrib,1, &ret1)); CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Authorization-Lifetime", &auth_attrib,1, &ret2)); if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Authorization-Lifetime"; ans_attrib->value.u32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Authorization-Lifetime"; ans_attrib->value.u32 = avp_attrib->value.u32; fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_avp_attrib(avp_attrib); } if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Authorization-Lifetime"; if (avp_attrib->value.u32 < atoi(auth_attrib->value)) { ans_attrib->value.u32 = avp_attrib->value.u32; } else { ans_attrib->value.u32 = atoi(auth_attrib->value); } fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_avp_attrib(avp_attrib); free_attrib(auth_attrib); } } /* Auth-Grace-Period */ { CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes, "Auth-Grace-Period", &avp_attrib,1, &ret1)); CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Grace-Period", &auth_attrib,1, &ret2)); if ((ret1 == 1) && (ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Auth-Grace-Period"; ans_attrib->value.u32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } if ((ret1 == 0) && (ret2 == 1) && (avp_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Auth-Grace-Period"; ans_attrib->value.u32 = avp_attrib->value.u32; fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_avp_attrib(avp_attrib); } if ((ret1 == 0) && (ret2 == 0) && (auth_attrib != NULL) && (avp_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Auth-Grace-Period"; if (avp_attrib->value.u32 < atoi(auth_attrib->value)) { ans_attrib->value.u32 = avp_attrib->value.u32; } else { ans_attrib->value.u32 = atoi(auth_attrib->value); } fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); free_avp_attrib(avp_attrib); } } /* Auth-Session-State */ { CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Auth-Session-State", &auth_attrib,1, &ret2)); if ((ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Auth-Session-State"; ans_attrib->value.i32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } } /* Re-Auth-Request-Type */ { CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Re-Auth-Request-Type", &auth_attrib,1, &ret2)); if ((ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Re-Auth-Request-Type"; ans_attrib->value.i32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } else { ans_attrib = NULL; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes, "Authorization-Lifetime", &ans_attrib,0, &ret1)); if ((ret1 == 0) && (ans_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Re-Auth-Request-Type"; ans_attrib->value.i32 = 0; fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); } } } /* Session-Timeout */ { CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Session-Timeout", &auth_attrib,1, &ret2)); if ((ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Session-Timeout"; ans_attrib->value.u32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } } /* Multi-Round-Time-Out */ { CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Multi-Round-Time-Out", &auth_attrib,1, &ret2)); if ((ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Multi-Round-Time-Out"; ans_attrib->value.u32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } } /* Acct-Interim-Interval */ { CHECK_FCT(diameap_get_auth_attribute(&diameap_sm->attributes, "Acct-Interim-Interval", &auth_attrib,1, &ret2)); if ((ret2 == 0) && (auth_attrib != NULL)) { CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = "Acct-Interim-Interval"; ans_attrib->value.u32 = atoi(auth_attrib->value); fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); free_attrib(auth_attrib); } } return 0; } #define DIAMEAP_STR 1 #define DIAMEAP_NUM 2 #define DIAMEAP_OP_NO 0 //Not supported operator #define DIAMEAP_OP_EQ 1 //== #define DIAMEAP_OP_GT 2 //> #define DIAMEAP_OP_LT 3 //< #define DIAMEAP_OP_GE 4 //>= #define DIAMEAP_OP_LE 5 //<= #define DIAMEAP_OP_NE 6 //!= #define DIAMEAP_OP_EX 7 //~= #define EQ(A,B) A==B ? TRUE : FALSE #define GT(A,B) A>B ? TRUE : FALSE #define GE(A,B) A>=B ? TRUE : FALSE #define LT(A,B) A<B ? TRUE : FALSE #define LE(A,B) A<=B ? TRUE : FALSE #define NE(A,B) A!=B ? TRUE : FALSE int diameap_get_operator(char *operator) { TRACE_ENTRY("%p",operator); if (strcmp(operator, "==") == 0) { return DIAMEAP_OP_EQ; } if (strcmp(operator, ">") == 0) { return DIAMEAP_OP_GT; } if (strcmp(operator, "<") == 0) { return DIAMEAP_OP_LT; } if (strcmp(operator, ">=") == 0) { return DIAMEAP_OP_GE; } if (strcmp(operator, "<=") == 0) { return DIAMEAP_OP_LE; } if (strcmp(operator, "!=") == 0) { return DIAMEAP_OP_NE; } if (strcmp(operator, "~=") == 0) { return DIAMEAP_OP_EX; } return DIAMEAP_OP_NO; } boolean is_operator(int format_type, char * operator) { TRACE_ENTRY("%d %p",format_type,operator); if ((format_type == DIAMEAP_STR) && (strcmp(operator, "==") == 0 || strcmp( operator, "~=") == 0 || strcmp(operator, "!=") == 0)) { return TRUE; } if ((format_type == DIAMEAP_NUM) && (strcmp(operator, "~=") != 0)) { return TRUE; } return FALSE; } union avp_value diameap_get_num(char * num, enum dict_avp_basetype datatype) { TRACE_ENTRY("%p %d",num,datatype); union avp_value val; switch (datatype) { case AVP_TYPE_INTEGER32://i32 val.i32 = atoi(num); break; case AVP_TYPE_INTEGER64://i64 val.i64 = atoll(num); break; case AVP_TYPE_UNSIGNED32://u32 val.u32 = strtoul(num, NULL, 10); break; case AVP_TYPE_UNSIGNED64://u64 val.u64 = strtoull(num, NULL, 10); break; case AVP_TYPE_FLOAT32://f32 val.f32 = atof(num); break; case AVP_TYPE_FLOAT64://f64 val.f64 = strtod(num, NULL); break; default: TRACE_DEBUG(INFO, "%sUnknown AVP Base Type.",DIAMEAP_EXTENSION) ; } return val; } boolean diameap_check(union avp_value *A, char * B, char * operator, enum dict_avp_basetype datatype) { TRACE_ENTRY("%p %p %p %d",A,B,operator,datatype); if (((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR, operator) == TRUE)) || ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE))) { switch (diameap_get_operator(operator)) { case DIAMEAP_OP_EQ: if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR, operator) == TRUE)) { if (strcmp((char *)A->os.data, B) == 0) return TRUE; else return FALSE; } else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return EQ(A->i32,diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return EQ(A->i64,diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return EQ(A->u32,diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return EQ(A->u64,diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return EQ(A->f32,diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return EQ(A->f64,diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; case DIAMEAP_OP_EX: { //string only boolean authorized = FALSE; if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR, operator) == TRUE)) { regex_t rule_regexp; regcomp(&rule_regexp, B, REG_EXTENDED | REG_NOSUB | REG_ICASE); if (regexec(&rule_regexp, (char *)A->os.data, 0, NULL, 0) != 0) { authorized = FALSE; } else { authorized = TRUE; } regfree(&rule_regexp); } return authorized; } case DIAMEAP_OP_GT: if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return GT(A->i32, diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return GT(A->i64, diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return GT(A->u32, diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return GT(A->u64, diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return GT(A->f32, diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return GT(A->f64, diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; case DIAMEAP_OP_GE: if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return GE(A->i32,diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return GE(A->i64,diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return GE(A->u32,diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return GE(A->u64,diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return GE(A->f32,diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return GE(A->f64,diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; case DIAMEAP_OP_LT: if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return LT(A->i32, diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return LT(A->i64, diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return LT(A->u32, diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return LT(A->u64, diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return LT(A->f32, diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return LT(A->f64, diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; case DIAMEAP_OP_LE: if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return LE(A->i32, diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return LE(A->i64, diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return LE(A->u32, diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return LE(A->u64, diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return LE(A->f32, diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return LE(A->f64, diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; case DIAMEAP_OP_NE: if ((datatype == AVP_TYPE_OCTETSTRING) && (is_operator(DIAMEAP_STR, operator) == TRUE)) { if (strcmp((char *)A->os.data, B) != 0) return TRUE; else return FALSE; } else if ((datatype != AVP_TYPE_OCTETSTRING) && (datatype != AVP_TYPE_GROUPED) && (is_operator(DIAMEAP_NUM, operator) == TRUE)) { switch (datatype) { case AVP_TYPE_INTEGER32://i32 return NE(A->i32, diameap_get_num(B, datatype).i32); break; case AVP_TYPE_INTEGER64://i64 return NE(A->i64, diameap_get_num(B, datatype).i64); break; case AVP_TYPE_UNSIGNED32://u32 return NE(A->u32, diameap_get_num(B, datatype).u32); break; case AVP_TYPE_UNSIGNED64://u64 return NE(A->u64, diameap_get_num(B, datatype).u64); break; case AVP_TYPE_FLOAT32://f32 return NE(A->f32, diameap_get_num(B, datatype).f32); break; case AVP_TYPE_FLOAT64://f64 return NE(A->f64, diameap_get_num(B, datatype).f64); break; default: return FALSE; } } else { return FALSE; } break; } } return FALSE; } char * diameap_attribute_operator(char * op, int * toadd, boolean *isrule) { TRACE_ENTRY("%p %p %p",op,toadd,isrule); char * attribute_op; if (op[0] == '+') { *toadd = 1; } else if (op[strlen(op) - 1] == '+') { *toadd = 2; } else { *toadd = 0; } switch (*toadd) { case 1: attribute_op = malloc(strlen(op)); memset(attribute_op, 0, strlen(op)); strncpy(attribute_op, op + 1, strlen(op) - 1); attribute_op[strlen(op)] = '\0'; break; case 2: attribute_op = malloc(strlen(op)); memset(attribute_op, 0, strlen(op)); strncpy(attribute_op, op, strlen(op) - 1); attribute_op[strlen(op)] = '\0'; break; default: attribute_op = malloc(strlen(op) + 1); memset(attribute_op, 0, strlen(op) + 1); strcpy(attribute_op, op); attribute_op[strlen(op) + 1] = '\0'; } if (strcmp(attribute_op, "=") == 0) { *isrule = FALSE; *toadd = 2; } else { *isrule = TRUE; } return attribute_op; } int diameap_answer_set_attribute_valueA(union avp_value *A, int *tofree, enum dict_avp_basetype datatype, union avp_value * rval) { TRACE_ENTRY("%p %p %d %p",A,tofree,datatype,rval); if (datatype == AVP_TYPE_OCTETSTRING) { CHECK_MALLOC(rval->os.data=malloc(A->os.len)); memcpy(rval->os.data,A->os.data,A->os.len); rval->os.len = A->os.len; *tofree = 1; } else { *rval = *A; } return 0; } int diameap_answer_set_attribute_valueB(char * B, int *tofree, enum dict_avp_basetype datatype, union avp_value * rval) { TRACE_ENTRY("%p %p %d %p",B,tofree,datatype,rval); if (datatype == AVP_TYPE_OCTETSTRING) { CHECK_MALLOC(rval->os.data=malloc(strlen(B))); memcpy(rval->os.data,B,strlen(B)); rval->os.len = strlen(B); *tofree = 1; } else { *rval = diameap_get_num(B, datatype); } return 0; } static int diameap_attribute_limits(char * attrib, int * max, int *ret) { TRACE_ENTRY("%p %p %p",attrib,max,ret); if (attrib == NULL) { return EINVAL; } int i; for (i = 0; i < sizeof(auth_avps); i++) { if (strcmp(auth_avps[i].avp_attribute, attrib) == 0) { *max = auth_avps[i].max; *ret = 0; return 0; } } *max = 0; *ret = 1; return 0; } static int diameap_answer_authorization_attributes( struct diameap_state_machine * diameap_sm) { TRACE_ENTRY("%p",diameap_sm); if (diameap_sm == NULL) { return EINVAL; } boolean checked = TRUE; struct fd_list * attrib; struct auth_attribute * auth_attrib; struct avp_attribute * avp_attrib; int ret; for (attrib = (&diameap_sm->attributes)->next; attrib != (&diameap_sm->attributes); attrib = attrib->next) { avp_attrib = NULL; auth_attrib = (struct auth_attribute *) attrib; int toadd = 0; boolean isrule = FALSE; char * op; op = diameap_attribute_operator(auth_attrib->op, &toadd, &isrule); struct dict_object * dobj; struct dict_avp_data avpdata; fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, auth_attrib->attrib, &dobj, ENOENT); fd_dict_getval(dobj, &avpdata); checked = TRUE; if (isrule == TRUE) { CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,auth_attrib->attrib,&avp_attrib,0,&ret)); if (ret == 0) { checked = diameap_check(&avp_attrib->value, auth_attrib->value, op, avpdata.avp_basetype); } } if (checked == TRUE && toadd != 0) { struct avp_attribute * ans_attrib; int max = 0; diameap_attribute_limits(auth_attrib->attrib, &max, &ret); if ((ret == 0) && (max != 0)) { if (max == 1)//only one { int ret = 0; diameap_get_ans_attribute(&diameap_sm->ans_attributes, auth_attrib->attrib, &ans_attrib, 0, &ret); if (ret == 1) { ans_attrib = NULL; CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = strdup(auth_attrib->attrib); if (toadd == 1) { diameap_answer_set_attribute_valueA( &avp_attrib->value, &ans_attrib->tofree, avpdata.avp_basetype, &ans_attrib->value); } else { diameap_answer_set_attribute_valueB( auth_attrib->value, &ans_attrib->tofree, avpdata.avp_basetype, &ans_attrib->value); } fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); } else { //an answer avp is already added } } else { ans_attrib = NULL; CHECK_MALLOC(ans_attrib = malloc(sizeof(struct avp_attribute))); memset(ans_attrib, 0, sizeof(struct avp_attribute)); fd_list_init(&ans_attrib->chain, NULL); ans_attrib->attrib = auth_attrib->attrib; if (toadd == 1) { diameap_answer_set_attribute_valueA(&avp_attrib->value, &ans_attrib->tofree, avpdata.avp_basetype, &ans_attrib->value); } else { diameap_answer_set_attribute_valueB(auth_attrib->value, &ans_attrib->tofree, avpdata.avp_basetype, &ans_attrib->value); } fd_list_insert_before(&diameap_sm->ans_attributes, &ans_attrib->chain); } } } if (checked == FALSE) { diameap_sm->authorized = FALSE; return 0; } } diameap_sm->authorized = checked; return 0; return 0; } static int diameap_policy_decision(struct diameap_state_machine * diameap_sm, struct diameap_eap_interface *eap_i) { TRACE_ENTRY("%p %p",diameap_sm,eap_i); if ((eap_i->aaaFail == TRUE) && (eap_i->aaaSuccess == TRUE)) { TRACE_DEBUG(INFO,"%s Incorrect EAP decision. EAP process should not return both success and failure for the same session.(please report this problem.)",DIAMEAP_EXTENSION); return -1; } if (eap_i->aaaFail == TRUE) { diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */ diameap_sm->authFailure = TRUE; TRACE_DEBUG(FULL+1,"%s Auth failure: Authentication Rejected ",DIAMEAP_EXTENSION); return 0; } if (eap_i->aaaSuccess == FALSE) { diameap_sm->result_code = 1001; /* DIAMETER_MULTI_ROUND_AUTH 1001 */ return 0; } if (eap_i->aaaSuccess == TRUE) { if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE) { if ((diameap_sm->verify_authorization == TRUE) && (diameap_sm->result_code == 0)) { diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */ diameap_sm->authSuccess = TRUE; TRACE_DEBUG(FULL+1,"%s Auth success: Authorization and Authentication ",DIAMEAP_EXTENSION); return 0; } else { // } } if (diameap_sm->auth_request_val == AUTHENTICATE_ONLY) { diameap_sm->result_code = 2001; /* DIAMETER_SUCCESS 2001 */ diameap_sm->authSuccess = TRUE; TRACE_DEBUG(FULL+1,"%s Auth success: Authentication Only ",DIAMEAP_EXTENSION); return 0; } } return 0; } static int diameap_add_avps(struct diameap_state_machine * diameap_sm, struct msg * ans, struct msg * req) { TRACE_ENTRY("%p %p %p",diameap_sm,ans,req); struct avp * avp, *avp2; struct avp_hdr * avpdata; union avp_value avp_val; int ret = 0; /* Origin-Host AVP and Origin-Realm AVP */ { CHECK_FCT( fd_msg_add_origin ( ans, 0 ) ); } /* Auth-Application-Id AVP */ { CHECK_FCT(fd_msg_avp_new(dataobj_auth_application_id, 0, &avp)); avp_val.u32 = diameap_config->application_id; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp)); } /* Auth-Request-Type AVP * Enumerated values: * AUTHENTICATE_ONLY 1 * AUTHORIZE_ONLY 2 * AUTHORIZE_AUTHENTICATE 3 */ { CHECK_FCT(fd_msg_avp_new(dataobj_auth_request_type, 0, &avp)); if (!diameap_config->authorize) { //AUTHENTICATE ONLY avp_val.i32 = AUTHENTICATE_ONLY; } else { if (diameap_sm->auth_request_val == 3) { //AUTHORIZE_AUTHENTICATE avp_val.i32 = AUTHORIZE_AUTHENTICATE; } else { //AUTHENTICATE_ONLY avp_val.i32 = AUTHENTICATE_ONLY; } } CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp)); } /* Proxy-Info AVP */ CHECK_FCT(fd_msg_search_avp(req, dataobj_proxy_info, &avp)); if (avp != NULL) { CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) ); u32 proxy_info_code = avpdata->avp_code; int depth; do { ret = 0; depth = 0; CHECK_FCT(fd_msg_avp_hdr ( avp, &avpdata ) ); if (avpdata->avp_code == proxy_info_code) { CHECK_FCT(fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp)); } ret = fd_msg_browse ( avp, MSG_BRW_NEXT, &avp2, &depth); avp = avp2; } while ((avp != NULL) && (ret == 0) && (ret == 0)); } if (diameap_sm->eap_sm.user.userid) { /* User-Name AVP */ { CHECK_FCT(fd_msg_avp_new(dataobj_user_name, 0, &avp)); if (diameap_sm->privateUser == FALSE) { avp_val.os.data = diameap_sm->eap_sm.user.userid; avp_val.os.len = diameap_sm->eap_sm.user.useridLength; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); } else { } } } return 0; } static int diameap_add_user_sessions_avps( struct diameap_state_machine * diameap_sm, struct msg * ans) { TRACE_ENTRY("%p %p",diameap_sm,ans); struct avp * avp; union avp_value avp_val; int ret; /* Authorization-Lifetime AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Authorization-Lifetime",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_authorization_lifetime, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Auth-Grace-Period AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Grace-Period",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_auth_grace_period, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Auth-Session-State AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Auth-Session-State",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_auth_session_state, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Re-Auth-Request-Type AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Re-Auth-Request-Type",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_re_auth_request_type, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Session-Timeout AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Session-Timeout",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_session_timeout, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Acct-Interim-Interval AVP */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Acct-Interim-Interval",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_acct_interim_interval, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } return 0; } static int diameap_add_authorization_avps( struct diameap_state_machine * diameap_sm, struct msg * ans) { TRACE_ENTRY("%p %p",diameap_sm, ans); struct avp * avp; union avp_value avp_val; int ret; if (diameap_sm == NULL) { return EINVAL; } if (ans == NULL) { return EINVAL; } /* Reply-Message */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_reply_message, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Reply-Message",&ans_attrib,1,&ret)); } } /* Service-Type */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Service-Type",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_service_type, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Callback-Number */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Number",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_callback_number, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Callback-Id */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Callback-Id",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_callback_id, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Idle-Timeout */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Idle-Timeout",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_idle_timeout, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* NAS-Filter-Rule */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Filter-Rule",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_nas_filter_rule, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Filter-Id */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_filter_id, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Filter-Id",&ans_attrib,1,&ret)); } } /* Configuration-Token */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_configuration_token, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Configuration-Token",&ans_attrib,1,&ret)); } } /* QoS-Filter-Rule */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_qos_filter_rule, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"QoS-Filter-Rule",&ans_attrib,1,&ret)); } } /* Framed-Protocol */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Protocol",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_protocol, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-Routing */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Routing",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_routing, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-MTU */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_mtu, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-Compression */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_compression, 0, &avp)); avp_val.i32 = ans_attrib->value.i32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Compression",&ans_attrib,1,&ret)); } } /* Framed-IP-Address */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Address",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_address, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-IP-Netmask */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IP-Netmask",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ip_netmask, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-Route */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_route, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Route",&ans_attrib,1,&ret)); } } /* Framed-Pool */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Pool",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_pool, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-Interface-Id */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-Interface-Id",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_interface_id, 0, &avp)); avp_val.u64 = ans_attrib->value.u64; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-IPv6-Prefix */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_prefix, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Prefix",&ans_attrib,1,&ret)); } } /* Framed-IPv6-Route */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_route, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Route",&ans_attrib,1,&ret)); } } /* Framed-IPv6-Pool */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPv6-Pool",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipv6_pool, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-IPX-Network */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-IPX-Network",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_ipx_network, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-AppleTalk-Link */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Link",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_link, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Framed-AppleTalk-Network */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret)); while ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_network, 0, &avp)); avp_val.u32 = ans_attrib->value.u32; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Network",&ans_attrib,1,&ret)); } } /* Framed-AppleTalk-Zone */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-AppleTalk-Zone",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { CHECK_FCT(fd_msg_avp_new(dataobj_framed_appletalk_zone, 0, &avp)); avp_val.os.data = ans_attrib->value.os.data; avp_val.os.len = ans_attrib->value.os.len; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_ans_attrib(ans_attrib); } } /* Tunneling */ // /* State */ // return 0; } static int diameap_add_result_code(struct diameap_state_machine * diameap_sm, struct msg * ans, struct session * sess) { TRACE_ENTRY("%p %p",diameap_sm,ans); struct avp * avp; union avp_value avp_val; int ret; /* Result-Code AVP */ CHECK_FCT(fd_msg_avp_new(dataobj_result_code, 0, &avp)); avp_val.u32 = diameap_sm->result_code; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); /* Add Result-Code AVP to the message */ CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); /* Multi_Round_Time_Out AVP */ if (diameap_sm->result_code == 1001) { struct timespec sess_timeout; CHECK_FCT(fd_msg_avp_new(dataobj_multi_round_time_out, 0, &avp)); struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Multi-Round-Time-Out",&ans_attrib,1,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { avp_val.u32 = ans_attrib->value.u32; /* Update the session timeout with multi-round-time-out value */ CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout)); sess_timeout.tv_sec += diameap_config->multi_round_time_out; CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout)); free_ans_attrib(ans_attrib); } else { avp_val.u32 = diameap_config->multi_round_time_out; /* Update the session timeout with multi-round-time-out value */ CHECK_SYS(clock_gettime(CLOCK_REALTIME,&sess_timeout)); sess_timeout.tv_sec += diameap_config->multi_round_time_out; CHECK_FCT(fd_sess_settimeout(sess, &sess_timeout)); } CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); } return 0; } static int diameap_add_eap_payload(struct diameap_state_machine * diameap_sm, struct msg * ans, struct diameap_eap_interface *eap_i) { TRACE_ENTRY("%p %p",diameap_sm,ans); struct avp * avp; union avp_value avp_val; int ret; u32 Framed_MTU = 1500; //1500 default value u32 NAS_Port_Type_HeaderLength = 4; int EAP_Max_Length = 0; /* get Framed-MTU AVP value */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"Framed-MTU",&ans_attrib,0,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { Framed_MTU = ans_attrib->value.u32; } } /* get NAS-Port-Type AVP value */ { struct avp_attribute * ans_attrib; CHECK_FCT(diameap_get_ans_attribute(&diameap_sm->ans_attributes,"NAS-Port-Type",&ans_attrib,0,&ret)); if ((ret == 0) && (ans_attrib != NULL)) { // = ans_attrib->value.i32; } } //TD take the link type into consideration when calculating EAP_MAX_Length EAP_Max_Length = Framed_MTU - NAS_Port_Type_HeaderLength; if (eap_i->aaaEapReqData.length <= EAP_Max_Length) { /* EAP-Payload AVP */ { CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &avp)); avp_val.os.data = eap_i->aaaEapReqData.data; avp_val.os.len = eap_i->aaaEapReqData.length; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); if (diameap_sm->lastReqEAPavp != NULL) { fd_msg_free(diameap_sm->lastReqEAPavp); diameap_sm->lastReqEAPavp = NULL; } CHECK_FCT(fd_msg_avp_new(dataobj_eap_payload, 0, &diameap_sm->lastReqEAPavp)); avp_val.os.data = eap_i->aaaEapReqData.data; avp_val.os.len = eap_i->aaaEapReqData.length; CHECK_FCT(fd_msg_avp_setvalue(diameap_sm->lastReqEAPavp, &avp_val)); } } else { //if EAP Packet length > EAP_Max_Length } return 0; } static int diameap_send(struct msg ** rmsg) { TRACE_ENTRY("%p",rmsg); CHECK_FCT( fd_msg_send( rmsg, NULL, NULL)); return 0; } static int diameap_add_eap_success_avps( struct diameap_state_machine * diameap_sm, struct msg * ans, struct diameap_eap_interface *eap_i) { TRACE_ENTRY("%p %p %p",diameap_sm,ans,eap_i); struct avp * avp; union avp_value avp_val; int ret; /* EAP-Master-Session-Key AVP */ if (eap_i->aaaEapKeyAvailable == TRUE) { CHECK_FCT(fd_msg_avp_new(dataobj_eap_master_session_key, 0, &avp)); avp_val.os.data = eap_i->aaaEapMSKData; avp_val.os.len = eap_i->aaaEapMSKLength; CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); } /* EAP-Key-Name AVP */ struct avp_attribute * avp_attrib = NULL; CHECK_FCT(diameap_get_avp_attribute(&diameap_sm->req_attributes,"EAP-Key-Name",&avp_attrib,1,&ret)) if ((avp_attrib != NULL) && (ret != 1)) { if (avp_attrib->value.os.len == 0) { CHECK_FCT(fd_msg_avp_new(dataobj_eap_key_name, 0, &avp)); avp_val.os.data = NULL;// avp_val.os.len = 0;// CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); free_avp_attrib(avp_attrib); } } return 0; } int diameap_authorize(struct diameap_state_machine * diameap_sm) { TRACE_ENTRY("%p",diameap_sm); CHECK_FCT(diameap_authorization_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes)); diameap_sm->authorized = TRUE; CHECK_FCT_DO(diameap_answer_authorization_attributes(diameap_sm), ); if (diameap_sm->authorized == FALSE) { diameap_sm->result_code = 4001; /* DIAMETER_AUTHENTICATION_REJECTED 4001 */ } return 0; } static int diameap_add_accounting_eap_auth_method( struct diameap_state_machine * diameap_sm, struct msg * ans) { TRACE_ENTRY("%p %p",diameap_sm,ans); int i = 0; struct avp * avp; union avp_value avp_val; /* Accounting-EAP-Auth-Method AVP */ while (i < diameap_sm->eap_sm.user.methodId) { CHECK_FCT(fd_msg_avp_new(dataobj_accounting_eap_auth_method, 0, &avp)); avp_val.u64 = (u64) (((diameap_sm->eap_sm.user.methods[i].vendor) * pow((double) 2, (double) 32)) + diameap_sm->eap_sm.user.methods[i].method); CHECK_FCT(fd_msg_avp_setvalue(avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) ); i++; } return 0; } static int diameap_add_eap_reissued_payload(struct msg * ans, struct msg * req) { TRACE_ENTRY("%p %p", ans, req); struct avp * avp, *re_avp; union avp_value avp_val; struct avp_hdr * avphdr; if ((ans == NULL) || (req == NULL)) { return EINVAL; } avp = NULL; CHECK_FCT(fd_msg_search_avp(req, dataobj_eap_payload, &avp)); if (avp != NULL) { CHECK_FCT( fd_msg_avp_hdr(avp, &avphdr)); CHECK_FCT( fd_msg_avp_new(dataobj_eap_reissued_payload, 0, &re_avp)); CHECK_MALLOC(avp_val.os.data=malloc(avphdr->avp_value->os.len)); memcpy(avp_val.os.data,avphdr->avp_value->os.data,avphdr->avp_value->os.len); avp_val.os.len = avphdr->avp_value->os.len; CHECK_FCT(fd_msg_avp_setvalue(re_avp, &avp_val)); CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, re_avp ) ); } else { TRACE_DEBUG(INFO,"%sUnable to find EAP-Payload AVP in received Diameter-EAP-Request.",DIAMEAP_EXTENSION); return 1; } return 0; } static int diameap_server_callback(struct msg ** rmsg, struct avp * ravp, struct session * sess, void * opaque, enum disp_action * action) { TRACE_ENTRY("%p %p %p %p", rmsg, ravp, sess, action); struct sess_state * diameap_sess_data = NULL; struct diameap_state_machine * diameap_sm = NULL; struct diameap_eap_interface eap_i; struct msg *req, *ans; boolean non_fatal_error = FALSE; if (rmsg == NULL) return EINVAL; req = *rmsg; CHECK_FCT_DO(fd_sess_state_retrieve(diameap_server_reg, sess, &diameap_sess_data), { TRACE_DEBUG(INFO,"%s retrieving session state failed.",DIAMEAP_EXTENSION); goto s_end;}); CHECK_MALLOC_DO(diameap_sm = malloc(sizeof(struct diameap_state_machine)), goto s_end); memset(diameap_sm, 0, sizeof(struct diameap_state_machine)); if (diameap_sess_data) { diameap_sm->state = DIAMEAP_RECEIVED; diameap_sm->eap_sm.eap_state = EAP_IDLE; } else { diameap_sm->state = DIAMEAP_DISABLED; diameap_sm->eap_sm.eap_state = EAP_INITIALIZE; } while (diameap_sm->state != DIAMEAP_IDLE && diameap_sm->state != DIAMEAP_END) { switch (diameap_sm->state) { case DIAMEAP_DISABLED: if (rmsg) { diameap_sm->state = DIAMEAP_INITIALIZE; } else { TRACE_DEBUG(INFO,"%sReceived empty Diameter EAP Request message.",DIAMEAP_EXTENSION); goto s_end; } break; case DIAMEAP_INITIALIZE: CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data), { TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;}) ; CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i), { TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION)) ; if ((diameap_sm->result_code != 0)) { diameap_sm->state = DIAMEAP_SEND_ERROR_MSG; } else { diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY; } break; case DIAMEAP_RECEIVED: CHECK_FCT_DO(diameap_initialize_diameap_sm(diameap_sm,diameap_sess_data), { TRACE_DEBUG(INFO,"%s Initializing DiamEAP state machine failed.",DIAMEAP_EXTENSION); goto s_end;}) ; CHECK_FCT_DO(diameap_initialize_diameap_eap_interface(&eap_i), { TRACE_DEBUG(INFO,"%s Initializing DiamEAP-EAP Interface failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sParsing AVPs",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(diameap_parse_avps(diameap_sm, req, &eap_i), TRACE_DEBUG(INFO,"%s Unable to parse Diameter-EAP-Request AVPs.",DIAMEAP_EXTENSION)) ; if (diameap_sm->result_code != 0) { diameap_sm->state = DIAMEAP_SEND_ERROR_MSG; } else { diameap_sm->state = DIAMEAP_AUTHENTICATION_VERIFY; } break; case DIAMEAP_AUTHENTICATION_VERIFY: { TRACE_DEBUG(FULL+1,"%sVerify authentication",DIAMEAP_EXTENSION); CHECK_FCT_DO(diameap_eap_statemachine(&diameap_sm->eap_sm, &eap_i,&non_fatal_error), { TRACE_DEBUG(INFO,"%s EAP process failed.",DIAMEAP_EXTENSION); goto s_end;}); if (non_fatal_error == TRUE) { TRACE_DEBUG(FULL+1,"%sAuthentication verify finished with a non-fatal-error.",DIAMEAP_EXTENSION); diameap_sm->state = DIAMEAP_SEND_ERROR_MSG; } else { diameap_sm->state = DIAMEAP_SELECT_DECISION; } } break; case DIAMEAP_SELECT_DECISION: CHECK_FCT_DO( diameap_policy_decision(diameap_sm,&eap_i), goto s_end) ; if ((eap_i.aaaSuccess == TRUE) && (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE) && (diameap_sm->verify_authorization == FALSE)) { diameap_sm->state = DIAMEAP_AUTHORIZATION_VERIFY; } else { diameap_sm->state = DIAMEAP_DIAMETER_EAP_ANSWER; } break; case DIAMEAP_AUTHORIZATION_VERIFY: diameap_sm->verify_authorization = TRUE; TRACE_DEBUG(FULL+1,"%sVerify authorization",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(diameap_authorize(diameap_sm), { TRACE_DEBUG(INFO,"%s Authorization check process failed.",DIAMEAP_EXTENSION); goto s_end;}) ; diameap_sm->state = DIAMEAP_SELECT_DECISION; break; case DIAMEAP_DIAMETER_EAP_ANSWER: TRACE_DEBUG(FULL+1,"%screate Diameter EAP Answer",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0), goto s_end) ; ans = *rmsg; TRACE_DEBUG(FULL+1,"%sAdding AVPs to Diameter EAP Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req), { TRACE_DEBUG(INFO,"%s Unable to add AVPs to Diameter-EAP-Answer message.",DIAMEAP_EXTENSION);goto s_end;}) ; if (diameap_sm->authFailure == FALSE) { if (diameap_sm->eap_sm.user.id != 0) { TRACE_DEBUG(FULL+1,"%sSelect authentication attributes.",DIAMEAP_EXTENSION); CHECK_FCT_DO(diameap_authentication_get_attribs(&diameap_sm->eap_sm.user, &diameap_sm->attributes), { TRACE_DEBUG(INFO,"%s Unable to get user's session attributes.",DIAMEAP_EXTENSION); goto s_end;}); TRACE_DEBUG(FULL+1,"%sCreate answer authentication attributes.",DIAMEAP_EXTENSION); CHECK_FCT_DO(diameap_answer_avp_attributes(diameap_sm), { TRACE_DEBUG(INFO,"%s Unable to generate answer attributes.",DIAMEAP_EXTENSION); goto s_end;}); } if (diameap_sm->authSuccess == FALSE) { diameap_sm->state = DIAMEAP_SEND_REQUEST; } else { diameap_sm->state = DIAMEAP_SEND_SUCCESS; } } else { diameap_sm->state = DIAMEAP_SEND_FAILURE; } break; case DIAMEAP_SEND_REQUEST: TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i), { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sStoring DiamEAP session data.",DIAMEAP_EXTENSION) ; CHECK_MALLOC(diameap_sess_data = malloc(sizeof(struct sess_state))) ; memset(diameap_sess_data, 0, sizeof(struct sess_state)); diameap_sess_data_new(diameap_sess_data, diameap_sm); CHECK_FCT_DO(fd_sess_state_store(diameap_server_reg, sess, &diameap_sess_data), { TRACE_DEBUG(INFO,"%s Storing session state failed.",DIAMEAP_EXTENSION); goto s_end;}) ; CHECK_FCT_DO( diameap_send(rmsg), goto s_end) ; diameap_sm->state = DIAMEAP_IDLE; break; case DIAMEAP_SEND_FAILURE: TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i), { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; LOG_N("%s Auth FAIL: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid); CHECK_FCT_DO( diameap_send(rmsg), goto s_end) ; diameap_sm->state = DIAMEAP_END; break; case DIAMEAP_SEND_SUCCESS: TRACE_DEBUG(FULL+1,"%sAdding User session AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(diameap_add_user_sessions_avps(diameap_sm,ans), { TRACE_DEBUG(INFO,"%s Adding user's session AVPs failed.",DIAMEAP_EXTENSION); goto s_end;}) ; if (diameap_sm->auth_request_val == AUTHORIZE_AUTHENTICATE) { TRACE_DEBUG(FULL+1,"%sAdding Authorization AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION); CHECK_FCT_DO(diameap_add_authorization_avps(diameap_sm,ans), { TRACE_DEBUG(INFO,"%s Adding Authorization AVPs failed.",DIAMEAP_EXTENSION); goto s_end;}); } TRACE_DEBUG(FULL+1,"%sAdding Result Code AVP to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), { TRACE_DEBUG(INFO,"%s Adding Result-Code AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sAdding EAP-Payload to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_eap_payload(diameap_sm, ans,&eap_i), { TRACE_DEBUG(INFO,"%s Adding EAP-Payload AVP failed.",DIAMEAP_EXTENSION); goto s_end;}) ; TRACE_DEBUG(FULL+1,"%sAdding EAP success AVPs AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO( diameap_add_eap_success_avps(diameap_sm, ans, &eap_i), goto s_end) ; TRACE_DEBUG(FULL+1,"%sAdding Accounting-EAP-Auth-Method AVPs to Diameter-EAP-Answer.",DIAMEAP_EXTENSION) ; CHECK_FCT_DO(diameap_add_accounting_eap_auth_method(diameap_sm, ans), { TRACE_DEBUG(INFO,"%s Adding accounting AVP failed",DIAMEAP_EXTENSION); goto s_end;}) ; LOG_N("%s Auth Success: %.*s",DIAMEAP_EXTENSION, diameap_sm->eap_sm.user.useridLength, diameap_sm->eap_sm.user.userid); CHECK_FCT_DO( diameap_send(rmsg), goto s_end) ; diameap_sm->state = DIAMEAP_END; break; case DIAMEAP_SEND_ERROR_MSG: diameap_sm->invalid_eappackets++; if (diameap_sm->invalid_eappackets == diameap_config->max_invalid_eap_packet) { diameap_sm->result_code = 4001;//DIAMETER_AUTHENTICATION_REJECTED TRACE_DEBUG(FULL,"%s Maximum permitted invalid EAP Packet reached. Diameter Authentication Rejected.",DIAMEAP_EXTENSION); } CHECK_FCT_DO(fd_msg_new_answer_from_req(fd_g_config->cnf_dict, rmsg, 0), goto s_end) ; ans = *rmsg; CHECK_FCT_DO( diameap_add_avps(diameap_sm, ans,req), { TRACE_DEBUG(INFO,"%s Adding AVPs to Diameter-EAP-Answer message failed.",DIAMEAP_EXTENSION);goto s_end;}) ; if ((non_fatal_error == TRUE) && (diameap_sm->result_code == 0)) { diameap_sm->result_code = 1001; } if (diameap_sm->result_code == 1001) { CHECK_FCT_DO( diameap_add_eap_reissued_payload(ans,req), goto s_end); } if (diameap_sm->result_code == 5004) { CHECK_FCT_DO( fd_msg_avp_add( ans , MSG_BRW_LAST_CHILD, diameap_sm->failedavp ),goto s_end ); } CHECK_FCT_DO( diameap_add_result_code(diameap_sm, ans, sess), goto s_end) ; CHECK_FCT_DO( diameap_send(rmsg), goto s_end) ; diameap_sm->state = DIAMEAP_IDLE; break; case DIAMEAP_END: break; case DIAMEAP_IDLE: break; } } diameap_free(diameap_sm); s_end: return 0; } int diameap_start_server(void) { struct disp_when when; /*create handler for sessions */ CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL, NULL)); /* Register the callback */ memset(&when, 0, sizeof(when)); when.command = dataobj_diameap_cmd; when.app = dataobj_diameap_app; /* Register the callback for EAP Application */ CHECK_FCT(fd_disp_register(diameap_server_callback, DISP_HOW_CC, &when, NULL, &handle)); if (handle == NULL) { TRACE_DEBUG(INFO, "%sCannot register the callback !!!",DIAMEAP_EXTENSION); return 1; } return 0; } int diameap_stop_server(void) { CHECK_FCT(fd_sess_handler_destroy(&diameap_server_reg, NULL)); CHECK_FCT(fd_disp_unregister(&handle, NULL)); return 0; }