2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "eap_payload.h"
24 typedef struct private_eap_payload_t private_eap_payload_t
;
27 * Private data of an eap_payload_t object.
30 struct private_eap_payload_t
{
32 * Public eap_payload_t interface.
39 u_int8_t next_payload
;
52 * Length of this payload.
54 u_int16_t payload_length
;
57 * EAP message data, if available
63 * Encoding rules to parse or generate a EAP payload.
65 * The defined offsets are the positions in a object of type
66 * private_eap_payload_t.
69 static encoding_rule_t encodings
[] = {
70 /* 1 Byte next payload type, stored in the field next_payload */
71 { U_INT_8
, offsetof(private_eap_payload_t
, next_payload
) },
72 /* the critical bit */
73 { FLAG
, offsetof(private_eap_payload_t
, critical
) },
74 /* 7 Bit reserved bits, nowhere stored */
75 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[0]) },
76 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[1]) },
77 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[2]) },
78 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[3]) },
79 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[4]) },
80 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[5]) },
81 { RESERVED_BIT
, offsetof(private_eap_payload_t
, reserved
[6]) },
82 /* Length of the whole payload*/
83 { PAYLOAD_LENGTH
, offsetof(private_eap_payload_t
, payload_length
) },
84 /* chunt to data, starting at "code" */
85 { CHUNK_DATA
, offsetof(private_eap_payload_t
, data
) },
90 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
91 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92 ! Next Payload !C! RESERVED ! Payload Length !
93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 ! Code ! Identifier ! Length !
95 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
100 METHOD(payload_t
, verify
, status_t
,
101 private_eap_payload_t
*this)
106 if (this->data
.len
< 4)
108 DBG1(DBG_ENC
, "EAP payloads EAP message too short (%d)", this->data
.len
);
111 length
= untoh16(this->data
.ptr
+ 2);
112 if (this->data
.len
!= length
)
114 DBG1(DBG_ENC
, "EAP payload length (%d) does not match contained "
115 "message length (%d)", this->data
.len
, length
);
118 code
= this->data
.ptr
[0];
124 if (this->data
.len
< 4)
126 DBG1(DBG_ENC
, "EAP Request/Response does not have any data");
134 if (this->data
.len
!= 4)
136 DBG1(DBG_ENC
, "EAP Success/Failure has data");
147 METHOD(payload_t
, get_encoding_rules
, int,
148 private_eap_payload_t
*this, encoding_rule_t
**rules
)
151 return countof(encodings
);
154 METHOD(payload_t
, get_header_length
, int,
155 private_eap_payload_t
*this)
160 METHOD(payload_t
, get_payload_type
, payload_type_t
,
161 private_eap_payload_t
*this)
163 return EXTENSIBLE_AUTHENTICATION
;
166 METHOD(payload_t
, get_next_type
, payload_type_t
,
167 private_eap_payload_t
*this)
169 return (this->next_payload
);
172 METHOD(payload_t
, set_next_type
, void,
173 private_eap_payload_t
*this, payload_type_t type
)
175 this->next_payload
= type
;
178 METHOD(payload_t
, get_length
, size_t,
179 private_eap_payload_t
*this)
181 return this->payload_length
;
184 METHOD(eap_payload_t
, get_data
, chunk_t
,
185 private_eap_payload_t
*this)
190 METHOD(eap_payload_t
, set_data
, void,
191 private_eap_payload_t
*this, chunk_t data
)
193 free(this->data
.ptr
);
194 this->data
= chunk_clone(data
);
195 this->payload_length
= this->data
.len
+ 4;
198 METHOD(eap_payload_t
, get_code
, eap_code_t
,
199 private_eap_payload_t
*this)
201 if (this->data
.len
> 0)
203 return this->data
.ptr
[0];
205 /* should not happen, as it is verified */
209 METHOD(eap_payload_t
, get_identifier
, u_int8_t
,
210 private_eap_payload_t
*this)
212 if (this->data
.len
> 1)
214 return this->data
.ptr
[1];
216 /* should not happen, as it is verified */
220 METHOD(eap_payload_t
, get_type
, eap_type_t
,
221 private_eap_payload_t
*this, u_int32_t
*vendor
)
226 if (this->data
.len
> 4)
228 type
= this->data
.ptr
[4];
229 if (type
!= EAP_EXPANDED
)
233 if (this->data
.len
>= 12)
235 *vendor
= untoh32(this->data
.ptr
+ 4) & 0x00FFFFFF;
236 return untoh32(this->data
.ptr
+ 8);
242 METHOD2(payload_t
, eap_payload_t
, destroy
, void,
243 private_eap_payload_t
*this)
245 chunk_free(&this->data
);
250 * Described in header
252 eap_payload_t
*eap_payload_create()
254 private_eap_payload_t
*this;
258 .payload_interface
= {
260 .get_encoding_rules
= _get_encoding_rules
,
261 .get_header_length
= _get_header_length
,
262 .get_length
= _get_length
,
263 .get_next_type
= _get_next_type
,
264 .set_next_type
= _set_next_type
,
265 .get_type
= _get_payload_type
,
268 .get_data
= _get_data
,
269 .set_data
= _set_data
,
270 .get_code
= _get_code
,
271 .get_identifier
= _get_identifier
,
272 .get_type
= _get_type
,
275 .next_payload
= NO_PAYLOAD
,
276 .payload_length
= get_header_length(this),
278 return &this->public;
282 * Described in header
284 eap_payload_t
*eap_payload_create_data(chunk_t data
)
286 eap_payload_t
*this = eap_payload_create();
288 this->set_data(this, data
);
293 * Described in header
295 eap_payload_t
*eap_payload_create_data_own(chunk_t data
)
297 eap_payload_t
*this = eap_payload_create();
299 this->set_data(this, data
);
305 * Described in header
307 eap_payload_t
*eap_payload_create_code(eap_code_t code
, u_int8_t identifier
)
311 data
= chunk_from_chars(code
, identifier
, 0, 0);
312 htoun16(data
.ptr
+ 2, data
.len
);
313 return eap_payload_create_data(data
);
317 * Described in header
319 eap_payload_t
*eap_payload_create_nak(u_int8_t identifier
)
323 data
= chunk_from_chars(EAP_RESPONSE
, identifier
, 0, 0, EAP_NAK
);
324 htoun16(data
.ptr
+ 2, data
.len
);
325 return eap_payload_create_data(data
);