Move debug messages into rad_virtual_server
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_ttls / ttls.c
index 3f0bad6..82da48b 100644 (file)
@@ -21,7 +21,6 @@
  *   Copyright 2006 The FreeRADIUS server project
  */
 
-#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 #include "eap_ttls.h"
@@ -43,74 +42,36 @@ RCSID("$Id$")
 /*
  *     Verify that the diameter packet is valid.
  */
-static int diameter_verify(REQUEST *request,
-                          const uint8_t *data, unsigned int data_len)
+static int diameter_verify(REQUEST *request, uint8_t const *data, unsigned int data_len)
 {
        uint32_t attr;
        uint32_t length;
-       unsigned int offset;
-       unsigned int data_left = data_len;
+       unsigned int hdr_len;
+       unsigned int remaining = data_len;
 
-       while (data_left > 0) {
-               if (data_len < 12) {
-                       RDEBUG2(" Diameter attribute is too small to contain a Diameter header");
+       while (remaining > 0) {
+               hdr_len = 12;
+
+               if (remaining < hdr_len) {
+                 RDEBUG2("Diameter attribute is too small (%u) to contain a Diameter header", remaining);
                        return 0;
                }
 
-               rad_assert(data_left <= data_len);
                memcpy(&attr, data, sizeof(attr));
-               data += 4;
                attr = ntohl(attr);
-               if (attr > 255) {
-                       RDEBUG2(" Non-RADIUS attribute in tunneled authentication is not supported");
-                       return 0;
-               }
-
-               memcpy(&length, data , sizeof(length));
-               data += 4;
+               memcpy(&length, data + 4, sizeof(length));
                length = ntohl(length);
 
-               /*
-                *      A "vendor" flag, with a vendor ID of zero,
-                *      is equivalent to no vendor.  This is stupid.
-                */
-               offset = 8;
-               if ((length & (1 << 31)) != 0) {
-                       int attribute;
-                       uint32_t vendor;
-                       DICT_ATTR *da;
-
-                       memcpy(&vendor, data, sizeof(vendor));
-                       vendor = ntohl(vendor);
-
-                       if (vendor > 65535) {
-                               RDEBUG2("Vendor codes larger than 65535 are not supported");
-                               return 0;
-                       }
-
-                       attribute = (vendor << 16) | attr;
-
-                       da = dict_attrbyvalue(attribute);
-
-                       /*
-                        *      SHOULD check ((length & (1 << 30)) != 0)
-                        *      for the mandatory bit.
-                        */
-                       if (!da) {
-                               RDEBUG2("Fatal! Vendor %u, Attribute %u was not found in our dictionary. ",
-                                      vendor, attr);
+               if ((data[4] & 0x80) != 0) {
+                       if (remaining < 16) {
+                               RDEBUG2("Diameter attribute is too small to contain a Diameter header with Vendor-Id");
                                return 0;
                        }
 
-                       data += 4; /* skip the vendor field */
-                       offset += 4; /* offset to value field */
+                       hdr_len = 16;
                }
 
                /*
-                *      Ignore the M bit.  We support all RADIUS attributes...
-                */
-
-               /*
                 *      Get the length.  If it's too big, die.
                 */
                length &= 0x00ffffff;
@@ -118,23 +79,15 @@ static int diameter_verify(REQUEST *request,
                /*
                 *      Too short or too long is bad.
                 */
-               if (length < offset) {
-                       RDEBUG2("Tunneled attribute %d is too short (%d)to contain anything useful.", attr, length);
-                       return 0;
-               }
-
-               /*
-                *      EAP Messages cane be longer than MAX_STRING_LEN.
-                *      Other attributes cannot be.
-                */
-               if ((attr != PW_EAP_MESSAGE) &&
-                   (length > (MAX_STRING_LEN + 8))) {
-                       RDEBUG2("Tunneled attribute %d is too long (%d) to pack into a RADIUS attribute.", attr, length);
+               if (length <= (hdr_len - 4)) {
+                       RDEBUG2("Tunneled attribute %u is too short (%u < %u) to contain anything useful.", attr,
+                               length, hdr_len);
                        return 0;
                }
 
-               if (length > data_left) {
-                       RDEBUG2("Tunneled attribute %d is longer than room left in the packet (%d > %d).", attr, length, data_left);
+               if (length > remaining) {
+                       RDEBUG2("Tunneled attribute %u is longer than room remaining in the packet (%u > %u).", attr,
+                               length, remaining);
                        return 0;
                }
 
@@ -142,7 +95,7 @@ static int diameter_verify(REQUEST *request,
                 *      Check for broken implementations, which don't
                 *      pad the AVP to a 4-octet boundary.
                 */
-               if (data_left == length) break;
+               if (remaining == length) break;
 
                /*
                 *      The length does NOT include the padding, so
@@ -159,22 +112,16 @@ static int diameter_verify(REQUEST *request,
                 *      Otherwise, if the attribute over-flows the end
                 *      of the packet, die.
                 */
-               if (data_left < length) {
-                       RDEBUG2("ERROR! Diameter attribute overflows packet!");
+               if (remaining < length) {
+                       REDEBUG2("Diameter attribute overflows packet!");
                        return 0;
                }
 
                /*
-                *      Check again for equality, now that we're padded
-                *      length to a multiple of 4 octets.
-                */
-               if (data_left == length) break;
-
-               /*
-                *      data_left > length, continue.
+                *      remaining > length, continue.
                 */
-               data_left -= length;
-               data += length - offset;
+               remaining -= length;
+               data += length;
        }
 
        /*
@@ -187,23 +134,29 @@ static int diameter_verify(REQUEST *request,
 /*
  *     Convert diameter attributes to our VALUE_PAIR's
  */
-static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
-                              const uint8_t *data, size_t data_len)
+static VALUE_PAIR *diameter2vp(REQUEST *request, REQUEST *fake, SSL *ssl,
+                              uint8_t const *data, size_t data_len)
 {
        uint32_t        attr;
+       uint32_t        vendor;
        uint32_t        length;
        size_t          offset;
        size_t          size;
        size_t          data_left = data_len;
+       char            *p;
        VALUE_PAIR      *first = NULL;
-       VALUE_PAIR      **last = &first;
        VALUE_PAIR      *vp;
+       RADIUS_PACKET   *packet = fake->packet; /* FIXME: api issues */
+       vp_cursor_t     out;
+
+       fr_cursor_init(&out, &first);
 
        while (data_left > 0) {
                rad_assert(data_left <= data_len);
                memcpy(&attr, data, sizeof(attr));
                data += 4;
                attr = ntohl(attr);
+               vendor = 0;
 
                memcpy(&length, data, sizeof(length));
                data += 4;
@@ -215,37 +168,14 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                 */
                offset = 8;
                if ((length & (1 << 31)) != 0) {
-                       uint32_t vendor;
-
                        memcpy(&vendor, data, sizeof(vendor));
                        vendor = ntohl(vendor);
 
-                       if (attr > 65535) {
-                               RDEBUG2("Cannot handle vendor attributes greater than 65535");
-                               pairfree(&first);
-                               return NULL;
-                       }
-
-                       if (vendor > 32767) {
-                               RDEBUG2("Cannot handle vendor Id greater than 32767");
-                               pairfree(&first);
-                               return NULL;
-                       }
-
-                       attr |= (vendor << 16);
-
                        data += 4; /* skip the vendor field, it's zero */
                        offset += 4; /* offset to value field */
-               }
 
-               /*
-                *      Vendor attributes can be larger than 255.
-                *      Normal attributes cannot be.
-                */
-               if ((attr > 255) && (VENDOR(attr) == 0)) {
-                       RDEBUG2("Cannot handle Diameter attributes");
-                       pairfree(&first);
-                       return NULL;
+                       if (attr > 65535) goto next_attr;
+                       if (vendor > FR_MAX_VENDOR) goto next_attr;
                }
 
                /*
@@ -253,7 +183,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                 *      some other module takes care of any attribute
                 *      with the M bit set.
                 */
-               
+
                /*
                 *      Get the length.
                 */
@@ -266,9 +196,68 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                size = length - offset;
 
                /*
-                *      Create it.
+                *      Vendor attributes can be larger than 255.
+                *      Normal attributes cannot be.
                 */
-               vp = paircreate(attr, PW_TYPE_OCTETS);
+               if ((attr > 255) && (vendor == 0)) {
+                       RWDEBUG2("Skipping Diameter attribute %u", attr);
+                       goto next_attr;
+               }
+
+               /*
+                *      EAP-Message AVPs can be larger than 253 octets.
+                *
+                *      For now, we rely on the main decoder in
+                *      src/lib/radius to decode data into VPs.  This
+                *      means putting the data into a RADIUS attribute
+                *      format.  It also means that we can't handle
+                *      "extended" attributes in the Diameter space.  Oh well...
+                */
+               if ((size > 253) && !((vendor == 0) && (attr == PW_EAP_MESSAGE))) {
+                       RWDEBUG2("diameter2vp skipping long attribute %u", attr);
+                       goto next_attr;
+               }
+
+               /*
+                *      RADIUS VSAs are handled as Diameter attributes
+                *      with Vendor-Id == 0, and the VSA data packed
+                *      into the "String" field as per normal.
+                *
+                *      EXCEPT for the MS-CHAP attributes.
+                */
+               if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+                       ssize_t decoded;
+                       uint8_t buffer[256];
+
+                       buffer[0] = PW_VENDOR_SPECIFIC;
+                       buffer[1] = size + 2;
+                       memcpy(buffer + 2, data, size);
+
+                       vp = NULL;
+                       decoded = rad_attr2vp(packet, NULL, NULL, NULL,
+                                             buffer, size + 2, &vp);
+                       if (decoded < 0) {
+                               REDEBUG2("diameter2vp failed decoding attr: %s",
+                                       fr_strerror());
+                               goto do_octets;
+                       }
+
+                       if ((size_t) decoded != size + 2) {
+                               REDEBUG2("diameter2vp failed to entirely decode VSA");
+                               pairfree(&vp);
+                               goto do_octets;
+                       }
+
+                       fr_cursor_insert(&out, vp);
+
+                       goto next_attr;
+               }
+
+               /*
+                *      Create it.  If this fails, it's because we're OOM.
+                */
+       do_octets:
+               vp = paircreate(packet, attr, vendor);
                if (!vp) {
                        RDEBUG2("Failure in creating VP");
                        pairfree(&first);
@@ -278,16 +267,27 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                /*
                 *      If it's a type from our dictionary, then
                 *      we need to put the data in a relevant place.
+                *
+                *      @todo: Export the lib/radius.c decoder, and use it here!
                 */
-               switch (vp->type) {
+               switch (vp->da->type) {
                case PW_TYPE_INTEGER:
                case PW_TYPE_DATE:
                        if (size != vp->length) {
-                               RDEBUG2("Invalid length attribute %d",
-                                      attr);
-                               pairfree(&first);
-                               pairfree(&vp);
-                               return NULL;
+                               DICT_ATTR const *da;
+
+                               /*
+                                *      Bad format.  Create a "raw"
+                                *      attribute.
+                                */
+               raw:
+                               if (vp) pairfree(&vp);
+                               da = dict_attrunknown(attr, vendor, true);
+                               if (!da) return NULL;
+                               vp = pairalloc(packet, da);
+                               if (!vp) return NULL;
+                               pairmemcpy(vp, data, size);
+                               break;
                        }
                        memcpy(&vp->vp_integer, data, vp->length);
 
@@ -297,7 +297,17 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                        vp->vp_integer = ntohl(vp->vp_integer);
                        break;
 
-               case PW_TYPE_IPADDR:
+               case PW_TYPE_INTEGER64:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_integer64, data, vp->length);
+
+                       /*
+                        *      Stored in host byte order: change it.
+                        */
+                       vp->vp_integer64 = ntohll(vp->vp_integer64);
+                       break;
+
+               case PW_TYPE_IPV4_ADDR:
                        if (size != vp->length) {
                                RDEBUG2("Invalid length attribute %d",
                                       attr);
@@ -305,133 +315,109 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                                pairfree(&vp);
                                return NULL;
                        }
-                 memcpy(&vp->vp_ipaddr, data, vp->length);
-
-                 /*
-                  *    Stored in network byte order: don't change it.
-                  */
-                 break;
-
-                 /*
-                  *    String, octet, etc.  Copy the data from the
-                  *    value field over verbatim.
-                  *
-                  *    FIXME: Ipv6 attributes ?
-                  *
-                  */
-               case PW_TYPE_OCTETS:
-                       if (attr == PW_EAP_MESSAGE) {
-                               const uint8_t *eap_message = data;
+                       memcpy(&vp->vp_ipaddr, data, vp->length);
 
-                               /*
-                                *      vp exists the first time around.
-                                */
-                               while (1) {
-                                       vp->length = size;
-                                       if (vp->length > 253) vp->length = 253;
-                                       memcpy(vp->vp_octets, eap_message,
-                                              vp->length);
-
-                                       size -= vp->length;
-                                       eap_message += vp->length;
-
-                                       *last = vp;
-                                       last = &(vp->next);
-
-                                       if (size == 0) break;
-
-                                       vp = paircreate(attr, PW_TYPE_OCTETS);
-                                       if (!vp) {
-                                               RDEBUG2("Failure in creating VP");
-                                               pairfree(&first);
-                                               return NULL;
-                                       }
-                               }
+                       /*
+                        *      Stored in network byte order: don't change it.
+                        */
+                       break;
 
-                               goto next_attr;
-                       } /* else it's another kind of attribute */
-                       /* FALL-THROUGH */
+               case PW_TYPE_BYTE:
+                       if (size != vp->length) goto raw;
+                       vp->vp_integer = data[0];
+                       break;
 
-               default:
-                       vp->length = size;
-                       memcpy(vp->vp_strvalue, data, vp->length);
+               case PW_TYPE_SHORT:
+                       if (size != vp->length) goto raw;
+                       vp->vp_integer = (data[0] * 256) + data[1];
+                       break;
+
+               case PW_TYPE_SIGNED:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_signed, data, vp->length);
+                       vp->vp_signed = ntohl(vp->vp_signed);
+                       break;
+
+               case PW_TYPE_IPV6_ADDR:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_ipv6addr, data, vp->length);
+                       break;
+
+               case PW_TYPE_IPV6_PREFIX:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_ipv6prefix, data, vp->length);
                        break;
-               }
 
-               /*
-                *      User-Password is NUL padded to a multiple
-                *      of 16 bytes.  Let's chop it to something
-                *      more reasonable.
-                *
-                *      NOTE: This means that the User-Password
-                *      attribute CANNOT EVER have embedded zeros in it!
-                */
-               switch (vp->attribute) {
-               case PW_USER_PASSWORD:
                        /*
-                        *      If the password is exactly 16 octets,
-                        *      it won't be zero-terminated.
+                        *      Ensure it's NUL terminated.
                         */
-                       vp->vp_strvalue[vp->length] = '\0';
-                       vp->length = strlen(vp->vp_strvalue);
+               case PW_TYPE_STRING:
+                       vp->vp_strvalue = p = talloc_array(vp, char, size + 1);
+                       vp->type = VT_DATA;
+                       memcpy(p, data, size);
+                       p[size] = '\0';
+                       vp->length = strlen(p);
                        break;
 
                        /*
-                        *      Ensure that the client is using the
-                        *      correct challenge.  This weirdness is
-                        *      to protect against against replay
-                        *      attacks, where anyone observing the
-                        *      CHAP exchange could pose as that user,
-                        *      by simply choosing to use the same
-                        *      challenge.
-                        *
-                        *      By using a challenge based on
-                        *      information from the current session,
-                        *      we can guarantee that the client is
-                        *      not *choosing* a challenge.
-                        *
-                        *      We're a little forgiving in that we
-                        *      have loose checks on the length, and
-                        *      we do NOT check the Id (first octet of
-                        *      the response to the challenge)
-                        *
-                        *      But if the client gets the challenge correct,
-                        *      we're not too worried about the Id.
+                        *      Copy it over verbatim.
                         */
-               case PW_CHAP_CHALLENGE:
-               case PW_MSCHAP_CHALLENGE:
+               case PW_TYPE_OCTETS:
+               default:
+                       pairmemcpy(vp, data, size);
+                       break;
+               }
+
+               /*
+                *      Ensure that the client is using the
+                *      correct challenge.  This weirdness is
+                *      to protect against against replay
+                *      attacks, where anyone observing the
+                *      CHAP exchange could pose as that user,
+                *      by simply choosing to use the same
+                *      challenge.
+                *
+                *      By using a challenge based on
+                *      information from the current session,
+                *      we can guarantee that the client is
+                *      not *choosing* a challenge.
+                *
+                *      We're a little forgiving in that we
+                *      have loose checks on the length, and
+                *      we do NOT check the Id (first octet of
+                *      the response to the challenge)
+                *
+                *      But if the client gets the challenge correct,
+                *      we're not too worried about the Id.
+                */
+               if (((vp->da->vendor == 0) && (vp->da->attr == PW_CHAP_CHALLENGE)) ||
+                   ((vp->da->vendor == VENDORPEC_MICROSOFT) && (vp->da->attr == PW_MSCHAP_CHALLENGE))) {
+                       uint8_t challenge[16];
+
                        if ((vp->length < 8) ||
                            (vp->length > 16)) {
                                RDEBUG("Tunneled challenge has invalid length");
                                pairfree(&first);
                                pairfree(&vp);
                                return NULL;
+                       }
 
-                       } else {
-                               uint8_t challenge[16];
-
-                               eapttls_gen_challenge(ssl, challenge,
-                                                     sizeof(challenge));
+                       eapttls_gen_challenge(ssl, challenge,
+                                             sizeof(challenge));
 
-                               if (memcmp(challenge, vp->vp_octets,
-                                          vp->length) != 0) {
-                                       RDEBUG("Tunneled challenge is incorrect");
-                                       pairfree(&first);
-                                       pairfree(&vp);
-                                       return NULL;
-                               }
+                       if (memcmp(challenge, vp->vp_octets,
+                                  vp->length) != 0) {
+                               RDEBUG("Tunneled challenge is incorrect");
+                               pairfree(&first);
+                               pairfree(&vp);
+                               return NULL;
                        }
-                       break;
-
-               default:
-                       break;
-               } /* switch over checking/re-writing of attributes. */
+               }
 
                /*
                 *      Update the list.
                 */
-               *last = vp;
-               last = &(vp->next);
+               fr_cursor_insert(&out, vp);
 
        next_attr:
                /*
@@ -479,12 +465,14 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
        uint32_t        length;
        uint32_t        vendor;
        size_t          total;
+       uint64_t        attr64;
        VALUE_PAIR      *vp;
+       vp_cursor_t     cursor;
 
        p = buffer;
        total = 0;
 
-       for (vp = first; vp != NULL; vp = vp->next) {
+       for (vp = fr_cursor_init(&cursor, &first); vp; vp = fr_cursor_next(&cursor)) {
                /*
                 *      Too much data: die.
                 */
@@ -498,17 +486,13 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                 *      together.  Maybe we should...
                 */
 
-               /*
-                *      Length is no more than 253, due to RADIUS
-                *      issues.
-                */
                length = vp->length;
-               vendor = (vp->attribute >> 16) & 0xffff;
+               vendor = vp->da->vendor;
                if (vendor != 0) {
-                       attr = vp->attribute & 0xffff;
+                       attr = vp->da->attr & 0xffff;
                        length |= (1 << 31);
                } else {
-                       attr = vp->attribute;
+                       attr = vp->da->attr;
                }
 
                /*
@@ -543,15 +527,21 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                        total += 4;
                }
 
-               switch (vp->type) {
+               switch (vp->da->type) {
                case PW_TYPE_INTEGER:
                case PW_TYPE_DATE:
-                       attr = ntohl(vp->vp_integer); /* stored in host order */
+                       attr = htonl(vp->vp_integer); /* stored in host order */
                        memcpy(p, &attr, sizeof(attr));
                        length = 4;
                        break;
 
-               case PW_TYPE_IPADDR:
+               case PW_TYPE_INTEGER64:
+                       attr64 = htonll(vp->vp_integer64); /* stored in host order */
+                       memcpy(p, &attr64, sizeof(attr64));
+                       length = 8;
+                       break;
+
+               case PW_TYPE_IPV4_ADDR:
                        memcpy(p, &vp->vp_ipaddr, 4); /* network order */
                        length = 4;
                        break;
@@ -594,7 +584,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
 
                if ((debug_flag > 2) && fr_log_fp) {
                        for (i = 0; i < total; i++) {
-                               if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data out %04x: ", i);
+                               if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data out %04x: ", (int) i);
 
                                fprintf(fr_log_fp, "%02x ", buffer[i]);
 
@@ -609,7 +599,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                /*
                 *      FIXME: Check the return code.
                 */
-               tls_handshake_send(tls_session);
+               tls_handshake_send(request, tls_session);
        }
 
        /*
@@ -621,14 +611,14 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
 /*
  *     Use a reply packet to determine what to do.
  */
-static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
-                        REQUEST *request, RADIUS_PACKET *reply)
+static rlm_rcode_t CC_HINT(nonnull) process_reply(UNUSED eap_handler_t *handler, tls_session_t *tls_session,
+                                                 REQUEST *request, RADIUS_PACKET *reply)
 {
-       int rcode = RLM_MODULE_REJECT;
+       rlm_rcode_t rcode = RLM_MODULE_REJECT;
        VALUE_PAIR *vp;
        ttls_tunnel_t *t = tls_session->opaque;
 
-       handler = handler;      /* -Wunused */
+       rad_assert(handler->request == request);
 
        /*
         *      If the response packet was Access-Accept, then
@@ -652,7 +642,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
         *      NOT 'eap start', so we should check for that....
         */
        switch (reply->code) {
-       case PW_AUTHENTICATION_ACK:
+       case PW_CODE_ACCESS_ACCEPT:
                RDEBUG("Got tunneled Access-Accept");
 
                rcode = RLM_MODULE_OK;
@@ -666,27 +656,29 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      packet, and we will send EAP-Success.
                 */
                vp = NULL;
-               pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS);
+               pairfilter(tls_session, &vp, &reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT, TAG_ANY);
                if (vp) {
-                       RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge.");
+                       RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge");
                        rcode = RLM_MODULE_HANDLED;
-                       t->authenticated = TRUE;
+                       t->authenticated = true;
 
                        /*
                         *      Delete MPPE keys & encryption policy.  We don't
                         *      want these here.
                         */
-                       pairdelete(&reply->vps, ((311 << 16) | 7));
-                       pairdelete(&reply->vps, ((311 << 16) | 8));
-                       pairdelete(&reply->vps, ((311 << 16) | 16));
-                       pairdelete(&reply->vps, ((311 << 16) | 17));
+                       pairdelete(&reply->vps, 7, VENDORPEC_MICROSOFT, TAG_ANY);
+                       pairdelete(&reply->vps, 8, VENDORPEC_MICROSOFT, TAG_ANY);
+                       pairdelete(&reply->vps, 16, VENDORPEC_MICROSOFT, TAG_ANY);
+                       pairdelete(&reply->vps, 17, VENDORPEC_MICROSOFT, TAG_ANY);
 
                        /*
                         *      Use the tunneled reply, but not now.
                         */
                        if (t->use_tunneled_reply) {
-                               t->reply = reply->vps;
-                               reply->vps = NULL;
+                               rad_assert(!t->accept_vps);
+                               pairfilter(t, &t->accept_vps, &reply->vps,
+                                         0, 0, TAG_ANY);
+                               rad_assert(!reply->vps);
                        }
 
                } else { /* no MS-CHAP2-Success */
@@ -699,7 +691,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                         *      can figure it out, from the non-tunneled
                         *      EAP-Success packet.
                         */
-                       pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+                       pairfilter(tls_session, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
                        pairfree(&vp);
                }
 
@@ -720,14 +712,14 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      tunneled user!
                 */
                if (t->use_tunneled_reply) {
-                       pairdelete(&reply->vps, PW_PROXY_STATE);
-                       pairadd(&request->reply->vps, reply->vps);
-                       reply->vps = NULL;
+                       pairdelete(&reply->vps, PW_PROXY_STATE, 0, TAG_ANY);
+                       pairfilter(request->reply, &request->reply->vps,
+                                 &reply->vps, 0, 0, TAG_ANY);
                }
                break;
 
 
-       case PW_AUTHENTICATION_REJECT:
+       case PW_CODE_ACCESS_REJECT:
                RDEBUG("Got tunneled Access-Reject");
                rcode = RLM_MODULE_REJECT;
                break;
@@ -738,7 +730,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      an Access-Challenge means that we MUST tunnel
                 *      a Reply-Message to the client.
                 */
-       case PW_ACCESS_CHALLENGE:
+       case PW_CODE_ACCESS_CHALLENGE:
                RDEBUG("Got tunneled Access-Challenge");
 
                /*
@@ -747,7 +739,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      Get rid of the old State, too.
                 */
                pairfree(&t->state);
-               pairmove2(&t->state, &reply->vps, PW_STATE);
+               pairfilter(t, &t->state, &reply->vps, PW_STATE, 0, TAG_ANY);
 
                /*
                 *      We should really be a bit smarter about this,
@@ -757,7 +749,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      method works in 99.9% of the situations.
                 */
                vp = NULL;
-               pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+               pairfilter(t, &vp, &reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
 
                /*
                 *      There MUST be a Reply-Message in the challenge,
@@ -767,7 +759,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      we MUST create one, with an empty string as
                 *      it's value.
                 */
-               pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE);
+               pairfilter(t, &vp, &reply->vps, PW_REPLY_MESSAGE, 0, TAG_ANY);
 
                /*
                 *      Handle the ACK, by tunneling any necessary reply
@@ -790,16 +782,17 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
 }
 
 
+#ifdef WITH_PROXY
 /*
  *     Do post-proxy processing,
  */
-static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
+static int CC_HINT(nonnull) eapttls_postproxy(eap_handler_t *handler, void *data)
 {
        int rcode;
        tls_session_t *tls_session = (tls_session_t *) data;
        REQUEST *fake, *request = handler->request;
 
-       RDEBUG("Passing reply from proxy back into the tunnel.");
+       RDEBUG("Passing reply from proxy back into the tunnel");
 
        /*
         *      If there was a fake request associated with the proxied
@@ -812,36 +805,36 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
        /*
         *      Do the callback, if it exists, and if it was a success.
         */
-       if (fake && (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {
+       if (fake && (handler->request->proxy_reply->code == PW_CODE_ACCESS_ACCEPT)) {
                /*
                 *      Terrible hacks.
                 */
-               rad_assert(fake->packet == NULL);
-               fake->packet = request->proxy;
+               rad_assert(!fake->packet);
+               fake->packet = talloc_steal(fake, request->proxy);
                fake->packet->src_ipaddr = request->packet->src_ipaddr;
                request->proxy = NULL;
 
-               rad_assert(fake->reply == NULL);
-               fake->reply = request->proxy_reply;
+               rad_assert(!fake->reply);
+               fake->reply = talloc_steal(fake, request->proxy_reply);
                request->proxy_reply = NULL;
 
                if ((debug_flag > 0) && fr_log_fp) {
                        fprintf(fr_log_fp, "server %s {\n",
-                               (fake->server == NULL) ? "" : fake->server);
+                               (!fake->server) ? "" : fake->server);
                }
 
                /*
                 *      Perform a post-auth stage for the tunneled
                 *      session.
                 */
-               fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
+               fake->log.lvl &= ~RAD_REQUEST_OPTION_PROXY_EAP;
                rcode = rad_postauth(fake);
                RDEBUG2("post-auth returns %d", rcode);
 
                if ((debug_flag > 0) && fr_log_fp) {
                        fprintf(fr_log_fp, "} # server %s\n",
-                               (fake->server == NULL) ? "" : fake->server);
-                       
+                               (!fake->server) ? "" : fake->server);
+
                        RDEBUG("Final reply from tunneled session code %d",
                               fake->reply->code);
                        debug_pair_list(fake->reply->vps);
@@ -850,9 +843,9 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                /*
                 *      Terrible hacks.
                 */
-               request->proxy = fake->packet;
+               request->proxy = talloc_steal(request, fake->packet);
                fake->packet = NULL;
-               request->proxy_reply = fake->reply;
+               request->proxy_reply = talloc_steal(request, fake->reply);
                fake->reply = NULL;
 
                /*
@@ -860,25 +853,23 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                 */
 
                switch (rcode) {
-                case RLM_MODULE_FAIL:
-                       request_free(&fake);
+               case RLM_MODULE_FAIL:
+                       talloc_free(fake);
                        eaptls_fail(handler, 0);
                        return 0;
-                       break;
 
-                default:  /* Don't Do Anything */
-                       RDEBUG2("sGot reply %d",
+               default:  /* Don't Do Anything */
+                       RDEBUG2("Got reply %d",
                               request->proxy_reply->code);
                        break;
                }
        }
-       request_free(&fake);    /* robust if fake == NULL */
+       talloc_free(fake);      /* robust if !fake */
 
        /*
         *      Process the reply from the home server.
         */
-       rcode = process_reply(handler, tls_session, handler->request,
-                             handler->request->proxy_reply);
+       rcode = process_reply(handler, tls_session, handler->request, handler->request->proxy_reply);
 
        /*
         *      The proxy code uses the reply from the home server as
@@ -895,6 +886,7 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
        case RLM_MODULE_HANDLED:
                RDEBUG("Reply was handled");
                eaptls_request(handler->eap_ds, tls_session);
+               request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE;
                return 1;
 
        case RLM_MODULE_OK:
@@ -906,7 +898,7 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                return eaptls_success(handler, 0);
 
        default:
-               RDEBUG("Reply was unknown.");
+               RDEBUG("Reply was unknown");
                break;
        }
 
@@ -914,28 +906,19 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
        return 0;
 }
 
-
-/*
- *     Free a request.
- */
-static void my_request_free(void *data)
-{
-       REQUEST *request = (REQUEST *)data;
-
-       request_free(&request);
-}
-
+#endif /* WITH_PROXY */
 
 /*
  *     Process the "diameter" contents of the tunneled data.
  */
-int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
+int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session)
 {
-       int rcode = PW_AUTHENTICATION_REJECT;
+       int code = PW_CODE_ACCESS_REJECT;
+       rlm_rcode_t rcode;
        REQUEST *fake;
        VALUE_PAIR *vp;
        ttls_tunnel_t *t;
-       const uint8_t *data;
+       uint8_t const *data;
        size_t data_len;
        REQUEST *request = handler->request;
 
@@ -955,8 +938,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        if (data_len == 0) {
                if (t->authenticated) {
-                       RDEBUG("Got ACK, and the user was already authenticated.");
-                       return PW_AUTHENTICATION_ACK;
+                       RDEBUG("Got ACK, and the user was already authenticated");
+                       return PW_CODE_ACCESS_ACCEPT;
                } /* else no session, no data, die. */
 
                /*
@@ -964,7 +947,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                 *      wrong.
                 */
                RDEBUG2("SSL_read Error");
-               return PW_AUTHENTICATION_REJECT;
+               return PW_CODE_ACCESS_REJECT;
        }
 
 #ifndef NDEBUG
@@ -972,7 +955,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                size_t i;
 
                for (i = 0; i < data_len; i++) {
-                       if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data in %04x: ", i);
+                       if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data in %04x: ", (int) i);
 
                        fprintf(fr_log_fp, "%02x ", data[i]);
 
@@ -983,7 +966,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
 #endif
 
        if (!diameter_verify(request, data, data_len)) {
-               return PW_AUTHENTICATION_REJECT;
+               return PW_CODE_ACCESS_REJECT;
        }
 
        /*
@@ -991,24 +974,21 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        fake = request_alloc_fake(request);
 
-       rad_assert(fake->packet->vps == NULL);
+       rad_assert(!fake->packet->vps);
 
        /*
         *      Add the tunneled attributes to the fake request.
         */
-       fake->packet->vps = diameter2vp(request, tls_session->ssl, data, data_len);
+       fake->packet->vps = diameter2vp(request, fake, tls_session->ssl, data, data_len);
        if (!fake->packet->vps) {
-               request_free(&fake);
-               return PW_AUTHENTICATION_REJECT;
+               talloc_free(fake);
+               return PW_CODE_ACCESS_REJECT;
        }
 
        /*
         *      Tell the request that it's a fake one.
         */
-       vp = pairmake("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
-       if (vp) {
-               pairadd(&fake->packet->vps, vp);
-       }
+       pairmake_packet("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
 
        if ((debug_flag > 0) && fr_log_fp) {
                RDEBUG("Got tunneled request");
@@ -1019,8 +999,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        /*
         *      Update other items in the REQUEST data structure.
         */
-       fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
-       fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD);
+       fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
+       fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
 
        /*
         *      No User-Name, try to create one from stored data.
@@ -1031,22 +1011,25 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                 *      an EAP-Identity, and pull it out of there.
                 */
                if (!t->username) {
-                       vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE);
+                       vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
                        if (vp &&
                            (vp->length >= EAP_HEADER_LEN + 2) &&
                            (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
                            (vp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
                            (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
+                               char *p;
+
                                /*
                                 *      Create & remember a User-Name
                                 */
-                               t->username = pairmake("User-Name", "", T_OP_EQ);
+                               t->username = pairmake(t, NULL, "User-Name", NULL, T_OP_EQ);
                                rad_assert(t->username != NULL);
-
-                               memcpy(t->username->vp_strvalue, vp->vp_strvalue + 5,
-                                      vp->length - 5);
                                t->username->length = vp->length - 5;
-                               t->username->vp_strvalue[t->username->length] = 0;
+
+                               t->username->vp_strvalue = p = talloc_array(t->username, char,
+                                                                           t->username->length + 1);
+                               memcpy(p, vp->vp_octets + 5, t->username->length);
+                               p[t->username->length] = 0;
 
                                RDEBUG("Got tunneled identity of %s",
                                       t->username->vp_strvalue);
@@ -1055,12 +1038,11 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                                 *      If there's a default EAP type,
                                 *      set it here.
                                 */
-                               if (t->default_eap_type != 0) {
-                                       RDEBUG("Setting default EAP type for tunneled EAP session.");
-                                       vp = paircreate(PW_EAP_TYPE,
-                                                       PW_TYPE_INTEGER);
+                               if (t->default_method != 0) {
+                                       RDEBUG("Setting default EAP type for tunneled EAP session");
+                                       vp = paircreate(fake, PW_EAP_TYPE, 0);
                                        rad_assert(vp != NULL);
-                                       vp->vp_integer = t->default_eap_type;
+                                       vp->vp_integer = t->default_method;
                                        pairadd(&fake->config_items, vp);
                                }
 
@@ -1070,14 +1052,14 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                                 *      as it's permitted to do EAP without
                                 *      user-name.
                                 */
-                               RDEBUG2("WARNING! No EAP-Identity found to start EAP conversation.");
+                               RWDEBUG2("No EAP-Identity found to start EAP conversation");
                        }
                } /* else there WAS a t->username */
 
                if (t->username) {
-                       vp = paircopy(t->username);
+                       vp = paircopy(fake->packet, t->username);
                        pairadd(&fake->packet->vps, vp);
-                       fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
+                       fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0, TAG_ANY);
                }
        } /* else the request ALREADY had a User-Name */
 
@@ -1085,7 +1067,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         *      Add the State attribute, too, if it exists.
         */
        if (t->state) {
-               vp = paircopy(t->state);
+               vp = paircopy(fake->packet, t->state);
                if (vp) pairadd(&fake->packet->vps, vp);
        }
 
@@ -1098,14 +1080,15 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        if (t->copy_request_to_tunnel) {
                VALUE_PAIR *copy;
+               vp_cursor_t cursor;
 
-               for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+               for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) {
                        /*
                         *      The attribute is a server-side thingy,
                         *      don't copy it.
                         */
-                       if ((vp->attribute > 255) &&
-                           (((vp->attribute >> 16) & 0xffff) == 0)) {
+                       if ((vp->da->attr > 255) &&
+                           (vp->da->vendor == 0)) {
                                continue;
                        }
 
@@ -1118,14 +1101,14 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      AND attributes which are copied there
                         *      from below.
                         */
-                       if (pairfind(fake->packet->vps, vp->attribute)) {
+                       if (pairfind(fake->packet->vps, vp->da->attr, vp->da->vendor, TAG_ANY)) {
                                continue;
                        }
 
                        /*
                         *      Some attributes are handled specially.
                         */
-                       switch (vp->attribute) {
+                       switch (vp->da->attr) {
                                /*
                                 *      NEVER copy Message-Authenticator,
                                 *      EAP-Message, or State.  They're
@@ -1153,12 +1136,12 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      Don't copy from the head, we've already
                         *      checked it.
                         */
-                       copy = paircopy2(vp, vp->attribute);
+                       copy = paircopy2(fake->packet, vp, vp->da->attr, vp->da->vendor, TAG_ANY);
                        pairadd(&fake->packet->vps, copy);
                }
        }
 
-       if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER)) != NULL) {
+       if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
                fake->server = vp->vp_strvalue;
 
        } else if (t->virtual_server) {
@@ -1169,38 +1152,21 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
 
        if ((debug_flag > 0) && fr_log_fp) {
                RDEBUG("Sending tunneled request");
-
-               debug_pair_list(fake->packet->vps);
-
-               fprintf(fr_log_fp, "server %s {\n",
-                       (fake->server == NULL) ? "" : fake->server);
        }
 
        /*
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */
-       rad_authenticate(fake);
-
-       /*
-        *      Note that we don't do *anything* with the reply
-        *      attributes.
-        */
-       if ((debug_flag > 0) && fr_log_fp) {
-               fprintf(fr_log_fp, "} # server %s\n",
-                       (fake->server == NULL) ? "" : fake->server);
-
-               RDEBUG("Got tunneled reply code %d", fake->reply->code);
-               
-               debug_pair_list(fake->reply->vps);
-       }
+       rad_virtual_server(fake);
 
        /*
         *      Decide what to do with the reply.
         */
        switch (fake->reply->code) {
        case 0:                 /* No reply code, must be proxied... */
-               vp = pairfind(fake->config_items, PW_PROXY_TO_REALM);
+#ifdef WITH_PROXY
+               vp = pairfind(fake->config_items, PW_PROXY_TO_REALM, 0, TAG_ANY);
                if (vp) {
                        eap_tunnel_data_t *tunnel;
                        RDEBUG("Tunneled authentication will be proxied to %s", vp->vp_strvalue);
@@ -1209,16 +1175,22 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      Tell the original request that it's going
                         *      to be proxied.
                         */
-                       pairmove2(&(request->config_items),
-                                 &(fake->config_items),
-                                 PW_PROXY_TO_REALM);
+                       pairfilter(request, &request->config_items,
+                                 &fake->config_items,
+                                 PW_PROXY_TO_REALM, 0, TAG_ANY);
 
                        /*
                         *      Seed the proxy packet with the
                         *      tunneled request.
                         */
-                       rad_assert(request->proxy == NULL);
-                       request->proxy = fake->packet;
+                       rad_assert(!request->proxy);
+                       request->proxy = talloc_steal(request, fake->packet);
+                       memset(&request->proxy->src_ipaddr, 0,
+                              sizeof(request->proxy->src_ipaddr));
+                       memset(&request->proxy->src_ipaddr, 0,
+                              sizeof(request->proxy->src_ipaddr));
+                       request->proxy->src_port = 0;
+                       request->proxy->dst_port = 0;
                        fake->packet = NULL;
                        rad_free(&fake->reply);
                        fake->reply = NULL;
@@ -1226,20 +1198,16 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                        /*
                         *      Set up the callbacks for the tunnel
                         */
-                       tunnel = rad_malloc(sizeof(*tunnel));
-                       memset(tunnel, 0, sizeof(*tunnel));
-
+                       tunnel = talloc_zero(request, eap_tunnel_data_t);
                        tunnel->tls_session = tls_session;
                        tunnel->callback = eapttls_postproxy;
 
                        /*
                         *      Associate the callback with the request.
                         */
-                       rcode = request_data_add(request,
-                                                request->proxy,
-                                                REQUEST_DATA_EAP_TUNNEL_CALLBACK,
-                                                tunnel, free);
-                       rad_assert(rcode == 0);
+                       code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
+                                               tunnel, false);
+                       rad_assert(code == 0);
 
                        /*
                         *      rlm_eap.c has taken care of associating
@@ -1248,54 +1216,52 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      So we associate the fake request with
                         *      this request.
                         */
-                       rcode = request_data_add(request,
-                                                request->proxy,
-                                                REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
-                                                fake, my_request_free);
-                       rad_assert(rcode == 0);
+                       code = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
+                                               fake, true);
+                       rad_assert(code == 0);
                        fake = NULL;
 
                        /*
                         *      Didn't authenticate the packet, but
                         *      we're proxying it.
                         */
-                       rcode = PW_STATUS_CLIENT;
+                       code = PW_CODE_STATUS_CLIENT;
 
-               } else {
+               } else
+#endif /* WITH_PROXY */
+                 {
                        RDEBUG("No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
                               request->number);
-                       rcode = PW_AUTHENTICATION_REJECT;
+                       code = PW_CODE_ACCESS_REJECT;
                }
                break;
 
        default:
                /*
-                *      Returns RLM_MODULE_FOO, and we want to return
-                *      PW_FOO
+                *      Returns RLM_MODULE_FOO, and we want to return PW_FOO
                 */
-               rcode = process_reply(handler, tls_session, request,
-                                     fake->reply);
+               rcode = process_reply(handler, tls_session, request, fake->reply);
                switch (rcode) {
                case RLM_MODULE_REJECT:
-                       rcode = PW_AUTHENTICATION_REJECT;
+                       code = PW_CODE_ACCESS_REJECT;
                        break;
 
                case RLM_MODULE_HANDLED:
-                       rcode = PW_ACCESS_CHALLENGE;
+                       code = PW_CODE_ACCESS_CHALLENGE;
                        break;
 
                case RLM_MODULE_OK:
-                       rcode = PW_AUTHENTICATION_ACK;
+                       code = PW_CODE_ACCESS_ACCEPT;
                        break;
 
                default:
-                       rcode = PW_AUTHENTICATION_REJECT;
+                       code = PW_CODE_ACCESS_REJECT;
                        break;
                }
                break;
        }
 
-       request_free(&fake);
+       talloc_free(fake);
 
-       return rcode;
+       return code;
 }