Return to xauth_eap.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / xauth_eap |
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: }