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