Home | History | Annotate | Download | only in eap_server
      1 /*
      2  * hostapd / Test method for vendor specific (expanded) EAP type
      3  * Copyright (c) 2005-2007, Jouni Malinen <j (at) 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 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "eap_i.h"
     19 
     20 
     21 #define EAP_VENDOR_ID 0xfffefd
     22 #define EAP_VENDOR_TYPE 0xfcfbfaf9
     23 
     24 
     25 struct eap_vendor_test_data {
     26 	enum { INIT, CONFIRM, SUCCESS, FAILURE } state;
     27 };
     28 
     29 
     30 static const char * eap_vendor_test_state_txt(int state)
     31 {
     32 	switch (state) {
     33 	case INIT:
     34 		return "INIT";
     35 	case CONFIRM:
     36 		return "CONFIRM";
     37 	case SUCCESS:
     38 		return "SUCCESS";
     39 	case FAILURE:
     40 		return "FAILURE";
     41 	default:
     42 		return "?";
     43 	}
     44 }
     45 
     46 
     47 static void eap_vendor_test_state(struct eap_vendor_test_data *data,
     48 				  int state)
     49 {
     50 	wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: %s -> %s",
     51 		   eap_vendor_test_state_txt(data->state),
     52 		   eap_vendor_test_state_txt(state));
     53 	data->state = state;
     54 }
     55 
     56 
     57 static void * eap_vendor_test_init(struct eap_sm *sm)
     58 {
     59 	struct eap_vendor_test_data *data;
     60 
     61 	data = os_zalloc(sizeof(*data));
     62 	if (data == NULL)
     63 		return NULL;
     64 	data->state = INIT;
     65 
     66 	return data;
     67 }
     68 
     69 
     70 static void eap_vendor_test_reset(struct eap_sm *sm, void *priv)
     71 {
     72 	struct eap_vendor_test_data *data = priv;
     73 	os_free(data);
     74 }
     75 
     76 
     77 static struct wpabuf * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv,
     78 						u8 id)
     79 {
     80 	struct eap_vendor_test_data *data = priv;
     81 	struct wpabuf *req;
     82 
     83 	req = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1,
     84 			    EAP_CODE_REQUEST, id);
     85 	if (req == NULL) {
     86 		wpa_printf(MSG_ERROR, "EAP-VENDOR-TEST: Failed to allocate "
     87 			   "memory for request");
     88 		return NULL;
     89 	}
     90 
     91 	wpabuf_put_u8(req, data->state == INIT ? 1 : 3);
     92 
     93 	return req;
     94 }
     95 
     96 
     97 static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv,
     98 				     struct wpabuf *respData)
     99 {
    100 	const u8 *pos;
    101 	size_t len;
    102 
    103 	pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len);
    104 	if (pos == NULL || len < 1) {
    105 		wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame");
    106 		return TRUE;
    107 	}
    108 
    109 	return FALSE;
    110 }
    111 
    112 
    113 static void eap_vendor_test_process(struct eap_sm *sm, void *priv,
    114 				    struct wpabuf *respData)
    115 {
    116 	struct eap_vendor_test_data *data = priv;
    117 	const u8 *pos;
    118 	size_t len;
    119 
    120 	pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len);
    121 	if (pos == NULL || len < 1)
    122 		return;
    123 
    124 	if (data->state == INIT) {
    125 		if (*pos == 2)
    126 			eap_vendor_test_state(data, CONFIRM);
    127 		else
    128 			eap_vendor_test_state(data, FAILURE);
    129 	} else if (data->state == CONFIRM) {
    130 		if (*pos == 4)
    131 			eap_vendor_test_state(data, SUCCESS);
    132 		else
    133 			eap_vendor_test_state(data, FAILURE);
    134 	} else
    135 		eap_vendor_test_state(data, FAILURE);
    136 }
    137 
    138 
    139 static Boolean eap_vendor_test_isDone(struct eap_sm *sm, void *priv)
    140 {
    141 	struct eap_vendor_test_data *data = priv;
    142 	return data->state == SUCCESS;
    143 }
    144 
    145 
    146 static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len)
    147 {
    148 	struct eap_vendor_test_data *data = priv;
    149 	u8 *key;
    150 	const int key_len = 64;
    151 
    152 	if (data->state != SUCCESS)
    153 		return NULL;
    154 
    155 	key = os_malloc(key_len);
    156 	if (key == NULL)
    157 		return NULL;
    158 
    159 	os_memset(key, 0x11, key_len / 2);
    160 	os_memset(key + key_len / 2, 0x22, key_len / 2);
    161 	*len = key_len;
    162 
    163 	return key;
    164 }
    165 
    166 
    167 static Boolean eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv)
    168 {
    169 	struct eap_vendor_test_data *data = priv;
    170 	return data->state == SUCCESS;
    171 }
    172 
    173 
    174 int eap_server_vendor_test_register(void)
    175 {
    176 	struct eap_method *eap;
    177 	int ret;
    178 
    179 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
    180 				      EAP_VENDOR_ID, EAP_VENDOR_TYPE,
    181 				      "VENDOR-TEST");
    182 	if (eap == NULL)
    183 		return -1;
    184 
    185 	eap->init = eap_vendor_test_init;
    186 	eap->reset = eap_vendor_test_reset;
    187 	eap->buildReq = eap_vendor_test_buildReq;
    188 	eap->check = eap_vendor_test_check;
    189 	eap->process = eap_vendor_test_process;
    190 	eap->isDone = eap_vendor_test_isDone;
    191 	eap->getKey = eap_vendor_test_getKey;
    192 	eap->isSuccess = eap_vendor_test_isSuccess;
    193 
    194 	ret = eap_server_method_register(eap);
    195 	if (ret)
    196 		eap_server_method_free(eap);
    197 	return ret;
    198 }
    199