]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
1 | /* |
2 | * hostapd / EAP-Identity | |
3 | * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> | |
4 | * | |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
6fc6879b JM |
7 | */ |
8 | ||
9 | #include "includes.h" | |
10 | ||
11 | #include "common.h" | |
12 | #include "eap_i.h" | |
13 | ||
14 | ||
15 | struct eap_identity_data { | |
16 | enum { CONTINUE, SUCCESS, FAILURE } state; | |
17 | int pick_up; | |
18 | }; | |
19 | ||
20 | ||
21 | static void * eap_identity_init(struct eap_sm *sm) | |
22 | { | |
23 | struct eap_identity_data *data; | |
24 | ||
25 | data = os_zalloc(sizeof(*data)); | |
26 | if (data == NULL) | |
27 | return NULL; | |
28 | data->state = CONTINUE; | |
29 | ||
30 | return data; | |
31 | } | |
32 | ||
33 | ||
34 | static void * eap_identity_initPickUp(struct eap_sm *sm) | |
35 | { | |
36 | struct eap_identity_data *data; | |
37 | data = eap_identity_init(sm); | |
38 | if (data) { | |
39 | data->pick_up = 1; | |
40 | } | |
41 | return data; | |
42 | } | |
43 | ||
44 | ||
45 | static void eap_identity_reset(struct eap_sm *sm, void *priv) | |
46 | { | |
47 | struct eap_identity_data *data = priv; | |
48 | os_free(data); | |
49 | } | |
50 | ||
51 | ||
52 | static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, | |
53 | u8 id) | |
54 | { | |
55 | struct eap_identity_data *data = priv; | |
56 | struct wpabuf *req; | |
57 | const char *req_data; | |
58 | size_t req_data_len; | |
59 | ||
60 | if (sm->eapol_cb->get_eap_req_id_text) { | |
61 | req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, | |
62 | &req_data_len); | |
63 | } else { | |
64 | req_data = NULL; | |
65 | req_data_len = 0; | |
66 | } | |
67 | req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, | |
68 | EAP_CODE_REQUEST, id); | |
69 | if (req == NULL) { | |
70 | wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " | |
71 | "memory for request"); | |
72 | data->state = FAILURE; | |
73 | return NULL; | |
74 | } | |
75 | ||
76 | wpabuf_put_data(req, req_data, req_data_len); | |
77 | ||
78 | return req; | |
79 | } | |
80 | ||
81 | ||
82 | static Boolean eap_identity_check(struct eap_sm *sm, void *priv, | |
83 | struct wpabuf *respData) | |
84 | { | |
85 | const u8 *pos; | |
86 | size_t len; | |
87 | ||
88 | pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, | |
89 | respData, &len); | |
90 | if (pos == NULL) { | |
91 | wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); | |
92 | return TRUE; | |
93 | } | |
94 | ||
95 | return FALSE; | |
96 | } | |
97 | ||
98 | ||
99 | static void eap_identity_process(struct eap_sm *sm, void *priv, | |
100 | struct wpabuf *respData) | |
101 | { | |
102 | struct eap_identity_data *data = priv; | |
103 | const u8 *pos; | |
104 | size_t len; | |
01f7fe10 | 105 | char *buf; |
6fc6879b JM |
106 | |
107 | if (data->pick_up) { | |
108 | if (eap_identity_check(sm, data, respData)) { | |
109 | wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " | |
110 | "up already started negotiation"); | |
111 | data->state = FAILURE; | |
112 | return; | |
113 | } | |
114 | data->pick_up = 0; | |
115 | } | |
116 | ||
117 | pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, | |
118 | respData, &len); | |
119 | if (pos == NULL) | |
120 | return; /* Should not happen - frame already validated */ | |
121 | ||
122 | wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); | |
95f6f6a4 | 123 | buf = os_malloc(len * 4 + 1); |
01f7fe10 | 124 | if (buf) { |
95f6f6a4 | 125 | printf_encode(buf, len * 4 + 1, pos, len); |
01f7fe10 JM |
126 | eap_log_msg(sm, "EAP-Response/Identity '%s'", buf); |
127 | os_free(buf); | |
128 | } | |
65d50f0a JM |
129 | if (sm->identity) |
130 | sm->update_user = TRUE; | |
6fc6879b JM |
131 | os_free(sm->identity); |
132 | sm->identity = os_malloc(len ? len : 1); | |
133 | if (sm->identity == NULL) { | |
134 | data->state = FAILURE; | |
135 | } else { | |
136 | os_memcpy(sm->identity, pos, len); | |
137 | sm->identity_len = len; | |
138 | data->state = SUCCESS; | |
139 | } | |
140 | } | |
141 | ||
142 | ||
143 | static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) | |
144 | { | |
145 | struct eap_identity_data *data = priv; | |
146 | return data->state != CONTINUE; | |
147 | } | |
148 | ||
149 | ||
150 | static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) | |
151 | { | |
152 | struct eap_identity_data *data = priv; | |
153 | return data->state == SUCCESS; | |
154 | } | |
155 | ||
156 | ||
157 | int eap_server_identity_register(void) | |
158 | { | |
159 | struct eap_method *eap; | |
6fc6879b JM |
160 | |
161 | eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, | |
162 | EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, | |
163 | "Identity"); | |
164 | if (eap == NULL) | |
165 | return -1; | |
166 | ||
167 | eap->init = eap_identity_init; | |
168 | eap->initPickUp = eap_identity_initPickUp; | |
169 | eap->reset = eap_identity_reset; | |
170 | eap->buildReq = eap_identity_buildReq; | |
171 | eap->check = eap_identity_check; | |
172 | eap->process = eap_identity_process; | |
173 | eap->isDone = eap_identity_isDone; | |
174 | eap->isSuccess = eap_identity_isSuccess; | |
175 | ||
814f43cf | 176 | return eap_server_method_register(eap); |
6fc6879b | 177 | } |