Return to eap_tnc.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_tnc |
1.1 misho 1: /* 2: * Copyright (C) 2010-2015 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_tnc.h" 17: 18: #include <tnc/tnc.h> 19: #include <tnc/tnccs/tnccs_manager.h> 20: #include <tls_eap.h> 21: #include <utils/debug.h> 22: #include <daemon.h> 23: 24: #include <tncifimv.h> 25: #include <tncif_names.h> 26: 27: /** 28: * Maximum size of an EAP-TNC message 29: */ 30: #define EAP_TNC_MAX_MESSAGE_LEN 65535 31: 32: /** 33: * Maximum number of EAP-TNC messages allowed 34: */ 35: #define EAP_TNC_MAX_MESSAGE_COUNT 10 36: 37: typedef struct private_eap_tnc_t private_eap_tnc_t; 38: 39: /** 40: * Private data of an eap_tnc_t object. 41: */ 42: struct private_eap_tnc_t { 43: 44: /** 45: * Public authenticator_t interface. 46: */ 47: eap_tnc_t public; 48: 49: /** 50: * Inner EAP authentication type 51: */ 52: eap_type_t type; 53: 54: /** 55: * Outer EAP authentication type 56: */ 57: eap_type_t auth_type; 58: 59: /** 60: * TLS stack, wrapped by EAP helper 61: */ 62: tls_eap_t *tls_eap; 63: 64: /** 65: * TNCCS instance running over EAP-TNC 66: */ 67: tnccs_t *tnccs; 68: 69: }; 70: 71: /** 72: * Callback function to get recommendation from TNCCS connection 73: */ 74: static bool enforce_recommendation(TNC_IMV_Action_Recommendation rec, 75: TNC_IMV_Evaluation_Result eval) 76: { 77: char *group; 78: identification_t *id; 79: ike_sa_t *ike_sa; 80: auth_cfg_t *auth; 81: bool no_access = FALSE; 82: 83: DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'", 84: TNC_IMV_Action_Recommendation_names, rec, 85: TNC_IMV_Evaluation_Result_names, eval); 86: 87: switch (rec) 88: { 89: case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: 90: group = "allow"; 91: break; 92: case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: 93: group = "isolate"; 94: break; 95: case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: 96: case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: 97: default: 98: group = "no access"; 99: no_access = TRUE; 100: break; 101: } 102: 103: ike_sa = charon->bus->get_sa(charon->bus); 104: if (!ike_sa) 105: { 106: DBG1(DBG_TNC, "policy enforcement point did not find IKE_SA"); 107: return FALSE; 108: } 109: 110: id = ike_sa->get_other_id(ike_sa); 111: DBG0(DBG_TNC, "policy enforced on peer '%Y' is '%s'", id, group); 112: 113: if (no_access) 114: { 115: return FALSE; 116: } 117: else 118: { 119: auth = ike_sa->get_auth_cfg(ike_sa, FALSE); 120: id = identification_create_from_string(group); 121: auth->add(auth, AUTH_RULE_GROUP, id); 122: DBG1(DBG_TNC, "policy enforcement point added group membership '%s'", 123: group); 124: } 125: return TRUE; 126: } 127: 128: METHOD(eap_method_t, initiate, status_t, 129: private_eap_tnc_t *this, eap_payload_t **out) 130: { 131: chunk_t data; 132: uint32_t auth_type; 133: 134: /* Determine TNC Client Authentication Type */ 135: switch (this->auth_type) 136: { 137: case EAP_TLS: 138: case EAP_TTLS: 139: case EAP_PEAP: 140: auth_type = TNC_AUTH_X509_CERT; 141: break; 142: case EAP_MD5: 143: case EAP_MSCHAPV2: 144: case EAP_GTC: 145: case EAP_OTP: 146: auth_type = TNC_AUTH_PASSWORD; 147: break; 148: case EAP_SIM: 149: case EAP_AKA: 150: auth_type = TNC_AUTH_SIM; 151: break; 152: default: 153: auth_type = TNC_AUTH_UNKNOWN; 154: } 155: this->tnccs->set_auth_type(this->tnccs, auth_type); 156: 157: if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE) 158: { 159: *out = eap_payload_create_data(data); 160: free(data.ptr); 161: return NEED_MORE; 162: } 163: return FAILED; 164: } 165: 166: METHOD(eap_method_t, process, status_t, 167: private_eap_tnc_t *this, eap_payload_t *in, eap_payload_t **out) 168: { 169: status_t status; 170: chunk_t data; 171: 172: data = in->get_data(in); 173: status = this->tls_eap->process(this->tls_eap, data, &data); 174: if (status == NEED_MORE) 175: { 176: *out = eap_payload_create_data(data); 177: free(data.ptr); 178: } 179: return status; 180: } 181: 182: METHOD(eap_method_t, get_type, eap_type_t, 183: private_eap_tnc_t *this, uint32_t *vendor) 184: { 185: *vendor = 0; 186: return this->type; 187: } 188: 189: METHOD(eap_method_t, get_msk, status_t, 190: private_eap_tnc_t *this, chunk_t *msk) 191: { 192: *msk = this->tls_eap->get_msk(this->tls_eap); 193: if (msk->len) 194: { 195: return SUCCESS; 196: } 197: return FAILED; 198: } 199: 200: METHOD(eap_method_t, get_identifier, uint8_t, 201: private_eap_tnc_t *this) 202: { 203: return this->tls_eap->get_identifier(this->tls_eap); 204: } 205: 206: METHOD(eap_method_t, set_identifier, void, 207: private_eap_tnc_t *this, uint8_t identifier) 208: { 209: this->tls_eap->set_identifier(this->tls_eap, identifier); 210: } 211: 212: METHOD(eap_method_t, is_mutual, bool, 213: private_eap_tnc_t *this) 214: { 215: return FALSE; 216: } 217: 218: METHOD(eap_method_t, destroy, void, 219: private_eap_tnc_t *this) 220: { 221: chunk_t pdp_server; 222: uint16_t pdp_port; 223: tls_t *tls; 224: 225: pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port); 226: if (pdp_server.len) 227: { 228: DBG2(DBG_TNC, "TODO: setup PT-TLS connection to %.*s:%u", 229: pdp_server.len, pdp_server.ptr, pdp_port); 230: } 231: tls = &this->tnccs->tls; 232: tls->destroy(tls); 233: this->tls_eap->destroy(this->tls_eap); 234: free(this); 235: } 236: 237: METHOD(eap_inner_method_t, get_auth_type, eap_type_t, 238: private_eap_tnc_t *this) 239: { 240: return this->auth_type; 241: } 242: 243: METHOD(eap_inner_method_t, set_auth_type, void, 244: private_eap_tnc_t *this, eap_type_t type) 245: { 246: this->auth_type = type; 247: } 248: 249: /** 250: * Generic private constructor 251: */ 252: static eap_tnc_t *eap_tnc_create(identification_t *server, 253: identification_t *peer, bool is_server, 254: eap_type_t type) 255: { 256: private_eap_tnc_t *this; 257: int max_msg_count; 258: char* protocol; 259: ike_sa_t *ike_sa; 260: host_t *server_ip, *peer_ip; 261: tnccs_t *tnccs; 262: tnccs_type_t tnccs_type; 263: 264: INIT(this, 265: .public = { 266: .eap_inner_method = { 267: .eap_method = { 268: .initiate = _initiate, 269: .process = _process, 270: .get_type = _get_type, 271: .is_mutual = _is_mutual, 272: .get_msk = _get_msk, 273: .get_identifier = _get_identifier, 274: .set_identifier = _set_identifier, 275: .destroy = _destroy, 276: }, 277: .get_auth_type = _get_auth_type, 278: .set_auth_type = _set_auth_type, 279: }, 280: }, 281: .type = type, 282: ); 283: 284: max_msg_count = lib->settings->get_int(lib->settings, 285: "%s.plugins.eap-tnc.max_message_count", 286: EAP_TNC_MAX_MESSAGE_COUNT, lib->ns); 287: protocol = lib->settings->get_str(lib->settings, 288: "%s.plugins.eap-tnc.protocol", "tnccs-2.0", lib->ns); 289: if (strcaseeq(protocol, "tnccs-2.0")) 290: { 291: tnccs_type = TNCCS_2_0; 292: } 293: else if (strcaseeq(protocol, "tnccs-1.1")) 294: { 295: tnccs_type = TNCCS_1_1; 296: } 297: else if (strcaseeq(protocol, "tnccs-dynamic") && is_server) 298: { 299: tnccs_type = TNCCS_DYNAMIC; 300: } 301: else 302: { 303: DBG1(DBG_TNC, "TNCCS protocol '%s' not supported", protocol); 304: free(this); 305: return NULL; 306: } 307: 308: /* Determine IP addresses of server and peer */ 309: ike_sa = charon->bus->get_sa(charon->bus); 310: if (!ike_sa) 311: { 312: DBG1(DBG_TNC, "%N constructor did not find IKE_SA", 313: eap_type_names, type); 314: free(this); 315: return NULL; 316: } 317: if (is_server) 318: { 319: server_ip = ike_sa->get_my_host(ike_sa); 320: peer_ip = ike_sa->get_other_host(ike_sa); 321: } 322: else 323: { 324: peer_ip = ike_sa->get_my_host(ike_sa); 325: server_ip = ike_sa->get_other_host(ike_sa); 326: } 327: 328: tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type, 329: is_server, server, peer, server_ip, peer_ip, 330: (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0, 331: enforce_recommendation); 332: if (!tnccs) 333: { 334: DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol); 335: free(this); 336: return NULL; 337: } 338: if (!is_server) 339: { 340: tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT); 341: } 342: this->tnccs = tnccs->get_ref(tnccs); 343: this->tls_eap = tls_eap_create(type, &tnccs->tls, 344: EAP_TNC_MAX_MESSAGE_LEN, 345: max_msg_count, FALSE); 346: if (!this->tls_eap) 347: { 348: free(this); 349: return NULL; 350: } 351: return &this->public; 352: } 353: 354: eap_tnc_t *eap_tnc_create_server(identification_t *server, 355: identification_t *peer) 356: { 357: return eap_tnc_create(server, peer, TRUE, EAP_TNC); 358: } 359: 360: eap_tnc_t *eap_tnc_create_peer(identification_t *server, 361: identification_t *peer) 362: { 363: return eap_tnc_create(server, peer, FALSE, EAP_TNC); 364: } 365: 366: eap_tnc_t *eap_tnc_pt_create_server(identification_t *server, 367: identification_t *peer) 368: { 369: return eap_tnc_create(server, peer, TRUE, EAP_PT_EAP); 370: } 371: 372: eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server, 373: identification_t *peer) 374: { 375: return eap_tnc_create(server, peer, FALSE, EAP_PT_EAP); 376: }