|
1 /* |
|
2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: EAP and WLAN authentication protocols. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // This is enumeration of EAPOL source code. |
|
20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
21 #undef EAP_FILE_NUMBER_ENUM |
|
22 #define EAP_FILE_NUMBER_ENUM 579 |
|
23 #undef EAP_FILE_NUMBER_DATE |
|
24 #define EAP_FILE_NUMBER_DATE 1127594498 |
|
25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
26 |
|
27 |
|
28 |
|
29 #include "eap_am_memory.h" |
|
30 #include "eap_automatic_variable.h" |
|
31 #include "eap_tlv_message_data.h" |
|
32 |
|
33 /** @file */ |
|
34 |
|
35 |
|
36 //-------------------------------------------------- |
|
37 |
|
38 EAP_FUNC_EXPORT eap_tlv_message_data_c::~eap_tlv_message_data_c() |
|
39 { |
|
40 } |
|
41 |
|
42 //-------------------------------------------------- |
|
43 |
|
44 EAP_FUNC_EXPORT eap_tlv_message_data_c::eap_tlv_message_data_c( |
|
45 abs_eap_am_tools_c * const tools) |
|
46 : m_am_tools(tools) |
|
47 , m_message_data(tools) |
|
48 { |
|
49 } |
|
50 |
|
51 //------------------------------------------------------------------- |
|
52 |
|
53 /** |
|
54 * This function should increase reference count. |
|
55 */ |
|
56 EAP_FUNC_EXPORT void eap_tlv_message_data_c::object_increase_reference_count() |
|
57 { |
|
58 } |
|
59 |
|
60 //------------------------------------------------------------------- |
|
61 |
|
62 /** |
|
63 * This function should first decrease reference count |
|
64 * and second return the remaining reference count. |
|
65 * Reference count must not be decreased when it is zero. |
|
66 */ |
|
67 EAP_FUNC_EXPORT u32_t eap_tlv_message_data_c::object_decrease_reference_count() |
|
68 { |
|
69 return 0; |
|
70 } |
|
71 |
|
72 //-------------------------------------------------- |
|
73 |
|
74 EAP_FUNC_EXPORT void * eap_tlv_message_data_c::get_message_data() const |
|
75 { |
|
76 return m_message_data.get_data(m_message_data.get_data_length()); |
|
77 } |
|
78 |
|
79 //-------------------------------------------------- |
|
80 |
|
81 EAP_FUNC_EXPORT u32_t eap_tlv_message_data_c::get_message_data_length() const |
|
82 { |
|
83 return m_message_data.get_data_length(); |
|
84 } |
|
85 |
|
86 //-------------------------------------------------- |
|
87 |
|
88 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::allocate_message_data_buffer( |
|
89 const u32_t approximate_buffer_requirement) |
|
90 { |
|
91 if (m_message_data.get_is_valid() == true) |
|
92 { |
|
93 return m_message_data.set_buffer_length(m_message_data.get_buffer_length()+approximate_buffer_requirement); |
|
94 } |
|
95 else |
|
96 { |
|
97 return m_message_data.set_buffer_length(approximate_buffer_requirement); |
|
98 } |
|
99 } |
|
100 |
|
101 //-------------------------------------------------- |
|
102 |
|
103 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::copy_message_data( |
|
104 const u32_t length, |
|
105 const void * const value) |
|
106 { |
|
107 eap_status_e status(eap_status_process_general_error); |
|
108 |
|
109 EAP_TRACE_DATA_DEBUG( |
|
110 m_am_tools, |
|
111 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
112 (EAPL("copy_message_data()"), |
|
113 value, |
|
114 length)); |
|
115 |
|
116 status = m_message_data.set_copy_of_buffer( |
|
117 value, |
|
118 length); |
|
119 if (status != eap_status_ok) |
|
120 { |
|
121 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
122 return EAP_STATUS_RETURN(m_am_tools, status); |
|
123 } |
|
124 |
|
125 return EAP_STATUS_RETURN(m_am_tools, status); |
|
126 } |
|
127 |
|
128 //-------------------------------------------------- |
|
129 |
|
130 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::set_message_data( |
|
131 const u32_t length, |
|
132 const void * const value) |
|
133 { |
|
134 eap_status_e status(eap_status_process_general_error); |
|
135 |
|
136 EAP_TRACE_DATA_DEBUG( |
|
137 m_am_tools, |
|
138 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
139 (EAPL("set_message_data()"), |
|
140 value, |
|
141 length)); |
|
142 |
|
143 status = m_message_data.set_buffer( |
|
144 value, |
|
145 length, |
|
146 false, |
|
147 false); |
|
148 if (status != eap_status_ok) |
|
149 { |
|
150 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
151 return EAP_STATUS_RETURN(m_am_tools, status); |
|
152 } |
|
153 |
|
154 return EAP_STATUS_RETURN(m_am_tools, status); |
|
155 } |
|
156 |
|
157 //-------------------------------------------------- |
|
158 |
|
159 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::add_message_data( |
|
160 const eap_tlv_type_t type, |
|
161 const u32_t length, |
|
162 const void * const value) |
|
163 { |
|
164 eap_status_e status(eap_status_process_general_error); |
|
165 |
|
166 EAP_TRACE_DEBUG( |
|
167 m_am_tools, |
|
168 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
169 (EAPL("eap_tlv_message_data_c::add_message_data(): type %2d=0x%08x, length %3d=0x%08x\n"), |
|
170 type, |
|
171 type, |
|
172 length, |
|
173 length)); |
|
174 |
|
175 EAP_TRACE_DATA_DEBUG( |
|
176 m_am_tools, |
|
177 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
178 (EAPL("add_message_data()"), |
|
179 value, |
|
180 length)); |
|
181 |
|
182 u32_t tlv_header_offset(0ul); |
|
183 |
|
184 if (m_message_data.get_is_valid() == true) |
|
185 { |
|
186 tlv_header_offset = m_message_data.get_data_length(); |
|
187 } |
|
188 else |
|
189 { |
|
190 tlv_header_offset = 0ul; |
|
191 } |
|
192 |
|
193 // This will allocate space for eap_tlv_header_c too. |
|
194 status = m_message_data.add_data_to_offset( |
|
195 tlv_header_offset+eap_tlv_header_c::get_header_length(), |
|
196 value, |
|
197 length); |
|
198 if (status != eap_status_ok) |
|
199 { |
|
200 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
201 return EAP_STATUS_RETURN(m_am_tools, status); |
|
202 } |
|
203 |
|
204 // Add eap_tlv_header_c to message. |
|
205 eap_tlv_header_c header( |
|
206 m_am_tools, |
|
207 m_message_data.get_data_offset(tlv_header_offset, eap_tlv_header_c::get_header_length()+length), |
|
208 eap_tlv_header_c::get_header_length()+length); |
|
209 |
|
210 if (header.get_is_valid() == false) |
|
211 { |
|
212 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
213 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
214 } |
|
215 |
|
216 status = header.reset_header(type, length); |
|
217 if (status != eap_status_ok) |
|
218 { |
|
219 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
220 return EAP_STATUS_RETURN(m_am_tools, status); |
|
221 } |
|
222 |
|
223 return EAP_STATUS_RETURN(m_am_tools, status); |
|
224 } |
|
225 |
|
226 //-------------------------------------------------- |
|
227 |
|
228 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::add_message_data_array( |
|
229 const eap_tlv_type_t type, |
|
230 const u32_t length_of_each_data_block, |
|
231 eap_array_c<eap_variable_data_c> * const data_array) |
|
232 { |
|
233 eap_status_e status(eap_status_process_general_error); |
|
234 |
|
235 u32_t tlv_header_offset(0ul); |
|
236 |
|
237 if (m_message_data.get_is_valid() == true) |
|
238 { |
|
239 tlv_header_offset = m_message_data.get_data_length(); |
|
240 } |
|
241 else |
|
242 { |
|
243 tlv_header_offset = 0ul; |
|
244 } |
|
245 |
|
246 if (data_array->get_object_count() != 0ul) |
|
247 { |
|
248 for (u32_t ind = 0ul; ind < data_array->get_object_count(); ind++) |
|
249 { |
|
250 eap_variable_data_c * const data = data_array->get_object(ind); |
|
251 if (data == 0) |
|
252 { |
|
253 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
254 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
255 } |
|
256 |
|
257 if (data->get_data_length() != length_of_each_data_block) |
|
258 { |
|
259 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
260 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
261 } |
|
262 |
|
263 // This will allocate space for eap_tlv_header_c too. |
|
264 status = m_message_data.add_data_to_offset( |
|
265 tlv_header_offset+eap_tlv_header_c::get_header_length()+(ind*length_of_each_data_block), |
|
266 data); |
|
267 if (status != eap_status_ok) |
|
268 { |
|
269 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
270 return EAP_STATUS_RETURN(m_am_tools, status); |
|
271 } |
|
272 } // for() |
|
273 } |
|
274 else |
|
275 { |
|
276 // This will allocate space for eap_tlv_header_c only. |
|
277 status = m_message_data.add_data_to_offset( |
|
278 tlv_header_offset+eap_tlv_header_c::get_header_length(), |
|
279 0, |
|
280 0ul); |
|
281 if (status != eap_status_ok) |
|
282 { |
|
283 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
284 return EAP_STATUS_RETURN(m_am_tools, status); |
|
285 } |
|
286 } |
|
287 |
|
288 u32_t length = data_array->get_object_count() * length_of_each_data_block; |
|
289 |
|
290 // Add eap_tlv_header_c to message. |
|
291 eap_tlv_header_c header( |
|
292 m_am_tools, |
|
293 m_message_data.get_data_offset(tlv_header_offset, eap_tlv_header_c::get_header_length()+length), |
|
294 eap_tlv_header_c::get_header_length()+length); |
|
295 |
|
296 if (header.get_is_valid() == false) |
|
297 { |
|
298 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
299 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
300 } |
|
301 |
|
302 status = header.reset_header(type, length); |
|
303 if (status != eap_status_ok) |
|
304 { |
|
305 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
306 return EAP_STATUS_RETURN(m_am_tools, status); |
|
307 } |
|
308 |
|
309 return EAP_STATUS_RETURN(m_am_tools, status); |
|
310 } |
|
311 |
|
312 //-------------------------------------------------- |
|
313 |
|
314 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::parse_message_data( |
|
315 eap_array_c<eap_tlv_header_c> * const tlv_blocks) |
|
316 { |
|
317 eap_status_e status(eap_status_ok); |
|
318 |
|
319 tlv_blocks->reset(); |
|
320 |
|
321 u8_t *next_header_begins = m_message_data.get_data(); |
|
322 u32_t remaining_message_data_length = m_message_data.get_data_length(); |
|
323 |
|
324 if (next_header_begins == 0 |
|
325 || remaining_message_data_length == 0) |
|
326 { |
|
327 // TLV is empty. |
|
328 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
329 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
330 } |
|
331 |
|
332 // This is reference to the first eap_tlv_header_c in the message_data. |
|
333 eap_tlv_header_c header( |
|
334 m_am_tools, |
|
335 next_header_begins, |
|
336 remaining_message_data_length); |
|
337 |
|
338 while (header.get_is_valid() == true) |
|
339 { |
|
340 const u32_t payload_length(header.get_header_length()+header.get_value_length()); |
|
341 |
|
342 status = header.check_header(); |
|
343 if (status != eap_status_ok) |
|
344 { |
|
345 EAP_TRACE_DATA_ERROR( |
|
346 m_am_tools, |
|
347 TRACE_FLAGS_ERROR, |
|
348 (EAPL("ERROR: illegal payload"), |
|
349 header.get_header_buffer(header.get_header_buffer_length()), |
|
350 header.get_header_buffer_length())); |
|
351 |
|
352 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
353 return EAP_STATUS_RETURN(m_am_tools, status); |
|
354 } |
|
355 else |
|
356 { |
|
357 EAP_TRACE_DATA_DEBUG( |
|
358 m_am_tools, |
|
359 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
360 (EAPL("payload"), |
|
361 header.get_header_buffer(payload_length), |
|
362 payload_length)); |
|
363 } |
|
364 |
|
365 |
|
366 if (remaining_message_data_length < payload_length) |
|
367 { |
|
368 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
369 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload); |
|
370 } |
|
371 |
|
372 { |
|
373 eap_tlv_header_c * const tlv = new eap_tlv_header_c( |
|
374 m_am_tools, |
|
375 header.get_header_buffer(payload_length), |
|
376 payload_length); |
|
377 |
|
378 eap_automatic_variable_c<eap_tlv_header_c> automatic_tlv(m_am_tools, tlv); |
|
379 |
|
380 if (tlv == 0) |
|
381 { |
|
382 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
383 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
384 } |
|
385 |
|
386 if (tlv->get_is_valid() == false) |
|
387 { |
|
388 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
389 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
390 } |
|
391 |
|
392 automatic_tlv.do_not_free_variable(); |
|
393 |
|
394 status = tlv_blocks->add_object(tlv, true); |
|
395 if (status != eap_status_ok) |
|
396 { |
|
397 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
398 return EAP_STATUS_RETURN(m_am_tools, status); |
|
399 } |
|
400 |
|
401 |
|
402 u32_t tlv_length = tlv->get_header_length()+tlv->get_value_length(); |
|
403 next_header_begins += tlv_length; |
|
404 remaining_message_data_length -= tlv_length; |
|
405 |
|
406 if (next_header_begins >= (m_message_data.get_data()+m_message_data.get_data_length()) |
|
407 || remaining_message_data_length == 0) |
|
408 { |
|
409 // No next header. |
|
410 break; |
|
411 } |
|
412 } |
|
413 |
|
414 header.set_header_buffer( |
|
415 next_header_begins, |
|
416 remaining_message_data_length); |
|
417 if (header.get_is_valid() == false) |
|
418 { |
|
419 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
420 return EAP_STATUS_RETURN(m_am_tools, status); |
|
421 } |
|
422 } // while() |
|
423 |
|
424 return EAP_STATUS_RETURN(m_am_tools, status); |
|
425 } |
|
426 |
|
427 //-------------------------------------------------- |
|
428 |
|
429 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::add_message_header( |
|
430 const eap_tlv_type_t type, |
|
431 const u32_t length) |
|
432 { |
|
433 // This will allocate space for eap_tlv_header_c without any value. |
|
434 |
|
435 EAP_TRACE_DEBUG( |
|
436 m_am_tools, |
|
437 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
438 (EAPL("eap_tlv_message_data_c::add_message_header(): type %2d=0x%08x, length %3d=0x%08x\n"), |
|
439 type, |
|
440 type, |
|
441 length, |
|
442 length)); |
|
443 |
|
444 u32_t network_order_type(eap_htonl(type)); |
|
445 |
|
446 eap_status_e status = m_message_data.add_data( |
|
447 &network_order_type, |
|
448 sizeof(network_order_type)); |
|
449 if (status != eap_status_ok) |
|
450 { |
|
451 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
452 return EAP_STATUS_RETURN(m_am_tools, status); |
|
453 } |
|
454 |
|
455 u32_t network_order_length(eap_htonl(length)); |
|
456 |
|
457 status = m_message_data.add_data( |
|
458 &network_order_length, |
|
459 sizeof(network_order_length)); |
|
460 if (status != eap_status_ok) |
|
461 { |
|
462 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
463 return EAP_STATUS_RETURN(m_am_tools, status); |
|
464 } |
|
465 |
|
466 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
467 return EAP_STATUS_RETURN(m_am_tools, status); |
|
468 } |
|
469 |
|
470 //-------------------------------------------------- |
|
471 |
|
472 EAP_FUNC_EXPORT eap_status_e eap_tlv_message_data_c::allocate_message_buffer( |
|
473 const eap_tlv_type_t type, |
|
474 const u32_t length, |
|
475 void * * const buffer) |
|
476 { |
|
477 eap_status_e status(eap_status_process_general_error); |
|
478 |
|
479 *buffer = 0; |
|
480 |
|
481 u32_t tlv_header_offset(0ul); |
|
482 |
|
483 if (m_message_data.get_is_valid() == true) |
|
484 { |
|
485 tlv_header_offset = m_message_data.get_data_length(); |
|
486 } |
|
487 else |
|
488 { |
|
489 tlv_header_offset = 0ul; |
|
490 } |
|
491 |
|
492 // This will allocate space for eap_tlv_header_c only. |
|
493 status = m_message_data.add_data_to_offset( |
|
494 tlv_header_offset+eap_tlv_header_c::get_header_length()+length, |
|
495 0, |
|
496 0ul); |
|
497 if (status != eap_status_ok) |
|
498 { |
|
499 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
500 return EAP_STATUS_RETURN(m_am_tools, status); |
|
501 } |
|
502 |
|
503 // Add eap_tlv_header_c to message. |
|
504 eap_tlv_header_c header( |
|
505 m_am_tools, |
|
506 m_message_data.get_data_offset(tlv_header_offset, eap_tlv_header_c::get_header_length()+length), |
|
507 eap_tlv_header_c::get_header_length()+length); |
|
508 |
|
509 if (header.get_is_valid() == false) |
|
510 { |
|
511 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
512 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
513 } |
|
514 |
|
515 status = header.reset_header(type, length); |
|
516 if (status != eap_status_ok) |
|
517 { |
|
518 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
519 return EAP_STATUS_RETURN(m_am_tools, status); |
|
520 } |
|
521 |
|
522 *buffer = header.get_value(length); |
|
523 |
|
524 if ((*buffer) == 0) |
|
525 { |
|
526 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
527 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
528 } |
|
529 |
|
530 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
531 return EAP_STATUS_RETURN(m_am_tools, status); |
|
532 } |
|
533 |
|
534 //-------------------------------------------------- |
|
535 |
|
536 EAP_FUNC_EXPORT bool eap_tlv_message_data_c::get_is_valid() |
|
537 { |
|
538 return m_message_data.get_is_valid(); |
|
539 } |
|
540 |
|
541 //-------------------------------------------------- |
|
542 |
|
543 |
|
544 |
|
545 // End. |