Reverse DICT_ATTR const order
[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                                 DICT_ATTR const *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                         vp->type = VT_DATA;
356                         memcpy(p, data, size);
357                         p[size] = '\0';
358                         vp->length = strlen(p);
359                         break;
360
361                         /*
362                          *      Copy it over verbatim.
363                          */
364                 case PW_TYPE_OCTETS:
365                 default:
366                         pairmemcpy(vp, data, size);
367                         break;
368                 }
369
370                 /*
371                  *      Ensure that the client is using the
372                  *      correct challenge.  This weirdness is
373                  *      to protect against against replay
374                  *      attacks, where anyone observing the
375                  *      CHAP exchange could pose as that user,
376                  *      by simply choosing to use the same
377                  *      challenge.
378                  *
379                  *      By using a challenge based on
380                  *      information from the current session,
381                  *      we can guarantee that the client is
382                  *      not *choosing* a challenge.
383                  *
384                  *      We're a little forgiving in that we
385                  *      have loose checks on the length, and
386                  *      we do NOT check the Id (first octet of
387                  *      the response to the challenge)
388                  *
389                  *      But if the client gets the challenge correct,
390                  *      we're not too worried about the Id.
391                  */
392                 if (((vp->da->vendor == 0) && (vp->da->attr == PW_CHAP_CHALLENGE)) ||
393                     ((vp->da->vendor == VENDORPEC_MICROSOFT) && (vp->da->attr == PW_MSCHAP_CHALLENGE))) {
394                         uint8_t challenge[16];
395
396                         if ((vp->length < 8) ||
397                             (vp->length > 16)) {
398                                 RDEBUG("Tunneled challenge has invalid length");
399                                 pairfree(&first);
400                                 pairfree(&vp);
401                                 return NULL;
402                         }
403
404                         eapttls_gen_challenge(ssl, challenge,
405                                               sizeof(challenge));
406
407                         if (memcmp(challenge, vp->vp_octets,
408                                    vp->length) != 0) {
409                                 RDEBUG("Tunneled challenge is incorrect");
410                                 pairfree(&first);
411                                 pairfree(&vp);
412                                 return NULL;
413                         }
414                 }
415
416                 /*
417                  *      Update the list.
418                  */
419                 pairinsert(&out, vp);
420
421         next_attr:
422                 /*
423                  *      Catch non-aligned attributes.
424                  */
425                 if (data_left == length) break;
426
427                 /*
428                  *      The length does NOT include the padding, so
429                  *      we've got to account for it here by rounding up
430                  *      to the nearest 4-byte boundary.
431                  */
432                 length += 0x03;
433                 length &= ~0x03;
434
435                 rad_assert(data_left >= length);
436                 data_left -= length;
437                 data += length - offset; /* already updated */
438         }
439
440         /*
441          *      We got this far.  It looks OK.
442          */
443         return first;
444 }
445
446 /*
447  *      Convert VALUE_PAIR's to diameter attributes, and write them
448  *      to an SSL session.
449  *
450  *      The ONLY VALUE_PAIR's which may be passed to this function
451  *      are ones which can go inside of a RADIUS (i.e. diameter)
452  *      packet.  So no server-configuration attributes, or the like.
453  */
454 static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *first)
455 {
456         /*
457          *      RADIUS packets are no more than 4k in size, so if
458          *      we've got more than 4k of data to write, it's very
459          *      bad.
460          */
461         uint8_t         buffer[4096];
462         uint8_t         *p;
463         uint32_t        attr;
464         uint32_t        length;
465         uint32_t        vendor;
466         size_t          total;
467         uint64_t        attr64;
468         VALUE_PAIR      *vp;
469         vp_cursor_t     cursor;
470
471         p = buffer;
472         total = 0;
473
474         for (vp = paircursor(&cursor, &first); vp; vp = pairnext(&cursor)) {
475                 /*
476                  *      Too much data: die.
477                  */
478                 if ((total + vp->length + 12) >= sizeof(buffer)) {
479                         RDEBUG2("output buffer is full!");
480                         return 0;
481                 }
482
483                 /*
484                  *      Hmm... we don't group multiple EAP-Messages
485                  *      together.  Maybe we should...
486                  */
487
488                 length = vp->length;
489                 vendor = vp->da->vendor;
490                 if (vendor != 0) {
491                         attr = vp->da->attr & 0xffff;
492                         length |= (1 << 31);
493                 } else {
494                         attr = vp->da->attr;
495                 }
496
497                 /*
498                  *      Hmm... set the M bit for all attributes?
499                  */
500                 length |= (1 << 30);
501
502                 attr = ntohl(attr);
503
504                 memcpy(p, &attr, sizeof(attr));
505                 p += 4;
506                 total += 4;
507
508                 length += 8;    /* includes 8 bytes of attr & length */
509
510                 if (vendor != 0) {
511                         length += 4; /* include 4 bytes of vendor */
512
513                         length = ntohl(length);
514                         memcpy(p, &length, sizeof(length));
515                         p += 4;
516                         total += 4;
517
518                         vendor = ntohl(vendor);
519                         memcpy(p, &vendor, sizeof(vendor));
520                         p += 4;
521                         total += 4;
522                 } else {
523                         length = ntohl(length);
524                         memcpy(p, &length, sizeof(length));
525                         p += 4;
526                         total += 4;
527                 }
528
529                 switch (vp->da->type) {
530                 case PW_TYPE_INTEGER:
531                 case PW_TYPE_DATE:
532                         attr = htonl(vp->vp_integer); /* stored in host order */
533                         memcpy(p, &attr, sizeof(attr));
534                         length = 4;
535                         break;
536
537                 case PW_TYPE_INTEGER64:
538                         attr64 = htonll(vp->vp_integer64); /* stored in host order */
539                         memcpy(p, &attr64, sizeof(attr64));
540                         length = 8;
541                         break;
542
543                 case PW_TYPE_IPADDR:
544                         memcpy(p, &vp->vp_ipaddr, 4); /* network order */
545                         length = 4;
546                         break;
547
548                 case PW_TYPE_STRING:
549                 case PW_TYPE_OCTETS:
550                 default:
551                         memcpy(p, vp->vp_strvalue, vp->length);
552                         length = vp->length;
553                         break;
554                 }
555
556                 /*
557                  *      Skip to the end of the data.
558                  */
559                 p += length;
560                 total += length;
561
562                 /*
563                  *      Align the data to a multiple of 4 bytes.
564                  */
565                 if ((total & 0x03) != 0) {
566                         size_t i;
567
568                         length = 4 - (total & 0x03);
569                         for (i = 0; i < length; i++) {
570                                 *p = '\0';
571                                 p++;
572                                 total++;
573                         }
574                 }
575         } /* loop over the VP's to write. */
576
577         /*
578          *      Write the data in the buffer to the SSL session.
579          */
580         if (total > 0) {
581 #ifndef NDEBUG
582                 size_t i;
583
584                 if ((debug_flag > 2) && fr_log_fp) {
585                         for (i = 0; i < total; i++) {
586                                 if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data out %04x: ", (int) i);
587
588                                 fprintf(fr_log_fp, "%02x ", buffer[i]);
589
590                                 if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
591                         }
592                         if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n");
593                 }
594 #endif
595
596                 (tls_session->record_plus)(&tls_session->clean_in, buffer, total);
597
598                 /*
599                  *      FIXME: Check the return code.
600                  */
601                 tls_handshake_send(request, tls_session);
602         }
603
604         /*
605          *      Everything's OK.
606          */
607         return 1;
608 }
609
610 /*
611  *      Use a reply packet to determine what to do.
612  */
613 static rlm_rcode_t process_reply(UNUSED eap_handler_t *handler, tls_session_t *tls_session,
614                                  REQUEST *request, RADIUS_PACKET *reply)
615 {
616         rlm_rcode_t rcode = RLM_MODULE_REJECT;
617         VALUE_PAIR *vp;
618         ttls_tunnel_t *t = tls_session->opaque;
619
620         rad_assert(request != NULL);
621         rad_assert(handler->request == request);
622
623         /*
624          *      If the response packet was Access-Accept, then
625          *      we're OK.  If not, die horribly.
626          *
627          *      FIXME: Take MS-CHAP2-Success attribute, and
628          *      tunnel it back to the client, to authenticate
629          *      ourselves to the client.
630          *
631          *      FIXME: If we have an Access-Challenge, then
632          *      the Reply-Message is tunneled back to the client.
633          *
634          *      FIXME: If we have an EAP-Message, then that message
635          *      must be tunneled back to the client.
636          *
637          *      FIXME: If we have an Access-Challenge with a State
638          *      attribute, then do we tunnel that to the client, or
639          *      keep track of it ourselves?
640          *
641          *      FIXME: EAP-Messages can only start with 'identity',
642          *      NOT 'eap start', so we should check for that....
643          */
644         switch (reply->code) {
645         case PW_AUTHENTICATION_ACK:
646                 RDEBUG("Got tunneled Access-Accept");
647
648                 rcode = RLM_MODULE_OK;
649
650                 /*
651                  *      MS-CHAP2-Success means that we do NOT return
652                  *      an Access-Accept, but instead tunnel that
653                  *      attribute to the client, and keep going with
654                  *      the TTLS session.  Once the client accepts
655                  *      our identity, it will respond with an empty
656                  *      packet, and we will send EAP-Success.
657                  */
658                 vp = NULL;
659                 pairfilter(tls_session, &vp, &reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT, TAG_ANY);
660                 if (vp) {
661                         RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge.");
662                         rcode = RLM_MODULE_HANDLED;
663                         t->authenticated = true;
664
665                         /*
666                          *      Delete MPPE keys & encryption policy.  We don't
667                          *      want these here.
668                          */
669                         pairdelete(&reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
670                         pairdelete(&reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
671                         pairdelete(&reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
672                         pairdelete(&reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
673
674                         /*
675                          *      Use the tunneled reply, but not now.
676                          */
677                         if (t->use_tunneled_reply) {
678                                 rad_assert(!t->accept_vps);
679                                 pairfilter(t, &t->accept_vps, &reply->vps,
680                                           0, 0, TAG_ANY);
681                                 rad_assert(!reply->vps);
682                         }
683
684                 } else { /* no MS-CHAP2-Success */
685                         /*
686                          *      Can only have EAP-Message if there's
687                          *      no MS-CHAP2-Success.  (FIXME: EAP-MSCHAP?)
688                          *
689                          *      We also do NOT tunnel the EAP-Success
690                          *      attribute back to the client, as the client
691                          *      can figure it out, from the non-tunneled
692                          *      EAP-Success packet.
693                          */
694                         pairfilter(tls_session, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
695                         pairfree(&vp);
696                 }
697
698                 /*
699                  *      Handle the ACK, by tunneling any necessary reply
700                  *      VP's back to the client.
701                  */
702                 if (vp) {
703                         vp2diameter(request, tls_session, vp);
704                         pairfree(&vp);
705                 }
706
707                 /*
708                  *      If we've been told to use the attributes from
709                  *      the reply, then do so.
710                  *
711                  *      WARNING: This may leak information about the
712                  *      tunneled user!
713                  */
714                 if (t->use_tunneled_reply) {
715                         pairdelete(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
716                         pairfilter(request->reply, &request->reply->vps,
717                                   &reply->vps, 0, 0, TAG_ANY);
718                 }
719                 break;
720
721
722         case PW_AUTHENTICATION_REJECT:
723                 RDEBUG("Got tunneled Access-Reject");
724                 rcode = RLM_MODULE_REJECT;
725                 break;
726
727                 /*
728                  *      Handle Access-Challenge, but only if we
729                  *      send tunneled reply data.  This is because
730                  *      an Access-Challenge means that we MUST tunnel
731                  *      a Reply-Message to the client.
732                  */
733         case PW_ACCESS_CHALLENGE:
734                 RDEBUG("Got tunneled Access-Challenge");
735
736                 /*
737                  *      Keep the State attribute, if necessary.
738                  *
739                  *      Get rid of the old State, too.
740                  */
741                 pairfree(&t->state);
742                 pairfilter(t, &t->state, &reply->vps, PW_STATE, 0, TAG_ANY);
743
744                 /*
745                  *      We should really be a bit smarter about this,
746                  *      and move over only those attributes which
747                  *      are relevant to the authentication request,
748                  *      but that's a lot more work, and this "dumb"
749                  *      method works in 99.9% of the situations.
750                  */
751                 vp = NULL;
752                 pairfilter(t, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
753
754                 /*
755                  *      There MUST be a Reply-Message in the challenge,
756                  *      which we tunnel back to the client.
757                  *
758                  *      If there isn't one in the reply VP's, then
759                  *      we MUST create one, with an empty string as
760                  *      it's value.
761                  */
762                 pairfilter(t, &vp, &reply->vps, PW_REPLY_MESSAGE, 0, TAG_ANY);
763
764                 /*
765                  *      Handle the ACK, by tunneling any necessary reply
766                  *      VP's back to the client.
767                  */
768                 if (vp) {
769                         vp2diameter(request, tls_session, vp);
770                         pairfree(&vp);
771                 }
772                 rcode = RLM_MODULE_HANDLED;
773                 break;
774
775         default:
776                 RDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
777                 rcode = RLM_MODULE_INVALID;
778                 break;
779         }
780
781         return rcode;
782 }
783
784
785 #ifdef WITH_PROXY
786 /*
787  *      Do post-proxy processing,
788  */
789 static int eapttls_postproxy(eap_handler_t *handler, void *data)
790 {
791         int rcode;
792         tls_session_t *tls_session = (tls_session_t *) data;
793         REQUEST *fake, *request = handler->request;
794
795         rad_assert(request != NULL);
796         RDEBUG("Passing reply from proxy back into the tunnel.");
797
798         /*
799          *      If there was a fake request associated with the proxied
800          *      request, do more processing of it.
801          */
802         fake = (REQUEST *) request_data_get(handler->request,
803                                             handler->request->proxy,
804                                             REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
805
806         /*
807          *      Do the callback, if it exists, and if it was a success.
808          */
809         if (fake &&
810             handler->request->proxy_reply &&
811             (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {
812                 /*
813                  *      Terrible hacks.
814                  */
815                 rad_assert(!fake->packet);
816                 fake->packet = request->proxy;
817                 fake->packet->src_ipaddr = request->packet->src_ipaddr;
818                 request->proxy = NULL;
819
820                 rad_assert(!fake->reply);
821                 fake->reply = request->proxy_reply;
822                 request->proxy_reply = NULL;
823
824                 if ((debug_flag > 0) && fr_log_fp) {
825                         fprintf(fr_log_fp, "server %s {\n",
826                                 (!fake->server) ? "" : fake->server);
827                 }
828
829                 /*
830                  *      Perform a post-auth stage for the tunneled
831                  *      session.
832                  */
833                 fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
834                 rcode = rad_postauth(fake);
835                 RDEBUG2("post-auth returns %d", rcode);
836
837                 if ((debug_flag > 0) && fr_log_fp) {
838                         fprintf(fr_log_fp, "} # server %s\n",
839                                 (!fake->server) ? "" : fake->server);
840
841                         RDEBUG("Final reply from tunneled session code %d",
842                                fake->reply->code);
843                         debug_pair_list(fake->reply->vps);
844                 }
845
846                 /*
847                  *      Terrible hacks.
848                  */
849                 request->proxy = fake->packet;
850                 fake->packet = NULL;
851                 request->proxy_reply = fake->reply;
852                 fake->reply = NULL;
853
854                 /*
855                  *      And we're done with this request.
856                  */
857
858                 switch (rcode) {
859                 case RLM_MODULE_FAIL:
860                         request_free(&fake);
861                         eaptls_fail(handler, 0);
862                         return 0;
863                         break;
864
865                 default:  /* Don't Do Anything */
866                         RDEBUG2("Got reply %d",
867                                request->proxy_reply->code);
868                         break;
869                 }
870         }
871         request_free(&fake);    /* robust if !fake */
872
873         /*
874          *      Process the reply from the home server.
875          */
876         rcode = process_reply(handler, tls_session, handler->request,
877                               handler->request->proxy_reply);
878
879         /*
880          *      The proxy code uses the reply from the home server as
881          *      the basis for the reply to the NAS.  We don't want that,
882          *      so we toss it, after we've had our way with it.
883          */
884         pairfree(&handler->request->proxy_reply->vps);
885
886         switch (rcode) {
887         case RLM_MODULE_REJECT:
888                 RDEBUG("Reply was rejected");
889                 break;
890
891         case RLM_MODULE_HANDLED:
892                 RDEBUG("Reply was handled");
893                 eaptls_request(handler->eap_ds, tls_session);
894                 return 1;
895
896         case RLM_MODULE_OK:
897                 RDEBUG("Reply was OK");
898
899                 /*
900                  *      Success: Automatically return MPPE keys.
901                  */
902                 return eaptls_success(handler, 0);
903
904         default:
905                 RDEBUG("Reply was unknown.");
906                 break;
907         }
908
909         eaptls_fail(handler, 0);
910         return 0;
911 }
912
913 #endif  /* WITH_PROXY */
914
915 /*
916  *      Process the "diameter" contents of the tunneled data.
917  */
918 int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session)
919 {
920         int code = PW_AUTHENTICATION_REJECT;
921         rlm_rcode_t rcode;
922         REQUEST *fake;
923         VALUE_PAIR *vp;
924         ttls_tunnel_t *t;
925         const uint8_t *data;
926         size_t data_len;
927         REQUEST *request = handler->request;
928
929         rad_assert(request != NULL);
930
931         /*
932          *      Just look at the buffer directly, without doing
933          *      record_minus.
934          */
935         data_len = tls_session->clean_out.used;
936         tls_session->clean_out.used = 0;
937         data = tls_session->clean_out.data;
938
939         t = (ttls_tunnel_t *) tls_session->opaque;
940
941         /*
942          *      If there's no data, maybe this is an ACK to an
943          *      MS-CHAP2-Success.
944          */
945         if (data_len == 0) {
946                 if (t->authenticated) {
947                         RDEBUG("Got ACK, and the user was already authenticated.");
948                         return PW_AUTHENTICATION_ACK;
949                 } /* else no session, no data, die. */
950
951                 /*
952                  *      FIXME: Call SSL_get_error() to see what went
953                  *      wrong.
954                  */
955                 RDEBUG2("SSL_read Error");
956                 return PW_AUTHENTICATION_REJECT;
957         }
958
959 #ifndef NDEBUG
960         if ((debug_flag > 2) && fr_log_fp) {
961                 size_t i;
962
963                 for (i = 0; i < data_len; i++) {
964                         if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data in %04x: ", (int) i);
965
966                         fprintf(fr_log_fp, "%02x ", data[i]);
967
968                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
969                 }
970                 if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
971         }
972 #endif
973
974         if (!diameter_verify(request, data, data_len)) {
975                 return PW_AUTHENTICATION_REJECT;
976         }
977
978         /*
979          *      Allocate a fake REQUEST structe.
980          */
981         fake = request_alloc_fake(request);
982
983         rad_assert(!fake->packet->vps);
984
985         /*
986          *      Add the tunneled attributes to the fake request.
987          */
988         fake->packet->vps = diameter2vp(request, fake, tls_session->ssl, data, data_len);
989         if (!fake->packet->vps) {
990                 request_free(&fake);
991                 return PW_AUTHENTICATION_REJECT;
992         }
993
994         /*
995          *      Tell the request that it's a fake one.
996          */
997         pairmake_packet("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
998
999         if ((debug_flag > 0) && fr_log_fp) {
1000                 RDEBUG("Got tunneled request");
1001
1002                 debug_pair_list(fake->packet->vps);
1003         }
1004
1005         /*
1006          *      Update other items in the REQUEST data structure.
1007          */
1008         fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1009         fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
1010
1011         /*
1012          *      No User-Name, try to create one from stored data.
1013          */
1014         if (!fake->username) {
1015                 /*
1016                  *      No User-Name in the stored data, look for
1017                  *      an EAP-Identity, and pull it out of there.
1018                  */
1019                 if (!t->username) {
1020                         vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
1021                         if (vp &&
1022                             (vp->length >= EAP_HEADER_LEN + 2) &&
1023                             (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
1024                             (vp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
1025                             (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
1026                                 char *p;
1027
1028                                 /*
1029                                  *      Create & remember a User-Name
1030                                  */
1031                                 t->username = pairmake(t, NULL, "User-Name", NULL, T_OP_EQ);
1032                                 rad_assert(t->username != NULL);
1033                                 t->username->length = vp->length - 5;
1034
1035                                 t->username->vp_strvalue = p = talloc_array(t->username, char,
1036                                                                             t->username->length + 1);
1037                                 memcpy(p, vp->vp_octets + 5, t->username->length);
1038                                 p[t->username->length] = 0;
1039
1040                                 RDEBUG("Got tunneled identity of %s",
1041                                        t->username->vp_strvalue);
1042
1043                                 /*
1044                                  *      If there's a default EAP type,
1045                                  *      set it here.
1046                                  */
1047                                 if (t->default_method != 0) {
1048                                         RDEBUG("Setting default EAP type for tunneled EAP session.");
1049                                         vp = paircreate(fake, PW_EAP_TYPE, 0);
1050                                         rad_assert(vp != NULL);
1051                                         vp->vp_integer = t->default_method;
1052                                         pairadd(&fake->config_items, vp);
1053                                 }
1054
1055                         } else {
1056                                 /*
1057                                  *      Don't reject the request outright,
1058                                  *      as it's permitted to do EAP without
1059                                  *      user-name.
1060                                  */
1061                                 RWDEBUG2("No EAP-Identity found to start EAP conversation.");
1062                         }
1063                 } /* else there WAS a t->username */
1064
1065                 if (t->username) {
1066                         vp = paircopy(fake->packet, t->username);
1067                         pairadd(&fake->packet->vps, vp);
1068                         fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1069                 }
1070         } /* else the request ALREADY had a User-Name */
1071
1072         /*
1073          *      Add the State attribute, too, if it exists.
1074          */
1075         if (t->state) {
1076                 vp = paircopy(fake->packet, t->state);
1077                 if (vp) pairadd(&fake->packet->vps, vp);
1078         }
1079
1080         /*
1081          *      If this is set, we copy SOME of the request attributes
1082          *      from outside of the tunnel to inside of the tunnel.
1083          *
1084          *      We copy ONLY those attributes which do NOT already
1085          *      exist in the tunneled request.
1086          */
1087         if (t->copy_request_to_tunnel) {
1088                 VALUE_PAIR *copy;
1089                 vp_cursor_t cursor;
1090
1091                 for (vp = paircursor(&cursor, &request->packet->vps); vp; vp = pairnext(&cursor)) {
1092                         /*
1093                          *      The attribute is a server-side thingy,
1094                          *      don't copy it.
1095                          */
1096                         if ((vp->da->attr > 255) &&
1097                             (vp->da->vendor == 0)) {
1098                                 continue;
1099                         }
1100
1101                         /*
1102                          *      The outside attribute is already in the
1103                          *      tunnel, don't copy it.
1104                          *
1105                          *      This works for BOTH attributes which
1106                          *      are originally in the tunneled request,
1107                          *      AND attributes which are copied there
1108                          *      from below.
1109                          */
1110                         if (pairfind(fake->packet->vps, vp->da->attr, vp->da->vendor, TAG_ANY)) {
1111                                 continue;
1112                         }
1113
1114                         /*
1115                          *      Some attributes are handled specially.
1116                          */
1117                         switch (vp->da->attr) {
1118                                 /*
1119                                  *      NEVER copy Message-Authenticator,
1120                                  *      EAP-Message, or State.  They're
1121                                  *      only for outside of the tunnel.
1122                                  */
1123                         case PW_USER_NAME:
1124                         case PW_USER_PASSWORD:
1125                         case PW_CHAP_PASSWORD:
1126                         case PW_CHAP_CHALLENGE:
1127                         case PW_PROXY_STATE:
1128                         case PW_MESSAGE_AUTHENTICATOR:
1129                         case PW_EAP_MESSAGE:
1130                         case PW_STATE:
1131                                 continue;
1132                                 break;
1133
1134                                 /*
1135                                  *      By default, copy it over.
1136                                  */
1137                         default:
1138                                 break;
1139                         }
1140
1141                         /*
1142                          *      Don't copy from the head, we've already
1143                          *      checked it.
1144                          */
1145                         copy = paircopy2(fake->packet, vp, vp->da->attr, vp->da->vendor, TAG_ANY);
1146                         pairadd(&fake->packet->vps, copy);
1147                 }
1148         }
1149
1150         if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
1151                 fake->server = vp->vp_strvalue;
1152
1153         } else if (t->virtual_server) {
1154                 fake->server = t->virtual_server;
1155
1156         } /* else fake->server == request->server */
1157
1158
1159         if ((debug_flag > 0) && fr_log_fp) {
1160                 RDEBUG("Sending tunneled request");
1161
1162                 debug_pair_list(fake->packet->vps);
1163
1164                 fprintf(fr_log_fp, "server %s {\n",
1165                         (!fake->server) ? "" : fake->server);
1166         }
1167
1168         /*
1169          *      Call authentication recursively, which will
1170          *      do PAP, CHAP, MS-CHAP, etc.
1171          */
1172         rad_virtual_server(fake);
1173
1174         /*
1175          *      Note that we don't do *anything* with the reply
1176          *      attributes.
1177          */
1178         if ((debug_flag > 0) && fr_log_fp) {
1179                 fprintf(fr_log_fp, "} # server %s\n",
1180                         (!fake->server) ? "" : fake->server);
1181
1182                 RDEBUG("Got tunneled reply code %d", fake->reply->code);
1183
1184                 debug_pair_list(fake->reply->vps);
1185         }
1186
1187         /*
1188          *      Decide what to do with the reply.
1189          */
1190         switch (fake->reply->code) {
1191         case 0:                 /* No reply code, must be proxied... */
1192 #ifdef WITH_PROXY
1193                 vp = pairfind(fake->config_items, PW_PROXY_TO_REALM, 0, TAG_ANY);
1194                 if (vp) {
1195                         eap_tunnel_data_t *tunnel;
1196                         RDEBUG("Tunneled authentication will be proxied to %s", vp->vp_strvalue);
1197
1198                         /*
1199                          *      Tell the original request that it's going
1200                          *      to be proxied.
1201                          */
1202                         pairfilter(request, &(request->config_items),
1203                                   &(fake->config_items),
1204                                   PW_PROXY_TO_REALM, 0, TAG_ANY);
1205
1206                         /*
1207                          *      Seed the proxy packet with the
1208                          *      tunneled request.
1209                          */
1210                         rad_assert(!request->proxy);
1211                         request->proxy = fake->packet;
1212                         memset(&request->proxy->src_ipaddr, 0,
1213                                sizeof(request->proxy->src_ipaddr));
1214                         memset(&request->proxy->src_ipaddr, 0,
1215                                sizeof(request->proxy->src_ipaddr));
1216                         request->proxy->src_port = 0;
1217                         request->proxy->dst_port = 0;
1218                         fake->packet = NULL;
1219                         rad_free(&fake->reply);
1220                         fake->reply = NULL;
1221
1222                         /*
1223                          *      Set up the callbacks for the tunnel
1224                          */
1225                         tunnel = talloc_zero(request, eap_tunnel_data_t);
1226                         tunnel->tls_session = tls_session;
1227                         tunnel->callback = eapttls_postproxy;
1228
1229                         /*
1230                          *      Associate the callback with the request.
1231                          */
1232                         code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
1233                                                 tunnel, false);
1234                         rad_assert(code == 0);
1235
1236                         /*
1237                          *      rlm_eap.c has taken care of associating
1238                          *      the handler with the fake request.
1239                          *
1240                          *      So we associate the fake request with
1241                          *      this request.
1242                          */
1243                         talloc_set_destructor(fake, request_opaque_free);
1244                         code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
1245                                                 fake, true);
1246                         rad_assert(code == 0);
1247                         fake = NULL;
1248
1249                         /*
1250                          *      Didn't authenticate the packet, but
1251                          *      we're proxying it.
1252                          */
1253                         code = PW_STATUS_CLIENT;
1254
1255                 } else
1256 #endif  /* WITH_PROXY */
1257                   {
1258                         RDEBUG("No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
1259                                request->number);
1260                         code = PW_AUTHENTICATION_REJECT;
1261                 }
1262                 break;
1263
1264         default:
1265                 /*
1266                  *      Returns RLM_MODULE_FOO, and we want to return PW_FOO
1267                  */
1268                 rcode = process_reply(handler, tls_session, request, fake->reply);
1269                 switch (rcode) {
1270                 case RLM_MODULE_REJECT:
1271                         code = PW_AUTHENTICATION_REJECT;
1272                         break;
1273
1274                 case RLM_MODULE_HANDLED:
1275                         code = PW_ACCESS_CHALLENGE;
1276                         break;
1277
1278                 case RLM_MODULE_OK:
1279                         code = PW_AUTHENTICATION_ACK;
1280                         break;
1281
1282                 default:
1283                         code = PW_AUTHENTICATION_REJECT;
1284                         break;
1285                 }
1286                 break;
1287         }
1288
1289         request_free(&fake);
1290
1291         return code;
1292 }