udp: Merge udp_send and udp_output
[dragonfly.git] / contrib / wpa_supplicant / src / eap_server / eap_identity.c
1 /*
2  * hostapd / EAP-Identity
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19
20
21 struct eap_identity_data {
22         enum { CONTINUE, SUCCESS, FAILURE } state;
23         int pick_up;
24 };
25
26
27 static void * eap_identity_init(struct eap_sm *sm)
28 {
29         struct eap_identity_data *data;
30
31         data = os_zalloc(sizeof(*data));
32         if (data == NULL)
33                 return NULL;
34         data->state = CONTINUE;
35
36         return data;
37 }
38
39
40 static void * eap_identity_initPickUp(struct eap_sm *sm)
41 {
42         struct eap_identity_data *data;
43         data = eap_identity_init(sm);
44         if (data) {
45                 data->pick_up = 1;
46         }
47         return data;
48 }
49
50
51 static void eap_identity_reset(struct eap_sm *sm, void *priv)
52 {
53         struct eap_identity_data *data = priv;
54         os_free(data);
55 }
56
57
58 static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv,
59                                              u8 id)
60 {
61         struct eap_identity_data *data = priv;
62         struct wpabuf *req;
63         const char *req_data;
64         size_t req_data_len;
65
66         if (sm->eapol_cb->get_eap_req_id_text) {
67                 req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx,
68                                                              &req_data_len);
69         } else {
70                 req_data = NULL;
71                 req_data_len = 0;
72         }
73         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len,
74                             EAP_CODE_REQUEST, id);
75         if (req == NULL) {
76                 wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate "
77                            "memory for request");
78                 data->state = FAILURE;
79                 return NULL;
80         }
81
82         wpabuf_put_data(req, req_data, req_data_len);
83
84         return req;
85 }
86
87
88 static Boolean eap_identity_check(struct eap_sm *sm, void *priv,
89                                   struct wpabuf *respData)
90 {
91         const u8 *pos;
92         size_t len;
93
94         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
95                                respData, &len);
96         if (pos == NULL) {
97                 wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame");
98                 return TRUE;
99         }
100
101         return FALSE;
102 }
103
104
105 static void eap_identity_process(struct eap_sm *sm, void *priv,
106                                  struct wpabuf *respData)
107 {
108         struct eap_identity_data *data = priv;
109         const u8 *pos;
110         size_t len;
111
112         if (data->pick_up) {
113                 if (eap_identity_check(sm, data, respData)) {
114                         wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick "
115                                    "up already started negotiation");
116                         data->state = FAILURE;
117                         return;
118                 }
119                 data->pick_up = 0;
120         }
121
122         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
123                                respData, &len);
124         if (pos == NULL)
125                 return; /* Should not happen - frame already validated */
126
127         wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
128         if (sm->identity)
129                 sm->update_user = TRUE;
130         os_free(sm->identity);
131         sm->identity = os_malloc(len ? len : 1);
132         if (sm->identity == NULL) {
133                 data->state = FAILURE;
134         } else {
135                 os_memcpy(sm->identity, pos, len);
136                 sm->identity_len = len;
137                 data->state = SUCCESS;
138         }
139 }
140
141
142 static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv)
143 {
144         struct eap_identity_data *data = priv;
145         return data->state != CONTINUE;
146 }
147
148
149 static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv)
150 {
151         struct eap_identity_data *data = priv;
152         return data->state == SUCCESS;
153 }
154
155
156 int eap_server_identity_register(void)
157 {
158         struct eap_method *eap;
159         int ret;
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
176         ret = eap_server_method_register(eap);
177         if (ret)
178                 eap_server_method_free(eap);
179         return ret;
180 }