⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap_ttls.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * EAP peer method: EAP-TTLS (RFC 5281) * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "eap_peer/eap_i.h"#include "eap_peer/eap_tls_common.h"#include "eap_peer/eap_config.h"#include "ms_funcs.h"#include "sha1.h"#include "eap_common/chap.h"#include "tls.h"#include "mschapv2.h"#include "eap_common/eap_ttls.h"/* Maximum supported TTLS version * 0 = RFC 5281 * 1 = draft-funk-eap-ttls-v1-00.txt */#ifndef EAP_TTLS_VERSION#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */#endif /* EAP_TTLS_VERSION */#define MSCHAPV2_KEY_LEN 16#define MSCHAPV2_NT_RESPONSE_LEN 24static void eap_ttls_deinit(struct eap_sm *sm, void *priv);struct eap_ttls_data {	struct eap_ssl_data ssl;	int ssl_initialized;	int ttls_version, force_ttls_version;	const struct eap_method *phase2_method;	void *phase2_priv;	int phase2_success;	int phase2_start;	enum phase2_types {		EAP_TTLS_PHASE2_EAP,		EAP_TTLS_PHASE2_MSCHAPV2,		EAP_TTLS_PHASE2_MSCHAP,		EAP_TTLS_PHASE2_PAP,		EAP_TTLS_PHASE2_CHAP	} phase2_type;	struct eap_method_type phase2_eap_type;	struct eap_method_type *phase2_eap_types;	size_t num_phase2_eap_types;	u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];	int auth_response_valid;	u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */	u8 ident;	int resuming; /* starting a resumed session */	int reauth; /* reauthentication */	u8 *key_data;	struct wpabuf *pending_phase2_req;#ifdef EAP_TNC	int ready_for_tnc;	int tnc_started;#endif /* EAP_TNC */};static void * eap_ttls_init(struct eap_sm *sm){	struct eap_ttls_data *data;	struct eap_peer_config *config = eap_get_config(sm);	char *selected;	data = os_zalloc(sizeof(*data));	if (data == NULL)		return NULL;	data->ttls_version = EAP_TTLS_VERSION;	data->force_ttls_version = -1;	selected = "EAP";	data->phase2_type = EAP_TTLS_PHASE2_EAP;#if EAP_TTLS_VERSION > 0	if (config && config->phase1) {		const char *pos = os_strstr(config->phase1, "ttlsver=");		if (pos) {			data->force_ttls_version = atoi(pos + 8);			data->ttls_version = data->force_ttls_version;			wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "				   "%d", data->force_ttls_version);		}	}#endif /* EAP_TTLS_VERSION */	if (config && config->phase2) {		if (os_strstr(config->phase2, "autheap=")) {			selected = "EAP";			data->phase2_type = EAP_TTLS_PHASE2_EAP;		} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {			selected = "MSCHAPV2";			data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;		} else if (os_strstr(config->phase2, "auth=MSCHAP")) {			selected = "MSCHAP";			data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;		} else if (os_strstr(config->phase2, "auth=PAP")) {			selected = "PAP";			data->phase2_type = EAP_TTLS_PHASE2_PAP;		} else if (os_strstr(config->phase2, "auth=CHAP")) {			selected = "CHAP";			data->phase2_type = EAP_TTLS_PHASE2_CHAP;		}	}	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);	if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {		if (eap_peer_select_phase2_methods(config, "autheap=",						   &data->phase2_eap_types,						   &data->num_phase2_eap_types)		    < 0) {			eap_ttls_deinit(sm, data);			return NULL;		}		data->phase2_eap_type.vendor = EAP_VENDOR_IETF;		data->phase2_eap_type.method = EAP_TYPE_NONE;	}#if EAP_TTLS_VERSION > 0	if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&	    data->ttls_version > 0) {		if (data->force_ttls_version > 0) {			wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "				   "TLS library does not support TLS/IA.",				   data->force_ttls_version);			eap_ttls_deinit(sm, data);			return NULL;		}		data->ttls_version = 0;	}#endif /* EAP_TTLS_VERSION */	return data;}static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,				       struct eap_ttls_data *data){	if (data->phase2_priv && data->phase2_method) {		data->phase2_method->deinit(sm, data->phase2_priv);		data->phase2_method = NULL;		data->phase2_priv = NULL;	}}static void eap_ttls_deinit(struct eap_sm *sm, void *priv){	struct eap_ttls_data *data = priv;	if (data == NULL)		return;	eap_ttls_phase2_eap_deinit(sm, data);	os_free(data->phase2_eap_types);	if (data->ssl_initialized)		eap_peer_tls_ssl_deinit(sm, &data->ssl);	os_free(data->key_data);	wpabuf_free(data->pending_phase2_req);	os_free(data);}static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,			     int mandatory, size_t len){	struct ttls_avp_vendor *avp;	u8 flags;	size_t hdrlen;	avp = (struct ttls_avp_vendor *) avphdr;	flags = mandatory ? AVP_FLAGS_MANDATORY : 0;	if (vendor_id) {		flags |= AVP_FLAGS_VENDOR;		hdrlen = sizeof(*avp);		avp->vendor_id = host_to_be32(vendor_id);	} else {		hdrlen = sizeof(struct ttls_avp);	}	avp->avp_code = host_to_be32(avp_code);	avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));	return avphdr + hdrlen;}static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,			     u32 vendor_id, int mandatory,			     const u8 *data, size_t len){	u8 *pos;	pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);	os_memcpy(pos, data, len);	pos += len;	AVP_PAD(start, pos);	return pos;}static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,				    int mandatory){	struct wpabuf *msg;	u8 *avp, *pos;	msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);	if (msg == NULL) {		wpabuf_free(*resp);		*resp = NULL;		return -1;	}	avp = wpabuf_mhead(msg);	pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp));	os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));	pos += wpabuf_len(*resp);	AVP_PAD(avp, pos);	wpabuf_free(*resp);	wpabuf_put(msg, pos - avp);	*resp = msg;	return 0;}#if EAP_TTLS_VERSION > 0static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,					    struct eap_ttls_data *data,					    const u8 *key, size_t key_len){	u8 *buf;	size_t buf_len;	int ret;	if (key) {		buf_len = 2 + key_len;		buf = os_malloc(buf_len);		if (buf == NULL)			return -1;		WPA_PUT_BE16(buf, key_len);		os_memcpy(buf + 2, key, key_len);	} else {		buf = NULL;		buf_len = 0;	}	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "			"secret permutation", buf, buf_len);	ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,						     data->ssl.conn,						     buf, buf_len);	os_free(buf);	return ret;}#endif /* EAP_TTLS_VERSION */static int eap_ttls_v0_derive_key(struct eap_sm *sm,				  struct eap_ttls_data *data){	os_free(data->key_data);	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,						 "ttls keying material",						 EAP_TLS_KEY_LEN);	if (!data->key_data) {		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");		return -1;	}	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",			data->key_data, EAP_TLS_KEY_LEN);	return 0;}#if EAP_TTLS_VERSION > 0static int eap_ttls_v1_derive_key(struct eap_sm *sm,				  struct eap_ttls_data *data){	struct tls_keys keys;	u8 *rnd;	os_free(data->key_data);	data->key_data = NULL;	os_memset(&keys, 0, sizeof(keys));	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||	    keys.client_random == NULL || keys.server_random == NULL ||	    keys.inner_secret == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "			   "client random, or server random to derive keying "			   "material");		return -1;	}	rnd = os_malloc(keys.client_random_len + keys.server_random_len);	data->key_data = os_malloc(EAP_TLS_KEY_LEN);	if (rnd == NULL || data->key_data == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");		os_free(rnd);		os_free(data->key_data);		data->key_data = NULL;		return -1;	}	os_memcpy(rnd, keys.client_random, keys.client_random_len);	os_memcpy(rnd + keys.client_random_len, keys.server_random,		  keys.server_random_len);	if (tls_prf(keys.inner_secret, keys.inner_secret_len,		    "ttls v1 keying material", rnd, keys.client_random_len +		    keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");		os_free(rnd);		os_free(data->key_data);		data->key_data = NULL;		return -1;	}	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",		    rnd, keys.client_random_len + keys.server_random_len);	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",			keys.inner_secret, keys.inner_secret_len);	os_free(rnd);	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",			data->key_data, EAP_TLS_KEY_LEN);	return 0;}#endif /* EAP_TTLS_VERSION */static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,					struct eap_ttls_data *data, size_t len){#if EAP_TTLS_VERSION > 0	struct tls_keys keys;	u8 *challenge, *rnd;#endif /* EAP_TTLS_VERSION */	if (data->ttls_version == 0) {		return eap_peer_tls_derive_key(sm, &data->ssl,					       "ttls challenge", len);	}#if EAP_TTLS_VERSION > 0	os_memset(&keys, 0, sizeof(keys));	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||	    keys.client_random == NULL || keys.server_random == NULL ||	    keys.inner_secret == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "			   "client random, or server random to derive "			   "implicit challenge");		return NULL;	}	rnd = os_malloc(keys.client_random_len + keys.server_random_len);	challenge = os_malloc(len);	if (rnd == NULL || challenge == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "			   "challenge derivation");		os_free(rnd);		os_free(challenge);		return NULL;	}	os_memcpy(rnd, keys.server_random, keys.server_random_len);	os_memcpy(rnd + keys.server_random_len, keys.client_random,		  keys.client_random_len);	if (tls_prf(keys.inner_secret, keys.inner_secret_len,		    "inner application challenge", rnd,		    keys.client_random_len + keys.server_random_len,		    challenge, len)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "			   "challenge");		os_free(rnd);		os_free(challenge);		return NULL;	}	os_free(rnd);	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",			challenge, len);	return challenge;#else /* EAP_TTLS_VERSION */	return NULL;#endif /* EAP_TTLS_VERSION */}static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm,					 struct eap_ttls_data *data,					 struct eap_method_ret *ret){#if EAP_TTLS_VERSION > 0	if (data->ttls_version > 0) {		const struct eap_method *m = data->phase2_method;		void *priv = data->phase2_priv;		/* TTLSv1 requires TLS/IA FinalPhaseFinished */		if (ret->decision == DECISION_UNCOND_SUCC)			ret->decision = DECISION_COND_SUCC;		ret->methodState = METHOD_CONT;		if (ret->decision == DECISION_COND_SUCC &&		    m->isKeyAvailable && m->getKey &&		    m->isKeyAvailable(sm, priv)) {			u8 *key;			size_t key_len;			key = m->getKey(sm, priv, &key_len);			if (key) {				eap_ttls_ia_permute_inner_secret(					sm, data, key, key_len);				os_free(key);			}		}	}#endif /* EAP_TTLS_VERSION */}static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,					      u8 method){	size_t i;	for (i = 0; i < data->num_phase2_eap_types; i++) {		if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||		    data->phase2_eap_types[i].method != method)			continue;		data->phase2_eap_type.vendor =			data->phase2_eap_types[i].vendor;		data->phase2_eap_type.method =			data->phase2_eap_types[i].method;		wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "			   "Phase 2 EAP vendor %d method %d",			   data->phase2_eap_type.vendor,			   data->phase2_eap_type.method);		break;	}}static int eap_ttls_phase2_eap_process(struct eap_sm *sm,				       struct eap_ttls_data *data,				       struct eap_method_ret *ret,				       struct eap_hdr *hdr, size_t len,				       struct wpabuf **resp){	struct wpabuf msg;	struct eap_method_ret iret;	os_memset(&iret, 0, sizeof(iret));	wpabuf_set(&msg, hdr, len);	*resp = data->phase2_method->process(sm, data->phase2_priv, &iret,					     &msg);	if ((iret.methodState == METHOD_DONE ||	     iret.methodState == METHOD_MAY_CONT) &&	    (iret.decision == DECISION_UNCOND_SUCC ||	     iret.decision == DECISION_COND_SUCC ||	     iret.decision == DECISION_FAIL)) {		ret->methodState = iret.methodState;		ret->decision = iret.decision;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -