Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/CMakeLists.txt b/extensions/app_diameap/CMakeLists.txt
new file mode 100644
index 0000000..f463022
--- /dev/null
+++ b/extensions/app_diameap/CMakeLists.txt
@@ -0,0 +1,56 @@
+# The Diameter EAP Application extension
+PROJECT("Diameter EAP Application extension" C)
+
+# Find MySQL
+FIND_PACKAGE(MySQL REQUIRED)
+FIND_PACKAGE(Gcrypt REQUIRED)
+INCLUDE_DIRECTORIES(${MySQL_INCLUDE_DIR})
+
+# Parse plugins
+ADD_SUBDIRECTORY(plugins)
+
+# Parser
+BISON_FILE(diameap.y)
+FLEX_FILE(diameap.l)
+SET_SOURCE_FILES_PROPERTIES(lex.diameap.c diameap.tab.c PROPERTIES COMPILE_FLAGS "-I \"${CMAKE_CURRENT_SOURCE_DIR}\"")
+
+
+set( diameapsrc
+ diameap_defs.h
+ diameap.h
+ diameap_server.h
+ diameap_plugins.h
+ diameap_eap.h
+ plugins.h
+ diameap_eappacket.h
+ diameap_user.h
+ diameap.tab.h
+ diameap.tab.c
+ lex.diameap.c
+ diameap.c
+ diameap_server.c
+ diameap_plugins.c
+ diameap_init.c
+ diameap_common.h
+ diameap_eappacket.c
+ libdiameap.h
+ diameap_eap.c
+ diameap_mysql.h
+ diameap_mysql.c
+ diameap_tls.h
+ diameap_tls.c
+ libcrypt.h
+ libcrypt.c
+ diameap_user.c
+)
+
+FD_ADD_EXTENSION(app_diameap ${diameapsrc})
+
+TARGET_LINK_LIBRARIES(app_diameap ${GCRYPT_LIBRARY} ${GNUTLS_LIBRARIES} ${MySQL_LIBRARY} )
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_diameap
+ LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+ COMPONENT freeDiameter-eap-server)
diff --git a/extensions/app_diameap/LICENSE b/extensions/app_diameap/LICENSE
new file mode 100644
index 0000000..cfe48d2
--- /dev/null
+++ b/extensions/app_diameap/LICENSE
@@ -0,0 +1,35 @@
+ 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.
+
diff --git a/extensions/app_diameap/README b/extensions/app_diameap/README
new file mode 100644
index 0000000..fad85bd
--- /dev/null
+++ b/extensions/app_diameap/README
@@ -0,0 +1,119 @@
+DiamEAP (http://diameap.yagami.freediameter.net/)
+
+Copyright (c) 2009-2010 Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project.
+
+Author: Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+
+
+
+----- SUMMARY -----
+
+DiamEAP is an implementation of the Diameter Extensible Authentication Protocol (EAP) Application (RFC 4072).
+The Diameter protocol is a AAA protocol to securely carry Authentication, Authorization and Accounting informations between the AAA client and the AAA server.
+Diameter EAP Application is a Diameter application that supports authentication using Extensible Authentication Protocol (RFC 3748).
+
+DiamEAP is designed to be extensible so that any new EAP method can be implemented separately as a shared library called 'EAP method plug-in'.
+Currently, DiamEAP comprises two EAP Methods plug-ins:
+ - EAP MD5 plug-in : implementation of EAP-MD5 authentication method.
+ - EAP TLS plug-in : implementation of EAP-TLS authentication method .
+
+Other EAP methods are scheduled to be added in future releases.
+
+DiamEAP is an extension for freeDiameter. Visit http://www.freediameter.net/ for more information on freeDiameter project.
+
+For more information on DiamEAP project, visit http://diameap.yagami.freediameter.net/
+
+
+
+----- REQUIREMENTS -----
+
+Some packages are required to compile DiamEAP from source.
+
+If you will install DiamEAP on Debian or Ubuntu system install the following packages: cmake flex bison libgnutls-dev libgcrypt-dev libmysqlclient-dev
+
+ $ sudo apt-get install cmake flex bison libgnutls-dev libgcrypt-dev libmysqlclient-dev
+
+
+
+----- INSTALLATION -----
+
+1- Add DiamEAP extension to freeDiameter.
+ See freeDiameter documentation (http://www.freediameter.net/)
+
+2-Create a new MySQL database and add tables using the sql script 'diameap.sql'.
+
+3- Edit the extensions/CMakeList.txt file to add DiamEAP to freeDiameter.
+
+Add the following lines:
+
+ OPTION(BUILD_APP_DIAMEAP "Build DiamEAP? (Diameter EAP Application - RFC 4072)" OFF)
+ IF (BUILD_APP_DIAMEAP)
+ ADD_SUBDIRECTORY(app_diameap)
+ ENDIF (BUILD_APP_DIAMEAP)
+
+Note: you can enable DiamEAP to be built with freeDiameter by setting the BUILD_APP_DIAMEAP to ON. If you enable it here you don't need to enable it when building freeDiameter.
+
+4- Enable DiamEAP by enabling BUILD_APP_DIAMEAP option with CMake:
+
+cmake -DBUILD_APP_DIAMEAP:BOOl=ON ../
+
+
+
+----- CONFIGURATION -----
+
+DiamEAP requires a configuration file to start the DiamEAP server.
+It is advised to start by a copy of the sample file, and customize the configuration to fit your needs.
+A sample configuration file 'diameap.conf.sample' can be find in extensions/app_diameap/ or in doc/ folder of freeDiameter.
+The file 'diameap.conf.sample' contains a description of all parameters that can be added to the DiamEAP configuration file.
+
+*Specify connection parameters to DiamEAP MySQL database:
+- username and password to connect to the MySQL Server
+- database server : address to MySQL server.
+- database name : database for DiamEAP.
+
+Example:
+
+DiamEAP_MySQL = "UserName" , "MyPassword" , "localhost" , "drupal_ui";
+
+
+*Add EAP Method plug-ins to be loaded with DiamEAP server. Note that EAP Identity must be add.
+
+Example:
+
+Load_plugin = "EAP MD5":4:0:"extensions/eap_md5.emp":"";
+Load_plugin = "EAP TLS":13:0:"extensions/eap_tls.emp":"doc/eap_tls_plugin.app_diameap.conf";
+
+
+* Enable Authorization with DiamEAP.
+
+You can enable DiamEAP to check authorization of authenticated users. To enable authorization set authorization to 1. ( by default disabled).
+
+
+* Multiple round trips timeout
+
+This parameter indicates the maximum number of seconds provides the user to answer to a Diameter-EAP-Request. (by default set to 30 seconds)
+
+
+* Invalid EAP Packets
+
+This parameter defines the maximum number of invalid EAP packets that can be received before rejecting the connection. (by default set to 5 packets)
+
+
+For more documentation on configuring DiamEAP, visit the documentation page of the project : http://diameap.yagami.freediameter.net/documentation
+
+
+
+----- COPYRIGHT -----
+
+See LICENSE file for legal information on this software.
+
+
+
+----- CONTACT -----
+
+Author: Souheil Ben Ayed (souheil@tera.ics.keio.ac.jp)
+
+
+Current maintainers:
+-Souheil Ben Ayed (Teraoka Laboratory of Keio University)
+ souheil@tera.ics.keio.ac.jp
diff --git a/extensions/app_diameap/diameap.c b/extensions/app_diameap/diameap.c
new file mode 100644
index 0000000..ac399cb
--- /dev/null
+++ b/extensions/app_diameap/diameap.c
@@ -0,0 +1,87 @@
+/*****************************************************************************************************
+ * 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"
+
+
+
+/* DiamEAP Configuration */
+static struct diameap_conf conf;
+struct diameap_conf * diameap_config = &conf;
+
+/* The entry point */
+static int diameap_main(char * conffile)
+{
+ TRACE_ENTRY("%p", conffile);
+
+ memset(diameap_config, 0, sizeof(struct diameap_conf));
+
+ /* Initialize configuration */
+ CHECK_FCT(diameap_init(conffile));
+
+ /* Start Diameter EAP Application (Back-end Authenticator ) */
+ CHECK_FCT(diameap_start_server());
+
+ /* Announce the support of Diameter EAP Application to other peers */
+ CHECK_FCT(fd_disp_app_support(dataobj_diameap_app, dataobj_diameap_ven, 1, 0));
+
+ LOG_D("%sDiameter EAP Application Extension started successfully.",DIAMEAP_EXTENSION);
+
+ return 0;
+}
+
+void fd_ext_fini(void)
+{
+ TRACE_DEBUG(FULL,"%sStopping the server",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_stop_server(),
+ { TRACE_DEBUG(INFO,"%sStopping the server: Error occurred.",DIAMEAP_EXTENSION);});
+
+ if (db_conn)
+ {
+ TRACE_DEBUG(FULL,"%sDisconnecting from MySQL Server",DIAMEAP_EXTENSION);
+ diameap_mysql_disconnect();
+ }
+
+ TRACE_DEBUG(FULL,"%sUnloading EAP Methods plug-ins: Error occurred.",DIAMEAP_EXTENSION);
+ CHECK_FCT_DO(diameap_plugin_unload(),
+ { TRACE_DEBUG(INFO,"%sUnloading EAP Methods plug-ins: Error occurred.",DIAMEAP_EXTENSION);});
+ return;
+}
+
+/* Define the entry point */
+EXTENSION_ENTRY("DiamEAP", diameap_main, "dict_eap")
+;
diff --git a/extensions/app_diameap/diameap.h b/extensions/app_diameap/diameap.h
new file mode 100644
index 0000000..b55b280
--- /dev/null
+++ b/extensions/app_diameap/diameap.h
@@ -0,0 +1,80 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_H_
+#define DIAMEAP_H_
+
+/* Structure to hold configuration of DiamEAP*/
+struct diameap_conf
+{
+ char *conffile; /* configuration file of the extension*/
+
+ int authorize; /* Set to 1 if provides Authorization. Otherwise set to 0. (by default set to 0)*/
+
+ u32 vendor_id; /* Vendor ID*/
+ u32 application_id; /* Diameter EAP Application ID. Value set to 5. */
+ u32 command_code; /* Diameter EAP Application Command Code. Value set to 268. */
+
+ char * diam_realm; /* Diameter realm of the peer */
+
+ /*Diameter EAP Server*/
+ int max_invalid_eap_packet;
+
+ //MySQL Database parameters
+
+ struct {
+ char *server;
+ char *user;
+ char *password;
+ char *database;
+ }db;
+
+ u32 multi_round_time_out;
+};
+
+/* The pointer to access DiamEAP configuration*/
+extern struct diameap_conf *diameap_config;
+
+/* Initialize the configuration of DiamEAP*/
+int diameap_init(char * conffile);
+
+/* parser */
+int diameapparse(struct diameap_conf * config);
+
+
+#endif /* DIAMEAP_H_ */
diff --git a/extensions/app_diameap/diameap.l b/extensions/app_diameap/diameap.l
new file mode 100644
index 0000000..1dcb470
--- /dev/null
+++ b/extensions/app_diameap/diameap.l
@@ -0,0 +1,128 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+
+/*Declarations and option settings*/
+%{
+#include <stdio.h>
+#include "diameap_common.h"
+#include "diameap.tab.h"
+
+#define YY_USER_ACTION { \
+ yylloc->first_line = yylloc->last_line = yylineno; \
+ yylloc->first_column = yylloc->last_column + 1; \
+ yylloc->last_column += yyleng +1; \
+ }
+
+#define YY_NO_INPUT
+%}
+
+
+
+%option noyywrap
+%option yylineno
+%option bison-bridge
+%option bison-locations
+%option nounput
+
+%%
+ /* List of patterns and actions */
+
+<*>\n {
+ yylloc->last_column=0;
+ }
+
+<*>#.*$ { }
+
+[ \t\n]+ {
+ yylloc->last_column=0;
+ /* ignore whitespace */
+ }
+
+\"([^\n\"]*)\" {
+ yylval->str = strdup(yytext+1); /* Quoted String */
+ yylval->str[yyleng-2]='\0';
+ return iSTRING;
+ }
+
+
+[[:digit:]]+ { /* Digital number */
+ yylval->val = atoi(yytext);
+ return NUM; /* Numeric value */
+ }
+
+(?i:"Load_Plugin") {
+ return EAPMETHOD;
+ }
+
+(?i:"Authorization") {
+ return AUTHORIZE;
+ }
+
+(?i:"DiamEAP_MySQL") {
+ return DIAMEAP_MYSQL;
+ }
+
+(?i:"MAX_Invalid_EAP_Packets") {
+ return MAX_INVALID_EAP_PACKET;
+ }
+
+(?i:"Multi_Round_Time_Out") {
+ return MULTI_ROUND_TIMEOUT;
+ }
+
+(?i:"Check_user_identity") {
+ return CHECK_USER_IDENTITY;
+ }
+
+"="|";"|":"|"," {
+ return yytext[0];
+ }
+
+ /* Unrecognized token or text */
+
+<*>[[:alnum:]]+ |
+<*>. {
+ fprintf(stderr,"Unrecognized input text '%s'( on line %i column %i )\n", yytext, yylloc->first_line, yylloc->first_column);
+ return LEX_ERROR;
+ }
+
+%%
+/* Routines */
+
+
diff --git a/extensions/app_diameap/diameap.sql b/extensions/app_diameap/diameap.sql
new file mode 100644
index 0000000..3d0a362
--- /dev/null
+++ b/extensions/app_diameap/diameap.sql
@@ -0,0 +1,82 @@
+#########################################################################
+# diameap.sql #
+# DiamEAP extension #
+# Users Information Database schema #
+# #
+# #
+# #
+# MySQL command to load the script: #
+# mysql> mysql -u username -p password diameap_ui < diameap.sql #
+# #
+#########################################################################
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `authe`
+--
+
+CREATE TABLE IF NOT EXISTS `authe` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `grp` int(11) NOT NULL,
+ `attribute` set('Authorization-Lifetime','Auth-Grace-Period','Auth-Session-State','Re-Auth-Request-Type','Session-Timeout','Multi-Round-Time-Out','Acct-Interim-Interval') NOT NULL DEFAULT 'Authorization-Lifetime',
+ `value` char(255) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `authz`
+--
+
+CREATE TABLE IF NOT EXISTS `authz` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `grp` int(11) NOT NULL,
+ `attribute` set('NAS-IPv6-Address','NAS-Identifier','NAS-IP-Address','NAS-Port','NAS-Port-Id','NAS-Port-Type','Called-Station-Id','Calling-Station-Id','Connect-Info','Originating-Line-Info','Service-Type','Callback-Number','Callback-Id','Idle-Timeout','Port-Limit','NAS-Filter-Rule','Filter-Id','Configuration-Token','QoS-Filter-Rule','Framed-Protocol','Framed-Routing','Framed-MTU','Framed-Compression','Framed-IP-Address','Framed-IP-Netmask','Framed-Route','Framed-Pool','Framed-Interface-Id','Framed-IPv6-Prefix','Framed-IPv6-Pool','Framed-IPv6-Route','Framed-IPX-Network','Framed-Appletalk-Link','Framed-Appletalk-Network','Framed-Appletalk-Zone') NOT NULL DEFAULT 'Service-Type',
+ `op` set('==','>','>=','<','<=','!=','~=','=+','+==','+>','+>=','+<','+<=','+!=','+~=','==+','>+','>=+','<+','<=+','!=+') NOT NULL DEFAULT '==',
+ `value` char(255) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `grp`
+--
+
+CREATE TABLE IF NOT EXISTS `grp` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `grp_name` char(255) NOT NULL,
+ `active` set('Y','N') NOT NULL DEFAULT 'Y',
+ PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `users`
+--
+
+CREATE TABLE IF NOT EXISTS `users` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `username` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
+ `eapmethod` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `vendor` int(11) NOT NULL DEFAULT '0',
+ `password` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
+ `active` enum('Y','N') CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'Y',
+ PRIMARY KEY (`id`)
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `user_grp`
+--
+
+CREATE TABLE IF NOT EXISTS `user_grp` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `user` int(11) NOT NULL,
+ `grp` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+);
diff --git a/extensions/app_diameap/diameap.y b/extensions/app_diameap/diameap.y
new file mode 100644
index 0000000..543d404
--- /dev/null
+++ b/extensions/app_diameap/diameap.y
@@ -0,0 +1,194 @@
+/*****************************************************************************************************
+ * 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 <stdio.h>
+#include "diameap_common.h"
+#include "diameap.tab.h"
+
+void yyerror (YYLTYPE *llocp, struct diameap_conf * config, const char *s);
+
+extern int yywrap();
+extern int yylex();
+
+
+/* The Lex parser prototype */
+int diameaplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+
+%}
+
+%locations
+%parse-param {struct diameap_conf * config}
+%pure_parser
+/*%defines */
+%error-verbose
+%debug
+
+%union {
+ char *str;
+ int val;
+ char byte;
+}
+
+
+
+/* In case of error in the lexical analysis */
+%token LEX_ERROR
+
+%token <val> NUM
+
+%token <str> iSTRING
+
+%token <byte> iBYTE
+
+%token EAPMETHOD
+%token AUTHORIZE
+%token MODE
+%token DIAMEAP_MYSQL
+%token MAX_INVALID_EAP_PACKET
+%token MULTI_ROUND_TIMEOUT
+%token CHECK_USER_IDENTITY
+
+%%
+
+confparams : /* empty */
+ | confparams EAPmethod
+ | confparams Authorize
+ | confparams DiamEAP_MySQL
+ | confparams MAX_Invalid_EAP_Packet
+ | confparams Multi_Round_Timeout
+ | confparams Check_User_Identity
+ | confparams errors
+ {
+ yyerror(&yylloc, config, "Unrecognized configuration parameter.");
+ return EINVAL;
+ }
+ ;
+
+errors : LEX_ERROR
+ | error
+ ;
+
+
+EAPmethod : EAPMETHOD '=' iSTRING ':' NUM ':' NUM ':' iSTRING ':' iSTRING ';'
+ {
+ char * infile, *cfile;
+ FILE * fl;
+
+ infile = $9;
+ fl = fopen(infile, "r");
+ if ((fl == NULL) && (*infile != '/')) {
+ char * tmpfile=infile;
+ CHECK_MALLOC_DO( infile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(infile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+ free(tmpfile);
+ fl = fopen(infile, "r");
+ }
+ if (fl == NULL) {
+ int ret = errno;
+ TRACE_DEBUG(INFO, "Unable to open %s plugin file %s for reading: %s", $3, infile, strerror(ret));
+ yyerror (&yylloc, config, "Error adding EAP Plugin");
+ YYERROR;
+ }
+ fclose(fl);
+
+ cfile = $11;
+
+ if(strlen(cfile)>0){
+ fl = fopen(cfile, "r");
+ if ((fl == NULL) && (*cfile != '/')) {
+ char * tmp = cfile;
+ CHECK_MALLOC_DO( cfile = malloc( strlen(tmp) + strlen(DEFAULT_CONF_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(cfile, DEFAULT_CONF_PATH "/%s", tmp);
+ free(tmp);
+ fl = fopen(cfile, "r");
+ }
+ if (fl == NULL) {
+
+ }
+ if(fl)
+ fclose(fl);
+ }
+
+ diameap_plugin_add($3,(char)$5,(char)$7,infile,cfile);
+ }
+ ;
+
+Authorize : AUTHORIZE '=' NUM ';'
+ {
+ if((int)$3)
+ config->authorize=1;
+ }
+ ;
+
+
+DiamEAP_MySQL : DIAMEAP_MYSQL '=' iSTRING ',' iSTRING ',' iSTRING ',' iSTRING ';'
+ {
+ diameap_set_mysql_param($3,$5,$7,$9);
+ }
+ ;
+
+MAX_Invalid_EAP_Packet : MAX_INVALID_EAP_PACKET '=' NUM ';'
+ {
+ config->max_invalid_eap_packet=(int)$3;
+ };
+
+Multi_Round_Timeout : MULTI_ROUND_TIMEOUT '=' NUM ';'
+ {
+ config->multi_round_time_out=(unsigned int)$3;
+ };
+
+Check_User_Identity: CHECK_USER_IDENTITY '=' NUM ';'
+ {
+ if((int)$3){
+ check_user_identity = TRUE;
+ }else{
+ check_user_identity = FALSE;
+ }
+ };
+
+
+%%
+
+void yyerror(YYLTYPE *llocp, struct diameap_conf * config,const char *str)
+{
+ fprintf(stderr,"Error in %s ( on line %i column %i -> line %i column %i) : %s\n",config->conffile, llocp->first_line, llocp->first_column, llocp->last_line, llocp->last_column, str);
+}
diff --git a/extensions/app_diameap/diameap_common.h b/extensions/app_diameap/diameap_common.h
new file mode 100644
index 0000000..82822c7
--- /dev/null
+++ b/extensions/app_diameap/diameap_common.h
@@ -0,0 +1,127 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_COMMON_H_
+#define DIAMEAP_COMMON_H_
+
+#include "libdiameap.h"
+#include "libcrypt.h"
+#include "diameap.h"
+#include "diameap_plugins.h"
+#include "diameap_eap.h"
+#include "diameap_server.h"
+#include <regex.h>
+
+
+
+/* Dictionary Object templates */
+extern struct dict_object * dataobj_diameap_cmd; /* Diameter-EAP-Request Command Code */
+extern struct dict_object * dataobj_diameap_app; /* Diameter EAP Application object */
+extern struct dict_object * dataobj_diameap_ven; /* Diameter EAP Application Vendor object */
+extern struct dict_object * dataobj_accounting_eap_auth_method;
+extern struct dict_object * dataobj_acct_interim_interval;
+extern struct dict_object * dataobj_auth_application_id;
+extern struct dict_object * dataobj_auth_grace_period;
+extern struct dict_object * dataobj_auth_request_type;
+extern struct dict_object * dataobj_auth_session_state;
+extern struct dict_object * dataobj_authorization_lifetime;
+extern struct dict_object * dataobj_callback_id;
+extern struct dict_object * dataobj_callback_number;
+extern struct dict_object * dataobj_called_station_id;
+extern struct dict_object * dataobj_calling_station_id;
+extern struct dict_object * dataobj_class;
+extern struct dict_object * dataobj_configuration_token;
+extern struct dict_object * dataobj_connect_info;
+extern struct dict_object * dataobj_destination_host;
+extern struct dict_object * dataobj_destination_realm;
+extern struct dict_object * dataobj_eap_master_session_key;
+extern struct dict_object * dataobj_eap_key_name;
+extern struct dict_object * dataobj_eap_payload;
+extern struct dict_object * dataobj_eap_reissued_payload;
+extern struct dict_object * dataobj_error_message;
+extern struct dict_object * dataobj_error_reporting_host;
+extern struct dict_object * dataobj_failed_avp;
+extern struct dict_object * dataobj_filter_id;
+extern struct dict_object * dataobj_framed_appletalk_link;
+extern struct dict_object * dataobj_framed_appletalk_network;
+extern struct dict_object * dataobj_framed_appletalk_zone;
+extern struct dict_object * dataobj_framed_compression;
+extern struct dict_object * dataobj_framed_interface_id;
+extern struct dict_object * dataobj_framed_ip_address;
+extern struct dict_object * dataobj_framed_ip_netmask;
+extern struct dict_object * dataobj_framed_ipv6_prefix;
+extern struct dict_object * dataobj_framed_ipv6_pool;
+extern struct dict_object * dataobj_framed_ipv6_route;
+extern struct dict_object * dataobj_framed_ipx_network;
+extern struct dict_object * dataobj_framed_mtu;
+extern struct dict_object * dataobj_framed_pool;
+extern struct dict_object * dataobj_framed_protocol;
+extern struct dict_object * dataobj_framed_route;
+extern struct dict_object * dataobj_framed_routing;
+extern struct dict_object * dataobj_idle_timeout;
+extern struct dict_object * dataobj_multi_round_time_out;
+extern struct dict_object * dataobj_nas_filter_rule;
+extern struct dict_object * dataobj_nas_identifier;
+extern struct dict_object * dataobj_nas_ip_address;
+extern struct dict_object * dataobj_nas_ipv6_address;
+extern struct dict_object * dataobj_nas_port;
+extern struct dict_object * dataobj_nas_port_id;
+extern struct dict_object * dataobj_nas_port_type;
+extern struct dict_object * dataobj_originating_line_info;
+extern struct dict_object * dataobj_origin_host;
+extern struct dict_object * dataobj_origin_realm;
+extern struct dict_object * dataobj_origin_state_id;
+extern struct dict_object * dataobj_port_limit;
+extern struct dict_object * dataobj_proxy_info;
+extern struct dict_object * dataobj_qos_filter_rule;
+extern struct dict_object * dataobj_re_auth_request_type;
+extern struct dict_object * dataobj_redirect_host;
+extern struct dict_object * dataobj_redirect_host_usage;
+extern struct dict_object * dataobj_redirect_max_cache_time;
+extern struct dict_object * dataobj_reply_message;
+extern struct dict_object * dataobj_result_code;
+extern struct dict_object * dataobj_route_record;
+extern struct dict_object * dataobj_service_type;
+extern struct dict_object * dataobj_session_id;
+extern struct dict_object * dataobj_session_timeout;
+extern struct dict_object * dataobj_state;
+extern struct dict_object * dataobj_tunneling;
+extern struct dict_object * dataobj_user_name;
+
+
+#endif /* DIAMEAP_COMMON_H_ */
diff --git a/extensions/app_diameap/diameap_defs.h b/extensions/app_diameap/diameap_defs.h
new file mode 100644
index 0000000..c095e86
--- /dev/null
+++ b/extensions/app_diameap/diameap_defs.h
@@ -0,0 +1,220 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_DEFS_H_
+#define DIAMEAP_DEFS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+
+/************************************************/
+/* Data Type Definition */
+/************************************************/
+
+/* boolean Type */
+typedef enum
+{
+ FALSE = 0, TRUE = 1
+} boolean;
+
+/* Exact-width integer types */
+typedef int8_t s8; /* signed char */
+typedef uint8_t u8; /* unsigned char */
+typedef int16_t s16; /* signed int */
+typedef uint16_t u16; /* unsigned int */
+typedef int32_t s32; /* signed long int */
+typedef uint32_t u32; /* unsigned long int */
+typedef int64_t s64; /* signed long long int */
+typedef uint64_t u64; /* unsigned long long int */
+
+/************************************************/
+/* Macros */
+/************************************************/
+
+/* Macros for manipulating data*/
+
+/* Retrieve signed/unsigned exact-width integer types */
+#define G8(v) (u8) (* (v) )
+
+#define G16BIGE(v) ( ( (u16) (* (v) ) << 8 ) ^ \
+ ( (u16) (*((v)+1)) ) )
+#define G16LITE(v) ( ( (u16) (*((v)+1)) << 8 ) ^ \
+ ( (u16) (* (v) ) ) )
+
+#define G24BIGE(v) ( ( (u32) (* (v) ) << 16 ) ^ \
+ ( (u32) (*((v)+1)) << 8 ) ^ \
+ ( (u32) (*((v)+2)) ) )
+#define G24LITE(v) ( ( (u32) (*((v)+2)) << 16 ) ^ \
+ ( (u32) (*((v)+1)) << 8 ) ^ \
+ ( (u32) (* (v) ) ) )
+
+#define G32BIGE(v) ( ( (u32) (* (v) ) << 24 ) ^ \
+ ( (u32) (*((v)+1)) << 16 ) ^ \
+ ( (u32) (*((v)+2)) << 8 ) ^ \
+ ( (u32) (*((v)+3)) ) )
+#define G32LITE(v) ( ( (u32) (*((v)+3)) << 24 ) ^ \
+ ( (u32) (*((v)+2)) << 16 ) ^ \
+ ( (u32) (*((v)+1)) << 8 ) ^ \
+ ( (u32) (* (v) ) ) )
+
+#define G64BIGE(v) ( ( (u64) (* (v) ) << 56 ) ^ \
+ ( (u64) (*((v)+1)) << 48 ) ^ \
+ ( (u64) (*((v)+2)) << 40 ) ^ \
+ ( (u64) (*((v)+3)) << 32 ) ^ \
+ ( (u64) (*((v)+4)) << 24 ) ^ \
+ ( (u64) (*((v)+5)) << 16 ) ^ \
+ ( (u64) (*((v)+6)) << 8 ) ^ \
+ ( (u64) (*((v)+7)) ) )
+#define G64LITE(v) ( ( (u64) (*((v)+7)) << 56 ) ^ \
+ ( (u64) (*((v)+6)) << 48 ) ^ \
+ ( (u64) (*((v)+5)) << 40 ) ^ \
+ ( (u64) (*((v)+4)) << 32 ) ^ \
+ ( (u64) (*((v)+3)) << 24 ) ^ \
+ ( (u64) (*((v)+2)) << 16 ) ^ \
+ ( (u64) (*((v)+1)) << 8 ) ^ \
+ ( (u64) (* (v) ) ) )
+
+/* Insert signed/unsigned exact-width integer types */
+/* v : pointer where to insert the data
+ * b : pointer of data to be inserted
+ */
+/* Insertion format
+ * BIGE : BIG ENDIAN
+ * LITE : LITTLE ENDIAN
+ */
+
+#define P8(v,b) do { \
+ u8 x = (b); \
+ u8 *d = (v); \
+ d[0] = (x&0xffU); \
+ } while (0)
+
+#define P16BIGE(v,b) do { \
+ u16 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x >> 8)&0xffU); \
+ d[1] = (x&0xffU); \
+ } while (0)
+
+#define P16LITE(v,b) do { \
+ u16 x = (b); \
+ u8 *d = (v); \
+ d[0] = (x&0xffU); \
+ d[1] = ((x >> 8)&0xffU); \
+ } while (0)
+
+#define P24BIGE(v, b) do { \
+ u32 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x >> 16)&0xffU); \
+ d[1] = ((x >> 8)&0xffU); \
+ d[2] = ((x)&0xffU); \
+ } while (0)
+
+#define P24LITE(v, b) do { \
+ u32 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x)&0xffU); \
+ d[1] = ((x >> 8)&0xffU); \
+ d[2] = ((x >> 16)&0xffU); \
+ } while (0)
+
+#define P32BIGE(v, b) do { \
+ u32 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x >> 24)&0xffU); \
+ d[1] = ((x >> 16)&0xffU); \
+ d[2] = ((x >> 8)&0xffU); \
+ d[3] = ((x)&0xffU); \
+ } while (0)
+
+#define P32LITE(v, b) do { \
+ u32 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x)&0xffU); \
+ d[1] = ((x >> 8)&0xffU); \
+ d[2] = ((x >> 16)&0xffU); \
+ d[3] = ((x >> 24)&0xffU); \
+ } while (0)
+
+#define P64BIGE(v, b) do { \
+ u64 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x >> 56)&0xffU); \
+ d[1] = ((x >> 48)&0xffU); \
+ d[2] = ((x >> 40)&0xffU); \
+ d[3] = ((x >> 32)&0xffU); \
+ d[4] = ((x >> 24)&0xffU); \
+ d[5] = ((x >> 16)&0xffU); \
+ d[6] = ((x >> 8)&0xffU); \
+ d[7] = ((x)&0xffU); \
+ } while (0)
+
+#define P64LITE(v, b) do { \
+ u64 x = (b); \
+ u8 *d = (v); \
+ d[0] = ((x)&0xffU); \
+ d[1] = ((x >> 8)&0xffU); \
+ d[2] = ((x >> 16)&0xffU); \
+ d[3] = ((x >> 24)&0xffU); \
+ d[4] = ((x >> 32)&0xffU); \
+ d[5] = ((x >> 40)&0xffU); \
+ d[6] = ((x >> 48)&0xffU); \
+ d[7] = ((x >> 56)&0xffU); \
+ } while (0)
+
+/*
+ * Insert data in a specified position
+ * a : (u8*) pointer where to insert the data
+ * f : (int) insert from this position
+ * l : (int) length of the data in byte to insert
+ * b : (u8*) pointer of data to be inserted
+ */
+
+#define U8COPY(a,f,l,b) do{ \
+ u8 * x = (a); \
+ u8 * y = (b); \
+ int i; \
+ for(i=0;i<l;i++) \
+ x[i+f]= y[i]; \
+ } while (0)
+
+
+#endif /*DIAMEAP_DEFS_H_*/
diff --git a/extensions/app_diameap/diameap_eap.c b/extensions/app_diameap/diameap_eap.c
new file mode 100644
index 0000000..72885ea
--- /dev/null
+++ b/extensions/app_diameap/diameap_eap.c
@@ -0,0 +1,604 @@
+/*****************************************************************************************************
+ * 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"
+
+static void diameap_ba_nextid(struct eap_state_machine * sm, int * id)
+{
+ TRACE_ENTRY("%p %p",sm,id);
+
+ if (sm->currentId < 0)
+ {
+ *id = (u8) (255 * rand() / RAND_MAX) & 0xFFU;
+ }
+ else
+ {
+ *id = (sm->currentId++) & 0xFFU;
+ }
+ if (*id == sm->lastId)
+ {
+ *id=*id+1;
+ }
+}
+
+static void diameap_ba_policyupdate(struct eap_state_machine * eap_sm,
+ struct eap_packet *eapPacket)
+{
+ TRACE_ENTRY("%p %p",eap_sm, eapPacket);
+ if ((eap_sm->respMethod == TYPE_NAK))
+ {
+ int id;
+ eap_sm->user.pmethods = 0;
+ u32 vendor;
+ eap_type type;
+ u8 *data = (u8 *) eapPacket->data;
+ data += 5;
+ id = 5;
+ while (id < eapPacket->length)
+ {
+ vendor = VENDOR_IETF;
+ type = G8(data);
+ if (diameap_plugin_exist(vendor, type) == TRUE)
+ {
+ eap_sm->user.proposedmethods[id - 5].method = type;
+ eap_sm->user.proposedmethods[id - 5].vendor = vendor;
+ eap_sm->user.pmethods++;
+ }
+ data++;
+ id++;
+ }
+ eap_sm->user.methodId = -1;
+ }
+}
+
+static int diameap_ba_policygetnextmethod(struct eap_state_machine * eap_sm,
+ eap_type * eaptype, u32 * vendor)
+{
+ TRACE_ENTRY("%p %p %p",eap_sm,eaptype,vendor);
+ *vendor = 0;
+ *eaptype = TYPE_NONE;
+ if (eap_sm == NULL)
+ {
+ return EINVAL;
+ }
+
+ eap_sm->selectedMethod = NULL;
+
+ if (eap_sm->user.userid == NULL)
+ {
+ if ((eap_sm->currentMethod == TYPE_NONE))
+ {
+ *vendor = VENDOR_IETF;
+ *eaptype = TYPE_IDENTITY;
+ if (eap_sm->selectedMethod != NULL)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ CHECK_FCT(diameap_plugin_get(VENDOR_IETF,TYPE_IDENTITY,&eap_sm->selectedMethod));
+ return 0;
+ }
+
+ eap_sm->selectedMethod = NULL;
+ *vendor = 0;
+ *eaptype = TYPE_NONE;
+ return 0;
+ }
+
+ if (eap_sm->user.methodId == -1)
+ {
+ if (eap_sm->user.proposed_eap_method >= TYPE_EAP_MD5)
+ {
+ *vendor = eap_sm->user.proposed_eap_method_vendor;
+ if (*vendor == VENDOR_IETF)
+ {
+ *eaptype = eap_sm->user.proposed_eap_method;
+ }
+ else
+ {
+ *eaptype = TYPE_EXPANDED_TYPES;
+ }
+ if (eap_sm->selectedMethod != NULL)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ CHECK_FCT_DO(diameap_plugin_get(*vendor,*eaptype,&eap_sm->selectedMethod),
+ { TRACE_DEBUG(INFO,"%s [EAP Protocol] Invalid EAP-TYPE %d (vendor %d)",DIAMEAP_EXTENSION,*eaptype,*vendor);return 1;});
+
+ }
+ eap_sm->user.proposed_eap_method = TYPE_NONE;
+ }
+ else
+ {
+ *vendor = eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor;
+ if (eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor
+ == VENDOR_IETF)
+ {
+ *eaptype
+ = eap_sm->user.proposedmethods[eap_sm->user.methodId].method;
+ }
+ else
+ {
+ *eaptype = TYPE_EXPANDED_TYPES;
+ }
+ if (eap_sm->selectedMethod != NULL)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+ eap_sm->methodData=NULL;
+ }
+ CHECK_FCT(diameap_plugin_get(eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor,eap_sm->user.proposedmethods[eap_sm->user.methodId].method,&eap_sm->selectedMethod));
+
+ eap_sm->user.methodId++;
+ }
+
+ return 0;
+}
+
+static int diameap_ba_policygetdecision(struct eap_state_machine * eap_sm,
+ struct diameap_eap_interface * eap_i, decision * gdecision)
+{
+ TRACE_ENTRY("%p %p %p",eap_sm,eap_i,gdecision);
+
+ if (eap_sm->user.userid != NULL)
+ {
+
+ if (eap_sm->methodState == EAP_M_END)
+ {
+
+ if (eap_sm->respMethod == TYPE_IDENTITY)
+ {
+
+ *gdecision = DECISION_CONTINUE;
+ return 0;
+ }
+
+ if ((eap_sm->respMethod == TYPE_NAK) || ((eap_sm->respMethod
+ == TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+ == VENDOR_IETF) && (eap_sm->respVendorMethod == TYPE_NAK)))
+ {
+ goto SelectNextMethod;
+ }
+
+ if (eap_sm->user.success == TRUE)
+ {
+
+ *gdecision = DECISION_SUCCESS;
+ }
+ else
+ {
+
+ *gdecision = DECISION_FAILURE;
+ }
+
+ }
+ else
+ {
+ goto SelectNextMethod;
+ }
+ return 0;
+
+ SelectNextMethod: if ((eap_sm->user.methodId
+ == (MAXPROPOSEDMETHODS - 1))
+ || ((eap_sm->user.proposedmethods[eap_sm->user.methodId + 1].method
+ == TYPE_NONE)
+ && (eap_sm->user.proposedmethods[eap_sm->user.methodId
+ + 1].vendor == VENDOR_IETF)))
+ {
+ TRACE_DEBUG(FULL+1,
+ "%s [EAP protocol] None of proposed EAP Methods authenticated the user.(FAILURE)",DIAMEAP_EXTENSION);
+ *gdecision = DECISION_FAILURE;
+ return 0;
+ }
+
+ eap_sm->user.methodId = 0;
+ *gdecision = DECISION_CONTINUE;
+ return 0;
+ }
+
+ if (eap_sm->currentMethod == TYPE_IDENTITY)
+ {
+ *gdecision = DECISION_FAILURE;
+ return 0;
+ }
+
+ *gdecision = DECISION_CONTINUE;
+ return 0;
+}
+
+static boolean diameap_ba_policydopickup(eap_type type)
+{
+ TRACE_ENTRY("%d",type);
+ if (type == TYPE_IDENTITY)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int diameap_eap_statemachine(struct eap_state_machine * eap_sm,
+ struct diameap_eap_interface * eap_i, boolean * non_fatal_error)
+{
+ TRACE_ENTRY("%p %p %p", eap_sm, eap_i, non_fatal_error);
+ int ret;
+
+ if ((eap_sm->eap_state == EAP_IDLE) && (eap_i->aaaEapResp == TRUE))
+ {
+ eap_sm->eap_state = EAP_RECEIVED;
+ }
+ while (!((eap_sm->eap_state == EAP_IDLE) || (eap_sm->eap_state == EAP_END)))
+ {
+ switch (eap_sm->eap_state)
+ {
+ case EAP_INITIALIZE:
+ if (eap_sm->rxResp == TRUE)
+ {
+ eap_sm->lastId = eap_sm->currentId;
+ eap_sm->currentId = eap_sm->respId;
+ }
+ else
+ {
+ eap_sm->lastId = -1;
+ eap_sm->currentId = -1;
+ }
+ if (eap_sm->rxResp == FALSE)
+ {
+ eap_sm->eap_state = EAP_SELECT_ACTION;
+ }
+ else if ((eap_sm->respMethod == TYPE_NAK) || (eap_sm->respMethod
+ == TYPE_EXPANDED_TYPES && eap_sm->respVendor == VENDOR_IETF
+ && eap_sm->respVendorMethod == TYPE_NAK))
+ {
+ eap_sm->eap_state = EAP_NAK;
+ }
+ else
+ {
+ eap_sm->eap_state = EAP_PICK_UP_METHOD;
+ }
+ break;
+ case EAP_PICK_UP_METHOD:
+ if (diameap_ba_policydopickup(eap_sm->respMethod) == TRUE)
+ {
+ eap_sm->currentMethod = eap_sm->respMethod;
+
+ if (diameap_plugin_get(eap_sm->currentVendor,
+ eap_sm->currentMethod, &eap_sm->selectedMethod))
+ {
+ TRACE_DEBUG(INFO,"%sNo EAP Method plugin available for EAP Method {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+ }
+ else
+ {
+ TRACE_DEBUG(FULL,"%sCurrent EAP Method {Type=%d, Vendor=%d} (EAP Method plugin selected).",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+ }
+ eap_sm->currentVendor = VENDOR_IETF;
+ if (eap_sm->selectedMethod != NULL)
+ {
+ ret = (*eap_sm->selectedMethod->eap_method_initPickUp)(
+ eap_sm);
+ if (ret)
+ {
+ TRACE_DEBUG(INFO, "%sEAP Method InitPickUp returned error.",DIAMEAP_EXTENSION);
+ eap_sm->selectedMethod = NULL;
+ eap_sm->currentMethod = TYPE_NONE;
+ }
+ }
+ }
+ if (eap_sm->currentMethod == TYPE_NONE)
+ {
+ eap_sm->eap_state = EAP_SELECT_ACTION;
+ }
+ else
+ {
+ eap_sm->eap_state = EAP_METHOD_RESPONSE;
+ }
+ break;
+
+ case EAP_RECEIVED:
+ TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP Response received",DIAMEAP_EXTENSION)
+ ;
+ diameap_eap_dump(FULL + 1, &eap_i->aaaEapRespData);
+ if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+ == eap_sm->currentId) && ((eap_sm->respMethod
+ == eap_sm->currentMethod) || ((eap_sm->respMethod
+ == TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+ == VENDOR_IETF) && (eap_sm->respVendorMethod
+ == eap_sm->currentMethod))))
+ {
+ eap_sm->eap_state = EAP_INTEGRITY_CHECK;
+ }
+ else if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+ == eap_sm->currentId) && ((eap_sm->respMethod == TYPE_NAK)
+ || (eap_sm->respMethod == TYPE_EXPANDED_TYPES
+ && eap_sm->respVendor == VENDOR_IETF
+ && eap_sm->respVendorMethod == TYPE_NAK))
+ && (eap_sm->methodState == EAP_M_PROPOSED))
+ {
+ eap_sm->eap_state = EAP_NAK;
+ }
+ else
+ {
+ eap_sm->eap_state = EAP_DISCARD;
+ }
+ break;
+ case EAP_DISCARD:
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP Packet received (Non fatal error).",DIAMEAP_EXTENSION)
+ ;
+ *non_fatal_error = TRUE;
+ eap_sm->eap_state = EAP_IDLE;
+ break;
+
+ case EAP_SEND_REQUEST:
+ TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP packet request created.",DIAMEAP_EXTENSION)
+ ;
+ diameap_eap_dump(FULL, &eap_i->aaaEapReqData);
+ eap_i->aaaEapResp = FALSE;
+ eap_i->aaaEapReq = TRUE;
+ eap_sm->eap_state = EAP_IDLE;
+ break;
+
+ case EAP_INTEGRITY_CHECK:
+ if ((*eap_sm->selectedMethod->eap_method_check)(eap_sm,
+ &eap_i->aaaEapRespData) == FALSE)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP packet received {Type=%d, Vendor=%d}. Integrity check failed (non fatal error).",DIAMEAP_EXTENSION,eap_sm->currentMethod,eap_sm->currentVendor);
+ //non_fata_error
+ *non_fatal_error = TRUE;
+ eap_sm->eap_state = EAP_IDLE;
+ }
+ else
+ {
+ eap_sm->eap_state = EAP_METHOD_RESPONSE;
+ }
+
+ break;
+ case EAP_METHOD_REQUEST:
+ eap_sm->lastId = eap_sm->currentId;
+ diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+ CHECK_FCT((*eap_sm->selectedMethod->eap_method_buildReq)(
+ eap_sm, eap_sm->currentId,&eap_i->aaaEapReqData))
+ ;
+ if (eap_sm->selectedMethod->eap_method_getTimeout)
+ {
+ if ((*eap_sm->selectedMethod->eap_method_getTimeout)(eap_sm,
+ &eap_i->aaaMethodTimeout))
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] getTimeout failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+ eap_i->aaaMethodTimeout = 0;
+ }
+ }
+ else
+ {
+ eap_i->aaaMethodTimeout = 0;
+ }
+ eap_sm->eap_state = EAP_SEND_REQUEST;
+ break;
+
+ case EAP_METHOD_RESPONSE:
+ if (eap_sm->respMethod >= TYPE_EAP_MD5)
+ {
+ if (eap_sm->user.methodId < 0)
+ {
+ eap_sm->user.methodId = 0;
+ eap_sm->user.methods[eap_sm->user.methodId].vendor
+ = eap_sm->respVendor;
+ eap_sm->user.methods[eap_sm->user.methodId].method
+ = eap_sm->respMethod;
+ eap_sm->user.methodId++;
+
+ }
+ else if (!((eap_sm->user.methods[eap_sm->user.methodId - 1].vendor
+ == eap_sm->respVendor)
+ && (eap_sm->user.methods[eap_sm->user.methodId - 1].method
+ == eap_sm->respMethod)))
+ {
+ eap_sm->user.methods[eap_sm->user.methodId].vendor
+ = eap_sm->respVendor;
+ eap_sm->user.methods[eap_sm->user.methodId].method
+ = eap_sm->respMethod;
+ eap_sm->user.methodId++;
+ }
+ }
+ if ((*eap_sm->selectedMethod->eap_method_process)(eap_sm,
+ &eap_i->aaaEapRespData))
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Authentication process failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+ *non_fatal_error = TRUE;
+ eap_sm->eap_state = EAP_IDLE;
+
+ }else{
+ if ((*eap_sm->selectedMethod->eap_method_isDone)(eap_sm) == TRUE)
+ {
+ /*diameap_ba_PolicyUpdate();*/
+ eap_i->aaaEapMSKLength = 0;
+ eap_i->aaaEapEMSKLength = 0;
+ if (eap_sm->selectedMethod->eap_method_getKey)
+ {
+ if ((*eap_sm->selectedMethod->eap_method_getKey)(eap_sm,
+ &eap_i->aaaEapMSKData, &eap_i->aaaEapMSKLength,
+ &eap_i->aaaEapEMSKData, &eap_i->aaaEapEMSKLength))
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Generating EAP Master Key failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname)
+ eap_i->aaaEapMSKLength = 0;
+ eap_i->aaaEapEMSKLength = 0;
+ eap_i->aaaEapKeyAvailable = FALSE;
+ }
+ else
+ {
+ eap_i->aaaEapKeyAvailable = TRUE;
+ }
+ }
+ eap_sm->methodState = EAP_M_END;
+ eap_sm->eap_state = EAP_SELECT_ACTION;
+ }
+ else
+ {
+ eap_sm->methodState = EAP_M_CONTINUE;
+ eap_sm->eap_state = EAP_METHOD_REQUEST;
+ }
+ }
+ break;
+ case EAP_PROPOSE_METHOD:
+ if (diameap_ba_policygetnextmethod(eap_sm, &eap_sm->currentMethod,
+ &eap_sm->currentVendor))
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Selecting EAP Method plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+
+ *non_fatal_error = TRUE;
+ eap_sm->eap_state = EAP_END;
+
+ }
+ TRACE_DEBUG(FULL,"%s[EAP Protocol] Selecting EAP Method plugin: %s(%d). [user: %s]",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname,eap_sm->selectedMethod->methodtype,eap_sm->user.userid)
+ ;
+ if ((*eap_sm->selectedMethod->eap_method_init)(eap_sm))
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Initializing EAP plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+ }
+
+ if ((eap_sm->currentMethod == TYPE_IDENTITY)
+ || (eap_sm->currentMethod == TYPE_NOTIFICATION))
+ {
+ eap_sm->methodState = EAP_M_CONTINUE;
+ }
+ else
+ {
+ eap_sm->methodState = EAP_M_PROPOSED;
+ }
+ eap_sm->eap_state = EAP_METHOD_REQUEST;
+ break;
+ case EAP_NAK:
+ TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP NAK Packet received.",DIAMEAP_EXTENSION)
+ ;
+ if (eap_sm->selectedMethod->eap_method_free)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ else
+ {
+ if (eap_sm->methodData)
+ {
+ free(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ }
+ diameap_ba_policyupdate(eap_sm, &eap_i->aaaEapRespData);
+ eap_sm->eap_state = EAP_SELECT_ACTION;
+ break;
+ case EAP_SELECT_ACTION:
+ CHECK_FCT(diameap_ba_policygetdecision(eap_sm, eap_i,&eap_sm->sm_decision))
+ ;
+ switch (eap_sm->sm_decision)
+ {
+ case DECISION_CONTINUE:
+ eap_sm->eap_state = EAP_PROPOSE_METHOD;
+ break;
+ case DECISION_FAILURE:
+ TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Failure [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+ ;
+ eap_sm->lastId = eap_sm->currentId;
+ diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+ CHECK_FCT(diameap_eap_new(EAP_FAILURE, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+ ;
+ eap_i->aaaFail = TRUE;
+ *non_fatal_error = FALSE;
+ eap_sm->eap_state = EAP_END;
+ if (eap_sm->methodData)
+ {
+ if (eap_sm->selectedMethod->eap_method_free)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(
+ eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ else
+ {
+ free(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ }
+ break;
+ case DECISION_SUCCESS:
+ TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Success [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+ ;
+ eap_sm->lastId = eap_sm->currentId;
+ diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+ CHECK_FCT(diameap_eap_new(EAP_SUCCESS, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+ ;
+ if (eap_i->aaaEapMSKData != NULL)
+ {
+ TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+ eap_i->aaaEapKeyAvailable = TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG(FULL+1,"%s[EAP Protocol] No EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+ }
+ eap_i->aaaSuccess = TRUE;
+ *non_fatal_error = FALSE;
+ eap_sm->eap_state = EAP_END;
+ if (eap_sm->selectedMethod->eap_method_free)
+ {
+ (*eap_sm->selectedMethod->eap_method_free)(
+ eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ else
+ {
+ if (eap_sm->methodData)
+ {
+ free(eap_sm->methodData);
+ eap_sm->methodData = NULL;
+ }
+ }
+ break;
+ default:
+ TRACE_DEBUG(INFO,"%sIncorrect EAP Decision.(Please report this problem.)",DIAMEAP_EXTENSION)
+ ;
+ }
+ break;
+
+ case EAP_END:
+ break;
+
+ case EAP_IDLE:
+ break;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/extensions/app_diameap/diameap_eap.h b/extensions/app_diameap/diameap_eap.h
new file mode 100644
index 0000000..8fb6617
--- /dev/null
+++ b/extensions/app_diameap/diameap_eap.h
@@ -0,0 +1,73 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_EAP_H_
+#define DIAMEAP_EAP_H_
+
+
+/************************************************/
+/* EAP AAA Interface */
+/************************************************/
+
+/* EAP Backend Authenticator State Machine */
+struct diameap_eap_interface
+{
+
+ /* Variables (AAA Interface to Backend Authenticator)*/
+ boolean aaaEapResp;
+ struct eap_packet aaaEapRespData;
+
+ /*Variables (Backend Authenticator to AAA Interface )*/
+ boolean aaaEapReq;
+ boolean aaaEapNoReq;
+ boolean aaaSuccess;
+ boolean aaaFail;
+ struct eap_packet aaaEapReqData;
+ u8 *aaaEapMSKData;
+ int aaaEapMSKLength;
+ u8 *aaaEapEMSKData;
+ int aaaEapEMSKLength;
+ boolean aaaEapKeyAvailable;
+ int aaaMethodTimeout;
+
+};
+
+int diameap_eap_statemachine(struct eap_state_machine * sm, struct diameap_eap_interface * eap_i, boolean * error);
+
+
+#endif /* EAP_H_ */
diff --git a/extensions/app_diameap/diameap_eappacket.c b/extensions/app_diameap/diameap_eappacket.c
new file mode 100644
index 0000000..a696161
--- /dev/null
+++ b/extensions/app_diameap/diameap_eappacket.c
@@ -0,0 +1,310 @@
+/*****************************************************************************************************
+ * 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 "libdiameap.h"
+
+int diameap_eap_get_code(struct eap_packet *eappacket, eap_code * eapcode)
+{
+ TRACE_ENTRY("%p %p",eappacket,eapcode);
+
+ if (eappacket->data == NULL)
+ {
+ *eapcode = ERROR;
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Code to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 1)
+ {
+ *eapcode = ERROR;
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Code to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *eapcode = G8(eappacket->data);
+ return 0;
+}
+
+int diameap_eap_get_identifier(struct eap_packet *eappacket, u8 * identifier)
+{
+ TRACE_ENTRY("%p %p",eappacket,identifier);
+ *identifier = 0;
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Identifier field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 2)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no Identifier field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *identifier = G8(eappacket->data + 1);
+ return 0;
+}
+
+int diameap_eap_get_length(struct eap_packet *eappacket, u16 *length)
+{
+ TRACE_ENTRY("%p %p",eappacket,length);
+ *length = 0;
+
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->ulength < 4)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no Length field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *length = (u16) G16BIGE((eappacket->data + 2));
+ return 0;
+}
+
+int diameap_eap_get_packetlength(struct eap_packet *eappacket, u16 *length)
+{
+ TRACE_ENTRY("%p %p",eappacket,length);
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ *length = eappacket->ulength;
+ return 0;
+}
+
+int diameap_eap_get_type(struct eap_packet *eappacket, eap_type * eaptype)
+{
+ TRACE_ENTRY("%p %p",eappacket,eaptype);
+ *eaptype = 0;
+
+ if (eappacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Type field to return.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (eappacket->length < 5)
+ {
+ TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Type field to return.",DIAMEAP_EXTENSION, eappacket->length);
+ return EINVAL;
+ }
+ *eaptype = (u32) G8(eappacket->data + 4);
+ return 0;
+}
+
+boolean diameap_eap_check_code(eap_code code)
+{
+ TRACE_ENTRY("%d",code);
+ if (code != EAP_REQUEST && code != EAP_RESPONSE && code != EAP_SUCCESS
+ && code != EAP_FAILURE)
+ {
+ TRACE_DEBUG(FULL,"%sIncorrect EAP Code (%d).",DIAMEAP_EXTENSION,code);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int diameap_eap_get_packetdata(struct eap_packet *eappacket, u8 ** data,
+ int *len)
+{
+ TRACE_ENTRY("%p %p",eappacket,data);
+ if (eappacket->length > 0)
+ {
+ *data = malloc(sizeof(u8) * eappacket->length);
+ U8COPY(*data,0,eappacket->length,eappacket->data);
+ *len = eappacket->length;
+ return 0;
+ }
+ TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+ *data = NULL;
+ *len = 0;
+ return EINVAL;
+}
+
+int diameap_eap_get_data(struct eap_packet *eappacket, u8 ** data, int * len)
+{
+ TRACE_ENTRY("%p %p",eappacket,data);
+ if (eappacket->length > 5)
+ {
+ CHECK_MALLOC( *data = malloc(sizeof(u8) * (eappacket->length - 5)) );
+ U8COPY(*data,0,(eappacket->length-5),(eappacket->data+5));
+ *len = eappacket->length - 5;
+ return 0;
+ }
+ TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
+ *data = NULL;
+ *len = 0;
+
+ return EINVAL;
+}
+
+void diameap_eap_dump(int level, struct eap_packet *eappacket)
+{
+ TRACE_ENTRY("%d %p",level,eappacket);
+ if (!TRACE_BOOL(level))
+ return;
+
+ if (eappacket->data == NULL)
+ return;
+ if (eappacket->length < 5)
+ return;
+ if (eappacket->ulength < 5)
+ return;
+
+ fd_log_debug("------------- Dump EAP Packet-------------");
+ int i;
+ fd_log_debug("\t -Code : ");
+ eap_code code;
+ CHECK_FCT_DO(diameap_eap_get_code(eappacket,&code),return);
+ switch (code)
+ {
+ case 1:
+ fd_log_debug("Request");
+ break;
+ case 2:
+ fd_log_debug("Response");
+ break;
+ case 3:
+ fd_log_debug("Success");
+ break;
+ case 4:
+ fd_log_debug("Failure");
+ break;
+ default:
+ fd_log_debug("Error (EAP Code value [%d] not allowed)",code);
+ break;
+ }
+ u8 id;
+ CHECK_FCT_DO(diameap_eap_get_identifier(eappacket,&id),return);
+ fd_log_debug("\t -Identifier : %x ", id);
+ u16 length;
+ CHECK_FCT_DO(diameap_eap_get_length(eappacket,&length),return);
+ fd_log_debug("\t -Length : %d ", (unsigned int)length);
+ if (eappacket->length > 4)
+ {
+ eap_type type;
+ CHECK_FCT_DO(diameap_eap_get_type(eappacket,&type),return);
+ fd_log_debug("\t -Type : %d ", type);
+ }
+ if (eappacket->length > 5)
+ {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "\t -Data : ");
+ for (i = 5; i < eappacket->length && i < 30; i++)
+ {
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02x ", G8(eappacket->data + i));
+ }
+ if(i+1<eappacket->length)
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "[...] (len=%d)",(unsigned int) length);
+ fd_log_debug("%s", buf);
+ }
+ fd_log_debug("-------------End Dump EAP Packet-------------");
+}
+
+int diameap_eap_new(eap_code code, u8 id, eap_type type, u8 * data,
+ u16 dataLength, struct eap_packet *eappacket)
+{
+
+ TRACE_ENTRY("%d %hhu %d %p %hu %p", code, id, type, data, dataLength,eappacket);
+
+ int length = 0;
+
+ //Initialize EAP Packet
+ eappacket->length = 0;
+ eappacket->ulength = 0;
+ eappacket->data = NULL;
+
+ if (diameap_eap_check_code(code) == FALSE)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%sWrong EAP Code. Only Request, Response, Success or Failure are permitted.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+
+ length += EAP_HEADER;
+ if (code == EAP_REQUEST || code == EAP_RESPONSE)
+ { // EAP Packet code is either Request or Response
+ if (type == TYPE_NONE)
+ {
+ TRACE_DEBUG(INFO,
+ "%sUnable to create a new EAP Packet (Request or Response) without EAP Type field.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ length += EAP_TYPE; // EAP Packet code
+ if (data != NULL)
+ {
+ length += dataLength;
+
+ if (length > (int) MAX_EAP_PACKET)
+ {
+
+ TRACE_DEBUG(INFO,
+ "%sUnable to add Data to EAP Packet. Data field length exceed allowed data size.", DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ else
+ {
+
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ U8COPY(eappacket->data, 5, dataLength, data);
+ }
+ }
+ else
+ {
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ }
+ P8(eappacket->data + 4, type);
+ }
+ else
+ { //EAP Packet code is SUCCESS or FAILURE
+ CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
+ memset(eappacket->data, 0, sizeof(u8) * length);
+ //No Data filed
+ //No Type field
+ }
+ //Add Code and Identifier fields
+ P8(eappacket->data, code);
+ P8(eappacket->data + 1, id);
+ //Add length field
+ P16BIGE(eappacket->data + 2, length);
+ eappacket->length = length;
+ eappacket->ulength = length;
+ return 0;
+}
diff --git a/extensions/app_diameap/diameap_eappacket.h b/extensions/app_diameap/diameap_eappacket.h
new file mode 100644
index 0000000..1f0c069
--- /dev/null
+++ b/extensions/app_diameap/diameap_eappacket.h
@@ -0,0 +1,258 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_EAPPACKET_H_
+#define DIAMEAP_EAPPACKET_H_
+
+#include "diameap_defs.h"
+
+/*EAP Packet definition : the Extensible Authentication Protocol (RFC3748) */
+
+/* Define Length/Size */
+#define EAP_HEADER 4 /* EAP Packet header size : 4 Bytes */
+#define EAP_TYPE 1 /* EAP Type field size : 1 Byte */
+#define MAX_EAP_PACKET (u16)0xffff /* Maximum value allowed for an EAP Packet */
+
+/*EAP Packet Codes Type*/
+typedef enum
+{
+ ERROR = 0, /* EAP Packet Code should not be set to ERROR. Indicates a wrong Code value received. */
+ EAP_REQUEST = 1, /* EAP Request (value=1). */
+ EAP_RESPONSE = 2, /* EAP Response (value=2). */
+ EAP_SUCCESS = 3, /* EAP Success (value=3). */
+ EAP_FAILURE = 4 /* EAP Failure (value=4). */
+} eap_code;
+
+/* EAP Packet */
+struct eap_packet
+{
+ u16 length; /* Length of data (equivalent to the length field). */
+ u16 ulength; /* Length of received or inserted bytes in the data pointer. */
+ u8 *data; /* Data buffer (including Code, Identifier, Length, (also Type and Data fields if exists)). */
+};
+
+/* EAP Methods Types */
+typedef enum
+{
+ TYPE_NONE = 0, /* Indicate no method specified */
+ TYPE_IDENTITY = 1, /* EAP Identity (RFC3748) */
+ TYPE_NOTIFICATION = 2, /* EAP Notification (RFC3748) */
+ TYPE_NAK = 3, /* EAP NAK (RFC3748) */
+ TYPE_EAP_MD5 = 4, /* EAP MD5 (RFC3748) */
+ TYPE_OTP = 5, /* EAP OTP (RFC3748) */
+ TYPE_GTC = 6, /* EAP GTC (RFC3748) */
+ TYPE_EAP_TLS = 13, /* EAP TLS (RFC5216) */
+ TYPE_EXPANDED_TYPES = 254, /* EAP Expanded NAK (RFC3748) */
+ TYPE_EXPERIMENTAL_USE = 255 /* for Experimental use (RFC3748) */
+} eap_type;
+
+
+/* Function : diameap_eap_get_code
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * eapcode : On successful return, the EAP Code is stored here.
+ *
+ * Description:
+ * Get the EAP Code of an EAP Packet. If NULL EAP Packet or empty packet ERROR is stored in eapcode.
+ *
+ * Return value:
+ * 0 : if successful
+* EINVAL : if EAP Packet is NULL or empty
+ */
+
+int diameap_eap_get_code(struct eap_packet *eapPacket, eap_code * eapcode);
+
+
+/* Function : diameap_eap_get_identifier
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * identifier : on successful return, the identifier value is stored here.
+ *
+ * Description:
+ * Get the Identifier field of an EAP Packet.
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if the EAP Packet is NULL or the EAP identifier value is not valid or data length < 2
+ *
+ */
+
+int diameap_eap_get_identifier(struct eap_packet *eapPacket, u8 * identifier);
+
+
+/* Function : diameap_eap_get_length
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * length : on successful return, the EAP Packet length field is stored here.
+ *
+ * Description:
+ * Get the Length field of an EAP Packet
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if the data length < 4, or the EAP Packet is NULL.
+ */
+
+int diameap_eap_get_length(struct eap_packet *eapPacket, u16 *length);
+
+
+/* Function : diameap_eap_get_packetlength
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * length : on successful return, the length of EAP Packet is stored here.
+ *
+ * Description:
+ * Get the received or inserted length of Bytes in an EAP Packet.
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if the EAP Packet is NULL
+ */
+
+int diameap_eap_get_packetlength(struct eap_packet *eapPacket, u16 *length);
+
+
+/* Function : diameap_eap_get_type
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * eaptype : on successful return, the EAP Type field is stored here.
+ *
+ * Description:
+ * Get the Type field of an EAP Packet.
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if the EAP Packet is NULL or data length < 5
+ */
+
+int diameap_eap_get_type(struct eap_packet *eapPacket,eap_type * eaptype);
+
+
+/* Function : diameap_eap_get_packetdata
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * eapdata : on successful return, the content of EAP Packet is stored here.
+ * eapdatalen : on successful return, the length of EAP Packet is stored here.
+ *
+ * Description:
+ * Get the data content of an EAP Packet.
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if there is no data in the current EAP Packet (ulength<1)
+ */
+
+int diameap_eap_get_packetdata(struct eap_packet *eapPacket, u8 ** data, int *len);
+
+
+/* Function : diameap_eap_get_data
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * data : on successful return, the content of data field is stored here.
+ * datalen : on successful return, the length of data field is stored here.
+ *
+ * Description:
+ * Return the Data field of an EAP Packet
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : if there is no data in the current EAP Packet (ulength<6)
+ */
+
+int diameap_eap_get_data(struct eap_packet *eapPacket, u8 ** data, int * len);
+
+
+/* Function : diameap_eap_chech_code
+ *
+ * Parameters:
+ * code : an EAP Code value
+ *
+ * Description:
+ * Check if the code value is valid or not
+ *
+ * Return value:
+ * TRUE : if valid value
+ * FALSE : if not valid value
+ *
+ */
+
+boolean diameap_eap_check_code(eap_code code);
+
+
+/* Function : diameap_eap_dump
+ *
+ * Parameters:
+ * eapPacket : an EAP Packet
+ * level : Debug level
+ *
+ * Description:
+ * Dump the structure and the content of all the fields in this EAP Packet
+ *
+ */
+
+void diameap_eap_dump(int level, struct eap_packet *eapPacket);
+
+
+/* Function : diameap_eap_new
+ *
+ * Parameters:
+ * code : EAP CODE field value
+ * id : EAP Identifier field value
+ * type : (optional) EAP type field value if exist, otherwise NULL
+ * data : (optional) EAP data field value if exist, otherwise NULL
+ * dataLength : (optional) Length of the data to be inserted in the Packet, otherwise 0
+ * eappacket : on successful return, pointer to eap packet is stored here.
+ * Description:
+ * Create a new EAP Packet with the specified parameters and data
+ *
+ * Return value:
+ * 0 : if successful
+ * EINVAL : Invalid parameter
+ */
+
+int diameap_eap_new(eap_code code, u8 id, eap_type type,
+ u8 * data, u16 dataLength, struct eap_packet *eappacket);
+
+#endif /* DIAMEAP_EAPPACKET_H_ */
diff --git a/extensions/app_diameap/diameap_init.c b/extensions/app_diameap/diameap_init.c
new file mode 100644
index 0000000..e3b8cc9
--- /dev/null
+++ b/extensions/app_diameap/diameap_init.c
@@ -0,0 +1,424 @@
+/*****************************************************************************************************
+ * 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"
+
+/* Dictionary Object templates */
+struct dict_object * dataobj_diameap_cmd = NULL; /* Diameter-EAP-Request Command Code */
+struct dict_object * dataobj_diameap_app = NULL; /* Diameter EAP Application object */
+struct dict_object * dataobj_diameap_ven = NULL; /* Diameter EAP Application Vendor object */
+struct dict_object * dataobj_accounting_eap_auth_method = NULL;
+struct dict_object * dataobj_acct_interim_interval = NULL;
+struct dict_object * dataobj_auth_application_id = NULL;
+struct dict_object * dataobj_auth_grace_period = NULL;
+struct dict_object * dataobj_auth_request_type = NULL;
+struct dict_object * dataobj_auth_session_state = NULL;
+struct dict_object * dataobj_authorization_lifetime = NULL;
+struct dict_object * dataobj_callback_id = NULL;
+struct dict_object * dataobj_callback_number = NULL;
+struct dict_object * dataobj_called_station_id = NULL;
+struct dict_object * dataobj_calling_station_id = NULL;
+struct dict_object * dataobj_class = NULL;
+struct dict_object * dataobj_configuration_token = NULL;
+struct dict_object * dataobj_connect_info = NULL;
+struct dict_object * dataobj_destination_host = NULL;
+struct dict_object * dataobj_destination_realm = NULL;
+struct dict_object * dataobj_eap_master_session_key = NULL;
+struct dict_object * dataobj_eap_key_name = NULL;
+struct dict_object * dataobj_eap_payload = NULL;
+struct dict_object * dataobj_eap_reissued_payload = NULL;
+struct dict_object * dataobj_error_message = NULL;
+struct dict_object * dataobj_error_reporting_host = NULL;
+struct dict_object * dataobj_failed_avp = NULL;
+struct dict_object * dataobj_filter_id = NULL;
+struct dict_object * dataobj_framed_appletalk_link = NULL;
+struct dict_object * dataobj_framed_appletalk_network = NULL;
+struct dict_object * dataobj_framed_appletalk_zone = NULL;
+struct dict_object * dataobj_framed_compression = NULL;
+struct dict_object * dataobj_framed_interface_id = NULL;
+struct dict_object * dataobj_framed_ip_address = NULL;
+struct dict_object * dataobj_framed_ip_netmask = NULL;
+struct dict_object * dataobj_framed_ipv6_prefix = NULL;
+struct dict_object * dataobj_framed_ipv6_pool = NULL;
+struct dict_object * dataobj_framed_ipv6_route = NULL;
+struct dict_object * dataobj_framed_ipx_network = NULL;
+struct dict_object * dataobj_framed_mtu = NULL;
+struct dict_object * dataobj_framed_pool = NULL;
+struct dict_object * dataobj_framed_protocol = NULL;
+struct dict_object * dataobj_framed_route = NULL;
+struct dict_object * dataobj_framed_routing = NULL;
+struct dict_object * dataobj_idle_timeout = NULL;
+struct dict_object * dataobj_multi_round_time_out = NULL;
+struct dict_object * dataobj_nas_filter_rule = NULL;
+struct dict_object * dataobj_nas_identifier = NULL;
+struct dict_object * dataobj_nas_ip_address = NULL;
+struct dict_object * dataobj_nas_ipv6_address = NULL;
+struct dict_object * dataobj_nas_port = NULL;
+struct dict_object * dataobj_nas_port_id = NULL;
+struct dict_object * dataobj_nas_port_type = NULL;
+struct dict_object * dataobj_originating_line_info = NULL;
+struct dict_object * dataobj_origin_host = NULL;
+struct dict_object * dataobj_origin_realm = NULL;
+struct dict_object * dataobj_origin_state_id = NULL;
+struct dict_object * dataobj_port_limit = NULL;
+struct dict_object * dataobj_proxy_info = NULL;
+struct dict_object * dataobj_qos_filter_rule = NULL;
+struct dict_object * dataobj_re_auth_request_type = NULL;
+struct dict_object * dataobj_redirect_host = NULL;
+struct dict_object * dataobj_redirect_host_usage = NULL;
+struct dict_object * dataobj_redirect_max_cache_time = NULL;
+struct dict_object * dataobj_reply_message = NULL;
+struct dict_object * dataobj_result_code = NULL;
+struct dict_object * dataobj_route_record = NULL;
+struct dict_object * dataobj_service_type = NULL;
+struct dict_object * dataobj_session_id = NULL;
+struct dict_object * dataobj_session_timeout = NULL;
+struct dict_object * dataobj_state = NULL;
+struct dict_object * dataobj_tunneling = NULL;
+struct dict_object * dataobj_user_name = NULL;
+
+
+
+static int diameap_init_config(char * conffile)
+{
+ TRACE_ENTRY("%p",conffile);
+
+ if (conffile != NULL)
+ {
+ diameap_config->conffile = conffile;
+ }
+ else
+ {
+ TRACE_DEBUG(FULL,"%sNo configuration file provided with the DiamEAP extension: default parameters will be used.",DIAMEAP_EXTENSION);
+ }
+
+ diameap_config->application_id = 5;
+ diameap_config->vendor_id = 0;
+ diameap_config->command_code = 268;
+ diameap_config->diam_realm = strdup(fd_g_config->cnf_diamrlm);
+ diameap_config->max_invalid_eap_packet = 5;
+ diameap_config->multi_round_time_out = 30;
+ check_user_identity = TRUE;
+
+ return 0;
+}
+
+static int diameap_init_obj(void)
+{
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &(diameap_config->application_id),&dataobj_diameap_app, ENOENT));
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND,CMD_BY_CODE_R, &(diameap_config->command_code), &dataobj_diameap_cmd, ENOENT));
+ // CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_VENDOR,VENDOR_OF_APPLICATION, &dataobj_diameap_app, &dataobj_diameap_ven,ENOENT) );
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Accounting-EAP-Auth-Method", &dataobj_accounting_eap_auth_method,
+ ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Acct-Interim-Interval", &dataobj_acct_interim_interval, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Auth-Application-Id", &dataobj_auth_application_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Auth-Grace-Period", &dataobj_auth_grace_period, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Auth-Request-Type", &dataobj_auth_request_type, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Auth-Session-State", &dataobj_auth_session_state, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Authorization-Lifetime", &dataobj_authorization_lifetime, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Callback-Id", &dataobj_callback_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Callback-Number", &dataobj_callback_number, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Called-Station-Id", &dataobj_called_station_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Calling-Station-Id", &dataobj_calling_station_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Class", &dataobj_class, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Configuration-Token", &dataobj_configuration_token, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Connect-Info", &dataobj_connect_info, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Destination-Host", &dataobj_destination_host, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Destination-Realm", &dataobj_destination_realm, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "EAP-Master-Session-Key", &dataobj_eap_master_session_key, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "EAP-Key-Name", &dataobj_eap_key_name, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "EAP-Payload", &dataobj_eap_payload, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "EAP-Reissued-Payload", &dataobj_eap_reissued_payload, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Error-Message", &dataobj_error_message, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Error-Reporting-Host", &dataobj_error_reporting_host, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Failed-AVP", &dataobj_failed_avp, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Filter-Id", &dataobj_filter_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-AppleTalk-Link", &dataobj_framed_appletalk_link, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-AppleTalk-Network", &dataobj_framed_appletalk_network,
+ ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-AppleTalk-Zone", &dataobj_framed_appletalk_zone, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Compression", &dataobj_framed_compression, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Interface-Id", &dataobj_framed_interface_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IP-Address", &dataobj_framed_ip_address, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IP-Netmask", &dataobj_framed_ip_netmask, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IPv6-Prefix", &dataobj_framed_ipv6_prefix, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IPv6-Pool", &dataobj_framed_ipv6_pool, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IPv6-Route", &dataobj_framed_ipv6_route, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-IPX-Network", &dataobj_framed_ipx_network, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-MTU", &dataobj_framed_mtu, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Pool", &dataobj_framed_pool, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Protocol", &dataobj_framed_protocol, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Route", &dataobj_framed_route, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Framed-Routing", &dataobj_framed_routing, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Idle-Timeout", &dataobj_idle_timeout, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Multi-Round-Time-Out", &dataobj_multi_round_time_out, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-Filter-Rule", &dataobj_nas_filter_rule, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-Identifier", &dataobj_nas_identifier, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-IP-Address", &dataobj_nas_ip_address, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-IPv6-Address", &dataobj_nas_ipv6_address, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-Port", &dataobj_nas_port, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-Port-Id", &dataobj_nas_port_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "NAS-Port-Type", &dataobj_nas_port_type, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Originating-Line-Info", &dataobj_originating_line_info, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Origin-Host", &dataobj_origin_host, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Origin-Realm", &dataobj_origin_realm, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Origin-State-Id", &dataobj_origin_state_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Port-Limit", &dataobj_port_limit, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Proxy-Info", &dataobj_proxy_info, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "QoS-Filter-Rule", &dataobj_qos_filter_rule, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Re-Auth-Request-Type", &dataobj_re_auth_request_type, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Redirect-Host", &dataobj_redirect_host, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Redirect-Host-Usage", &dataobj_redirect_host_usage, ENOENT));
+ CHECK_FCT(
+ fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Redirect-Max-Cache-Time",
+ &dataobj_redirect_max_cache_time, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Reply-Message", &dataobj_reply_message, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Result-Code", &dataobj_result_code, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Route-Record", &dataobj_route_record, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Service-Type", &dataobj_service_type, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Session-Id", &dataobj_session_id, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Session-Timeout", &dataobj_session_timeout, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "State", &dataobj_state, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "Tunneling", &dataobj_tunneling, ENOENT));
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME,
+ "User-Name", &dataobj_user_name, ENOENT));
+
+ return 0;
+}
+
+/* Parse the configuration file (using the yacc parser) */
+static int diameap_parse_conffile(void)
+{
+ if (!diameap_config->conffile)
+ {
+ TRACE_DEBUG (INFO,"%sNo configuration file to parse for DiamEAP Extension.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ extern FILE * diameapin;
+
+ TRACE_DEBUG (FULL, "%sParsing configuration file: %s",DIAMEAP_EXTENSION, diameap_config->conffile);
+ diameapin = fopen(diameap_config->conffile, "r");
+ if (!diameapin)
+ {
+ TRACE_DEBUG(INFO,"%sUnable to open configuration file %s for reading: %s",DIAMEAP_EXTENSION, diameap_config->conffile, strerror(errno));
+ return errno;
+ }
+
+ /* call yacc parser */
+ CHECK_FCT(diameapparse(diameap_config));
+
+ /* close the file */
+ CHECK_FCT(fclose(diameapin));
+ return 0;
+}
+
+int diameap_set_mysql_param(char * user, char * passwd, char * server,
+ char * database)
+{
+ TRACE_ENTRY("%p %p %p %p",user,passwd,server,database);
+ if (user == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: Empty user name or missing in the configuration file.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+
+ if (server == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: MySQL Database Server address missing in the configuration file.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ if (database == NULL)
+ {
+ TRACE_DEBUG(INFO,"%sUnable to connect to MySQL Database Server: MySQL Database name missing in configuration file.",DIAMEAP_EXTENSION);
+ return EINVAL;
+ }
+ diameap_config->db.user = user;
+ diameap_config->db.password = passwd;
+ diameap_config->db.server = server;
+ diameap_config->db.database = database;
+ return 0;
+}
+
+/* Connecting to MySQL Database */
+int diameap_mysql_connect(void)
+{
+ TRACE_ENTRY();
+ db_conn = mysql_init(NULL);
+ const my_bool mysql_reconnect_val=1;
+ mysql_options(db_conn,MYSQL_OPT_RECONNECT,&mysql_reconnect_val);
+ /* Connect to database */
+ if (!mysql_real_connect(db_conn, diameap_config->db.server,
+ diameap_config->db.user, diameap_config->db.password,
+ diameap_config->db.database, 0, NULL, 0))
+ {
+ TRACE_DEBUG(INFO,"%sConnection to MySQL Database Server failed: %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+ return errno;
+ }
+ return 0;
+}
+
+static void diameap_conf_dump(void)
+{
+
+ if (!TRACE_BOOL(INFO))
+ return;
+
+ fd_log_debug("-------- DiamEAP extension : Configuration parameters (Dump) -------------");
+ fd_log_debug("\t-Configuration file.....: %s", diameap_config->conffile);
+ fd_log_debug("\t-EAP Application Id.....: %u",
+ diameap_config->application_id);
+ fd_log_debug("\t-EAP Application Command: %u",
+ diameap_config->command_code);
+ fd_log_debug("\t-EAP Application Vendor.: %u", diameap_config->vendor_id);
+ fd_log_debug("\t-Max invalid EAP packets: %u", diameap_config->max_invalid_eap_packet);
+ fd_log_debug("\t-Multi-Round Timeout....: %u", diameap_config->multi_round_time_out);
+ if (diameap_config->db.user)
+ {
+ fd_log_debug("\t-MySQL Database Params..:");
+ fd_log_debug("\t\tUser .......:%s", diameap_config->db.user);
+ fd_log_debug("\t\tServer .....:%s", diameap_config->db.server);
+ fd_log_debug("\t\tDatabase....:%s", diameap_config->db.database);
+ }
+
+ fd_log_debug("\t-EAP Method Plugins.....: ");
+ diameap_plugin_dump();
+
+ fd_log_debug("-------- DiamEAP extension : Configuration parameters (End) ---------------");
+}
+
+int diameap_init(char * conffile)
+{
+ TRACE_ENTRY("%p",conffile);
+
+ /* Initialize the diameap_config structure*/
+ CHECK_FCT(diameap_init_config(conffile));
+
+ if (diameap_config->conffile)
+ {
+ /* parse the configuration file*/
+ CHECK_FCT(diameap_parse_conffile());
+
+ /* Load EAP methods plug-ins */
+ CHECK_FCT(diameap_plugin_load());
+
+ }
+ else
+ {
+ TRACE_DEBUG(FULL,"%sNo EAP method plug-in available with a default configuration.",DIAMEAP_EXTENSION);
+ }
+
+ /* Initialize Dictionary templates */
+ CHECK_FCT(diameap_init_obj());
+
+ /* Initialize access to user's information Database */
+ CHECK_FCT(diameap_mysql_connect());
+
+ /* Dump DiamEAP extension configuration */
+ diameap_conf_dump();
+
+ return 0;
+}
diff --git a/extensions/app_diameap/diameap_mysql.c b/extensions/app_diameap/diameap_mysql.c
new file mode 100644
index 0000000..b7a09c5
--- /dev/null
+++ b/extensions/app_diameap/diameap_mysql.c
@@ -0,0 +1,234 @@
+/*****************************************************************************************************
+ * 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_mysql.h"
+
+static pthread_mutex_t db_cs_mutex =
+PTHREAD_MUTEX_INITIALIZER;
+
+int diameap_get_eap_user(struct eap_user * user, char * username)
+{
+ TRACE_ENTRY("%p %p",user,username);
+ if (db_conn == NULL)
+ {
+ TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+ return EINVAL;
+
+ }
+ mysql_thread_init();
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char * query;
+ CHECK_MALLOC(query=(char *)malloc(sizeof(char)*255));
+
+ sprintf(
+ query,
+ "SELECT id,username,password,eapmethod, vendor FROM users WHERE users.username='%s' and users.active='Y' ",
+ username);
+
+ CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+ if (mysql_query(db_conn, query))
+ {
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+ TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return EINVAL;
+ }
+
+ res = mysql_store_result(db_conn);
+
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+ if ((row = mysql_fetch_row(res)) != NULL)
+ {
+
+ user->id = atoi(row[0]);
+ CHECK_MALLOC(user->userid=malloc(strlen(row[1])+1));
+ memcpy(user->userid,row[1],strlen(row[1])+1);
+ user->useridLength = strlen(row[1]);
+ CHECK_MALLOC(user->password=malloc(strlen(row[2])+1));
+ memcpy(user->password, row[2],strlen(row[2])+1);
+ user->passwordLength = strlen(row[2]);
+ user->proposed_eap_method = atoi(row[3]);
+ user->proposed_eap_method_vendor = atoi(row[4]);
+
+ mysql_free_result(res);
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return 0;
+ }
+
+ TRACE_DEBUG(INFO, "%sUser unavailable.",DIAMEAP_EXTENSION);
+ mysql_free_result(res);
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return EINVAL;
+
+}
+
+int diameap_authentication_get_attribs(struct eap_user *user,
+ struct fd_list * attribute_list)
+{
+
+ TRACE_ENTRY("%p %p",user,attribute_list);
+
+ if (db_conn == NULL)
+ {
+ TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+ return EINVAL;
+
+ }
+
+ mysql_thread_init();
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char * query;
+ CHECK_MALLOC(query=malloc(sizeof(char)*255));
+
+ sprintf(
+ query,
+ "SELECT `authe`.`attribute` ,`authe`.`value` FROM `authe` WHERE `authe`.`grp` IN ( SELECT `user_grp`.`grp` FROM `user_grp` WHERE `user_grp`.`user` = %d ) ",
+ user->id);
+
+ CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+ if (mysql_query(db_conn, query))
+ {
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+ TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return EINVAL;
+ }
+
+ res = mysql_store_result(db_conn);
+
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+ while ((row = mysql_fetch_row(res)))
+ {
+ struct auth_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct auth_attribute)));
+ memset(attribute, 0, sizeof(struct auth_attribute));
+ fd_list_init(&attribute->chain, NULL);
+ attribute->attrib = strdup(row[0]);
+ attribute->op = NULL;
+ attribute->value = strdup(row[1]);
+ fd_list_insert_before(attribute_list, &attribute->chain);
+
+ }
+
+ mysql_free_result(res);
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return 0;
+}
+
+int diameap_authorization_get_attribs(struct eap_user *user,
+ struct fd_list * attribute_list)
+{
+ TRACE_ENTRY("%p %p",user,attribute_list);
+
+ if (db_conn == NULL)
+ {
+ TRACE_DEBUG(INFO, "%sNot connected to the MySQL Database server.",DIAMEAP_EXTENSION);
+
+ return EINVAL;
+
+ }
+
+ mysql_thread_init();
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char * query;
+ CHECK_MALLOC(query=malloc(sizeof(char)*255));
+
+ sprintf(
+ query,
+ "SELECT `authz`.`attribute` , `authz`.`op` , `authz`.`value` FROM `authz` WHERE `authz`.`grp` IN ( SELECT `user_grp`.`grp` FROM `user_grp` WHERE `user_grp`.`user` = %d ) ",
+ user->id);
+
+ CHECK_POSIX(pthread_mutex_lock( &db_cs_mutex ));
+
+ if (mysql_query(db_conn, query))
+ {
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+ TRACE_DEBUG(INFO, "%sQuery execution fail. %s",DIAMEAP_EXTENSION, mysql_error(db_conn));
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return EINVAL;
+ }
+
+ res = mysql_store_result(db_conn);
+
+ CHECK_POSIX(pthread_mutex_unlock( &db_cs_mutex ));
+
+ while ((row = mysql_fetch_row(res)))
+ {
+ struct auth_attribute * attribute;
+ CHECK_MALLOC(attribute = malloc(sizeof(struct auth_attribute)));
+ memset(attribute, 0, sizeof(struct auth_attribute));
+ fd_list_init(&attribute->chain, NULL);
+ attribute->attrib = strdup(row[0]);
+ attribute->op = strdup(row[1]);
+ attribute->value = strdup(row[2]);
+ fd_list_insert_before(attribute_list, &attribute->chain);
+ }
+
+ mysql_free_result(res);
+ mysql_thread_end();
+ free(query);
+ query = NULL;
+ return 0;
+}
+
+void diameap_mysql_disconnect()
+{
+ mysql_close(db_conn);
+}
diff --git a/extensions/app_diameap/diameap_mysql.h b/extensions/app_diameap/diameap_mysql.h
new file mode 100644
index 0000000..c217dc6
--- /dev/null
+++ b/extensions/app_diameap/diameap_mysql.h
@@ -0,0 +1,67 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_MYSQL_H_
+#define DIAMEAP_MYSQL_H_
+
+#include "libdiameap.h"
+#include <mysql.h>
+
+/* MySQL Database connection */
+MYSQL *db_conn;
+
+int diameap_get_eap_user(struct eap_user * user, char * username);
+
+int diameap_mysql_connect();
+
+int diameap_mysql_reconnect();
+
+int diameap_set_mysql_param(char * user, char * passwd, char * server, char * database);
+
+void diameap_mysql_disconnect();
+
+/* */
+int diameap_authentication_get_attribs(struct eap_user *user,
+ struct fd_list * attribute_list);
+
+/* */
+int diameap_authorization_get_attribs(struct eap_user *user,
+ struct fd_list * attribute_list);
+
+
+#endif /* DIAMEAP_MYSQL_H_ */
diff --git a/extensions/app_diameap/diameap_plugins.c b/extensions/app_diameap/diameap_plugins.c
new file mode 100644
index 0000000..836c686
--- /dev/null
+++ b/extensions/app_diameap/diameap_plugins.c
@@ -0,0 +1,455 @@
+/*****************************************************************************************************
+ * 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 CONTRIBUTfORS 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"
+
+/********************************************/
+/* Loading and initializing plug-ins */
+/********************************************/
+
+/* Add new plugin */
+int diameap_plugin_add(char * name, eap_type methodtype, u32 vendor,
+ char * filename, char * conffile)
+{
+ TRACE_ENTRY("%p %d %d %p %p", name, methodtype, vendor, filename, conffile);
+
+ /* Check the filename is valid */
+ CHECK_PARAMS(filename);
+
+ /* add new EAP method in the list of plugins*/
+ {
+ struct plugin * plugin;
+ CHECK_MALLOC(plugin = malloc(sizeof(struct plugin)));
+ memset(plugin, 0, sizeof(struct plugin));
+ fd_list_init(&plugin->chain, plugin);
+ plugin->methodname = name;
+ plugin->methodtype = methodtype;
+ plugin->vendor = vendor;
+ plugin->pluginfile = filename;
+ plugin->conffile = conffile;
+ fd_list_insert_before(&plugins_list, &plugin->chain);
+ }
+
+ return 0;
+}
+
+/* Dump plugins list */
+void diameap_plugin_dump(void)
+{
+ struct fd_list * pl;
+
+ for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+ {
+ struct plugin * plugin = (struct plugin *) pl;
+ fd_log_debug("\t\t - %s plugin \t [Type: %i, Vendor: %i] %sloaded", plugin->methodname,
+ plugin->methodtype,plugin->vendor, plugin->handler ? "" : "not ");
+ }
+}
+
+int diameap_plugin_get(u32 vendor, eap_type type, struct plugin ** getplugin)
+{
+ TRACE_ENTRY("%d %d %p",vendor,type,getplugin);
+ struct fd_list * pl;
+
+ for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+ {
+ struct plugin * plugin = (struct plugin *) pl;
+ if (plugin->methodtype == type && plugin->vendor == vendor)
+ {
+ *getplugin = plugin;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Load all method in the plugins list */
+int diameap_plugin_load(void)
+{
+
+ int ret;
+ struct fd_list * pl;
+
+ /* Loop on all plugins */
+
+ for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+ {
+ struct plugin * plugin = (struct plugin *) pl;
+ struct register_plugin * registerplugin;
+ int (*diameap_plugin_register)();
+
+ TRACE_DEBUG(FULL, "%sLoading EAP method plugin: %s",DIAMEAP_EXTENSION, plugin->methodname);
+
+ /* Load the method */
+ plugin->handler = dlopen(plugin->pluginfile, RTLD_LAZY | RTLD_GLOBAL);
+ if (plugin->handler == NULL)
+ {
+ TRACE_DEBUG(INFO, "%sLoading of plugin %s failed: %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+
+ /* Defined register methods for this EAP method*/
+ diameap_plugin_register = (int(*)()) dlsym(plugin->handler,
+ "diameap_plugin_register");
+ if (!diameap_plugin_register)
+ {
+ TRACE_DEBUG(INFO,
+ "%s[%s plugin] Unable to register EAP method: %s.",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+
+ if ((*diameap_plugin_register)() != 0)
+ {
+ TRACE_DEBUG(INFO,
+ "%s[%s plugin] Unable to register EAP method plugin",DIAMEAP_EXTENSION,plugin->methodname);
+ }
+
+ int (*diameap_plugin_objects)(struct register_plugin **);
+
+ diameap_plugin_objects = (int(*)(struct register_plugin **)) dlsym(
+ plugin->handler, "diameap_plugin_objects");
+ if (!diameap_plugin_objects)
+ {
+ TRACE_DEBUG(INFO,
+ "%s[%s plugin] Unable to resolve symbol of the plugin: %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+
+ if ((*diameap_plugin_objects)(®isterplugin) != 0)
+ {
+
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to get objects description from the plug-in: %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+
+ /* eap_method_configure method */
+ if (registerplugin->configure)
+ {
+ plugin->eap_method_configure = (int(*)(char *)) dlsym(
+ plugin->handler, registerplugin->configure);
+ if (plugin->eap_method_configure == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_configure': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ }
+ }
+ else
+ {
+ plugin->eap_method_configure = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_configure'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ /* eap_method_init method */
+ if (registerplugin->init)
+ {
+ plugin->eap_method_init
+ = (int(*)(struct eap_state_machine *)) dlsym(
+ plugin->handler, registerplugin->init);
+ if (plugin->eap_method_init == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_init': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_init = NULL;
+ TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_init'",DIAMEAP_EXTENSION, plugin->methodname);
+ return EINVAL;
+ }
+
+ /* eap_method_initPickUp method */
+ if (registerplugin->initPickUp)
+ {
+ plugin->eap_method_initPickUp
+ = (int(*)(struct eap_state_machine *)) dlsym(
+ plugin->handler, registerplugin->initPickUp);
+ }
+ else
+ {
+ plugin->eap_method_initPickUp = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_initPickUp'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ /* eap_method_buildReq method */
+ if (registerplugin->buildReq)
+ {
+ plugin->eap_method_buildReq = (int(*)(struct eap_state_machine *,
+ u8, struct eap_packet *)) dlsym(plugin->handler,
+ registerplugin->buildReq);
+ if (plugin->eap_method_buildReq == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_buildReq': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_buildReq = NULL;
+ TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_buildReq'",DIAMEAP_EXTENSION, plugin->methodname);
+ return EINVAL;
+ }
+
+ /* eap_method_getTimeout method */
+ if (registerplugin->getTimeout)
+ {
+ plugin->eap_method_getTimeout = (int(*)(struct eap_state_machine *,
+ int *)) dlsym(plugin->handler, registerplugin->getTimeout);
+ if (plugin->eap_method_getTimeout == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_getTimeout': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_getTimeout = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_getTimeout'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ /* eap_method_check method */
+ if (registerplugin->check)
+ {
+ plugin->eap_method_check = (boolean(*)(struct eap_state_machine *,
+ struct eap_packet*)) dlsym(plugin->handler,
+ registerplugin->check);
+ if (plugin->eap_method_check == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_check': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_check = NULL;
+ TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_check'",DIAMEAP_EXTENSION, plugin->methodname);
+ return EINVAL;
+ }
+
+ /* eap_method_process method */
+ if (registerplugin->process)
+ {
+ plugin->eap_method_process = (int(*)(struct eap_state_machine *,
+ struct eap_packet*)) dlsym(plugin->handler,
+ registerplugin->process);
+ if (plugin->eap_method_process == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_process': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_process = NULL;
+ TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_process'",DIAMEAP_EXTENSION, plugin->methodname);
+ return EINVAL;
+ }
+
+ /* eap_method_isDone method */
+ if (registerplugin->isDone)
+ {
+ plugin->eap_method_isDone
+ = (boolean(*)(struct eap_state_machine *)) dlsym(
+ plugin->handler, registerplugin->isDone);
+ if (plugin->eap_method_isDone == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_isDone': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_isDone = NULL;
+ TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_isDone'",DIAMEAP_EXTENSION, plugin->methodname);
+ return EINVAL;
+ }
+
+ /* eap_method_getKey method */
+ if (registerplugin->getKey)
+ {
+ plugin->eap_method_getKey = (int(*)(struct eap_state_machine *,
+ u8**, int*,u8**, int*)) dlsym(plugin->handler, registerplugin->getKey);
+ if (plugin->eap_method_getKey == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_getKey': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_getKey = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_getKey'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ /* eap_method_unregister method */
+ if (registerplugin->unregister)
+ {
+ plugin->eap_method_unregister = (void(*)(void)) dlsym(
+ plugin->handler, registerplugin->unregister);
+ if (plugin->eap_method_unregister == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_unregister': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_unregister = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_unregister'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ /* eap_method_datafree method */
+ if (registerplugin->datafree)
+ {
+ plugin->eap_method_free = (void(*)(void *)) dlsym(plugin->handler,
+ registerplugin->datafree);
+ if (plugin->eap_method_free == NULL)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to resolve symbol for 'eap_method_datafree': %s",DIAMEAP_EXTENSION,
+ plugin->methodname, dlerror());
+ return EINVAL;
+ }
+ }
+ else
+ {
+ plugin->eap_method_free = NULL;
+ TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_datafree'",DIAMEAP_EXTENSION, plugin->methodname);
+ }
+
+ if (plugin->eap_method_configure != NULL)
+ {
+ /* call the configuration method */
+ ret = (*plugin->eap_method_configure)(plugin->conffile);
+ if (ret != 0)
+ {
+ TRACE_DEBUG(
+ INFO,
+ "%s[%s plugin] Unable to configure the plugin",DIAMEAP_EXTENSION,
+ plugin->methodname);
+ return ret;
+ }
+ }
+
+ TRACE_DEBUG(FULL, "%s[%s plugin] Loaded successfully.",DIAMEAP_EXTENSION,
+ plugin->methodname);
+
+ /* load next method */
+ }
+
+ return 0;
+}
+
+boolean diameap_plugin_exist(u32 vendor, eap_type type)
+{
+
+ TRACE_ENTRY("%d %d",vendor,type);
+ struct fd_list * pl;
+
+ for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+ {
+ struct plugin * plugin = (struct plugin *) pl;
+ if (plugin->methodtype == type && plugin->vendor == vendor)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int diameap_plugin_unload(void)
+{
+
+ while (!FD_IS_LIST_EMPTY(&plugins_list))
+ {
+ struct fd_list * plugin = plugins_list.next;
+ struct plugin * item = (struct plugin *) plugin;
+
+ fd_list_unlink(plugin);
+
+ if (item->eap_method_unregister != NULL)
+ {
+ (*item->eap_method_unregister)();
+ }
+
+ if (item->handler)
+ {
+ if (dlclose(item->handler) != 0)
+ {
+ TRACE_DEBUG (INFO, "%sFail to unload plugin %s : %s",DIAMEAP_EXTENSION, item->methodname, dlerror());
+ }
+ }
+
+ free(item->conffile);
+ free(item->pluginfile);
+ free(item);
+ }
+ return 0;
+}
diff --git a/extensions/app_diameap/diameap_plugins.h b/extensions/app_diameap/diameap_plugins.h
new file mode 100644
index 0000000..9a12c39
--- /dev/null
+++ b/extensions/app_diameap/diameap_plugins.h
@@ -0,0 +1,67 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_PLUGINS_H_
+#define DIAMEAP_PLUGINS_H_
+
+#include <dlfcn.h>
+
+
+
+static struct fd_list plugins_list = FD_LIST_INITIALIZER(plugins_list);
+
+/* Add a plug-in to the list of plugins*/
+int diameap_plugin_add(char * name, eap_type methodtype, u32 vendor, char * filename,
+ char * conffile);
+
+/* Dump all plug-ins (plugins_list)*/
+void diameap_plugin_dump();
+
+/* Return pointer to a plug-in */
+int diameap_plugin_get(u32 vendor,eap_type type, struct plugin ** getplugin);
+
+/* Load plug-ins */
+int diameap_plugin_load(void);
+
+/* Check if a plug-in exists for a given EAP method type */
+boolean diameap_plugin_exist(u32 vendor, eap_type type);
+
+/* Unload all plug-ins*/
+int diameap_plugin_unload(void);
+
+#endif /* DIAMEAP_PLUGINS_H_ */
diff --git a/extensions/app_diameap/diameap_server.c b/extensions/app_diameap/diameap_server.c
new file mode 100644
index 0000000..b93f6bb
--- /dev/null
+++ b/extensions/app_diameap/diameap_server.c
@@ -0,0 +1,3419 @@
+/*****************************************************************************************************
+ * 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;
+}
diff --git a/extensions/app_diameap/diameap_server.h b/extensions/app_diameap/diameap_server.h
new file mode 100644
index 0000000..cef11c7
--- /dev/null
+++ b/extensions/app_diameap/diameap_server.h
@@ -0,0 +1,117 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_SERVER_H_
+#define DIAMEAP_SERVER_H_
+
+
+/* session data structure to store */
+struct sess_state
+{
+ int invalid_eappackets; /* Number of invalid EAP Packet received*/
+
+ eap_type currentMethod;
+ u32 currentVendor;
+ int currentId;
+ int lastId;
+ void * methodData;
+
+ u8 NAKproposedMethods[251];
+
+ eap_method_state methodState;
+
+ struct eap_user user;
+};
+
+typedef enum
+{
+ AUTHENTICATE_ONLY = 1, AUTHORIZE_ONLY = 2, AUTHORIZE_AUTHENTICATE = 3
+} auth_request;
+
+struct diameap_state_machine
+{
+ int invalid_eappackets; /* Number of invalid EAP Packet received*/
+ struct avp * lastReqEAPavp; //last EAP-Payload AVP
+
+ int result_code; /*Error number for Result_code*/
+ struct fd_list attributes; //database attributes
+ struct fd_list req_attributes; //attributes from DER
+ struct fd_list ans_attributes; //attributes to be set for DEA
+ struct avp * failedavp; /* The Failed-AVP AVP. should be update whenever a Failed AVP is encountered during authentication. */
+ struct eap_state_machine eap_sm; /* EAP State Machine */
+ auth_request auth_request_val; /*the Request Type of Auth-Request-Type AVP*/
+ boolean verify_authorization; /* Set to TRUE at the authorization state. Parameter used to indicate that authorization is performed.*/
+ boolean authSuccess; // Set to TRUE if client authenticated and authorized
+ boolean authFailure; //set to TRUE if client is not authenticated
+ boolean authorized; //set to TRUE if client is authorized
+ enum
+ {
+ DIAMEAP_DISABLED,
+ DIAMEAP_INITIALIZE,
+ DIAMEAP_RECEIVED,
+ DIAMEAP_IDLE,
+ DIAMEAP_AUTHENTICATION_VERIFY,
+ DIAMEAP_SEND_ERROR_MSG,
+ DIAMEAP_SELECT_DECISION,
+ DIAMEAP_DIAMETER_EAP_ANSWER,
+ DIAMEAP_END,
+ DIAMEAP_AUTHORIZATION_VERIFY,
+ DIAMEAP_SEND_REQUEST,
+ DIAMEAP_SEND_SUCCESS,
+ DIAMEAP_SEND_FAILURE
+
+ } state; // state of DiamEAP
+
+ boolean privateUser;//TD
+};
+
+struct avp_max_occurences
+{
+ char * avp_attribute;
+ int max; //-1 means no limits
+};
+
+
+
+/* start server */
+int diameap_start_server(void);
+
+/* stop server*/
+int diameap_stop_server(void);
+
+#endif /* DIAMEAP_SERVER_H_ */
diff --git a/extensions/app_diameap/diameap_tls.c b/extensions/app_diameap/diameap_tls.c
new file mode 100644
index 0000000..e77a65c
--- /dev/null
+++ b/extensions/app_diameap/diameap_tls.c
@@ -0,0 +1,492 @@
+/*****************************************************************************************************
+ * 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_tls.h"
+
+//GCRY_THREAD_OPTION_PTHREAD_IMPL;
+
+int diameap_tls_init(struct tls_config * tls_conf)
+{
+ int ret;
+ ret = gnutls_global_init();
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ }
+
+ gnutls_global_set_log_function(diameap_tls_log);
+ //gnutls_global_set_log_level(9);
+
+
+ if(tls_conf->cafile ==NULL){
+ fprintf(stderr,"[DiamEAP extension] [EAP TLS] Missing certification authority (CA) certificates. Please provide CA configuration directive.\n");
+ return EINVAL;
+ }
+ if( !tls_conf->certfile || !tls_conf->keyfile){
+ fprintf(stderr,"[DiamEAP extension] [EAP TLS] Missing private Key. Please provide Cred configuration directive.\n");
+ return EINVAL;
+ }
+
+ ret = gnutls_certificate_allocate_credentials(&tls_conf->cert_cred);
+
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ return ret;
+ }
+
+ ret = gnutls_certificate_set_x509_trust_file(tls_conf->cert_cred,
+ tls_conf->cafile, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ return ret;
+ }
+ if (tls_conf->crlfile)
+ {
+ ret = gnutls_certificate_set_x509_crl_file(tls_conf->cert_cred,
+ tls_conf->crlfile, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ return ret;
+ }
+ }
+
+ ret = gnutls_certificate_set_x509_key_file(tls_conf->cert_cred,
+ tls_conf->certfile, tls_conf->keyfile, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ return ret;
+ }
+ return 0;
+}
+
+void diameap_tls_log(int lev, const char * text)
+{
+ u8 * msg;
+ if (text == NULL)
+ return;
+ msg = (u8 *) strdup(text);
+ int i;
+ for (i = 0; (G8(text+i) != '\n') && (G8(text+i) != '\0'); i++)
+ {
+ }
+ P8((msg+i),'\0');
+ fprintf(stderr, "[DiamEAP extension] [EAP TLS] GNUTLS log[%d] : %s\n", lev, msg);
+ free(msg);
+}
+
+int diameap_tls_init_session(struct tls_config * tls_conf,
+ struct tls_data * data)
+{
+ int ret;
+ ret = gnutls_init(&data->session, GNUTLS_SERVER);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ }
+ ret = gnutls_set_default_priority(data->session);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ }
+
+ ret = gnutls_credentials_set(data->session, GNUTLS_CRD_CERTIFICATE,
+ tls_conf->cert_cred);
+ if (ret < 0)
+ {
+ gnutls_perror(ret);
+ }
+
+ /* request client certificate if any.
+ */
+ gnutls_certificate_server_set_request(data->session, GNUTLS_CERT_REQUIRE); //GNUTLS_CERT_REQUEST);
+
+ gnutls_transport_set_pull_function(data->session, diameap_tls_receive);
+ gnutls_transport_set_push_function(data->session, diameap_tls_send);
+ gnutls_transport_set_ptr(data->session, (gnutls_transport_ptr_t) data);
+
+ /* starting version 2.12, this call is not needed */
+ //gnutls_transport_set_lowat(data->session, 0);
+
+ return ret;
+}
+
+ssize_t diameap_tls_receive(gnutls_transport_ptr_t ptr, void *buffer,
+ size_t length)
+{
+ struct tls_data * data = (struct tls_data *) ptr;
+ if (data->p_length == 0)
+ {
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+ if (length > data->p_length)
+ {
+ length = data->p_length;
+ }
+ memcpy(buffer, data->tlsResp.data + (data->tlsResp.datalength
+ - data->p_length), length);
+ data->p_length -= length;
+
+ return length;
+}
+
+ssize_t diameap_tls_send(gnutls_transport_ptr_t ptr, const void *buffer,
+ size_t length)
+{
+ struct tls_data * data = (struct tls_data *) ptr;
+ data->tlsReq.data = realloc(data->tlsReq.data, data->tlsReq.datalength
+ + length);
+ U8COPY(data->tlsReq.data,data->tlsReq.datalength,length,(u8*)buffer);
+ data->tlsReq.datalength += length;
+
+ return length;
+}
+
+int diameap_tls_new(struct tls_msg * tlsmsg)
+{
+ if (!tlsmsg)
+ {
+ return EINVAL;
+ }
+ tlsmsg->flags = 0x00;
+ tlsmsg->length = 0;
+ tlsmsg->data = NULL;
+ tlsmsg->datalength = 0;
+ return 0;
+}
+
+int diameap_tls_get_flags(struct tls_msg tlsmsg, u8 * flags)
+{
+ *flags = tlsmsg.flags;
+ return 0;
+}
+
+int diameap_tls_set_flags(struct tls_msg * tlsmsg, u8 flags)
+{
+ if (!tlsmsg)
+ {
+ return EINVAL;
+ }
+ if ((flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ flags = flags ^ TLS_FLAG_LENGTH;
+ }
+ tlsmsg->flags = tlsmsg->flags | flags;
+ return 0;
+}
+
+int diameap_tls_get_message_length(struct tls_msg tlsmsg, u32 * length)
+{
+ if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ *length = tlsmsg.length;
+ }
+ else
+ {
+ *length = 0;
+ }
+ return 0;
+}
+
+int diameap_tls_set_message_length(struct tls_msg * tlsmsg, u32 length)
+{
+ if (!tlsmsg)
+ {
+ return EINVAL;
+ }
+ if (length > 0)
+ {
+ tlsmsg->length = length;
+ tlsmsg->flags = tlsmsg->flags | TLS_FLAG_LENGTH;
+ }
+ else
+ {
+ tlsmsg->length = 0;
+ if ((tlsmsg->flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ tlsmsg->flags = tlsmsg->flags ^ TLS_FLAG_LENGTH;
+ }
+ }
+ return 0;
+}
+
+int diameap_tls_get_data(struct tls_msg tlsmsg, u8** tls_data,
+ u32 * data_length)
+{
+ if (tlsmsg.datalength > 0)
+ {
+ *tls_data = malloc(sizeof(u8) * tlsmsg.datalength);
+ U8COPY(*tls_data,0,tlsmsg.datalength,tlsmsg.data);
+ *data_length = tlsmsg.datalength;
+ }
+ else
+ {
+ *tls_data = NULL;
+ *data_length = 0;
+ }
+ return 0;
+}
+
+int diameap_tls_set_data(struct tls_msg * tlsmsg, u8* tls_data, int data_length)
+{
+ if (!tlsmsg)
+ {
+ return EINVAL;
+ }
+ tlsmsg->data = malloc(sizeof(u8) * data_length);
+ U8COPY(tlsmsg->data,0,data_length,tls_data);
+ tlsmsg->datalength = data_length;
+ return 0;
+}
+
+/*
+ * data : returned data
+ * eaptls_data : the TLS_Data field
+ * length : the length of eaptls_data
+ * flags : combination of flags et set
+ */
+int diameap_tls_new_tls_packet(u8** data, int * len, struct tls_msg tlsmsg)
+{
+ int buflen, pos = 0;
+
+ buflen = 1;
+
+ if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ buflen += 4;
+ }
+
+ if (tlsmsg.datalength > 0)
+ {
+ buflen += tlsmsg.datalength;
+ }
+ *data = malloc(sizeof(u8) * buflen);
+ memset(*data, 0, sizeof(u8) * buflen);
+ P8(*data,tlsmsg.flags);
+ pos++;
+
+ if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ P32BIGE(*data+pos,tlsmsg.length);
+ pos += 4;
+ }
+ if (tlsmsg.data)
+ {
+ U8COPY(*data,pos,tlsmsg.datalength,tlsmsg.data);
+ }
+ *len = buflen;
+ return 0;
+}
+
+int diameap_set_tls(struct tls_msg * tlsmsg, u8 flags, u32 length,
+ u8 *tls_data, int data_length)
+{
+ diameap_tls_new(tlsmsg);
+ diameap_tls_set_flags(tlsmsg, flags);
+ diameap_tls_set_message_length(tlsmsg, length);
+ diameap_tls_set_data(tlsmsg, tls_data, data_length);
+ return 0;
+}
+
+int diameap_tls_parse(u8* data, int len, struct tls_msg * tlsmsg)
+{
+
+ if (data == NULL)
+ return EINVAL;
+ int pos = 0;
+ diameap_tls_new(tlsmsg);
+ tlsmsg->flags = G8(data);
+ pos++;
+ if ((tlsmsg->flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ tlsmsg->length = G32BIGE(data+1);
+ pos = pos + 4;
+ }
+
+ if (len > pos)
+ {
+ tlsmsg->data = malloc(sizeof(u8) * (len - pos));
+ U8COPY(tlsmsg->data,0,(len-pos),data+pos);
+ tlsmsg->datalength = len - pos;
+ }
+ else
+ {
+ tlsmsg->data = NULL;
+ tlsmsg->datalength = 0;
+ }
+ return 0;
+}
+
+void diameap_tls_dump(struct tls_msg tlsmsg)
+{
+ u8 * data = NULL;
+ u32 len;
+ diameap_tls_get_data(tlsmsg, &data, &len);
+
+ fprintf(stderr, "-------------Dump EAP-TLS msg-------------\n");
+ u8 flags;
+ diameap_tls_get_flags(tlsmsg, &flags);
+ fprintf(stderr, "\t -flags : %02x ", flags);
+ if (flags & TLS_FLAG_LENGTH)
+ fprintf(stderr, " TLS_FLAG_LENGTH ");
+ if (flags & TLS_FLAG_MORE)
+ fprintf(stderr, " TLS_FLAG_MORE ");
+ if (flags & TLS_FLAG_START)
+ fprintf(stderr, " TLS_FLAG_START ");
+ fprintf(stderr, "\n");
+ if ((tlsmsg.flags & TLS_FLAG_LENGTH) == TLS_FLAG_LENGTH)
+ {
+ u32 length;
+ diameap_tls_get_message_length(tlsmsg, &length);
+ fprintf(stderr, "\t -TLS msg length : %u (0x%02x%02x%02x%02x)\n",
+ length, (length >> 24) & 0xffU, (length >> 16) & 0xffU, (length
+ >> 8) & 0xffU, length & 0xffU);
+ }
+ fprintf(stderr, "\t -data length : %d \n", len);
+ /*
+ if (len > 0)
+ {
+ int i;
+ fprintf(stderr, "\t -Data : ");
+ for (i = 0; i < len; i++)
+ {
+ fprintf(stderr, "%02x ", G8(data + i));
+ }
+ fprintf(stderr, "\n");
+ }
+ */
+ fprintf(stderr, "-------------End Dump EAP-TLS msg-------------\n");
+
+ free(data);
+}
+
+int diameap_tls_initialize(struct tls_data * data)
+{
+ if (!data)
+ {
+ return EINVAL;
+ }
+ data->state = START;
+ data->more_tosend_length = 0;
+ data->more_toreceive = FALSE;
+ data->handshake = FALSE;
+ return 0;
+}
+
+int diameap_tls_reassemble(struct tls_msg * to, struct tls_msg from)
+{
+ u8 from_flag;
+ diameap_tls_get_flags(from, &from_flag);
+
+ if (from_flag & TLS_FLAG_LENGTH)
+ {
+ diameap_tls_new(to);
+ u32 length;
+ diameap_tls_get_message_length(from, &length);
+ diameap_tls_set_message_length(to, length);
+ }
+ diameap_tls_set_flags(to, from_flag);
+
+ u8 * tlsRespData;
+ u32 tlsRespDataLength;
+ diameap_tls_get_data(from, &tlsRespData, &tlsRespDataLength);
+ to->data = realloc(to->data, to->datalength + tlsRespDataLength);
+ U8COPY(to->data,to->datalength,tlsRespDataLength,tlsRespData);
+ to->datalength += tlsRespDataLength;
+ free(tlsRespData);
+ return 0;
+}
+
+int diameap_tls_copy(struct tls_msg * to, struct tls_msg from)
+{
+ u8 flag;
+ u32 length;
+ u8 * data;
+ diameap_tls_new(to);
+ diameap_tls_get_flags(from, &flag);
+ diameap_tls_set_flags(to, flag);
+ diameap_tls_get_message_length(from, &length);
+ diameap_tls_set_message_length(to, length);
+ length = 0;
+ diameap_tls_get_data(from, &data, &length);
+ diameap_tls_set_data(to, data, length);
+ return 0;
+}
+
+int diameap_tls_process_receive(struct tls_data * data)
+{
+ int ret;
+
+ data->p_length = data->tlsResp.datalength;
+
+ ret = gnutls_handshake(data->session);
+
+ if (ret < 0)
+ {
+ switch (ret)
+ {
+ case GNUTLS_E_AGAIN:
+ break;
+ case GNUTLS_E_INTERRUPTED:
+ fprintf(stderr, "[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_INTERRUPTED");
+ break;
+ case GNUTLS_E_GOT_APPLICATION_DATA:
+ fprintf(stderr,
+ "[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_GOT_APPLICATION_DATA");
+ break;
+ case GNUTLS_E_WARNING_ALERT_RECEIVED:
+ fprintf(stderr,
+ "[DiamEAP extension] [EAP TLS] gnutls handshake : GNUTLS_E_WARNING_ALERT_RECEIVED");
+ break;
+ }
+ if (ret != GNUTLS_E_AGAIN)
+ {
+ gnutls_perror(ret);
+ }
+ }
+ if (ret == GNUTLS_E_SUCCESS)
+ {
+ data->handshake = TRUE;
+ }
+ return 0;
+}
+
diff --git a/extensions/app_diameap/diameap_tls.h b/extensions/app_diameap/diameap_tls.h
new file mode 100644
index 0000000..c5774e7
--- /dev/null
+++ b/extensions/app_diameap/diameap_tls.h
@@ -0,0 +1,141 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_TLS_H_
+#define DIAMEAP_TLS_H_
+
+#if defined(__GNUC__)
+# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
+# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 /* 4.6.x */
+# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
+ GCC_DIAG_PRAGMA(ignored x)
+# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
+# else /* older */
+# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored x)
+# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning x)
+# endif
+#else
+# define GCC_DIAG_OFF(x)
+# define GCC_DIAG_ON(x)
+#endif
+
+
+#include "diameap_defs.h"
+#include <gnutls/gnutls.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <errno.h>
+#include <pthread.h>
+
+
+
+#define TLS_FLAG_LENGTH 0x80
+#define TLS_FLAG_MORE 0x40
+#define TLS_FLAG_START 0x20
+
+struct tls_config{
+ char * conffile;
+ //certificates
+ char * keyfile;
+ char * certfile;
+ char * cafile;
+ char * crlfile;
+
+ //configuration parameters
+ boolean check_cert_cn_username;
+
+ int max_size;
+
+ gnutls_certificate_credentials_t cert_cred;
+};
+
+struct tls_msg{
+ u8 flags;
+ u32 length;
+ u8 *data;
+ u32 datalength;
+};
+
+struct tls_data
+{
+ gnutls_session_t session;
+ enum { START, CONTINUE, SUCCESS, FAILURE } state;
+ struct tls_msg tlsReq;
+ int p_length; /* length of buffer still not returned to handshake */
+ struct tls_msg tlsResp;
+ int more_tosend_length; /* 0 if no more fragment to send. Otherwise the length of the buff not yet sent */
+ boolean more_toreceive; /* TRUE if wait for more fragments. */
+ boolean handshake; /* TRUE if handshake terminated successful. */
+};
+
+int diameap_tls_init(struct tls_config * tls_conf );
+void diameap_tls_log(int lev, const char * text);
+int diameap_tls_init_session(struct tls_config * tls_conf, struct tls_data * data);
+int diameap_tls_new(struct tls_msg * tlsmsg);
+
+int diameap_tls_get_message_length(struct tls_msg tlsmsg, u32 * length);
+int diameap_tls_set_message_length(struct tls_msg * tlsmsg, u32 length);
+
+int diameap_tls_get_flags(struct tls_msg tlsmsg, u8 * flags);
+int diameap_tls_set_flags(struct tls_msg * tlsmsg, u8 flags);
+
+int diameap_tls_get_data(struct tls_msg tlsmsg, u8** tls_data, u32 * data_length);
+int diameap_tls_set_data(struct tls_msg * tlsmsg, u8* tls_data, int data_length);
+
+int diameap_tls_parse(u8* data, int length, struct tls_msg * tlsmsg);
+
+int diameap_tls_new_tls_packet(u8** data, int * len, struct tls_msg tlsmsg);
+
+int diameap_set_tls(struct tls_msg * tlsmsg, u8 flags, u32 length,u8 *tls_data, int data_length);
+
+void diameap_tls_dump(struct tls_msg tlsmsg);
+
+int diameap_tls_initialize(struct tls_data * data);
+
+int diameap_tls_reassemble(struct tls_msg * to,struct tls_msg from);
+
+int diameap_tls_copy(struct tls_msg * to,struct tls_msg from);
+
+int diameap_tls_process_receive(struct tls_data * data);
+
+ssize_t diameap_tls_receive(gnutls_transport_ptr_t data , void *buffer, size_t length);
+ssize_t diameap_tls_send(gnutls_transport_ptr_t data , const void *buffer, size_t length);
+
+#endif /* DIAMEAP_TLS_H_ */
diff --git a/extensions/app_diameap/diameap_user.c b/extensions/app_diameap/diameap_user.c
new file mode 100644
index 0000000..8e8de1b
--- /dev/null
+++ b/extensions/app_diameap/diameap_user.c
@@ -0,0 +1,152 @@
+/*****************************************************************************************************
+ * 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 "libdiameap.h"
+
+int diameap_user_get_userid(struct eap_user *user, u8* userid)
+{
+ TRACE_ENTRY("%p %p",user,userid);
+ if (user->userid == NULL)
+ return EINVAL;
+ userid = user->userid;
+ return 0;
+}
+
+int diameap_user_get_password(struct eap_user *user, u8* password,u16 * passwordlength)
+{
+ TRACE_ENTRY("%p %p",user,password);
+ if (user->password == NULL)
+ return EINVAL;
+ password = user->password;
+ *passwordlength = user->passwordLength;
+ return 0;
+}
+
+int diameap_user_get_passwordlength(struct eap_user *user, u16 * passwordlength)
+{
+ TRACE_ENTRY("%p %p",user,passwordlength);
+ if (user->password == NULL)
+ return EINVAL;
+ *passwordlength = user->passwordLength;
+ return 0;
+}
+
+int diameap_user_set_password(struct eap_user * user, u8 * password,
+ u16 passwordLength)
+{
+ TRACE_ENTRY("%p %p %hu",user,password,passwordLength);
+ if (password == NULL)
+ return EINVAL;
+ if (passwordLength < 1)
+ return EINVAL;
+ user->password = password;
+ user->passwordLength = passwordLength;
+ return 0;
+}
+
+int diameap_user_set_userid(struct eap_user * user, u8 * userid,
+ u16 useridLength)
+{
+ TRACE_ENTRY("%p %p %hu",user,userid,useridLength);
+ if (userid == NULL)
+ return EINVAL;
+ if (useridLength < 1)
+ return EINVAL;
+ user->userid = userid;
+ user->useridLength = useridLength;
+ return 0;
+}
+
+int diameap_user_get_methodid(struct eap_user *user, int * methodid)
+{
+ TRACE_ENTRY("%p %p",user,methodid);
+ if (user->password == NULL)
+ return EINVAL;
+ *methodid = user->methodId;
+ return 0;
+}
+
+int diameap_user_set_methodid(struct eap_user * user, int methodId)
+{
+ TRACE_ENTRY("%p %d",user,methodId);
+ if (user->password == NULL)
+ return EINVAL;
+ if (methodId < 0)
+ return EINVAL;
+ user->methodId = methodId;
+ return 0;
+}
+
+boolean diameap_user_issuccess(struct eap_user *user)
+{
+ TRACE_ENTRY("%p",user);
+ if (user->password == NULL)
+ return FALSE;
+ return user->success;
+}
+
+int diameap_user_set_success(struct eap_user * user)
+{
+ TRACE_ENTRY("%p",user);
+ if (user->password == NULL)
+ return EINVAL;
+ user->success = TRUE;
+ return 0;
+}
+
+int diameap_user_get_eap_method(struct eap_user *user, int id,
+ struct eap_method *method)
+{
+ TRACE_ENTRY("%p %d %p",user,id,method);
+ if (sizeof(user->methods) >= (id - 1))
+ *method = user->methods[id];
+ return 0;
+}
+
+int diameap_user_set_eap_method(struct eap_user * user, int id,
+ struct eap_method * method)
+{
+ TRACE_ENTRY("%p %d %p",user,id,method);
+ if (user->password == NULL)
+ return EINVAL;
+ if (sizeof(user->methods) < (id - 1))
+ return EINVAL;
+ user->methods[id].vendor = method->vendor;
+ user->methods[id].method = method->method;
+ return 0;
+}
diff --git a/extensions/app_diameap/diameap_user.h b/extensions/app_diameap/diameap_user.h
new file mode 100644
index 0000000..f798a88
--- /dev/null
+++ b/extensions/app_diameap/diameap_user.h
@@ -0,0 +1,98 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef DIAMEAP_USER_H_
+#define DIAMEAP_USER_H_
+
+#define MAXMETHODS 8 /*Maximum number of allowed methods */
+
+#define MAXPROPOSEDMETHODS 8 /*Maximum number of allowed proposed methods */
+
+#define VENDOR_IETF 0
+
+/*EAP User structure */
+struct eap_user
+{
+ int id; /*user's identifier*/
+ u8 *userid; /*user's identity*/
+ u16 useridLength; /*User's identity length*/
+ u8 *password; /*user's password*/
+ u16 passwordLength; /*Length of password*/
+
+ int methodId; /*Current method Id*/
+ struct eap_method
+ {
+ u32 vendor;
+ eap_type method;
+ } methods[MAXMETHODS]; /*used method for authentication*/
+
+ struct proposed_eap_method
+ {
+ u32 vendor;
+ eap_type method;
+ } proposedmethods[MAXPROPOSEDMETHODS]; /* methods proposed throw NAK response or EXPANDED NAK*/
+ int pmethods; /*Number of accepted methods from peer's proposed methods*/
+
+ eap_type proposed_eap_method; /* Proposed EAP Method*/
+ u32 proposed_eap_method_vendor;
+ boolean success; /* Set to TRUE if User is authenticated successfully */
+};
+
+boolean check_user_identity;
+
+int diameap_user_get_password(struct eap_user *user, u8 * password,u16 *length);
+
+int diameap_user_get_userid(struct eap_user *user, u8 * userid);
+
+int diameap_user_set_password(struct eap_user * user, u8 * password, u16 Length);
+
+int diameap_user_set_userid(struct eap_user * user, u8 * userid, u16 Length);
+
+int diameap_user_get_methodid(struct eap_user *user,int *methodId);
+
+int diameap_user_set_methodid(struct eap_user * user, int methodId);
+
+boolean diameap_user_issuccess(struct eap_user *user);
+
+int diameap_user_set_success(struct eap_user * user);
+
+int diameap_user_get_eap_method(struct eap_user *user, int id, struct eap_method * eapmethod);
+
+int diameap_user_set_eap_method(struct eap_user * user, int id, struct eap_method * method);
+
+#endif /* DIAMEAP_USER_H_ */
diff --git a/extensions/app_diameap/libcrypt.c b/extensions/app_diameap/libcrypt.c
new file mode 100644
index 0000000..846d6c8
--- /dev/null
+++ b/extensions/app_diameap/libcrypt.c
@@ -0,0 +1,56 @@
+/*****************************************************************************************************
+ * 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 "libcrypt.h"
+
+int md5hash(void * buffer, int length, void * digest){
+
+ gcry_md_hd_t md5_ctx;
+
+ gcry_md_open ( &md5_ctx, GCRY_MD_MD5, 0);
+
+ if(!gcry_md_is_enabled(md5_ctx, GCRY_MD_MD5)){
+ fprintf(stderr,"[libcrypt] unable to initiate MD5 hash algorithm.\n");
+ }
+
+ gcry_md_write(md5_ctx,buffer,length);
+
+ memcpy (digest, gcry_md_read (md5_ctx, 0), 16);
+ gcry_md_close (md5_ctx);
+ return 0;
+}
diff --git a/extensions/app_diameap/libcrypt.h b/extensions/app_diameap/libcrypt.h
new file mode 100644
index 0000000..375234b
--- /dev/null
+++ b/extensions/app_diameap/libcrypt.h
@@ -0,0 +1,54 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef LIBCRYPT_H_
+#define LIBCRYPT_H_
+
+/* EAP-TLS*/
+#include "diameap_tls.h"
+
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <stdio.h>
+
+
+
+int md5hash(void * buffer, int length, void * digest);
+
+#endif /* LIBCRYPT_H_ */
diff --git a/extensions/app_diameap/libdiameap.h b/extensions/app_diameap/libdiameap.h
new file mode 100644
index 0000000..b459e29
--- /dev/null
+++ b/extensions/app_diameap/libdiameap.h
@@ -0,0 +1,187 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef LIBDIAMEAP_H_
+#define LIBDIAMEAP_H_
+
+#include <freeDiameter/extension.h>
+
+#define DIAMEAP_EXTENSION "[DiamEAP extension] "
+
+#include "diameap_defs.h"
+#include "diameap_eappacket.h"
+#include "diameap_user.h"
+#include "diameap_mysql.h"
+
+#include <math.h>
+#include <dlfcn.h>
+
+
+/* authentication and authorization attributes */
+
+struct auth_attribute
+{
+ struct fd_list chain;
+ char * attrib;
+ char * op;
+ char * value;
+};
+
+struct avp_attribute
+{
+ struct fd_list chain;
+ char * attrib;
+ union avp_value value;
+ int tofree;
+};
+
+
+/************************************************/
+/* EAP Methods plugins */
+/************************************************/
+
+/* The register functions of an EAP method */
+struct register_plugin
+{
+ char * configure;
+ char * init;
+ char * initPickUp;
+ char * buildReq;
+ char * isDone;
+ char * process;
+ char * check;
+ char * getTimeout;
+ char * getKey;
+ char * unregister;
+ char * datafree;
+};
+
+struct eap_state_machine;
+/* List of plugins to load ( only EAP methods declared in the configuration file will be loaded) */
+struct plugin
+{
+ struct fd_list chain; /* link in the list */
+ u32 vendor; /* vendor*/
+ const char *methodname; /* name of the EAP method*/
+ eap_type methodtype; /* type number of the EAP method */
+ char *pluginfile; /* plugin filename */
+ char *conffile; /* optional configuration file name for the method */
+ void *handler; /* object returned by dlopen() */
+ int (*eap_method_configure)(char * configfile); /* (Optional) address of the eap_method_configure method */
+ int (*eap_method_init)(struct eap_state_machine *smd); /* address of the eap_method_init method */
+ int (*eap_method_initPickUp)(struct eap_state_machine *smd); /* address of the eap_method_initPickUp method */
+ int (*eap_method_buildReq)(struct eap_state_machine *smd,
+ u8 identifier,struct eap_packet * eapPacket); /* address of the eap_method_buildReq method */
+ int (*eap_method_getTimeout)(struct eap_state_machine *smd, int * timeout); /* address of the eap_method_getTimeout method */
+ boolean (*eap_method_check)(struct eap_state_machine *smd,
+ struct eap_packet * eapRespData); /* address of the eap_method_check method */
+ int (*eap_method_process)(struct eap_state_machine *smd,
+ struct eap_packet * eapRespData); /* address of the eap_method_process method */
+ boolean (*eap_method_isDone)(struct eap_state_machine *smd); /* address of the eap_method_isDone method */
+ int (*eap_method_getKey)(struct eap_state_machine *smd, u8 ** msk,int *msklength,
+ u8 ** emsk,int *emsklength); /* address of the eap_method_getKey method */
+ void (*eap_method_unregister)(void); /* (Optional) address of the eap_method_unregister method */
+ void (*eap_method_free)(void *); /* (Optional) address of the eap_method_datafree method */
+
+};
+
+
+/************************************************/
+/* EAP State Machine */
+/************************************************/
+
+/* EAP Policy Decision */
+typedef enum
+{
+ DECISION_FAILURE = 0, DECISION_SUCCESS = 1, DECISION_CONTINUE = 2
+} decision;
+
+typedef enum
+{
+ EAP_M_END, EAP_M_CONTINUE, EAP_M_PROPOSED
+} eap_method_state;
+
+/* EAP Backend Authenticator State Machine (RFC4137) */
+/* Most of variables are described in the part 6 of the RFC 4137 */
+/* */
+struct eap_state_machine
+{
+ /*Local state Machine Variables*/
+
+ /* Long-Term (Maintained between Packets) */
+ eap_type currentMethod;
+ u32 currentVendor;
+ int currentId;
+ int lastId;
+ void * methodData;
+ struct plugin *selectedMethod;
+ u8 NAKproposedMethods[251];
+
+ eap_method_state methodState;
+
+ struct eap_user user;
+
+ /* Short-Term (Not Maintained between exchanged Diameter EAP messages)*/
+ boolean rxResp;
+ int respId;
+ eap_type respMethod;
+ int respVendorMethod;
+ u32 respVendor;
+ decision sm_decision;
+ enum
+ {
+ EAP_INITIALIZE,
+ EAP_PICK_UP_METHOD,
+ EAP_IDLE,
+ EAP_RECEIVED,
+ EAP_SEND_REQUEST,
+ EAP_INTEGRITY_CHECK,
+ EAP_METHOD_REQUEST,
+ EAP_METHOD_RESPONSE,
+ EAP_PROPOSE_METHOD,
+ EAP_NAK,
+ EAP_SELECT_ACTION,
+ EAP_END,
+ EAP_DISCARD
+ } eap_state;
+
+};
+
+
+
+#endif /* LIBDIAMEAP_H_ */
diff --git a/extensions/app_diameap/plugins.h b/extensions/app_diameap/plugins.h
new file mode 100644
index 0000000..edf92e5
--- /dev/null
+++ b/extensions/app_diameap/plugins.h
@@ -0,0 +1,82 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+#ifndef _PLUGINS_H
+#define _PLUGINS_H
+
+#include "libdiameap.h"
+#include "libcrypt.h"
+
+
+
+
+/* Macro that define the register functions of an EAP method */
+#define REGISTER_METHOD(_methodName, _configFunction, _initFunction, _initPickUpFunction, _buildReqFunction, _getTimeoutFunction, _checkFunction, _processFunction, _isDoneFunction, _getKeyFunction, _unregisterFunction, _datafreeFunction ) \
+static struct register_plugin *registerplugin = NULL; \
+static int isregistered = 0; \
+int diameap_plugin_register() { \
+ if (!isregistered){ \
+ registerplugin = malloc (sizeof(struct register_plugin)); \
+ if(registerplugin==NULL) \
+ fprintf(stderr,"[DiamEAP extension] Error in registering plug-in\t%s\n",strerror(errno)); \
+ memset(registerplugin, 0, sizeof(struct register_plugin)); \
+ if(_configFunction) registerplugin->configure=_configFunction; \
+ if(_initFunction) registerplugin->init=_initFunction; \
+ if(_initPickUpFunction) registerplugin->initPickUp=_initPickUpFunction; \
+ if(_buildReqFunction) registerplugin->buildReq=_buildReqFunction; \
+ if(_getTimeoutFunction) registerplugin->getTimeout=_getTimeoutFunction; \
+ if(_checkFunction) registerplugin->check=_checkFunction; \
+ if(_processFunction) registerplugin->process=_processFunction; \
+ if(_isDoneFunction) registerplugin->isDone=_isDoneFunction; \
+ if(_getKeyFunction) registerplugin->getKey=_getKeyFunction; \
+ if(_unregisterFunction) registerplugin->unregister=_unregisterFunction; \
+ if(_datafreeFunction) registerplugin->datafree=_datafreeFunction; \
+ isregistered++; \
+ }else{ \
+ fprintf(stderr, "Cannot register the " _methodName " plugin twice\n"); \
+ return EINVAL; \
+ } \
+ return 0; \
+ } \
+int diameap_plugin_objects(struct register_plugin ** rplugin){ \
+*rplugin=registerplugin; \
+return 0; \
+} \
+
+
+#endif /*_PLUGINS_H*/
diff --git a/extensions/app_diameap/plugins/CMakeLists.txt b/extensions/app_diameap/plugins/CMakeLists.txt
new file mode 100644
index 0000000..5b36611
--- /dev/null
+++ b/extensions/app_diameap/plugins/CMakeLists.txt
@@ -0,0 +1,34 @@
+PROJECT("EAP Methods Plugins" C)
+
+MACRO(EAP_ADD_METHOD METHNAME)
+ ADD_LIBRARY(${METHNAME} MODULE ${ARGN})
+ SET_TARGET_PROPERTIES(${METHNAME} PROPERTIES PREFIX "" )
+ SET_TARGET_PROPERTIES(${METHNAME} PROPERTIES SUFFIX ".emp" )
+ INSTALL(TARGETS ${METHNAME}
+ LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+ COMPONENT freeDiameter-eap-server)
+ENDMACRO(EAP_ADD_METHOD)
+
+# Use the macro FD_EAP_PLUGIN(extmacroname subdir descr default) to
+# add a new extension subdirectory.
+MACRO(FD_EAP_PLUGIN EXTSUBDIR EXTDESCR EXTDEFAULT)
+ STRING(TOUPPER ${EXTSUBDIR} EXTMACRONAME)
+ IF (NOT ALL_EXTENSIONS)
+ OPTION(BUILD_${EXTMACRONAME} ${EXTDESCR} ${EXTDEFAULT})
+ ENDIF (NOT ALL_EXTENSIONS)
+ IF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+ ADD_SUBDIRECTORY(${EXTSUBDIR})
+ ENDIF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+ENDMACRO(FD_EAP_PLUGIN)
+
+###########################
+# EAP Methods Plugins Section
+
+# EAP Identity plugin
+FD_EAP_PLUGIN(eap_identity "Build EAP Identity Plugin " ON)
+
+# EAP MD5 plugin
+FD_EAP_PLUGIN(eap_md5 "Build EAP-MD5 Plugin " OFF)
+
+# EAP TLS plugin
+FD_EAP_PLUGIN(eap_tls "Build EAP-TLS Plugin " OFF)
diff --git a/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt b/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt
new file mode 100644
index 0000000..45f469f
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_identity/CMakeLists.txt
@@ -0,0 +1,4 @@
+# EAP Identity plugin
+PROJECT("EAP Identity Plugin" C)
+
+EAP_ADD_METHOD(eap_identity eap_identity.c)
diff --git a/extensions/app_diameap/plugins/eap_identity/eap_identity.c b/extensions/app_diameap/plugins/eap_identity/eap_identity.c
new file mode 100644
index 0000000..e736f9d
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_identity/eap_identity.c
@@ -0,0 +1,177 @@
+/*****************************************************************************************************
+ * 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 "../../plugins.h"
+
+struct identity_data
+{
+ enum
+ {
+ IDENTITY_CONTINUE, IDENTITY_SUCCESS, IDENTITY_FAILURE
+ } state;
+};
+
+int identity_init(struct eap_state_machine *smd);
+int identity_initPickUp(struct eap_state_machine *smd);
+int identity_buildReq(struct eap_state_machine *smd, u8 identity, struct eap_packet * eapPacket);
+boolean identity_check(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+int identity_process(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+boolean identity_isDone(struct eap_state_machine *smd);
+void identity_free(void * data);
+
+REGISTER_METHOD("identity", NULL, "identity_init", "identity_initPickUp", "identity_buildReq", NULL, "identity_check", "identity_process", "identity_isDone", NULL, NULL, "identity_free");
+
+
+int identity_init(struct eap_state_machine *smd)
+{
+ struct identity_data *data = NULL;
+ CHECK_MALLOC(data = malloc(sizeof(struct identity_data)));
+ memset(data, 0, sizeof(struct identity_data));
+ data->state = IDENTITY_CONTINUE;
+ smd->methodData = (struct identity_data*) data;
+
+ return 0;
+}
+
+int identity_initPickUp(struct eap_state_machine *smd)
+{
+ struct identity_data *data = NULL;
+ CHECK_MALLOC(data = malloc(sizeof(struct identity_data)));
+ memset(data, 0, sizeof(struct identity_data));
+ data->state = IDENTITY_CONTINUE;
+ smd->methodData = (struct identity_data*) data;
+ return 0;
+}
+
+int identity_buildReq(struct eap_state_machine *smd, u8 identity, struct eap_packet * eapPacket)
+{
+
+ CHECK_FCT(diameap_eap_new(EAP_REQUEST, identity, TYPE_IDENTITY, NULL, 0,eapPacket));
+ return 0;
+
+}
+
+
+boolean identity_check(struct eap_state_machine *smd, struct eap_packet *eapPacket)
+{
+
+ if (eapPacket->data == NULL)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Empty EAP packet received.",DIAMEAP_EXTENSION);
+ return FALSE;
+ }
+ eap_type type;
+ if(diameap_eap_get_type(eapPacket,&type)!=0){
+ return FALSE;
+ }
+ if (type == TYPE_IDENTITY)
+ {
+ u16 length;
+ CHECK_FCT(diameap_eap_get_length(eapPacket,&length));
+ if ((int)length < 6)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+ return FALSE;
+ }
+ if ((int)length > 1020)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP Identity plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int identity_process(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+ struct identity_data * data;
+ u16 length;
+ char * user;
+ u8 * Respdata;
+ int len,ret;
+
+ CHECK_FCT(diameap_eap_get_length(eapRespData,&length));
+ data = (struct identity_data*) smd->methodData;
+
+ CHECK_MALLOC(user=malloc(sizeof(char)*((int)length-4)));
+
+ diameap_eap_get_data(eapRespData,&Respdata,&len);
+ if(Respdata==NULL){
+ data->state = IDENTITY_FAILURE;
+ goto end;
+ }
+ U8COPY((u8 *)user,0,len,Respdata);
+ user[length-5]='\0';
+ if(check_user_identity == FALSE){
+ ret=diameap_get_eap_user(&(smd->user),"Default User");
+ CHECK_MALLOC_DO(smd->user.userid=realloc(smd->user.userid,strlen(user)+1),{ret = 1; goto next;});
+ memcpy(smd->user.userid,user,strlen(user)+1);
+ smd->user.useridLength = strlen(user);
+ } else {
+ ret=diameap_get_eap_user(&(smd->user),user);
+ }
+next:
+ if(ret==0)
+ {
+ smd->user.methodId = -1;
+ data->state = IDENTITY_SUCCESS;
+ }else{
+ data->state = IDENTITY_FAILURE;
+ }
+end:
+ smd->methodData = data;
+ free(user);
+ user=NULL;
+ return 0;
+}
+
+boolean identity_isDone(struct eap_state_machine *smd)
+{
+ struct identity_data *data;
+ data = (struct identity_data*) smd->methodData;
+ if (data->state != IDENTITY_CONTINUE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void identity_free(void * data)
+{
+ free(data);
+ data=NULL;
+}
diff --git a/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt b/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt
new file mode 100644
index 0000000..1c0253b
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_md5/CMakeLists.txt
@@ -0,0 +1,4 @@
+# EAP MD5 Plugin
+PROJECT("EAP MD5 Plugin" C)
+
+EAP_ADD_METHOD(eap_md5 eap_md5.c)
diff --git a/extensions/app_diameap/plugins/eap_md5/eap_md5.c b/extensions/app_diameap/plugins/eap_md5/eap_md5.c
new file mode 100644
index 0000000..d21c9ce
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_md5/eap_md5.c
@@ -0,0 +1,200 @@
+/*****************************************************************************************************
+ * 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 "../../plugins.h"
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+
+#define CHALLENGE_LEN 16
+
+struct eap_md5_data
+{
+ enum
+ {
+ EAP_MD5_CONTINUE, EAP_MD5_SUCCESS, EAP_MD5_FAILURE
+ } state;
+ u8 * challenge;
+};
+
+int eap_md5_configure(char * configfile);
+int eap_md5_init(struct eap_state_machine *smd);
+int eap_md5_initPickUp(struct eap_state_machine *smd);
+int eap_md5_buildReq(struct eap_state_machine *smd, u8 eap_md5,
+ struct eap_packet * eapPacket);
+boolean eap_md5_check(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+int eap_md5_process(struct eap_state_machine *smd, struct eap_packet *eapRespData);
+boolean eap_md5_isDone(struct eap_state_machine *smd);
+void eap_md5_free(void * data);
+
+REGISTER_METHOD("eap_md5", "eap_md5_configure", "eap_md5_init", "eap_md5_initPickUp", "eap_md5_buildReq", NULL, "eap_md5_check", "eap_md5_process", "eap_md5_isDone", NULL, NULL, "eap_md5_free")
+;
+
+int eap_md5_configure(char * configfile)
+{
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+
+ return 0;
+}
+
+int eap_md5_init(struct eap_state_machine *smd)
+{
+ struct eap_md5_data *data = NULL;
+ CHECK_MALLOC(data = malloc(sizeof(struct eap_md5_data)));
+ memset(data, 0, sizeof(struct eap_md5_data));
+ data->state = EAP_MD5_CONTINUE;
+ data->challenge = NULL;
+ smd->methodData = (struct eap_md5_data*) data;
+ return 0;
+}
+
+
+int eap_md5_buildReq(struct eap_state_machine *smd, u8 id,
+ struct eap_packet * eapPacket)
+{
+ struct eap_md5_data * data;
+ u8 *payload, *challenge;
+
+ data = (struct eap_md5_data *) smd->methodData;
+ CHECK_MALLOC( challenge=malloc(sizeof(u8)*CHALLENGE_LEN));
+ CHECK_MALLOC( payload=malloc(sizeof(u8)*(CHALLENGE_LEN+1)));
+ memset(payload, 0, sizeof(u8) * (CHALLENGE_LEN + 1));
+
+ gcry_create_nonce(challenge,CHALLENGE_LEN);
+ U8COPY(payload, 1, CHALLENGE_LEN, challenge);
+ payload[0] = (u8) CHALLENGE_LEN;
+ CHECK_FCT(diameap_eap_new(EAP_REQUEST, id, TYPE_EAP_MD5, payload, CHALLENGE_LEN
+ + 1,eapPacket));
+ CHECK_MALLOC(data->challenge=realloc(data->challenge,sizeof(u8)*CHALLENGE_LEN));
+ U8COPY(data->challenge,0,CHALLENGE_LEN,challenge);
+
+ smd->methodData = data;
+
+ free(challenge);
+ challenge=NULL;
+ free(payload);
+ payload=NULL;
+
+ return 0;
+}
+
+
+boolean eap_md5_check(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+ eap_type type;
+ if(diameap_eap_get_type(eapRespData,&type)!=0){
+ return FALSE;
+ }
+ if (type == TYPE_EAP_MD5)
+ {
+ u16 length;
+ CHECK_FCT(diameap_eap_get_length(eapRespData,&length));
+ if ((int) length < 6)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP MD5 plugin] Incorrect EAP packet received (length = %d ).",DIAMEAP_EXTENSION,length);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+int eap_md5_process(struct eap_state_machine *smd, struct eap_packet *eapRespData)
+{
+
+ struct eap_md5_data * data;
+ int wordlen = 0, i = 0;
+ u8 * word, *hash, id;
+ data = (struct eap_md5_data*) smd->methodData;
+ wordlen = 1 + smd->user.passwordLength + CHALLENGE_LEN;
+ CHECK_MALLOC(word = malloc(sizeof(u8)*wordlen));
+ memset(word, 0, sizeof(u8) * wordlen);
+ CHECK_FCT(diameap_eap_get_identifier(eapRespData,&id));
+ *word = id;
+ U8COPY(word,1,smd->user.passwordLength,smd->user.password);
+ U8COPY(word,1+smd->user.passwordLength,CHALLENGE_LEN,data->challenge);
+ CHECK_MALLOC(hash = malloc(sizeof(u8)*16));
+
+ md5hash(word, wordlen, hash);
+
+
+ for (i = 0; i < CHALLENGE_LEN; i++)
+ {
+ if (G8(hash + i) != G8(eapRespData->data + 6 + i))
+ {
+ data->state = EAP_MD5_FAILURE;
+ }
+ }
+
+ if (data->state != EAP_MD5_FAILURE)
+ {
+ data->state = EAP_MD5_SUCCESS;
+ smd->user.success = TRUE;
+ }
+
+ smd->methodData = data;
+ free(hash);
+ hash=NULL;
+ free(word);
+ word=NULL;
+ return 0;
+}
+
+boolean eap_md5_isDone(struct eap_state_machine *smd)
+{
+ struct eap_md5_data *data;
+ data = (struct eap_md5_data*) smd->methodData;
+ if (data->state != EAP_MD5_CONTINUE)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void eap_md5_free(void * mdata)
+{
+ struct eap_md5_data *data;
+ data = (struct eap_md5_data*) mdata;
+ free(data->challenge);
+ data->challenge=NULL;
+ free(data);
+ data=NULL;
+}
diff --git a/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt b/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt
new file mode 100644
index 0000000..023d134
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/CMakeLists.txt
@@ -0,0 +1,18 @@
+# The EAP-TLS Plugin
+PROJECT("EAP-TLS Plugin" C)
+
+# Parser for the configuration file
+BISON_FILE(eaptls.y)
+FLEX_FILE(eaptls.l)
+
+SET_SOURCE_FILES_PROPERTIES(lex.eaptls.c eaptls.tab.c PROPERTIES COMPILE_FLAGS "-I \"${CMAKE_CURRENT_SOURCE_DIR}\"")
+
+EAP_ADD_METHOD(eap_tls
+ eap_tls.c
+ eap_tls.h
+ lex.eaptls.c
+ eaptls.tab.c
+ eaptls.tab.h
+ )
+
+TARGET_LINK_LIBRARIES(eap_tls ${GNUTLS_LIBRARIES})
diff --git a/extensions/app_diameap/plugins/eap_tls/eap_tls.c b/extensions/app_diameap/plugins/eap_tls/eap_tls.c
new file mode 100644
index 0000000..6b812dd
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eap_tls.c
@@ -0,0 +1,426 @@
+/*****************************************************************************************************
+ * 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 "eap_tls.h"
+
+int eap_tls_configure(char * configfile);
+int eap_tls_init(struct eap_state_machine *smd);
+int eap_tls_initPickUp(struct eap_state_machine *smd);
+int eap_tls_buildReq(struct eap_state_machine *smd, u8 eap_md5,
+ struct eap_packet * eapPacket);
+int eap_tls_getTimeout(struct eap_state_machine *smd, int * timeout);
+boolean eap_tls_check(struct eap_state_machine *smd,
+ struct eap_packet *eapRespData);
+int eap_tls_process(struct eap_state_machine *smd,
+ struct eap_packet *eapRespData);
+boolean eap_tls_isDone(struct eap_state_machine *smd);
+int eap_tls_getKey(struct eap_state_machine *smd, u8** msk, int * msklen, u8** emsk, int * emsklen);
+void eap_tls_unregister(void);
+void eap_tls_free(void * data);
+
+REGISTER_METHOD("eap_tls", "eap_tls_configure", "eap_tls_init", "eap_tls_initPickUp", "eap_tls_buildReq", "eap_tls_getTimeout", "eap_tls_check", "eap_tls_process", "eap_tls_isDone", "eap_tls_getKey", "eap_tls_unregister", "eap_tls_free")
+;
+
+int eap_tls_configure(char * configfile)
+{
+ int ret;
+ extern FILE * eaptlsin;
+
+ if (configfile)
+ {
+ tls_global_conf.conffile = configfile;
+ }
+ tls_global_conf.certfile = NULL;
+ tls_global_conf.keyfile = NULL;
+ tls_global_conf.cafile = NULL;
+ tls_global_conf.crlfile = NULL;
+ tls_global_conf.check_cert_cn_username = FALSE;
+
+ /*Parse EAP TLS configuration file */
+ eaptlsin = fopen(tls_global_conf.conffile, "r");
+ if (!eaptlsin)
+ {
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open configuration file %s for reading: %s",DIAMEAP_EXTENSION, tls_global_conf.conffile, strerror(errno));
+ return errno;
+ }
+
+ /* call yacc parser */
+ CHECK_FCT(eaptlsparse(&tls_global_conf));
+
+
+ tls_global_conf.max_size = 64*1024 /* As per RFC 5216 recommendation */;
+
+ /* Initializing GnuTLS library */
+ ret = diameap_tls_init(&tls_global_conf);
+
+ return ret;
+}
+
+int eap_tls_init(struct eap_state_machine *smd)
+{
+ int ret;
+ struct tls_data *data = NULL;
+ CHECK_MALLOC(data = malloc(sizeof(struct tls_data)));
+ memset(data, 0, sizeof(struct tls_data));
+ CHECK_FCT(diameap_tls_initialize(data));
+ ret = diameap_tls_init_session(&tls_global_conf, data);
+
+ smd->methodData = (struct tls_data*) data;
+ if (ret < 0)
+ {
+ return ret;
+ }
+ return 0;
+}
+
+int eap_tls_initPickUp(struct eap_state_machine *smd)
+{
+ return 0;
+}
+
+int eap_tls_buildReq(struct eap_state_machine *smd, u8 id,
+ struct eap_packet * eapPacket)
+{
+ struct tls_data * data;
+ data = (struct tls_data *) smd->methodData;
+
+ if (data->more_toreceive == TRUE)
+ {
+ CHECK_FCT(diameap_eap_tls_buildReq_ack(id,eapPacket));
+ return 0;
+ }
+
+ if (data->state == START)
+ {
+ CHECK_FCT(diameap_eap_tls_buildReq_start(id,eapPacket));
+ return 0;
+ }
+
+ if (data->state == CONTINUE)
+ {
+ diameap_eap_tls_buildReq_data(data, id, eapPacket);
+
+ smd->methodData = (struct tls_data*) data;
+ return 0;
+ }
+
+ return 0;
+}
+
+int eap_tls_getTimeout(struct eap_state_machine *smd, int * timeout)
+{
+ return 0;
+}
+
+boolean eap_tls_check(struct eap_state_machine *smd,
+ struct eap_packet *eapRespData)
+{
+ eap_type type;
+ if(diameap_eap_get_type(eapRespData,&type)!=0){
+ goto cf;
+ }
+ if (type == TYPE_EAP_TLS)
+ {
+ return TRUE;
+ }
+cf:
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] EAP-TLS check failed: Received EAP packet with different EAP-Type (Type = %d)",DIAMEAP_EXTENSION, type);
+ return FALSE;
+}
+
+int eap_tls_process(struct eap_state_machine *smd,
+ struct eap_packet *eapRespData)
+{
+ struct tls_data * data;
+ data = (struct tls_data *) smd->methodData;
+ struct tls_msg tlsmsg;
+ CHECK_FCT(diameap_eap_tls_parse(&tlsmsg,eapRespData));
+
+ if ((tlsmsg.datalength == 0))
+ {
+ if (data->more_tosend_length > 0)
+ {
+ //ACK and more to send
+ return 0;
+ }
+ else
+ {
+ //Success
+ if (data->handshake == TRUE)
+ {
+ data->state = SUCCESS;
+ smd->user.success = TRUE;
+
+ if(tls_global_conf.check_cert_cn_username == TRUE){
+ unsigned int list_size;
+ const gnutls_datum_t * list = gnutls_certificate_get_peers (data->session, &list_size);
+ if(list_size<1){
+ goto failure;
+ }
+
+ gnutls_x509_crt_t cert;
+
+ CHECK_GNUTLS_DO(gnutls_x509_crt_init(&cert),{
+ TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error in initialization crt init",DIAMEAP_EXTENSION);
+ goto failure;});
+
+ CHECK_GNUTLS_DO(gnutls_x509_crt_import(cert, &list[0], GNUTLS_X509_FMT_DER), {
+ TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error parsing certificate",DIAMEAP_EXTENSION);
+ goto failure;});
+
+ void * buff;
+ size_t size_buffer;
+ int ret;
+ ret = gnutls_x509_crt_get_dn_by_oid(cert,GNUTLS_OID_X520_COMMON_NAME,0,0,NULL,&size_buffer);
+ if( ret != GNUTLS_E_SHORT_MEMORY_BUFFER){
+ CHECK_GNUTLS_DO(ret,{
+ TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error get dn by oid",DIAMEAP_EXTENSION);
+ goto failure;});
+ }
+
+ CHECK_MALLOC_DO(buff=malloc(size_buffer), goto failure);
+
+ CHECK_GNUTLS_DO(gnutls_x509_crt_get_dn_by_oid(cert,GNUTLS_OID_X520_COMMON_NAME,0,0,buff,&size_buffer),{
+ TRACE_DEBUG(NONE,"%s[EAP TLS plugin] [GnuTLS] error get dn by oid",DIAMEAP_EXTENSION);
+ goto failure;});
+
+ if(strncmp((char *)smd->user.userid,buff,smd->user.useridLength)!=0){
+ goto failure;
+ }
+
+ gnutls_x509_crt_deinit(cert);
+ goto next;
+
+ failure:
+ TRACE_DEBUG(NONE,"%s[EAP TLS plugin] Checking failed. certificate's CN does not match User_Name AVP value.",DIAMEAP_EXTENSION);
+ data->state = FAILURE;
+ smd->user.success = FALSE;
+ gnutls_x509_crt_deinit(cert);
+ }
+
+ next:
+ smd->methodData = (struct tls_data*) data;
+ return 0;
+
+ }
+
+ return 0;
+ }
+
+ }
+
+ if (data->more_toreceive == TRUE)
+ {
+ //reassemble received fragment to TLS Response
+ CHECK_FCT(diameap_tls_reassemble(&data->tlsResp,tlsmsg));
+ }
+ else
+ {
+ //receive the first fragment or a complete TLS message
+ CHECK_FCT(diameap_tls_copy(&data->tlsResp,tlsmsg));
+ }
+
+ if (tlsmsg.flags & TLS_FLAG_MORE)
+ {
+ data->more_toreceive = TRUE;
+ smd->methodData = (struct tls_data*) data;
+ return 0;
+ }
+ else
+ {
+ //last fragment received
+ data->more_toreceive = FALSE;
+ }
+ data->state = CONTINUE;
+ diameap_tls_process_receive(data);
+
+ if (data->state == SUCCESS)
+ {
+ smd->user.success = TRUE;
+ }
+ smd->methodData = (struct tls_data*) data;
+ return 0;
+}
+
+boolean eap_tls_isDone(struct eap_state_machine *smd)
+{
+ struct tls_data * data;
+ data = (struct tls_data *) smd->methodData;
+ if (data->state == CONTINUE || data->state == START)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int eap_tls_getKey(struct eap_state_machine *smd, u8 ** msk, int *msklen, u8 ** emsk, int *emsklen)
+{
+ struct tls_data * data;
+ int len = emsk ? 128 : 64;
+ data = (struct tls_data *) smd->methodData;
+ *msk = malloc(len);
+ if (gnutls_prf(data->session, strlen("client EAP encryption"),
+ "client EAP encryption", 0, 0, NULL, len, (char *) *msk)
+ != GNUTLS_E_SUCCESS)
+ {
+ free(*msk);
+ *msk = NULL;
+ *msklen = 0;
+ return 1;
+ }
+ else
+ {
+ *msklen = 64;
+ }
+ if (emsk) {
+ *emsk = malloc(64);
+ memcpy(*emsk, (*msk)+64, 64);
+ memset((*msk)+64, 0, 64);
+ *emsklen = 64;
+ }
+
+ return 0;
+}
+
+void eap_tls_unregister(void)
+{
+ //
+}
+
+void eap_tls_free(void * mdata)
+{
+ struct tls_data *data;
+ data = (struct tls_data*) mdata;
+ gnutls_deinit(data->session);
+ if(data->tlsReq.data){
+ free(data->tlsReq.data);
+ data->tlsReq.data=NULL;
+ }
+ if(data->tlsResp.data){
+ free(data->tlsResp.data);
+ data->tlsResp.data=NULL;
+ }
+ free(data);
+ data=NULL;
+}
+
+//send TLS ACK Request (empty TLS msg)
+int diameap_eap_tls_buildReq_ack(u8 id, struct eap_packet * eapPacket)
+{
+ u8* payload;
+ struct tls_msg tlsmsg;
+ int len;
+ CHECK_FCT(diameap_tls_new(&tlsmsg));
+ CHECK_FCT(diameap_tls_new_tls_packet(&payload,&len,tlsmsg));
+ CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,payload,len,eapPacket));
+ return 0;
+}
+
+// parse EAP TLS msg
+int diameap_eap_tls_parse(struct tls_msg * tlsmsg, struct eap_packet *eapPacket)
+{
+ u8 *datatls;
+ int len;
+
+ //initialize a new empty EAP TLS msg
+ diameap_tls_new(tlsmsg);
+ //retrieve the data field from EAP Packet
+ diameap_eap_get_data(eapPacket, &datatls, &len);
+ //parse EAP TLS msg
+ diameap_tls_parse(datatls, len, tlsmsg);
+ return 0;
+}
+
+int diameap_eap_tls_buildReq_start(u8 id, struct eap_packet * eapPacket)
+{
+ u8* payload;
+ struct tls_msg tlsmsg;
+ int len;
+ CHECK_FCT(diameap_tls_new(&tlsmsg));
+ CHECK_FCT(diameap_tls_set_flags(&tlsmsg,TLS_FLAG_START));
+ CHECK_FCT(diameap_tls_new_tls_packet(&payload,&len,tlsmsg));
+ CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,payload,len,eapPacket));
+ return 0;
+}
+
+int diameap_eap_tls_buildReq_data(struct tls_data * data, int id,
+ struct eap_packet * eapPacket)
+{
+ struct tls_msg tlsmsg;
+ u8* datatosend;
+ u8 * eaptls_data;
+ int length = 0;
+
+ diameap_tls_new(&tlsmsg);
+
+ if (data->more_tosend_length == 0)
+ {
+ //First fragment of message or the only fragment of message
+ data->more_tosend_length = data->tlsReq.datalength;
+ }
+ if (data->more_tosend_length > tls_global_conf.max_size)
+ {
+ //New fragment of message. Is not the last fragment.
+ length = tls_global_conf.max_size;
+ CHECK_FCT(diameap_tls_set_flags(&tlsmsg,TLS_FLAG_MORE));
+ if (data->more_tosend_length == data->tlsReq.datalength)
+ {
+ //The first fragment of message
+ CHECK_FCT(diameap_tls_set_message_length(&tlsmsg,data->tlsReq.datalength));//set L flag and length value
+ }
+ }
+ else
+ {
+ //The last fragment or the only fragment.
+ length = data->more_tosend_length;
+ }
+
+ datatosend = malloc(sizeof(u8) * length);
+ U8COPY(datatosend,0,length,data->tlsReq.data+(data->tlsReq.datalength-data->more_tosend_length));
+ data->more_tosend_length -= length;
+ CHECK_FCT(diameap_tls_set_data(&tlsmsg,datatosend,length));
+
+ CHECK_FCT(diameap_tls_new_tls_packet(&eaptls_data,&length,tlsmsg));
+ CHECK_FCT(diameap_eap_new(EAP_REQUEST,id,TYPE_EAP_TLS,eaptls_data,length,eapPacket));
+
+ if (data->more_tosend_length == 0)
+ {
+ diameap_tls_new(&data->tlsReq);
+ }
+ return 0;
+}
diff --git a/extensions/app_diameap/plugins/eap_tls/eap_tls.h b/extensions/app_diameap/plugins/eap_tls/eap_tls.h
new file mode 100644
index 0000000..400f3d9
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eap_tls.h
@@ -0,0 +1,51 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+#ifndef EAP_TLS_H_
+#define EAP_TLS_H_
+
+#include "../../plugins.h"
+
+struct tls_config tls_global_conf;
+
+int diameap_eap_tls_buildReq_ack(u8 id, struct eap_packet * eapPacket);
+int diameap_eap_tls_buildReq_start(u8 id, struct eap_packet * eapPacket);
+int diameap_eap_tls_buildReq_data(struct tls_data * data,int id,struct eap_packet * eapPacket);
+int diameap_eap_tls_parse(struct tls_msg * eaptls,struct eap_packet *eapPacket);
+int eaptlsparse(struct tls_config * conf);
+
+#endif /* EAP_TLS_H_ */
diff --git a/extensions/app_diameap/plugins/eap_tls/eaptls.l b/extensions/app_diameap/plugins/eap_tls/eaptls.l
new file mode 100644
index 0000000..7689333
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eaptls.l
@@ -0,0 +1,119 @@
+/*****************************************************************************************************
+ * 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.
+ *****************************************************************************************************/
+
+
+/*Declarations and option settings*/
+%{
+#include <stdio.h>
+#include "eap_tls.h"
+#include "eaptls.tab.h"
+
+#define YY_USER_ACTION { \
+ yylloc->first_line = yylloc->last_line = yylineno; \
+ yylloc->first_column = yylloc->last_column + 1; \
+ yylloc->last_column += yyleng +1; \
+ }
+
+#define YY_NO_INPUT
+%}
+
+%option noyywrap
+%option yylineno
+%option bison-bridge
+%option bison-locations
+%option nounput
+%%
+ /* List of patterns and actions */
+
+<*>\n {
+ yylloc->last_column=0;
+ }
+
+
+<*>#.*$ {}
+
+
+[ \t\n]+ {
+ yylloc->last_column=0;
+ }
+
+\"([^\n\"]*)\" { /* Quoted String */
+ yylval->str = strdup(yytext+1);
+ yylval->str[yyleng-2]='\0';
+ return iSTRING;
+ }
+
+
+[[:digit:]]+ { /* Digital number */
+ yylval->val = atoi(yytext);
+ return NUM; /* Numeric value */
+ }
+
+(?i:"Cred") {
+ return CERTS;
+ }
+
+(?i:"CA") {
+ return CAPATH;
+ }
+
+(?i:"CRL") {
+ return CRLPATH;
+ }
+
+(?i:"check_cert_cn_username") {
+ return CHECK_CN_USERNAME;
+ }
+
+
+
+"="|";"|":"|"," { /* Single characters for yyparse */
+ return yytext[0];
+ }
+
+ /* Unrecognized token or text */
+
+<*>[[:alnum:]]+ |
+<*>. {
+ fprintf(stderr,"Unrecognized input text '%s'( on line %i column %i )\n", yytext, yylloc->first_line, yylloc->first_column);
+ return LEX_ERROR;
+ }
+
+%%
+/* Routines */
+
+
diff --git a/extensions/app_diameap/plugins/eap_tls/eaptls.y b/extensions/app_diameap/plugins/eap_tls/eaptls.y
new file mode 100644
index 0000000..31559eb
--- /dev/null
+++ b/extensions/app_diameap/plugins/eap_tls/eaptls.y
@@ -0,0 +1,243 @@
+/*****************************************************************************************************
+ * 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 <stdio.h>
+#include "eap_tls.h"
+#include "eaptls.tab.h"
+
+void yyerror (YYLTYPE *llocp, struct tls_config * config, const char *s);
+
+extern int yywrap();
+extern int yylex();
+
+
+/* The Lex parser prototype */
+int eaptlslex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+
+%}
+
+%locations
+%parse-param {struct tls_config * config}
+%pure_parser
+/*%defines */
+%error-verbose
+%debug
+
+%union {
+ char *str;
+ int val;
+ char byte;
+}
+
+
+
+/* In case of error in the lexical analysis */
+%token LEX_ERROR
+
+%token <val> NUM
+
+%token <str> iSTRING
+
+%token <byte> iBYTE
+
+%token CERTS
+%token CAPATH
+%token CRLPATH
+%token CHECK_CN_USERNAME
+
+%%
+
+confparams : /* empty */
+ | confparams CERTS_files
+ | confparams CA_file
+ | confparams CRL_file
+ | confparams CHECK_CN_USERNAME_param
+ | confparams errors
+ {
+ return EINVAL;
+ }
+ ;
+
+errors : LEX_ERROR
+ | error
+ ;
+
+
+CERTS_files : CERTS '=' iSTRING ':' iSTRING ';'
+ {
+ char * certfile, *keyfile;
+ FILE * fl;
+
+ certfile = $3;
+ keyfile = $5;
+ if(certfile == NULL){
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] certificate file missing in configuration file",DIAMEAP_EXTENSION);
+ yyerror (&yylloc, config, "cert file missing");
+ YYERROR;
+ }
+ if(keyfile == NULL){
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] privateKey file missing in configuration file",DIAMEAP_EXTENSION);
+ yyerror (&yylloc, config, "privateKey file missing");
+ YYERROR;
+ }
+
+ fl = fopen(certfile, "r");
+ if ((fl == NULL) && (*certfile != '/')) {
+ char * tmpfile=certfile;
+ CHECK_MALLOC_DO( certfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(certfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+ free(tmpfile);
+ fl = fopen(certfile, "r");
+ }
+ if (fl == NULL) {
+ int ret = errno;
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open certificate file %s for reading: %s",DIAMEAP_EXTENSION,certfile,strerror(ret));
+ yyerror (&yylloc, config, "Error configuring certificate for EAP-TLS");
+ YYERROR;
+ }
+ fclose(fl);
+
+ fl = fopen(keyfile, "r");
+ if ((fl == NULL) && (*keyfile != '/')) {
+ char * tmpfile=keyfile;
+ CHECK_MALLOC_DO( keyfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(keyfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+ free(tmpfile);
+ fl = fopen(keyfile, "r");
+ }
+ if (fl == NULL) {
+ int ret = errno;
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open privateKey file %s for reading: %s",DIAMEAP_EXTENSION,keyfile,strerror(ret));
+ yyerror (&yylloc, config, "Error configuring privateKey for EAP-TLS");
+ YYERROR;
+ }
+ fclose(fl);
+
+ config->certfile = certfile;
+ config->keyfile = keyfile;
+ }
+ ;
+
+CA_file : CAPATH '=' iSTRING ';'
+ {
+ char * cafile;
+ FILE * fl;
+
+ cafile = $3;
+
+ if(cafile == NULL){
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] CA file missing in configuration file",DIAMEAP_EXTENSION);
+ yyerror (&yylloc, config, "cert file missing");
+ YYERROR;
+ }
+
+ fl = fopen(cafile, "r");
+ if ((fl == NULL) && (*cafile != '/')) {
+ char * tmpfile=cafile;
+ CHECK_MALLOC_DO( cafile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(cafile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+ free(tmpfile);
+ fl = fopen(cafile, "r");
+ }
+ if (fl == NULL) {
+ int ret = errno;
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open CA file %s for reading: %s",DIAMEAP_EXTENSION,cafile,strerror(ret));
+ yyerror (&yylloc, config, "Error configuring CA file for EAP-TLS");
+ YYERROR;
+ }
+ fclose(fl);
+ config->cafile=$3;
+ }
+ ;
+
+CRL_file : CRLPATH '=' iSTRING ';'
+ {
+ char * crlfile;
+ FILE * fl;
+
+ crlfile = $3;
+
+ if(crlfile == NULL){
+ TRACE_DEBUG(FULL+1,"%s[EAP TLS plugin] CRL file missing in configuration file",DIAMEAP_EXTENSION);
+
+ }else{
+
+ fl = fopen(crlfile, "r");
+ if ((fl == NULL) && (*crlfile != '/')) {
+ char * tmpfile=crlfile;
+ CHECK_MALLOC_DO( crlfile = malloc( strlen(tmpfile) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+ { yyerror (&yylloc, config, "Not enough memory"); YYERROR; } );
+ sprintf(crlfile, DEFAULT_EXTENSIONS_PATH "/%s", tmpfile);
+ free(tmpfile);
+ fl = fopen(crlfile, "r");
+ }
+ if (fl == NULL) {
+ int ret = errno;
+ TRACE_DEBUG(INFO,"%s[EAP TLS plugin] Unable to open CRL file %s for reading: %s",DIAMEAP_EXTENSION,crlfile,strerror(ret));
+ yyerror (&yylloc, config, "Error configuring CRL file for EAP-TLS");
+ YYERROR;
+ }
+ fclose(fl);
+ }
+ config->crlfile=$3;
+ }
+ ;
+
+CHECK_CN_USERNAME_param :
+ CHECK_CN_USERNAME '=' NUM ';'
+ {
+ if((int)$3 == 0){
+ config->check_cert_cn_username = FALSE;
+ }
+ else
+ {
+ config->check_cert_cn_username = TRUE;
+ }
+ }
+ ;
+
+%%
+
+void yyerror(YYLTYPE *llocp, struct tls_config * config,const char *str)
+{
+ fprintf(stderr,"Error in %s ( on line %i column %i -> line %i column %i) : %s\n",config->conffile, llocp->first_line, llocp->first_column, llocp->last_line, llocp->last_column, str);
+}