/*
- * peap.c contains the interfaces that are called from eap
+ * peap.c contains the interfaces that are called from eap
*
* Version: $Id$
*
static int eappeap_failure(EAP_HANDLER *handler, tls_session_t *tls_session)
{
uint8_t tlv_packet[11];
+ REQUEST *request = handler->request;
- DEBUG2(" rlm_eap_peap: FAILURE");
+ RDEBUG2("FAILURE");
tlv_packet[0] = PW_EAP_REQUEST;
tlv_packet[1] = handler->eap_ds->response->id +1;
/*
* FIXME: Check the return code.
*/
- tls_handshake_send(tls_session);
+ tls_handshake_send(request, tls_session);
return 1;
}
static int eappeap_success(EAP_HANDLER *handler, tls_session_t *tls_session)
{
uint8_t tlv_packet[11];
+ REQUEST *request = handler->request;
- DEBUG2(" rlm_eap_peap: SUCCESS");
+ RDEBUG2("SUCCESS");
tlv_packet[0] = PW_EAP_REQUEST;
tlv_packet[1] = handler->eap_ds->response->id +1;
/*
* FIXME: Check the return code.
*/
- tls_handshake_send(tls_session);
+ tls_handshake_send(request, tls_session);
+
+ return 1;
+}
+
+
+static int eappeap_identity(EAP_HANDLER *handler, tls_session_t *tls_session)
+{
+ eap_packet_t eap_packet;
+
+ eap_packet.code = PW_EAP_REQUEST;
+ eap_packet.id = handler->eap_ds->response->id + 1;
+ eap_packet.length[0] = 0;
+ eap_packet.length[1] = EAP_HEADER_LEN + 1;
+ eap_packet.data[0] = PW_EAP_IDENTITY;
+
+ (tls_session->record_plus)(&tls_session->clean_in,
+ &eap_packet, sizeof(eap_packet));
+
+ tls_handshake_send(handler->request, tls_session);
+ (tls_session->record_init)(&tls_session->clean_in);
return 1;
}
/*
* Verify the tunneled EAP message.
*/
-static int eapmessage_verify(const uint8_t *data, unsigned int data_len)
+static int eapmessage_verify(REQUEST *request,
+ const uint8_t *data, unsigned int data_len)
{
const eap_packet_t *eap_packet = (const eap_packet_t *) data;
uint8_t eap_type;
- char identity[256];
+ char buffer[256];
- if (!data || (data_len <= 1)) {
+ /*
+ * No data, OR only 1 byte of EAP type.
+ */
+ if (!data || (data_len == 0) ||
+ ((data_len <= 1) && (data[0] != PW_EAP_IDENTITY))) {
return 0;
}
eap_type = *data;
switch (eap_type) {
case PW_EAP_IDENTITY:
- memcpy(identity, data + 1, data_len - 1);
- identity[data_len - 1] = '\0';
- DEBUG2(" rlm_eap_peap: Identity - %s", identity);
+ if (data_len == 1) {
+ RDEBUG2("Identity - ");
+ return 1;
+ }
+ RDEBUG2("Identity - %*s",
+ data_len - 1, data + 1);
return 1;
break;
*/
case PW_EAP_RESPONSE:
if (eap_packet->data[0] == PW_EAP_TLV) {
- DEBUG2(" rlm_eap_peap: Received EAP-TLV response.");
+ RDEBUG2("Received EAP-TLV response.");
return 1;
}
- DEBUG2(" rlm_eap_peap: Got something weird.");
+ RDEBUG2("Got something weird.");
break;
*/
case PW_EAP_MSCHAPV2:
default:
- DEBUG2(" rlm_eap_peap: EAP type %s",
+ RDEBUG2("EAP type %s",
eaptype_type2name(eap_type,
- identity, sizeof(identity)));
+ buffer, sizeof(buffer)));
return 1;
break;
}
/*
* Convert a pseudo-EAP packet to a list of VALUE_PAIR's.
*/
-static VALUE_PAIR *eap2vp(EAP_DS *eap_ds,
- const uint8_t *data, unsigned int data_len)
+static VALUE_PAIR *eap2vp(REQUEST *request, EAP_DS *eap_ds,
+ const uint8_t *data, size_t data_len)
{
- int total;
+ size_t total;
VALUE_PAIR *vp = NULL, *head, **tail;
- vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
+ if (data_len > 65535) return NULL; /* paranoia */
+
+ vp = paircreate(PW_EAP_MESSAGE, 0, PW_TYPE_OCTETS);
if (!vp) {
- DEBUG2(" rlm_eap_peap: Failure in creating VP");
+ RDEBUG2("Failure in creating VP");
return NULL;
}
*/
vp->vp_octets[0] = PW_EAP_RESPONSE;
vp->vp_octets[1] = eap_ds->response->id;
- vp->vp_octets[2] = 0;
- vp->vp_octets[3] = EAP_HEADER_LEN + total;
+ vp->vp_octets[2] = (data_len + EAP_HEADER_LEN) >> 8;
+ vp->vp_octets[3] = (data_len + EAP_HEADER_LEN) & 0xff;
memcpy(vp->vp_octets + EAP_HEADER_LEN, data, total);
vp->length = EAP_HEADER_LEN + total;
head = vp;
+ tail = &(vp->next);
while (total < data_len) {
int vp_len;
- tail = &(vp->next);
- vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
+ vp = paircreate(PW_EAP_MESSAGE, 0, PW_TYPE_OCTETS);
if (!vp) {
- DEBUG2(" rlm_eap_peap: Failure in creating VP");
+ RDEBUG2("Failure in creating VP");
pairfree(&head);
return NULL;
}
vp->length = vp_len;
total += vp_len;
+ *tail = vp;
+ tail = &(vp->next);
}
return head;
* Convert a list of VALUE_PAIR's to an EAP packet, through the
* simple expedient of dumping the EAP message
*/
-static int vp2eap(tls_session_t *tls_session, VALUE_PAIR *vp)
+static int vp2eap(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *vp)
{
/*
* Skip the id, code, and length. Just write the EAP
* type & data to the client.
*/
#ifndef NDEBUG
- if (debug_flag > 2) {
- int i, total;
+ if ((debug_flag > 2) && fr_log_fp) {
+ size_t i, total;
VALUE_PAIR *this;
total = 0;
if (this == vp) start = EAP_HEADER_LEN;
for (i = start; i < vp->length; i++) {
- if ((total & 0x0f) == 0) printf(" PEAP tunnel data out %04x: ", total);
+ if ((total & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data out %04x: ", (int) total);
- printf("%02x ", vp->vp_octets[i]);
+ fprintf(fr_log_fp, "%02x ", vp->vp_octets[i]);
- if ((total & 0x0f) == 0x0f) printf("\n");
+ if ((total & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
total++;
}
}
- if ((total & 0x0f) != 0) printf("\n");
+ if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n");
}
#endif
vp->vp_octets, vp->length);
}
- tls_handshake_send(tls_session);
+ tls_handshake_send(request, tls_session);
return 1;
}
/*
* See if there's a TLV in the response.
*/
-static int eappeap_check_tlv(const uint8_t *data)
+static int eappeap_check_tlv(REQUEST *request, const uint8_t *data)
{
const eap_packet_t *eap_packet = (const eap_packet_t *) data;
}
if (data[10] == EAP_TLV_FAILURE) {
- DEBUG2(" rlm_eap_peap: Client rejected our response. The password is probably incorrect.");
+ RDEBUG2("Client rejected our response. The password is probably incorrect.");
return 0;
}
}
* Use a reply packet to determine what to do.
*/
static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
- UNUSED REQUEST *request, RADIUS_PACKET *reply)
+ REQUEST *request, RADIUS_PACKET *reply)
{
int rcode = RLM_MODULE_REJECT;
VALUE_PAIR *vp;
peap_tunnel_t *t = tls_session->opaque;
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" PEAP: Processing from tunneled session code %p %d\n",
- reply, reply->code);
+ if ((debug_flag > 0) && fr_log_fp) {
+ RDEBUG("Got tunneled reply RADIUS code %d",
+ reply->code);
- for (vp = reply->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ debug_pair_list(reply->vps);
}
-#endif
switch (reply->code) {
case PW_AUTHENTICATION_ACK:
- DEBUG2(" PEAP: Tunneled authentication was successful.");
+ RDEBUG2("Tunneled authentication was successful.");
t->status = PEAP_STATUS_SENT_TLV_SUCCESS;
eappeap_success(handler, tls_session);
rcode = RLM_MODULE_HANDLED;
* tunneled user!
*/
if (t->use_tunneled_reply) {
- DEBUG2(" Saving tunneled attributes for later");
+ RDEBUG2("Saving tunneled attributes for later");
/*
* Clean up the tunneled reply.
*/
- pairdelete(&reply->vps, PW_PROXY_STATE);
- pairdelete(&reply->vps, PW_EAP_MESSAGE);
- pairdelete(&reply->vps, PW_MESSAGE_AUTHENTICATOR);
+ pairdelete(&reply->vps, PW_PROXY_STATE, 0);
+ pairdelete(&reply->vps, PW_EAP_MESSAGE, 0);
+ pairdelete(&reply->vps, PW_MESSAGE_AUTHENTICATOR, 0);
+
+ /*
+ * 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);
t->accept_vps = reply->vps;
reply->vps = NULL;
break;
case PW_AUTHENTICATION_REJECT:
- DEBUG2(" PEAP: Tunneled authentication was rejected.");
+ RDEBUG2("Tunneled authentication was rejected.");
t->status = PEAP_STATUS_SENT_TLV_FAILURE;
eappeap_failure(handler, tls_session);
rcode = RLM_MODULE_HANDLED;
break;
case PW_ACCESS_CHALLENGE:
- DEBUG2(" PEAP: Got tunneled Access-Challenge");
+ RDEBUG2("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);
/*
* PEAP takes only EAP-Message attributes inside
* Access-Challenge is ignored.
*/
vp = NULL;
- pairmove2(&vp, &(reply->vps), PW_EAP_MESSAGE);
+ pairmove2(&vp, &(reply->vps), PW_EAP_MESSAGE, 0);
/*
* Handle EAP-MSCHAP-V2, where Access-Accept's
* an "ack" packet.
*/
if (t->home_access_accept && t->use_tunneled_reply) {
- DEBUG2(" Saving tunneled attributes for later");
+ RDEBUG2("Saving tunneled attributes for later");
/*
* Clean up the tunneled reply.
*/
- pairdelete(&reply->vps, PW_PROXY_STATE);
- pairdelete(&reply->vps, PW_MESSAGE_AUTHENTICATOR);
+ pairdelete(&reply->vps, PW_PROXY_STATE, 0);
+ pairdelete(&reply->vps, PW_MESSAGE_AUTHENTICATOR, 0);
t->accept_vps = reply->vps;
reply->vps = NULL;
* VP's back to the client.
*/
if (vp) {
- vp2eap(tls_session, vp);
+ vp2eap(request, tls_session, vp);
pairfree(&vp);
}
break;
default:
- DEBUG2(" PEAP: Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
+ RDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
rcode = RLM_MODULE_REJECT;
break;
}
return rcode;
}
-
+#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(" PEAP: Passing reply from proxy back into the tunnel.");
+ RDEBUG2("Passing reply from proxy back into the tunnel.");
/*
* If there was a fake request associated with the proxied
* 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;
peap_tunnel_t *t = tls_session->opaque;
t->home_access_accept = TRUE;
*/
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);
+ }
+
/*
* Perform a post-auth stage, which will get the EAP
* handler, too...
*/
fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
- DEBUG2(" PEAP: Passing reply back for EAP-MS-CHAP-V2 %p %d",
- fake, fake->reply->code);
+ RDEBUG2("Passing reply back for EAP-MS-CHAP-V2");
rcode = module_post_proxy(0, fake);
/*
* FIXME: If rcode returns fail, do something
* intelligent...
*/
- DEBUG2(" POST-PROXY %d", rcode);
rcode = rad_postauth(fake);
- DEBUG2(" POST-AUTH %d", rcode);
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" PEAP: Final reply from tunneled session code %d\n",
+ if ((debug_flag > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "} # server %s\n", fake->server);
+
+ RDEBUG("Final reply from tunneled session code %d",
fake->reply->code);
-
- for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+
+ 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(" PEAP: Got reply %d",
- request->proxy_reply->code);
+ RDEBUG2("Got reply %d", request->proxy_reply->code);
break;
}
}
switch (rcode) {
case RLM_MODULE_REJECT:
- DEBUG2(" PEAP: Reply was rejected");
- eaptls_fail(handler->eap_ds, 0);
+ RDEBUG2("Reply was rejected");
+ eaptls_fail(handler, 0);
return 0;
case RLM_MODULE_HANDLED:
- DEBUG2(" PEAP: Reply was handled");
+ RDEBUG2("Reply was handled");
eaptls_request(handler->eap_ds, tls_session);
return 1;
case RLM_MODULE_OK:
- DEBUG2(" PEAP: Reply was OK");
- eaptls_success(handler->eap_ds, 0);
- eaptls_gen_mppe_keys(&handler->request->reply->vps,
- tls_session->ssl,
- "client EAP encryption");
- return 1;
+ RDEBUG2("Reply was OK");
+
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ return eaptls_success(handler, 0);
default:
- DEBUG2(" PEAP: Reply was unknown.");
+ RDEBUG2("Reply was unknown.");
break;
}
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
}
request_free(&request);
}
+#endif
+
+
+static const char *peap_state(peap_tunnel_t *t)
+{
+ switch (t->status) {
+ case PEAP_STATUS_TUNNEL_ESTABLISHED:
+ return "TUNNEL ESTABLISHED";
+ case PEAP_STATUS_INNER_IDENTITY_REQ_SENT:
+ return "WAITING FOR INNER IDENTITY";
+ case PEAP_STATUS_SENT_TLV_SUCCESS:
+ return "send tlv success";
+ case PEAP_STATUS_SENT_TLV_FAILURE:
+ return "send tlv failure";
+ case PEAP_STATUS_PHASE2_INIT:
+ return "phase2_init";
+ case PEAP_STATUS_PHASE2:
+ return "phase2";
+ default:
+ break;
+ }
+ return "?";
+}
+
+static void print_tunneled_data(const uint8_t *data, size_t data_len)
+{
+ size_t i;
+
+ if ((debug_flag > 2) && fr_log_fp) {
+ for (i = 0; i < data_len; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data in %02x: ", (int) i);
+
+ fprintf(fr_log_fp, "%02x ", data[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
+ }
+}
/*
*/
int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
{
- int err;
peap_tunnel_t *t = tls_session->opaque;
REQUEST *fake;
VALUE_PAIR *vp;
int rcode = RLM_MODULE_REJECT;
const uint8_t *data;
unsigned int data_len;
-#ifndef NDEBUG
- int i;
-#endif
REQUEST *request = handler->request;
EAP_DS *eap_ds = handler->eap_ds;
/*
- * FIXME: if the SSL session says "want read", or
- * similar, leave the data in the clean_out buffer. This
- * lets the application data be sent across multiple
- * fragments.
- */
- err = tls_handshake_recv(tls_session);
- if (!err) {
- DEBUG2(" rlm_eap_peap: Failed in SSL");
- return RLM_MODULE_REJECT;
- }
-
- /*
* Just look at the buffer directly, without doing
- * record_minus.
+ * record_minus. This lets us avoid another data copy.
*/
data_len = tls_session->clean_out.used;
+ tls_session->clean_out.used = 0;
data = tls_session->clean_out.data;
-#ifndef NDEBUG
- if (debug_flag > 2) {
- for (i = 0; i < data_len; i++) {
- if ((i & 0x0f) == 0) printf(" PEAP tunnel data in %04x: ", i);
+ RDEBUG2("Peap state %s", peap_state(t));
- printf("%02x ", data[i]);
+ if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) &&
+ !eapmessage_verify(request, data, data_len)) {
+ RDEBUG2("FAILED processing PEAP: Tunneled data is invalid.");
+ if (debug_flag > 2) print_tunneled_data(data, data_len);
+ return RLM_MODULE_REJECT;
+ }
- if ((i & 0x0f) == 0x0f) printf("\n");
+ switch (t->status) {
+ case PEAP_STATUS_TUNNEL_ESTABLISHED:
+ /* FIXME: should be no data in the buffer here, check & assert? */
+
+ if (SSL_session_reused(tls_session->ssl)) {
+ RDEBUG2("Skipping Phase2 because of session resumption");
+ t->session_resumption_state = PEAP_RESUMPTION_YES;
+
+ /* we're good, send success TLV */
+ t->status = PEAP_STATUS_SENT_TLV_SUCCESS;
+ eappeap_success(handler, tls_session);
+
+ } else {
+ /* send an identity request */
+ t->session_resumption_state = PEAP_RESUMPTION_NO;
+ t->status = PEAP_STATUS_INNER_IDENTITY_REQ_SENT;
+ eappeap_identity(handler, tls_session);
}
- if ((data_len & 0x0f) != 0) printf("\n");
- }
-#endif
+ return RLM_MODULE_HANDLED;
- if (!eapmessage_verify(data, data_len)) {
- return RLM_MODULE_REJECT;
- }
+ case PEAP_STATUS_INNER_IDENTITY_REQ_SENT:
+ /* we're expecting an identity response */
+ if (data[0] != PW_EAP_IDENTITY) {
+ RDEBUG("Expected EAP-Identity, got something else.");
+ return RLM_MODULE_REJECT;
+ }
- DEBUG2(" rlm_eap_peap: Tunneled data is valid.");
+ if (data_len >= sizeof(t->username->vp_strvalue)) {
+ RDEBUG("EAP-Identity is too long");
+ return RLM_MODULE_REJECT;
+ }
+
+ /*
+ * Save it for later.
+ */
+ t->username = pairmake("User-Name", "", T_OP_EQ);
+ rad_assert(t->username != NULL);
+
+ memcpy(t->username->vp_strvalue, data + 1, data_len - 1);
+ t->username->length = data_len - 1;
+ t->username->vp_strvalue[t->username->length] = 0;
+ RDEBUG("Got inner identity '%s'", t->username->vp_strvalue);
+
+ t->status = PEAP_STATUS_PHASE2_INIT;
+ break;
/*
* If we authenticated the user, then it's OK.
*/
- if (t->status == PEAP_STATUS_SENT_TLV_SUCCESS) {
- if (eappeap_check_tlv(data)) {
- DEBUG2(" rlm_eap_peap: Success");
+ case PEAP_STATUS_SENT_TLV_SUCCESS:
+ if (eappeap_check_tlv(request, data)) {
+ RDEBUG2("Success");
return RLM_MODULE_OK;
}
+ /*
+ * Otherwise, the client rejected the session
+ * resumption. If the session is being re-used,
+ * we need to do a full authentication.
+ *
+ * We do this by sending an EAP-Identity request
+ * inside of the PEAP tunnel.
+ */
+ if (t->session_resumption_state == PEAP_RESUMPTION_YES) {
+ RDEBUG2("Client rejected session resumption. Re-starting full authentication");
+
+ /*
+ * Mark session resumption status.
+ */
+ t->status = PEAP_STATUS_INNER_IDENTITY_REQ_SENT;
+ t->session_resumption_state = PEAP_RESUMPTION_NO;
+
+ eappeap_identity(handler, tls_session);
+ return RLM_MODULE_HANDLED;
+ }
+
+ RDEBUG2("We sent a success, but received something weird in return.");
return RLM_MODULE_REJECT;
- } else if (t->status == PEAP_STATUS_SENT_TLV_FAILURE) {
- DEBUG2(" rlm_eap_peap: Had sent TLV failure. User was rejected earlier in this session.");
+ /*
+ * Damned if I know why the clients continue sending EAP
+ * packets after we told them to f*ck off.
+ */
+ case PEAP_STATUS_SENT_TLV_FAILURE:
+ RDEBUG(" The users session was previously rejected: returning reject (again.)");
+ RDEBUG(" *** This means you need to read the PREVIOUS messages in the debug output");
+ RDEBUG(" *** to find out the reason why the user was rejected.");
+ RDEBUG(" *** Look for \"reject\" or \"fail\". Those earlier messages will tell you.");
+ RDEBUG(" *** what went wrong, and how to fix the problem.");
return RLM_MODULE_REJECT;
+
+ case PEAP_STATUS_PHASE2_INIT:
+ RDEBUG("In state machine in phase2 init?");
+
+ case PEAP_STATUS_PHASE2:
+ break;
+
+ default:
+ RDEBUG2("Unhandled state in peap");
+ return RLM_MODULE_REJECT;
}
fake = request_alloc_fake(request);
rad_assert(fake->packet->vps == NULL);
- fake->packet->vps = eap2vp(eap_ds, data, data_len);
- if (!fake->packet->vps) {
- request_free(&fake);
- DEBUG2(" rlm_eap_peap: Unable to convert tunneled EAP packet to internal server data structures");
+ switch (t->status) {
+ /*
+ * If we're in PHASE2_INIT, the phase2 method hasn't been
+ * sent an Identity packet yet; do so from the stored
+ * username and this will kick off the phase2 eap method
+ */
+
+ case PEAP_STATUS_PHASE2_INIT: {
+ int len = t->username->length + EAP_HEADER_LEN + 1;
+
+ t->status = PEAP_STATUS_PHASE2;
+
+ vp = paircreate(PW_EAP_MESSAGE, 0, PW_TYPE_OCTETS);
+
+ vp->vp_octets[0] = PW_EAP_RESPONSE;
+ vp->vp_octets[1] = eap_ds->response->id;
+ vp->vp_octets[2] = (len >> 8) & 0xff;
+ vp->vp_octets[3] = len & 0xff;
+ vp->vp_octets[4] = PW_EAP_IDENTITY;
+
+ memcpy(vp->vp_octets + EAP_HEADER_LEN + 1, t->username->vp_strvalue, t->username->length);
+ vp->length = len;
+
+ pairadd(&fake->packet->vps, vp);
+
+ if (t->default_eap_type != 0) {
+ RDEBUG2("Setting default EAP type for tunneled EAP session.");
+ vp = pairmake("EAP-Type", "0", T_OP_EQ);
+ vp->vp_integer = t->default_eap_type;
+ pairadd(&fake->config_items, vp);
+ }
+ break; }
+
+ case PEAP_STATUS_PHASE2:
+ fake->packet->vps = eap2vp(request, eap_ds, data, data_len);
+ if (!fake->packet->vps) {
+ request_free(&fake);
+ RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
+ return PW_AUTHENTICATION_REJECT;
+ }
+ break;
+
+ default:
+ RDEBUG("Invalid state change in PEAP.");
return PW_AUTHENTICATION_REJECT;
}
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" PEAP: Got tunneled EAP-Message\n");
+ if ((debug_flag > 0) && fr_log_fp) {
+ RDEBUG("Got tunneled request");
+
+ debug_pair_list(fake->packet->vps);
- for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ fprintf(fr_log_fp, "server %s {\n",
+ (fake->server == NULL) ? "" : fake->server);
}
-#endif
/*
* Tell the request that it's a fake one.
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);
DEBUG2(" PEAP: Setting User-Name to %s",
fake->username->vp_strvalue);
}
* Add the State attribute, too, if it exists.
*/
if (t->state) {
- DEBUG2(" PEAP: Adding old state with %02x %02x",
- t->state->vp_octets[0], t->state->vp_octets[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);
}
}
- if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER)) != NULL) {
+ if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0)) != NULL) {
fake->server = vp->vp_strvalue;
} else if (t->virtual_server) {
} /* else fake->server == request->server */
-#ifndef NDEBUG
- if (debug_flag > 0) {
- printf(" PEAP: Sending tunneled request\n");
+ if ((debug_flag > 0) && fr_log_fp) {
+ fprintf(fr_log_fp, "Sending tunneled request\n");
- for (vp = fake->packet->vps; vp != NULL; vp = vp->next) {
- putchar('\t');vp_print(stdout, vp);putchar('\n');
- }
+ debug_pair_list(fake->packet->vps);
- printf("server %s {\n", fake->server);
+ 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("} # server %s\n", fake->server);
-
- printf(" PEAP: 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;
* of attributes.
*/
pairdelete(&fake->packet->vps,
- PW_EAP_MESSAGE);
+ PW_EAP_MESSAGE, 0);
}
DEBUG2(" PEAP: Tunneled authentication will be proxied to %s", vp->vp_strvalue);
*/
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;
*/
rcode = RLM_MODULE_UPDATED;
- } else {
+ } else
+#endif /* WITH_PROXY */
+ {
DEBUG2(" PEAP: Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
rcode = RLM_MODULE_REJECT;
- }
+ }
break;
default: