Home | History | Annotate | Download | only in eap_peer
      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