1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / EAP-Identity
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_identity_data {
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	enum { CONTINUE, SUCCESS, FAILURE } state;
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int pick_up;
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_identity_init(struct eap_sm *sm)
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data;
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data = os_zalloc(sizeof(*data));
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data == NULL)
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data->state = CONTINUE;
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return data;
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_identity_initPickUp(struct eap_sm *sm)
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data;
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data = eap_identity_init(sm);
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data) {
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data->pick_up = 1;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return data;
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_identity_reset(struct eap_sm *sm, void *priv)
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data = priv;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(data);
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv,
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     u8 id)
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data = priv;
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpabuf *req;
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const char *req_data;
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t req_data_len;
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eapol_cb->get_eap_req_id_text) {
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx,
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt							     &req_data_len);
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		req_data = NULL;
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		req_data_len = 0;
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len,
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    EAP_CODE_REQUEST, id);
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (req == NULL) {
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate "
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "memory for request");
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data->state = FAILURE;
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_put_data(req, req_data, req_data_len);
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return req;
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_check(struct eap_sm *sm, void *priv,
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  struct wpabuf *respData)
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *pos;
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       respData, &len);
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos == NULL) {
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame");
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return TRUE;
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return FALSE;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_identity_process(struct eap_sm *sm, void *priv,
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 struct wpabuf *respData)
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data = priv;
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *pos;
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data->pick_up) {
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_identity_check(sm, data, respData)) {
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick "
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "up already started negotiation");
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			data->state = FAILURE;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return;
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data->pick_up = 0;
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       respData, &len);
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos == NULL)
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return; /* Should not happen - frame already validated */
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->identity)
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->update_user = TRUE;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->identity);
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->identity = os_malloc(len ? len : 1);
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->identity == NULL) {
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data->state = FAILURE;
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(sm->identity, pos, len);
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->identity_len = len;
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data->state = SUCCESS;
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_isDone(struct eap_sm *sm, void *priv)
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data = priv;
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return data->state != CONTINUE;
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv)
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_identity_data *data = priv;
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return data->state == SUCCESS;
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_identity_register(void)
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_method *eap;
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret;
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      "Identity");
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (eap == NULL)
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->init = eap_identity_init;
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->initPickUp = eap_identity_initPickUp;
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->reset = eap_identity_reset;
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->buildReq = eap_identity_buildReq;
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->check = eap_identity_check;
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->process = eap_identity_process;
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->isDone = eap_identity_isDone;
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap->isSuccess = eap_identity_isSuccess;
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = eap_server_method_register(eap);
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret)
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eap_server_method_free(eap);
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
181