From: Arran Cudbard-Bell Date: Tue, 4 Jun 2013 13:16:02 +0000 (-0400) Subject: Remove rlm_eap2 X-Git-Tag: release_3_0_0_beta1~3 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=d4dcc40b94ebdb4ab51b469cca8f251a8116f7d3;p=freeradius.git Remove rlm_eap2 The name confuses people and requires a special build of hostapd to work. Any required EAP methods should be implemented by the rlm_eap module. --- diff --git a/raddb/experimental.conf b/raddb/experimental.conf index 4e89c89..3c6a957 100644 --- a/raddb/experimental.conf +++ b/raddb/experimental.conf @@ -114,258 +114,6 @@ hash_reload = 600 } - # Another implementation of the EAP module. - # - # This module requires the libeap.so file from the hostap - # software (http://hostap.epitest.fi/hostapd/). It has been - # tested on the development version of hostapd (0.6.1) ONLY. - # - # In order to use it, you MUST build a "libeap.so" in hostapd, - # which is not done by default. - # - # You MUST also edit the file: src/modules/rlm_eap2/Makefile - # to point to the location of the hostap include files. - # - # This module CANNOT be used in the same way as the current - # FreeRADIUS "eap" module. There is NO way to look inside of - # a tunneled request. There is NO way to proxy a tunneled - # request. There is NO way to even look at the user name inside - # of the tunneled request. There is NO way to control the - # choice of EAP types inside of the tunnel. You MUST force - # the server to choose "eap2" for authentication, because this - # module has no "authorize" section. - # - # If you want to use this module for experimentation, please - # post your comments to the freeradius-devel list: - # - # http://lists.freeradius.org/mailman/listinfo/freeradius-devel - # - # If you want to use this module in a production (i.e. real-world) - # environment: - # - # !!! DO NOT USE IT IN A PRODUCTION ENVIRONMENT !!! - # - # The module needs additional work to make it ready for - # production use.. Please supply patches, or sponsor the - # work by hiring a developer. Do NOT ask when the work will - # be done, because there is no plan to finish this module - # unless there is demand for it. - # - eap2 { - # EAP types are chosen in the order that they are - # listed in this section. There is no "default_eap_type" - # as with rlm_eap. Instead, the *first* EAP type is - # used as the default type. - # - peap { - } - - ttls { - } - - # This is the ONLY EAP type that has any configuration. - # All other EAP types have no configuration. - # - tls { - ca_cert = ${confdir}/certs/ca.pem - server_cert = ${confdir}/certs/server.pem - private_key_file = ${confdir}/certs/server.pem - private_key_password = whatever - } - - # - # These next two methods do not supply keying material. - # - md5 { - } - - mschapv2 { - } - - fast { - pac_opaque_encr_key = 000102030405060708090a0b0c0d0e0f - eap_fast_a_id = xxxxxx - eap_fast_a_id_info = my_server - eap_fast_prov = 3 - pac_key_lifetime = 604800 # 7 days - pac_key_refresh_tim = 86400 - } - - # LEAP is NOT supported by this module. - # Use the "eap" module instead. - - # For other methods that MIGHT work, see the - # configuration of hostap. The methods are statically - # linked in at compile time, and cannot be controlled - # here. - } - - # Configuration for experimental EAP types. The sub-sections - # can be copied into eap.conf. - eap { - ikev2 { - - # Server auth type - # Allowed values are: - # cert - for certificate based server authentication, - # other required settings for this type are - # 'private_key_file' and 'certificate_file' - # secret - for shared secret based server authentication, - # other required settings for this type is 'id' - # Default value of this option is 'secret' - # server_authtype=cert - - # Allowed default client auth types - # Allowed values are: - # secret - for shared secret based client authentication - # cert - for certificate based client authentication - # both - shared secret and certificate is allowed - # none - authentication will always fail - # Default value for this option is 'both'. This option could - # be overwritten within 'usersfile' file by EAP-IKEv2-Auth - # option. - # default_authtype = both - - # path to trusted CA certificate file - CA_file="/path/to/CA/cacert.pem" - - # path to CRL file, if not set, then there will be no - # checks against CRL - # crl_file="/path/to/crl.pem" - - # path to file with user settings - # - # Note that this file is read ONLY on module initialization! - # - # default ${confdir}/eap_ikev2_users - # usersfile=${confdir}/eap_ikev2_users - -# -# Sample "eap_ikev2_users" file entry: -# -#username EAP-IKEv2-IDType := KEY_ID, EAP-IKEv2-Secret := "tajne" - -## where: -## username - client user name from IKE-AUTH (IDr) or CommonName -## from x509 certificate -## EAP-IKEv2-IDType - ID Type - same as in expected IDType payload -## allowable attributes for EAP-IKEv2-IDType: -## IPV4_ADDR FQDN RFC822_ADDR IPV6_ADDR DER_ASN1_DN -## DER_ASN1_GN KEY_ID -## EAP-IKEv2-Secret - shared secret -## EAP-IKEv2-AuthType - optional parameter which defines expected client auth -## type. Allowed values are: secret,cert,both,none. -## For the meaning of this values, please see the -## description of 'default_authtype'. -## This attribute can overwrite 'default_authtype' value. - - - - # path to file with server private key - private_key_file="/path/to/srv-private-key.pem" - - # password to private key file - private_key_password="passwd" - - # path to file with server certificate - certificate_file="/path/to/srv-cert.pem" - - # server identity string - id="deMaio" - - # Server identity type. Allowed values are: - # IPV4_ADDR, FQDN, RFC822_ADDR, IPV6_ADDR, ASN1_DN, ASN1_GN, - # KEY_ID - # Default value is: KEY_ID - # id_type = KEY_ID - - - # MTU (default: 1398) - # fragment_size = 1398 - - # maximal allowed number of resends SA_INIT after receiving - # 'invalid KEY' notification (default 3) - # DH_counter_max = 3 - - # option which is used to control whenever send CERT REQ - # payload or not. - # Allowed values for this option are "yes" or "no". - #Default value is "no". - # certreq = "yes" - - # option which cotrols fast reconnect capability. - # Allowed valuse for this option are "yes" or "no". - # Default value is "yes". - # enable_fast_reauth = "no" - - # option which is used to control performing of DH exchange - # during fast rekeying protocol run. - # Allowed values for this option are "yes" or "no". - # Default value is "no" - # fast_DH_exchange = "yes" - - # Option which is used to set up expiration time of inactive - # IKEv2 session. - # After selected period of time (in seconds), inactive - # session data will be deleted. - # Default value of this option is set to 900 seconds - # fast_timer_expire = 900 - - # list of server proposals of available cryptographic - # suites - proposals { - # proposal number #1 - proposal { - - # Supported transforms types: encryption, - # prf, integrity, dhgroup. For multiple - # transforms just simple repeat key (i.e. - # integity). - - # encryption algorithm - # supported algorithms: - # null,3des,aes_128_cbc,aes_192_cbc, - # aes_256_cbc,idea - # blowfish:n, where n range from 8 to 448 bits, - # step 8 bits - # cast:n, where n range from 40 to 128 bits, - # step 8 bits - encryption = 3des - - # pseudo random function. Supported prf's: - # hmac_md5, hmac_sha1, hmac_tiger - prf = hmac_sha1 - - # integrity algorithm. Supported algorithms: - # hmac_md5_96, hmac_sha1_96,des_mac - integrity = hmac_sha1_96 - integrity = hmac_md5_96 - - # Diffie-Hellman groups: - # modp768, modp1024, modp1536, modp2048, - # modp3072, modp4096, modp6144, modp8192 - dhgroup = modp2048 - } - - # proposal number #2 - proposal { - encryption = 3des - prf = hmac_md5 - integrity = hmac_md5_96 - dhgroup = modp1024 - } - - # proposal number #3 - proposal { - encryption=3des - prf=hmac_md5 - integrity=hmac_md5_96 - dhgroup=modp2048 - } - } - } - } - # Instantiate a couple instances of the idn module idn { } diff --git a/src/modules/rlm_eap2/all.mk b/src/modules/rlm_eap2/all.mk deleted file mode 100644 index acccfbc..0000000 --- a/src/modules/rlm_eap2/all.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# $Id$ -# - -# -# This module is EXPERIMENTAL! -# - -# -# You will have to edit this Makefile to define where the -# hostap distribution is located. -# -# You will also have to edit: hostap/eap_example/Makefile -# to enable it to create a shared library, rather than a static one. -# -HOSTAP := /path/to/hostap - -#TARGET := rlm_eap2.a -SOURCES := rlm_eap2.c -SRC_CFLAGS := -I$(HOSTAP)/src/eap_common \ - -I$(HOSTAP)/src/eap_server -I$(HOSTAP)/src \ - -I$(HOSTAP)/src/common -I$(HOSTAP)/src/utils - -TGT_LDLIBS := $(HOSTAP)/eap_example/libeap.so diff --git a/src/modules/rlm_eap2/rlm_eap2.c b/src/modules/rlm_eap2/rlm_eap2.c deleted file mode 100644 index 1cafa0b..0000000 --- a/src/modules/rlm_eap2/rlm_eap2.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * This program is is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2 if the - * License as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** - * $Id$ - * @file rlm_eap2.c - * @brief Uses hostapd library to support some methods not provided by rlm_eap. - * - * @copyright 2007 Alan DeKok - */ -RCSID("$Id$") - -#include -#include -#include - -/* - * Hostap includes. - */ -#include - -#include -#include -#include - - -struct eap_server_ctx { - struct eap_eapol_interface *eap_if; - struct eap_sm *eap; - void *tls_ctx; -}; - -#define EAP_STATE_LEN (AUTH_VECTOR_LEN) -typedef struct EAP_HANDLER { - struct EAP_HANDLER *prev, *next; - uint8_t state[EAP_STATE_LEN]; - fr_ipaddr_t src_ipaddr; - - time_t timestamp; - - REQUEST *request; - struct rlm_eap_t *inst; - - struct eapol_callbacks eap_cb; - struct eap_config eap_conf; - struct eap_server_ctx server_ctx; -} EAP_HANDLER; - -typedef struct rlm_eap_t { - rbtree_t *session_tree; - EAP_HANDLER *session_head, *session_tail; - - /* - * Configuration items. - */ - int timer_limit; - int mod_accounting_username_bug; - - struct tls_connection_params tparams; - - /* - * For EAP-FAST - */ - char *pac_opaque_encr_key; - char *eap_fast_a_id; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int backend_auth; - - int num_types; - EapType methods[EAP_MAX_METHODS]; - int vendors[EAP_MAX_METHODS]; - -#ifdef HAVE_PTHREAD_H - pthread_mutex_t session_mutex; -#endif - - fr_randctx rand_pool; - void *tls_ctx; -} rlm_eap_t; - - -static void eap_handler_free(EAP_HANDLER *handler) -{ - eap_server_sm_deinit(handler->server_ctx.eap); - free(handler); -} - -static void eaplist_free(rlm_eap_t *inst) -{ - EAP_HANDLER *node, *next; - - for (node = inst->session_head; node != NULL; node = next) { - next = node->next; - eap_handler_free(node); - } - - inst->session_head = inst->session_tail = NULL; -} - -/* - * Return a 32-bit random number. - */ -static uint32_t eap_rand(fr_randctx *ctx) -{ - uint32_t num; - - num = ctx->randrsl[ctx->randcnt++]; - if (ctx->randcnt == 256) { - ctx->randcnt = 0; - fr_isaac(ctx); - } - - return num; -} - -/* - * Add a handler to the set of active sessions. - * - * Since we're adding it to the list, we guess that this means - * the packet needs a State attribute. So add one. - */ -static int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler) -{ - int i, status; - uint32_t lvalue; - VALUE_PAIR *state; - REQUEST *request = handler->request; - - rad_assert(handler != NULL); - rad_assert(handler->request != NULL); - - /* - * Generate State, since we've been asked to add it to - * the list. - */ - state = pairmake_reply("State", NULL, T_OP_EQ); - if (!state) return 0; - state->length = EAP_STATE_LEN; - - /* - * The time at which this request was made was the time - * at which it was received by the RADIUS server. - */ - handler->timestamp = handler->request->timestamp; - - handler->src_ipaddr = handler->request->packet->src_ipaddr; - - /* - * We don't need this any more. - */ - handler->request = NULL; - - /* - * Playing with a data structure shared among threads - * means that we need a lock, to avoid conflict. - */ - pthread_mutex_lock(&(inst->session_mutex)); - - /* - * Create a completely random state. - */ - for (i = 0; i < 4; i++) { - lvalue = eap_rand(&inst->rand_pool); - memcpy(state->vp_octets + i * 4, &lvalue, sizeof(lvalue)); - } - memcpy(handler->state, state->vp_strvalue, sizeof(handler->state)); - - /* - * Big-time failure. - */ - status = rbtree_insert(inst->session_tree, handler); - - if (status) { - EAP_HANDLER *prev; - - prev = inst->session_tail; - if (prev) { - prev->next = handler; - handler->prev = prev; - handler->next = NULL; - inst->session_tail = handler; - } else { - inst->session_head = inst->session_tail = handler; - handler->next = handler->prev = NULL; - } - } - - /* - * Now that we've finished mucking with the list, - * unlock it. - */ - pthread_mutex_unlock(&(inst->session_mutex)); - - if (!status) { - ERROR("rlm_eap2: Failed to remember handler!"); - eap_handler_free(handler); - return 0; - } - - return 1; -} - -/* - * Find a a previous EAP-Request sent by us, which matches - * the current EAP-Response. - * - * Then, release the handle from the list, and return it to - * the caller. - * - * Also since we fill the eap_ds with the present EAP-Response we - * got to free the prev_eapds & move the eap_ds to prev_eapds - */ -static EAP_HANDLER *eaplist_find(rlm_eap_t *inst, REQUEST *request) -{ - int i; - VALUE_PAIR *state; - rbnode_t *node; - EAP_HANDLER *handler, myHandler; - - /* - * We key the sessions off of the 'state' attribute, so it - * must exist. - */ - state = pairfind(request->packet->vps, PW_STATE, 0, TAG_ANY); - if (!state || - (state->length != EAP_STATE_LEN)) { - return NULL; - } - - myHandler.src_ipaddr = request->packet->src_ipaddr; - memcpy(myHandler.state, state->vp_strvalue, sizeof(myHandler.state)); - - /* - * Playing with a data structure shared among threads - * means that we need a lock, to avoid conflict. - */ - pthread_mutex_lock(&(inst->session_mutex)); - - /* - * Check the first few handlers in the list, and delete - * them if they're too old. We don't need to check them - * all, as incoming requests will quickly cause older - * handlers to be deleted. - * - */ - for (i = 0; i < 2; i++) { - handler = inst->session_head; - if (handler && - ((request->timestamp - handler->timestamp) > inst->timer_limit)) { - node = rbtree_find(inst->session_tree, handler); - rad_assert(node != NULL); - rbtree_delete(inst->session_tree, node); - - /* - * handler == inst->session_head - */ - inst->session_head = handler->next; - if (handler->next) { - handler->next->prev = NULL; - } else { - inst->session_head = NULL; - } - eap_handler_free(handler); - } - } - - handler = NULL; - node = rbtree_find(inst->session_tree, &myHandler); - if (node) { - handler = rbtree_node2data(inst->session_tree, node); - - /* - * Delete old handler from the tree. - */ - rbtree_delete(inst->session_tree, node); - - /* - * And unsplice it from the linked list. - */ - if (handler->prev) { - handler->prev->next = handler->next; - } else { - inst->session_head = handler->next; - } - if (handler->next) { - handler->next->prev = handler->prev; - } else { - inst->session_tail = handler->prev; - } - handler->prev = handler->next = NULL; - } - - pthread_mutex_unlock(&(inst->session_mutex)); - - /* - * Not found. - */ - if (!node) { - RDEBUG2("Request not found in the list"); - return NULL; - } - - /* - * Found, but state verification failed. - */ - if (!handler) { - ERROR("rlm_eap2: State verification failed."); - return NULL; - } - - RDEBUG2("Request found, released from the list"); - - return handler; -} - - -/* - * delete all the allocated space by eap module - */ -static int mod_detach(void *instance) -{ - rlm_eap_t *inst; - - inst = (rlm_eap_t *)instance; - - rbtree_free(inst->session_tree); - inst->session_tree = NULL; - eaplist_free(inst); - eap_server_unregister_methods(); - tls_deinit(inst->tls_ctx); - - pthread_mutex_destroy(&(inst->session_mutex)); - - return 0; -} - - -/* - * Compare two handlers. - */ -static int eap_handler_cmp(void const *a, void const *b) -{ - int rcode; - const EAP_HANDLER *one = a; - const EAP_HANDLER *two = b; - - rcode = fr_ipaddr_cmp(&one->src_ipaddr, &two->src_ipaddr); - if (rcode != 0) return rcode; - - return memcmp(one->state, two->state, sizeof(one->state)); -} - - -static int server_get_eap_user(void *ctx, UNUSED const u8 *identity, UNUSED size_t identity_len, int phase2, - struct eap_user *user) -{ - int i; - VALUE_PAIR *vp; - EAP_HANDLER *handler = ctx; - REQUEST *request = handler->request; - - os_memset(user, 0, sizeof(*user)); - - /* - * FIXME: Run through "authorise" again to look up - * password for the given identity - */ - - /* - * Do this always, just in case. - */ - vp = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY); - if (vp) { - user->password = (u8 *) os_strdup(vp->vp_strvalue); - user->password_len = vp->length; - } - if (!vp) vp = pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY); - if (vp) { - user->password = (u8 *) malloc(vp->length); - memcpy(user->password, vp->vp_octets, vp->length); - user->password_len = vp->length; - } - - if (!phase2) { - for (i = 0; i < handler->inst->num_types; i++) { - user->methods[i].vendor = handler->inst->vendors[i]; - user->methods[i].method = handler->inst->methods[i]; - } - return 0; - } - - /* - * FIXME: run tunneled sessions through the tunneled portion... - */ - - /* - * FIXME: Selectively control tunneled EAP types. - */ - user->methods[0].vendor = EAP_VENDOR_IETF; - user->methods[0].method = EAP_TYPE_MD5; - user->methods[1].vendor = EAP_VENDOR_IETF; - user->methods[1].method = EAP_TYPE_MSCHAPV2; - - /* - * No password configured... - */ - - return 0; -} - - -static char const * server_get_eap_req_id_text(UNUSED void *ctx, size_t *len) -{ - *len = 0; - return NULL; -} - - -static CONF_PARSER tls_config[] = { - /* - * TLS parameters. - */ - { "ca_cert", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, tparams.ca_cert), - NULL, "${confdir}/certs/ca.pem" }, - { "server_cert", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, tparams.client_cert), - NULL, "${confdir}/certs/server.pem" }, - { "private_key_file", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, tparams.private_key), - NULL, "${confdir}/certs/server.pem" }, - { "private_key_password", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, tparams.private_key_passwd), - NULL, "whatever" }, - - { "dh_file", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, tparams.dh_file), NULL, "whatever" }, - - { NULL, -1, 0, NULL, NULL } /* end the list */ -}; - -static CONF_PARSER fast_config[] = { - { "pac_opaque_encr_key", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, pac_opaque_encr_key), NULL, NULL }, - { "eap_fast_a_id", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, eap_fast_a_id), NULL, NULL }, - { "eap_fast_a_id_info", PW_TYPE_STRING_PTR, - offsetof(rlm_eap_t, eap_fast_a_id_info), NULL, NULL }, - { "eap_fast_prov", PW_TYPE_INTEGER, - offsetof(rlm_eap_t, eap_fast_prov), NULL, "3"}, - { "pac_key_lifetime", PW_TYPE_INTEGER, - offsetof(rlm_eap_t, pac_key_lifetime), NULL, "604800"}, - { "pac_key_refresh_time", PW_TYPE_INTEGER, - offsetof(rlm_eap_t, pac_key_refresh_time), NULL, "86400"}, - { NULL, -1, 0, NULL, NULL } /* end the list */ -}; - -static const CONF_PARSER module_config[] = { - { "timer_expire", PW_TYPE_INTEGER, - offsetof(rlm_eap_t, timer_limit), NULL, "60"}, - { "mod_accounting_username_bug", PW_TYPE_BOOLEAN, - offsetof(rlm_eap_t, mod_accounting_username_bug), NULL, "no" }, - - { "backend_auth", PW_TYPE_BOOLEAN, - offsetof(rlm_eap_t, backend_auth), NULL, "yes" }, - - { "tls", PW_TYPE_SUBSECTION, 0, NULL, (void const *) tls_config }, - - { "fast", PW_TYPE_SUBSECTION, 0, NULL, (void const *) fast_config }, - - { NULL, -1, 0, NULL, NULL } /* end the list */ -}; - - -static int eap_example_server_init_tls(rlm_eap_t *inst) -{ - struct tls_config tconf; - - os_memset(&tconf, 0, sizeof(tconf)); - inst->tls_ctx = tls_init(&tconf); - if (!inst->tls_ctx) - return -1; - - if (tls_global_set_params(inst->tls_ctx, &inst->tparams)) { - ERROR("rlm_eap2: Failed to set TLS parameters"); - return -1; - } - - if (tls_global_set_verify(inst->tls_ctx, 0)) { - ERROR("rlm_eap2: Failed to set check_crl"); - return -1; - } - - return 0; -} - - -/* - * read the config section and load all the eap authentication types present. - */ -static int mod_instantiate(CONF_SECTION *cs, void *instance) -{ - int i, num_types; - int has_tls, do_tls; - rlm_eap_t *inst = instance; - CONF_SECTION *scs; - - /* - * Create our own random pool. - */ - for (i = 0; i < 256; i++) { - inst->rand_pool.randrsl[i] = fr_rand(); - } - fr_randinit(&inst->rand_pool, 1); - - /* - * List of sessions are set to NULL by the memset - * of 'inst', above. - */ - - /* - * Lookup sessions in the tree. We don't free them in - * the tree, as that's taken care of elsewhere... - */ - inst->session_tree = rbtree_create(eap_handler_cmp, NULL, 0); - if (!inst->session_tree) { - ERROR("rlm_eap2: Cannot initialize tree"); - return -1; - } - - /* - * This registers ALL available methods. - * - * FIXME: we probably want to selectively register - * some methods. - */ - if (eap_server_register_methods() < 0) { - return -1; - } - - /* Load all the configured EAP-Types */ - num_types = 0; - has_tls = do_tls = 0; - for (scs=cf_subsection_find_next(cs, NULL, NULL); - scs != NULL; - scs=cf_subsection_find_next(cs, scs, NULL)) { - char const *auth_type; - char buffer[64], *p; - - auth_type = cf_section_name1(scs); - - if (!auth_type) continue; - - if (num_types >= EAP_MAX_METHODS) { - WARN("Ignoring EAP type %s: too many types defined", auth_type); - continue; - } - - /* - * Hostapd doesn't do case-insensitive comparisons. - * So we mash everything to uppercase for it. - */ - strlcpy(buffer, auth_type, sizeof(buffer)); - - for (p = buffer; *p; p++) { - if (!islower((int)*p)) continue; - *p = toupper((int)*p); - } - - inst->methods[num_types] = eap_server_get_type(buffer, - &inst->vendors[num_types]); - if (inst->methods[num_types] == EAP_TYPE_NONE) { - ERROR("rlm_eap2: Unknown EAP type %s", - auth_type); - return -1; - } - - switch (inst->methods[num_types]) { - case EAP_TYPE_TLS: - has_tls = true; - /* FALL-THROUGH */ - - case EAP_TYPE_TTLS: - case EAP_TYPE_PEAP: - case EAP_TYPE_FAST: - do_tls = true; - break; - - default: - break; - } - - num_types++; /* successfully loaded one more types */ - } - inst->num_types = num_types; - - if (do_tls && !has_tls) { - ERROR("rlm_eap2: TLS has not been configured. Cannot do methods that need TLS."); - return -1; - } - - if (do_tls) { - /* - * Initialize TLS. - */ - if (eap_example_server_init_tls(inst) < 0) { - ERROR("rlm_eap2: Cannot initialize TLS"); - return -1; - } - } - - pthread_mutex_init(&(inst->session_mutex), NULL); - return 0; -} - - -static int eap_req2vp(EAP_HANDLER *handler) -{ - int encoded, total, size; - const uint8_t *ptr; - VALUE_PAIR *head = NULL; - VALUE_PAIR **tail = &head; - VALUE_PAIR *vp; - - ptr = wpabuf_head(handler->server_ctx.eap_if->eapReqData); - encoded = total = wpabuf_len(handler->server_ctx.eap_if->eapReqData); - - do { - size = total; - if (size > 253) size = 253; - - vp = paircreate(handler->request->reply, PW_EAP_MESSAGE, 0); - if (!vp) { - pairfree(&head); - return -1; - } - pairmemcpy(vp, ptr, size); - - *tail = vp; - tail = &(vp->next); - - ptr += size; - total -= size; - } while (total > 0); - - pairdelete(&handler->request->reply->vps, PW_EAP_MESSAGE, TAG_ANY); - pairadd(&handler->request->reply->vps, head); - - return encoded; -} - -static int eap_example_server_step(EAP_HANDLER *handler) -{ - int res, process = 0; - REQUEST *request = handler->request; - - res = eap_server_sm_step(handler->server_ctx.eap); - - if (handler->server_ctx.eap_if->eapReq) { - DEBUG("==> Request"); - process = 1; - handler->server_ctx.eap_if->eapReq = 0; - } - - if (handler->server_ctx.eap_if->eapSuccess) { - DEBUG("==> Success"); - process = 1; - res = 0; - - if (handler->server_ctx.eap_if->eapKeyAvailable) { - int length = handler->server_ctx.eap_if->eapKeyDataLen; - VALUE_PAIR *vp; - - if (length > 64) { - length = 32; - } else { - length /= 2; - /* - * FIXME: Length is zero? - */ - } - - vp = pairmake_reply("MS-MPPE-Recv-Key", NULL, T_OP_EQ); - if (vp) { - pairmemcpy(vp, - handler->server_ctx.eap_if->eapKeyData, - length); - } - - vp = pairmake_reply("MS-MPPE-Send-Key", NULL, T_OP_EQ); - if (vp) { - pairmemcpy(vp, - handler->server_ctx.eap_if->eapKeyData + length, - length); - } - } - } - - if (handler->server_ctx.eap_if->eapFail) { - DEBUG("==> Fail"); - process = 1; - } - - if (process) { - if (wpabuf_head(handler->server_ctx.eap_if->eapReqData)) { - if (!eap_req2vp(handler)) return -1; - } else { - return -1; - } - } - - return res; -} - - -/* - * Handles multiple EAP-Message attrs - * ie concatenates all to get the complete EAP packet. - * - * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message, - * refer fragmentation in rfc2869. - */ -static int eap_vp2data(VALUE_PAIR *vps, void **data, int *data_len) -{ - VALUE_PAIR *first, *vp; - unsigned char *ptr; - uint16_t len; - int total_len; - - /* - * Get only EAP-Message attribute list - */ - first = pairfind(vps, PW_EAP_MESSAGE, 0, TAG_ANY); - if (!first) { - ERROR("rlm_eap2: EAP-Message not found"); - return -1; - } - - /* - * Sanity check the length before doing anything. - */ - if (first->length < 4) { - ERROR("rlm_eap2: EAP packet is too short."); - return -1; - } - - /* - * Get the Actual length from the EAP packet - * First EAP-Message contains the EAP packet header - */ - memcpy(&len, first->vp_strvalue + 2, sizeof(len)); - len = ntohs(len); - - /* - * Take out even more weird things. - */ - if (len < 4) { - ERROR("rlm_eap2: EAP packet has invalid length."); - return -1; - } - - /* - * Sanity check the length, BEFORE malloc'ing memory. - */ - total_len = 0; - for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0, TAG_ANY)) { - total_len += vp->length; - - if (total_len > len) { - ERROR("rlm_eap2: Malformed EAP packet. Length in packet header does not match actual length"); - return -1; - } - } - - /* - * If the length is SMALLER, die, too. - */ - if (total_len < len) { - ERROR("rlm_eap2: Malformed EAP packet. Length in packet header does not match actual length"); - return -1; - } - - /* - * Now that we know the lengths are OK, allocate memory. - */ - *data = malloc(len); - if (!*data) { - return -1; - } - *data_len = len; - - /* - * Copy the data from EAP-Message's over to our EAP packet. - */ - ptr = *data; - - /* RADIUS ensures order of attrs, so just concatenate all */ - for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0, TAG_ANY)) { - memcpy(ptr, vp->vp_strvalue, vp->length); - ptr += vp->length; - } - - return 0; -} - -/* - * FIXME: Add an "authorize" section which sets Auth-Type = EAP2 - * FIXME: Also in "authorize", set User-Name if not already set. - */ - - -/* - * Do EAP. - */ -static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) -{ - rlm_eap_t *inst; - EAP_HANDLER *handler; - void *data; - int data_len; - rlm_rcode_t rcode; - VALUE_PAIR *vp; - - inst = (rlm_eap_t *) instance; - - vp = pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY); - if (!vp) { - RDEBUG("No EAP-Message. Not doing EAP."); - return RLM_MODULE_FAIL; - } - - /* - * Get the eap packet to start with - */ - data = NULL; - data_len = 0; - if (eap_vp2data(request->packet->vps, &data, &data_len) < 0) { - ERROR("rlm_eap2: Malformed EAP Message"); - return RLM_MODULE_FAIL; - } - - vp = pairfind(request->packet->vps, PW_STATE, 0, TAG_ANY); - if (vp) { - handler = eaplist_find(inst, request); - if (!handler) { - RDEBUG("No handler found"); - return RLM_MODULE_FAIL; - } - } else { - handler = malloc(sizeof(*handler)); - if (!handler) return RLM_MODULE_FAIL; - - memset(handler, 0, sizeof(*handler)); - - handler->inst = inst; - handler->eap_cb.get_eap_user = server_get_eap_user; - handler->eap_cb.get_eap_req_id_text = server_get_eap_req_id_text; - - handler->eap_conf.eap_server = 1; - handler->eap_conf.ssl_ctx = inst->tls_ctx; - - /* - * Copy EAP-FAST parameters. - */ - handler->eap_conf.pac_opaque_encr_key = inst->pac_opaque_encr_key; - handler->eap_conf.eap_fast_a_id = inst->eap_fast_a_id; - handler->eap_conf.eap_fast_a_id_len = strlen(inst->eap_fast_a_id); - handler->eap_conf.eap_fast_a_id_info = inst->eap_fast_a_id_info; - handler->eap_conf.eap_fast_prov = inst->eap_fast_prov; - handler->eap_conf.pac_key_lifetime = inst->pac_key_lifetime; - handler->eap_conf.pac_key_refresh_time = inst->pac_key_refresh_time; - handler->eap_conf.backend_auth = inst->backend_auth; - - handler->server_ctx.eap = eap_server_sm_init(handler, - &handler->eap_cb, - &handler->eap_conf); - if (!handler->server_ctx.eap) { - free(handler); - return RLM_MODULE_FAIL; - } - - handler->server_ctx.eap_if = eap_get_interface(handler->server_ctx.eap); - - /* Enable "port" and request EAP to start authentication. */ - handler->server_ctx.eap_if->portEnabled = true; - handler->server_ctx.eap_if->eapRestart = true; - } - - handler->request = request; - wpabuf_free(handler->server_ctx.eap_if->eapRespData); - handler->server_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len); - if (handler->server_ctx.eap_if->eapRespData) { - handler->server_ctx.eap_if->eapResp = true; - } - - if (eap_example_server_step(handler) < 0) { - RDEBUG("Failed in EAP library"); - goto fail; - } - - if (handler->server_ctx.eap_if->eapSuccess) { - request->reply->code = PW_AUTHENTICATION_ACK; - rcode = RLM_MODULE_OK; - - } else if (handler->server_ctx.eap_if->eapFail) { - fail: - request->reply->code = PW_AUTHENTICATION_REJECT; - rcode = RLM_MODULE_REJECT; - - } else { - request->reply->code = PW_ACCESS_CHALLENGE; - rcode = RLM_MODULE_HANDLED; - } - - if (handler->server_ctx.eap_if->eapFail || - handler->server_ctx.eap_if->eapSuccess) { - RDEBUG2("Freeing handler"); - /* handler is not required any more, free it now */ - eap_handler_free(handler); - handler = NULL; - } else { - eaplist_add(inst, handler); - } - - /* - * If it's an Access-Accept, RFC 2869, Section 2.3.1 - * says that we MUST include a User-Name attribute in the - * Access-Accept. - */ - if ((request->reply->code == PW_AUTHENTICATION_ACK) && - request->username) { - /* - * Doesn't exist, add it in. - */ - vp = pairfind(request->reply->vps, PW_USER_NAME, 0, TAG_ANY); - if (!vp) { - vp = pairmake("User-Name", request->username->vp_strvalue, - T_OP_EQ); - rad_assert(vp != NULL); - pairadd(&(request->reply->vps), vp); - } - - /* - * Cisco AP1230 has a bug and needs a zero - * terminated string in Access-Accept. - */ - if ((inst->mod_accounting_username_bug) && - (vp->length < (int) sizeof(vp->vp_strvalue))) { - vp->vp_strvalue[vp->length] = '\0'; - vp->length++; - } - } - - vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY); - if (!vp) { - vp = paircreate(PW_MESSAGE_AUTHENTICATOR, 0); - memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN); - vp->length = AUTH_VECTOR_LEN; - pairadd(&(request->reply->vps), vp); - } - return rcode; -} - - -/* - * The module name should be the only globally exported symbol. - * That is, everything else should be 'static'. - */ -module_t rlm_eap2 = { - RLM_MODULE_INIT, - "eap2", - RLM_TYPE_CHECK_CONFIG_SAFE, /* type */ - sizeof(rlm_eap_t), - module_config, - mod_instantiate, /* instantiation */ - mod_detach, /* detach */ - { - mod_authenticate, /* authentication */ - NULL, /* authorization */ - NULL, /* preaccounting */ - NULL, /* accounting */ - NULL, /* checksimul */ - NULL, /* pre-proxy */ - NULL, /* post-proxy */ - NULL /* post-auth */ - }, -};