*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
*/
-#include "rlm_eap_tls.h"
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
#include "eap_ttls.h"
/*
/*
* Verify that the diameter packet is valid.
*/
-static int diameter_verify(const uint8_t *data, unsigned int data_len)
+static int diameter_verify(REQUEST *request,
+ const uint8_t *data, unsigned int data_len)
{
uint32_t attr;
uint32_t length;
unsigned int data_left = data_len;
while (data_left > 0) {
+ if (data_len < 12) {
+ RDEBUG2(" Diameter attribute is too small to contain a Diameter header");
+ return 0;
+ }
+
rad_assert(data_left <= data_len);
memcpy(&attr, data, sizeof(attr));
data += 4;
attr = ntohl(attr);
if (attr > 255) {
- DEBUG2(" rlm_eap_ttls: Non-RADIUS attribute in tunneled authentication is not supported");
+ RDEBUG2(" Non-RADIUS attribute in tunneled authentication is not supported");
return 0;
}
*/
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) {
- DEBUG2(" rlm_eap_ttls: Vendor codes larger than 65535 are not supported");
+ if (vendor > FR_MAX_VENDOR) {
+ RDEBUG2("Vendor codes larger than 2^24 are not supported");
return 0;
}
- attribute = (vendor << 16) | attr;
-
- da = dict_attrbyvalue(attribute);
+ da = dict_attrbyvalue(attr, vendor);
/*
* SHOULD check ((length & (1 << 30)) != 0)
* for the mandatory bit.
*/
if (!da) {
- DEBUG2(" rlm_eap_ttls: Fatal! Vendor %u, Attribute %u was not found in our dictionary. ",
+ RDEBUG2("Fatal! Vendor %u, Attribute %u was not found in our dictionary. ",
vendor, attr);
return 0;
}
/*
* Too short or too long is bad.
- *
- * FIXME: EAP-Message
*/
if (length < offset) {
- DEBUG2(" rlm_eap_ttls: Tunneled attribute %d is too short (%d)to contain anything useful.", attr, length);
+ RDEBUG2("Tunneled attribute %d is too short (%d)to contain anything useful.", attr, length);
return 0;
}
- if (length > (MAX_STRING_LEN + 8)) {
- DEBUG2(" rlm_eap_ttls: Tunneled attribute %d is too long (%d) to pack into a RADIUS attribute.", attr, length);
+ /*
+ * 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);
return 0;
}
-
+
if (length > data_left) {
- DEBUG2(" rlm_eap_ttls: Tunneled attribute %d is longer than room left in the packet (%d > %d).", attr, length, data_left);
+ RDEBUG2("Tunneled attribute %d is longer than room left in the packet (%d > %d).", attr, length, data_left);
return 0;
}
* of the packet, die.
*/
if (data_left < length) {
- DEBUG2(" rlm_eap_ttls: ERROR! Diameter attribute overflows packet!");
+ RDEBUG2("ERROR! Diameter attribute overflows packet!");
return 0;
}
-
+
/*
* Check again for equality, now that we're padded
* length to a multiple of 4 octets.
/*
* Convert diameter attributes to our VALUE_PAIR's
*/
-static VALUE_PAIR *diameter2vp(SSL *ssl,
- const uint8_t *data, unsigned int data_len)
+static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
+ const uint8_t *data, size_t data_len)
{
uint32_t attr;
+ uint32_t vendor;
uint32_t length;
- unsigned int offset;
- int size;
- unsigned int data_left = data_len;
+ size_t offset;
+ size_t size;
+ size_t data_left = data_len;
VALUE_PAIR *first = NULL;
VALUE_PAIR **last = &first;
VALUE_PAIR *vp;
memcpy(&attr, data, sizeof(attr));
data += 4;
attr = ntohl(attr);
+ vendor = 0;
memcpy(&length, data, sizeof(length));
data += 4;
length = ntohl(length);
/*
- * Ignore the M bit. We support all RADIUS attributes...
- */
-
- /*
* A "vendor" flag, with a vendor ID of zero,
* is equivalent to no vendor. This is stupid.
*/
offset = 8;
if ((length & (1 << 31)) != 0) {
- uint32_t vendor;
-
memcpy(&vendor, data, sizeof(vendor));
vendor = ntohl(vendor);
- attr |= (vendor << 16);
+ if (vendor > FR_MAX_VENDOR) {
+ RDEBUG2("Cannot handle vendor Id greater than 2^&24");
+ pairfree(&first);
+ return NULL;
+ }
data += 4; /* skip the vendor field, it's zero */
offset += 4; /* offset to value field */
}
/*
- * Get the length.
+ * Vendor attributes can be larger than 255.
+ * Normal attributes cannot be.
*/
- length &= 0x00ffffff;
+ if ((attr > 255) && (vendor == 0)) {
+ RDEBUG2("Cannot handle Diameter attributes");
+ pairfree(&first);
+ return NULL;
+ }
/*
- * diameter code + length, and it must fit in
- * a VALUE_PAIR.
+ * FIXME: Handle the M bit. For now, we assume that
+ * some other module takes care of any attribute
+ * with the M bit set.
+ */
+
+ /*
+ * Get the length.
*/
- rad_assert(length <= (offset + MAX_STRING_LEN));
+ length &= 0x00ffffff;
/*
* Get the size of the value portion of the
/*
* Create it.
*/
- vp = paircreate(attr, PW_TYPE_OCTETS);
+ vp = paircreate(attr, vendor, PW_TYPE_OCTETS);
if (!vp) {
- DEBUG2(" rlm_eap_ttls: Failure in creating VP");
+ RDEBUG2("Failure in creating VP");
pairfree(&first);
return NULL;
}
case PW_TYPE_INTEGER:
case PW_TYPE_DATE:
if (size != vp->length) {
- DEBUG2(" rlm_eap_ttls: Invalid length attribute %d",
+ RDEBUG2("Invalid length attribute %d",
attr);
pairfree(&first);
+ pairfree(&vp);
return NULL;
}
- memcpy(&vp->lvalue, data, vp->length);
-
+ memcpy(&vp->vp_integer, data, vp->length);
+
/*
* Stored in host byte order: change it.
*/
- vp->lvalue = ntohl(vp->lvalue);
+ vp->vp_integer = ntohl(vp->vp_integer);
break;
-
+
case PW_TYPE_IPADDR:
if (size != vp->length) {
- DEBUG2(" rlm_eap_ttls: Invalid length attribute %d",
+ RDEBUG2("Invalid length attribute %d",
attr);
pairfree(&first);
+ pairfree(&vp);
return NULL;
}
- memcpy(&vp->lvalue, data, vp->length);
-
+ memcpy(&vp->vp_ipaddr, data, vp->length);
+
/*
* Stored in network byte order: don't change it.
*/
* FIXME: Ipv6 attributes ?
*
*/
+ case PW_TYPE_OCTETS:
+ if (attr == PW_EAP_MESSAGE) {
+ const uint8_t *eap_message = data;
+
+ /*
+ * 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, vendor, PW_TYPE_OCTETS);
+ if (!vp) {
+ RDEBUG2("Failure in creating VP");
+ pairfree(&first);
+ return NULL;
+ }
+ }
+
+ goto next_attr;
+ } /* else it's another kind of attribute */
+ /* FALL-THROUGH */
+
default:
vp->length = size;
memcpy(vp->vp_strvalue, data, vp->length);
*/
switch (vp->attribute) {
case PW_USER_PASSWORD:
- rad_assert(vp->length <= 128); /* RFC requirements */
-
/*
* If the password is exactly 16 octets,
* it won't be zero-terminated.
case PW_MSCHAP_CHALLENGE:
if ((vp->length < 8) ||
(vp->length > 16)) {
- DEBUG2(" TTLS: Tunneled challenge has invalid length");
+ RDEBUG("Tunneled challenge has invalid length");
pairfree(&first);
+ pairfree(&vp);
return NULL;
} else {
- int i;
uint8_t challenge[16];
eapttls_gen_challenge(ssl, challenge,
sizeof(challenge));
- for (i = 0; i < vp->length; i++) {
- if (challenge[i] != vp->vp_strvalue[i]) {
- DEBUG2(" TTLS: Tunneled challenge is incorrect");
- pairfree(&first);
- return NULL;
- }
+ if (memcmp(challenge, vp->vp_octets,
+ vp->length) != 0) {
+ RDEBUG("Tunneled challenge is incorrect");
+ pairfree(&first);
+ pairfree(&vp);
+ return NULL;
}
}
break;
*last = vp;
last = &(vp->next);
+ next_attr:
/*
* Catch non-aligned attributes.
*/
* are ones which can go inside of a RADIUS (i.e. diameter)
* packet. So no server-configuration attributes, or the like.
*/
-static int vp2diameter(tls_session_t *tls_session, VALUE_PAIR *first)
+static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *first)
{
/*
* RADIUS packets are no more than 4k in size, so if
* Too much data: die.
*/
if ((total + vp->length + 12) >= sizeof(buffer)) {
- DEBUG2(" TTLS output buffer is full!");
+ RDEBUG2("output buffer is full!");
return 0;
}
* issues.
*/
length = vp->length;
- vendor = (vp->attribute >> 16) & 0xffff;
+ vendor = vp->vendor;
if (vendor != 0) {
attr = vp->attribute & 0xffff;
length |= (1 << 31);
switch (vp->type) {
case PW_TYPE_INTEGER:
case PW_TYPE_DATE:
- attr = ntohl(vp->lvalue); /* stored in host order */
+ attr = ntohl(vp->vp_integer); /* stored in host order */
memcpy(p, &attr, sizeof(attr));
length = 4;
break;
case PW_TYPE_IPADDR:
- attr = vp->lvalue; /* stored in network order */
- memcpy(p, &attr, sizeof(attr));
+ memcpy(p, &vp->vp_ipaddr, 4); /* network order */
length = 4;
break;
* Align the data to a multiple of 4 bytes.
*/
if ((total & 0x03) != 0) {
- unsigned int i;
+ size_t i;
length = 4 - (total & 0x03);
for (i = 0; i < length; i++) {
*/
if (total > 0) {
#ifndef NDEBUG
- unsigned int i;
+ size_t i;
- if (debug_flag > 2) {
+ if ((debug_flag > 2) && fr_log_fp) {
for (i = 0; i < total; i++) {
- if ((i & 0x0f) == 0) printf(" TTLS tunnel data out %04x: ", i);
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " TTLS tunnel data out %04x: ", (int) i);
- printf("%02x ", buffer[i]);
+ fprintf(fr_log_fp, "%02x ", buffer[i]);
- if ((i & 0x0f) == 0x0f) printf("\n");
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
}
- if ((total & 0x0f) != 0) printf("\n");
+ if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n");
}
#endif
/*
* FIXME: Check the return code.
*/
- tls_handshake_send(tls_session);
+ tls_handshake_send(request, tls_session);
}
/*
ttls_tunnel_t *t = tls_session->opaque;
handler = handler; /* -Wunused */
+ rad_assert(request != NULL);
+ rad_assert(handler->request == request);
/*
* If the response packet was Access-Accept, then
*/
switch (reply->code) {
case PW_AUTHENTICATION_ACK:
- DEBUG2(" TTLS: Got tunneled Access-Accept");
+ RDEBUG("Got tunneled Access-Accept");
rcode = RLM_MODULE_OK;
* packet, and we will send EAP-Success.
*/
vp = NULL;
- pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS);
+ pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT);
if (vp) {
-#if 1
- /*
- * FIXME: Tunneling MS-CHAP2-Success causes
- * the only client we have access to, to die.
- *
- * We don't want that...
- */
- pairfree(&vp);
-#else
- DEBUG2(" TTLS: 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;
-#endif
+
+ /*
+ * Delete MPPE keys & encryption policy. We don't
+ * want these here.
+ */
+ pairdelete(&reply->vps, 7, VENDORPEC_MICROSOFT);
+ pairdelete(&reply->vps, 8, VENDORPEC_MICROSOFT);
+ pairdelete(&reply->vps, 16, VENDORPEC_MICROSOFT);
+ pairdelete(&reply->vps, 17, VENDORPEC_MICROSOFT);
+
+ /*
+ * Use the tunneled reply, but not now.
+ */
+ if (t->use_tunneled_reply) {
+ t->accept_vps = reply->vps;
+ reply->vps = NULL;
+ }
+
} else { /* no MS-CHAP2-Success */
/*
* Can only have EAP-Message if there's
* can figure it out, from the non-tunneled
* EAP-Success packet.
*/
- pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+ pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE, 0);
pairfree(&vp);
}
* VP's back to the client.
*/
if (vp) {
- vp2diameter(tls_session, vp);
+ vp2diameter(request, tls_session, vp);
pairfree(&vp);
}
* tunneled user!
*/
if (t->use_tunneled_reply) {
- pairdelete(&reply->vps, PW_PROXY_STATE);
+ pairdelete(&reply->vps, PW_PROXY_STATE, 0);
pairadd(&request->reply->vps, reply->vps);
reply->vps = NULL;
}
case PW_AUTHENTICATION_REJECT:
- DEBUG2(" TTLS: Got tunneled Access-Reject");
+ RDEBUG("Got tunneled Access-Reject");
rcode = RLM_MODULE_REJECT;
break;
* a Reply-Message to the client.
*/
case PW_ACCESS_CHALLENGE:
- DEBUG2(" TTLS: Got tunneled Access-Challenge");
+ RDEBUG("Got tunneled Access-Challenge");
/*
* Keep the State attribute, if necessary.
* Get rid of the old State, too.
*/
pairfree(&t->state);
- pairmove2(&t->state, &reply->vps, PW_STATE);
+ pairmove2(&t->state, &reply->vps, PW_STATE, 0);
/*
* We should really be a bit smarter about this,
* method works in 99.9% of the situations.
*/
vp = NULL;
- pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+ pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE, 0);
/*
* There MUST be a Reply-Message in the challenge,
* we MUST create one, with an empty string as
* it's value.
*/
- pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE);
+ pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE, 0);
/*
* Handle the ACK, by tunneling any necessary reply
* VP's back to the client.
*/
if (vp) {
- vp2diameter(tls_session, vp);
+ vp2diameter(request, tls_session, vp);
pairfree(&vp);
}
rcode = RLM_MODULE_HANDLED;
break;
default:
- DEBUG2(" TTLS: Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
+ RDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
rcode = RLM_MODULE_INVALID;
break;
}
}
+#ifdef WITH_PROXY
/*
* Do post-proxy processing,
*/
{
int rcode;
tls_session_t *tls_session = (tls_session_t *) data;
- REQUEST *fake;
+ REQUEST *fake, *request = handler->request;
- DEBUG2(" TTLS: Passing reply from proxy back into the tunnel.");
+ rad_assert(request != NULL);
+ RDEBUG("Passing reply from proxy back into the tunnel.");
/*
* If there was a fake request associated with the proxied
fake = (REQUEST *) request_data_get(handler->request,
handler->request->proxy,
REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
-
+
/*
* Do the callback, if it exists, and if it was a success.
*/
if (fake && (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {
- VALUE_PAIR *vp;
- REQUEST *request = handler->request;
-
/*
* Terrible hacks.
*/
rad_assert(fake->packet == NULL);
fake->packet = request->proxy;
+ fake->packet->src_ipaddr = request->packet->src_ipaddr;
request->proxy = NULL;
rad_assert(fake->reply == NULL);
fake->reply = 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);
+ }
+
/*
* Perform a post-auth stage for the tunneled
* session.
*/
fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
rcode = rad_postauth(fake);
- DEBUG2(" POST-AUTH %d", rcode);
+ RDEBUG2("post-auth returns %d", rcode);
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" TTLS: Final reply from tunneled session code %d\n",
- fake->reply->code);
+ if ((debug_flag > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "} # server %s\n",
+ (fake->server == NULL) ? "" : fake->server);
- for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ RDEBUG("Final reply from tunneled session code %d",
+ fake->reply->code);
+ debug_pair_list(fake->reply->vps);
}
-#endif
/*
* Terrible hacks.
switch (rcode) {
case RLM_MODULE_FAIL:
request_free(&fake);
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
break;
-
+
default: /* Don't Do Anything */
- DEBUG2(" TTLS: Got reply %d",
+ RDEBUG2("Got reply %d",
request->proxy_reply->code);
break;
- }
+ }
}
request_free(&fake); /* robust if fake == NULL */
switch (rcode) {
case RLM_MODULE_REJECT:
- DEBUG2(" TTLS: Reply was rejected");
+ RDEBUG("Reply was rejected");
break;
case RLM_MODULE_HANDLED:
- DEBUG2(" TTLS: Reply was handled");
+ RDEBUG("Reply was handled");
eaptls_request(handler->eap_ds, tls_session);
return 1;
case RLM_MODULE_OK:
- DEBUG2(" TTLS: Reply was OK");
- eaptls_success(handler->eap_ds, 0);
- eaptls_gen_mppe_keys(&handler->request->reply->vps,
- tls_session->ssl,
- "ttls keying material");
- return 1;
+ RDEBUG("Reply was OK");
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ return eaptls_success(handler, 0);
default:
- DEBUG2(" TTLS: Reply was unknown.");
+ RDEBUG("Reply was unknown.");
break;
}
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
}
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 err;
int rcode = PW_AUTHENTICATION_REJECT;
REQUEST *fake;
VALUE_PAIR *vp;
ttls_tunnel_t *t;
const uint8_t *data;
- unsigned int data_len;
- char buffer[1024];
+ size_t data_len;
REQUEST *request = handler->request;
- /*
- * Grab the dirty data, and copy it to our buffer.
- *
- * I *really* don't like these 'record_t' things...
- */
- data_len = (tls_session->record_minus)(&tls_session->dirty_in, buffer, sizeof(buffer));
- data = buffer;
-
- /*
- * Write the data from the dirty buffer (i.e. packet
- * data) into the buffer which we will give to SSL for
- * decoding.
- *
- * Some of this code COULD technically go into the TLS
- * module, in eaptls_process(), where it returns EAPTLS_OK.
- *
- * Similarly, the writing of data to the SSL context could
- * go there, too...
- */
- BIO_write(tls_session->into_ssl, buffer, data_len);
- (tls_session->record_init)(&tls_session->clean_out);
+ rad_assert(request != NULL);
/*
- * Read (and decrypt) the tunneled data from the SSL session,
- * and put it into the decrypted data buffer.
+ * Just look at the buffer directly, without doing
+ * record_minus.
*/
- err = SSL_read(tls_session->ssl, tls_session->clean_out.data,
- sizeof(tls_session->clean_out.data));
- if (err < 0) {
- /*
- * FIXME: Call SSL_get_error() to see what went
- * wrong.
- */
- radlog(L_INFO, "rlm_eap_ttls: SSL_read Error");
- return PW_AUTHENTICATION_REJECT;
- }
+ data_len = tls_session->clean_out.used;
+ tls_session->clean_out.used = 0;
+ data = tls_session->clean_out.data;
t = (ttls_tunnel_t *) tls_session->opaque;
* If there's no data, maybe this is an ACK to an
* MS-CHAP2-Success.
*/
- if (err == 0) {
+ if (data_len == 0) {
if (t->authenticated) {
- DEBUG2(" TTLS: Got ACK, and the user was already authenticated.");
+ RDEBUG("Got ACK, and the user was already authenticated.");
return PW_AUTHENTICATION_ACK;
} /* else no session, no data, die. */
* FIXME: Call SSL_get_error() to see what went
* wrong.
*/
- radlog(L_INFO, "rlm_eap_ttls: SSL_read Error");
+ RDEBUG2("SSL_read Error");
return PW_AUTHENTICATION_REJECT;
}
- data_len = tls_session->clean_out.used = err;
- data = tls_session->clean_out.data;
-
#ifndef NDEBUG
- if (debug_flag > 2) {
- unsigned int i;
+ if ((debug_flag > 2) && fr_log_fp) {
+ size_t i;
for (i = 0; i < data_len; i++) {
- if ((i & 0x0f) == 0) printf(" TTLS tunnel data in %04x: ", i);
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " TTLS tunnel data in %04x: ", (int) i);
- printf("%02x ", data[i]);
+ fprintf(fr_log_fp, "%02x ", data[i]);
- if ((i & 0x0f) == 0x0f) printf("\n");
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
}
- if ((data_len & 0x0f) != 0) printf("\n");
+ if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
}
#endif
- if (!diameter_verify(data, data_len)) {
+ if (!diameter_verify(request, data, data_len)) {
return PW_AUTHENTICATION_REJECT;
}
/*
* Add the tunneled attributes to the fake request.
*/
- fake->packet->vps = diameter2vp(tls_session->ssl, data, data_len);
+ fake->packet->vps = diameter2vp(request, tls_session->ssl, data, data_len);
if (!fake->packet->vps) {
+ request_free(&fake);
return PW_AUTHENTICATION_REJECT;
}
pairadd(&fake->packet->vps, vp);
}
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" TTLS: Got tunneled request\n");
-
- for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ if ((debug_flag > 0) && fr_log_fp) {
+ RDEBUG("Got tunneled request");
+
+ debug_pair_list(fake->packet->vps);
}
-#endif
/*
* Update other items in the REQUEST data structure.
*/
- fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
- fake->password = pairfind(fake->packet->vps, PW_PASSWORD);
+ fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0);
+ fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD, 0);
/*
* No User-Name, try to create one from stored data.
* 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);
if (vp &&
(vp->length >= EAP_HEADER_LEN + 2) &&
(vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
t->username->length = vp->length - 5;
t->username->vp_strvalue[t->username->length] = 0;
- DEBUG2(" TTLS: Got tunneled identity of %s",
+ RDEBUG("Got tunneled identity of %s",
t->username->vp_strvalue);
/*
* set it here.
*/
if (t->default_eap_type != 0) {
- DEBUG2(" TTLS: Setting default EAP type for tunneled EAP session.");
- vp = paircreate(PW_EAP_TYPE,
+ RDEBUG("Setting default EAP type for tunneled EAP session.");
+ vp = paircreate(PW_EAP_TYPE, 0,
PW_TYPE_INTEGER);
rad_assert(vp != NULL);
- vp->lvalue = t->default_eap_type;
+ vp->vp_integer = t->default_eap_type;
pairadd(&fake->config_items, vp);
}
* as it's permitted to do EAP without
* user-name.
*/
- DEBUG2(" rlm_eap_ttls: WARNING! No EAP-Identity found to start EAP conversation.");
+ RDEBUG2("WARNING! No EAP-Identity found to start EAP conversation.");
}
} /* else there WAS a t->username */
if (t->username) {
vp = paircopy(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);
}
} /* else the request ALREADY had a User-Name */
* Add the State attribute, too, if it exists.
*/
if (t->state) {
- DEBUG2(" TTLS: Adding old state with %02x %02x",
- t->state->vp_strvalue[0], t->state->vp_strvalue[1]);
vp = paircopy(t->state);
if (vp) pairadd(&fake->packet->vps, vp);
}
* don't copy it.
*/
if ((vp->attribute > 255) &&
- (((vp->attribute >> 16) & 0xffff) == 0)) {
+ (vp->vendor == 0)) {
continue;
}
* AND attributes which are copied there
* from below.
*/
- if (pairfind(fake->packet->vps, vp->attribute)) {
+ if (pairfind(fake->packet->vps, vp->attribute, vp->vendor)) {
continue;
}
* Don't copy from the head, we've already
* checked it.
*/
- copy = paircopy2(vp, vp->attribute);
+ copy = paircopy2(vp, vp->attribute, vp->vendor);
pairadd(&fake->packet->vps, copy);
}
}
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" TTLS: Sending tunneled request\n");
+ if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0)) != NULL) {
+ fake->server = vp->vp_strvalue;
+
+ } else if (t->virtual_server) {
+ fake->server = t->virtual_server;
+
+ } /* else fake->server == request->server */
+
- for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ 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);
}
-#endif
/*
* Call authentication recursively, which will
* Note that we don't do *anything* with the reply
* attributes.
*/
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" TTLS: Got tunneled reply RADIUS code %d\n",
- fake->reply->code);
+ if ((debug_flag > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "} # server %s\n",
+ (fake->server == NULL) ? "" : fake->server);
- for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ RDEBUG("Got tunneled reply code %d", fake->reply->code);
+
+ debug_pair_list(fake->reply->vps);
}
-#endif
/*
* 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);
if (vp) {
eap_tunnel_data_t *tunnel;
- DEBUG2(" TTLS: Tunneled authentication will be proxied to %s", vp->vp_strvalue);
+ RDEBUG("Tunneled authentication will be proxied to %s", vp->vp_strvalue);
/*
* Tell the original request that it's going
*/
pairmove2(&(request->config_items),
&(fake->config_items),
- PW_PROXY_TO_REALM);
+ PW_PROXY_TO_REALM, 0);
/*
* Seed the proxy packet with the
*/
rad_assert(request->proxy == NULL);
request->proxy = 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;
REQUEST_DATA_EAP_TUNNEL_CALLBACK,
tunnel, free);
rad_assert(rcode == 0);
-
+
/*
* rlm_eap.c has taken care of associating
* the handler with the fake request.
*/
rcode = PW_STATUS_CLIENT;
- } else {
- DEBUG2(" TTLS: No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
+ } 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;
}
case RLM_MODULE_REJECT:
rcode = PW_AUTHENTICATION_REJECT;
break;
-
+
case RLM_MODULE_HANDLED:
rcode = PW_ACCESS_CHALLENGE;
break;
-
+
case RLM_MODULE_OK:
rcode = PW_AUTHENTICATION_ACK;
break;
-
+
default:
rcode = PW_AUTHENTICATION_REJECT;
break;