2 * hostapd / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
22 /* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */
23 #define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */
24 #define EAP_TLV_NAK_TLV 4
25 #define EAP_TLV_CRYPTO_BINDING_TLV 5
26 #define EAP_TLV_CONNECTION_BINDING_TLV 6
27 #define EAP_TLV_VENDOR_SPECIFIC_TLV 7
28 #define EAP_TLV_URI_TLV 8
29 #define EAP_TLV_EAP_PAYLOAD_TLV 9
30 #define EAP_TLV_INTERMEDIATE_RESULT_TLV 10
32 #define EAP_TLV_RESULT_SUCCESS 1
33 #define EAP_TLV_RESULT_FAILURE 2
37 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
41 static void * eap_tlv_init(struct eap_sm
*sm
)
43 struct eap_tlv_data
*data
;
45 data
= wpa_zalloc(sizeof(*data
));
48 data
->state
= CONTINUE
;
54 static void eap_tlv_reset(struct eap_sm
*sm
, void *priv
)
56 struct eap_tlv_data
*data
= priv
;
61 static u8
* eap_tlv_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
68 if (sm
->tlv_request
== TLV_REQ_SUCCESS
) {
69 status
= EAP_TLV_RESULT_SUCCESS
;
71 status
= EAP_TLV_RESULT_FAILURE
;
74 *reqDataLen
= sizeof(struct eap_hdr
) + 1 + 6;
75 req
= malloc(*reqDataLen
);
79 req
->code
= EAP_CODE_REQUEST
;
81 req
->length
= host_to_be16(*reqDataLen
);
82 pos
= (u8
*) (req
+ 1);
83 *pos
++ = EAP_TYPE_TLV
;
84 *pos
++ = 0x80; /* Mandatory */
85 *pos
++ = EAP_TLV_RESULT_TLV
;
91 *pos
++ = status
& 0xff;
97 static Boolean
eap_tlv_check(struct eap_sm
*sm
, void *priv
,
98 u8
*respData
, size_t respDataLen
)
100 struct eap_hdr
*resp
;
103 resp
= (struct eap_hdr
*) respData
;
104 pos
= (u8
*) (resp
+ 1);
105 if (respDataLen
< sizeof(*resp
) + 1 || *pos
!= EAP_TYPE_TLV
||
106 (ntohs(resp
->length
)) > respDataLen
) {
107 wpa_printf(MSG_INFO
, "EAP-TLV: Invalid frame");
115 static void eap_tlv_process(struct eap_sm
*sm
, void *priv
,
116 u8
*respData
, size_t respDataLen
)
118 struct eap_tlv_data
*data
= priv
;
119 struct eap_hdr
*resp
;
122 u8
*result_tlv
= NULL
;
123 size_t result_tlv_len
= 0;
124 int tlv_type
, mandatory
, tlv_len
;
126 resp
= (struct eap_hdr
*) respData
;
127 pos
= (u8
*) (resp
+ 1);
130 left
= be_to_host16(resp
->length
) - sizeof(struct eap_hdr
) - 1;
131 pos
= (u8
*) (resp
+ 1);
133 wpa_hexdump(MSG_DEBUG
, "EAP-TLV: Received TLVs", pos
, left
);
135 mandatory
= !!(pos
[0] & 0x80);
136 tlv_type
= pos
[0] & 0x3f;
137 tlv_type
= (tlv_type
<< 8) | pos
[1];
138 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
141 if ((size_t) tlv_len
> left
) {
142 wpa_printf(MSG_DEBUG
, "EAP-TLV: TLV underrun "
143 "(tlv_len=%d left=%lu)", tlv_len
,
144 (unsigned long) left
);
145 data
->state
= FAILURE
;
149 case EAP_TLV_RESULT_TLV
:
151 result_tlv_len
= tlv_len
;
154 wpa_printf(MSG_DEBUG
, "EAP-TLV: Unsupported TLV Type "
156 mandatory
? " (mandatory)" : "");
158 data
->state
= FAILURE
;
161 /* Ignore this TLV, but process other TLVs */
169 wpa_printf(MSG_DEBUG
, "EAP-TLV: Last TLV too short in "
170 "Request (left=%lu)", (unsigned long) left
);
171 data
->state
= FAILURE
;
175 /* Process supported TLVs */
178 const char *requested
;
180 wpa_hexdump(MSG_DEBUG
, "EAP-TLV: Result TLV",
181 result_tlv
, result_tlv_len
);
182 if (result_tlv_len
< 2) {
183 wpa_printf(MSG_INFO
, "EAP-TLV: Too short Result TLV "
185 (unsigned long) result_tlv_len
);
186 data
->state
= FAILURE
;
189 requested
= sm
->tlv_request
== TLV_REQ_SUCCESS
? "Success" :
191 status
= ((int) result_tlv
[0] << 8) | result_tlv
[1];
192 if (status
== EAP_TLV_RESULT_SUCCESS
) {
193 wpa_printf(MSG_INFO
, "EAP-TLV: TLV Result - Success "
194 "- requested %s", requested
);
195 if (sm
->tlv_request
== TLV_REQ_SUCCESS
)
196 data
->state
= SUCCESS
;
198 data
->state
= FAILURE
;
200 } else if (status
== EAP_TLV_RESULT_FAILURE
) {
201 wpa_printf(MSG_INFO
, "EAP-TLV: TLV Result - Failure - "
202 "requested %s", requested
);
203 if (sm
->tlv_request
== TLV_REQ_FAILURE
)
204 data
->state
= SUCCESS
;
206 data
->state
= FAILURE
;
208 wpa_printf(MSG_INFO
, "EAP-TLV: Unknown TLV Result "
209 "Status %d", status
);
210 data
->state
= FAILURE
;
216 static Boolean
eap_tlv_isDone(struct eap_sm
*sm
, void *priv
)
218 struct eap_tlv_data
*data
= priv
;
219 return data
->state
!= CONTINUE
;
223 static Boolean
eap_tlv_isSuccess(struct eap_sm
*sm
, void *priv
)
225 struct eap_tlv_data
*data
= priv
;
226 return data
->state
== SUCCESS
;
230 int eap_server_tlv_register(void)
232 struct eap_method
*eap
;
235 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
236 EAP_VENDOR_IETF
, EAP_TYPE_TLV
, "TLV");
240 eap
->init
= eap_tlv_init
;
241 eap
->reset
= eap_tlv_reset
;
242 eap
->buildReq
= eap_tlv_buildReq
;
243 eap
->check
= eap_tlv_check
;
244 eap
->process
= eap_tlv_process
;
245 eap
->isDone
= eap_tlv_isDone
;
246 eap
->isSuccess
= eap_tlv_isSuccess
;
248 ret
= eap_server_method_register(eap
);
250 eap_server_method_free(eap
);