Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_ttls/eap_ttls_server.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2010-2014 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "eap_ttls_server.h"
! 17: #include "eap_ttls_avp.h"
! 18:
! 19: #include <utils/debug.h>
! 20: #include <daemon.h>
! 21:
! 22: #include <sa/eap/eap_method.h>
! 23: #include <sa/eap/eap_inner_method.h>
! 24:
! 25: typedef struct private_eap_ttls_server_t private_eap_ttls_server_t;
! 26:
! 27: /**
! 28: * Private data of an eap_ttls_server_t object.
! 29: */
! 30: struct private_eap_ttls_server_t {
! 31:
! 32: /**
! 33: * Public eap_ttls_server_t interface.
! 34: */
! 35: eap_ttls_server_t public;
! 36:
! 37: /**
! 38: * Server identity
! 39: */
! 40: identification_t *server;
! 41:
! 42: /**
! 43: * Peer identity
! 44: */
! 45: identification_t *peer;
! 46:
! 47: /**
! 48: * Current EAP-TTLS phase2 state
! 49: */
! 50: bool start_phase2;
! 51:
! 52: /**
! 53: * Current EAP-TTLS phase2 TNC state
! 54: */
! 55: bool start_phase2_tnc;
! 56:
! 57: /**
! 58: * Current phase 2 EAP method
! 59: */
! 60: eap_method_t *method;
! 61:
! 62: /**
! 63: * Pending outbound EAP message
! 64: */
! 65: eap_payload_t *out;
! 66:
! 67: /**
! 68: * AVP handler
! 69: */
! 70: eap_ttls_avp_t *avp;
! 71: };
! 72:
! 73: /**
! 74: * Start EAP client authentication protocol
! 75: */
! 76: static status_t start_phase2_auth(private_eap_ttls_server_t *this)
! 77: {
! 78: char *eap_type_str;
! 79: eap_type_t type;
! 80:
! 81: eap_type_str = lib->settings->get_str(lib->settings,
! 82: "%s.plugins.eap-ttls.phase2_method", "md5",
! 83: lib->ns);
! 84: type = eap_type_from_string(eap_type_str);
! 85: if (type == 0)
! 86: {
! 87: DBG1(DBG_IKE, "unrecognized phase2 method \"%s\"", eap_type_str);
! 88: return FAILED;
! 89: }
! 90: DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type);
! 91: this->method = charon->eap->create_instance(charon->eap, type, 0,
! 92: EAP_SERVER, this->server, this->peer);
! 93: if (this->method == NULL)
! 94: {
! 95: DBG1(DBG_IKE, "%N method not available", eap_type_names, type);
! 96: return FAILED;
! 97: }
! 98: if (this->method->initiate(this->method, &this->out) == NEED_MORE)
! 99: {
! 100: return NEED_MORE;
! 101: }
! 102: else
! 103: {
! 104: DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
! 105: return FAILED;
! 106: }
! 107: }
! 108:
! 109: /**
! 110: * If configured, start PT-EAP or legacy EAP-TNC protocol
! 111: */
! 112: static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
! 113: eap_type_t auth_type)
! 114: {
! 115: eap_inner_method_t *inner_method;
! 116: eap_type_t type;
! 117: char *eap_type_str;
! 118:
! 119: if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
! 120: "%s.plugins.eap-ttls.phase2_tnc", FALSE, lib->ns))
! 121: {
! 122: eap_type_str = lib->settings->get_str(lib->settings,
! 123: "%s.plugins.eap-ttls.phase2_tnc_method", "pt",
! 124: lib->ns);
! 125: type = eap_type_from_string(eap_type_str);
! 126: if (type == 0)
! 127: {
! 128: DBG1(DBG_IKE, "unrecognized phase2 EAP TNC method \"%s\"",
! 129: eap_type_str);
! 130: return FAILED;
! 131: }
! 132: DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type);
! 133: this->method = charon->eap->create_instance(charon->eap, type,
! 134: 0, EAP_SERVER, this->server, this->peer);
! 135: if (this->method == NULL)
! 136: {
! 137: DBG1(DBG_IKE, "%N method not available", eap_type_names, type);
! 138: return FAILED;
! 139: }
! 140: inner_method = (eap_inner_method_t *)this->method;
! 141: inner_method->set_auth_type(inner_method, auth_type);
! 142:
! 143: this->start_phase2_tnc = FALSE;
! 144: if (this->method->initiate(this->method, &this->out) == NEED_MORE)
! 145: {
! 146: return NEED_MORE;
! 147: }
! 148: else
! 149: {
! 150: DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
! 151: return FAILED;
! 152: }
! 153: }
! 154: return SUCCESS;
! 155: }
! 156:
! 157: METHOD(tls_application_t, process, status_t,
! 158: private_eap_ttls_server_t *this, bio_reader_t *reader)
! 159: {
! 160: chunk_t data = chunk_empty;
! 161: status_t status;
! 162: payload_t *payload;
! 163: eap_payload_t *in;
! 164: eap_code_t code;
! 165: eap_type_t type = EAP_NAK, received_type;
! 166: uint32_t vendor, received_vendor;
! 167:
! 168: status = this->avp->process(this->avp, reader, &data);
! 169: switch (status)
! 170: {
! 171: case SUCCESS:
! 172: break;
! 173: case NEED_MORE:
! 174: return NEED_MORE;
! 175: case FAILED:
! 176: default:
! 177: return FAILED;
! 178: }
! 179: in = eap_payload_create_data(data);
! 180: chunk_free(&data);
! 181: payload = (payload_t*)in;
! 182:
! 183: if (payload->verify(payload) != SUCCESS)
! 184: {
! 185: in->destroy(in);
! 186: return FAILED;
! 187: }
! 188: code = in->get_code(in);
! 189: received_type = in->get_type(in, &received_vendor);
! 190: DBG1(DBG_IKE, "received tunneled EAP-TTLS AVP [EAP/%N/%N]",
! 191: eap_code_short_names, code,
! 192: eap_type_short_names, received_type);
! 193: if (code != EAP_RESPONSE)
! 194: {
! 195: DBG1(DBG_IKE, "%N expected", eap_code_names, EAP_RESPONSE);
! 196: in->destroy(in);
! 197: return FAILED;
! 198: }
! 199:
! 200: if (this->method)
! 201: {
! 202: type = this->method->get_type(this->method, &vendor);
! 203:
! 204: if (type != received_type || vendor != received_vendor)
! 205: {
! 206: if (received_vendor == 0 && received_type == EAP_NAK)
! 207: {
! 208: DBG1(DBG_IKE, "peer does not support %N", eap_type_names, type);
! 209: }
! 210: else
! 211: {
! 212: DBG1(DBG_IKE, "received invalid EAP response");
! 213: }
! 214: in->destroy(in);
! 215: return FAILED;
! 216: }
! 217: }
! 218:
! 219: if (!received_vendor && received_type == EAP_IDENTITY)
! 220: {
! 221: chunk_t eap_id;
! 222:
! 223: if (this->method == NULL)
! 224: {
! 225: /* Received an EAP Identity response without a matching request */
! 226: this->method = charon->eap->create_instance(charon->eap,
! 227: EAP_IDENTITY, 0, EAP_SERVER,
! 228: this->server, this->peer);
! 229: if (this->method == NULL)
! 230: {
! 231: DBG1(DBG_IKE, "%N method not available",
! 232: eap_type_names, EAP_IDENTITY);
! 233: return FAILED;
! 234: }
! 235: }
! 236:
! 237: if (this->method->process(this->method, in, &this->out) != SUCCESS)
! 238: {
! 239:
! 240: DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_IDENTITY);
! 241: return FAILED;
! 242: }
! 243:
! 244: if (this->method->get_msk(this->method, &eap_id) == SUCCESS)
! 245: {
! 246: this->peer->destroy(this->peer);
! 247: this->peer = identification_create_from_data(eap_id);
! 248: DBG1(DBG_IKE, "received EAP identity '%Y'", this->peer);
! 249: }
! 250:
! 251: in->destroy(in);
! 252: this->method->destroy(this->method);
! 253: this->method = NULL;
! 254:
! 255: /* Start Phase 2 of EAP-TTLS authentication */
! 256: if (lib->settings->get_bool(lib->settings,
! 257: "%s.plugins.eap-ttls.request_peer_auth", FALSE, lib->ns))
! 258: {
! 259: return start_phase2_tnc(this, EAP_TLS);
! 260: }
! 261: else
! 262: {
! 263: return start_phase2_auth(this);
! 264: }
! 265: }
! 266:
! 267: if (this->method == 0)
! 268: {
! 269: DBG1(DBG_IKE, "no %N phase2 method installed", eap_type_names, EAP_TTLS);
! 270: in->destroy(in);
! 271: return FAILED;
! 272: }
! 273:
! 274: status = this->method->process(this->method, in, &this->out);
! 275: in->destroy(in);
! 276:
! 277: switch (status)
! 278: {
! 279: case SUCCESS:
! 280: DBG1(DBG_IKE, "%N phase2 authentication of '%Y' with %N successful",
! 281: eap_type_names, EAP_TTLS, this->peer,
! 282: eap_type_names, type);
! 283: this->method->destroy(this->method);
! 284: this->method = NULL;
! 285:
! 286: /* continue phase2 with EAP-TNC? */
! 287: return start_phase2_tnc(this, type);
! 288: case NEED_MORE:
! 289: break;
! 290: case FAILED:
! 291: default:
! 292: if (vendor)
! 293: {
! 294: DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed",
! 295: type, vendor);
! 296: }
! 297: else
! 298: {
! 299: DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
! 300: }
! 301: return FAILED;
! 302: }
! 303: return status;
! 304: }
! 305:
! 306: METHOD(tls_application_t, build, status_t,
! 307: private_eap_ttls_server_t *this, bio_writer_t *writer)
! 308: {
! 309: chunk_t data;
! 310: eap_code_t code;
! 311: eap_type_t type;
! 312: uint32_t vendor;
! 313:
! 314: if (this->method == NULL && this->start_phase2 &&
! 315: lib->settings->get_bool(lib->settings,
! 316: "%s.plugins.eap-ttls.phase2_piggyback", FALSE, lib->ns))
! 317: {
! 318: /* generate an EAP Identity request which will be piggybacked right
! 319: * onto the TLS Finished message thus initiating EAP-TTLS phase2
! 320: */
! 321: this->method = charon->eap->create_instance(charon->eap, EAP_IDENTITY,
! 322: 0, EAP_SERVER, this->server, this->peer);
! 323: if (this->method == NULL)
! 324: {
! 325: DBG1(DBG_IKE, "%N method not available",
! 326: eap_type_names, EAP_IDENTITY);
! 327: return FAILED;
! 328: }
! 329: this->method->initiate(this->method, &this->out);
! 330: this->start_phase2 = FALSE;
! 331: }
! 332:
! 333: if (this->out)
! 334: {
! 335: code = this->out->get_code(this->out);
! 336: type = this->out->get_type(this->out, &vendor);
! 337: DBG1(DBG_IKE, "sending tunneled EAP-TTLS AVP [EAP/%N/%N]",
! 338: eap_code_short_names, code, eap_type_short_names, type);
! 339:
! 340: /* get the raw EAP message data */
! 341: data = this->out->get_data(this->out);
! 342: this->avp->build(this->avp, writer, data);
! 343:
! 344: this->out->destroy(this->out);
! 345: this->out = NULL;
! 346: }
! 347: return INVALID_STATE;
! 348: }
! 349:
! 350: METHOD(tls_application_t, destroy, void,
! 351: private_eap_ttls_server_t *this)
! 352: {
! 353: this->server->destroy(this->server);
! 354: this->peer->destroy(this->peer);
! 355: DESTROY_IF(this->method);
! 356: DESTROY_IF(this->out);
! 357: this->avp->destroy(this->avp);
! 358: free(this);
! 359: }
! 360:
! 361: /**
! 362: * See header
! 363: */
! 364: eap_ttls_server_t *eap_ttls_server_create(identification_t *server,
! 365: identification_t *peer)
! 366: {
! 367: private_eap_ttls_server_t *this;
! 368:
! 369: INIT(this,
! 370: .public = {
! 371: .application = {
! 372: .process = _process,
! 373: .build = _build,
! 374: .destroy = _destroy,
! 375: },
! 376: },
! 377: .server = server->clone(server),
! 378: .peer = peer->clone(peer),
! 379: .start_phase2 = TRUE,
! 380: .start_phase2_tnc = TRUE,
! 381: .avp = eap_ttls_avp_create(),
! 382: );
! 383:
! 384: return &this->public;
! 385: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>