Return to eap_ttls_peer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_ttls |
1.1 misho 1: /* 2: * Copyright (C) 2010 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_peer.h" 17: #include "eap_ttls_avp.h" 18: 19: #include <utils/debug.h> 20: #include <daemon.h> 21: #include <radius_message.h> 22: #include <sa/eap/eap_method.h> 23: 24: typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t; 25: 26: /** 27: * Private data of an eap_ttls_peer_t object. 28: */ 29: struct private_eap_ttls_peer_t { 30: 31: /** 32: * Public eap_ttls_peer_t interface. 33: */ 34: eap_ttls_peer_t public; 35: 36: /** 37: * Server identity 38: */ 39: identification_t *server; 40: 41: /** 42: * Peer identity 43: */ 44: identification_t *peer; 45: 46: /** 47: * Current EAP-TTLS state 48: */ 49: bool start_phase2; 50: 51: /** 52: * Current phase 2 EAP method 53: */ 54: eap_method_t *method; 55: 56: /** 57: * Pending outbound EAP message 58: */ 59: eap_payload_t *out; 60: 61: /** 62: * AVP handler 63: */ 64: eap_ttls_avp_t *avp; 65: }; 66: 67: METHOD(tls_application_t, process, status_t, 68: private_eap_ttls_peer_t *this, bio_reader_t *reader) 69: { 70: chunk_t avp_data = chunk_empty; 71: chunk_t eap_data = chunk_empty; 72: status_t status; 73: payload_t *payload; 74: eap_payload_t *in; 75: eap_packet_t *pkt; 76: eap_code_t code; 77: eap_type_t type, received_type; 78: uint32_t vendor, received_vendor; 79: uint16_t eap_len; 80: size_t eap_pos = 0; 81: bool concatenated = FALSE; 82: 83: do 84: { 85: status = this->avp->process(this->avp, reader, &avp_data); 86: switch (status) 87: { 88: case SUCCESS: 89: break; 90: case NEED_MORE: 91: DBG1(DBG_IKE, "need more AVP data"); 92: return NEED_MORE; 93: case FAILED: 94: default: 95: return FAILED; 96: } 97: 98: if (eap_data.len == 0) 99: { 100: if (avp_data.len < 4) 101: { 102: DBG1(DBG_IKE, "AVP size to small to contain EAP header"); 103: chunk_free(&avp_data); 104: return FAILED; 105: } 106: pkt = (eap_packet_t*)avp_data.ptr; 107: eap_len = untoh16(&pkt->length); 108: 109: if (eap_len <= avp_data.len) 110: { 111: /* standard: EAP packet contained in a single AVP */ 112: eap_data = avp_data; 113: break; 114: } 115: else if (eap_len > reader->remaining(reader) + avp_data.len) 116: { 117: /* rough size check, ignoring AVP headers in remaining data */ 118: DBG1(DBG_IKE, "EAP packet too large for EAP-TTLS AVP(s)"); 119: chunk_free(&avp_data); 120: return FAILED; 121: } 122: else if (avp_data.len == MAX_RADIUS_ATTRIBUTE_SIZE) 123: { 124: /* non-standard: EAP packet segmented into multiple AVPs */ 125: eap_data = chunk_alloc(eap_len); 126: concatenated = TRUE; 127: } 128: else 129: { 130: DBG1(DBG_IKE, "non-radius segmentation of EAP packet into AVPs"); 131: chunk_free(&avp_data); 132: return FAILED; 133: } 134: } 135: 136: if (avp_data.len > eap_data.len - eap_pos) 137: { 138: DBG1(DBG_IKE, "AVP size too large to fit into EAP packet"); 139: chunk_free(&avp_data); 140: chunk_free(&eap_data); 141: return FAILED; 142: } 143: memcpy(eap_data.ptr + eap_pos, avp_data.ptr, avp_data.len); 144: eap_pos += avp_data.len; 145: chunk_free(&avp_data); 146: } 147: while (eap_pos < eap_data.len); 148: 149: in = eap_payload_create_data(eap_data); 150: chunk_free(&eap_data); 151: payload = (payload_t*)in; 152: 153: if (payload->verify(payload) != SUCCESS) 154: { 155: in->destroy(in); 156: return FAILED; 157: } 158: code = in->get_code(in); 159: received_type = in->get_type(in, &received_vendor); 160: DBG1(DBG_IKE, "received tunneled EAP-TTLS AVP%s [EAP/%N/%N]", 161: concatenated ? "s" : "", 162: eap_code_short_names, code, 163: eap_type_short_names, received_type); 164: if (code != EAP_REQUEST) 165: { 166: DBG1(DBG_IKE, "%N expected", eap_code_names, EAP_REQUEST); 167: in->destroy(in); 168: return FAILED; 169: } 170: 171: /* yet another phase2 authentication? */ 172: if (this->method) 173: { 174: type = this->method->get_type(this->method, &vendor); 175: 176: if (type != received_type || vendor != received_vendor) 177: { 178: this->method->destroy(this->method); 179: this->method = NULL; 180: } 181: } 182: 183: if (this->method == NULL) 184: { 185: if (received_vendor) 186: { 187: DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d " 188: "(id 0x%02X)", received_type, received_vendor, 189: in->get_identifier(in)); 190: } 191: else 192: { 193: DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", 194: eap_type_names, received_type, in->get_identifier(in)); 195: } 196: this->method = charon->eap->create_instance(charon->eap, 197: received_type, received_vendor, 198: EAP_PEER, this->server, this->peer); 199: if (!this->method) 200: { 201: DBG1(DBG_IKE, "EAP method not supported"); 202: this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0, 203: in->is_expanded(in)); 204: in->destroy(in); 205: return NEED_MORE; 206: } 207: type = this->method->get_type(this->method, &vendor); 208: this->start_phase2 = FALSE; 209: } 210: 211: status = this->method->process(this->method, in, &this->out); 212: in->destroy(in); 213: 214: switch (status) 215: { 216: case SUCCESS: 217: this->method->destroy(this->method); 218: this->method = NULL; 219: /* fall through to NEED_MORE */ 220: case NEED_MORE: 221: return NEED_MORE; 222: case FAILED: 223: default: 224: if (vendor) 225: { 226: DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", 227: type, vendor); 228: } 229: else 230: { 231: DBG1(DBG_IKE, "%N method failed", eap_type_names, type); 232: } 233: return FAILED; 234: } 235: } 236: 237: METHOD(tls_application_t, build, status_t, 238: private_eap_ttls_peer_t *this, bio_writer_t *writer) 239: { 240: chunk_t data; 241: eap_code_t code; 242: eap_type_t type; 243: uint32_t vendor; 244: 245: if (this->method == NULL && this->start_phase2) 246: { 247: /* generate an EAP Identity response */ 248: this->method = charon->eap->create_instance(charon->eap, EAP_IDENTITY, 249: 0, EAP_PEER, this->server, this->peer); 250: if (this->method == NULL) 251: { 252: DBG1(DBG_IKE, "EAP_IDENTITY method not available"); 253: return FAILED; 254: } 255: this->method->process(this->method, NULL, &this->out); 256: this->method->destroy(this->method); 257: this->method = NULL; 258: this->start_phase2 = FALSE; 259: } 260: 261: if (this->out) 262: { 263: code = this->out->get_code(this->out); 264: type = this->out->get_type(this->out, &vendor); 265: DBG1(DBG_IKE, "sending tunneled EAP-TTLS AVP [EAP/%N/%N]", 266: eap_code_short_names, code, eap_type_short_names, type); 267: 268: /* get the raw EAP message data */ 269: data = this->out->get_data(this->out); 270: this->avp->build(this->avp, writer, data); 271: 272: this->out->destroy(this->out); 273: this->out = NULL; 274: } 275: return INVALID_STATE; 276: } 277: 278: METHOD(tls_application_t, destroy, void, 279: private_eap_ttls_peer_t *this) 280: { 281: this->server->destroy(this->server); 282: this->peer->destroy(this->peer); 283: DESTROY_IF(this->method); 284: DESTROY_IF(this->out); 285: this->avp->destroy(this->avp); 286: free(this); 287: } 288: 289: /** 290: * See header 291: */ 292: eap_ttls_peer_t *eap_ttls_peer_create(identification_t *server, 293: identification_t *peer) 294: { 295: private_eap_ttls_peer_t *this; 296: 297: INIT(this, 298: .public = { 299: .application = { 300: .process = _process, 301: .build = _build, 302: .destroy = _destroy, 303: }, 304: }, 305: .server = server->clone(server), 306: .peer = peer->clone(peer), 307: .start_phase2 = TRUE, 308: .avp = eap_ttls_avp_create(), 309: ); 310: 311: return &this->public; 312: }