Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_eap/xauth_eap.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011 Martin Willi
! 3: * Copyright (C) 2011 revosec AG
! 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 "xauth_eap.h"
! 17:
! 18: #include <daemon.h>
! 19:
! 20: #include <library.h>
! 21: #include <credentials/sets/callback_cred.h>
! 22:
! 23: typedef struct private_xauth_eap_t private_xauth_eap_t;
! 24:
! 25: /**
! 26: * Private data of an xauth_eap_t object.
! 27: */
! 28: struct private_xauth_eap_t {
! 29:
! 30: /**
! 31: * Public interface.
! 32: */
! 33: xauth_eap_t public;
! 34:
! 35: /**
! 36: * ID of the server
! 37: */
! 38: identification_t *server;
! 39:
! 40: /**
! 41: * ID of the peer
! 42: */
! 43: identification_t *peer;
! 44:
! 45: /**
! 46: * Callback credential set
! 47: */
! 48: callback_cred_t *cred;
! 49:
! 50: /**
! 51: * XAuth password
! 52: */
! 53: chunk_t pass;
! 54: };
! 55:
! 56: /**
! 57: * Callback credential set function
! 58: */
! 59: static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type,
! 60: identification_t *me, identification_t *other,
! 61: id_match_t *match_me, id_match_t *match_other)
! 62: {
! 63: shared_key_t *shared;
! 64:
! 65: if (!this->pass.len)
! 66: {
! 67: return NULL;
! 68: }
! 69: if (type != SHARED_EAP && type != SHARED_ANY)
! 70: {
! 71: return NULL;
! 72: }
! 73: if (me)
! 74: {
! 75: if (!this->peer->equals(this->peer, me))
! 76: {
! 77: return NULL;
! 78: }
! 79: if (match_me)
! 80: {
! 81: *match_me = ID_MATCH_PERFECT;
! 82: }
! 83: }
! 84: else if (match_me)
! 85: {
! 86: *match_me = ID_MATCH_ANY;
! 87: }
! 88: if (other)
! 89: {
! 90: if (!this->server->equals(this->server, other))
! 91: {
! 92: return NULL;
! 93: }
! 94: if (match_other)
! 95: {
! 96: *match_other = ID_MATCH_PERFECT;
! 97: }
! 98: }
! 99: else if (match_other)
! 100: {
! 101: *match_other = ID_MATCH_ANY;
! 102: }
! 103: shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass));
! 104: this->pass = chunk_empty;
! 105: return shared;
! 106: }
! 107:
! 108: /**
! 109: * Do EAP exchanges to verify secret
! 110: */
! 111: static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend)
! 112: {
! 113: eap_payload_t *request, *response;
! 114: eap_method_t *frontend;
! 115: eap_type_t type;
! 116: uint32_t vendor;
! 117: status_t status;
! 118:
! 119: if (backend->initiate(backend, &request) != NEED_MORE)
! 120: {
! 121: return FALSE;
! 122: }
! 123: type = request->get_type(request, &vendor);
! 124: frontend = charon->eap->create_instance(charon->eap, type, vendor,
! 125: EAP_PEER, this->server, this->peer);
! 126: if (!frontend)
! 127: {
! 128: DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported",
! 129: eap_type_names, type);
! 130: request->destroy(request);
! 131: return FALSE;
! 132: }
! 133: while (TRUE)
! 134: {
! 135: /* credential set is active in frontend only, but not in backend */
! 136: lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE);
! 137: status = frontend->process(frontend, request, &response);
! 138: lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set);
! 139: request->destroy(request);
! 140: if (status != NEED_MORE)
! 141: { /* clients should never return SUCCESS */
! 142: frontend->destroy(frontend);
! 143: return FALSE;
! 144: }
! 145: status = backend->process(backend, response, &request);
! 146: response->destroy(response);
! 147: switch (status)
! 148: {
! 149: case SUCCESS:
! 150: frontend->destroy(frontend);
! 151: return TRUE;
! 152: case NEED_MORE:
! 153: break;
! 154: default:
! 155: frontend->destroy(frontend);
! 156: return FALSE;
! 157: }
! 158: }
! 159: }
! 160:
! 161: METHOD(xauth_method_t, initiate, status_t,
! 162: private_xauth_eap_t *this, cp_payload_t **out)
! 163: {
! 164: cp_payload_t *cp;
! 165:
! 166: cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
! 167: cp->add_attribute(cp, configuration_attribute_create_chunk(
! 168: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
! 169: cp->add_attribute(cp, configuration_attribute_create_chunk(
! 170: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
! 171: *out = cp;
! 172: return NEED_MORE;
! 173: }
! 174:
! 175: METHOD(xauth_method_t, process, status_t,
! 176: private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out)
! 177: {
! 178: configuration_attribute_t *attr;
! 179: enumerator_t *enumerator;
! 180: identification_t *id;
! 181: chunk_t user = chunk_empty;
! 182: eap_method_t *backend;
! 183: eap_type_t type;
! 184: char *name;
! 185: bool ok;
! 186:
! 187: enumerator = in->create_attribute_enumerator(in);
! 188: while (enumerator->enumerate(enumerator, &attr))
! 189: {
! 190: switch (attr->get_type(attr))
! 191: {
! 192: case XAUTH_USER_NAME:
! 193: user = attr->get_chunk(attr);
! 194: break;
! 195: case XAUTH_USER_PASSWORD:
! 196: this->pass = attr->get_chunk(attr);
! 197: break;
! 198: default:
! 199: break;
! 200: }
! 201: }
! 202: enumerator->destroy(enumerator);
! 203:
! 204: if (!user.ptr || !this->pass.ptr)
! 205: {
! 206: DBG1(DBG_IKE, "peer did not respond to our XAuth request");
! 207: return FAILED;
! 208: }
! 209: if (user.len)
! 210: {
! 211: id = identification_create_from_data(user);
! 212: if (!id)
! 213: {
! 214: DBG1(DBG_IKE, "failed to parse provided XAuth username");
! 215: return FAILED;
! 216: }
! 217: this->peer->destroy(this->peer);
! 218: this->peer = id;
! 219: }
! 220: if (this->pass.len && this->pass.ptr[this->pass.len - 1] == 0)
! 221: { /* fix null-terminated passwords (Android etc.) */
! 222: this->pass.len -= 1;
! 223: }
! 224:
! 225: name = lib->settings->get_str(lib->settings,
! 226: "%s.plugins.xauth-eap.backend", "radius",
! 227: lib->ns);
! 228: type = eap_type_from_string(name);
! 229: if (!type)
! 230: {
! 231: DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name);
! 232: return FAILED;
! 233: }
! 234: backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER,
! 235: this->server, this->peer);
! 236: if (!backend)
! 237: {
! 238: DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name);
! 239: return FAILED;
! 240: }
! 241: ok = verify_eap(this, backend);
! 242: backend->destroy(backend);
! 243: if (ok)
! 244: {
! 245: return SUCCESS;
! 246: }
! 247: return FAILED;
! 248: }
! 249:
! 250: METHOD(xauth_method_t, get_identity, identification_t*,
! 251: private_xauth_eap_t *this)
! 252: {
! 253: return this->peer;
! 254: }
! 255:
! 256: METHOD(xauth_method_t, destroy, void,
! 257: private_xauth_eap_t *this)
! 258: {
! 259: this->cred->destroy(this->cred);
! 260: this->server->destroy(this->server);
! 261: this->peer->destroy(this->peer);
! 262: free(this);
! 263: }
! 264:
! 265: /*
! 266: * Described in header.
! 267: */
! 268: xauth_eap_t *xauth_eap_create_server(identification_t *server,
! 269: identification_t *peer, char *profile)
! 270: {
! 271: private_xauth_eap_t *this;
! 272:
! 273: INIT(this,
! 274: .public = {
! 275: .xauth_method = {
! 276: .initiate = _initiate,
! 277: .process = _process,
! 278: .get_identity = _get_identity,
! 279: .destroy = _destroy,
! 280: },
! 281: },
! 282: .server = server->clone(server),
! 283: .peer = peer->clone(peer),
! 284: );
! 285:
! 286: this->cred = callback_cred_create_shared((void*)shared_cb, this);
! 287:
! 288: return &this->public;
! 289: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>