Return to eap_peap_peer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_peap |
1.1 misho 1: /* 2: * Copyright (C) 2011 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_peap_peer.h" 17: #include "eap_peap_avp.h" 18: 19: #include <utils/debug.h> 20: #include <daemon.h> 21: 22: typedef struct private_eap_peap_peer_t private_eap_peap_peer_t; 23: 24: /** 25: * Private data of an eap_peap_peer_t object. 26: */ 27: struct private_eap_peap_peer_t { 28: 29: /** 30: * Public eap_peap_peer_t interface. 31: */ 32: eap_peap_peer_t public; 33: 34: /** 35: * Server identity 36: */ 37: identification_t *server; 38: 39: /** 40: * Peer identity 41: */ 42: identification_t *peer; 43: 44: /** 45: * Outer phase 1 EAP method 46: */ 47: eap_method_t *ph1_method; 48: 49: /** 50: * Current phase 2 EAP method 51: */ 52: eap_method_t *ph2_method; 53: 54: /** 55: * Pending outbound EAP message 56: */ 57: eap_payload_t *out; 58: 59: /** 60: * AVP handler 61: */ 62: eap_peap_avp_t *avp; 63: }; 64: 65: METHOD(tls_application_t, process, status_t, 66: private_eap_peap_peer_t *this, bio_reader_t *reader) 67: { 68: chunk_t data = chunk_empty; 69: status_t status; 70: payload_t *payload; 71: eap_payload_t *in; 72: eap_code_t code; 73: eap_type_t type, received_type; 74: uint32_t vendor, received_vendor; 75: 76: status = this->avp->process(this->avp, reader, &data, 77: this->ph1_method->get_identifier(this->ph1_method)); 78: switch (status) 79: { 80: case SUCCESS: 81: break; 82: case NEED_MORE: 83: return NEED_MORE; 84: case FAILED: 85: default: 86: return FAILED; 87: } 88: 89: in = eap_payload_create_data(data); 90: DBG3(DBG_IKE, "%B", &data); 91: chunk_free(&data); 92: payload = (payload_t*)in; 93: 94: if (payload->verify(payload) != SUCCESS) 95: { 96: in->destroy(in); 97: return FAILED; 98: } 99: 100: code = in->get_code(in); 101: if (code == EAP_REQUEST || code == EAP_RESPONSE) 102: { 103: received_type = in->get_type(in, &received_vendor); 104: DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N/%N]", 105: eap_code_short_names, code, 106: eap_type_short_names, received_type); 107: if (code != EAP_REQUEST) 108: { 109: DBG1(DBG_IKE, "%N expected", eap_code_names, EAP_REQUEST); 110: in->destroy(in); 111: return FAILED; 112: } 113: } 114: else 115: { 116: DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]", 117: eap_code_short_names, code); 118: this->out = eap_payload_create_code(code, in->get_identifier(in)); 119: in->destroy(in); 120: return NEED_MORE; 121: } 122: 123: /* yet another phase2 authentication? */ 124: if (this->ph2_method) 125: { 126: type = this->ph2_method->get_type(this->ph2_method, &vendor); 127: 128: if (type != received_type || vendor != received_vendor) 129: { 130: this->ph2_method->destroy(this->ph2_method); 131: this->ph2_method = NULL; 132: } 133: } 134: 135: if (this->ph2_method == NULL) 136: { 137: if (received_vendor) 138: { 139: DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d " 140: "(id 0x%02X", received_type, received_vendor, 141: in->get_identifier(in)); 142: } 143: else 144: { 145: DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", 146: eap_type_names, received_type, in->get_identifier(in)); 147: } 148: this->ph2_method = charon->eap->create_instance(charon->eap, 149: received_type, received_vendor, 150: EAP_PEER, this->server, this->peer); 151: if (!this->ph2_method) 152: { 153: DBG1(DBG_IKE, "EAP method not supported"); 154: this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0, 155: in->is_expanded(in)); 156: in->destroy(in); 157: return NEED_MORE; 158: } 159: type = this->ph2_method->get_type(this->ph2_method, &vendor); 160: } 161: 162: status = this->ph2_method->process(this->ph2_method, in, &this->out); 163: in->destroy(in); 164: 165: switch (status) 166: { 167: case SUCCESS: 168: this->ph2_method->destroy(this->ph2_method); 169: this->ph2_method = NULL; 170: /* fall through to NEED_MORE */ 171: case NEED_MORE: 172: return NEED_MORE; 173: case FAILED: 174: default: 175: if (vendor) 176: { 177: DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", 178: type, vendor); 179: } 180: else 181: { 182: DBG1(DBG_IKE, "%N method failed", eap_type_names, type); 183: } 184: return FAILED; 185: } 186: } 187: 188: METHOD(tls_application_t, build, status_t, 189: private_eap_peap_peer_t *this, bio_writer_t *writer) 190: { 191: chunk_t data; 192: eap_code_t code; 193: eap_type_t type; 194: uint32_t vendor; 195: 196: if (this->out) 197: { 198: code = this->out->get_code(this->out); 199: type = this->out->get_type(this->out, &vendor); 200: if (code == EAP_REQUEST || code == EAP_RESPONSE) 201: { 202: DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N/%N]", 203: eap_code_short_names, code, eap_type_short_names, type); 204: } 205: else 206: { 207: DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N]", 208: eap_code_short_names, code); 209: } 210: 211: /* get the raw EAP message data */ 212: data = this->out->get_data(this->out); 213: DBG3(DBG_IKE, "%B", &data); 214: this->avp->build(this->avp, writer, data); 215: 216: this->out->destroy(this->out); 217: this->out = NULL; 218: } 219: return INVALID_STATE; 220: } 221: 222: METHOD(tls_application_t, destroy, void, 223: private_eap_peap_peer_t *this) 224: { 225: this->server->destroy(this->server); 226: this->peer->destroy(this->peer); 227: DESTROY_IF(this->ph2_method); 228: DESTROY_IF(this->out); 229: this->avp->destroy(this->avp); 230: free(this); 231: } 232: 233: /** 234: * See header 235: */ 236: eap_peap_peer_t *eap_peap_peer_create(identification_t *server, 237: identification_t *peer, 238: eap_method_t *eap_method) 239: { 240: private_eap_peap_peer_t *this; 241: 242: INIT(this, 243: .public = { 244: .application = { 245: .process = _process, 246: .build = _build, 247: .destroy = _destroy, 248: }, 249: }, 250: .server = server->clone(server), 251: .peer = peer->clone(peer), 252: .ph1_method = eap_method, 253: .avp = eap_peap_avp_create(FALSE), 254: ); 255: 256: return &this->public; 257: }