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