*
* 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"
typedef struct rlm_eap_ttls_t {
/*
+ * Default tunneled EAP type
+ */
+ char *default_eap_type_name;
+ int default_eap_type;
+
+ /*
* Use the reply attributes from the tunneled session in
* the non-tunneled reply to the client.
*/
int use_tunneled_reply;
/*
- * Default tunneled EAP type
+ * Use SOME of the request attributes from outside of the
+ * tunneled session in the tunneled request
*/
- char *default_eap_type_name;
- int default_eap_type;
+ 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;
static CONF_PARSER module_config[] = {
+ { "default_eap_type", PW_TYPE_STRING_PTR,
+ offsetof(rlm_eap_ttls_t, default_eap_type_name), NULL, "md5" },
+
+ { "copy_request_to_tunnel", PW_TYPE_BOOLEAN,
+ offsetof(rlm_eap_ttls_t, copy_request_to_tunnel), NULL, "no" },
+
{ "use_tunneled_reply", PW_TYPE_BOOLEAN,
offsetof(rlm_eap_ttls_t, use_tunneled_reply), NULL, "no" },
- { "default_eap_type", PW_TYPE_STRING_PTR,
- offsetof(rlm_eap_ttls_t, default_eap_type_name), NULL, "md5" },
+ { "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 = rad_malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
- t->use_tunneled_reply = inst->use_tunneled_reply;
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
/*
* Process the TTLS portion of the request.
*/
- rcode = eapttls_process(handler->request, tls_session);
- if (rcode == PW_AUTHENTICATION_REJECT) {
- eaptls_fail(handler->eap_ds, 0);
+ rcode = eapttls_process(handler, tls_session);
+ switch (rcode) {
+ case PW_AUTHENTICATION_REJECT:
+ eaptls_fail(handler, 0);
return 0;
- }
- /*
- * Access-Challenge, continue tunneled conversation.
- */
- if (rcode == PW_ACCESS_CHALLENGE) {
+ /*
+ * Access-Challenge, continue tunneled conversation.
+ */
+ case PW_ACCESS_CHALLENGE:
eaptls_request(handler->eap_ds, tls_session);
return 1;
- }
- /*
- * Success: Return MPPE keys.
- */
- if (rcode == PW_AUTHENTICATION_ACK) {
- eaptls_success(handler->eap_ds, 0);
- eaptls_gen_mppe_keys(&handler->request->reply->vps,
- tls_session->ssl,
- "ttls keying material");
+ /*
+ * Success: Automatically return MPPE keys.
+ */
+ case PW_AUTHENTICATION_ACK:
+ return eaptls_success(handler, 0);
+
+ /*
+ * No response packet, MUST be proxying it.
+ * The main EAP module will take care of discovering
+ * that the request now has a "proxy" packet, and
+ * will proxy it, rather than returning an EAP packet.
+ */
+ case PW_STATUS_CLIENT:
+#ifdef WITH_PROXY
+ rad_assert(handler->request->proxy != NULL);
+#endif
return 1;
+ break;
+
+ default:
+ break;
}
/*
* Something we don't understand: Reject it.
*/
- eaptls_fail(handler->eap_ds, 0);
+ eaptls_fail(handler, 0);
return 0;
}