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