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