Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_gtc/eap_gtc.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2007-2012 Martin Willi
! 3: * Copyright (C) 2012 revosec AG
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "eap_gtc.h"
! 18:
! 19: #include <daemon.h>
! 20: #include <library.h>
! 21:
! 22: #define GTC_REQUEST_MSG "password"
! 23:
! 24: typedef struct private_eap_gtc_t private_eap_gtc_t;
! 25:
! 26: /**
! 27: * Private data of an eap_gtc_t object.
! 28: */
! 29: struct private_eap_gtc_t {
! 30:
! 31: /**
! 32: * Public authenticator_t interface.
! 33: */
! 34: eap_gtc_t public;
! 35:
! 36: /**
! 37: * ID of the server
! 38: */
! 39: identification_t *server;
! 40:
! 41: /**
! 42: * ID of the peer
! 43: */
! 44: identification_t *peer;
! 45:
! 46: /**
! 47: * EAP message identifier
! 48: */
! 49: uint8_t identifier;
! 50: };
! 51:
! 52: typedef struct eap_gtc_header_t eap_gtc_header_t;
! 53:
! 54: /**
! 55: * packed eap GTC header struct
! 56: */
! 57: struct eap_gtc_header_t {
! 58: /** EAP code (REQUEST/RESPONSE) */
! 59: uint8_t code;
! 60: /** unique message identifier */
! 61: uint8_t identifier;
! 62: /** length of whole message */
! 63: uint16_t length;
! 64: /** EAP type */
! 65: uint8_t type;
! 66: /** type data */
! 67: uint8_t data[];
! 68: } __attribute__((__packed__));
! 69:
! 70: METHOD(eap_method_t, initiate_peer, status_t,
! 71: private_eap_gtc_t *this, eap_payload_t **out)
! 72: {
! 73: /* peer never initiates */
! 74: return FAILED;
! 75: }
! 76:
! 77: METHOD(eap_method_t, initiate_server, status_t,
! 78: private_eap_gtc_t *this, eap_payload_t **out)
! 79: {
! 80: eap_gtc_header_t *req;
! 81: size_t len;
! 82:
! 83: len = strlen(GTC_REQUEST_MSG);
! 84: req = alloca(sizeof(eap_gtc_header_t) + len);
! 85: req->length = htons(sizeof(eap_gtc_header_t) + len);
! 86: req->code = EAP_REQUEST;
! 87: req->identifier = this->identifier;
! 88: req->type = EAP_GTC;
! 89: memcpy(req->data, GTC_REQUEST_MSG, len);
! 90:
! 91: *out = eap_payload_create_data(chunk_create((void*)req,
! 92: sizeof(eap_gtc_header_t) + len));
! 93: return NEED_MORE;
! 94: }
! 95:
! 96: METHOD(eap_method_t, process_peer, status_t,
! 97: private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
! 98: {
! 99: eap_gtc_header_t *res;
! 100: shared_key_t *shared;
! 101: chunk_t key;
! 102: size_t len;
! 103:
! 104: shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
! 105: this->peer, this->server);
! 106: if (shared == NULL)
! 107: {
! 108: DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
! 109: this->peer, this->server);
! 110: return FAILED;
! 111: }
! 112: key = shared->get_key(shared);
! 113: len = key.len;
! 114:
! 115: /* TODO: According to the draft we should "SASLprep" password, RFC4013. */
! 116:
! 117: this->identifier = in->get_identifier(in);
! 118: res = alloca(sizeof(eap_gtc_header_t) + len);
! 119: res->length = htons(sizeof(eap_gtc_header_t) + len);
! 120: res->code = EAP_RESPONSE;
! 121: res->identifier = this->identifier;
! 122: res->type = EAP_GTC;
! 123: memcpy(res->data, key.ptr, len);
! 124:
! 125: shared->destroy(shared);
! 126:
! 127: *out = eap_payload_create_data(chunk_create((void*)res,
! 128: sizeof(eap_gtc_header_t) + len));
! 129: return NEED_MORE;
! 130: }
! 131:
! 132: METHOD(eap_method_t, process_server, status_t,
! 133: private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
! 134: {
! 135: status_t status = FAILED;
! 136: chunk_t user, pass;
! 137: xauth_method_t *xauth;
! 138: cp_payload_t *ci, *co;
! 139: char *backend;
! 140:
! 141: user = this->peer->get_encoding(this->peer);
! 142: pass = chunk_skip(in->get_data(in), 5);
! 143: if (this->identifier != in->get_identifier(in) || !pass.len)
! 144: {
! 145: DBG1(DBG_IKE, "received invalid EAP-GTC message");
! 146: return FAILED;
! 147: }
! 148:
! 149: /* get XAuth backend to use for credential verification. Default to PAM
! 150: * to support legacy EAP-GTC configurations */
! 151: backend = lib->settings->get_str(lib->settings,
! 152: "%s.plugins.eap-gtc.backend", "pam", lib->ns);
! 153: xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
! 154: this->server, this->peer);
! 155: if (!xauth)
! 156: {
! 157: DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
! 158: return FAILED;
! 159: }
! 160: if (xauth->initiate(xauth, &co) == NEED_MORE)
! 161: {
! 162: /* assume that "out" contains username/password attributes */
! 163: co->destroy(co);
! 164: ci = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
! 165: ci->add_attribute(ci, configuration_attribute_create_chunk(
! 166: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, user));
! 167: ci->add_attribute(ci, configuration_attribute_create_chunk(
! 168: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, pass));
! 169: switch (xauth->process(xauth, ci, &co))
! 170: {
! 171: case SUCCESS:
! 172: status = SUCCESS;
! 173: break;
! 174: case NEED_MORE:
! 175: /* TODO: multiple exchanges currently not supported */
! 176: co->destroy(co);
! 177: break;
! 178: case FAILED:
! 179: default:
! 180: break;
! 181: }
! 182: ci->destroy(ci);
! 183: }
! 184: xauth->destroy(xauth);
! 185: return status;
! 186: }
! 187:
! 188: METHOD(eap_method_t, get_type, eap_type_t,
! 189: private_eap_gtc_t *this, uint32_t *vendor)
! 190: {
! 191: *vendor = 0;
! 192: return EAP_GTC;
! 193: }
! 194:
! 195: METHOD(eap_method_t, get_msk, status_t,
! 196: private_eap_gtc_t *this, chunk_t *msk)
! 197: {
! 198: return FAILED;
! 199: }
! 200:
! 201: METHOD(eap_method_t, get_identifier, uint8_t,
! 202: private_eap_gtc_t *this)
! 203: {
! 204: return this->identifier;
! 205: }
! 206:
! 207: METHOD(eap_method_t, set_identifier, void,
! 208: private_eap_gtc_t *this, uint8_t identifier)
! 209: {
! 210: this->identifier = identifier;
! 211: }
! 212:
! 213: METHOD(eap_method_t, is_mutual, bool,
! 214: private_eap_gtc_t *this)
! 215: {
! 216: return FALSE;
! 217: }
! 218:
! 219: METHOD(eap_method_t, destroy, void,
! 220: private_eap_gtc_t *this)
! 221: {
! 222: this->peer->destroy(this->peer);
! 223: this->server->destroy(this->server);
! 224: free(this);
! 225: }
! 226:
! 227: /**
! 228: * Generic constructor
! 229: */
! 230: static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
! 231: identification_t *peer)
! 232: {
! 233: private_eap_gtc_t *this;
! 234:
! 235: INIT(this,
! 236: .public = {
! 237: .eap_method_interface = {
! 238: .get_type = _get_type,
! 239: .is_mutual = _is_mutual,
! 240: .get_msk = _get_msk,
! 241: .get_identifier = _get_identifier,
! 242: .set_identifier = _set_identifier,
! 243: .destroy = _destroy,
! 244: },
! 245: },
! 246: .peer = peer->clone(peer),
! 247: .server = server->clone(server),
! 248: );
! 249:
! 250: return this;
! 251: }
! 252:
! 253: /*
! 254: * see header
! 255: */
! 256: eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *peer)
! 257: {
! 258: private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
! 259:
! 260: this->public.eap_method_interface.initiate = _initiate_server;
! 261: this->public.eap_method_interface.process = _process_server;
! 262:
! 263: /* generate a non-zero identifier */
! 264: do {
! 265: this->identifier = random();
! 266: } while (!this->identifier);
! 267:
! 268: return &this->public;
! 269: }
! 270:
! 271: /*
! 272: * see header
! 273: */
! 274: eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer)
! 275: {
! 276: private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
! 277:
! 278: this->public.eap_method_interface.initiate = _initiate_peer;
! 279: this->public.eap_method_interface.process = _process_peer;
! 280:
! 281: return &this->public;
! 282: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>