1 /* 2 * EAP peer method: Test method for vendor specific (expanded) EAP type 3 * Copyright (c) 2005-2006, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 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 EAP_VENDOR_HOSTAP 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 } 190