diff options
Diffstat (limited to 'src')
69 files changed, 1454 insertions, 206 deletions
diff --git a/src/charon-nm/nm/nm_backend.c b/src/charon-nm/nm/nm_backend.c index f36cf1f68..5bb2ed930 100644 --- a/src/charon-nm/nm/nm_backend.c +++ b/src/charon-nm/nm/nm_backend.c @@ -117,10 +117,13 @@ static bool nm_backend_init() nm_backend_t *this; g_type_init (); + +#if !GLIB_CHECK_VERSION(2,23,0) if (!g_thread_supported()) { g_thread_init(NULL); } +#endif INIT(this, .creds = nm_creds_create(), diff --git a/src/charon/charon.c b/src/charon/charon.c index c301874c8..f4bd27d34 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -401,7 +401,6 @@ int main(int argc, char *argv[]) if (check_pidfile()) { DBG1(DBG_DMN, "charon already running (\""PID_FILE"\" exists)"); - status = -1; goto deinit; } diff --git a/src/conftest/README b/src/conftest/README index 133ae603c..617195df9 100644 --- a/src/conftest/README +++ b/src/conftest/README @@ -98,9 +98,10 @@ The IKE_SA configuration uses the following options (as key/value pairs): src/libstrongswan/crypt/proposal/proposal_keywords.txt fake_nat: Fake the NAT_DETECTION_*_IP payloads to simulate a NAT scenario - rsa_strength: connection requires a trustchain with RSA keys of given bits - ecdsa_strength: connection requires a trustchain with ECDSA keys of given bits - cert_policy: connection requries a certificate with the given OID policy + rsa_strength: Connection requires a trustchain with RSA keys of given bits + ecdsa_strength: Connection requires a trustchain with ECDSA keys of given bits + cert_policy: Connection requries a certificate with the given OID policy + named_pool: Name of an IP pool defined e.g. in a database backend The following CHILD_SA specific configuration options are supported: diff --git a/src/conftest/config.c b/src/conftest/config.c index 22c9d23e0..ae0d93460 100644 --- a/src/conftest/config.c +++ b/src/conftest/config.c @@ -244,7 +244,7 @@ static peer_cfg_t *load_peer_config(private_config_t *this, child_cfg_t *child_cfg; enumerator_t *enumerator; identification_t *lid, *rid; - char *child, *policy; + char *child, *policy, *pool; uintptr_t strength; ike_cfg = load_ike_config(this, settings, config); @@ -280,6 +280,11 @@ static peer_cfg_t *load_peer_config(private_config_t *this, } auth->add(auth, AUTH_RULE_IDENTITY, rid); peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); + pool = settings->get_str(settings, "configs.%s.named_pool", NULL, config); + if (pool) + { + peer_cfg->add_pool(peer_cfg, pool); + } DBG1(DBG_CFG, "loaded config %s: %Y - %Y", config, lid, rid); diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 5203890ff..3c1b6aa5e 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -60,7 +60,7 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ -sa/eap/eap_method.c sa/eap/eap_method.h \ +sa/eap/eap_method.c sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \ diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 28fdda735..ca964d749 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -151,7 +151,7 @@ static payload_rule_t ike_sa_init_r_rules[] = { {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, {NONCE, 1, 1, FALSE, FALSE}, - {CERTIFICATE_REQUEST, 0, 1, FALSE, FALSE}, + {CERTIFICATE_REQUEST, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, }; @@ -181,7 +181,7 @@ static payload_rule_t ike_auth_i_rules[] = { {AUTHENTICATION, 0, 1, TRUE, TRUE}, {ID_INITIATOR, 0, 1, TRUE, FALSE}, {CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE}, - {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE}, + {CERTIFICATE_REQUEST, 0, MAX_CERTREQ_PAYLOADS, TRUE, FALSE}, {ID_RESPONDER, 0, 1, TRUE, FALSE}, #ifdef ME {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE}, diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index ffa1bae39..7363ade1d 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -21,6 +21,8 @@ #include <utils/debug.h> #include <daemon.h> +#include <tncifimv.h> + /** * Maximum size of an EAP-TNC message */ @@ -44,15 +46,50 @@ struct private_eap_tnc_t { eap_tnc_t public; /** + * Outer EAP authentication type + */ + eap_type_t auth_type; + + /** * TLS stack, wrapped by EAP helper */ tls_eap_t *tls_eap; + + /** + * TNCCS instance running over EAP-TNC + */ + tnccs_t *tnccs; + }; METHOD(eap_method_t, initiate, status_t, private_eap_tnc_t *this, eap_payload_t **out) { chunk_t data; + u_int32_t auth_type; + + /* Determine TNC Client Authentication Type */ + switch (this->auth_type) + { + case EAP_TLS: + case EAP_TTLS: + case EAP_PEAP: + auth_type = TNC_AUTH_CERT; + break; + case EAP_MD5: + case EAP_MSCHAPV2: + case EAP_GTC: + case EAP_OTP: + auth_type = TNC_AUTH_PASSWORD; + break; + case EAP_SIM: + case EAP_AKA: + auth_type = TNC_AUTH_SIM; + break; + default: + auth_type = TNC_AUTH_UNKNOWN; + } + this->tnccs->set_auth_type(this->tnccs, auth_type); if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE) { @@ -122,6 +159,18 @@ METHOD(eap_method_t, destroy, void, free(this); } +METHOD(eap_inner_method_t, get_auth_type, eap_type_t, + private_eap_tnc_t *this) +{ + return this->auth_type; +} + +METHOD(eap_inner_method_t, set_auth_type, void, + private_eap_tnc_t *this, eap_type_t type) +{ + this->auth_type = type; +} + /** * Generic private constructor */ @@ -132,19 +181,22 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, int max_msg_count; char* protocol; tnccs_type_t type; - tnccs_t *tnccs; INIT(this, .public = { - .eap_method = { - .initiate = _initiate, - .process = _process, - .get_type = _get_type, - .is_mutual = _is_mutual, - .get_msk = _get_msk, - .get_identifier = _get_identifier, - .set_identifier = _set_identifier, - .destroy = _destroy, + .eap_inner_method = { + .eap_method = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, }, ); @@ -172,10 +224,11 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, free(this); return NULL; } - tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server); - this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, - EAP_TNC_MAX_MESSAGE_LEN, - max_msg_count, FALSE); + this->tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server, + server, peer, TNC_IFT_EAP_1_1); + this->tls_eap = tls_eap_create(EAP_TNC, &this->tnccs->tls, + EAP_TNC_MAX_MESSAGE_LEN, + max_msg_count, FALSE); if (!this->tls_eap) { free(this); diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h index 09abe60fc..8c881f6cf 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.h +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h @@ -23,7 +23,7 @@ typedef struct eap_tnc_t eap_tnc_t; -#include <sa/eap/eap_method.h> +#include <sa/eap/eap_inner_method.h> /** * Implementation of the eap_method_t interface using EAP-TNC. @@ -31,9 +31,9 @@ typedef struct eap_tnc_t eap_tnc_t; struct eap_tnc_t { /** - * Implemented eap_method_t interface. + * Implemented eap_inner_method_t interface. */ - eap_method_t eap_method; + eap_inner_method_t eap_inner_method; }; /** diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c index 464de17ba..eef8d6682 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c @@ -20,6 +20,7 @@ #include <daemon.h> #include <sa/eap/eap_method.h> +#include <sa/eap/eap_inner_method.h> typedef struct private_eap_ttls_server_t private_eap_ttls_server_t; @@ -108,8 +109,11 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this) /** * If configured, start EAP-TNC protocol */ -static status_t start_phase2_tnc(private_eap_ttls_server_t *this) +static status_t start_phase2_tnc(private_eap_ttls_server_t *this, + eap_type_t auth_type) { + eap_inner_method_t *inner_method; + if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings, "%s.plugins.eap-ttls.phase2_tnc", FALSE, charon->name)) { @@ -121,6 +125,9 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this) DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC); return FAILED; } + inner_method = (eap_inner_method_t *)this->method; + inner_method->set_auth_type(inner_method, auth_type); + this->start_phase2_tnc = FALSE; if (this->method->initiate(this->method, &this->out) == NEED_MORE) { @@ -237,7 +244,7 @@ METHOD(tls_application_t, process, status_t, if (lib->settings->get_bool(lib->settings, "%s.plugins.eap-ttls.request_peer_auth", FALSE, charon->name)) { - return start_phase2_tnc(this); + return start_phase2_tnc(this, EAP_TLS); } else { @@ -265,7 +272,7 @@ METHOD(tls_application_t, process, status_t, this->method = NULL; /* continue phase2 with EAP-TNC? */ - return start_phase2_tnc(this); + return start_phase2_tnc(this, type); case NEED_MORE: break; case FAILED: diff --git a/src/libcharon/plugins/lookip/lookip.c b/src/libcharon/plugins/lookip/lookip.c index d5d8d0a63..9887a3a92 100644 --- a/src/libcharon/plugins/lookip/lookip.c +++ b/src/libcharon/plugins/lookip/lookip.c @@ -184,7 +184,7 @@ static void usage(char *cmd) fprintf(stderr, " %s --lookup <IP>\n", cmd); fprintf(stderr, " %s --listen-up\n", cmd); fprintf(stderr, " %s --listen-down\n", cmd); - fprintf(stderr, "Any combination of options is allowed.\n", cmd); + fprintf(stderr, "Any combination of options is allowed.\n"); } int main(int argc, char *argv[]) diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 4ecb63d19..c401bc6f1 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -82,6 +82,9 @@ struct private_stroke_cred_t { bool cachecrl; }; +/** Length of smartcard specifier parts (module, keyid) */ +#define SC_PART_LEN 128 + /** * Kind of smartcard specifier token */ @@ -96,14 +99,14 @@ typedef enum { * Parse a smartcard specifier token */ static smartcard_format_t parse_smartcard(char *smartcard, u_int *slot, - char module[128], char keyid[128]) + char *module, char *keyid) { /* The token has one of the following three formats: * - %smartcard<slot>@<module>:<keyid> * - %smartcard<slot>:<keyid> * - %smartcard:<keyid> */ - char buf[256], *pos; + char buf[2 * SC_PART_LEN], *pos; if (sscanf(smartcard, "%%smartcard%u@%255s", slot, buf) == 2) { @@ -113,8 +116,8 @@ static smartcard_format_t parse_smartcard(char *smartcard, u_int *slot, return SC_FORMAT_INVALID; } *pos++ = '\0'; - snprintf(module, BUF_LEN, "%s", buf); - snprintf(keyid, BUF_LEN, "%s", pos); + snprintf(module, SC_PART_LEN, "%s", buf); + snprintf(keyid, SC_PART_LEN, "%s", pos); return SC_FORMAT_SLOT_MODULE_KEYID; } if (sscanf(smartcard, "%%smartcard%u:%127s", slot, keyid) == 2) @@ -174,7 +177,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, if (strneq(filename, "%smartcard", strlen("%smartcard"))) { smartcard_format_t format; - char module[128], keyid[128]; + char module[SC_PART_LEN], keyid[SC_PART_LEN]; u_int slot; format = parse_smartcard(filename, &slot, module, keyid); @@ -238,7 +241,7 @@ METHOD(stroke_cred_t, load_peer, certificate_t*, if (strneq(filename, "%smartcard", strlen("%smartcard"))) { smartcard_format_t format; - char module[128], keyid[128]; + char module[SC_PART_LEN], keyid[SC_PART_LEN]; u_int slot; format = parse_smartcard(filename, &slot, module, keyid); @@ -702,7 +705,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, FILE *prompt) { chunk_t sc = chunk_empty, secret = chunk_empty; - char smartcard[256], keyid[128], module[128]; + char smartcard[BUF_LEN], keyid[SC_PART_LEN], module[SC_PART_LEN]; private_key_t *key = NULL; u_int slot; chunk_t chunk; diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 2771f0146..e31616cf8 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -516,11 +516,18 @@ static void stroke_loglevel(private_stroke_socket_t *this, DBG1(DBG_CFG, "received stroke: loglevel %d for %s", msg->loglevel.level, msg->loglevel.type); - group = enum_from_name(debug_names, msg->loglevel.type); - if ((int)group < 0) + if (strcaseeq(msg->loglevel.type, "any")) { - fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); - return; + group = DBG_ANY; + } + else + { + group = enum_from_name(debug_names, msg->loglevel.type); + if ((int)group < 0) + { + fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); + return; + } } charon->set_level(charon, group, msg->loglevel.level); } diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am index 5e2c30df9..eba280690 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.am +++ b/src/libcharon/plugins/tnc_imc/Makefile.am @@ -4,7 +4,8 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtncif \ - -I$(top_srcdir)/src/libtnccs + -I$(top_srcdir)/src/libtnccs \ + -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am index eca3b377b..90b3507ce 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.am +++ b/src/libcharon/plugins/tnc_imv/Makefile.am @@ -4,7 +4,8 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtncif \ - -I$(top_srcdir)/src/libtnccs + -I$(top_srcdir)/src/libtnccs \ + -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.am b/src/libcharon/plugins/tnc_tnccs/Makefile.am index c7fc02f7c..9ee9e86ad 100644 --- a/src/libcharon/plugins/tnc_tnccs/Makefile.am +++ b/src/libcharon/plugins/tnc_tnccs/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = \ -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libtncif \ -I$(top_srcdir)/src/libtnccs diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c index 0b623d6ff..6ddda594d 100644 --- a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +20,13 @@ #include <tnc/imc/imc_manager.h> #include <tnc/imv/imv_manager.h> +#include <tncif_identity.h> + +#include <tls.h> + #include <utils/debug.h> +#include <pen/pen.h> +#include <bio/bio_writer.h> #include <collections/linked_list.h> #include <threading/rwlock.h> @@ -158,7 +164,9 @@ METHOD(tnccs_manager_t, remove_method, void, } METHOD(tnccs_manager_t, create_instance, tnccs_t*, - private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server) + private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server, + identification_t *server, identification_t *peer, + tnc_ift_type_t transport) { enumerator_t *enumerator; tnccs_entry_t *entry; @@ -170,7 +178,7 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*, { if (type == entry->type) { - protocol = entry->constructor(is_server); + protocol = entry->constructor(is_server, server, peer, transport); if (protocol) { break; @@ -442,6 +450,44 @@ static TNC_Result str_attribute(TNC_UInt32 buffer_len, } } +/** + * Write the value of a TNC identity list into the buffer + */ +static TNC_Result identity_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + linked_list_t *list) +{ + bio_writer_t *writer; + enumerator_t *enumerator; + u_int32_t count; + chunk_t value; + tncif_identity_t *tnc_id; + TNC_Result result = TNC_RESULT_INVALID_PARAMETER; + + count = list->get_count(list); + writer = bio_writer_create(4 + TNCIF_IDENTITY_MIN_SIZE * count); + writer->write_uint32(writer, count); + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &tnc_id)) + { + tnc_id->build(tnc_id, writer); + } + enumerator->destroy(enumerator); + + value = writer->get_buf(writer); + *value_len = value.len; + if (buffer && buffer_len >= value.len) + { + memcpy(buffer, value.ptr, value.len); + result = TNC_RESULT_SUCCESS; + } + writer->destroy(writer); + + return result; +} + METHOD(tnccs_manager_t, get_attribute, TNC_Result, private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, @@ -487,6 +533,7 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, /* these attributes are supported */ case TNC_ATTRIBUTEID_PRIMARY_IMV_ID: + case TNC_ATTRIBUTEID_AR_IDENTITIES: attribute_match = TRUE; break; @@ -616,15 +663,111 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, version = "1.0"; break; default: - return TNC_RESULT_INVALID_PARAMETER; + return TNC_RESULT_INVALID_PARAMETER; } return str_attribute(buffer_len, buffer, value_len, version); } case TNC_ATTRIBUTEID_IFT_PROTOCOL: - return str_attribute(buffer_len, buffer, value_len, - "IF-T for Tunneled EAP"); + { + char *protocol; + + switch (entry->tnccs->get_transport(entry->tnccs)) + { + case TNC_IFT_EAP_1_0: + case TNC_IFT_EAP_1_1: + case TNC_IFT_EAP_2_0: + protocol = "IF-T for Tunneled EAP"; + break; + case TNC_IFT_TLS_1_0: + case TNC_IFT_TLS_2_0: + protocol = "IF-T for TLS"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, protocol); + } case TNC_ATTRIBUTEID_IFT_VERSION: - return str_attribute(buffer_len, buffer, value_len, "1.1"); + { + char *version; + + switch (entry->tnccs->get_transport(entry->tnccs)) + { + case TNC_IFT_EAP_1_0: + case TNC_IFT_TLS_1_0: + version = "1.0"; + break; + case TNC_IFT_EAP_1_1: + version = "1.1"; + break; + case TNC_IFT_EAP_2_0: + case TNC_IFT_TLS_2_0: + version = "2.0"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, version); + } + case TNC_ATTRIBUTEID_AR_IDENTITIES: + { + linked_list_t *list; + identification_t *peer; + tnccs_t *tnccs; + tncif_identity_t *tnc_id; + u_int32_t id_type, subject_type; + TNC_Result result; + + list = linked_list_create(); + tnccs = entry->tnccs; + peer = tnccs->tls.get_peer_id(&tnccs->tls); + if (peer) + { + switch (peer->get_type(peer)) + { + case ID_IPV4_ADDR: + id_type = TNC_ID_IPV4_ADDR; + subject_type = TNC_SUBJECT_MACHINE; + break; + case ID_IPV6_ADDR: + id_type = TNC_ID_IPV6_ADDR; + subject_type = TNC_SUBJECT_MACHINE; + break; + case ID_FQDN: + id_type = TNC_ID_USER_NAME; + subject_type = TNC_SUBJECT_USER; + break; + case ID_RFC822_ADDR: + id_type = TNC_ID_RFC822_ADDR; + subject_type = TNC_SUBJECT_USER; + break; + case ID_DER_ASN1_DN: + id_type = TNC_ID_DER_ASN1_DN; + subject_type = TNC_SUBJECT_USER; + break; + case ID_DER_ASN1_GN: + id_type = TNC_ID_DER_ASN1_GN; + subject_type = TNC_SUBJECT_UNKNOWN; + break; + default: + id_type = TNC_ID_UNKNOWN; + subject_type = TNC_SUBJECT_UNKNOWN; + } + if (id_type != TNC_ID_UNKNOWN) + { + tnc_id = tncif_identity_create( + pen_type_create(PEN_TCG, id_type), + peer->get_encoding(peer), + pen_type_create(PEN_TCG, subject_type), + pen_type_create(PEN_TCG, + tnccs->get_auth_type(tnccs))); + list->insert_last(list, tnc_id); + } + } + result = identity_attribute(buffer_len, buffer, value_len, list); + list->destroy_offset(list, offsetof(tncif_identity_t, destroy)); + return result; + } default: return TNC_RESULT_INVALID_PARAMETER; } diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index cfc29d6ab..53817c710 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -43,9 +43,9 @@ typedef struct private_tnccs_11_t private_tnccs_11_t; struct private_tnccs_11_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; /** * TNCC if TRUE, TNCS if FALSE @@ -53,6 +53,26 @@ struct private_tnccs_11_t { bool is_server; /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + + /** * Connection ID assigned to this TNCCS connection */ TNC_ConnectionID connection_id; @@ -495,6 +515,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_11_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_11_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_11_t *this) { @@ -528,29 +560,69 @@ METHOD(tls_t, destroy, void, { tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, this->is_server); + this->server->destroy(this->server); + this->peer->destroy(this->peer); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_11_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_11_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_11_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_11_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_11_create(bool is_server) +tnccs_t* tnccs_11_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_11_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, .is_server = is_server, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .max_msg_len = lib->settings->get_int(lib->settings, "%s.plugins.tnccs-11.max_message_size", 45000, diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.h b/src/libcharon/plugins/tnccs_11/tnccs_11.h index 7331fc8cd..531ebb611 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.h +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of the TNC IF-TNCCS 1.1 protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return TNC_IF_TNCCS 1.1 protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return TNC_IF_TNCCS 1.1 protocol stack */ -tls_t *tnccs_11_create(bool is_server); +tnccs_t* tnccs_11_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_11_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 6239b152d..6deaff8a9 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Sansar Choinyanbuu - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -48,9 +48,9 @@ typedef struct private_tnccs_20_t private_tnccs_20_t; struct private_tnccs_20_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; /** * TNCC if TRUE, TNCS if FALSE @@ -58,6 +58,26 @@ struct private_tnccs_20_t { bool is_server; /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + + /** * PB-TNC State Machine */ pb_tnc_state_machine_t *state_machine; @@ -759,6 +779,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_20_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_20_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_20_t *this) { @@ -792,6 +824,8 @@ METHOD(tls_t, destroy, void, { tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, this->is_server); + this->server->destroy(this->server); + this->peer->destroy(this->peer); this->state_machine->destroy(this->state_machine); this->mutex->destroy(this->mutex); this->messages->destroy_offset(this->messages, @@ -799,24 +833,62 @@ METHOD(tls_t, destroy, void, free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_20_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_20_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_20_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_20_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_20_create(bool is_server) +tnccs_t* tnccs_20_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_20_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, .is_server = is_server, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, .state_machine = pb_tnc_state_machine_create(is_server), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .messages = linked_list_create(), diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.h b/src/libcharon/plugins/tnccs_20/tnccs_20.h index 400d1dc12..314935069 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.h +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of the TNC IF-TNCCS 2.0 protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return TNC_IF_TNCCS 2.0 protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return TNC_IF_TNCCS 2.0 protocol stack */ -tls_t *tnccs_20_create(bool is_server); +tnccs_t* tnccs_20_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_20_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c index 03795a947..d4fc6a6f7 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -27,14 +27,35 @@ typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t; struct private_tnccs_dynamic_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; + + /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; /** * Detected TNC IF-TNCCS stack */ tls_t *tls; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + }; /** @@ -66,6 +87,7 @@ METHOD(tls_t, process, status_t, private_tnccs_dynamic_t *this, void *buf, size_t buflen) { tnccs_type_t type; + tnccs_t *tnccs; if (!this->tls) { @@ -76,12 +98,15 @@ METHOD(tls_t, process, status_t, type = determine_tnccs_protocol(*(char*)buf); DBG1(DBG_TNC, "%N protocol detected dynamically", tnccs_type_names, type); - this->tls = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, type, TRUE); - if (!this->tls) + tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE, + this->server, this->peer, this->transport); + if (!tnccs) { DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type); return FAILED; } + tnccs->set_auth_type(tnccs, this->auth_type); + this->tls = &tnccs->tls; } return this->tls->process(this->tls, buf, buflen); } @@ -98,6 +123,18 @@ METHOD(tls_t, is_server, bool, return TRUE; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_dynamic_t *this) { @@ -120,26 +157,66 @@ METHOD(tls_t, destroy, void, private_tnccs_dynamic_t *this) { DESTROY_IF(this->tls); + this->server->destroy(this->server); + this->peer->destroy(this->peer); free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_dynamic_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_dynamic_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_dynamic_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_dynamic_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_dynamic_create(bool is_server) +tnccs_t* tnccs_dynamic_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_dynamic_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, ); return &this->public; diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h index 42410b17f..e4cff74b8 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of a dynamic TNC IF-TNCCS protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return dynamic TNC IF-TNCCS protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return dynamic TNC IF-TNCCS protocol stack */ -tls_t *tnccs_dynamic_create(bool is_server); +tnccs_t* tnccs_dynamic_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_DYNAMIC_H_ @}*/ diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c index d4d374f1b..655b8724a 100644 --- a/src/libcharon/plugins/unity/unity_provider.c +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -58,16 +58,9 @@ METHOD(enumerator_t, attribute_enumerate, bool, { return FALSE; } - if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE && - !ts->is_dynamic(ts) && - ts->to_subnet(ts, &net, &mask)) + if (ts->to_subnet(ts, &net, &mask)) { - if (mask > 0) - { - ts->destroy(ts); - break; - } - net->destroy(net); + break; } ts->destroy(ts); } @@ -99,6 +92,30 @@ METHOD(enumerator_t, attribute_destroy, void, free(this); } +/** + * Check if we should send a configured TS as Split-Include attribute + */ +static bool use_ts(traffic_selector_t *ts) +{ + u_int8_t mask; + host_t *net; + + if (ts->get_type(ts) != TS_IPV4_ADDR_RANGE) + { + return FALSE; + } + if (ts->is_dynamic(ts)) + { + return FALSE; + } + if (!ts->to_subnet(ts, &net, &mask)) + { + return FALSE; + } + net->destroy(net); + return mask > 0; +} + METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_unity_provider_t *this, linked_list_t *pools, identification_t *id, linked_list_t *vips) @@ -127,7 +144,14 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); while (current->remove_first(current, (void**)&ts) == SUCCESS) { - list->insert_last(list, ts); + if (use_ts(ts)) + { + list->insert_last(list, ts); + } + else + { + ts->destroy(ts); + } } current->destroy(current); } diff --git a/src/libcharon/sa/eap/eap_inner_method.h b/src/libcharon/sa/eap/eap_inner_method.h new file mode 100644 index 000000000..500852965 --- /dev/null +++ b/src/libcharon/sa/eap/eap_inner_method.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_inner_method eap_inner_method + * @{ @ingroup eap + */ + +#ifndef EAP_INNER_METHOD_H_ +#define EAP_INNER_METHOD_H_ + +typedef struct eap_inner_method_t eap_inner_method_t; + +#include <library.h> + +#include "eap_method.h" + +/** + * Interface of a weak inner EAP method like EAP-TNC or PT-EAP + * that must be encapsulated in a strong TLS-based EAP method + */ +struct eap_inner_method_t { + + /* + * Public EAP method interface + */ + eap_method_t eap_method; + + /* + * Get type of outer EAP authentication method + * + * @return outer EAP authentication type + */ + eap_type_t (*get_auth_type)(eap_inner_method_t *this); + + /* + * Set type of outer EAP Client/Server authentication + * + * @param type outer EAP authentication type + */ + void (*set_auth_type)(eap_inner_method_t *this, eap_type_t type); + +}; + +#endif /** EAP_INNER_METHOD_H_ @}*/ diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index 37a20e7f3..625859a3f 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -1026,9 +1026,8 @@ struct ike_sa_t { * * When rekeying is completed, all CHILD_SAs, the virtual IP and all * outstanding tasks are moved from other to this. - * As this call may initiate inherited tasks, a status is returned. * - * @param other other task to inherit from + * @param other other IKE SA to inherit from */ void (*inherit) (ike_sa_t *this, ike_sa_t *other); diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 5cb1490eb..ea0117c54 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -630,6 +630,8 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message_t *message; host_t *me, *other; bool delete = FALSE, hook = FALSE; + ike_sa_id_t *id = NULL; + u_int64_t responder_spi; status_t status; me = request->get_destination(request); @@ -680,10 +682,15 @@ static status_t build_response(private_task_manager_t *this, message_t *request) } enumerator->destroy(enumerator); - /* remove resonder SPI if IKE_SA_INIT failed */ + /* RFC 5996, section 2.6 mentions that in the event of a failure during + * IKE_SA_INIT the responder's SPI will be 0 in the response, while it + * actually explicitly allows it to be non-zero. Since we use the responder + * SPI to create hashes in the IKE_SA manager we can only set the SPI to + * zero temporarily, otherwise checking the SA in would fail. */ if (delete && request->get_exchange_type(request) == IKE_SA_INIT) { - ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa); + id = this->ike_sa->get_id(this->ike_sa); + responder_spi = id->get_responder_spi(id); id->set_responder_spi(id, 0); } @@ -693,6 +700,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request) status = this->ike_sa->generate_message(this->ike_sa, message, &this->responding.packet); message->destroy(message); + if (id) + { + id->set_responder_spi(id, responder_spi); + } if (status != SUCCESS) { charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index 69b23e1df..6c0ae19c7 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -170,8 +170,8 @@ METHOD(trap_manager_t, install, u_int32_t, if (status != SUCCESS) { DBG1(DBG_CFG, "installing trap failed"); - child_sa->destroy(child_sa); reqid = 0; + /* hold off destroying the CHILD_SA until we released the lock */ } else { @@ -184,6 +184,10 @@ METHOD(trap_manager_t, install, u_int32_t, } this->lock->unlock(this->lock); + if (status != SUCCESS) + { + child_sa->destroy(child_sa); + } if (found) { destroy_entry(found); diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.c b/src/libimcv/ietf/ietf_attr_numeric_version.c index d4e79cc32..797205473 100644 --- a/src/libimcv/ietf/ietf_attr_numeric_version.c +++ b/src/libimcv/ietf/ietf_attr_numeric_version.c @@ -134,8 +134,8 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint32(writer, this->major_version); writer->write_uint32(writer, this->minor_version); writer->write_uint32(writer, this->build); - writer->write_uint32(writer, this->service_pack_major); - writer->write_uint32(writer, this->service_pack_minor); + writer->write_uint16(writer, this->service_pack_major); + writer->write_uint16(writer, this->service_pack_minor); this->value = chunk_clone(writer->get_buf(writer)); writer->destroy(writer); @@ -280,4 +280,3 @@ pa_tnc_attr_t *ietf_attr_numeric_version_create_from_data(chunk_t data) return &this->public.pa_tnc_attribute; } - diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index 6a33e396c..99683bc72 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -18,8 +18,11 @@ #include "ietf/ietf_attr_assess_result.h" #include <tncif_names.h> +#include <tncif_identity.h> #include <utils/debug.h> +#include <collections/linked_list.h> +#include <bio/bio_reader.h> #include <threading/rwlock.h> typedef struct private_imv_agent_t private_imv_agent_t; @@ -352,12 +355,59 @@ static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID return 0; } +/** + * Read a TNC identity attribute + */ +static linked_list_t* get_identity_attribute(private_imv_agent_t *this, + TNC_ConnectionID id, + TNC_AttributeID attribute_id) +{ + TNC_UInt32 len; + char buf[2048]; + u_int32_t count; + tncif_identity_t *tnc_id; + bio_reader_t *reader; + linked_list_t *list; + + list = linked_list_create(); + + if (!this->get_attribute || + this->get_attribute(this->id, id, attribute_id, sizeof(buf), buf, &len) + != TNC_RESULT_SUCCESS || len > sizeof(buf)) + { + return list; + } + + reader = bio_reader_create(chunk_create(buf, len)); + if (!reader->read_uint32(reader, &count)) + { + goto end; + } + while (count--) + { + tnc_id = tncif_identity_create_empty(); + if (!tnc_id->process(tnc_id, reader)) + { + tnc_id->destroy(tnc_id); + goto end; + } + list->insert_last(list, tnc_id); + } + +end: + reader->destroy(reader); + return list; + } + METHOD(imv_agent_t, create_state, TNC_Result, private_imv_agent_t *this, imv_state_t *state) { TNC_ConnectionID conn_id; char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL; bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE; + linked_list_t *ar_identities; + enumerator_t *enumerator; + tncif_identity_t *tnc_id; u_int32_t max_msg_len; conn_id = state->get_connection_id(state); @@ -378,6 +428,7 @@ METHOD(imv_agent_t, create_state, TNC_Result, t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL); t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION); max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE); + ar_identities = get_identity_attribute(this, conn_id, TNC_ATTRIBUTEID_AR_IDENTITIES); state->set_flags(state, has_long, has_excl); state->set_max_msg_len(state, max_msg_len); @@ -389,6 +440,64 @@ METHOD(imv_agent_t, create_state, TNC_Result, DBG2(DBG_IMV, " over %s %s with maximum PA-TNC message size of %u bytes", t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len); + enumerator = ar_identities->create_enumerator(ar_identities); + while (enumerator->enumerate(enumerator, &tnc_id)) + { + pen_type_t id_type, subject_type, auth_type; + int tcg_id_type, tcg_subject_type, tcg_auth_type; + chunk_t id_value; + id_type_t ike_type; + identification_t *id; + + id_type = tnc_id->get_identity_type(tnc_id); + id_value = tnc_id->get_identity_value(tnc_id); + subject_type = tnc_id->get_subject_type(tnc_id); + auth_type = tnc_id->get_auth_type(tnc_id); + + tcg_id_type = (id_type.vendor_id == PEN_TCG) ? + id_type.type : TNC_ID_UNKNOWN; + tcg_subject_type = (subject_type.vendor_id == PEN_TCG) ? + subject_type.type : TNC_SUBJECT_UNKNOWN; + tcg_auth_type = (auth_type.vendor_id == PEN_TCG) ? + auth_type.type : TNC_AUTH_UNKNOWN; + + switch (tcg_id_type) + { + case TNC_ID_IPV4_ADDR: + ike_type = ID_IPV4_ADDR; + break; + case TNC_ID_IPV6_ADDR: + ike_type = ID_IPV6_ADDR; + break; + case TNC_ID_FQDN: + case TNC_ID_USER_NAME: + ike_type = ID_FQDN; + break; + case TNC_ID_RFC822_ADDR: + ike_type = ID_RFC822_ADDR; + break; + case TNC_ID_DER_ASN1_DN: + ike_type = ID_DER_ASN1_DN; + break; + case TNC_ID_DER_ASN1_GN: + ike_type = ID_IPV4_ADDR; + break; + case TNC_ID_UNKNOWN: + default: + ike_type = ID_KEY_ID; + break; + } + + id = identification_create_from_encoding(ike_type, id_value); + DBG2(DBG_IMV, "%N identity '%Y' authenticated by %N", + TNC_Subject_names, tcg_subject_type, id, + TNC_Authentication_names, tcg_auth_type); + id->destroy(id); + } + enumerator->destroy(enumerator); + + ar_identities->destroy_offset(ar_identities, + offsetof(tncif_identity_t, destroy)); free(tnccs_p); free(tnccs_v); free(t_p); diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 92f47519d..2c49cb01d 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -156,7 +156,7 @@ METHOD(os_info_t, get_uptime, time_t, { const char proc_uptime[] = "/proc/uptime"; FILE *file; - time_t uptime; + u_int uptime; file = fopen(proc_uptime, "r"); if (!file) @@ -214,7 +214,7 @@ METHOD(os_info_t, get_setting, chunk_t, typedef struct { /** - * implements enumerator_t + * implements enumerator_t */ enumerator_t public; @@ -273,6 +273,7 @@ static bool package_enumerator_enumerate(package_enumerator_t *this, ...) pos = strchr(pos, '\t'); if (!pos) { + va_end(args); return FALSE; } name->len = pos++ - name->ptr; @@ -569,6 +570,8 @@ os_info_t *os_info_create(void) version.len = strlen(version.ptr); version = chunk_clone(version); + + type = os_type_from_name(name); } else { diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c index 63445f3a1..d3aceee06 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.c +++ b/src/libimcv/pa_tnc/pa_tnc_msg.c @@ -284,6 +284,18 @@ METHOD(pa_tnc_msg_t, process, status_t, } DBG3(DBG_TNC, "%B", &value); + if (vendor_id == PEN_RESERVED) + { + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + 1); + goto err; + } + if (type == IETF_ATTR_RESERVED) + { + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + 4); + goto err; + } attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes, vendor_id, type, value); if (!attr) diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index 65538df07..ecc6cfc4f 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -360,7 +360,9 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) out_msg->add_attribute(out_msg, attr); } - if (fatal_error) + if (fatal_error || + (os_state->get_attribute_request(os_state) && + os_state->get_info(os_state, NULL, NULL, NULL) == NULL)) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, @@ -371,7 +373,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) /* If all Installed Packages attributes were received, go to assessment */ if (!assessment && !os_state->get_package_request(os_state) && - !os_state->get_angel_count(os_state)) + !os_state->get_angel_count(os_state) && + os_state->get_info(os_state, NULL, NULL, NULL)) { int device_id, count, count_update, count_blacklist, count_ok; u_int os_settings; @@ -518,6 +521,8 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, { imv_state_t *state; imv_os_state_t *os_state; + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; TNC_Result result = TNC_RESULT_SUCCESS; if (!imv_os) @@ -531,6 +536,18 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, } os_state = (imv_os_state_t*)state; + state->get_recommendation(state, &rec, &eval); + + /* + * Don't send an attribute request if an evaluation is available + * or if an attribute request has already been sent + */ + if (eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW || + os_state->get_attribute_request(os_state)) + { + return TNC_RESULT_SUCCESS; + } + if (os_state->get_info(os_state, NULL, NULL, NULL) == NULL) { imv_msg_t *out_msg; @@ -548,6 +565,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED); attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED); out_msg->add_attribute(out_msg, attr); + os_state->set_attribute_request(os_state, TRUE); /* send PA-TNC message with excl flag not set */ result = out_msg->send(out_msg, FALSE); diff --git a/src/libimcv/plugins/imv_os/imv_os_database.c b/src/libimcv/plugins/imv_os/imv_os_database.c index eb4c2acbc..c6db9953f 100644 --- a/src/libimcv/plugins/imv_os/imv_os_database.c +++ b/src/libimcv/plugins/imv_os/imv_os_database.c @@ -68,8 +68,8 @@ METHOD(imv_os_database_t, check_packages, status_t, pos = memchr(os_version.ptr, ' ', os_version.len); os_version_len = pos ? (pos - os_version.ptr) : os_version.len; product = malloc(os_name.len + 1 + os_version_len + 1); - sprintf(product, "%.*s %.*s", os_name.len, os_name.ptr, - os_version_len, os_version.ptr); + sprintf(product, "%.*s %.*s", (int)os_name.len, os_name.ptr, + (int)os_version_len, os_version.ptr); } DBG1(DBG_IMV, "processing installed '%s' packages", product); @@ -148,7 +148,7 @@ METHOD(imv_os_database_t, check_packages, status_t, } } e->destroy(e); - + if (found) { if (match) diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index f16983611..00e0424fb 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -137,6 +137,11 @@ struct private_imv_os_state_t { int count_ok; /** + * Attribute request sent - mandatory response expected + */ + bool attribute_request; + + /** * OS Installed Package request sent - mandatory response expected */ bool package_request; @@ -448,8 +453,8 @@ METHOD(imv_os_state_t, set_info, void, /* OS info is a concatenation of OS name and OS version */ free(this->info); this->info = malloc(len); - snprintf(this->info, len, "%.*s %.*s", name.len, name.ptr, - version.len, version.ptr); + snprintf(this->info, len, "%.*s %.*s", (int)name.len, name.ptr, + (int)version.len, version.ptr); this->type = type; this->name = chunk_clone(name); this->version = chunk_clone(version); @@ -506,6 +511,18 @@ METHOD(imv_os_state_t, get_count, void, } } +METHOD(imv_os_state_t, set_attribute_request, void, + private_imv_os_state_t *this, bool set) +{ + this->attribute_request = set; +} + +METHOD(imv_os_state_t, get_attribute_request, bool, + private_imv_os_state_t *this) +{ + return this->attribute_request; +} + METHOD(imv_os_state_t, set_package_request, void, private_imv_os_state_t *this, bool set) { @@ -597,6 +614,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .get_info = _get_info, .set_count = _set_count, .get_count = _get_count, + .set_attribute_request = _set_attribute_request, + .get_attribute_request = _get_attribute_request, .set_package_request = _set_package_request, .get_package_request = _get_package_request, .set_device_id = _set_device_id, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 05abdbb6c..d3e319171 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -87,6 +87,21 @@ struct imv_os_state_t { */ void (*get_count)(imv_os_state_t *this, int *count, int *count_update, int *count_blacklist, int *count_ok); + + /** + * Set/reset attribute request status + * + * @param set TRUE to set, FALSE to clear + */ + void (*set_attribute_request)(imv_os_state_t *this, bool set); + + /** + * Get attribute request status + * + * @return TRUE if set, FALSE if unset + */ + bool (*get_attribute_request)(imv_os_state_t *this); + /** * Set/reset OS Installed Packages request status * diff --git a/src/libimcv/plugins/imv_os/pacman.c b/src/libimcv/plugins/imv_os/pacman.c index feb3ff399..f5f52885d 100644 --- a/src/libimcv/plugins/imv_os/pacman.c +++ b/src/libimcv/plugins/imv_os/pacman.c @@ -97,13 +97,13 @@ static time_t extract_time(char *line) char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int i; - + if (sscanf(line, "Generated: %3s %3s %2d %2d:%2d:%2d %4d UTC", wday, mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) != 7) { return UNDEFINED_TIME; } - t.tm_isdst = 0; + t.tm_isdst = 0; t.tm_year -= 1900; t.tm_mon = 12; @@ -173,7 +173,7 @@ static void process_packages(char *filename, char *product, bool update) e->destroy(e); } if (!pid) - { + { if (db->execute(db, &pid, "INSERT INTO products (name) VALUES (?)", DB_TEXT, product) != 1) { @@ -221,8 +221,8 @@ static void process_packages(char *filename, char *product, bool update) pos = strchr(line, ' '); if (!pos) { - fprintf(stderr, "could not extract package name from '%.*s'", - strlen(line)-1, line); + fprintf(stderr, "could not extract package name from '%.*s'\n", + (int)(strlen(line)-1), line); errored++; continue; } @@ -240,8 +240,8 @@ static void process_packages(char *filename, char *product, bool update) } else { - fprintf(stderr, "could not extract package version from '%.*s'\n", - strlen(line)-1, line); + fprintf(stderr, "could not extract package version from " + "'%.*s'\n", (int)(strlen(line)-1), line); errored++; continue; } @@ -275,7 +275,7 @@ static void process_packages(char *filename, char *product, bool update) e->destroy(e); } if (!gid && security) - { + { if (db->execute(db, &gid, "INSERT INTO packages (name) VALUES (?)", DB_TEXT, package) != 1) { @@ -289,7 +289,7 @@ static void process_packages(char *filename, char *product, bool update) } /* check for package versions already in database */ - e = db->query(db, + e = db->query(db, "SELECT id, release, security, time FROM versions " "WHERE package = ? AND product = ?", DB_INT, gid, DB_INT, pid, DB_INT, DB_TEXT, DB_INT, DB_INT); @@ -350,7 +350,7 @@ static void process_packages(char *filename, char *product, bool update) } if ((!vid && security) || (vid && !vid_update)) - { + { printf("%s (%s) %s\n", package, version, security ? "[s]" : ""); if (db->execute(db, &vid, diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c index 4c814bf7b..91e9766d0 100644 --- a/src/libpts/plugins/imv_attestation/attest_db.c +++ b/src/libpts/plugins/imv_attestation/attest_db.c @@ -827,7 +827,7 @@ METHOD(attest_db_t, list_devices, void, { if (id != last_id) { - printf("%4d: %.*s\n", id, value.len, value.ptr); + printf("%4d: %.*s\n", id, (int)value.len, value.ptr); device_count++; last_id = id; } @@ -1543,7 +1543,7 @@ METHOD(attest_db_t, add, bool, hashes_added); if (ima) { - printf(", %d ima hashes", ima_hashes_added, ima_hashes_updated); + printf(", %d ima hashes", ima_hashes_added); hasher->destroy(hasher); } printf(", updated %d file hashes", hashes_updated); diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index ec5ac1e56..84a9961c8 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -344,8 +344,8 @@ METHOD(pts_t, set_platform_info, void, /* platform info is a concatenation of OS name and OS version */ free(this->platform_info); this->platform_info = malloc(len); - snprintf(this->platform_info, len, "%.*s %.*s", name.len, name.ptr, - version.len, version.ptr); + snprintf(this->platform_info, len, "%.*s %.*s", (int)name.len, name.ptr, + (int)version.len, version.ptr); } METHOD(pts_t, get_tpm_version_info, bool, diff --git a/src/libstrongswan/networking/host.c b/src/libstrongswan/networking/host.c index 81af1da27..bffa96064 100644 --- a/src/libstrongswan/networking/host.c +++ b/src/libstrongswan/networking/host.c @@ -362,7 +362,6 @@ host_t *host_create_from_string_and_family(char *string, int family, u_int16_t port) { union { - sockaddr_t sockaddr; struct sockaddr_in v4; struct sockaddr_in6 v6; } addr; @@ -399,8 +398,8 @@ host_t *host_create_from_string_and_family(char *string, int family, return NULL; } addr.v6.sin6_port = htons(port); - addr.sockaddr.sa_family = AF_INET6; - return host_create_from_sockaddr(&addr.sockaddr); + addr.v6.sin6_family = AF_INET6; + return host_create_from_sockaddr((sockaddr_t*)&addr); case AF_INET: if (strchr(string, ':')) { /* do not try to convert v6 addresses for v4 family */ @@ -412,8 +411,8 @@ host_t *host_create_from_string_and_family(char *string, int family, return NULL; } addr.v4.sin_port = htons(port); - addr.sockaddr.sa_family = AF_INET; - return host_create_from_sockaddr(&addr.sockaddr); + addr.v4.sin_family = AF_INET; + return host_create_from_sockaddr((sockaddr_t*)&addr); default: return NULL; } diff --git a/src/libstrongswan/pen/pen.c b/src/libstrongswan/pen/pen.c index b1b0731d4..b8537398f 100644 --- a/src/libstrongswan/pen/pen.c +++ b/src/libstrongswan/pen/pen.c @@ -41,7 +41,8 @@ ENUM_NEXT(pen_names, PEN_ITA, PEN_ITA, PEN_FHH, "ITA-HSR"); ENUM_NEXT(pen_names, PEN_OPENPTS, PEN_OPENPTS, PEN_ITA, "OpenPTS"); -ENUM_NEXT(pen_names, PEN_RESERVED, PEN_RESERVED, PEN_OPENPTS, +ENUM_NEXT(pen_names, PEN_UNASSIGNED, PEN_RESERVED, PEN_OPENPTS, + "Unassigned", "Reserved"); ENUM_END(pen_names, PEN_RESERVED); diff --git a/src/libstrongswan/pen/pen.h b/src/libstrongswan/pen/pen.h index 9d5df7d49..351c71b97 100644 --- a/src/libstrongswan/pen/pen.h +++ b/src/libstrongswan/pen/pen.h @@ -30,20 +30,21 @@ typedef enum pen_t pen_t; typedef struct pen_type_t pen_type_t; enum pen_t { - PEN_IETF = 0x000000, /* 0 */ - PEN_IBM = 0x000002, /* 2 */ - PEN_MICROSOFT = 0x000137, /* 311 */ - PEN_REDHAT = 0x000908, /* 2312 */ - PEN_OSC = 0x002358, /* 9048 */ - PEN_DEBIAN = 0x002572, /* 9586 */ - PEN_GOOGLE = 0x002B79, /* 11129 */ - PEN_TCG = 0x005597, /* 21911 */ - PEN_CANONICAL = 0x007132, /* 28978 */ - PEN_FEDORA = 0x0076C1, /* 30401 */ - PEN_FHH = 0x0080ab, /* 32939 */ - PEN_ITA = 0x00902a, /* 36906 */ - PEN_OPENPTS = 0x00950e, /* 38158 */ - PEN_RESERVED = 0xffffff, /* 16777215 */ + PEN_IETF = 0x000000, /* 0 */ + PEN_IBM = 0x000002, /* 2 */ + PEN_MICROSOFT = 0x000137, /* 311 */ + PEN_REDHAT = 0x000908, /* 2312 */ + PEN_OSC = 0x002358, /* 9048 */ + PEN_DEBIAN = 0x002572, /* 9586 */ + PEN_GOOGLE = 0x002B79, /* 11129 */ + PEN_TCG = 0x005597, /* 21911 */ + PEN_CANONICAL = 0x007132, /* 28978 */ + PEN_FEDORA = 0x0076C1, /* 30401 */ + PEN_FHH = 0x0080ab, /* 32939 */ + PEN_ITA = 0x00902a, /* 36906 */ + PEN_OPENPTS = 0x00950e, /* 38158 */ + PEN_UNASSIGNED = 0xfffffe, /* 16777214 */ + PEN_RESERVED = 0xffffff, /* 16777215 */ }; /** diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index c68b74f96..b49961a90 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -21,7 +21,7 @@ #include "curl_fetcher.h" -#define DEFAULT_TIMEOUT 10 +#define CONNECT_TIMEOUT 10 typedef struct private_curl_fetcher_t private_curl_fetcher_t; @@ -48,6 +48,11 @@ struct private_curl_fetcher_t { * Callback function */ fetcher_callback_t cb; + + /** + * Timeout for a transfer + */ + long timeout; }; /** @@ -94,7 +99,11 @@ METHOD(fetcher_t, fetch, status_t, curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error); curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT); + if (this->timeout) + { + curl_easy_setopt(this->curl, CURLOPT_TIMEOUT, this->timeout); + } + curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT); curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)curl_cb); curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, &data); if (this->headers) @@ -160,8 +169,7 @@ METHOD(fetcher_t, set_option, bool, } case FETCH_TIMEOUT: { - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, - va_arg(args, u_int)); + this->timeout = va_arg(args, u_int); break; } case FETCH_CALLBACK: @@ -211,4 +219,3 @@ curl_fetcher_t *curl_fetcher_create() } return &this->public; } - diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 4dc5663f1..ff3382473 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_DH + #include <openssl/dh.h> #include "openssl_diffie_hellman.h" @@ -193,3 +197,5 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( return &this->public; } + +#endif /* OPENSSL_NO_DH */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index d350d050b..12f264267 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_private_key.h" #include "openssl_ec_public_key.h" @@ -423,5 +423,4 @@ error: destroy(this); return NULL; } -#endif /* OPENSSL_NO_EC */ - +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 3f5125b31..c8a45f79a 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_public_key.h" #include "openssl_util.h" @@ -360,5 +360,5 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type, } return &this->public; } -#endif /* OPENSSL_NO_EC */ +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index 5d05425d3..4f0bcc7c3 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hmac.c +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -35,6 +35,10 @@ * THE SOFTWARE. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_HMAC + #include <openssl/evp.h> #include <openssl/hmac.h> @@ -189,3 +193,4 @@ signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo) return NULL; } +#endif /* OPENSSL_NO_HMAC */ diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index 663397e59..ccc426235 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -615,7 +615,7 @@ static bool decrypt(private_openssl_pkcs7_t *this, continue; } chunk = openssl_asn1_str2chunk(sn); - if (chunk.len && chunk.ptr[0] | 0x80) + if (chunk.len && chunk.ptr[0] & 0x80) { /* if MSB is set, append a zero to make it non-negative */ chunk = chunk_cata("cc", chunk_from_thing(zero), chunk); } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 926e5928c..fb86a6bf1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_private_key.h" #include "openssl_rsa_public_key.h" @@ -599,3 +603,4 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, #endif /* OPENSSL_NO_ENGINE */ } +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 0da5d2514..bf71d7901 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_public_key.h" #include <utils/debug.h> @@ -388,3 +392,5 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type, destroy(this); return NULL; } + +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 8501e2cd4..8c00e6a57 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -13,6 +13,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_SHA1 + #include "openssl_sha1_prf.h" #include <openssl/sha.h> @@ -143,3 +147,4 @@ openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo) return &this->public; } +#endif /* OPENSSL_NO_SHA1 */ diff --git a/src/libstrongswan/plugins/rdrand/rdrand_rng.h b/src/libstrongswan/plugins/rdrand/rdrand_rng.h index d15a48224..3fb49ce6e 100644 --- a/src/libstrongswan/plugins/rdrand/rdrand_rng.h +++ b/src/libstrongswan/plugins/rdrand/rdrand_rng.h @@ -15,7 +15,7 @@ /** * @defgroup rdrand_rng rdrand_rng - * @{ @ingroup rdrand + * @{ @ingroup rdrand_p */ #ifndef RDRAND_RNG_H_ diff --git a/src/libstrongswan/plugins/soup/soup_plugin.c b/src/libstrongswan/plugins/soup/soup_plugin.c index b21b28b9f..1260a5a60 100644 --- a/src/libstrongswan/plugins/soup/soup_plugin.c +++ b/src/libstrongswan/plugins/soup/soup_plugin.c @@ -66,10 +66,13 @@ plugin_t *soup_plugin_create() private_soup_plugin_t *this; g_type_init(); + +#if !GLIB_CHECK_VERSION(2,23,0) if (!g_thread_get_initialized()) { g_thread_init(NULL); } +#endif INIT(this, .public = { diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index bf0224c5f..fc2fe4a3e 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -460,7 +460,7 @@ int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, bool utc = *((bool*)(args[1]));; struct tm t; - if (time == UNDEFINED_TIME) + if (*time == UNDEFINED_TIME) { return print_in_hook(data, "--- -- --:--:--%s----", utc ? " UTC " : " "); diff --git a/src/libtls/tls.c b/src/libtls/tls.c index dea08e3eb..85a05a00b 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -359,6 +359,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tls_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tls_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_version, tls_version_t, private_tls_t *this) { @@ -457,6 +469,8 @@ tls_t *tls_create(bool is_server, identification_t *server, .process = _process, .build = _build, .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, .get_version = _get_version, .set_version = _set_version, .get_purpose = _get_purpose, diff --git a/src/libtls/tls.h b/src/libtls/tls.h index 6b4876f73..c8186b829 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -193,6 +193,20 @@ struct tls_t { bool (*is_server)(tls_t *this); /** + * Return the server identity + * + * @return Server identity + */ + identification_t* (*get_server_id)(tls_t *this); + + /** + * Return the peer identity + * + * @return Peer identity + */ + identification_t* (*get_peer_id)(tls_t *this); + + /** * Get the negotiated TLS/SSL version. * * @return negotiated TLS version diff --git a/src/libtnccs/Makefile.am b/src/libtnccs/Makefile.am index 449d32d92..c6492d8d3 100644 --- a/src/libtnccs/Makefile.am +++ b/src/libtnccs/Makefile.am @@ -1,5 +1,8 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libtncif +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtls ipseclib_LTLIBRARIES = libtnccs.la diff --git a/src/libtnccs/tnc/tnccs/tnccs.h b/src/libtnccs/tnc/tnccs/tnccs.h index c3020d7c3..81d393684 100644 --- a/src/libtnccs/tnc/tnccs/tnccs.h +++ b/src/libtnccs/tnc/tnccs/tnccs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ typedef struct tnccs_t tnccs_t; typedef enum tnccs_type_t tnccs_type_t; +typedef enum tnc_ift_type_t tnc_ift_type_t; #include <tncif.h> #include <tncifimc.h> @@ -34,6 +35,8 @@ typedef enum tnccs_type_t tnccs_type_t; #include <library.h> #include <plugins/plugin.h> +#include <tls.h> + /** * Type of TNC Client/Server protocol */ @@ -46,17 +49,68 @@ enum tnccs_type_t { }; /** + * Type of TNC Transport protocol + */ +enum tnc_ift_type_t { + TNC_IFT_UNKNOWN, + TNC_IFT_EAP_1_0, + TNC_IFT_EAP_1_1, + TNC_IFT_EAP_2_0, + TNC_IFT_TLS_1_0, + TNC_IFT_TLS_2_0 +}; + +/** * enum names for tnccs_type_t. */ extern enum_name_t *tnccs_type_names; /** + * TNCCS public interface + */ +struct tnccs_t { + + /** + * Implements tls_t + */ + tls_t tls; + + /** + * Get underlying TNC IF-T transport protocol + */ + tnc_ift_type_t (*get_transport)(tnccs_t *this); + + /** + * Set underlying TNC IF-T transport protocol + + */ + void (*set_transport)(tnccs_t *this, tnc_ift_type_t transport); + + /** + * Get type of TNC Client authentication + */ + u_int32_t (*get_auth_type)(tnccs_t *this); + + /** + * Set type of TNC Client authentication + */ + void (*set_auth_type)(tnccs_t *this, u_int32_t auth_type); + +}; + +/** * Constructor definition for a pluggable TNCCS protocol implementation. * * @param is_server TRUE if TNC Server, FALSE if TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying TNC IF-T transport protocol used * @return implementation of the tnccs_t interface */ -typedef tnccs_t *(*tnccs_constructor_t)(bool is_server); +typedef tnccs_t *(*tnccs_constructor_t)(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); /** * Callback function adding a message to a TNCCS batch diff --git a/src/libtnccs/tnc/tnccs/tnccs_manager.h b/src/libtnccs/tnc/tnccs/tnccs_manager.h index cbf2dc0e9..4ab9d7e18 100644 --- a/src/libtnccs/tnc/tnccs/tnccs_manager.h +++ b/src/libtnccs/tnc/tnccs/tnccs_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -56,10 +56,15 @@ struct tnccs_manager_t { * * @param type type of the TNCCS protocol * @param is_server TRUE if TNC Server, FALSE if TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying TNC IF-T transport protocol used * @return TNCCS protocol instance, NULL if no constructor found */ tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type, - bool is_server); + bool is_server, identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); /** * Create a TNCCS connection and assign a unique connection ID as well a diff --git a/src/libtncif/Makefile.am b/src/libtncif/Makefile.am index cc262ffca..6da1201f3 100644 --- a/src/libtncif/Makefile.am +++ b/src/libtncif/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libtncif.la libtncif_la_SOURCES = \ tncif.h tncifimc.h tncifimv.h tncif_names.h tncif_names.c \ +tncif_identity.h tncif_identity.c \ tncif_pa_subtypes.h tncif_pa_subtypes.c EXTRA_DIST = Android.mk diff --git a/src/libtncif/tncif_identity.c b/src/libtncif/tncif_identity.c new file mode 100644 index 000000000..66de83dbd --- /dev/null +++ b/src/libtncif/tncif_identity.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "tncif_identity.h" + +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <pen/pen.h> +#include <utils/debug.h> + +typedef struct private_tncif_identity_t private_tncif_identity_t; + +/** + * TNC Identity List Attribute Format (TCG TNC IF-IMV 1.4 Draft) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Count | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Identity Type Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Value Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * ~ Identity Value ~ + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Subject Type Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Subject Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Authentication Method Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Authentication Method | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a tncif_identity_t object. + * + */ +struct private_tncif_identity_t { + + /** + * Public tncif_identity_t interface. + */ + tncif_identity_t public; + + /** + * Identity Type + */ + pen_type_t identity_type; + + /** + * Identity Value + */ + chunk_t identity_value; + + /** + * Subject Type + */ + pen_type_t subject_type; + + /** + * Authentication Type + */ + pen_type_t auth_type; +}; + +METHOD(tncif_identity_t, get_identity_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->identity_type; +} + +METHOD(tncif_identity_t, get_identity_value, chunk_t, + private_tncif_identity_t *this) +{ + return this->identity_value; +} + +METHOD(tncif_identity_t, get_subject_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->subject_type; +} + +METHOD(tncif_identity_t, get_auth_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->auth_type; +} + +METHOD(tncif_identity_t, build, void, + private_tncif_identity_t *this, bio_writer_t *writer) +{ + writer->write_uint32(writer, this->identity_type.vendor_id); + writer->write_uint32(writer, this->identity_type.type); + writer->write_data32(writer, this->identity_value); + writer->write_uint32(writer, this->subject_type.vendor_id); + writer->write_uint32(writer, this->subject_type.type); + writer->write_uint32(writer, this->auth_type.vendor_id); + writer->write_uint32(writer, this->auth_type.type); +} + +METHOD(tncif_identity_t, process, bool, + private_tncif_identity_t *this, bio_reader_t *reader) +{ + u_int8_t reserved; + u_int32_t vendor_id, type; + chunk_t identity_value; + + if (reader->remaining(reader) < TNCIF_IDENTITY_MIN_SIZE) + { + return FALSE; + } + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->identity_type = pen_type_create(vendor_id, type); + + if (!reader->read_data32(reader, &identity_value) || + reader->remaining(reader) < 16) + { + return FALSE; + } + this->identity_value = chunk_clone(identity_value); + + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->subject_type = pen_type_create(vendor_id, type); + + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->auth_type = pen_type_create(vendor_id, type); + + return TRUE; +} + +METHOD(tncif_identity_t, destroy, void, + private_tncif_identity_t *this) +{ + free(this->identity_value.ptr); + free(this); +} + + +/** + * See header + */ +tncif_identity_t *tncif_identity_create_empty(void) +{ + private_tncif_identity_t *this; + + INIT(this, + .public = { + .get_identity_type = _get_identity_type, + .get_identity_value = _get_identity_value, + .get_subject_type = _get_subject_type, + .get_auth_type = _get_auth_type, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + ); + + return &this->public; +} + +/** + * See header + */ +tncif_identity_t *tncif_identity_create(pen_type_t identity_type, + chunk_t identity_value, + pen_type_t subject_type, + pen_type_t auth_type) +{ + private_tncif_identity_t *this; + + this = (private_tncif_identity_t*)tncif_identity_create_empty(); + this->identity_type = identity_type; + this->identity_value = chunk_clone(identity_value); + this->subject_type = subject_type; + this->auth_type = auth_type; + + return &this->public; +} + diff --git a/src/libtncif/tncif_identity.h b/src/libtncif/tncif_identity.h new file mode 100644 index 000000000..3ef0dd4f0 --- /dev/null +++ b/src/libtncif/tncif_identity.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup libtncif libtncif + * + * @addtogroup libtncif + * TNC interface definitions + * + * @defgroup tnc_identities tnc_identities + * @{ @ingroup libtncif + */ + +#ifndef TNCIF_IDENTITY_H_ +#define TNCIF_IDENTITY_H_ + +#include <library.h> + +#include <pen/pen.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> + +#define TNCIF_IDENTITY_MIN_SIZE 28 + +typedef struct tncif_identity_t tncif_identity_t; + +/** + * Public interface of a TNC Identity object + */ +struct tncif_identity_t { + + /** + * Get the TNC Identity Type + * + * @return TNC Identity Type + */ + pen_type_t (*get_identity_type)(tncif_identity_t *this); + + /** + * Get the TNC Identity Value + * + * @return TNC Identity Value + */ + chunk_t (*get_identity_value)(tncif_identity_t *this); + + /** + * Get the TNC Subject Type + * + * @return TNC Subject Type + */ + pen_type_t (*get_subject_type)(tncif_identity_t *this); + + /** + * Get the TNC Authentication Type + * + * @return TNC Authentication Type + */ + pen_type_t (*get_auth_type)(tncif_identity_t *this); + + /** + * Build the IF-IMV TNC Identity attribute encoding + * + * @param writer writer to write encoded data to + */ + void (*build)(tncif_identity_t *this, bio_writer_t *writer); + + /** + * Process the IF-IMV TNC Identity attribute encoding + * + * @param reader reader to read encoded data from + * @return TRUE if successful + */ + bool (*process)(tncif_identity_t *this, bio_reader_t *reader); + + /** + * Destroys a tncif_identity_t object. + */ + void (*destroy)(tncif_identity_t *this); + +}; + +/** + * Create an empty TNC Identity object + */ +tncif_identity_t* tncif_identity_create_empty(void); + +/** + * Create an TNC Identity object from its components + * + * @param identity_type TNC Identity Type + * @param identity_value TNC Identity Value + * @param subject_type TNC Subject Type + * @param auth_type TNC Authentication Type + */ +tncif_identity_t* tncif_identity_create(pen_type_t identity_type, + chunk_t identity_value, + pen_type_t subject_type, + pen_type_t auth_type); + +#endif /** TNCIF_IDENTITY_H_ @}*/ diff --git a/src/libtncif/tncif_names.c b/src/libtncif/tncif_names.c index c108776ec..ac948c8ba 100644 --- a/src/libtncif/tncif_names.c +++ b/src/libtncif/tncif_names.c @@ -45,3 +45,20 @@ ENUM(TNC_IMV_Evaluation_Result_names, "error", "don't know" ); + +ENUM(TNC_Subject_names, + TNC_SUBJECT_UNKNOWN, + TNC_SUBJECT_USER, + "unknown", + "machine", + "user" +); + +ENUM(TNC_Authentication_names, + TNC_AUTH_UNKNOWN, + TNC_AUTH_SIM, + "unknown method", + "certificate", + "password", + "SIM card" +); diff --git a/src/libtncif/tncif_names.h b/src/libtncif/tncif_names.h index 9b50a34e9..75458f960 100644 --- a/src/libtncif/tncif_names.h +++ b/src/libtncif/tncif_names.h @@ -30,5 +30,7 @@ extern enum_name_t *TNC_Connection_State_names; extern enum_name_t *TNC_IMV_Action_Recommendation_names; extern enum_name_t *TNC_IMV_Evaluation_Result_names; +extern enum_name_t *TNC_Subject_names; +extern enum_name_t *TNC_Authentication_names; #endif /** TNCIF_NAME_H_ @}*/ diff --git a/src/libtncif/tncifimv.h b/src/libtncif/tncifimv.h index 3c9db0055..6bce8b4e4 100644 --- a/src/libtncif/tncifimv.h +++ b/src/libtncif/tncifimv.h @@ -209,6 +209,31 @@ typedef TNC_Result (*TNC_IMV_ProvideBindFunctionPointer)( #define TNC_ATTRIBUTEID_SOH ((TNC_AttributeID) 0x00559706) #define TNC_ATTRIBUTEID_SSOH ((TNC_AttributeID) 0x00559707) #define TNC_ATTRIBUTEID_PRIMARY_IMV_ID ((TNC_AttributeID) 0x00559710) +#define TNC_ATTRIBUTEID_AR_IDENTITIES ((TNC_AttributeID) 0x00559712) + +/* TNC Identity Types */ + +#define TNC_ID_UNKNOWN 0 +#define TNC_ID_IPV4_ADDR 1 +#define TNC_ID_IPV6_ADDR 2 +#define TNC_ID_FQDN 3 +#define TNC_ID_RFC822_ADDR 4 +#define TNC_ID_USER_NAME 5 +#define TNC_ID_DER_ASN1_DN 6 +#define TNC_ID_DER_ASN1_GN 7 + +/* TNC Subject Types */ + +#define TNC_SUBJECT_UNKNOWN 0 +#define TNC_SUBJECT_MACHINE 1 +#define TNC_SUBJECT_USER 2 + +/* TNC Authentication Types */ + +#define TNC_AUTH_UNKNOWN 0 +#define TNC_AUTH_CERT 1 +#define TNC_AUTH_PASSWORD 2 +#define TNC_AUTH_SIM 3 /* IMV Functions */ diff --git a/src/pki/commands/pkcs7.c b/src/pki/commands/pkcs7.c index 3d53ace00..790656c62 100644 --- a/src/pki/commands/pkcs7.c +++ b/src/pki/commands/pkcs7.c @@ -31,13 +31,16 @@ static chunk_t read_from_stream(FILE *stream) while (TRUE) { len = fread(buf + total, 1, sizeof(buf) - total, stream); - if (len < 0) + if (len < (sizeof(buf) - total)) { - return chunk_empty; - } - if (len == 0) - { - return chunk_clone(chunk_create(buf, total)); + if (ferror(stream)) + { + return chunk_empty; + } + if (feof(stream)) + { + return chunk_clone(chunk_create(buf, total + len)); + } } total += len; if (total == sizeof(buf)) @@ -295,6 +298,7 @@ static int pkcs7() switch (command_getopt(&arg)) { case 'h': + creds->destroy(creds); return command_usage(NULL); case 'i': file = arg; diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index f2090274c..3fdcd6c28 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -151,8 +151,7 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, chunk_t digest = chunk_alloca(HASH_SIZE_MD5); chunk_t keyEncoding = chunk_empty, keyInfo; hasher_t *hasher; - bool msb_set; - u_char *pos; + int zeros = 0, msb_set = 0; key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding); @@ -168,20 +167,27 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, DESTROY_IF(hasher); free(keyInfo.ptr); - /* is the most significant bit of the digest set? */ - msb_set = (*digest.ptr & 0x80) == 0x80; - - /* allocate space for the serialNumber */ - serialNumber->len = msb_set + digest.len; - serialNumber->ptr = malloc(serialNumber->len); - - /* the serial number as the two's complement of the digest */ - pos = serialNumber->ptr; + /* the serialNumber should be valid ASN1 integer content: + * remove leading zeros, add one if MSB is set (two's complement) */ + while (zeros < digest.len) + { + if (digest.ptr[zeros]) + { + if (digest.ptr[zeros] & 0x80) + { + msb_set = 1; + } + break; + } + zeros++; + } + *serialNumber = chunk_alloc(digest.len - zeros + msb_set); if (msb_set) { - *pos++ = 0x00; + serialNumber->ptr[0] = 0x00; } - memcpy(pos, digest.ptr, digest.len); + memcpy(serialNumber->ptr + msb_set, digest.ptr + zeros, + digest.len - zeros); /* the transaction id is the serial number in hex format */ *transID = chunk_to_hex(digest, NULL, TRUE); @@ -333,7 +339,7 @@ static char* escape_http_request(chunk_t req) * Send a SCEP request via HTTP and wait for a response */ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, - bool http_get_request, chunk_t *response) + bool http_get_request, u_int timeout, chunk_t *response) { int len; status_t status; @@ -361,6 +367,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_REQUEST_HEADER, "Pragma:", FETCH_REQUEST_HEADER, "Host:", FETCH_REQUEST_HEADER, "Accept:", @@ -375,6 +382,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_REQUEST_DATA, msg, FETCH_REQUEST_TYPE, "", FETCH_REQUEST_HEADER, "Expect:", @@ -403,6 +411,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_END); } diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h index 30551d2db..ec8fa6515 100644 --- a/src/scepclient/scep.h +++ b/src/scepclient/scep.h @@ -79,7 +79,7 @@ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, size_t key_size, certificate_t *signer_cert, hash_algorithm_t digest_alg, private_key_t *private_key); bool scep_http_request(const char *url, chunk_t message, scep_op_t op, - bool http_get_request, chunk_t *response); + bool http_get_request, u_int timeout, chunk_t *response); err_t scep_parse_response(chunk_t response, chunk_t transID, container_t **out, scep_attributes_t *attrs); diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 83b5d6219..a957968a5 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -113,6 +113,9 @@ long crl_check_interval = 0; /* by default pluto logs out after every smartcard use */ bool pkcs11_keep_state = FALSE; +/* by default HTTP fetch timeout is 30s */ +static u_int http_timeout = 30; + /* options read by optionsfrom */ options_t *options; @@ -344,6 +347,7 @@ static void usage(const char *message) " - if no filename is given, default is used\n" " --optionsfrom (-+) <filename> reads additional options from given file\n" " --force (-f) force existing file(s)\n" + " --httptimeout (-T) timeout for HTTP operations (default: 30s)\n" "\n" "Options for key generation (pkcs1):\n" " --keylength (-k) <bits> key length for RSA key generation\n" @@ -518,6 +522,7 @@ int main(int argc, char **argv) { "in", required_argument, NULL, 'i' }, { "out", required_argument, NULL, 'o' }, { "force", no_argument, NULL, 'f' }, + { "httptimeout", required_argument, NULL, 'T' }, { "keylength", required_argument, NULL, 'k' }, { "dn", required_argument, NULL, 'd' }, { "days", required_argument, NULL, 'D' }, @@ -662,6 +667,14 @@ int main(int argc, char **argv) force = TRUE; continue; + case 'T': /* --httptimeout */ + http_timeout = atoi(optarg); + if (http_timeout <= 0) + { + usage("invalid httptimeout specified"); + } + continue; + case '+': /* --optionsfrom <filename> */ if (!options->from(options, optarg, &argc, &argv, optind)) { @@ -939,7 +952,8 @@ int main(int argc, char **argv) pkcs7_t *pkcs7; if (!scep_http_request(scep_url, chunk_create(ca_name, strlen(ca_name)), - SCEP_GET_CA_CERT, http_get_request, &scep_response)) + SCEP_GET_CA_CERT, http_get_request, + http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1317,7 +1331,7 @@ int main(int argc, char **argv) creds->add_cert(creds, TRUE, x509_ca_sig->get_ref(x509_ca_sig)); if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1367,7 +1381,7 @@ int main(int argc, char **argv) exit_scepclient("failed to build scep request"); } if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1458,5 +1472,3 @@ int main(int argc, char **argv) exit_scepclient(NULL); return -1; /* should never be reached */ } - - diff --git a/src/starter/starter.c b/src/starter/starter.c index 727a0d60c..ae6863fd7 100644 --- a/src/starter/starter.c +++ b/src/starter/starter.c @@ -328,7 +328,8 @@ static bool check_pid(char *pid_file) static void usage(char *name) { fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>]\n" - " [--debug|--debug-more|--debug-all|--nolog]\n"); + " [--debug|--debug-more|--debug-all|--nolog]\n" + " [--attach-gdb]\n"); exit(LSB_RC_INVALID_ARGUMENT); } |