free(vp) on decoding error.
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_ttls / ttls.c
1 /*
2  * rlm_eap_ttls.c  contains the interfaces that are called from eap
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 2003 Alan DeKok <aland@freeradius.org>
21  */
22 #include "eap_ttls.h"
23
24 /*
25  *    0                   1                   2                   3
26  *    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
27  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28  *   |                           AVP Code                            |
29  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30  *   |V M r r r r r r|                  AVP Length                   |
31  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32  *   |                        Vendor-ID (opt)                        |
33  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34  *   |    Data ...
35  *   +-+-+-+-+-+-+-+-+
36  */
37
38 /*
39  *      Verify that the diameter packet is valid.
40  */
41 static int diameter_verify(const uint8_t *data, unsigned int data_len)
42 {
43         uint32_t attr;
44         uint32_t length;
45         unsigned int offset;
46         unsigned int data_left = data_len;
47
48         while (data_left > 0) {
49                 if (data_len < 12) {
50                         DEBUG2("  rlm_eap_ttls:  Diameter attribute is too small to contain a Diameter header");
51                         return 0;
52                 }
53
54                 rad_assert(data_left <= data_len);
55                 memcpy(&attr, data, sizeof(attr));
56                 data += 4;
57                 attr = ntohl(attr);
58                 if (attr > 255) {
59                         DEBUG2("  rlm_eap_ttls:  Non-RADIUS attribute in tunneled authentication is not supported");
60                         return 0;
61                 }
62
63                 memcpy(&length, data , sizeof(length));
64                 data += 4;
65                 length = ntohl(length);
66
67                 /*
68                  *      A "vendor" flag, with a vendor ID of zero,
69                  *      is equivalent to no vendor.  This is stupid.
70                  */
71                 offset = 8;
72                 if ((length & (1 << 31)) != 0) {
73                         int attribute;
74                         uint32_t vendor;
75                         DICT_ATTR *da;
76
77                         memcpy(&vendor, data, sizeof(vendor));
78                         vendor = ntohl(vendor);
79
80                         if (vendor > 65535) {
81                                 DEBUG2("  rlm_eap_ttls: Vendor codes larger than 65535 are not supported");
82                                 return 0;
83                         }
84
85                         attribute = (vendor << 16) | attr;
86
87                         da = dict_attrbyvalue(attribute);
88
89                         /*
90                          *      SHOULD check ((length & (1 << 30)) != 0)
91                          *      for the mandatory bit.
92                          */
93                         if (!da) {
94                                 DEBUG2("  rlm_eap_ttls: Fatal! Vendor %u, Attribute %u was not found in our dictionary. ",
95                                        vendor, attr);
96                                 return 0;
97                         }
98
99                         data += 4; /* skip the vendor field */
100                         offset += 4; /* offset to value field */
101                 }
102
103                 /*
104                  *      Ignore the M bit.  We support all RADIUS attributes...
105                  */
106
107                 /*
108                  *      Get the length.  If it's too big, die.
109                  */
110                 length &= 0x00ffffff;
111
112                 /*
113                  *      Too short or too long is bad.
114                  *
115                  *      FIXME: EAP-Message
116                  */
117                 if (length < offset) {
118                         DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is too short (%d)to contain anything useful.", attr, length);
119                         return 0;
120                 }
121
122                 if (length > (MAX_STRING_LEN + 8)) {
123                         DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is too long (%d) to pack into a RADIUS attribute.", attr, length);
124                         return 0;
125                 }
126                     
127                 if (length > data_left) {
128                         DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is longer than room left in the packet (%d > %d).", attr, length, data_left);
129                         return 0;
130                 }
131
132                 /*
133                  *      Check for broken implementations, which don't
134                  *      pad the AVP to a 4-octet boundary.
135                  */
136                 if (data_left == length) break;
137
138                 /*
139                  *      The length does NOT include the padding, so
140                  *      we've got to account for it here by rounding up
141                  *      to the nearest 4-byte boundary.
142                  */
143                 length += 0x03;
144                 length &= ~0x03;
145
146                 /*
147                  *      If the rest of the diameter packet is larger than
148                  *      this attribute, continue.
149                  *
150                  *      Otherwise, if the attribute over-flows the end
151                  *      of the packet, die.
152                  */
153                 if (data_left < length) {
154                         DEBUG2("  rlm_eap_ttls: ERROR! Diameter attribute overflows packet!");
155                         return 0;
156                 }
157         
158                 /*
159                  *      Check again for equality, now that we're padded
160                  *      length to a multiple of 4 octets.
161                  */
162                 if (data_left == length) break;
163
164                 /*
165                  *      data_left > length, continue.
166                  */
167                 data_left -= length;
168                 data += length - offset;
169         }
170
171         /*
172          *      We got this far.  It looks OK.
173          */
174         return 1;
175 }
176
177
178 /*
179  *      Convert diameter attributes to our VALUE_PAIR's
180  */
181 static VALUE_PAIR *diameter2vp(SSL *ssl,
182                                const uint8_t *data, unsigned int data_len)
183 {
184         uint32_t        attr;
185         uint32_t        length;
186         unsigned int    offset;
187         int             size;
188         unsigned int    data_left = data_len;
189         VALUE_PAIR      *first = NULL;
190         VALUE_PAIR      **last = &first;
191         VALUE_PAIR      *vp;
192
193         while (data_left > 0) {
194                 rad_assert(data_left <= data_len);
195                 memcpy(&attr, data, sizeof(attr));
196                 data += 4;
197                 attr = ntohl(attr);
198
199                 memcpy(&length, data, sizeof(length));
200                 data += 4;
201                 length = ntohl(length);
202
203                 /*
204                  *      Ignore the M bit.  We support all RADIUS attributes...
205                  */
206
207                 /*
208                  *      A "vendor" flag, with a vendor ID of zero,
209                  *      is equivalent to no vendor.  This is stupid.
210                  */
211                 offset = 8;
212                 if ((length & (1 << 31)) != 0) {
213                         uint32_t vendor;
214
215                         memcpy(&vendor, data, sizeof(vendor));
216                         vendor = ntohl(vendor);
217
218                         attr |= (vendor << 16);
219
220                         data += 4; /* skip the vendor field, it's zero */
221                         offset += 4; /* offset to value field */
222                 }
223
224                 /*
225                  *      Get the length.
226                  */
227                 length &= 0x00ffffff;
228
229                 /*
230                  *      diameter code + length, and it must fit in
231                  *      a VALUE_PAIR.
232                  */
233                 rad_assert(length <= (offset + MAX_STRING_LEN));
234
235                 /*
236                  *      Get the size of the value portion of the
237                  *      attribute.
238                  */
239                 size = length - offset;
240
241                 /*
242                  *      Create it.
243                  */
244                 vp = paircreate(attr, PW_TYPE_OCTETS);
245                 if (!vp) {
246                         DEBUG2("  rlm_eap_ttls: Failure in creating VP");
247                         pairfree(&first);
248                         return NULL;
249                 }
250
251                 /*
252                  *      If it's a type from our dictionary, then
253                  *      we need to put the data in a relevant place.
254                  */
255                 switch (vp->type) {
256                 case PW_TYPE_INTEGER:
257                 case PW_TYPE_DATE:
258                         if (size != vp->length) {
259                                 DEBUG2("  rlm_eap_ttls: Invalid length attribute %d",
260                                        attr);
261                                 pairfree(&first);
262                                 pairfree(&vp);
263                                 return NULL;
264                         }
265                         memcpy(&vp->lvalue, data, vp->length);
266                         
267                         /*
268                          *      Stored in host byte order: change it.
269                          */
270                         vp->lvalue = ntohl(vp->lvalue);
271                         break;
272                         
273                 case PW_TYPE_IPADDR:
274                         if (size != vp->length) {
275                                 DEBUG2("  rlm_eap_ttls: Invalid length attribute %d",
276                                        attr);
277                                 pairfree(&first);
278                                 pairfree(&vp);
279                                 return NULL;
280                         }
281                   memcpy(&vp->lvalue, data, vp->length);
282                   
283                   /*
284                    *    Stored in network byte order: don't change it.
285                    */
286                   break;
287
288                   /*
289                    *    String, octet, etc.  Copy the data from the
290                    *    value field over verbatim.
291                    *
292                    *    FIXME: Ipv6 attributes ?
293                    *
294                    */
295                 default:
296                         vp->length = size;
297                         memcpy(vp->strvalue, data, vp->length);
298                         break;
299                 }
300
301                 /*
302                  *      User-Password is NUL padded to a multiple
303                  *      of 16 bytes.  Let's chop it to something
304                  *      more reasonable.
305                  *
306                  *      NOTE: This means that the User-Password
307                  *      attribute CANNOT EVER have embedded zeros in it!
308                  */
309                 switch (vp->attribute) {
310                 case PW_USER_PASSWORD:
311                         rad_assert(vp->length <= 128); /* RFC requirements */
312
313                         /*
314                          *      If the password is exactly 16 octets,
315                          *      it won't be zero-terminated.
316                          */
317                         vp->strvalue[vp->length] = '\0';
318                         vp->length = strlen(vp->strvalue);
319                         break;
320
321                         /*
322                          *      Ensure that the client is using the
323                          *      correct challenge.  This weirdness is
324                          *      to protect against against replay
325                          *      attacks, where anyone observing the
326                          *      CHAP exchange could pose as that user,
327                          *      by simply choosing to use the same
328                          *      challenge.
329                          *
330                          *      By using a challenge based on
331                          *      information from the current session,
332                          *      we can guarantee that the client is
333                          *      not *choosing* a challenge.
334                          *
335                          *      We're a little forgiving in that we
336                          *      have loose checks on the length, and
337                          *      we do NOT check the Id (first octet of
338                          *      the response to the challenge)
339                          *
340                          *      But if the client gets the challenge correct,
341                          *      we're not too worried about the Id.
342                          */
343                 case PW_CHAP_CHALLENGE:
344                 case PW_MSCHAP_CHALLENGE:
345                         if ((vp->length < 8) ||
346                             (vp->length > 16)) {
347                                 DEBUG2("  TTLS: Tunneled challenge has invalid length");
348                                 pairfree(&first);
349                                 pairfree(&vp);
350                                 return NULL;
351
352                         } else {
353                                 int i;
354                                 uint8_t challenge[16];
355
356                                 eapttls_gen_challenge(ssl, challenge,
357                                                       sizeof(challenge));
358
359                                 for (i = 0; i < vp->length; i++) {
360                                         if (challenge[i] != vp->strvalue[i]) {
361                                                 DEBUG2("  TTLS: Tunneled challenge is incorrect");
362                                                 pairfree(&first);
363                                                 pairfree(&vp);
364                                                 return NULL;
365                                         }
366                                 }
367                         }
368                         break;
369
370                 default:
371                         break;
372                 } /* switch over checking/re-writing of attributes. */
373
374                 /*
375                  *      Update the list.
376                  */
377                 *last = vp;
378                 last = &(vp->next);
379
380                 /*
381                  *      Catch non-aligned attributes.
382                  */
383                 if (data_left == length) break;
384
385                 /*
386                  *      The length does NOT include the padding, so
387                  *      we've got to account for it here by rounding up
388                  *      to the nearest 4-byte boundary.
389                  */
390                 length += 0x03;
391                 length &= ~0x03;
392
393                 rad_assert(data_left >= length);
394                 data_left -= length;
395                 data += length - offset; /* already updated */
396         }
397
398         /*
399          *      We got this far.  It looks OK.
400          */
401         return first;
402 }
403
404 /*
405  *      Convert VALUE_PAIR's to diameter attributes, and write them
406  *      to an SSL session.
407  *
408  *      The ONLY VALUE_PAIR's which may be passed to this function
409  *      are ones which can go inside of a RADIUS (i.e. diameter)
410  *      packet.  So no server-configuration attributes, or the like.
411  */
412 static int vp2diameter(tls_session_t *tls_session, VALUE_PAIR *first)
413 {
414         /*
415          *      RADIUS packets are no more than 4k in size, so if
416          *      we've got more than 4k of data to write, it's very
417          *      bad.
418          */
419         uint8_t         buffer[4096];
420         uint8_t         *p;
421         uint32_t        attr;
422         uint32_t        length;
423         uint32_t        vendor;
424         size_t          total;
425         VALUE_PAIR      *vp;
426
427         p = buffer;
428         total = 0;
429
430         for (vp = first; vp != NULL; vp = vp->next) {
431                 /*
432                  *      Too much data: die.
433                  */
434                 if ((total + vp->length + 12) >= sizeof(buffer)) {
435                         DEBUG2("  TTLS output buffer is full!");
436                         return 0;
437                 }
438
439                 /*
440                  *      Hmm... we don't group multiple EAP-Messages
441                  *      together.  Maybe we should...
442                  */
443
444                 /*
445                  *      Length is no more than 253, due to RADIUS
446                  *      issues.
447                  */
448                 length = vp->length;
449                 vendor = (vp->attribute >> 16) & 0xffff;
450                 if (vendor != 0) {
451                         attr = vp->attribute & 0xffff;
452                         length |= (1 << 31);
453                 } else {
454                         attr = vp->attribute;
455                 }
456
457                 /*
458                  *      Hmm... set the M bit for all attributes?
459                  */
460                 length |= (1 << 30);
461
462                 attr = ntohl(attr);
463
464                 memcpy(p, &attr, sizeof(attr));
465                 p += 4;
466                 total += 4;
467
468                 length += 8;    /* includes 8 bytes of attr & length */
469
470                 if (vendor != 0) {
471                         length += 4; /* include 4 bytes of vendor */
472
473                         length = ntohl(length);
474                         memcpy(p, &length, sizeof(length));
475                         p += 4;
476                         total += 4;
477
478                         vendor = ntohl(vendor);
479                         memcpy(p, &vendor, sizeof(vendor));
480                         p += 4;
481                         total += 4;
482                 } else {
483                         length = ntohl(length);
484                         memcpy(p, &length, sizeof(length));
485                         p += 4;
486                         total += 4;
487                 }
488
489                 switch (vp->type) {
490                 case PW_TYPE_INTEGER:
491                 case PW_TYPE_DATE:
492                         attr = ntohl(vp->lvalue); /* stored in host order */
493                         memcpy(p, &attr, sizeof(attr));
494                         length = 4;
495                         break;
496
497                 case PW_TYPE_IPADDR:
498                         attr = vp->lvalue; /* stored in network order */
499                         memcpy(p, &attr, sizeof(attr));
500                         length = 4;
501                         break;
502
503                 case PW_TYPE_STRING:
504                 case PW_TYPE_OCTETS:
505                 default:
506                         memcpy(p, vp->strvalue, vp->length);
507                         length = vp->length;
508                         break;
509                 }
510
511                 /*
512                  *      Skip to the end of the data.
513                  */
514                 p += length;
515                 total += length;
516
517                 /*
518                  *      Align the data to a multiple of 4 bytes.
519                  */
520                 if ((total & 0x03) != 0) {
521                         unsigned int i;
522
523                         length = 4 - (total & 0x03);
524                         for (i = 0; i < length; i++) {
525                                 *p = '\0';
526                                 p++;
527                                 total++;
528                         }
529                 }
530         } /* loop over the VP's to write. */
531
532         /*
533          *      Write the data in the buffer to the SSL session.
534          */
535         if (total > 0) {
536 #ifndef NDEBUG
537                 unsigned int i;
538
539                 if (debug_flag > 2) {
540                         for (i = 0; i < total; i++) {
541                                 if ((i & 0x0f) == 0) printf("  TTLS tunnel data out %04x: ", i);
542
543                                 printf("%02x ", buffer[i]);
544
545                                 if ((i & 0x0f) == 0x0f) printf("\n");
546                         }
547                         if ((total & 0x0f) != 0) printf("\n");
548                 }
549 #endif
550
551                 (tls_session->record_plus)(&tls_session->clean_in, buffer, total);
552
553                 /*
554                  *      FIXME: Check the return code.
555                  */
556                 tls_handshake_send(tls_session);
557         }
558
559         /*
560          *      Everything's OK.
561          */
562         return 1;
563 }
564
565 /*
566  *      Use a reply packet to determine what to do.
567  */
568 static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
569                          REQUEST *request, RADIUS_PACKET *reply)
570 {
571         int rcode = RLM_MODULE_REJECT;
572         VALUE_PAIR *vp;
573         ttls_tunnel_t *t = tls_session->opaque;
574
575         handler = handler;      /* -Wunused */
576
577         /*
578          *      If the response packet was Access-Accept, then
579          *      we're OK.  If not, die horribly.
580          *
581          *      FIXME: Take MS-CHAP2-Success attribute, and
582          *      tunnel it back to the client, to authenticate
583          *      ourselves to the client.
584          *
585          *      FIXME: If we have an Access-Challenge, then
586          *      the Reply-Message is tunneled back to the client.
587          *
588          *      FIXME: If we have an EAP-Message, then that message
589          *      must be tunneled back to the client.
590          *
591          *      FIXME: If we have an Access-Challenge with a State
592          *      attribute, then do we tunnel that to the client, or
593          *      keep track of it ourselves?
594          *
595          *      FIXME: EAP-Messages can only start with 'identity',
596          *      NOT 'eap start', so we should check for that....
597          */
598         switch (reply->code) {
599         case PW_AUTHENTICATION_ACK:
600                 DEBUG2("  TTLS: Got tunneled Access-Accept");
601
602                 rcode = RLM_MODULE_OK;
603
604                 /*
605                  *      MS-CHAP2-Success means that we do NOT return
606                  *      an Access-Accept, but instead tunnel that
607                  *      attribute to the client, and keep going with
608                  *      the TTLS session.  Once the client accepts
609                  *      our identity, it will respond with an empty
610                  *      packet, and we will send EAP-Success.
611                  */
612                 vp = NULL;
613                 pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS);
614                 if (vp) {
615                         DEBUG2("  TTLS: Got MS-CHAP2-Success, tunneling it to the client in a challenge.");
616                         rcode = RLM_MODULE_HANDLED;
617                         t->authenticated = TRUE;
618                         
619                         /*
620                          *      Delete MPPE keys & encryption policy.  We don't
621                          *      want these here.
622                          */
623                         pairdelete(&reply->vps, ((311 << 16) | 7));
624                         pairdelete(&reply->vps, ((311 << 16) | 8));
625                         pairdelete(&reply->vps, ((311 << 16) | 16));
626                         pairdelete(&reply->vps, ((311 << 16) | 17));
627                         
628                         /*
629                          *      Use the tunneled reply, but not now.
630                          */
631                         if (t->use_tunneled_reply) {
632                                 t->reply = reply->vps;
633                                 reply->vps = NULL;
634                         }
635
636                 } else { /* no MS-CHAP2-Success */
637                         /*
638                          *      Can only have EAP-Message if there's
639                          *      no MS-CHAP2-Success.  (FIXME: EAP-MSCHAP?)
640                          *
641                          *      We also do NOT tunnel the EAP-Success
642                          *      attribute back to the client, as the client
643                          *      can figure it out, from the non-tunneled
644                          *      EAP-Success packet.
645                          */
646                         pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
647                         pairfree(&vp);
648                 }
649
650                 /*
651                  *      Handle the ACK, by tunneling any necessary reply
652                  *      VP's back to the client.
653                  */
654                 if (vp) {
655                         vp2diameter(tls_session, vp);
656                         pairfree(&vp);
657                 }
658
659                 /*
660                  *      If we've been told to use the attributes from
661                  *      the reply, then do so.
662                  *
663                  *      WARNING: This may leak information about the
664                  *      tunneled user!
665                  */
666                 if (t->use_tunneled_reply) {
667                         pairdelete(&reply->vps, PW_PROXY_STATE);
668                         pairadd(&request->reply->vps, reply->vps);
669                         reply->vps = NULL;
670                 }
671                 break;
672
673
674         case PW_AUTHENTICATION_REJECT:
675                 DEBUG2("  TTLS: Got tunneled Access-Reject");
676                 rcode = RLM_MODULE_REJECT;
677                 break;
678
679                 /*
680                  *      Handle Access-Challenge, but only if we
681                  *      send tunneled reply data.  This is because
682                  *      an Access-Challenge means that we MUST tunnel
683                  *      a Reply-Message to the client.
684                  */
685         case PW_ACCESS_CHALLENGE:
686                 DEBUG2("  TTLS: Got tunneled Access-Challenge");
687
688                 /*
689                  *      Keep the State attribute, if necessary.
690                  *
691                  *      Get rid of the old State, too.
692                  */
693                 pairfree(&t->state);
694                 pairmove2(&t->state, &reply->vps, PW_STATE);
695
696                 /*
697                  *      We should really be a bit smarter about this,
698                  *      and move over only those attributes which
699                  *      are relevant to the authentication request,
700                  *      but that's a lot more work, and this "dumb"
701                  *      method works in 99.9% of the situations.
702                  */
703                 vp = NULL;
704                 pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
705
706                 /*
707                  *      There MUST be a Reply-Message in the challenge,
708                  *      which we tunnel back to the client.
709                  *
710                  *      If there isn't one in the reply VP's, then
711                  *      we MUST create one, with an empty string as
712                  *      it's value.
713                  */
714                 pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE);
715
716                 /*
717                  *      Handle the ACK, by tunneling any necessary reply
718                  *      VP's back to the client.
719                  */
720                 if (vp) {
721                         vp2diameter(tls_session, vp);
722                         pairfree(&vp);
723                 }
724                 rcode = RLM_MODULE_HANDLED;
725                 break;
726
727         default:
728                 DEBUG2("  TTLS: Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
729                 rcode = RLM_MODULE_INVALID;
730                 break;
731         }
732
733         return rcode;
734 }
735
736
737 /*
738  *      Do post-proxy processing,
739  */
740 static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
741 {
742         int rcode;
743         tls_session_t *tls_session = (tls_session_t *) data;
744         REQUEST *fake;
745
746         DEBUG2("  TTLS: Passing reply from proxy back into the tunnel.");
747
748         /*
749          *      If there was a fake request associated with the proxied
750          *      request, do more processing of it.
751          */
752         fake = (REQUEST *) request_data_get(handler->request,
753                                             handler->request->proxy,
754                                             REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
755         
756         /*
757          *      Do the callback, if it exists, and if it was a success.
758          */
759         if (fake && (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {
760                 VALUE_PAIR *vp;
761                 REQUEST *request = handler->request;
762
763                 /*
764                  *      Terrible hacks.
765                  */
766                 rad_assert(fake->packet == NULL);
767                 fake->packet = request->proxy;
768                 request->proxy = NULL;
769
770                 rad_assert(fake->reply == NULL);
771                 fake->reply = request->proxy_reply;
772                 request->proxy_reply = NULL;
773
774                 /*
775                  *      Perform a post-auth stage for the tunneled
776                  *      session.
777                  */
778                 fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
779                 rcode = rad_postauth(fake);
780                 DEBUG2("  POST-AUTH %d", rcode);
781
782 #ifndef NDEBUG
783                 if (debug_flag > 0) {
784                         printf("  TTLS: Final reply from tunneled session code %d\n",
785                                fake->reply->code);
786                         
787                         for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {
788                                 putchar('\t');vp_print(stdout, vp);putchar('\n');
789                         }
790                 }
791 #endif
792
793                 /*
794                  *      Terrible hacks.
795                  */
796                 request->proxy = fake->packet;
797                 fake->packet = NULL;
798                 request->proxy_reply = fake->reply;
799                 fake->reply = NULL;
800
801                 /*
802                  *      And we're done with this request.
803                  */
804
805                 switch (rcode) {
806                 case RLM_MODULE_FAIL:
807                         request_free(&fake);
808                         eaptls_fail(handler->eap_ds, 0);
809                         return 0;
810                         break;
811                         
812                 default:  /* Don't Do Anything */
813                         DEBUG2(" TTLS: Got reply %d",
814                                request->proxy_reply->code);
815                         break;
816                 }       
817         }
818         request_free(&fake);    /* robust if fake == NULL */
819
820         /*
821          *      Process the reply from the home server.
822          */
823         rcode = process_reply(handler, tls_session, handler->request,
824                               handler->request->proxy_reply);
825
826         /*
827          *      The proxy code uses the reply from the home server as
828          *      the basis for the reply to the NAS.  We don't want that,
829          *      so we toss it, after we've had our way with it.
830          */
831         pairfree(&handler->request->proxy_reply->vps);
832
833         switch (rcode) {
834         case RLM_MODULE_REJECT:
835                 DEBUG2("  TTLS: Reply was rejected");
836                 break;
837
838         case RLM_MODULE_HANDLED:
839                 DEBUG2("  TTLS: Reply was handled");
840                 eaptls_request(handler->eap_ds, tls_session);
841                 return 1;
842
843         case RLM_MODULE_OK:
844                 DEBUG2("  TTLS: Reply was OK");
845                 eaptls_success(handler->eap_ds, 0);
846                 eaptls_gen_mppe_keys(&handler->request->reply->vps,
847                                      tls_session->ssl,
848                                      "ttls keying material");
849                 return 1;
850
851         default:
852                 DEBUG2("  TTLS: Reply was unknown.");
853                 break;
854         }
855
856         eaptls_fail(handler->eap_ds, 0);
857         return 0;
858 }
859
860
861 /*
862  *      Free a request.
863  */
864 static void my_request_free(void *data)
865 {
866         REQUEST *request = (REQUEST *)data;
867
868         request_free(&request);
869 }
870
871
872 /*
873  *      Process the "diameter" contents of the tunneled data.
874  */
875 int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
876 {
877         int err;
878         int rcode = PW_AUTHENTICATION_REJECT;
879         REQUEST *fake;
880         VALUE_PAIR *vp;
881         ttls_tunnel_t *t;
882         const uint8_t *data;
883         unsigned int data_len;
884         char buffer[1024];
885         REQUEST *request = handler->request;
886
887         /*
888          *      Grab the dirty data, and copy it to our buffer.
889          *
890          *      I *really* don't like these 'record_t' things...
891          */
892         data_len = (tls_session->record_minus)(&tls_session->dirty_in, buffer, sizeof(buffer));
893         data = buffer;
894
895         /*
896          *      Write the data from the dirty buffer (i.e. packet
897          *      data) into the buffer which we will give to SSL for
898          *      decoding.
899          *
900          *      Some of this code COULD technically go into the TLS
901          *      module, in eaptls_process(), where it returns EAPTLS_OK.
902          *
903          *      Similarly, the writing of data to the SSL context could
904          *      go there, too...
905          */
906         BIO_write(tls_session->into_ssl, buffer, data_len);
907         (tls_session->record_init)(&tls_session->clean_out);
908
909         /*
910          *      Read (and decrypt) the tunneled data from the SSL session,
911          *      and put it into the decrypted data buffer.
912          */
913         err = SSL_read(tls_session->ssl, tls_session->clean_out.data,
914                        sizeof(tls_session->clean_out.data));
915         if (err < 0) {
916                 /*
917                  *      FIXME: Call SSL_get_error() to see what went
918                  *      wrong.
919                  */
920                 radlog(L_INFO, "rlm_eap_ttls: SSL_read Error");
921                 return PW_AUTHENTICATION_REJECT;
922         }
923
924         t = (ttls_tunnel_t *) tls_session->opaque;
925
926         /*
927          *      If there's no data, maybe this is an ACK to an
928          *      MS-CHAP2-Success.
929          */
930         if (err == 0) {
931                 if (t->authenticated) {
932                         DEBUG2("  TTLS: Got ACK, and the user was already authenticated.");
933                         return PW_AUTHENTICATION_ACK;
934                 } /* else no session, no data, die. */
935
936                 /*
937                  *      FIXME: Call SSL_get_error() to see what went
938                  *      wrong.
939                  */
940                 radlog(L_INFO, "rlm_eap_ttls: SSL_read Error");
941                 return PW_AUTHENTICATION_REJECT;
942         }
943
944         data_len = tls_session->clean_out.used = err;
945         data = tls_session->clean_out.data;
946
947 #ifndef NDEBUG
948         if (debug_flag > 2) {
949                 unsigned int i;
950
951                 for (i = 0; i < data_len; i++) {
952                         if ((i & 0x0f) == 0) printf("  TTLS tunnel data in %04x: ", i);
953
954                         printf("%02x ", data[i]);
955
956                         if ((i & 0x0f) == 0x0f) printf("\n");
957                 }
958                 if ((data_len & 0x0f) != 0) printf("\n");
959         }
960 #endif
961
962         if (!diameter_verify(data, data_len)) {
963                 return PW_AUTHENTICATION_REJECT;
964         }
965
966         /*
967          *      Allocate a fake REQUEST structe.
968          */
969         fake = request_alloc_fake(request);
970
971         rad_assert(fake->packet->vps == NULL);
972
973         /*
974          *      Add the tunneled attributes to the fake request.
975          */
976         fake->packet->vps = diameter2vp(tls_session->ssl, data, data_len);
977         if (!fake->packet->vps) {
978                 return PW_AUTHENTICATION_REJECT;
979         }
980
981         /*
982          *      Tell the request that it's a fake one.
983          */
984         vp = pairmake("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
985         if (vp) {
986                 pairadd(&fake->packet->vps, vp);
987         }
988
989 #ifndef NDEBUG
990         if (debug_flag > 0) {
991                 printf("  TTLS: Got tunneled request\n");
992                 
993                 for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
994                         putchar('\t');vp_print(stdout, vp);putchar('\n');
995                 }
996         }
997 #endif
998
999         /*
1000          *      Update other items in the REQUEST data structure.
1001          */
1002         fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
1003         fake->password = pairfind(fake->packet->vps, PW_PASSWORD);
1004
1005         /*
1006          *      No User-Name, try to create one from stored data.
1007          */
1008         if (!fake->username) {
1009                 /*
1010                  *      No User-Name in the stored data, look for
1011                  *      an EAP-Identity, and pull it out of there.
1012                  */
1013                 if (!t->username) {
1014                         vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE);
1015                         if (vp &&
1016                             (vp->length >= EAP_HEADER_LEN + 2) &&
1017                             (vp->strvalue[0] == PW_EAP_RESPONSE) &&
1018                             (vp->strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
1019                             (vp->strvalue[EAP_HEADER_LEN + 1] != 0)) {
1020                                 /*
1021                                  *      Create & remember a User-Name
1022                                  */
1023                                 t->username = pairmake("User-Name", "", T_OP_EQ);
1024                                 rad_assert(t->username != NULL);
1025
1026                                 memcpy(t->username->strvalue, vp->strvalue + 5,
1027                                        vp->length - 5);
1028                                 t->username->length = vp->length - 5;
1029                                 t->username->strvalue[t->username->length] = 0;
1030
1031                                 DEBUG2("  TTLS: Got tunneled identity of %s",
1032                                        t->username->strvalue);
1033
1034                                 /*
1035                                  *      If there's a default EAP type,
1036                                  *      set it here.
1037                                  */
1038                                 if (t->default_eap_type != 0) {
1039                                         DEBUG2("  TTLS: Setting default EAP type for tunneled EAP session.");
1040                                         vp = paircreate(PW_EAP_TYPE,
1041                                                         PW_TYPE_INTEGER);
1042                                         rad_assert(vp != NULL);
1043                                         vp->lvalue = t->default_eap_type;
1044                                         pairadd(&fake->config_items, vp);
1045                                 }
1046
1047                         } else {
1048                                 /*
1049                                  *      Don't reject the request outright,
1050                                  *      as it's permitted to do EAP without
1051                                  *      user-name.
1052                                  */
1053                                 DEBUG2("  rlm_eap_ttls: WARNING! No EAP-Identity found to start EAP conversation.");
1054                         }
1055                 } /* else there WAS a t->username */
1056
1057                 if (t->username) {
1058                         vp = paircopy(t->username);
1059                         pairadd(&fake->packet->vps, vp);
1060                         fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
1061                 }
1062         } /* else the request ALREADY had a User-Name */
1063
1064         /*
1065          *      Add the State attribute, too, if it exists.
1066          */
1067         if (t->state) {
1068                 DEBUG2("  TTLS: Adding old state with %02x %02x",
1069                        t->state->strvalue[0], t->state->strvalue[1]);
1070                 vp = paircopy(t->state);
1071                 if (vp) pairadd(&fake->packet->vps, vp);
1072         }
1073
1074         /*
1075          *      If this is set, we copy SOME of the request attributes
1076          *      from outside of the tunnel to inside of the tunnel.
1077          *
1078          *      We copy ONLY those attributes which do NOT already
1079          *      exist in the tunneled request.
1080          */
1081         if (t->copy_request_to_tunnel) {
1082                 VALUE_PAIR *copy;
1083
1084                 for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
1085                         /*
1086                          *      The attribute is a server-side thingy,
1087                          *      don't copy it.
1088                          */
1089                         if ((vp->attribute > 255) &&
1090                             (((vp->attribute >> 16) & 0xffff) == 0)) {
1091                                 continue;
1092                         }
1093
1094                         /*
1095                          *      The outside attribute is already in the
1096                          *      tunnel, don't copy it.
1097                          *
1098                          *      This works for BOTH attributes which
1099                          *      are originally in the tunneled request,
1100                          *      AND attributes which are copied there
1101                          *      from below.
1102                          */
1103                         if (pairfind(fake->packet->vps, vp->attribute)) {
1104                                 continue;
1105                         }
1106
1107                         /*
1108                          *      Some attributes are handled specially.
1109                          */
1110                         switch (vp->attribute) {
1111                                 /*
1112                                  *      NEVER copy Message-Authenticator,
1113                                  *      EAP-Message, or State.  They're
1114                                  *      only for outside of the tunnel.
1115                                  */
1116                         case PW_USER_NAME:
1117                         case PW_USER_PASSWORD:
1118                         case PW_CHAP_PASSWORD:
1119                         case PW_CHAP_CHALLENGE:
1120                         case PW_PROXY_STATE:
1121                         case PW_MESSAGE_AUTHENTICATOR:
1122                         case PW_EAP_MESSAGE:
1123                         case PW_STATE:
1124                                 continue;
1125                                 break;
1126
1127                                 /*
1128                                  *      By default, copy it over.
1129                                  */
1130                         default:
1131                                 break;
1132                         }
1133
1134                         /*
1135                          *      Don't copy from the head, we've already
1136                          *      checked it.
1137                          */
1138                         copy = paircopy2(vp, vp->attribute);
1139                         pairadd(&fake->packet->vps, copy);
1140                 }
1141         }
1142
1143 #ifndef NDEBUG
1144         if (debug_flag > 0) {
1145           printf("  TTLS: Sending tunneled request\n");
1146
1147           for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
1148             putchar('\t');vp_print(stdout, vp);putchar('\n');
1149           }
1150         }
1151 #endif
1152
1153         /*
1154          *      Call authentication recursively, which will
1155          *      do PAP, CHAP, MS-CHAP, etc.
1156          */
1157         rad_authenticate(fake);
1158
1159         /*
1160          *      Note that we don't do *anything* with the reply
1161          *      attributes.
1162          */
1163 #ifndef NDEBUG
1164         if (debug_flag > 0) {
1165           printf("  TTLS: Got tunneled reply RADIUS code %d\n",
1166                  fake->reply->code);
1167
1168           for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {
1169             putchar('\t');vp_print(stdout, vp);putchar('\n');
1170           }
1171         }
1172 #endif
1173
1174         /*
1175          *      Decide what to do with the reply.
1176          */
1177         switch (fake->reply->code) {
1178         case 0:                 /* No reply code, must be proxied... */
1179                 vp = pairfind(fake->config_items, PW_PROXY_TO_REALM);
1180                 if (vp) {
1181                         eap_tunnel_data_t *tunnel;
1182                         DEBUG2("  TTLS: Tunneled authentication will be proxied to %s", vp->strvalue);
1183
1184                         /*
1185                          *      Tell the original request that it's going
1186                          *      to be proxied.
1187                          */
1188                         pairmove2(&(request->config_items),
1189                                   &(fake->config_items),
1190                                   PW_PROXY_TO_REALM);
1191
1192                         /*
1193                          *      Seed the proxy packet with the
1194                          *      tunneled request.
1195                          */
1196                         rad_assert(request->proxy == NULL);
1197                         request->proxy = fake->packet;
1198                         fake->packet = NULL;
1199                         rad_free(&fake->reply);
1200                         fake->reply = NULL;
1201
1202                         /*
1203                          *      Set up the callbacks for the tunnel
1204                          */
1205                         tunnel = rad_malloc(sizeof(*tunnel));
1206                         memset(tunnel, 0, sizeof(*tunnel));
1207
1208                         tunnel->tls_session = tls_session;
1209                         tunnel->callback = eapttls_postproxy;
1210
1211                         /*
1212                          *      Associate the callback with the request.
1213                          */
1214                         rcode = request_data_add(request,
1215                                                  request->proxy,
1216                                                  REQUEST_DATA_EAP_TUNNEL_CALLBACK,
1217                                                  tunnel, free);
1218                         rad_assert(rcode == 0);
1219                         
1220                         /*
1221                          *      rlm_eap.c has taken care of associating
1222                          *      the handler with the fake request.
1223                          *
1224                          *      So we associate the fake request with
1225                          *      this request.
1226                          */
1227                         rcode = request_data_add(request,
1228                                                  request->proxy,
1229                                                  REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
1230                                                  fake, my_request_free);
1231                         rad_assert(rcode == 0);
1232                         fake = NULL;
1233
1234                         /*
1235                          *      Didn't authenticate the packet, but
1236                          *      we're proxying it.
1237                          */
1238                         rcode = PW_STATUS_CLIENT;
1239
1240                 } else {
1241                         DEBUG2("  TTLS: No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
1242                                request->number);
1243                         rcode = PW_AUTHENTICATION_REJECT;
1244                 }
1245                 break;
1246
1247         default:
1248                 /*
1249                  *      Returns RLM_MODULE_FOO, and we want to return
1250                  *      PW_FOO
1251                  */
1252                 rcode = process_reply(handler, tls_session, request,
1253                                       fake->reply);
1254                 switch (rcode) {
1255                 case RLM_MODULE_REJECT:
1256                         rcode = PW_AUTHENTICATION_REJECT;
1257                         break;
1258                         
1259                 case RLM_MODULE_HANDLED:
1260                         rcode = PW_ACCESS_CHALLENGE;
1261                         break;
1262                         
1263                 case RLM_MODULE_OK:
1264                         rcode = PW_AUTHENTICATION_ACK;
1265                         break;
1266                         
1267                 default:
1268                         rcode = PW_AUTHENTICATION_REJECT;
1269                         break;
1270                 }
1271                 break;
1272         }
1273
1274         request_free(&fake);
1275
1276         return rcode;
1277 }