Merge branch 'vendor/FLEX'
[dragonfly.git] / contrib / hostapd / src / eap_peer / eap_vendor_test.c
1 /*
2  * EAP peer method: Test method for vendor specific (expanded) EAP type
3  * Copyright (c) 2005-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  * This file implements a vendor specific test method using EAP expanded types.
15  * This is only for test use and must not be used for authentication since no
16  * security is provided.
17  */
18
19 #include "includes.h"
20
21 #include "common.h"
22 #include "eap_i.h"
23 #ifdef TEST_PENDING_REQUEST
24 #include "eloop.h"
25 #endif /* TEST_PENDING_REQUEST */
26
27
28 #define EAP_VENDOR_ID 0xfffefd
29 #define EAP_VENDOR_TYPE 0xfcfbfaf9
30
31
32 /* #define TEST_PENDING_REQUEST */
33
34 struct eap_vendor_test_data {
35         enum { INIT, CONFIRM, SUCCESS } state;
36         int first_try;
37 };
38
39
40 static void * eap_vendor_test_init(struct eap_sm *sm)
41 {
42         struct eap_vendor_test_data *data;
43         data = os_zalloc(sizeof(*data));
44         if (data == NULL)
45                 return NULL;
46         data->state = INIT;
47         data->first_try = 1;
48         return data;
49 }
50
51
52 static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv)
53 {
54         struct eap_vendor_test_data *data = priv;
55         os_free(data);
56 }
57
58
59 #ifdef TEST_PENDING_REQUEST
60 static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx)
61 {
62         struct eap_sm *sm = eloop_ctx;
63         wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending "
64                    "request");
65         eap_notify_pending(sm);
66 }
67 #endif /* TEST_PENDING_REQUEST */
68
69
70 static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv,
71                                                struct eap_method_ret *ret,
72                                                const struct wpabuf *reqData)
73 {
74         struct eap_vendor_test_data *data = priv;
75         struct wpabuf *resp;
76         const u8 *pos;
77         size_t len;
78
79         pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len);
80         if (pos == NULL || len < 1) {
81                 ret->ignore = TRUE;
82                 return NULL;
83         }
84
85         if (data->state == INIT && *pos != 1) {
86                 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
87                            "%d in INIT state", *pos);
88                 ret->ignore = TRUE;
89                 return NULL;
90         }
91
92         if (data->state == CONFIRM && *pos != 3) {
93                 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
94                            "%d in CONFIRM state", *pos);
95                 ret->ignore = TRUE;
96                 return NULL;
97         }
98
99         if (data->state == SUCCESS) {
100                 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
101                            "in SUCCESS state");
102                 ret->ignore = TRUE;
103                 return NULL;
104         }
105
106         if (data->state == CONFIRM) {
107 #ifdef TEST_PENDING_REQUEST
108                 if (data->first_try) {
109                         data->first_try = 0;
110                         wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing "
111                                    "pending request");
112                         ret->ignore = TRUE;
113                         eloop_register_timeout(1, 0, eap_vendor_ready, sm,
114                                                NULL);
115                         return NULL;
116                 }
117 #endif /* TEST_PENDING_REQUEST */
118         }
119
120         ret->ignore = FALSE;
121
122         wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response");
123         ret->allowNotifications = TRUE;
124
125         resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1,
126                              EAP_CODE_RESPONSE, eap_get_id(reqData));
127         if (resp == NULL)
128                 return NULL;
129
130         if (data->state == INIT) {
131                 wpabuf_put_u8(resp, 2);
132                 data->state = CONFIRM;
133                 ret->methodState = METHOD_CONT;
134                 ret->decision = DECISION_FAIL;
135         } else {
136                 wpabuf_put_u8(resp, 4);
137                 data->state = SUCCESS;
138                 ret->methodState = METHOD_DONE;
139                 ret->decision = DECISION_UNCOND_SUCC;
140         }
141
142         return resp;
143 }
144
145
146 static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv)
147 {
148         struct eap_vendor_test_data *data = priv;
149         return data->state == SUCCESS;
150 }
151
152
153 static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len)
154 {
155         struct eap_vendor_test_data *data = priv;
156         u8 *key;
157         const int key_len = 64;
158
159         if (data->state != SUCCESS)
160                 return NULL;
161
162         key = os_malloc(key_len);
163         if (key == NULL)
164                 return NULL;
165
166         os_memset(key, 0x11, key_len / 2);
167         os_memset(key + key_len / 2, 0x22, key_len / 2);
168         *len = key_len;
169
170         return key;
171 }
172
173
174 int eap_peer_vendor_test_register(void)
175 {
176         struct eap_method *eap;
177         int ret;
178
179         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
180                                     EAP_VENDOR_ID, EAP_VENDOR_TYPE,
181                                     "VENDOR-TEST");
182         if (eap == NULL)
183                 return -1;
184
185         eap->init = eap_vendor_test_init;
186         eap->deinit = eap_vendor_test_deinit;
187         eap->process = eap_vendor_test_process;
188         eap->isKeyAvailable = eap_vendor_test_isKeyAvailable;
189         eap->getKey = eap_vendor_test_getKey;
190
191         ret = eap_peer_method_register(eap);
192         if (ret)
193                 eap_peer_method_free(eap);
194         return ret;
195 }