5b19f65e81fd89ec27da4eee3d0f398cd1b18251
[freeradius.git] / src / modules / rlm_eap2 / rlm_eap2.c
1 /*
2  * rlm_eap.c  contains handles that are called from modules.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2007  Alan DeKok <aland@deployingradius.com>
21  */
22
23 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/modules.h>
28 #include <freeradius-devel/rad_assert.h>
29
30 /*
31  *      Hostap includes.
32  */
33 #include <utils/includes.h>
34
35 #include <utils/common.h>
36 #include <eap_server/eap.h>
37 #include <crypto/tls.h>
38
39
40 struct eap_server_ctx {
41         struct eap_eapol_interface *eap_if;
42         struct eap_sm *eap;
43         void *tls_ctx;
44 };
45
46 #define EAP_STATE_LEN (AUTH_VECTOR_LEN)
47 typedef struct EAP_HANDLER {
48         struct EAP_HANDLER *prev, *next;
49         uint8_t         state[EAP_STATE_LEN];
50         fr_ipaddr_t     src_ipaddr;
51
52         time_t          timestamp;
53
54         REQUEST         *request;
55         struct rlm_eap_t *inst;
56
57         struct eapol_callbacks eap_cb;
58         struct eap_config eap_conf;
59         struct eap_server_ctx server_ctx;
60 } EAP_HANDLER;
61
62 typedef struct rlm_eap_t {
63         rbtree_t        *session_tree;
64         EAP_HANDLER     *session_head, *session_tail;
65
66         /*
67          *      Configuration items.
68          */
69         int             timer_limit;
70         int             cisco_accounting_username_bug;
71
72         struct tls_connection_params tparams;
73
74         int             num_types;
75         EapType         methods[EAP_MAX_METHODS];
76         int             vendors[EAP_MAX_METHODS];
77
78 #ifdef HAVE_PTHREAD_H
79         pthread_mutex_t session_mutex;
80 #endif
81
82         fr_randctx      rand_pool;
83         void *tls_ctx;
84 } rlm_eap_t;
85
86
87 static void eap_handler_free(EAP_HANDLER *handler)
88 {
89         eap_server_sm_deinit(handler->server_ctx.eap);
90         free(handler);
91 }
92
93 static void eaplist_free(rlm_eap_t *inst)
94 {
95         EAP_HANDLER *node, *next;
96
97         for (node = inst->session_head; node != NULL; node = next) {
98                 next = node->next;
99                 eap_handler_free(node);
100         }
101
102         inst->session_head = inst->session_tail = NULL;
103 }
104
105 /*
106  *      Return a 32-bit random number.
107  */
108 static uint32_t eap_rand(fr_randctx *ctx)
109 {
110         uint32_t num;
111
112         num = ctx->randrsl[ctx->randcnt++];
113         if (ctx->randcnt == 256) {
114                 ctx->randcnt = 0;
115                 fr_isaac(ctx);
116         }
117
118         return num;
119 }
120
121 /*
122  *      Add a handler to the set of active sessions.
123  *
124  *      Since we're adding it to the list, we guess that this means
125  *      the packet needs a State attribute.  So add one.
126  */
127 static int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler)
128 {
129         int             i, status;
130         uint32_t        lvalue;
131         VALUE_PAIR      *state;
132
133         rad_assert(handler != NULL);
134         rad_assert(handler->request != NULL);
135
136         /*
137          *      Generate State, since we've been asked to add it to
138          *      the list.
139          */
140         state = pairmake("State", "0x00", T_OP_EQ);
141         if (!state) return 0;
142         pairadd(&(handler->request->reply->vps), state);
143         state->length = EAP_STATE_LEN;
144
145         /*
146          *      The time at which this request was made was the time
147          *      at which it was received by the RADIUS server.
148          */
149         handler->timestamp = handler->request->timestamp;
150
151         handler->src_ipaddr = handler->request->packet->src_ipaddr;
152
153         /*
154          *      We don't need this any more.
155          */
156         handler->request = NULL;
157
158         /*
159          *      Playing with a data structure shared among threads
160          *      means that we need a lock, to avoid conflict.
161          */
162         pthread_mutex_lock(&(inst->session_mutex));
163
164         /*
165          *      Create a completely random state.
166          */
167         for (i = 0; i < 4; i++) {
168                 lvalue = eap_rand(&inst->rand_pool);
169                 memcpy(state->vp_octets + i * 4, &lvalue, sizeof(lvalue));
170         }
171         memcpy(handler->state, state->vp_strvalue, sizeof(handler->state));
172
173         /*
174          *      Big-time failure.
175          */
176         status = rbtree_insert(inst->session_tree, handler);
177
178         if (status) {
179                 EAP_HANDLER *prev;
180
181                 prev = inst->session_tail;
182                 if (prev) {
183                         prev->next = handler;
184                         handler->prev = prev;
185                         handler->next = NULL;
186                         inst->session_tail = handler;
187                 } else {
188                         inst->session_head = inst->session_tail = handler;
189                         handler->next = handler->prev = NULL;
190                 }
191         }
192
193         /*
194          *      Now that we've finished mucking with the list,
195          *      unlock it.
196          */
197         pthread_mutex_unlock(&(inst->session_mutex));
198
199         if (!status) {
200                 radlog(L_ERR, "rlm_eap2: Failed to remember handler!");
201                 eap_handler_free(handler);
202                 return 0;
203         }
204
205         return 1;
206 }
207
208 /*
209  *      Find a a previous EAP-Request sent by us, which matches
210  *      the current EAP-Response.
211  *
212  *      Then, release the handle from the list, and return it to
213  *      the caller.
214  *
215  *      Also since we fill the eap_ds with the present EAP-Response we
216  *      got to free the prev_eapds & move the eap_ds to prev_eapds
217  */
218 static EAP_HANDLER *eaplist_find(rlm_eap_t *inst, REQUEST *request)
219 {
220         int             i;
221         VALUE_PAIR      *state;
222         rbnode_t        *node;
223         EAP_HANDLER     *handler, myHandler;
224
225         /*
226          *      We key the sessions off of the 'state' attribute, so it
227          *      must exist.
228          */
229         state = pairfind(request->packet->vps, PW_STATE, 0);
230         if (!state ||
231             (state->length != EAP_STATE_LEN)) {
232                 return NULL;
233         }
234
235         myHandler.src_ipaddr = request->packet->src_ipaddr;
236         memcpy(myHandler.state, state->vp_strvalue, sizeof(myHandler.state));
237
238         /*
239          *      Playing with a data structure shared among threads
240          *      means that we need a lock, to avoid conflict.
241          */
242         pthread_mutex_lock(&(inst->session_mutex));
243
244         /*
245          *      Check the first few handlers in the list, and delete
246          *      them if they're too old.  We don't need to check them
247          *      all, as incoming requests will quickly cause older
248          *      handlers to be deleted.
249          *
250          */
251         for (i = 0; i < 2; i++) {
252                 handler = inst->session_head;
253                 if (handler &&
254                     ((request->timestamp - handler->timestamp) > inst->timer_limit)) {
255                         node = rbtree_find(inst->session_tree, handler);
256                         rad_assert(node != NULL);
257                         rbtree_delete(inst->session_tree, node);
258
259                         /*
260                          *      handler == inst->session_head
261                          */
262                         inst->session_head = handler->next;
263                         if (handler->next) {
264                                 handler->next->prev = NULL;
265                         } else {
266                                 inst->session_head = NULL;
267                         }
268                         eap_handler_free(handler);
269                 }
270         }
271
272         handler = NULL;
273         node = rbtree_find(inst->session_tree, &myHandler);
274         if (node) {
275                 handler = rbtree_node2data(inst->session_tree, node);
276
277                 /*
278                  *      Delete old handler from the tree.
279                  */
280                 rbtree_delete(inst->session_tree, node);
281                 
282                 /*
283                  *      And unsplice it from the linked list.
284                  */
285                 if (handler->prev) {
286                         handler->prev->next = handler->next;
287                 } else {
288                         inst->session_head = handler->next;
289                 }
290                 if (handler->next) {
291                         handler->next->prev = handler->prev;
292                 } else {
293                         inst->session_tail = handler->prev;
294                 }
295                 handler->prev = handler->next = NULL;
296         }
297
298         pthread_mutex_unlock(&(inst->session_mutex));
299
300         /*
301          *      Not found.
302          */
303         if (!node) {
304                 RDEBUG2("Request not found in the list");
305                 return NULL;
306         }
307
308         /*
309          *      Found, but state verification failed.
310          */
311         if (!handler) {
312                 radlog(L_ERR, "rlm_eap2: State verification failed.");
313                 return NULL;
314         }
315
316         RDEBUG2("Request found, released from the list");
317
318         return handler;
319 }
320
321
322 /*
323  * delete all the allocated space by eap module
324  */
325 static int eap_detach(void *instance)
326 {
327         rlm_eap_t *inst;
328
329         inst = (rlm_eap_t *)instance;
330
331         rbtree_free(inst->session_tree);
332         inst->session_tree = NULL;
333         eaplist_free(inst);
334         eap_server_unregister_methods();
335         tls_deinit(inst->tls_ctx);
336
337         pthread_mutex_destroy(&(inst->session_mutex));
338
339         free(inst);
340
341         return 0;
342 }
343
344
345 /*
346  *      Compare two handlers.
347  */
348 static int eap_handler_cmp(const void *a, const void *b)
349 {
350         int rcode;
351         const EAP_HANDLER *one = a;
352         const EAP_HANDLER *two = b;
353
354         rcode = fr_ipaddr_cmp(&one->src_ipaddr, &two->src_ipaddr);
355         if (rcode != 0) return rcode;
356
357         return memcmp(one->state, two->state, sizeof(one->state));
358 }
359
360
361 static int server_get_eap_user(void *ctx, const u8 *identity,
362                                size_t identity_len, int phase2,
363                                struct eap_user *user)
364 {
365         int i;
366         VALUE_PAIR *vp;
367         EAP_HANDLER *handler = ctx;
368         REQUEST *request = handler->request;
369
370         os_memset(user, 0, sizeof(*user));
371
372         /*
373          *      FIXME: Run through "authorise" again to look up
374          *      password for the given identity
375          */
376         identity = identity;    /* -Wunused */
377         identity_len = identity_len; /* -Wunused */
378
379         /*
380          *      Do this always, just in case.
381          */
382         vp = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0);
383         if (vp) {
384                 user->password = (u8 *) os_strdup(vp->vp_strvalue);
385                 user->password_len = vp->length;
386         }
387         if (!vp) vp = pairfind(request->config_items, PW_NT_PASSWORD, 0);
388         if (vp) {
389                 user->password = (u8 *) malloc(vp->length);
390                 memcpy(user->password, vp->vp_octets, vp->length);
391                 user->password_len = vp->length;
392         }
393
394         if (!phase2) {
395                 for (i = 0; i < handler->inst->num_types; i++) {
396                         user->methods[i].vendor = handler->inst->vendors[i];
397                         user->methods[i].method = handler->inst->methods[i];
398                 }
399                 return 0;
400         }
401
402         /*
403          *      FIXME: run tunneled sessions through the tunneled portion...
404          */
405
406         /*
407          *      FIXME: Selectively control tunneled EAP types.
408          */
409         user->methods[0].vendor = EAP_VENDOR_IETF;
410         user->methods[0].method = EAP_TYPE_MD5;
411         user->methods[1].vendor = EAP_VENDOR_IETF;
412         user->methods[1].method = EAP_TYPE_MSCHAPV2;
413
414         /*
415          *      No password configured...
416          */
417
418         return 0;
419 }
420
421
422 static const char * server_get_eap_req_id_text(void *ctx, size_t *len)
423 {
424         ctx = ctx;              /* -Wunused */
425         *len = 0;
426         return NULL;
427 }
428
429
430 static CONF_PARSER tls_config[] = {
431         /*
432          *      TLS parameters.
433          */
434         { "ca_cert", PW_TYPE_STRING_PTR,
435           offsetof(rlm_eap_t, tparams.ca_cert),
436           NULL, "${confdir}/certs/ca.pem" },
437         { "server_cert", PW_TYPE_STRING_PTR,
438           offsetof(rlm_eap_t, tparams.client_cert),
439           NULL, "${confdir}/certs/server.pem" },
440         { "private_key_file", PW_TYPE_STRING_PTR,
441           offsetof(rlm_eap_t, tparams.private_key),
442           NULL, "${confdir}/certs/server.pem" },
443         { "private_key_password", PW_TYPE_STRING_PTR,
444           offsetof(rlm_eap_t, tparams.private_key_passwd),
445           NULL, "whatever" },
446
447         { NULL, -1, 0, NULL, NULL }           /* end the list */
448 };
449
450 static const CONF_PARSER module_config[] = {
451         { "timer_expire", PW_TYPE_INTEGER,
452           offsetof(rlm_eap_t, timer_limit), NULL, "60"},
453         { "cisco_accounting_username_bug", PW_TYPE_BOOLEAN,
454           offsetof(rlm_eap_t, cisco_accounting_username_bug), NULL, "no" },
455
456         { "tls", PW_TYPE_SUBSECTION, 0, NULL, (const void *) tls_config },
457
458         { NULL, -1, 0, NULL, NULL }           /* end the list */
459 };
460
461
462 static int eap_example_server_init_tls(rlm_eap_t *inst)
463 {
464         struct tls_config tconf;
465
466         os_memset(&tconf, 0, sizeof(tconf));
467         inst->tls_ctx = tls_init(&tconf);
468         if (inst->tls_ctx == NULL)
469                 return -1;
470
471         if (tls_global_set_params(inst->tls_ctx, &inst->tparams)) {
472                 radlog(L_ERR, "rlm_eap2: Failed to set TLS parameters");
473                 return -1;
474         }
475
476         if (tls_global_set_verify(inst->tls_ctx, 0)) {
477                 radlog(L_ERR, "rlm_eap2: Failed to set check_crl");
478                 return -1;
479         }
480
481         return 0;
482 }
483
484
485 /*
486  * read the config section and load all the eap authentication types present.
487  */
488 static int eap_instantiate(CONF_SECTION *cs, void **instance)
489 {
490         int i, num_types;
491         int             has_tls, do_tls;
492         rlm_eap_t       *inst;
493         CONF_SECTION    *scs;
494
495         inst = (rlm_eap_t *) malloc(sizeof(*inst));
496         if (!inst) {
497                 return -1;
498         }
499         memset(inst, 0, sizeof(*inst));
500         if (cf_section_parse(cs, inst, module_config) < 0) {
501                 eap_detach(inst);
502                 return -1;
503         }
504
505         /*
506          *      Create our own random pool.
507          */
508         for (i = 0; i < 256; i++) {
509                 inst->rand_pool.randrsl[i] = fr_rand();
510         }
511         fr_randinit(&inst->rand_pool, 1);
512
513         /*
514          *      List of sessions are set to NULL by the memset
515          *      of 'inst', above.
516          */
517
518         /*
519          *      Lookup sessions in the tree.  We don't free them in
520          *      the tree, as that's taken care of elsewhere...
521          */
522         inst->session_tree = rbtree_create(eap_handler_cmp, NULL, 0);
523         if (!inst->session_tree) {
524                 radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize tree");
525                 eap_detach(inst);
526                 return -1;
527         }
528
529         /*
530          *      This registers ALL available methods.
531          *
532          *      FIXME: we probably want to selectively register
533          *      some methods.
534          */
535         if (eap_server_register_methods() < 0) {
536                 eap_detach(inst);
537                 return -1;
538         }
539
540         /* Load all the configured EAP-Types */
541         num_types = 0;
542         has_tls = do_tls = 0;
543         for (scs=cf_subsection_find_next(cs, NULL, NULL);
544                 scs != NULL;
545                 scs=cf_subsection_find_next(cs, scs, NULL)) {
546                 const char      *auth_type;
547                 char            buffer[64], *p;
548
549                 auth_type = cf_section_name1(scs);
550
551                 if (!auth_type)  continue;
552
553                 if (num_types >= EAP_MAX_METHODS) {
554                         radlog(L_INFO, "WARNING: Ignoring EAP type %s: too many types defined", auth_type);
555                         continue;
556                 }
557
558                 /*
559                  *      Hostapd doesn't do case-insensitive comparisons.
560                  *      So we mash everything to uppercase for it.
561                  */
562                 strlcpy(buffer, auth_type, sizeof(buffer));
563
564                 for (p = buffer; *p; p++) {
565                         if (!islower((int)*p)) continue;
566                         *p = toupper((int)*p);
567                 }
568
569                 inst->methods[num_types] = eap_server_get_type(buffer,
570                                                                &inst->vendors[num_types]);
571                 if (inst->methods[num_types] == EAP_TYPE_NONE) {
572                         radlog(L_ERR|L_CONS, "rlm_eap2: Unknown EAP type %s",
573                                auth_type);
574                         eap_detach(inst);
575                         return -1;
576                 }
577
578                 switch (inst->methods[num_types]) {
579                 case EAP_TYPE_TLS:
580                         has_tls = TRUE;
581                         /* FALL-THROUGH */
582
583                 case EAP_TYPE_TTLS:
584                 case EAP_TYPE_PEAP:
585                 case EAP_TYPE_FAST:
586                         do_tls = TRUE;
587                         break;
588
589                 default:
590                         break;
591                 }
592
593                 num_types++;    /* successfully loaded one more types */
594         }
595         inst->num_types = num_types;
596
597         if (do_tls && !has_tls) {
598                 radlog(L_ERR|L_CONS, "rlm_eap2: TLS has not been configured.  Cannot do methods that need TLS.");
599                 eap_detach(inst);
600                 return -1;
601         }
602
603         if (do_tls) {
604                 /*
605                  *      Initialize TLS.
606                  */
607                 if (eap_example_server_init_tls(inst) < 0) {
608                         radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize TLS");
609                         eap_detach(inst);
610                         return -1;
611                 }
612         }
613
614         pthread_mutex_init(&(inst->session_mutex), NULL);
615
616         *instance = inst;
617         return 0;
618 }
619
620
621 static int eap_req2vp(EAP_HANDLER *handler)
622 {
623         int             encoded, total, size;
624         const uint8_t   *ptr;
625         VALUE_PAIR      *head = NULL;
626         VALUE_PAIR      **tail = &head;
627         VALUE_PAIR      *vp;
628
629         ptr = wpabuf_head(handler->server_ctx.eap_if->eapReqData);
630         encoded = total = wpabuf_len(handler->server_ctx.eap_if->eapReqData);
631
632         do {
633                 size = total;
634                 if (size > 253) size = 253;
635
636                 vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
637                 if (!vp) {
638                         pairfree(&head);
639                         return -1;
640                 }
641                 memcpy(vp->vp_octets, ptr, size);
642                 vp->length = size;
643
644                 *tail = vp;
645                 tail = &(vp->next);
646
647                 ptr += size;
648                 total -= size;
649         } while (total > 0);
650
651         pairdelete(&handler->request->reply->vps, PW_EAP_MESSAGE);
652         pairadd(&handler->request->reply->vps, head);
653
654         return encoded;
655 }
656
657 static int eap_example_server_step(EAP_HANDLER *handler)
658 {
659         int res, process = 0;
660         REQUEST *request = handler->request;
661
662         res = eap_server_sm_step(handler->server_ctx.eap);
663
664         if (handler->server_ctx.eap_if->eapReq) {
665                 DEBUG("==> Request");
666                 process = 1;
667                 handler->server_ctx.eap_if->eapReq = 0;
668         }
669
670         if (handler->server_ctx.eap_if->eapSuccess) {
671                 DEBUG("==> Success");
672                 process = 1;
673                 res = 0;
674
675                 if (handler->server_ctx.eap_if->eapKeyAvailable) {
676                         int length = handler->server_ctx.eap_if->eapKeyDataLen;
677                         VALUE_PAIR *vp;
678
679                         if (length > 64) {
680                                 length = 32;
681                         } else {
682                                 length /= 2;
683                                 /*
684                                  *      FIXME: Length is zero?
685                                  */
686                         }
687
688                         vp = radius_pairmake(request, &request->reply->vps,
689                                              "MS-MPPE-Recv-Key", "", T_OP_EQ);
690                         if (vp) {
691                                 memcpy(vp->vp_octets,
692                                        handler->server_ctx.eap_if->eapKeyData,
693                                        length);
694                                 vp->length = length;
695                         }
696                         
697                         vp = radius_pairmake(request, &request->reply->vps,
698                                              "MS-MPPE-Send-Key", "", T_OP_EQ);
699                         if (vp) {
700                                 memcpy(vp->vp_octets,
701                                        handler->server_ctx.eap_if->eapKeyData + length,
702                                        length);
703                                 vp->length = length;
704                         }
705                 }
706         }
707
708         if (handler->server_ctx.eap_if->eapFail) {
709                 DEBUG("==> Fail");
710                 process = 1;
711         }
712
713         if (process) {
714                 if (wpabuf_head(handler->server_ctx.eap_if->eapReqData)) {
715                         if (!eap_req2vp(handler)) return -1;
716                 } else {
717                         return -1;
718                 }
719         }
720
721         return res;
722 }
723
724
725 /*
726  * Handles multiple EAP-Message attrs
727  * ie concatenates all to get the complete EAP packet.
728  *
729  * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
730  *      refer fragmentation in rfc2869.
731  */
732 static int eap_vp2data(VALUE_PAIR *vps, void **data, int *data_len)
733 {
734         VALUE_PAIR *first, *vp;
735         unsigned char *ptr;
736         uint16_t len;
737         int total_len;
738
739         /*
740          *      Get only EAP-Message attribute list
741          */
742         first = pairfind(vps, PW_EAP_MESSAGE, 0);
743         if (first == NULL) {
744                 radlog(L_ERR, "rlm_eap2: EAP-Message not found");
745                 return -1;
746         }
747
748         /*
749          *      Sanity check the length before doing anything.
750          */
751         if (first->length < 4) {
752                 radlog(L_ERR, "rlm_eap2: EAP packet is too short.");
753                 return -1;
754         }
755
756         /*
757          *      Get the Actual length from the EAP packet
758          *      First EAP-Message contains the EAP packet header
759          */
760         memcpy(&len, first->vp_strvalue + 2, sizeof(len));
761         len = ntohs(len);
762
763         /*
764          *      Take out even more weird things.
765          */
766         if (len < 4) {
767                 radlog(L_ERR, "rlm_eap2: EAP packet has invalid length.");
768                 return -1;
769         }
770
771         /*
772          *      Sanity check the length, BEFORE malloc'ing memory.
773          */
774         total_len = 0;
775         for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0)) {
776                 total_len += vp->length;
777
778                 if (total_len > len) {
779                         radlog(L_ERR, "rlm_eap2: Malformed EAP packet.  Length in packet header does not match actual length");
780                         return -1;
781                 }
782         }
783
784         /*
785          *      If the length is SMALLER, die, too.
786          */
787         if (total_len < len) {
788                 radlog(L_ERR, "rlm_eap2: Malformed EAP packet.  Length in packet header does not match actual length");
789                 return -1;
790         }
791
792         /*
793          *      Now that we know the lengths are OK, allocate memory.
794          */
795         *data = malloc(len);
796         if (!*data) {
797                 radlog(L_ERR, "rlm_eap2: out of memory");
798                 return -1;
799         }
800         *data_len = len;
801
802         /*
803          *      Copy the data from EAP-Message's over to our EAP packet.
804          */
805         ptr = *data;
806
807         /* RADIUS ensures order of attrs, so just concatenate all */
808         for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0)) {
809                 memcpy(ptr, vp->vp_strvalue, vp->length);
810                 ptr += vp->length;
811         }
812
813         return 0;
814 }
815
816 /*
817  *      FIXME: Add an "authorize" section which sets Auth-Type = EAP2
818  *      FIXME: Also in "authorize", set User-Name if not already set.
819  */
820
821
822 /*
823  *      Do EAP.
824  */
825 static int eap_authenticate(void *instance, REQUEST *request)
826 {
827         rlm_eap_t       *inst;
828         EAP_HANDLER     *handler;
829         void            *data;
830         int             data_len;
831         int             rcode;
832         VALUE_PAIR      *vp;
833
834         inst = (rlm_eap_t *) instance;
835
836         vp = pairfind(request->packet->vps, PW_EAP_MESSAGE, 0);
837         if (!vp) {
838                 RDEBUG("No EAP-Message.  Not doing EAP.");
839                 return RLM_MODULE_FAIL;
840         }
841
842         /*
843          *      Get the eap packet  to start with
844          */
845         data = NULL;
846         data_len = 0;
847         if (eap_vp2data(request->packet->vps, &data, &data_len) < 0) {
848                 radlog(L_ERR, "rlm_eap2: Malformed EAP Message");
849                 return RLM_MODULE_FAIL;
850         }
851
852         vp = pairfind(request->packet->vps, PW_STATE, 0);
853         if (vp) {
854                 handler = eaplist_find(inst, request);
855                 if (!handler) {
856                         RDEBUG("No handler found");
857                         return RLM_MODULE_FAIL;
858                 }
859         } else {
860                 handler = malloc(sizeof(*handler));
861                 if (!handler) return RLM_MODULE_FAIL;
862
863                 memset(handler, 0, sizeof(*handler));
864
865                 handler->inst = inst;
866                 handler->eap_cb.get_eap_user = server_get_eap_user;
867                 handler->eap_cb.get_eap_req_id_text = server_get_eap_req_id_text;
868
869                 handler->eap_conf.eap_server = 1;
870                 handler->eap_conf.ssl_ctx = inst->tls_ctx;
871
872                 handler->server_ctx.eap = eap_server_sm_init(handler,
873                                                              &handler->eap_cb,
874                                                              &handler->eap_conf);
875                 if (handler->server_ctx.eap == NULL) {
876                         free(handler);
877                         return RLM_MODULE_FAIL;
878                 }
879                 
880                 handler->server_ctx.eap_if = eap_get_interface(handler->server_ctx.eap);
881                 
882                 /* Enable "port" and request EAP to start authentication. */
883                 handler->server_ctx.eap_if->portEnabled = TRUE;
884                 handler->server_ctx.eap_if->eapRestart = TRUE;
885         }
886
887         handler->request = request;
888         wpabuf_free(handler->server_ctx.eap_if->eapRespData);
889         handler->server_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
890         if (handler->server_ctx.eap_if->eapRespData) {
891                 handler->server_ctx.eap_if->eapResp = TRUE;
892         }
893         
894         if (eap_example_server_step(handler) < 0) {
895                 RDEBUG("Failed in EAP library");
896                 goto fail;
897         }
898
899         if (handler->server_ctx.eap_if->eapSuccess) {
900                 request->reply->code = PW_AUTHENTICATION_ACK;
901                 rcode = RLM_MODULE_OK;
902
903         } else if (handler->server_ctx.eap_if->eapFail) {
904         fail:
905                 request->reply->code = PW_AUTHENTICATION_REJECT;
906                 rcode = RLM_MODULE_REJECT;
907
908         } else {
909                 request->reply->code = PW_ACCESS_CHALLENGE;
910                 rcode = RLM_MODULE_HANDLED;
911         }
912
913         if (handler->server_ctx.eap_if->eapFail ||
914             handler->server_ctx.eap_if->eapSuccess) {
915                 RDEBUG2("Freeing handler");
916                 /* handler is not required any more, free it now */
917                 eap_handler_free(handler);
918                 handler = NULL;
919         } else {
920                 eaplist_add(inst, handler);
921         }
922
923         /*
924          *      If it's an Access-Accept, RFC 2869, Section 2.3.1
925          *      says that we MUST include a User-Name attribute in the
926          *      Access-Accept.
927          */
928         if ((request->reply->code == PW_AUTHENTICATION_ACK) &&
929             request->username) {
930                 /*
931                  *      Doesn't exist, add it in.
932                  */
933                 vp = pairfind(request->reply->vps, PW_USER_NAME, 0);
934                 if (!vp) {
935                         vp = pairmake("User-Name", request->username->vp_strvalue,
936                                       T_OP_EQ);
937                         rad_assert(vp != NULL);
938                         pairadd(&(request->reply->vps), vp);
939                 }
940
941                 /*
942                  *      Cisco AP1230 has a bug and needs a zero
943                  *      terminated string in Access-Accept.
944                  */
945                 if ((inst->cisco_accounting_username_bug) &&
946                     (vp->length < (int) sizeof(vp->vp_strvalue))) {
947                         vp->vp_strvalue[vp->length] = '\0';
948                         vp->length++;
949                 }
950         }
951
952         vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0);
953         if (!vp) {
954                 vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
955                 memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN);
956                 vp->length = AUTH_VECTOR_LEN;
957                 pairadd(&(request->reply->vps), vp);
958         }
959         return rcode;
960 }
961
962
963 /*
964  *      The module name should be the only globally exported symbol.
965  *      That is, everything else should be 'static'.
966  */
967 module_t rlm_eap2 = {
968         RLM_MODULE_INIT,
969         "eap2",
970         RLM_TYPE_CHECK_CONFIG_SAFE,     /* type */
971         eap_instantiate,                /* instantiation */
972         eap_detach,                     /* detach */
973         {
974                 eap_authenticate,       /* authentication */
975                 NULL,                   /* authorization */
976                 NULL,                   /* preaccounting */
977                 NULL,                   /* accounting */
978                 NULL,                   /* checksimul */
979                 NULL,                   /* pre-proxy */
980                 NULL,                   /* post-proxy */
981                 NULL                    /* post-auth */
982         },
983 };