updated Doxyfile
[strongswan.git] / src / charon / encoding / payloads / eap_payload.c
1 /*
2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <stddef.h>
20
21 #include "eap_payload.h"
22
23 #include <daemon.h>
24
25 typedef struct private_eap_payload_t private_eap_payload_t;
26
27 /**
28 * Private data of an eap_payload_t object.
29 *
30 */
31 struct private_eap_payload_t {
32 /**
33 * Public eap_payload_t interface.
34 */
35 eap_payload_t public;
36
37 /**
38 * Next payload type.
39 */
40 u_int8_t next_payload;
41
42 /**
43 * Critical flag.
44 */
45 bool critical;
46
47 /**
48 * Length of this payload.
49 */
50 u_int16_t payload_length;
51
52 /**
53 * EAP message data, if available
54 */
55 chunk_t data;
56 };
57
58 /**
59 * Encoding rules to parse or generate a EAP payload.
60 *
61 * The defined offsets are the positions in a object of type
62 * private_eap_payload_t.
63 *
64 */
65 encoding_rule_t eap_payload_encodings[] = {
66 /* 1 Byte next payload type, stored in the field next_payload */
67 { U_INT_8, offsetof(private_eap_payload_t, next_payload) },
68 /* the critical bit */
69 { FLAG, offsetof(private_eap_payload_t, critical) },
70 /* 7 Bit reserved bits, nowhere stored */
71 { RESERVED_BIT, 0 },
72 { RESERVED_BIT, 0 },
73 { RESERVED_BIT, 0 },
74 { RESERVED_BIT, 0 },
75 { RESERVED_BIT, 0 },
76 { RESERVED_BIT, 0 },
77 { RESERVED_BIT, 0 },
78 /* Length of the whole payload*/
79 { PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
80 /* chunt to data, starting at "code" */
81 { EAP_DATA, offsetof(private_eap_payload_t, data) },
82 };
83
84 /*
85 1 2 3
86 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
87 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88 ! Next Payload !C! RESERVED ! Payload Length !
89 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 ! Code ! Identifier ! Length !
91 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92 ! Type ! Type_Data...
93 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
94 */
95
96 /**
97 * Implementation of payload_t.verify.
98 */
99 static status_t verify(private_eap_payload_t *this)
100 {
101 u_int16_t length;
102 u_int8_t code;
103
104 if (this->data.len < 4)
105 {
106 DBG1(DBG_ENC, "EAP payloads EAP message too short (%d)", this->data.len);
107 return FAILED;
108 }
109 code = *this->data.ptr;
110 length = htons(*(u_int16_t*)(this->data.ptr + 2));
111 if (this->data.len != length)
112 {
113 DBG1(DBG_ENC, "EAP payload length (%d) does not match contained message length (%d)",
114 this->data.len, length);
115 return FAILED;
116 }
117 switch (code)
118 {
119 case EAP_REQUEST:
120 case EAP_RESPONSE:
121 {
122 if (this->data.len < 4)
123 {
124 DBG1(DBG_ENC, "EAP Request/Response does not have any data");
125 return FAILED;
126 }
127 break;
128 }
129 case EAP_SUCCESS:
130 case EAP_FAILURE:
131 {
132 if (this->data.len != 4)
133 {
134 DBG1(DBG_ENC, "EAP Success/Failure has data");
135 return FAILED;
136 }
137 break;
138 }
139 default:
140 return FAILED;
141 }
142 return SUCCESS;
143 }
144
145 /**
146 * Implementation of eap_payload_t.get_encoding_rules.
147 */
148 static void get_encoding_rules(private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
149 {
150 *rules = eap_payload_encodings;
151 *rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
152 }
153
154 /**
155 * Implementation of payload_t.get_type.
156 */
157 static payload_type_t get_payload_type(private_eap_payload_t *this)
158 {
159 return EXTENSIBLE_AUTHENTICATION;
160 }
161
162 /**
163 * Implementation of payload_t.get_next_type.
164 */
165 static payload_type_t get_next_type(private_eap_payload_t *this)
166 {
167 return (this->next_payload);
168 }
169
170 /**
171 * Implementation of payload_t.set_next_type.
172 */
173 static void set_next_type(private_eap_payload_t *this,payload_type_t type)
174 {
175 this->next_payload = type;
176 }
177
178 /**
179 * Implementation of payload_t.get_length.
180 */
181 static size_t get_length(private_eap_payload_t *this)
182 {
183 return this->payload_length;
184 }
185
186 /**
187 * Implementation of eap_payload_t.get_data.
188 */
189 static chunk_t get_data(private_eap_payload_t *this)
190 {
191 return this->data;
192 }
193
194 /**
195 * Implementation of eap_payload_t.set_data.
196 */
197 static void set_data(private_eap_payload_t *this, chunk_t data)
198 {
199 chunk_free(&this->data);
200 this->data = chunk_clone(data);
201 this->payload_length = this->data.len + 4;
202 }
203
204 /**
205 * Implementation of eap_payload_t.get_code.
206 */
207 static eap_code_t get_code(private_eap_payload_t *this)
208 {
209 if (this->data.len > 0)
210 {
211 return *this->data.ptr;
212 }
213 /* should not happen, as it is verified */
214 return 0;
215 }
216
217 /**
218 * Implementation of eap_payload_t.get_identifier.
219 */
220 static u_int8_t get_identifier(private_eap_payload_t *this)
221 {
222 if (this->data.len > 1)
223 {
224 return *(this->data.ptr + 1);
225 }
226 /* should not happen, as it is verified */
227 return 0;
228 }
229
230 /**
231 * Implementation of eap_payload_t.get_type.
232 */
233 static eap_type_t get_type(private_eap_payload_t *this, u_int32_t *vendor)
234 {
235 eap_type_t type;
236
237 *vendor = 0;
238 if (this->data.len > 4)
239 {
240 type = *(this->data.ptr + 4);
241 if (type != EAP_EXPANDED)
242 {
243 return type;
244 }
245 if (this->data.len >= 12)
246 {
247 *vendor = ntohl(*(u_int32_t*)(this->data.ptr + 4)) & 0x00FFFFFF;
248 return ntohl(*(u_int32_t*)(this->data.ptr + 8));
249 }
250 }
251 return 0;
252 }
253
254 /**
255 * Implementation of payload_t.destroy and eap_payload_t.destroy.
256 */
257 static void destroy(private_eap_payload_t *this)
258 {
259 chunk_free(&this->data);
260 free(this);
261 }
262
263 /*
264 * Described in header
265 */
266 eap_payload_t *eap_payload_create()
267 {
268 private_eap_payload_t *this = malloc_thing(private_eap_payload_t);
269
270 /* interface functions */
271 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
272 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
273 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
274 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
275 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
276 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
277 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
278
279 /* public functions */
280 this->public.destroy = (void (*) (eap_payload_t *)) destroy;
281 this->public.get_data = (chunk_t (*) (eap_payload_t*))get_data;
282 this->public.set_data = (void (*) (eap_payload_t *,chunk_t))set_data;
283 this->public.get_code = (eap_code_t (*) (eap_payload_t*))get_code;
284 this->public.get_identifier = (u_int8_t (*) (eap_payload_t*))get_identifier;
285 this->public.get_type = (eap_type_t (*) (eap_payload_t*,u_int32_t*))get_type;
286
287 /* private variables */
288 this->critical = FALSE;
289 this->next_payload = NO_PAYLOAD;
290 this->payload_length = EAP_PAYLOAD_HEADER_LENGTH;
291 this->data = chunk_empty;
292
293 return &(this->public);
294 }
295
296 /*
297 * Described in header
298 */
299 eap_payload_t *eap_payload_create_data(chunk_t data)
300 {
301 eap_payload_t *this = eap_payload_create();
302
303 this->set_data(this, data);
304 return this;
305 }
306
307 /*
308 * Described in header
309 */
310 eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier)
311 {
312 eap_payload_t *this = eap_payload_create();
313 chunk_t data = chunk_alloca(4);
314
315 *(data.ptr + 0) = code;
316 *(data.ptr + 1) = identifier;
317 *(u_int16_t*)(data.ptr + 2) = htons(data.len);
318
319 this->set_data(this, data);
320 return this;
321 }
322
323 /*
324 * Described in header
325 */
326 eap_payload_t *eap_payload_create_nak(u_int8_t identifier)
327 {
328 eap_payload_t *this = eap_payload_create();
329 chunk_t data = chunk_alloca(5);
330
331 *(data.ptr + 0) = EAP_RESPONSE;
332 *(data.ptr + 1) = identifier;
333 *(u_int16_t*)(data.ptr + 2) = htons(data.len);
334 *(data.ptr + 4) = EAP_NAK;
335
336 this->set_data(this, data);
337 return this;
338 }
339