*
*/
-#include "eap.h"
+#include "rlm_eap.h"
static const char *eap_types[] = {
"",
* Load all the required eap authentication types.
* Get all the supported EAP-types from config file.
*/
-void eaptype_load(EAP_TYPES **type_list, const char *type_name, CONF_SECTION *cs)
+int eaptype_load(EAP_TYPES **type_list, const char *type_name, CONF_SECTION *cs)
{
EAP_TYPES **last, *node;
lt_dlhandle handle;
last = type_list;
for (node = *type_list; node != NULL; node = node->next) {
if (strcmp(node->typename, auth_type_name) == 0)
- return;
+ return 0;
last = &node->next;
}
handle = lt_dlopenext(auth_type_name);
if (handle == NULL) {
- radlog(L_ERR, "rlm_eap: Failed to link to type %s: %s\n", type_name, lt_dlerror());
- return;
+ radlog(L_ERR, "rlm_eap: Failed to link EAP-Type/%s: %s",
+ type_name, lt_dlerror());
+ return -1;
}
/* make room for auth type */
node = (EAP_TYPES *)malloc(sizeof(EAP_TYPES));
if (node == NULL) {
radlog(L_ERR, "rlm_eap: out of memory");
- return;
+ return -1;
}
/* fill in the structure */
if (node->typeid == 0) {
radlog(L_ERR, "rlm_eap: Invalid type name %s cannot be linked", type_name);
free(node);
- return;
+ return -1;
}
node->type = (EAP_TYPE *)lt_dlsym(node->handle, auth_type_name);
auth_type_name, type_name, lt_dlerror());
lt_dlclose(node->handle); /* ignore any errors */
free(node);
- return;
+ return -1;
}
if ((node->type->attach) &&
((node->type->attach)(node->cs, &(node->type_stuff)) < 0)) {
radlog(L_ERR, "rlm_eap: Failed to initialize the type %s", type_name);
lt_dlclose(node->handle);
free(node);
- return;
+ return -1;
}
radlog(L_INFO, "rlm_eap: Loaded and initialized the type %s", type_name);
*last = node;
- return;
+ return 0;
}
/*
}
eaptype = &handler->eap_ds->response->type;
- switch(eaptype->type) {
- case PW_EAP_IDENTITY:
+ switch(eaptype->type) {
+ case PW_EAP_IDENTITY:
if (eaptype_call(type, INITIATE, type_list, handler) == 0)
return EAP_INVALID;
- break;
+ break;
- case PW_EAP_NAK:
- /*
+ case PW_EAP_NAK:
+ /*
* It is invalid to request identity, notification & nak in nak
*/
- if ((eaptype->data != NULL) &&
- (eaptype->data[0] < PW_EAP_MD5)) {
- return EAP_INVALID;
- }
+ if ((eaptype->data != NULL) &&
+ (eaptype->data[0] < PW_EAP_MD5)) {
+ return EAP_INVALID;
+ }
switch (eaptype->data[0]) {
case PW_EAP_MD5:
case PW_EAP_TLS:
break;
}
break;
- case PW_EAP_MD5:
- case PW_EAP_OTP:
- case PW_EAP_GTC:
- case PW_EAP_TLS:
- default:
- radlog(L_INFO, "rlm_eap: EAP_TYPE - %s",
- eap_types[eaptype->type]);
- if (eaptype_call(eaptype->type, AUTHENTICATE,
- type_list, handler) == 0) {
- return EAP_INVALID;
- }
+ case PW_EAP_MD5:
+ case PW_EAP_OTP:
+ case PW_EAP_GTC:
+ case PW_EAP_TLS:
+ default:
+ radlog(L_INFO, "rlm_eap: EAP_TYPE - %s",
+ eap_types[eaptype->type]);
+ if (eaptype_call(eaptype->type, AUTHENTICATE,
+ type_list, handler) == 0) {
+ return EAP_INVALID;
+ }
break;
- }
+ }
return EAP_OK;
}
uint16_t len;
int total_len;
- vp_list = paircopy2(vps, PW_EAP_MESSAGE);
- if (vp_list == NULL) {
+ vp_list = paircopy2(vps, PW_EAP_MESSAGE);
+ if (vp_list == NULL) {
radlog(L_ERR, "rlm_eap: EAP_Message not found");
- return NULL;
+ return NULL;
}
/*
* Get the Actual length from the EAP packet
* First EAP-Message contains the EAP packet header
*/
- memcpy(&len, vp_list->strvalue+2, sizeof(uint16_t));
- len = ntohs(len);
+ memcpy(&len, vp_list->strvalue+2, sizeof(uint16_t));
+ len = ntohs(len);
eap_packet = (eap_packet_t *)malloc(len);
if (eap_packet == NULL) {
int eap_wireformat(EAP_PACKET *reply)
{
eap_packet_t *hdr;
- uint16_t total_length = 0;
+ uint16_t total_length = 0;
if (reply == NULL) return EAP_INVALID;
free(reply->type.data);
reply->type.data = reply->packet + EAP_HEADER_LEN + 1/*EAPtype*/;
}
- }
+ }
return EAP_VALID;
}
* If EAP exceeds 253, frame it in multiple EAP-Message attrs.
* Set the RADIUS reply codes based on EAP request codes
* Append any additonal VPs to RADIUS reply
- *
*/
int eap_compose(REQUEST *request, EAP_PACKET *reply)
{
- int len;
- uint16_t eap_len;
+ uint16_t eap_len, len;
VALUE_PAIR *eap_msg;
VALUE_PAIR *vp;
eap_packet_t *eap_packet;
- unsigned char *ptr;
+ unsigned char *ptr;
/*
- * Either use unique id or we can use the below to get id
- * good way is to use uniqe id, and not depend on any thing else
+ * Id is expected to be set by the EAP-Type, if not,
+ * currently RADIUS request Id is used.
+ * Ideally, a unique Id should be generated.
*/
if (reply->id == 0) reply->id = request->packet->id;
if (eap_wireformat(reply) == EAP_INVALID) {
- return EAP_VALID;
+ return EAP_INVALID;
}
eap_packet = (eap_packet_t *)reply->packet;
/* Set request reply code */
switch(reply->code) {
- case PW_EAP_SUCCESS:
- request->reply->code = PW_AUTHENTICATION_ACK;
- break;
- case PW_EAP_FAILURE:
- request->reply->code = PW_AUTHENTICATION_REJECT;
- break;
- case PW_EAP_REQUEST:
- request->reply->code = PW_ACCESS_CHALLENGE;
- break;
- case PW_EAP_RESPONSE:
- default:
- /* Should never enter here */
- radlog(L_ERR, "rlm_eap: reply code is unknown, Reject it.");
- request->reply->code = PW_AUTHENTICATION_REJECT;
- break;
+ case PW_EAP_SUCCESS:
+ request->reply->code = PW_AUTHENTICATION_ACK;
+ break;
+ case PW_EAP_FAILURE:
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+ break;
+ case PW_EAP_REQUEST:
+ request->reply->code = PW_ACCESS_CHALLENGE;
+ break;
+ case PW_EAP_RESPONSE:
+ default:
+ /* Should never enter here */
+ radlog(L_ERR, "rlm_eap: reply code is unknown, Reject it.");
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+ break;
}
return 0;
}
VALUE_PAIR *eap_msg;
EAP_DS *eapstart;
- eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);
- if (eap_msg == NULL) {
+ eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);
+ if (eap_msg == NULL) {
radlog(L_ERR, "rlm_eap: EAP-Message not found");
return EAP_NOOP;
}
- if (eap_msg->length != EAP_START) {
+ if (eap_msg->length != EAP_START) {
return EAP_NOTFOUND;
}
{
uint16_t len;
- memcpy(&len, eap_packet->length, sizeof(uint16_t));
- len = ntohs(len);
+ memcpy(&len, eap_packet->length, sizeof(uint16_t));
+ len = ntohs(len);
/* High level EAP packet checks */
- if ((len <= EAP_HEADER_LEN) ||
+ if ((len <= EAP_HEADER_LEN) ||
(eap_packet->code != PW_EAP_RESPONSE) ||
(eap_packet->data[0] <= 0) ||
(eap_packet->data[0] > PW_EAP_MAX_TYPES)) {
memcpy(&len, eap_packet->length, sizeof(uint16_t));
len = ntohs(len);
- eap_ds->response->length = len;
+ eap_ds->response->length = len;
/* First byte in eap_packet->data is *EAP-Type* */
/*
* The rest is TypeData
* skip *type* while getting typedata from data
*/
- typelen = len - 5/*code+id+length+type*/;
+ typelen = len - 5/*code+id+length+type*/;
if (typelen > 0) {
/*
* Since packet contians the complete eap_packet,
+/*
+ * eap.h Header file containing the interfaces for all EAP types.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
+ */
#ifndef _EAP_H
#define _EAP_H
-/*
- * TODO: This file needs cleanup.
- * Some local definitions & structures
- * should be removed from here.
- */
-#include <ltdl.h>
-
#include "conffile.h"
#include "libradius.h"
#include "radiusd.h"
-#include "modules.h"
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#include <string.h>
-#define EAP_START 2
-
#define PW_EAP_REQUEST 1
#define PW_EAP_RESPONSE 2
#define PW_EAP_SUCCESS 3
#define EAP_HEADER_LEN 4
-#define NAME_LEN 32
-
-
-enum {
- EAP_NOTFOUND, /* not found */
- EAP_FOUND, /* found, continue */
- EAP_OK, /* ok, continue */
- EAP_FAIL, /* failed, don't reply */
- EAP_NOOP, /* succeeded without doing anything */
- EAP_INVALID, /* invalid, don't reply */
- EAP_VALID /* valid, continue */
-};
-
/*
- * structure to represent packet format of eap
- */
-typedef struct eap_packet_t {
- unsigned char code;
- unsigned char id;
- unsigned char length[2];
- unsigned char data[1];
-} eap_packet_t;
-
-/*
- * Contains EAP-Type specific data
+ * EAP-Type specific data.
*/
typedef struct eaptype_t {
unsigned char type;
} eaptype_t;
/*
- * core data structure that is through out.
+ * Structure to hold EAP data.
*
* length = code + id + length + type + type.data
- * = 1 + 1 + 2 + 1 + X
+ * = 1 + 1 + 2 + 1 + X
*/
typedef struct eap_packet {
unsigned char code;
} EAP_PACKET;
/*
- * DS with all the required information
+ * EAP_DS contains all the received/sending information
+ * response = Received EAP packet
+ * request = Sending EAP packet
+ *
* Note: We are authentication server,
- * we get EAP-Response and we send
- * EAP-Request/EAP-success/EAP-failure
+ * we get ONLY EAP-Responses and
+ * we send EAP-Request/EAP-success/EAP-failure
*/
typedef struct eap_ds {
EAP_PACKET *response;
struct _eap_handler *next;
} EAP_HANDLER;
-/* Prototype to call eap sub mdoules */
+/*
+ * Interface to call EAP sub mdoules
+ */
typedef struct eap_type_t {
const char *name;
int (*attach)(CONF_SECTION *conf, void **type_arg);
int (*detach)(void **type_arg);
} EAP_TYPE;
-typedef enum operation_t {
- INITIATE = 0,
- AUTHENTICATE
-} operation_t;
-
-/*
- * Keep track of which sub modules we've loaded.
- */
-typedef struct eap_types_t {
- struct eap_types_t *next;
- int typeid;
- char typename[NAME_LEN];
- EAP_TYPE *type;
- lt_dlhandle handle;
- CONF_SECTION *cs;
- void *type_stuff;
-} EAP_TYPES;
-
-/*
- * currently this is not properly defined as
- * there is not much config stuff that eap depends on.
- */
-typedef struct eap_conf {
- char* default_eap_type;
- int timer_limit;
-} EAP_CONF;
-
-typedef struct rlm_eap_t {
- EAP_HANDLER *echolist;
- EAP_TYPES *typelist;
- EAP_CONF *conf;
-} rlm_eap_t;
-
-/* define the functions */
-
-/* EAP-Type */
-EAP_TYPES *eaptype_byid(EAP_TYPES **list, int type);
-EAP_TYPES *eaptype_byname(EAP_TYPES **list, const char *name);
-void eaptype_load(EAP_TYPES **tl, const char *tname, CONF_SECTION *cs);
-int eaptype_select(EAP_TYPES *tl, EAP_HANDLER *h, char *eaptype);
-int eaptype_call(int type, operation_t action,
- EAP_TYPES *tl, EAP_HANDLER *h);
-void eaptype_freelist(EAP_TYPES **tl);
-
-
-/* EAP */
-int eap_start(REQUEST *request);
-void eap_fail(REQUEST *request, EAP_PACKET *reply);
-void eap_success(REQUEST *request, EAP_PACKET *reply);
-int eap_validation(eap_packet_t *eap_msg);
-int eap_wireformat(EAP_PACKET *packet);
-int eap_compose(REQUEST *request, EAP_PACKET *reply);
-eap_packet_t *eap_attribute(VALUE_PAIR *vps);
-EAP_DS *eap_buildds(eap_packet_t **eap_msg);
-EAP_HANDLER *eap_handler(EAP_HANDLER **list, eap_packet_t **eap_msg, REQUEST *request);
-char *eap_identity(eap_packet_t *eap_packet);
-VALUE_PAIR *eap_useridentity(EAP_HANDLER *list, eap_packet_t *eap_packet, unsigned char id[]);
-unsigned char *eap_generateid(REQUEST *request, unsigned char response_id);
-unsigned char *eap_regenerateid(REQUEST *request, unsigned char response_id);
-
-/* Memory Management */
-EAP_PACKET *eap_packet_alloc(void);
-EAP_DS *eap_ds_alloc(void);
-EAP_HANDLER *eap_handler_alloc(void);
-void eap_packet_free(EAP_PACKET **eap_packet);
-void eap_ds_free(EAP_DS **eap_ds);
-void eap_handler_free(EAP_HANDLER **handler);
-
-int eaplist_add(EAP_HANDLER **list, EAP_HANDLER *handler);
-void eaplist_clean(EAP_HANDLER **list, time_t limit);
-void eaplist_free(EAP_HANDLER **list);
-EAP_HANDLER *eaplist_isreply(EAP_HANDLER **list, unsigned char id[]);
-EAP_HANDLER *eaplist_findhandler(EAP_HANDLER *list, unsigned char id[]);
-
-/* State */
-void generate_key(void);
-VALUE_PAIR *generate_state(void);
-int verify_state(VALUE_PAIR *state);
-
#endif /*_EAP_H*/
* Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
*/
#include <stdio.h>
-#include "eap.h"
+#include "rlm_eap.h"
/*
* Allocate a new EAP_PACKET
*/
EAP_PACKET *eap_packet_alloc(void)
{
- EAP_PACKET *rp;
+ EAP_PACKET *rp;
rp = rad_malloc(sizeof(EAP_PACKET));
- memset(rp, 0, sizeof(EAP_PACKET));
- return rp;
+ memset(rp, 0, sizeof(EAP_PACKET));
+ return rp;
}
/*
*/
void eap_packet_free(EAP_PACKET **eap_packet_ptr)
{
- EAP_PACKET *eap_packet;
+ EAP_PACKET *eap_packet;
- if (!eap_packet_ptr) return;
- eap_packet = *eap_packet_ptr;
+ if (!eap_packet_ptr) return;
+ eap_packet = *eap_packet_ptr;
if (!eap_packet) return;
- if (eap_packet->type.data) {
+ if (eap_packet->type.data) {
/*
* This is just a pointer in the packet
* so we do not free it but we NULL it
eap_packet->packet = NULL;
}
- free(eap_packet);
+ free(eap_packet);
- *eap_packet_ptr = NULL;
+ *eap_packet_ptr = NULL;
}
/*
*/
EAP_DS *eap_ds_alloc(void)
{
- EAP_DS *eap_ds;
+ EAP_DS *eap_ds;
- eap_ds = rad_malloc(sizeof(EAP_DS));
- memset(eap_ds, 0, sizeof(EAP_DS));
+ eap_ds = rad_malloc(sizeof(EAP_DS));
+ memset(eap_ds, 0, sizeof(EAP_DS));
if ((eap_ds->response = eap_packet_alloc()) == NULL) {
eap_ds_free(&eap_ds);
return NULL;
void eap_ds_free(EAP_DS **eap_ds_p)
{
- EAP_DS *eap_ds;
+ EAP_DS *eap_ds;
if (!eap_ds_p) return;
eap_ds = *eap_ds_p;
*/
EAP_HANDLER *eap_handler_alloc(void)
{
- EAP_HANDLER *handler;
+ EAP_HANDLER *handler;
- if ((handler = malloc(sizeof(EAP_HANDLER))) == NULL) {
- radlog(L_ERR, "out of memory");
- return NULL;
- }
- handler = rad_malloc(sizeof(EAP_HANDLER));
- /*memset(handler, 0, sizeof(EAP_HANDLER));
- */
+ if ((handler = malloc(sizeof(EAP_HANDLER))) == NULL) {
+ radlog(L_ERR, "out of memory");
+ return NULL;
+ }
+ handler = rad_malloc(sizeof(EAP_HANDLER));
return handler;
}
EAP_HANDLER *node;
node = list;
- while (node) {
- /*
- * Match is identified by the same IDs
- */
+ while (node) {
+ /*
+ * Match is identified by the same IDs
+ */
if (memcmp(node->id, id, id[0]) == 0) {
radlog(L_INFO, "rlm_eap: EAP Handler found in the list ");
return node;
}
- node = node->next;
+ node = node->next;
}
return NULL;
}
*/
#include "autoconf.h"
-#include "eap.h"
+#include "rlm_eap.h"
+#include "modules.h"
static CONF_PARSER module_config[] = {
{ "default_eap_type", PW_TYPE_STRING_PTR, offsetof(EAP_CONF, default_eap_type), NULL, "md5" },
eap_stuff = (rlm_eap_t **)instance;
types = NULL;
conf = NULL;
- auth_name = NULL;
+ auth_name = NULL;
conf = (EAP_CONF *)malloc(sizeof(EAP_CONF));
if (conf == NULL) {
radlog(L_ERR, "rlm_eap: out of memory");
return -1;
}
- if (cf_section_parse(cs, conf, module_config) < 0) {
- free(conf);
- return -1;
- }
+ if (cf_section_parse(cs, conf, module_config) < 0) {
+ free(conf);
+ return -1;
+ }
+
+ for(scs=cf_subsection_find_next(cs, NULL, NULL);
+ scs != NULL;
+ scs=cf_subsection_find_next(cs, scs, NULL)) {
- for(scs=cf_subsection_find_next(cs, NULL, NULL);
- scs != NULL;
- scs=cf_subsection_find_next(cs, scs, NULL)) {
- auth_name = cf_section_name1(scs);
+ auth_name = cf_section_name1(scs);
- if (!auth_name) continue;
- eaptype_load(&types, auth_name, scs);
- }
+ if (!auth_name) continue;
+
+ if (eaptype_load(&types, auth_name, scs) < 0) {
+ free(conf);
+ return -1;
+ }
+ }
if (!types) {
free(conf->default_eap_type);
*/
}
-
/*
* Select the appropriate eap_type or default to the configured one
*/
* Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
*/
-#include "eap.h"
#include <fcntl.h>
+#include <stdlib.h>
+#include "radiusd.h"
static const char rcsid[] = "$Id$";
static void generate_random(uint8_t *vector, int length)
{
int i;
- static unsigned char random_vector_pool[AUTH_VECTOR_LEN * 2];
+ static unsigned char random_vector_pool[AUTH_VECTOR_LEN * 2];
static int did_srand = 0;
static int counter = 0;
#ifdef __linux__