Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_tnc/eap_tnc.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>