2018-04-20 03:33:04 +00:00
|
|
|
/*
|
|
|
|
* EAP peer state machines (RFC 4137)
|
|
|
|
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
|
|
|
|
*
|
|
|
|
* This software may be distributed under the terms of the BSD license.
|
|
|
|
* See README for more details.
|
|
|
|
*
|
|
|
|
* This file implements the Peer State Machine as defined in RFC 4137. The used
|
|
|
|
* states and state transitions match mostly with the RFC. However, there are
|
|
|
|
* couple of additional transitions for working around small issues noticed
|
|
|
|
* during testing. These exceptions are explained in comments within the
|
|
|
|
* functions in this file. The method functions, m.func(), are similar to the
|
|
|
|
* ones used in RFC 4137, but some small changes have used here to optimize
|
|
|
|
* operations and to add functionality needed for fast re-authentication
|
|
|
|
* (session resumption).
|
|
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "esp_err.h"
|
|
|
|
|
2018-08-13 08:37:56 +00:00
|
|
|
#include "utils/includes.h"
|
|
|
|
#include "utils/common.h"
|
|
|
|
#include "utils/wpa_debug.h"
|
|
|
|
#include "common/eapol_common.h"
|
|
|
|
#include "common/ieee802_11_defs.h"
|
|
|
|
#include "utils/state_machine.h"
|
|
|
|
#include "rsn_supp/wpa.h"
|
2018-04-20 03:33:04 +00:00
|
|
|
|
|
|
|
#include "crypto/crypto.h"
|
|
|
|
|
2018-08-13 08:37:56 +00:00
|
|
|
#include "utils/ext_password.h"
|
|
|
|
#include "tls/tls.h"
|
|
|
|
#include "eap_peer/eap_i.h"
|
|
|
|
#include "eap_peer/eap_config.h"
|
|
|
|
#include "eap_peer/eap.h"
|
|
|
|
#include "eap_peer/eap_tls.h"
|
|
|
|
#include "esp_supplicant/esp_wifi_driver.h"
|
2018-04-20 03:33:04 +00:00
|
|
|
#ifdef EAP_PEER_METHOD
|
2018-08-13 08:37:56 +00:00
|
|
|
#include "eap_peer/eap_methods.h"
|
2018-04-20 03:33:04 +00:00
|
|
|
#endif
|
|
|
|
|
2018-08-13 08:37:56 +00:00
|
|
|
#include "supplicant_opt.h"
|
|
|
|
|
2018-04-20 03:33:04 +00:00
|
|
|
|
|
|
|
void eap_peer_config_deinit(struct eap_sm *sm);
|
|
|
|
void eap_peer_blob_deinit(struct eap_sm *sm);
|
|
|
|
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt);
|
|
|
|
|
|
|
|
#ifdef EAP_PEER_METHOD
|
|
|
|
static struct eap_method *eap_methods = NULL;
|
|
|
|
|
|
|
|
const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
|
|
|
|
{
|
|
|
|
struct eap_method *m;
|
|
|
|
for (m = eap_methods; m; m = m->next) {
|
|
|
|
if (m->vendor == vendor && m->method == method)
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct eap_method * eap_peer_get_methods(size_t *count)
|
|
|
|
{
|
|
|
|
int c = 0;
|
|
|
|
struct eap_method *m;
|
|
|
|
|
|
|
|
for (m = eap_methods; m; m = m->next)
|
|
|
|
c++;
|
|
|
|
|
|
|
|
*count = c;
|
|
|
|
return eap_methods;
|
|
|
|
}
|
|
|
|
|
|
|
|
EapType eap_peer_get_type(const char *name, int *vendor)
|
|
|
|
{
|
|
|
|
struct eap_method *m;
|
|
|
|
for (m = eap_methods; m; m = m->next) {
|
|
|
|
if (os_strcmp(m->name, name) == 0) {
|
|
|
|
*vendor = m->vendor;
|
|
|
|
return m->method;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*vendor = EAP_VENDOR_IETF;
|
|
|
|
return EAP_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
eap_allowed_phase2_type(int vendor, int type)
|
|
|
|
{
|
|
|
|
if (vendor != EAP_VENDOR_IETF)
|
|
|
|
return 0;
|
|
|
|
return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
|
|
|
|
type != EAP_TYPE_FAST;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 eap_get_phase2_type(const char *name, int *vendor)
|
|
|
|
{
|
|
|
|
int v;
|
|
|
|
u8 type = eap_peer_get_type(name, &v);
|
|
|
|
if (eap_allowed_phase2_type(v, type)) {
|
|
|
|
*vendor = v;
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
*vendor = EAP_VENDOR_IETF;
|
|
|
|
return EAP_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
|
|
|
|
size_t *count)
|
|
|
|
{
|
|
|
|
struct eap_method_type *buf;
|
|
|
|
u32 method;
|
|
|
|
int vendor;
|
|
|
|
size_t mcount;
|
|
|
|
const struct eap_method *methods, *m;
|
|
|
|
|
|
|
|
methods = eap_peer_get_methods(&mcount);
|
|
|
|
if (methods == NULL)
|
|
|
|
return NULL;
|
|
|
|
*count = 0;
|
|
|
|
buf = os_malloc(mcount * sizeof(struct eap_method_type));
|
|
|
|
if (buf == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (m = methods; m; m = m->next) {
|
|
|
|
vendor = m->vendor;
|
|
|
|
method = m->method;
|
|
|
|
if (eap_allowed_phase2_type(vendor, method)) {
|
|
|
|
if (vendor == EAP_VENDOR_IETF &&
|
|
|
|
method == EAP_TYPE_TLS && config &&
|
|
|
|
config->private_key2 == NULL)
|
|
|
|
continue;
|
|
|
|
buf[*count].vendor = vendor;
|
|
|
|
buf[*count].method = method;
|
|
|
|
(*count)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct eap_method * eap_peer_method_alloc(int vendor, EapType method,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
struct eap_method *eap;
|
|
|
|
eap = (struct eap_method *)os_zalloc(sizeof(*eap));
|
|
|
|
if (eap == NULL)
|
|
|
|
return NULL;
|
|
|
|
eap->vendor = vendor;
|
|
|
|
eap->method = method;
|
|
|
|
eap->name = name;
|
|
|
|
return eap;
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_peer_method_free(struct eap_method *method)
|
|
|
|
{
|
|
|
|
os_free(method);
|
|
|
|
}
|
|
|
|
|
|
|
|
int eap_peer_method_register(struct eap_method *method)
|
|
|
|
{
|
|
|
|
struct eap_method *m, *last = NULL;
|
|
|
|
|
|
|
|
if (method == NULL || method->name == NULL)
|
|
|
|
return -1;
|
|
|
|
for (m = eap_methods; m; m = m->next) {
|
|
|
|
if (m->vendor == method->vendor &&
|
|
|
|
m->method == method->method &&
|
|
|
|
os_strcmp(m->name, method->name))
|
|
|
|
return -2;
|
|
|
|
last = m;
|
|
|
|
}
|
|
|
|
if (last)
|
|
|
|
last->next = method;
|
|
|
|
else
|
|
|
|
eap_methods = method;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_peer_unregister_methods(void)
|
|
|
|
{
|
|
|
|
struct eap_method *m;
|
|
|
|
while (eap_methods) {
|
|
|
|
m = eap_methods;
|
|
|
|
eap_methods = eap_methods->next;
|
|
|
|
|
|
|
|
if (m->free)
|
|
|
|
m->free(m);
|
|
|
|
else
|
|
|
|
eap_peer_method_free(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int eap_peer_register_methods(void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
#ifdef EAP_MD5
|
|
|
|
if (ret == 0)
|
|
|
|
ret = eap_peer_md5_register();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef EAP_TLS
|
|
|
|
if (ret == 0)
|
|
|
|
ret = eap_peer_tls_register();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef EAP_MSCHAPv2
|
|
|
|
if (ret == 0)
|
|
|
|
ret = eap_peer_mschapv2_register();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef EAP_PEAP
|
|
|
|
if (ret == 0)
|
|
|
|
ret = eap_peer_peap_register();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef EAP_TTLS
|
|
|
|
if (ret == 0)
|
|
|
|
ret = eap_peer_ttls_register();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
|
|
|
{
|
|
|
|
if (sm->m == NULL || sm->eap_method_priv == NULL)
|
|
|
|
return;
|
|
|
|
sm->m->deinit(sm, sm->eap_method_priv);
|
|
|
|
sm->eap_method_priv = NULL;
|
|
|
|
sm->m = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted)
|
|
|
|
{
|
|
|
|
const u8 *identity;
|
|
|
|
size_t identity_len;
|
|
|
|
struct wpabuf *eap_buf = NULL;
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
|
|
|
|
if (config == NULL) {
|
|
|
|
wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> configuration was not available\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sm->m && sm->m->get_identity) {
|
|
|
|
identity = sm->m->get_identity(sm,
|
|
|
|
sm->eap_method_priv,
|
|
|
|
&identity_len);
|
|
|
|
} else if (!encrypted && config->anonymous_identity) {
|
|
|
|
identity = config->anonymous_identity;
|
|
|
|
identity_len = config->anonymous_identity_len;
|
|
|
|
} else {
|
|
|
|
identity = config->identity;
|
|
|
|
identity_len = config->identity_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (identity == NULL) {
|
|
|
|
wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> identity was not available\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
|
|
|
|
identity_len, EAP_CODE_RESPONSE, id);
|
|
|
|
if (!eap_buf) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wpabuf_put_data(eap_buf, identity, identity_len);
|
|
|
|
return eap_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id)
|
|
|
|
{
|
|
|
|
size_t count = 0;
|
|
|
|
int found = 0;
|
|
|
|
struct wpabuf *resp;
|
|
|
|
const struct eap_method *methods, *m;
|
|
|
|
|
|
|
|
methods = eap_peer_get_methods(&count);
|
|
|
|
if (methods == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (type == EAP_TYPE_EXPANDED) {
|
|
|
|
/*Build Expanded NAK*/
|
|
|
|
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
|
|
|
|
8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
|
|
|
|
if (resp == NULL)
|
|
|
|
return NULL;
|
|
|
|
wpabuf_put_be24(resp, EAP_VENDOR_IETF);
|
|
|
|
wpabuf_put_be32(resp, EAP_TYPE_NAK);
|
|
|
|
} else {
|
|
|
|
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
|
|
|
|
sizeof(struct eap_hdr) + 1 + count + 1,
|
|
|
|
EAP_CODE_RESPONSE, id);
|
|
|
|
if (resp == NULL)
|
|
|
|
return NULL;
|
|
|
|
wpabuf_put(resp, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (m = methods; m; m = m->next) {
|
2018-09-01 09:59:48 +00:00
|
|
|
//do not propose insecure unencapsulated MSCHAPv2 as Phase 1 Method
|
|
|
|
if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_MSCHAPV2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
//do not propose EAP_TYPE_TLS if no client cert/key are configured
|
|
|
|
if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_TLS) {
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL || config->private_key == 0 || config->client_cert == 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-04-20 03:33:04 +00:00
|
|
|
if (type == EAP_TYPE_EXPANDED) {
|
|
|
|
wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
|
|
|
|
wpabuf_put_be24(resp, m->vendor);
|
|
|
|
wpabuf_put_be32(resp, m->method);
|
|
|
|
} else
|
2018-05-30 05:48:29 +00:00
|
|
|
wpabuf_put_u8(resp, m->method);
|
2018-04-20 03:33:04 +00:00
|
|
|
found++;
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
if (type == EAP_TYPE_EXPANDED) {
|
|
|
|
wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
|
|
|
|
wpabuf_put_be24(resp, EAP_VENDOR_IETF);
|
|
|
|
wpabuf_put_be32(resp, EAP_TYPE_NONE);
|
|
|
|
} else
|
|
|
|
wpabuf_put_u8(resp, EAP_TYPE_NONE);
|
|
|
|
}
|
|
|
|
eap_update_len(resp);
|
|
|
|
return resp;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int eap_peer_config_init(
|
2018-08-13 08:37:56 +00:00
|
|
|
struct eap_sm *sm, const u8 *private_key_passwd,
|
2018-04-20 03:33:04 +00:00
|
|
|
int private_key_passwd_len)
|
|
|
|
{
|
|
|
|
if (!sm)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
sm->config.anonymous_identity = NULL;
|
|
|
|
sm->config.identity = NULL;
|
|
|
|
sm->config.password = NULL;
|
|
|
|
sm->config.new_password = NULL;
|
|
|
|
|
|
|
|
sm->config.private_key_passwd = private_key_passwd;
|
|
|
|
sm->config.client_cert = (u8 *)sm->blob[0].name;
|
|
|
|
sm->config.private_key = (u8 *)sm->blob[1].name;
|
|
|
|
sm->config.ca_cert = (u8 *)sm->blob[2].name;
|
|
|
|
|
|
|
|
sm->config.ca_path = NULL;
|
|
|
|
|
|
|
|
sm->config.fragment_size = 1400; /* fragment size */
|
|
|
|
|
|
|
|
/* anonymous identity */
|
|
|
|
if (g_wpa_anonymous_identity && g_wpa_anonymous_identity_len > 0) {
|
|
|
|
sm->config.anonymous_identity_len = g_wpa_anonymous_identity_len;
|
|
|
|
sm->config.anonymous_identity = (u8 *)os_zalloc(sm->config.anonymous_identity_len);
|
|
|
|
if (sm->config.anonymous_identity == NULL)
|
|
|
|
return -2;
|
|
|
|
os_memcpy(sm->config.anonymous_identity, g_wpa_anonymous_identity, g_wpa_anonymous_identity_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Configre identity */
|
|
|
|
if (g_wpa_username && g_wpa_username_len > 0) {
|
|
|
|
sm->config.identity_len = g_wpa_username_len;
|
|
|
|
sm->config.identity = (u8 *)os_zalloc(sm->config.identity_len);
|
|
|
|
if (sm->config.identity == NULL) {
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
os_memcpy(sm->config.identity, g_wpa_username, g_wpa_username_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_wpa_password && g_wpa_password_len) {
|
|
|
|
sm->config.password_len = g_wpa_password_len;
|
|
|
|
sm->config.password = (u8 *)os_zalloc(sm->config.password_len);
|
|
|
|
if (sm->config.password == NULL)
|
|
|
|
return -2;
|
|
|
|
os_memcpy(sm->config.password, g_wpa_password, sm->config.password_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_wpa_new_password && g_wpa_new_password_len) {
|
|
|
|
sm->config.new_password_len = g_wpa_new_password_len;
|
|
|
|
sm->config.new_password = (u8 *)os_zalloc(sm->config.new_password_len);
|
|
|
|
if (sm->config.new_password == NULL)
|
|
|
|
return -2;
|
|
|
|
os_memcpy(sm->config.new_password, g_wpa_new_password,
|
|
|
|
sm->config.new_password_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_peer_config_deinit(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
if (!sm)
|
|
|
|
return;
|
|
|
|
|
|
|
|
os_free(sm->config.anonymous_identity);
|
|
|
|
os_free(sm->config.identity);
|
|
|
|
os_free(sm->config.password);
|
|
|
|
os_free(sm->config.new_password);
|
|
|
|
os_bzero(&sm->config, sizeof(struct eap_peer_config));
|
|
|
|
}
|
|
|
|
|
|
|
|
int eap_peer_blob_init(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
if (!sm)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (g_wpa_client_cert && g_wpa_client_cert_len) {
|
|
|
|
sm->blob[0].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
|
|
|
|
if (sm->blob[0].name == NULL) {
|
|
|
|
ret = -2;
|
|
|
|
goto _out;
|
|
|
|
}
|
2018-05-29 07:36:43 +00:00
|
|
|
os_strncpy(sm->blob[0].name, CLIENT_CERT_NAME, BLOB_NAME_LEN+1);
|
2018-04-20 03:33:04 +00:00
|
|
|
sm->blob[0].len = g_wpa_client_cert_len;
|
|
|
|
sm->blob[0].data = g_wpa_client_cert;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_wpa_private_key && g_wpa_private_key_len) {
|
|
|
|
sm->blob[1].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
|
|
|
|
if (sm->blob[1].name == NULL) {
|
|
|
|
ret = -2;
|
|
|
|
goto _out;
|
|
|
|
}
|
2018-05-29 07:36:43 +00:00
|
|
|
os_strncpy(sm->blob[1].name, PRIVATE_KEY_NAME, BLOB_NAME_LEN+1);
|
2018-04-20 03:33:04 +00:00
|
|
|
sm->blob[1].len = g_wpa_private_key_len;
|
|
|
|
sm->blob[1].data = g_wpa_private_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_wpa_ca_cert && g_wpa_ca_cert_len) {
|
|
|
|
sm->blob[2].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
|
|
|
|
if (sm->blob[2].name == NULL) {
|
|
|
|
ret = -2;
|
|
|
|
goto _out;
|
|
|
|
}
|
2018-05-29 07:36:43 +00:00
|
|
|
os_strncpy(sm->blob[2].name, CA_CERT_NAME, BLOB_NAME_LEN+1);
|
2018-04-20 03:33:04 +00:00
|
|
|
sm->blob[2].len = g_wpa_ca_cert_len;
|
|
|
|
sm->blob[2].data = g_wpa_ca_cert;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
_out:
|
|
|
|
for (i = 0; i < BLOB_NUM; i++) {
|
|
|
|
if (sm->blob[i].name) {
|
|
|
|
os_free(sm->blob[i].name);
|
|
|
|
sm->blob[i].name = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_peer_blob_deinit(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < BLOB_NUM; i++) {
|
|
|
|
if (sm->blob[i].name) {
|
|
|
|
os_free(sm->blob[i].name);
|
|
|
|
sm->blob[i].name = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
|
|
|
|
|
|
|
|
sm->config.client_cert = NULL;
|
|
|
|
sm->config.private_key = NULL;
|
|
|
|
sm->config.ca_cert = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void eap_sm_abort(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
wpabuf_free(sm->lastRespData);
|
|
|
|
sm->lastRespData = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* eap_get_config - Get current network configuration
|
|
|
|
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
|
|
|
* Returns: Pointer to the current network configuration or %NULL if not found
|
|
|
|
*
|
|
|
|
* EAP peer methods should avoid using this function if they can use other
|
|
|
|
* access functions, like eap_get_config_identity() and
|
|
|
|
* eap_get_config_password(), that do not require direct access to
|
|
|
|
* struct eap_peer_config.
|
|
|
|
*/
|
|
|
|
struct eap_peer_config * eap_get_config(struct eap_sm *sm)
|
|
|
|
{
|
|
|
|
return &sm->config;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL)
|
|
|
|
return NULL;
|
|
|
|
*len = config->identity_len;
|
|
|
|
return config->identity;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL)
|
|
|
|
return NULL;
|
|
|
|
*len = config->password_len;
|
|
|
|
return config->password;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
|
|
|
|
{
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*len = config->password_len;
|
|
|
|
if (hash)
|
|
|
|
*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
|
|
|
|
return config->password;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
|
|
|
|
{
|
|
|
|
struct eap_peer_config *config = eap_get_config(sm);
|
|
|
|
if (config == NULL)
|
|
|
|
return NULL;
|
|
|
|
*len = config->new_password_len;
|
|
|
|
return config->new_password;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* eap_get_config_blob - Get a named configuration blob
|
|
|
|
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
|
|
|
* @name: Name of the blob
|
|
|
|
* Returns: Pointer to blob data or %NULL if not found
|
|
|
|
*/
|
|
|
|
const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!sm)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < BLOB_NUM; i++) {
|
|
|
|
if (sm->blob[i].name == NULL)
|
|
|
|
continue;
|
|
|
|
if (os_strncmp(name, sm->blob[i].name, BLOB_NAME_LEN) == 0) {
|
|
|
|
return &sm->blob[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|