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