| /***************************************************************************************************** |
| * 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; |
| } |