6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
21 * Copyright 2003 Alan DeKok <aland@freeradius.org>
22 * Copyright 2006 The FreeRADIUS server project
27 * TLS Packet Format in EAP
28 * --- ------ ------ -- ---
30 * 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
31 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 * | Code | Identifier | Length |
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | Type | Flags | TLS Message Length
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | TLS Message Length | TLS Data...
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 #include <freeradius-devel/ident.h>
44 #include <freeradius-devel/autoconf.h>
49 * Allocate a new TLS_PACKET
51 EAPTLS_PACKET *eaptls_alloc(void)
55 if ((rp = malloc(sizeof(EAPTLS_PACKET))) == NULL) {
56 radlog(L_ERR, "rlm_eap_tls: out of memory");
59 memset(rp, 0, sizeof(EAPTLS_PACKET));
66 void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr)
68 EAPTLS_PACKET *eaptls_packet;
70 if (!eaptls_packet_ptr) return;
71 eaptls_packet = *eaptls_packet_ptr;
72 if (eaptls_packet == NULL) return;
74 if (eaptls_packet->data) {
75 free(eaptls_packet->data);
76 eaptls_packet->data = NULL;
80 *eaptls_packet_ptr = NULL;
84 The S flag is set only within the EAP-TLS start message
85 sent from the EAP server to the peer.
87 int eaptls_start(EAP_DS *eap_ds, int peap_flag)
91 reply.code = FR_TLS_START;
92 reply.length = TLS_HEADER_LEN + 1/*flags*/;
94 reply.flags = peap_flag;
95 reply.flags = SET_START(reply.flags);
100 eaptls_compose(eap_ds, &reply);
105 int eaptls_success(EAP_HANDLER *handler, int peap_flag)
108 REQUEST *request = handler->request;
109 tls_session_t *tls_session = handler->opaque;
111 handler->finished = TRUE;
112 reply.code = FR_TLS_SUCCESS;
113 reply.length = TLS_HEADER_LEN;
114 reply.flags = peap_flag;
118 tls_success(tls_session, request);
121 * Call compose AFTER checking for cached data.
123 eaptls_compose(handler->eap_ds, &reply);
126 * Automatically generate MPPE keying material.
128 if (tls_session->prf_label) {
129 eaptls_gen_mppe_keys(&handler->request->reply->vps,
130 tls_session->ssl, tls_session->prf_label);
132 RDEBUG("WARNING: Not adding MPPE keys because there is no PRF label");
138 int eaptls_fail(EAP_HANDLER *handler, int peap_flag)
141 tls_session_t *tls_session = handler->opaque;
143 handler->finished = TRUE;
144 reply.code = FR_TLS_FAIL;
145 reply.length = TLS_HEADER_LEN;
146 reply.flags = peap_flag;
151 * Force the session to NOT be cached.
153 SSL_CTX_remove_session(tls_session->ctx, tls_session->ssl->session);
155 eaptls_compose(handler->eap_ds, &reply);
161 A single TLS record may be up to 16384 octets in length, but a TLS
162 message may span multiple TLS records, and a TLS certificate message
163 may in principle be as long as 16MB.
167 * Frame the Dirty data that needs to be send to the client in an
168 * EAP-Request. We always embed the TLS-length in all EAP-TLS
169 * packets that we send, for easy reference purpose. Handle
170 * fragmentation and sending the next fragment etc.
172 int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn)
177 unsigned int lbit = 0;
179 /* This value determines whether we set (L)ength flag for
180 EVERY packet we send and add corresponding
181 "TLS Message Length" field.
184 This means we include L flag and "TLS Msg Len" in EVERY
188 This means we include L flag and "TLS Msg Len" **ONLY**
189 in First packet of a fragment series. We do not use
192 Having L flag in every packet is prefered.
195 if (ssn->length_flag) {
198 if (ssn->fragment == 0) {
199 ssn->tls_msg_len = ssn->dirty_out.used;
202 reply.code = FR_TLS_REQUEST;
203 reply.flags = ssn->peap_flag;
205 /* Send data, NOT more than the FRAGMENT size */
206 if (ssn->dirty_out.used > ssn->offset) {
208 reply.flags = SET_MORE_FRAGMENTS(reply.flags);
209 /* Length MUST be included if it is the First Fragment */
210 if (ssn->fragment == 0) {
215 size = ssn->dirty_out.used;
219 reply.dlen = lbit + size;
220 reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen;
222 reply.data = malloc(reply.dlen);
224 nlen = htonl(ssn->tls_msg_len);
225 memcpy(reply.data, &nlen, lbit);
226 reply.flags = SET_LENGTH_INCLUDED(reply.flags);
228 (ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size);
230 eaptls_compose(eap_ds, &reply);
239 * Similarly, when the EAP server receives an EAP-Response with
240 * the M bit set, it MUST respond with an EAP-Request with
241 * EAP-Type=EAP-TLS and no data. This serves as a fragment ACK.
243 * In order to prevent errors in the processing of fragments, the
244 * EAP server MUST use increment the Identifier value for each
245 * fragment ACK contained within an EAP-Request, and the peer
246 * MUST include this Identifier value in the subsequent fragment
247 * contained within an EAP- Reponse.
249 * EAP server sends an ACK when it determines there are More
250 * fragments to receive to make the complete
251 * TLS-record/TLS-Message
253 static int eaptls_send_ack(EAP_DS *eap_ds, int peap_flag)
257 reply.code = FR_TLS_ACK;
258 reply.length = TLS_HEADER_LEN + 1/*flags*/;
259 reply.flags = peap_flag;
263 eaptls_compose(eap_ds, &reply);
269 * The S flag is set only within the EAP-TLS start message sent
270 * from the EAP server to the peer.
272 * Similarly, when the EAP server receives an EAP-Response with
273 * the M bit set, it MUST respond with an EAP-Request with
274 * EAP-Type=EAP-TLS and no data. This serves as a fragment
275 * ACK. The EAP peer MUST wait.
277 static fr_tls_status_t eaptls_verify(EAP_HANDLER *handler)
279 EAP_DS *eap_ds = handler->eap_ds;
280 EAP_DS *prev_eap_ds = handler->prev_eapds;
281 eaptls_packet_t *eaptls_packet, *eaptls_prev = NULL;
282 REQUEST *request = handler->request;
285 * We don't check ANY of the input parameters. It's all
286 * code which works together, so if something is wrong,
287 * we SHOULD core dump.
289 * e.g. if eap_ds is NULL, of if eap_ds->response is
290 * NULL, of if it's NOT an EAP-Response, or if the packet
291 * is too short. See eap_validation()., in ../../eap.c
293 * Also, eaptype_select() takes care of selecting the
294 * appropriate type, so we don't need to check
295 * eap_ds->response->type.type == PW_EAP_TLS, or anything
298 eaptls_packet = (eaptls_packet_t *)eap_ds->response->type.data;
299 if (prev_eap_ds && prev_eap_ds->response)
300 eaptls_prev = (eaptls_packet_t *)prev_eap_ds->response->type.data;
305 * If there's no TLS data, or there's 1 byte of TLS data,
306 * with the flags set to zero, then it's an ACK.
308 * Find if this is a reply to the previous request sent
310 if ((eaptls_packet == NULL) ||
311 ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&
312 ((eaptls_packet->flags & 0xc0) == 0x00))) {
315 (prev_eap_ds->request->id == eap_ds->response->id)) {
317 * Run the ACK handler directly from here.
319 RDEBUG2("Received TLS ACK");
320 return tls_ack_handler(handler->opaque, request);
322 radlog_request(L_ERR, 0, request, "Received Invalid TLS ACK");
323 return FR_TLS_INVALID;
328 * We send TLS_START, but do not receive it.
330 if (TLS_START(eaptls_packet->flags)) {
331 RDEBUG("Received unexpected EAP-TLS Start message");
332 return FR_TLS_INVALID;
336 * The L bit (length included) is set to indicate the
337 * presence of the four octet TLS Message Length field,
338 * and MUST be set for the first fragment of a fragmented
339 * TLS message or set of messages.
341 * The M bit (more fragments) is set on all but the last
344 * The S bit (EAP-TLS start) is set in an EAP-TLS Start
345 * message. This differentiates the EAP-TLS Start message
346 * from a fragment acknowledgement.
348 if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) {
349 DEBUG2(" TLS Length %d",
350 eaptls_packet->data[2] * 256 | eaptls_packet->data[3]);
351 if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
353 * FIRST_FRAGMENT is identified
354 * 1. If there is no previous EAP-response received.
355 * 2. If EAP-response received, then its M bit not set.
356 * (It is because Last fragment will not have M bit set)
359 (prev_eap_ds->response == NULL) ||
360 (eaptls_prev == NULL) ||
361 !TLS_MORE_FRAGMENTS(eaptls_prev->flags)) {
363 RDEBUG2("Received EAP-TLS First Fragment of the message");
364 return FR_TLS_FIRST_FRAGMENT;
367 RDEBUG2("More Fragments with length included");
368 return FR_TLS_MORE_FRAGMENTS_WITH_LENGTH;
371 RDEBUG2("Length Included");
372 return FR_TLS_LENGTH_INCLUDED;
376 if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
377 RDEBUG2("More fragments to follow");
378 return FR_TLS_MORE_FRAGMENTS;
382 * None of the flags are set, but it's still a valid
392 * length = code + id + length + flags + tlsdata
393 * = 1 + 1 + 2 + 1 + X
394 * length = EAP-length - 1(EAP-Type = 1 octet)
395 * flags = EAP-typedata[0] (1 octet)
396 * dlen = EAP-typedata[1-4] (4 octets), if L flag set
397 * = length - 5(code+id+length+flags), otherwise
398 * data = EAP-typedata[5-n], if L flag set
399 * = EAP-typedata[1-n], otherwise
400 * packet = EAP-typedata (complete typedata)
402 * Points to consider during EAP-TLS data extraction
403 * 1. In the received packet, No data will be present incase of ACK-NAK
404 * 2. Incase if more fragments need to be received then ACK after retreiving this fragment.
406 * RFC 2716 Section 4.2. PPP EAP TLS Request Packet
409 * 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
410 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
411 * | Code | Identifier | Length |
412 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
413 * | Type | Flags | TLS Message Length
414 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
415 * | TLS Message Length | TLS Data...
416 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
418 * The Length field is two octets and indicates the length of the EAP
419 * packet including the Code, Identifir, Length, Type, and TLS data
422 static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_status_t status)
424 EAPTLS_PACKET *tlspacket;
425 uint32_t data_len = 0;
427 uint8_t *data = NULL;
429 if (status == FR_TLS_INVALID)
433 * The main EAP code & eaptls_verify() take care of
434 * ensuring that the packet is OK, and that we can
435 * extract the various fields we want.
437 * e.g. a TLS packet with zero data is allowed as an ACK,
438 * but we will never see it here, as we will simply
439 * send another fragment, instead of trying to extract
442 * MUST have TLS type octet, followed by flags, followed
445 assert(eap_ds->response->length > 2);
447 tlspacket = eaptls_alloc();
448 if (tlspacket == NULL) return NULL;
451 * Code & id for EAPTLS & EAP are same
452 * but eaptls_length = eap_length - 1(EAP-Type = 1 octet)
454 * length = code + id + length + type + tlsdata
455 * = 1 + 1 + 2 + 1 + X
457 tlspacket->code = eap_ds->response->code;
458 tlspacket->id = eap_ds->response->id;
459 tlspacket->length = eap_ds->response->length - 1; /* EAP type */
460 tlspacket->flags = eap_ds->response->type.data[0];
463 * A quick sanity check of the flags. If we've been told
464 * that there's a length, and there isn't one, then stop.
466 if (TLS_LENGTH_INCLUDED(tlspacket->flags) &&
467 (tlspacket->length < 5)) { /* flags + TLS message length */
468 RDEBUG("Invalid EAP-TLS packet received. (Length bit is set, but no length was found.)");
469 eaptls_free(&tlspacket);
474 * If the final TLS packet is larger than we can handle, die
477 * Likewise, if the EAP packet says N bytes, and the TLS
478 * packet says there's fewer bytes, it's a problem.
480 * FIXME: Try to ensure that the claimed length is
481 * consistent across multiple TLS fragments.
483 if (TLS_LENGTH_INCLUDED(tlspacket->flags)) {
484 memcpy(&data_len, &eap_ds->response->type.data[1], 4);
485 data_len = ntohl(data_len);
486 if (data_len > MAX_RECORD_SIZE) {
487 RDEBUG("The EAP-TLS packet will contain more data than we can process.");
488 eaptls_free(&tlspacket);
493 DEBUG2(" TLS: %d %d\n", data_len, tlspacket->length);
495 if (data_len < tlspacket->length) {
496 RDEBUG("EAP-TLS packet claims to be smaller than the encapsulating EAP packet.");
497 eaptls_free(&tlspacket);
505 * The TLS Message Length field is four octets, and
506 * provides the total length of the TLS message or set of
507 * messages that is being fragmented; this simplifies
510 * Dynamic allocation of buffers as & when we know the
511 * length should solve the problem.
513 case FR_TLS_FIRST_FRAGMENT:
514 case FR_TLS_LENGTH_INCLUDED:
515 case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
516 if (tlspacket->length < 5) { /* flags + TLS message length */
517 RDEBUG("Invalid EAP-TLS packet received. (Expected length, got none.)");
518 eaptls_free(&tlspacket);
523 * Extract all the TLS fragments from the
524 * previous eap_ds Start appending this
525 * fragment to the above ds
527 memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t));
528 data_len = ntohl(data_len);
529 data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/);
530 len = eap_ds->response->type.length - 5/*flags+TLS-Length*/;
533 * Hmm... this should be an error, too.
535 if (data_len > len) {
541 * Data length is implicit, from the EAP header.
543 case FR_TLS_MORE_FRAGMENTS:
545 data_len = eap_ds->response->type.length - 1/*flags*/;
546 data = eap_ds->response->type.data + 1/*flags*/;
550 RDEBUG("Invalid EAP-TLS packet received");
551 eaptls_free(&tlspacket);
555 tlspacket->dlen = data_len;
557 tlspacket->data = (unsigned char *)malloc(data_len);
558 if (tlspacket->data == NULL) {
559 RDEBUG("out of memory");
560 eaptls_free(&tlspacket);
563 memcpy(tlspacket->data, data, data_len);
572 * To process the TLS,
574 * 1. EAP-TLS should get the compelete TLS data from the peer.
575 * 2. Store that data in a data structure with any other required info
576 * 3. Handle that data structure to the TLS module.
577 * 4. TLS module will perform its operations on the data and
578 * handle back to EAP-TLS
581 * 1. EAP-TLS if necessary will fragment it and send it to the
584 * During EAP-TLS initialization, TLS Context object will be
585 * initialized and stored. For every new authentication
586 * requests, TLS will open a new session object and that session
587 * object should be maintained even after the session is
588 * completed for session resumption. (Probably later as a feature
589 * as we donot know who maintains these session objects ie,
590 * SSL_CTX (internally) or TLS module(explicitly). If TLS module,
591 * then how to let SSL API know about these sessions.)
593 static fr_tls_status_t eaptls_operation(fr_tls_status_t status,
594 EAP_HANDLER *handler)
596 tls_session_t *tls_session;
598 tls_session = (tls_session_t *)handler->opaque;
600 if ((status == FR_TLS_MORE_FRAGMENTS) ||
601 (status == FR_TLS_MORE_FRAGMENTS_WITH_LENGTH) ||
602 (status == FR_TLS_FIRST_FRAGMENT)) {
606 eaptls_send_ack(handler->eap_ds, tls_session->peap_flag);
607 return FR_TLS_HANDLED;
612 * We have the complete TLS-data or TLS-message.
614 * Clean the dirty message.
616 * Authenticate the user and send
620 * is required then send another request.
622 if (!tls_handshake_recv(handler->request, tls_session)) {
623 DEBUG2("TLS receive handshake failed during operation");
624 eaptls_fail(handler, tls_session->peap_flag);
629 * FIXME: return success/fail.
631 * TLS proper can decide what to do, then.
633 if (tls_session->dirty_out.used > 0) {
634 eaptls_request(handler->eap_ds, tls_session);
635 return FR_TLS_HANDLED;
639 * If there is no data to send i.e
640 * dirty_out.used <=0 and if the SSL
641 * handshake is finished, then return a
645 if (SSL_is_init_finished(tls_session->ssl)) {
647 * Init is finished. The rest is
650 tls_session->info.content_type = application_data;
651 return FR_TLS_SUCCESS;
655 * Who knows what happened...
657 DEBUG2("TLS failed during operation");
663 * In the actual authentication first verify the packet and then create the data structure
666 * To process the TLS,
668 * 1. EAP-TLS should get the compelete TLS data from the peer.
669 * 2. Store that data in a data structure with any other required info
670 * 3. Hand this data structure to the TLS module.
671 * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
673 * 1. EAP-TLS if necessary will fragment it and send it to the destination.
675 * During EAP-TLS initialization, TLS Context object will be
676 * initialized and stored. For every new authentication
677 * requests, TLS will open a new session object and that
678 * session object SHOULD be maintained even after the session
679 * is completed, for session resumption. (Probably later as a
680 * feature, as we do not know who maintains these session
681 * objects ie, SSL_CTX (internally) or TLS module (explicitly). If
682 * TLS module, then how to let SSL API know about these
687 * Process an EAP request
689 fr_tls_status_t eaptls_process(EAP_HANDLER *handler)
691 tls_session_t *tls_session = (tls_session_t *) handler->opaque;
692 EAPTLS_PACKET *tlspacket;
693 fr_tls_status_t status;
694 REQUEST *request = handler->request;
696 if (!request) return FR_TLS_FAIL;
698 RDEBUG2("processing EAP-TLS");
699 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);
701 if (handler->certs) pairadd(&request->packet->vps,
702 paircopy(handler->certs));
704 /* This case is when SSL generates Alert then we
705 * send that alert to the client and then send the EAP-Failure
707 status = eaptls_verify(handler);
708 RDEBUG2("eaptls_verify returned %d\n", status);
716 * Success means that we're done the initial
717 * handshake. For TTLS, this means send stuff
718 * back to the client, and the client sends us
719 * more tunneled data.
725 * Normal TLS request, continue with the "get rest
726 * of fragments" phase.
729 eaptls_request(handler->eap_ds, tls_session);
730 status = FR_TLS_HANDLED;
734 * The handshake is done, and we're in the "tunnel
738 RDEBUG2("Done initial handshake");
741 * Get the rest of the fragments.
743 case FR_TLS_FIRST_FRAGMENT:
744 case FR_TLS_MORE_FRAGMENTS:
745 case FR_TLS_LENGTH_INCLUDED:
746 case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
751 * Extract the TLS packet from the buffer.
753 if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL) {
754 status = FR_TLS_FAIL;
759 * Get the session struct from the handler
761 * update the dirty_in buffer
763 * NOTE: This buffer will contain partial data when M bit is set.
765 * CAUTION while reinitializing this buffer, it should be
766 * reinitialized only when this M bit is NOT set.
768 if (tlspacket->dlen !=
769 (tls_session->record_plus)(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) {
770 eaptls_free(&tlspacket);
771 RDEBUG("Exceeded maximum record size");
779 eaptls_free(&tlspacket);
782 * SSL initalization is done. Return.
784 * The TLS data will be in the tls_session structure.
786 if (SSL_is_init_finished(tls_session->ssl)) {
788 * The initialization may be finished, but if
789 * there more fragments coming, then send ACK,
790 * and get the caller to continue the
793 if ((status == FR_TLS_MORE_FRAGMENTS) ||
794 (status == FR_TLS_MORE_FRAGMENTS_WITH_LENGTH) ||
795 (status == FR_TLS_FIRST_FRAGMENT)) {
799 eaptls_send_ack(handler->eap_ds,
800 tls_session->peap_flag);
801 RDEBUG2("Init is done, but tunneled data is fragmented");
802 status = FR_TLS_HANDLED;
806 status = tls_application_data(tls_session, request);
811 * Continue the handshake.
813 status = eaptls_operation(status, handler);
816 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);
823 * compose the TLS reply packet in the EAP reply typedata
825 int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply)
830 * Don't set eap_ds->request->type.type, as the main EAP
831 * handler will do that for us. This allows the TLS
832 * module to be called from TTLS & PEAP.
836 * When the EAP server receives an EAP-Response with the
837 * M bit set, it MUST respond with an EAP-Request with
838 * EAP-Type=EAP-TLS and no data. This serves as a
839 * fragment ACK. The EAP peer MUST wait until it receives
840 * the EAP-Request before sending another fragment.
842 * In order to prevent errors in the processing of
843 * fragments, the EAP server MUST use increment the
844 * Identifier value for each fragment ACK contained
845 * within an EAP-Request, and the peer MUST include this
846 * Identifier value in the subsequent fragment contained
847 * within an EAP- Reponse.
849 eap_ds->request->type.data = malloc(reply->length - TLS_HEADER_LEN + 1);
850 if (eap_ds->request->type.data == NULL) {
851 radlog(L_ERR, "out of memory");
855 /* EAPTLS Header length is excluded while computing EAP typelen */
856 eap_ds->request->type.length = reply->length - TLS_HEADER_LEN;
858 ptr = eap_ds->request->type.data;
859 *ptr++ = (uint8_t)(reply->flags & 0xFF);
861 if (reply->dlen) memcpy(ptr, reply->data, reply->dlen);
863 switch (reply->code) {
867 eap_ds->request->code = PW_EAP_REQUEST;
870 eap_ds->request->code = PW_EAP_SUCCESS;
873 eap_ds->request->code = PW_EAP_FAILURE;
876 /* Should never enter here */
877 eap_ds->request->code = PW_EAP_FAILURE;