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