2 * hostapd / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
3 * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.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.
18 #include <netinet/in.h>
25 /* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */
26 #define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */
27 #define EAP_TLV_NAK_TLV 4
28 #define EAP_TLV_CRYPTO_BINDING_TLV 5
29 #define EAP_TLV_CONNECTION_BINDING_TLV 6
30 #define EAP_TLV_VENDOR_SPECIFIC_TLV 7
31 #define EAP_TLV_URI_TLV 8
32 #define EAP_TLV_EAP_PAYLOAD_TLV 9
33 #define EAP_TLV_INTERMEDIATE_RESULT_TLV 10
35 #define EAP_TLV_RESULT_SUCCESS 1
36 #define EAP_TLV_RESULT_FAILURE 2
40 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
44 static void * eap_tlv_init(struct eap_sm
*sm
)
46 struct eap_tlv_data
*data
;
48 data
= malloc(sizeof(*data
));
51 memset(data
, 0, sizeof(*data
));
52 data
->state
= CONTINUE
;
58 static void eap_tlv_reset(struct eap_sm
*sm
, void *priv
)
60 struct eap_tlv_data
*data
= priv
;
65 static u8
* eap_tlv_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
72 if (sm
->tlv_request
== TLV_REQ_SUCCESS
) {
73 status
= EAP_TLV_RESULT_SUCCESS
;
75 status
= EAP_TLV_RESULT_FAILURE
;
78 *reqDataLen
= sizeof(struct eap_hdr
) + 1 + 6;
79 req
= malloc(*reqDataLen
);
83 req
->code
= EAP_CODE_REQUEST
;
85 req
->length
= host_to_be16(*reqDataLen
);
86 pos
= (u8
*) (req
+ 1);
87 *pos
++ = EAP_TYPE_TLV
;
88 *pos
++ = 0x80; /* Mandatory */
89 *pos
++ = EAP_TLV_RESULT_TLV
;
95 *pos
++ = status
& 0xff;
101 static Boolean
eap_tlv_check(struct eap_sm
*sm
, void *priv
,
102 u8
*respData
, size_t respDataLen
)
104 struct eap_hdr
*resp
;
108 resp
= (struct eap_hdr
*) respData
;
109 pos
= (u8
*) (resp
+ 1);
110 if (respDataLen
< sizeof(*resp
) + 1 || *pos
!= EAP_TYPE_TLV
||
111 (len
= ntohs(resp
->length
)) > respDataLen
) {
112 wpa_printf(MSG_INFO
, "EAP-TLV: Invalid frame");
120 static void eap_tlv_process(struct eap_sm
*sm
, void *priv
,
121 u8
*respData
, size_t respDataLen
)
123 struct eap_tlv_data
*data
= priv
;
124 struct eap_hdr
*resp
;
128 u8
*result_tlv
= NULL
;
129 size_t result_tlv_len
= 0;
130 int tlv_type
, mandatory
, tlv_len
;
132 resp
= (struct eap_hdr
*) respData
;
133 len
= ntohs(resp
->length
);
134 pos
= (u8
*) (resp
+ 1);
137 left
= be_to_host16(resp
->length
) - sizeof(struct eap_hdr
) - 1;
138 pos
= (u8
*) (resp
+ 1);
140 wpa_hexdump(MSG_DEBUG
, "EAP-TLV: Received TLVs", pos
, left
);
142 mandatory
= !!(pos
[0] & 0x80);
143 tlv_type
= pos
[0] & 0x3f;
144 tlv_type
= (tlv_type
<< 8) | pos
[1];
145 tlv_len
= ((int) pos
[2] << 8) | pos
[3];
148 if (tlv_len
> left
) {
149 wpa_printf(MSG_DEBUG
, "EAP-TLV: TLV underrun "
150 "(tlv_len=%d left=%lu)", tlv_len
,
151 (unsigned long) left
);
152 data
->state
= FAILURE
;
156 case EAP_TLV_RESULT_TLV
:
158 result_tlv_len
= tlv_len
;
161 wpa_printf(MSG_DEBUG
, "EAP-TLV: Unsupported TLV Type "
163 mandatory
? " (mandatory)" : "");
165 data
->state
= FAILURE
;
168 /* Ignore this TLV, but process other TLVs */
176 wpa_printf(MSG_DEBUG
, "EAP-TLV: Last TLV too short in "
177 "Request (left=%lu)", (unsigned long) left
);
178 data
->state
= FAILURE
;
182 /* Process supported TLVs */
185 const char *requested
;
187 wpa_hexdump(MSG_DEBUG
, "EAP-TLV: Result TLV",
188 result_tlv
, result_tlv_len
);
189 if (result_tlv_len
< 2) {
190 wpa_printf(MSG_INFO
, "EAP-TLV: Too short Result TLV "
192 (unsigned long) result_tlv_len
);
193 data
->state
= FAILURE
;
196 requested
= sm
->tlv_request
== TLV_REQ_SUCCESS
? "Success" :
198 status
= ((int) result_tlv
[0] << 8) | result_tlv
[1];
199 if (status
== EAP_TLV_RESULT_SUCCESS
) {
200 wpa_printf(MSG_INFO
, "EAP-TLV: TLV Result - Success "
201 "- requested %s", requested
);
202 if (sm
->tlv_request
== TLV_REQ_SUCCESS
)
203 data
->state
= SUCCESS
;
205 data
->state
= FAILURE
;
207 } else if (status
== EAP_TLV_RESULT_FAILURE
) {
208 wpa_printf(MSG_INFO
, "EAP-TLV: TLV Result - Failure - "
209 "requested %s", requested
);
210 if (sm
->tlv_request
== TLV_REQ_FAILURE
)
211 data
->state
= SUCCESS
;
213 data
->state
= FAILURE
;
215 wpa_printf(MSG_INFO
, "EAP-TLV: Unknown TLV Result "
216 "Status %d", status
);
217 data
->state
= FAILURE
;
223 static Boolean
eap_tlv_isDone(struct eap_sm
*sm
, void *priv
)
225 struct eap_tlv_data
*data
= priv
;
226 return data
->state
!= CONTINUE
;
230 static Boolean
eap_tlv_isSuccess(struct eap_sm
*sm
, void *priv
)
232 struct eap_tlv_data
*data
= priv
;
233 return data
->state
== SUCCESS
;
237 const struct eap_method eap_method_tlv
=
239 .method
= EAP_TYPE_TLV
,
241 .init
= eap_tlv_init
,
242 .reset
= eap_tlv_reset
,
243 .buildReq
= eap_tlv_buildReq
,
244 .check
= eap_tlv_check
,
245 .process
= eap_tlv_process
,
246 .isDone
= eap_tlv_isDone
,
247 .isSuccess
= eap_tlv_isSuccess
,