*
* 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 "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
#include "eap_ttls.h"
* tunneled session in the tunneled request
*/
int copy_request_to_tunnel;
+
+ /*
+ * RFC 5281 (TTLS) says that the length field MUST NOT be
+ * in fragments after the first one. However, we've done
+ * it that way for years, and no one has complained.
+ *
+ * In the interests of allowing the server to follow the
+ * RFC, we add the option here. If set to "no", it sends
+ * the length field in ONLY the first fragment.
+ */
+ int include_length;
+
+ /*
+ * Virtual server for inner tunnel session.
+ */
+ char *virtual_server;
} rlm_eap_ttls_t;
{ "use_tunneled_reply", PW_TYPE_BOOLEAN,
offsetof(rlm_eap_ttls_t, use_tunneled_reply), NULL, "no" },
+ { "virtual_server", PW_TYPE_STRING_PTR,
+ offsetof(rlm_eap_ttls_t, virtual_server), NULL, NULL },
+
+ { "include_length", PW_TYPE_BOOLEAN,
+ offsetof(rlm_eap_ttls_t, include_length), NULL, "yes" },
+
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
{
rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg;
- if (inst->default_eap_type_name) free(inst->default_eap_type_name);
free(inst);
return -1;
}
- /*
- * Can't tunnel TLS inside of TLS, we don't like it.
- *
- * More realistically, we haven't tested it, so we don't
- * claim it works.
- */
- if ((inst->default_eap_type == PW_EAP_TLS) ||
- (inst->default_eap_type == PW_EAP_TTLS) ||
- (inst->default_eap_type == PW_EAP_PEAP)) {
- radlog(L_ERR, "rlm_eap_ttls: Cannot tunnel EAP-Type/%s inside of TTLS",
- inst->default_eap_type_name);
- eapttls_detach(inst);
- return -1;
- }
-
*instance = inst;
return 0;
}
if (!t) return;
if (t->username) {
- DEBUG2(" TTLS: Freeing handler for user %s",
- t->username->strvalue);
+ DEBUG2("rlm_eap_ttls: Freeing handler for user %s",
+ t->username->vp_strvalue);
}
pairfree(&t->username);
pairfree(&t->state);
+ pairfree(&t->accept_vps);
free(t);
}
/*
- * Free the TTLS per-session data
+ * Allocate the TTLS per-session data
*/
static ttls_tunnel_t *ttls_alloc(rlm_eap_ttls_t *inst)
{
t->default_eap_type = inst->default_eap_type;
t->copy_request_to_tunnel = inst->copy_request_to_tunnel;
t->use_tunneled_reply = inst->use_tunneled_reply;
+ t->virtual_server = inst->virtual_server;
return t;
}
eaptls_status_t status;
rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg;
tls_session_t *tls_session = (tls_session_t *) handler->opaque;
+ ttls_tunnel_t *t = (ttls_tunnel_t *) tls_session->opaque;
+ REQUEST *request = handler->request;
+
+ RDEBUG2("Authenticate");
- DEBUG2(" rlm_eap_ttls: Authenticate");
+ tls_session->length_flag = inst->include_length;
/*
* Process TLS layer until done.
*/
status = eaptls_process(handler);
- DEBUG2(" eaptls_process returned %d\n", status);
+ RDEBUG2("eaptls_process returned %d\n", status);
switch (status) {
/*
* EAP-TLS handshake was successful, tell the
* an EAP-TLS-Success packet here.
*/
case EAPTLS_SUCCESS:
- eaptls_request(handler->eap_ds, tls_session);
+ if (SSL_session_reused(tls_session->ssl)) {
+ RDEBUG("Skipping Phase2 due to session resumption");
+ goto do_keys;
+ }
+
+ if (t && t->authenticated) {
+ if (t->accept_vps) {
+ pairadd(&handler->request->reply->vps,
+ t->accept_vps);
+ t->accept_vps = NULL;
+ }
+ do_keys:
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ return eaptls_success(handler, 0);
+ } else {
+ eaptls_request(handler->eap_ds, tls_session);
+ }
return 1;
/*
* Session is established, proceed with decoding
* tunneled data.
*/
- DEBUG2(" rlm_eap_ttls: Session established. Proceeding to decode tunneled attributes.");
+ RDEBUG2("Session established. Proceeding to decode tunneled attributes.");
/*
* We may need TTLS data associated with the session, so
rcode = eapttls_process(handler, tls_session);
switch (rcode) {
case PW_AUTHENTICATION_REJECT:
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
/*
return 1;
/*
- * Success: Return MPPE keys.
+ * Success: Automatically return MPPE keys.
*/
case PW_AUTHENTICATION_ACK:
- eaptls_success(handler->eap_ds, 0);
- eaptls_gen_mppe_keys(&handler->request->reply->vps,
- tls_session->ssl,
- "ttls keying material");
- return 1;
+ return eaptls_success(handler, 0);
/*
* No response packet, MUST be proxying it.
* that the request now has a "proxy" packet, and
* will proxy it, rather than returning an EAP packet.
*/
- case RLM_MODULE_UPDATED:
+ case PW_STATUS_CLIENT:
+#ifdef WITH_PROXY
rad_assert(handler->request->proxy != NULL);
+#endif
return 1;
break;
/*
* Something we don't understand: Reject it.
*/
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
}