definitions moved to libeap.
[freeradius.git] / src / modules / rlm_eap / eap.c
1 /*
2  * eap.c    rfc2284 & rfc2869 implementation
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2000-2003  The FreeRADIUS server project
21  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
22  * Copyright 2003  Alan DeKok <aland@freeradius.org>
23  */
24 /*
25  *  EAP PACKET FORMAT
26  *  --- ------ ------
27  *  0                   1                   2                   3
28  *  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
29  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30  * |     Code      |  Identifier   |            Length             |
31  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32  * |    Data ...
33  * +-+-+-+-+
34  *
35  *
36  * EAP Request and Response Packet Format 
37  * --- ------- --- -------- ------ ------
38  *  0                   1                   2                   3
39  *  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
40  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41  * |     Code      |  Identifier   |            Length             |
42  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43  * |     Type      |  Type-Data ...
44  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
45  *
46  *
47  * EAP Success and Failure Packet Format 
48  * --- ------- --- ------- ------ ------
49  *  0                   1                   2                   3
50  *  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
51  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52  * |     Code      |  Identifier   |            Length             |
53  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54  *
55  */
56
57 #include "rlm_eap.h"
58
59 static const char rcsid[] = "$Id$";
60
61 static const char *eap_codes[] = {
62   "",                           /* 0 is invalid */
63   "request",
64   "response",
65   "success",
66   "failure"
67 };
68
69 /*
70  * Load all the required eap authentication types.
71  * Get all the supported EAP-types from config file. 
72  */
73 int eaptype_load(EAP_TYPES **type, int eap_type, CONF_SECTION *cs)
74 {
75         char            buffer[64];
76         lt_dlhandle     handle;
77         EAP_TYPES       *node;
78
79         snprintf(buffer, sizeof(buffer), "rlm_eap_%s", eap_types[eap_type]);
80
81         /* Link the loaded EAP-Type */
82         handle = lt_dlopenext(buffer);
83         if (handle == NULL) {
84                 radlog(L_ERR, "rlm_eap: Failed to link EAP-Type/%s: %s", 
85                                 eap_types[eap_type], lt_dlerror());
86                 return -1;
87         }
88
89         /* Make room for the EAP-Type */
90         node = (EAP_TYPES *)malloc(sizeof(EAP_TYPES));
91         if (node == NULL) {
92                 radlog(L_ERR, "rlm_eap: out of memory");
93                 return -1;
94         }
95         memset(node, 0, sizeof(*node));
96
97         /* fill in the structure */
98         node->handle = handle;
99         node->cs = cs;
100         node->typename = eap_types[eap_type];
101         node->type_data = NULL;
102         
103         node->type = (EAP_TYPE *)lt_dlsym(node->handle, buffer);
104         if (!node->type) {
105                 radlog(L_ERR, "rlm_eap: Failed linking to %s structure in %s: %s",
106                                 buffer, eap_types[eap_type], lt_dlerror());
107                 lt_dlclose(node->handle);       /* ignore any errors */
108                 free(node);
109                 return -1;
110         }
111         if ((node->type->attach) && 
112                 ((node->type->attach)(node->cs, &(node->type_data)) < 0)) {
113
114                 radlog(L_ERR, "rlm_eap: Failed to initialize type %s",
115                        eap_types[eap_type]);
116                 lt_dlclose(node->handle);
117                 free(node);
118                 return -1;
119         }
120
121         DEBUG("rlm_eap: Loaded and initialized type %s", eap_types[eap_type]);
122         *type = node;
123         return 0;
124 }
125
126
127 /*
128  * Call the appropriate handle with the right eap_type.
129  */
130 static int eaptype_call(EAP_TYPES *atype, EAP_HANDLER *handler)
131 {
132         int rcode = 1;
133
134         DEBUG2("  rlm_eap: processing type %s", atype->typename);
135
136         rad_assert(atype != NULL);
137
138         switch (handler->stage) {
139         case INITIATE:
140                 if (!atype->type->initiate(atype->type_data, handler))
141                         rcode = 0;
142                 break;
143
144         case AUTHORIZE:
145                 /*
146                  *   The called function updates the EAP reply packet.
147                  */
148                 if (!atype->type->authorize ||
149                     !atype->type->authorize(atype->type_data, handler))
150                         rcode = 0;
151                 break;
152
153         case AUTHENTICATE:
154                 /*
155                  *   The called function updates the EAP reply packet.
156                  */
157                 if (!atype->type->authenticate ||
158                     !atype->type->authenticate(atype->type_data, handler))
159                         rcode = 0;
160                 break;
161
162         default:
163                 /* Should never enter here */
164                 radlog(L_DBG, "rlm_eap: Invalid operation on eap_type");
165                 rcode = 0;
166                 break;
167         }
168
169         return rcode;
170 }
171
172 /*
173  * Based on TYPE, call the appropriate EAP-type handler
174  * Default to the configured EAP-Type 
175  * for all Unsupported EAP-Types 
176  */
177 int eaptype_select(rlm_eap_t *inst, EAP_HANDLER *handler)
178 {
179         eaptype_t       *eaptype;
180         int             default_eap_type = inst->default_eap_type;
181
182         eaptype = &handler->eap_ds->response->type;
183
184         /*
185          *      Don't trust anyone.
186          */
187         if ((eaptype->type == 0) ||
188             (eaptype->type > PW_EAP_MAX_TYPES)) {
189                 DEBUG2(" rlm_eap: Asked to select bad type");
190                 return EAP_INVALID;
191         }
192
193         /*
194          *      Figure out what to do.
195          */
196         switch(eaptype->type) {
197         case PW_EAP_IDENTITY:
198                 {
199                         VALUE_PAIR  *vp;
200
201                         DEBUG2("  rlm_eap: EAP Identity");
202                         
203                         /*
204                          *      Allow per-user configuration of EAP types.
205                          */
206                         vp = pairfind(handler->request->config_items,
207                                       PW_EAP_TYPE);
208                         if (vp) default_eap_type = vp->lvalue;
209
210                 do_initiate:
211                         /*
212                          *      Ensure it's valid.
213                          */
214                         if ((default_eap_type < PW_EAP_MD5) ||
215                             (default_eap_type > PW_EAP_MAX_TYPES) ||
216                             (inst->types[default_eap_type] == NULL)) {
217                                 DEBUG2(" rlm_eap: No such EAP type %d",
218                                        default_eap_type);
219                                 return EAP_INVALID;
220                         }
221                         
222                         handler->stage = INITIATE;
223                         handler->eap_type = default_eap_type;
224
225                         /*
226                          *      Wild & crazy stuff!  For TTLS & PEAP,
227                          *      we initiate a TLS session, and then pass
228                          *      that session data to TTLS or PEAP for
229                          *      the authenticate stage.
230                          *
231                          *      Handler->eap_type holds the TRUE
232                          *      type.
233                          */
234                         if ((default_eap_type == PW_EAP_TTLS) ||
235                             (default_eap_type == PW_EAP_PEAP)) {
236                                 default_eap_type = PW_EAP_TLS;
237                         }
238
239
240                         /*
241                          *      We don't do TLS inside of TLS, as it's
242                          *      a bad idea...
243                          */
244                         if (((handler->request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) &&
245                             (default_eap_type == PW_EAP_TLS)) {
246                                 DEBUG2(" rlm_eap: Unable to tunnel TLS inside of TLS");
247                                 return EAP_INVALID;
248                         }
249
250                         if (eaptype_call(inst->types[default_eap_type],
251                                          handler) == 0) {
252                                 DEBUG2(" rlm_eap: Default EAP type %s failed in initiate", eap_types[default_eap_type]);
253                                 return EAP_INVALID;
254                         }
255                 }
256                 break;
257
258         case PW_EAP_NAK:
259                 /*
260                  *      The one byte of NAK data is the preferred EAP type
261                  *      of the client.
262                  */
263                 DEBUG2("  rlm_eap: EAP NAK");
264
265                 /*
266                  *      Delete old data, if necessary.
267                  */
268                 if (handler->opaque && handler->free_opaque) {
269                         handler->free_opaque(handler->opaque);
270                         handler->free_opaque = NULL;
271                         handler->opaque = NULL;
272                 }
273
274                 /*
275                  *      It is invalid to request identity,
276                  *      notification & nak in nak
277                  */
278                 if (eaptype->data == NULL) {
279                         DEBUG2(" rlm_eap: Empty NAK packet, cannot decide what EAP type the client wants.");
280                         return EAP_INVALID;
281                 }
282
283                 if ((eaptype->data[0] < PW_EAP_MD5) ||
284                     (eaptype->data[0] > PW_EAP_MAX_TYPES)) {
285                         DEBUG2(" rlm_eap: NAK asked for bad type %d",
286                                eaptype->data[0]);
287                         return EAP_INVALID;
288                 }
289
290                 default_eap_type = eaptype->data[0];
291                 DEBUG2(" rlm_eap: EAP-NAK asked for EAP-Type/%s",
292                        eap_types[default_eap_type]);
293
294                 if (handler->eap_type == default_eap_type) {
295                         DEBUG2(" rlm_eap: ERROR! Our request for %s was NAK'd with a request for %s, what is the client thinking?",
296                                eap_types[default_eap_type],
297                                eap_types[default_eap_type]);
298                 }
299
300                 goto do_initiate;
301                 break;
302
303                 /*
304                  *      Key off of the configured sub-modules.
305                  */
306                 default:
307                         DEBUG2("  rlm_eap: EAP_TYPE - %s",
308                                eap_types[eaptype->type]);
309                         
310                         /*
311                          *      We haven't configured it, it doesn't exit.
312                          */
313                         if (!inst->types[eaptype->type]) {
314                                 DEBUG2(" rlm_eap: EAP type %d is unsupported",
315                                        eaptype->type);
316                                 return EAP_INVALID;
317                         }
318                         
319                         rad_assert(handler->stage == AUTHENTICATE);
320                         handler->eap_type = eaptype->type;
321                         if (eaptype_call(inst->types[eaptype->type],
322                                          handler) == 0) {
323                                 DEBUG2(" rlm_eap: Handler failed in EAP type %d",
324                                        eaptype->type);
325                                 return EAP_INVALID;
326                         }
327                 break;
328         }
329
330         return EAP_OK;
331 }
332
333 /*
334  * Handles multiple EAP-Message attrs
335  * ie concatenates all to get the complete EAP packet
336  *
337  * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
338  *      refer fragmentation in rfc2869.
339  */
340 eap_packet_t *eap_attribute(VALUE_PAIR *vps)
341 {
342         VALUE_PAIR *first, *vp;
343         eap_packet_t *eap_packet;
344         unsigned char *ptr;
345         uint16_t len;
346         int total_len;
347
348         /*
349          *      Get only EAP-Message attribute list
350          */
351         first = pairfind(vps, PW_EAP_MESSAGE);
352         if (first == NULL) {
353                 radlog(L_ERR, "rlm_eap: EAP-Message not found.  You have misconfigured the server.");
354                 DEBUG2("  You have 'Auth-Type := EAP' in another module or configuration file.");
355                 DEBUG2("  DO NOT set 'Auth-Type' to 'EAP'.  The EAP module will do it, if necessary.");
356                 return NULL;
357         }
358
359         /*
360          *      Sanity check the length before doing anything.
361          */
362         if (first->length < 4) {
363                 radlog(L_ERR, "rlm_eap: EAP packet is too short.");
364                 return NULL;
365         }
366
367         /*
368          *      Get the Actual length from the EAP packet
369          *      First EAP-Message contains the EAP packet header
370          */
371         memcpy(&len, first->strvalue + 2, sizeof(len));
372         len = ntohs(len);
373
374         /*
375          *      Take out even more weird things.
376          */
377         if (len < 4) {
378                 radlog(L_ERR, "rlm_eap: EAP packet has invalid length.");
379                 return NULL;
380         }
381
382         /*
383          *      Sanity check the length, BEFORE malloc'ing memory.
384          */
385         total_len = 0;
386         for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) {
387                 total_len += vp->length;
388                 
389                 if (total_len > len) {
390                         radlog(L_ERR, "rlm_eap: Malformed EAP packet.  Length in packet header does not match actual length");
391                         return NULL;
392                 }
393         }
394
395         /*
396          *      If the length is SMALLER, die, too.
397          */
398         if (total_len < len) {
399                 radlog(L_ERR, "rlm_eap: Malformed EAP packet.  Length in packet header does not match actual length");
400                 return NULL;
401         }
402
403         /*
404          *      Now that we know the lengths are OK, allocate memory.
405          */
406         eap_packet = (eap_packet_t *) malloc(len);
407         if (eap_packet == NULL) {
408                 radlog(L_ERR, "rlm_eap: out of memory");
409                 return NULL;
410         }
411
412         /*
413          *      Copy the data from EAP-Message's over to out EAP packet.
414          */
415         ptr = (unsigned char *)eap_packet;
416
417         /* RADIUS ensures order of attrs, so just concatenate all */
418         for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) {
419                 memcpy(ptr, vp->strvalue, vp->length);
420                 ptr += vp->length;
421         }
422
423         return eap_packet;
424 }
425
426 /*
427  *      EAP packet format to be sent over the wire
428  *
429  *      i.e. code+id+length+data where data = null/type+typedata
430  *      based on code.
431  */
432 static int eap_wireformat(EAP_PACKET *reply)
433 {
434         eap_packet_t    *hdr;
435         uint16_t total_length = 0;
436
437         if (reply == NULL) return EAP_INVALID;
438
439         total_length = EAP_HEADER_LEN;
440         if (reply->code < 3) {
441                 total_length += 1/*EAPtype*/;
442                 if (reply->type.data && reply->type.length > 0) {
443                         total_length += reply->type.length;
444                 }
445         }
446
447         reply->packet = (unsigned char *)malloc(total_length);
448         hdr = (eap_packet_t *)reply->packet;
449         if (!hdr) {
450                 radlog(L_ERR, "rlm_eap: out of memory");
451                 return EAP_INVALID;
452         }
453
454         hdr->code = (reply->code & 0xFF);
455         hdr->id = (reply->id & 0xFF);
456         total_length = htons(total_length);
457         memcpy(hdr->length, &total_length, sizeof(uint16_t));
458
459         /*
460          *      Request and Response packets are special.
461          */
462         if ((reply->code == PW_EAP_REQUEST) ||
463             (reply->code == PW_EAP_RESPONSE)) {
464                 hdr->data[0] = (reply->type.type & 0xFF);
465
466                 /*
467                  * Here since we cannot know the typedata format and length
468                  *
469                  * Type_data is expected to be wired by each EAP-Type
470                  *
471                  * Zero length/No typedata is supported as long as
472                  * type is defined
473                  */
474                 if (reply->type.data && reply->type.length > 0) {
475                         memcpy(&hdr->data[1], reply->type.data, reply->type.length);
476                         free(reply->type.data);
477                         reply->type.data = reply->packet + EAP_HEADER_LEN + 1/*EAPtype*/;
478                 }
479         }
480
481         return EAP_VALID;
482 }
483
484 /*
485  *      compose EAP reply packet in EAP-Message attr of RADIUS.  If
486  *      EAP exceeds 253, frame it in multiple EAP-Message attrs.
487  *
488  *      Set the RADIUS reply codes based on EAP request codes.  Append
489  *      any additonal VPs to RADIUS reply
490  */
491 int eap_compose(EAP_HANDLER *handler)
492 {
493         uint16_t eap_len, len;
494         VALUE_PAIR *eap_msg;
495         VALUE_PAIR *vp;
496         eap_packet_t *eap_packet;
497         unsigned char   *ptr;
498         REQUEST *request = handler->request;
499         EAP_DS *eap_ds = handler->eap_ds;
500         EAP_PACKET *reply = eap_ds->request;
501         int rcode;
502
503         /*
504          *      The Id for the EAP packet to the NAS wasn't set.
505          *      Do so now.
506          *
507          *      LEAP requires the Id to be incremented on EAP-Success
508          *      in Stage 4, so that we can carry on the conversation
509          *      where the client asks us to authenticate ourselves
510          *      in stage 5.
511          */
512         if (!eap_ds->set_request_id) {
513                 /*
514                  *      Id serves to suppport request/response
515                  *      retransmission in the EAP layer and as such
516                  *      must be different for 'adjacent' packets
517                  *      except in case of success/failure-replies.
518                  *
519                  *      RFC2716 (EAP-TLS) requires this to be
520                  *      incremented, RFC2284 only makes the above-
521                  *      mentioned restriction.
522                  */
523                 reply->id = handler->eap_ds->response->id;
524                 
525                 switch (reply->code) {
526                         /*
527                          *      The Id is a simple "ack" for success
528                          *      and failure.
529                          */
530                 case PW_EAP_SUCCESS:
531                 case PW_EAP_FAILURE:
532                         break;
533                         
534                         /*
535                          *      We've sent a response to their
536                          *      request, the Id is incremented.
537                          */
538                 default:
539                         ++reply->id;
540                 }
541         } else {
542                 DEBUG2("  rlm_eap: Underlying EAP-Type set EAP ID to %d",
543                        reply->id);
544         }
545
546         /*
547          *      For Request & Response packets, set the EAP sub-type,
548          *      if the EAP sub-module didn't already set it.
549          *
550          *      This allows the TLS module to be "morphic", and means
551          *      that the TTLS and PEAP modules can call it to do most
552          *      of their dirty work.
553          */
554         if (((eap_ds->request->code == PW_EAP_REQUEST) ||
555              (eap_ds->request->code == PW_EAP_RESPONSE)) &&
556             (eap_ds->request->type.type == 0)) {
557                 rad_assert(handler->eap_type >= PW_EAP_MD5);
558                 rad_assert(handler->eap_type <= PW_EAP_MAX_TYPES);
559
560                 eap_ds->request->type.type = handler->eap_type;
561         }
562           
563
564         if (eap_wireformat(reply) == EAP_INVALID) {
565                 return RLM_MODULE_INVALID;
566         }
567         eap_packet = (eap_packet_t *)reply->packet;
568
569         memcpy(&eap_len, &(eap_packet->length), sizeof(uint16_t));
570         len = eap_len = ntohs(eap_len);
571         ptr = (unsigned char *)eap_packet;
572
573         do {
574                 if (eap_len > 253) {
575                         len = 253;
576                         eap_len -= 253;
577                 } else {
578                         len = eap_len;
579                         eap_len = 0;
580                 }
581
582                 /* 
583                  * create a value pair & append it to the request reply list
584                  * This memory gets freed up when request is freed up
585                  */
586                 eap_msg = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
587                 memcpy(eap_msg->strvalue, ptr, len);
588                 eap_msg->length = len;
589                 pairadd(&(request->reply->vps), eap_msg);
590                 ptr += len;
591                 eap_msg = NULL;
592         } while (eap_len);
593
594         /*
595          *      EAP-Message is always associated with
596          *      Message-Authenticator but not vice-versa.
597          *
598          *      Don't add a Message-Authenticator if it's already
599          *      there.
600          */
601         vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR);
602         if (!vp) {
603                 vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
604                 memset(vp->strvalue, 0, AUTH_VECTOR_LEN);
605                 vp->length = AUTH_VECTOR_LEN;
606                 pairadd(&(request->reply->vps), vp);
607         }
608
609         /* Set request reply code, but only if it's not already set. */
610         rcode = RLM_MODULE_OK;
611         if (!request->reply->code) switch(reply->code) {
612         case PW_EAP_RESPONSE:
613                 request->reply->code = PW_AUTHENTICATION_ACK;
614                 rcode = RLM_MODULE_HANDLED; /* leap weirdness */
615                 break;
616         case PW_EAP_SUCCESS:
617                 request->reply->code = PW_AUTHENTICATION_ACK;
618                 rcode = RLM_MODULE_OK;
619                 break;
620         case PW_EAP_FAILURE:
621                 request->reply->code = PW_AUTHENTICATION_REJECT;
622                 rcode = RLM_MODULE_REJECT;
623                 break;
624         case PW_EAP_REQUEST:
625                 request->reply->code = PW_ACCESS_CHALLENGE;
626                 rcode = RLM_MODULE_HANDLED;
627                 break;
628         default:
629                 /* Should never enter here */
630                 radlog(L_ERR, "rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code);
631                 request->reply->code = PW_AUTHENTICATION_REJECT;
632                 rcode = RLM_MODULE_REJECT;
633                 break;
634         }
635
636         return rcode;
637 }
638
639 /*
640  * Radius criteria, EAP-Message is invalid without Message-Authenticator
641  * For EAP_START, send Access-Challenge with EAP Identity request.
642  */
643 int eap_start(rlm_eap_t *inst, REQUEST *request)
644 {
645         VALUE_PAIR *vp;
646         VALUE_PAIR *eap_msg;
647         EAP_DS *eap_ds;
648         EAP_HANDLER handler;
649
650         eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);
651         if (eap_msg == NULL) {
652                 DEBUG2("  rlm_eap: No EAP-Message, not doing EAP");
653                 return EAP_NOOP;
654         }
655
656         /*
657          *      Look for EAP-Type = None (FreeRADIUS specific attribute)
658          *      this allows you to NOT do EAP for some users.
659          */
660         vp = pairfind(request->packet->vps, PW_EAP_TYPE);
661         if (vp && vp->lvalue == 0) {
662                 DEBUG2("  rlm_eap: Found EAP-Message, but EAP-Type = None, so we're not doing EAP.");
663                 return EAP_NOOP;
664         }
665
666         /*
667          *      http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
668          *
669          *      This is handled by rad_recv().
670          */
671
672         /*
673          *      We're allowed only a few codes.  Request, Response,
674          *      Success, or Failure.
675          */
676         if ((eap_msg->strvalue[0] == 0) ||
677             (eap_msg->strvalue[0] > PW_EAP_MAX_CODES)) {
678                 DEBUG2("  rlm_eap: Unknown EAP packet");
679         } else {
680                 DEBUG2("  rlm_eap: EAP packet type %s id %d length %d",
681                        eap_codes[eap_msg->strvalue[0]],
682                        eap_msg->strvalue[1],
683                        eap_msg->length);
684         }
685
686         /*
687          *      If we've been configured to proxy, do nothing.
688          *
689          *      Note that we don't check if the realm is local.
690          *      We figure that anyone bright enough to add
691          *      Proxy-To-Realm is bright enough to NOT do so
692          *      when it's a local realm.
693          */
694         if (pairfind(request->config_items, PW_PROXY_TO_REALM) != NULL) {
695                 DEBUG2("  rlm_eap: Request is supposed to be proxied.  Not doing EAP.");
696                 return EAP_NOOP;
697         }
698
699         /*
700          *      Not a start message.  Don't start anything.
701          *
702          *      Later EAP messages are longer than the 'start' message,
703          *      so this function returns 'no start found', so that
704          *      the rest of the EAP code can use the State attribute
705          *      to match this EAP-Message to an ongoing conversation.
706          */
707         if (eap_msg->length != EAP_START) {
708                 DEBUG2("  rlm_eap: No EAP Start, assuming it's an on-going EAP conversation");
709
710                 /*
711                  *      Add the 'EAP-Type' attribute to the request,
712                  *      if it's part of an EAP conversation, and the
713                  *      EAP sub-type is in the EAP packet.
714                  *
715                  *      Store the EAP type in the request, so modules
716                  *      outside of EAP can check & use it.
717                  */
718                 if (((eap_msg->strvalue[0] == PW_EAP_REQUEST) ||
719                      (eap_msg->strvalue[0] == PW_EAP_RESPONSE)) &&
720                     (eap_msg->length >= (EAP_HEADER_LEN + 1))) {
721                         /*
722                          *      Create an EAP-Type of the type which
723                          *      was NAK'd, or of the type in the packet.
724                          */
725                         vp = paircreate(PW_EAP_TYPE, PW_TYPE_INTEGER);
726                         if (vp) {
727                                 vp->lvalue = eap_msg->strvalue[4];
728                                 pairadd(&(request->packet->vps), vp);
729                         }
730                         
731                         /*
732                          *      We've been told to ignore unknown EAP
733                          *      types, AND it's an unknown type.
734                          *      Return "NOOP", which will cause the
735                          *      eap_authorize() to return NOOP.
736                          *
737                          *      EAP-Identity, Notification, and NAK
738                          *      are all handled internally, so they
739                          *      never have handlers.
740                          */
741                         if ((eap_msg->strvalue[4] >= PW_EAP_MD5) &&
742                             inst->ignore_unknown_eap_types &&
743                             ((eap_msg->strvalue[4] == 0) ||
744                              (eap_msg->strvalue[4] > PW_EAP_MAX_TYPES) ||
745                              (inst->types[eap_msg->strvalue[4]] == NULL))) {
746                                 DEBUG2("  rlm_eap:  Ignoring Unknown EAP type");
747                                 return EAP_NOOP;
748                         }
749
750                         /*
751                          *      They're NAKing the EAP type we wanted
752                          *      to use, and asking for one which we don't
753                          *      support.
754                          *
755                          *      NAK is code + id + length1 + length + NAK
756                          *             + requested EAP type.
757                          *
758                          *      We know at this point that we can't
759                          *      handle the request.  We could either
760                          *      return an EAP-Fail here, but it's not
761                          *      too critical.
762                          *
763                          *      By returning "noop", we can ensure
764                          *      that authorize() returns NOOP, and
765                          *      another module may choose to proxy
766                          *      the request.
767                          */
768                         if ((eap_msg->strvalue[4] == PW_EAP_NAK) &&
769                             (eap_msg->length >= (EAP_HEADER_LEN + 2)) &&
770                             inst->ignore_unknown_eap_types &&
771                             ((eap_msg->strvalue[5] == 0) ||
772                              (eap_msg->strvalue[5] > PW_EAP_MAX_TYPES) ||
773                              (inst->types[eap_msg->strvalue[5]] == NULL))) {
774                                 DEBUG2("  rlm_eap: Ignoring NAK with request for unknown EAP type");
775                                 return EAP_NOOP;
776                         }
777                 } /* else it's not an EAP-Request or EAP-Response */
778  
779                 /*
780                  *      No EAP-Start found.
781                  */
782                 return EAP_NOTFOUND;
783         }
784
785         DEBUG2("  rlm_eap: Got EAP_START message");
786         if ((eap_ds = eap_ds_alloc()) == NULL) {
787                 DEBUG2("  rlm_eap: EAP Start failed in allocation");
788                 return EAP_FAIL;
789         }
790
791         /*
792          *      It's an EAP-Start packet.  Tell them to stop wasting
793          *      our time, and give us an EAP-Identity packet.
794          *
795          *      Hmm... we should probably check the contents of the
796          *      EAP-Start packet for something...
797          */
798         eap_ds->request->code = PW_EAP_REQUEST;
799         eap_ds->request->type.type = PW_EAP_IDENTITY;
800
801         /*
802          *      We don't have a handler, but eap_compose needs one,
803          *      (for various reasons), so we fake it out here.
804          */
805         memset(&handler, 0, sizeof(handler));
806         handler.request = request;
807         handler.eap_ds = eap_ds;
808
809         eap_compose(&handler);
810
811         eap_ds_free(&eap_ds);
812         return EAP_FOUND;
813 }
814
815 /*
816  *      compose EAP FAILURE packet in EAP-Message
817  */
818 void eap_fail(EAP_HANDLER *handler)
819 {
820         handler->eap_ds->request->code = PW_EAP_FAILURE;
821         eap_compose(handler);
822 }
823
824 /*
825  *      compose EAP SUCCESS packet in EAP-Message
826  */
827 void eap_success(EAP_HANDLER *handler)
828 {
829         handler->eap_ds->request->code = PW_EAP_SUCCESS;
830         eap_compose(handler);
831 }
832
833 /*
834  * Basic EAP packet verfications & validations
835  */
836 static int eap_validation(eap_packet_t *eap_packet)
837 {
838         uint16_t len;
839
840         memcpy(&len, eap_packet->length, sizeof(uint16_t));
841         len = ntohs(len);
842
843         /*
844          *      High level EAP packet checks
845          */
846         if ((len <= EAP_HEADER_LEN) ||
847             ((eap_packet->code != PW_EAP_RESPONSE) &&
848              (eap_packet->code != PW_EAP_REQUEST)) ||
849             (eap_packet->data[0] <= 0) ||
850             (eap_packet->data[0] > PW_EAP_MAX_TYPES)) {
851
852                 radlog(L_AUTH, "rlm_eap: Incorrect EAP Message, "
853                                 "Ignoring the packet");
854                 return EAP_INVALID;
855         }
856
857         /* we don't expect notification, but we send it */
858         if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {
859                 radlog(L_AUTH, "rlm_eap: Got NOTIFICATION, "
860                                 "Ignoring the packet");
861                 return EAP_INVALID;
862         }
863
864         return EAP_VALID;
865 }
866
867
868 /*
869  *  Get the user Identity only from EAP-Identity packets
870  */
871 static char *eap_identity(eap_packet_t *eap_packet)
872 {
873         int size;
874         uint16_t len;
875         char *identity;
876
877         if ((eap_packet == NULL) ||
878             (eap_packet->code != PW_EAP_RESPONSE) ||
879             (eap_packet->data[0] != PW_EAP_IDENTITY)) {
880                 return NULL;
881         }
882
883         memcpy(&len, eap_packet->length, sizeof(uint16_t));
884         len = ntohs(len);
885
886         if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
887                 radlog(L_ERR, "rlm_eap: UserIdentity Unknown ");
888                 return NULL;
889         }
890
891         size = len - 5;
892         identity = (char *)malloc(size + 1);
893         if (identity == NULL) {
894                 radlog(L_ERR, "rlm_eap: out of memory");
895                 return NULL;
896         }
897         memcpy(identity, &eap_packet->data[1], size);
898         identity[size] = '\0';
899
900         return identity;
901 }
902
903
904 /*
905  *      Create our Request-Response data structure with the eap packet
906  */
907 static EAP_DS *eap_buildds(eap_packet_t **eap_packet_p)
908 {
909         EAP_DS          *eap_ds = NULL;
910         eap_packet_t    *eap_packet = *eap_packet_p;
911         int             typelen;
912         uint16_t        len;
913
914         if ((eap_ds = eap_ds_alloc()) == NULL) {
915                 return NULL;
916         }
917
918         eap_ds->response->packet = (unsigned char *)eap_packet;
919         eap_ds->response->code = eap_packet->code;
920         eap_ds->response->id = eap_packet->id;
921         eap_ds->response->type.type = eap_packet->data[0];
922
923         memcpy(&len, eap_packet->length, sizeof(uint16_t));
924         len = ntohs(len);
925         eap_ds->response->length = len;
926
927         /*
928          *      We've eaten the eap packet into the eap_ds.
929          */
930         *eap_packet_p = NULL;
931
932         /*
933          *      First 5 bytes in eap, are code + id + length(2) + type.
934          *
935          *      The rest is type-specific data.  We skip type while
936          *      getting typedata from data.
937          */
938         typelen = len - 5/*code + id + length + type */;
939         if (typelen > 0) {
940                 /*
941                  *      Since the packet contains the complete
942                  *      eap_packet, typedata will be a ptr in packet
943                  *      to its typedata
944                  */
945                 eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;
946                 eap_ds->response->type.length = typelen;
947         } else {
948                 eap_ds->response->type.length = 0;
949                 eap_ds->response->type.data = NULL;
950         }
951
952         return eap_ds;
953 }
954
955
956 /*
957  * If identity response then create a fresh handler & fill the identity
958  * else handler MUST be in our list, get that.
959  * This handler creation cannot fail
960  *
961  * username contains REQUEST->username which might have been stripped.
962  * identity contains the one sent in EAP-Identity response
963  */
964 EAP_HANDLER *eap_handler(rlm_eap_t *inst, eap_packet_t **eap_packet_p,
965                          REQUEST *request)
966 {
967         EAP_HANDLER     *handler = NULL;
968         eap_packet_t    *eap_packet = *eap_packet_p;
969
970         /*
971          *      Ensure it's a valid EAP-Request, or EAP-Response.
972          */
973         if (eap_validation(eap_packet) == EAP_INVALID) {
974                 free(*eap_packet_p);
975                 *eap_packet_p = NULL;
976                 return NULL;
977         }
978
979         /*
980          *      EAP_HANDLER MUST be found in the list if it is not
981          *      EAP-Identity response
982          */
983         if (eap_packet->data[0] != PW_EAP_IDENTITY) {
984                 handler = eaplist_find(inst, request, eap_packet);
985                 if (handler == NULL) {
986                         /* Either send EAP_Identity or EAP-Fail */
987                         radlog(L_ERR, "rlm_eap: Either EAP-request timed out OR"
988                                 " EAP-response to an unknown EAP-request");
989                         free(*eap_packet_p);
990                         *eap_packet_p = NULL;
991                         return NULL;
992                 }
993
994                 /*
995                  *      Even more paranoia.  Without this, some weird
996                  *      clients could do crazy things.
997                  *
998                  *      It's ok to send EAP sub-type NAK in response
999                  *      to a request for a particular type, but it's NOT
1000                  *      OK to blindly return data for another type.
1001                  */
1002                 if ((eap_packet->data[0] != PW_EAP_NAK) &&
1003                     (eap_packet->data[0] != handler->eap_type)) {
1004                         radlog(L_ERR, "rlm_eap: Response appears to match, but EAP type is wrong.");
1005                         free(*eap_packet_p);
1006                         *eap_packet_p = NULL;
1007                         return NULL;
1008                 }
1009         } else {
1010                 handler = eap_handler_alloc();
1011                 if (handler == NULL) {
1012                         radlog(L_ERR, "rlm_eap: out of memory");
1013                         free(*eap_packet_p);
1014                         *eap_packet_p = NULL;
1015                         return NULL;
1016                 }
1017
1018                 /*
1019                  *      All fields in the handler are set to zero.
1020                  */
1021
1022                 handler->identity = eap_identity(eap_packet);
1023                 if (handler->identity == NULL) {
1024                         radlog(L_ERR, "rlm_eap: Identity Unknown, authentication failed");
1025                         free(*eap_packet_p);
1026                         *eap_packet_p = NULL;
1027                         eap_handler_free(&handler);
1028                         return NULL;
1029                 }
1030         }
1031
1032         handler->eap_ds = eap_buildds(eap_packet_p);
1033         if (handler->eap_ds == NULL) {
1034                 free(*eap_packet_p);
1035                 *eap_packet_p = NULL;
1036                 eap_handler_free(&handler);
1037                 return NULL;
1038         }
1039
1040         handler->timestamp = time(NULL);
1041         handler->request = request; /* LEAP needs this */
1042         return handler;
1043 }