From 180a2f2642fc55c9d0836449e55bf76a52391c31 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Wed, 7 Aug 2013 19:41:29 +0200 Subject: [PATCH] rapid PT-TLS AR/PDP prototype --- configure.ac | 1 + src/Makefile.am | 2 +- src/libcharon/plugins/tnc_imc/tnc_imc.c | 3 +- .../plugins/tnc_imc/tnc_imc_manager.c | 3 +- src/libcharon/plugins/tnc_pdp/tnc_pdp.c | 297 +++++++++++++++--- .../plugins/tnc_pdp/tnc_pdp_plugin.c | 4 + src/libcharon/plugins/tnccs_20/tnccs_20.c | 7 +- src/libpttls/pt_tls.h | 5 + src/libpttls/pt_tls_client.c | 7 + src/libpttls/pt_tls_dispatcher.c | 4 +- src/libpttls/pt_tls_server.c | 2 +- src/pt-tls-client/Makefile.am | 21 ++ src/pt-tls-client/pt-tls-client | 228 ++++++++++++++ src/pt-tls-client/pt-tls-client.c | 250 +++++++++++++++ 14 files changed, 769 insertions(+), 65 deletions(-) create mode 100644 src/pt-tls-client/Makefile.am create mode 100755 src/pt-tls-client/pt-tls-client create mode 100644 src/pt-tls-client/pt-tls-client.c diff --git a/configure.ac b/configure.ac index a2be84495..7b23a9cb5 100644 --- a/configure.ac +++ b/configure.ac @@ -1467,6 +1467,7 @@ AC_CONFIG_FILES([ src/medsrv/Makefile src/checksum/Makefile src/conftest/Makefile + src/pt-tls-client/Makefile scripts/Makefile testing/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 47299b03c..1a025ad24 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,7 @@ if USE_LIBTNCCS endif if USE_LIBPTTLS - SUBDIRS += libpttls + SUBDIRS += libpttls pt-tls-client endif if USE_IMCV diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c index 9ac578401..122554abe 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -304,7 +303,7 @@ METHOD(imc_t, destroy, void, private_tnc_imc_t *this) { if (this->handle && lib->settings->get_bool(lib->settings, - "%s.plugins.tnc-imc.dlclose", TRUE, charon->name)) + "%s.plugins.tnc-imc.dlclose", TRUE, "charon")) { dlclose(this->handle); } diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c index 078f7bc34..b34a6ffd8 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c @@ -19,7 +19,6 @@ #include -#include #include #include #include @@ -225,7 +224,7 @@ METHOD(imc_manager_t, get_preferred_language, char*, private_tnc_imc_manager_t *this) { return lib->settings->get_str(lib->settings, - "%s.plugins.tnc-imc.preferred_language", "en", charon->name); + "%s.plugins.tnc-imc.preferred_language", "en", "charon"); } METHOD(imc_manager_t, notify_connection_change, void, diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c index 7ef67fd18..686df15c7 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -22,7 +22,9 @@ #include #include -#include +#include + +#include #include #include @@ -38,11 +40,6 @@ typedef struct private_tnc_pdp_t private_tnc_pdp_t; */ #define RADIUS_PORT 1812 -/** - * Default PT-TLS port, when not configured - */ -#define PT_TLS_PORT 271 - /** * Maximum size of a RADIUS IP packet */ @@ -69,14 +66,24 @@ struct private_tnc_pdp_t { eap_type_t type; /** - * IPv4 RADIUS socket + * PT-TLS IPv4 socket */ - int ipv4; + int pt_tls_ipv4; /** - * IPv6 RADIUS socket + * PT-TLS IPv6 socket */ - int ipv6; + int pt_tls_ipv6; + + /** + * RADIUS IPv4 socket + */ + int radius_ipv4; + + /** + * RADIUS IPv6 socket + */ + int radius_ipv6; /** * RADIUS shared secret @@ -103,18 +110,12 @@ struct private_tnc_pdp_t { */ tnc_pdp_connections_t *connections; - /** - * PT-TLS dispatcher - */ - pt_tls_dispatcher_t *pt_tls_dispatcher; - }; - /** - * Open IPv4 or IPv6 UDP RADIUS socket + * Open IPv4 or IPv6 UDP socket */ -static int open_socket(int family, u_int16_t port) +static int open_udp_socket(int family, u_int16_t port) { int on = TRUE; struct sockaddr_storage addr; @@ -153,20 +154,115 @@ static int open_socket(int family, u_int16_t port) skt = socket(family, SOCK_DGRAM, IPPROTO_UDP); if (skt < 0) { - DBG1(DBG_CFG, "opening RADIUS socket failed: %s", strerror(errno)); + DBG1(DBG_CFG, "opening UDP socket failed: %s", strerror(errno)); return 0; } if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) { - DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s", strerror(errno)); + DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s", + strerror(errno)); close(skt); return 0; } + if (family == AF_INET6) + { + if (setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "unable to set IPV6_V6ONLY on socket: %s", + strerror(errno)); + close(skt); + return 0; + } + } /* bind the socket */ if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0) { - DBG1(DBG_CFG, "unable to bind RADIUS socket: %s", strerror(errno)); + DBG1(DBG_CFG, "unable to bind UDP socket: %s", strerror(errno)); + close(skt); + return 0; + } + + return skt; +} + +/** + * Open IPv4 or IPv6 TCP socket + */ +static int open_tcp_socket(int family, u_int16_t port) +{ + int on = TRUE; + struct sockaddr_storage addr; + socklen_t addrlen; + int skt; + + memset(&addr, 0, sizeof(addr)); + addr.ss_family = family; + + /* precalculate constants depending on address family */ + switch (family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)&addr; + + htoun32(&sin->sin_addr.s_addr, INADDR_ANY); + htoun16(&sin->sin_port, port); + addrlen = sizeof(struct sockaddr_in); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; + + memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); + htoun16(&sin6->sin6_port, port); + addrlen = sizeof(struct sockaddr_in6); + break; + } + default: + return 0; + } + + /* open the socket */ + skt = socket(family, SOCK_STREAM, IPPROTO_TCP); + if (skt < 0) + { + DBG1(DBG_CFG, "opening TCP socket failed: %s", strerror(errno)); + return 0; + } + if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s", + strerror(errno)); + close(skt); + return 0; + } + if (family == AF_INET6) + { + if (setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "unable to set IPV6_V6ONLY on socket: %s", + strerror(errno)); + close(skt); + return 0; + } + } + + /* bind the socket */ + if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0) + { + DBG1(DBG_CFG, "unable to bind TCP socket: %s", strerror(errno)); + close(skt); + return 0; + } + + /* start listening on socket */ + if (listen(skt, 5) == -1) + { + DBG1(DBG_TNC, "listen on TCP socket failed: %s", strerror(errno)); close(skt); return 0; } @@ -183,7 +279,8 @@ static void send_message(private_tnc_pdp_t *this, radius_message_t *message, int fd; chunk_t data; - fd = (client->get_family(client) == AF_INET) ? this->ipv4 : this->ipv6; + fd = (client->get_family(client) == AF_INET) ? + this->radius_ipv4 : this->radius_ipv6; data = message->get_encoding(message); DBG2(DBG_CFG, "sending RADIUS packet to %#H", client); @@ -465,10 +562,80 @@ end: } } +/** + * Get more data on a PT-TLS connection + */ +static bool pt_tls_receive_more(pt_tls_server_t *this, int fd, + watcher_event_t event) +{ + switch (this->handle(this)) + { + case NEED_MORE: + DBG1(DBG_TNC, "PT-TLS connection needs more"); + break; + case FAILED: + case SUCCESS: + default: + DBG1(DBG_TNC, "PT-TLS connection terminates"); + lib->watcher->remove(lib->watcher, fd); + close(fd); + this->destroy(this); + break; + } + + return TRUE; +} + +/** + * Accept TCP connection received on the PT-TLS listening socket + */ +static bool pt_tls_receive(private_tnc_pdp_t *this, int fd, watcher_event_t event) +{ + int pt_tls_fd; + identification_t *peer; + pt_tls_server_t *pt_tls; + tnccs_t *tnccs; + + pt_tls_fd = accept(fd, NULL, NULL); + if (pt_tls_fd == -1) + { + DBG1(DBG_TNC, "accepting PT-TLS stream failed: %s", strerror(errno)); + return FALSE; + } + + /* At this moment the peer identity is not known yet */ + peer = identification_create_from_encoding(ID_ANY, chunk_empty), + + tnccs = tnc->tnccs->create_instance(tnc->tnccs, TNCCS_2_0, TRUE, + this->server, peer, TNC_IFT_TLS_2_0); + peer->destroy(peer); + + if (!tnccs) + { + DBG1(DBG_TNC, "could not create TNCCS 2.0 connection instance"); + close(pt_tls_fd); + return FALSE; + } + + pt_tls = pt_tls_server_create(this->server, pt_tls_fd, PT_TLS_AUTH_NONE, + tnccs); + if (!pt_tls) + { + DBG1(DBG_TNC, "could not create PT-TLS connection instance"); + close(pt_tls_fd); + return FALSE; + } + + lib->watcher->add(lib->watcher, pt_tls_fd, WATCHER_READ, + (watcher_cb_t)pt_tls_receive_more, pt_tls); + + return TRUE; +} + /** * Process packets received on the RADIUS socket */ -static bool receive(private_tnc_pdp_t *this, int fd, watcher_event_t event) +static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t event) { radius_message_t *request; char buffer[MAX_PACKET]; @@ -528,18 +695,27 @@ static bool receive(private_tnc_pdp_t *this, int fd, watcher_event_t event) METHOD(tnc_pdp_t, destroy, void, private_tnc_pdp_t *this) { - if (this->ipv4) + if (this->pt_tls_ipv4) { - lib->watcher->remove(lib->watcher, this->ipv4); - close(this->ipv4); + lib->watcher->remove(lib->watcher, this->pt_tls_ipv4); + close(this->pt_tls_ipv4); } - if (this->ipv6) + if (this->pt_tls_ipv6) { - lib->watcher->remove(lib->watcher, this->ipv6); - close(this->ipv6); + lib->watcher->remove(lib->watcher, this->pt_tls_ipv6); + close(this->pt_tls_ipv6); + } + if (this->radius_ipv4) + { + lib->watcher->remove(lib->watcher, this->radius_ipv4); + close(this->radius_ipv4); + } + if (this->radius_ipv6) + { + lib->watcher->remove(lib->watcher, this->radius_ipv6); + close(this->radius_ipv6); } DESTROY_IF(this->server); - DESTROY_IF(this->pt_tls_dispatcher); DESTROY_IF(this->signer); DESTROY_IF(this->hasher); DESTROY_IF(this->ng); @@ -555,8 +731,6 @@ tnc_pdp_t *tnc_pdp_create(void) private_tnc_pdp_t *this; char *secret, *server, *eap_type_str; int radius_port, pt_tls_port; - identification_t *id; - host_t *host; server = lib->settings->get_str(lib->settings, "%s.plugins.tnc-pdp.server", NULL, charon->name); @@ -580,22 +754,15 @@ tnc_pdp_t *tnc_pdp_create(void) return NULL; } - host = host_create_from_dns(server, AF_UNSPEC, pt_tls_port); - if (!host) - { - DBG1(DBG_CFG, "could not resolve server name"); - return NULL; - } - id = identification_create_from_string(server); - INIT(this, .public = { .destroy = _destroy, }, - .server = id, - .pt_tls_dispatcher = pt_tls_dispatcher_create(host, id, PT_TLS_AUTH_NONE), - .ipv4 = open_socket(AF_INET, radius_port), - .ipv6 = open_socket(AF_INET6, radius_port), + .server = identification_create_from_string(server), + .pt_tls_ipv4 = open_tcp_socket(AF_INET, pt_tls_port), + .pt_tls_ipv6 = open_tcp_socket(AF_INET6, pt_tls_port), + .radius_ipv4 = open_udp_socket(AF_INET, radius_port), + .radius_ipv6 = open_udp_socket(AF_INET6, radius_port), .secret = chunk_from_str(secret), .type = eap_type_from_string(eap_type_str), .hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5), @@ -604,6 +771,31 @@ tnc_pdp_t *tnc_pdp_create(void) .connections = tnc_pdp_connections_create(), ); + if (!this->pt_tls_ipv4 && !this->pt_tls_ipv6) + { + DBG1(DBG_NET, "could not create any PT-TLS sockets"); + destroy(this); + return NULL; + } + if (this->pt_tls_ipv4) + { + lib->watcher->add(lib->watcher, this->pt_tls_ipv4, WATCHER_READ, + (watcher_cb_t)pt_tls_receive, this); + } + else + { + DBG1(DBG_NET, "could not open IPv4 PT-TLS socket, IPv4 disabled"); + } + if (this->pt_tls_ipv6) + { + lib->watcher->add(lib->watcher, this->pt_tls_ipv6, WATCHER_READ, + (watcher_cb_t)pt_tls_receive, this); + } + else + { + DBG1(DBG_NET, "could not open IPv6 PT-TLS socket, IPv6 disabled"); + } + if (!this->hasher || !this->signer || !this->ng) { DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/NG required"); @@ -611,25 +803,26 @@ tnc_pdp_t *tnc_pdp_create(void) return NULL; } - if (!this->ipv4 && !this->ipv6) + if (!this->radius_ipv4 && !this->radius_ipv6) { DBG1(DBG_NET, "could not create any RADIUS sockets"); destroy(this); return NULL; } - if (this->ipv4) + if (this->radius_ipv4) { - lib->watcher->add(lib->watcher, this->ipv4, WATCHER_READ, - (watcher_cb_t)receive, this); + lib->watcher->add(lib->watcher, this->radius_ipv4, WATCHER_READ, + (watcher_cb_t)radius_receive, this); } else { DBG1(DBG_NET, "could not open IPv4 RADIUS socket, IPv4 disabled"); } - if (this->ipv6) + if (this->radius_ipv6) + { - lib->watcher->add(lib->watcher, this->ipv6, WATCHER_READ, - (watcher_cb_t)receive, this); + lib->watcher->add(lib->watcher, this->radius_ipv6, WATCHER_READ, + (watcher_cb_t)radius_receive, this); } else { diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c index 14ab9cf6f..5586b568b 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c @@ -52,6 +52,10 @@ static bool plugin_cb(private_tnc_pdp_plugin_t *this, if (reg) { this->pdp = tnc_pdp_create(); + if (!this->pdp) + { + return FALSE; + } } else { diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 4c8f3a925..55f33c143 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -34,9 +34,8 @@ #include #include -#include -#include #include +#include #include #include @@ -934,10 +933,10 @@ tnccs_t* tnccs_20_create(bool is_server, .messages = linked_list_create(), .max_batch_len = lib->settings->get_int(lib->settings, "%s.plugins.tnccs-20.max_batch_size", 65522, - charon->name), + "charon"), .max_msg_len = lib->settings->get_int(lib->settings, "%s.plugins.tnccs-20.max_message_size", 65490, - charon->name), + "charon"), ); return &this->public; diff --git a/src/libpttls/pt_tls.h b/src/libpttls/pt_tls.h index 92a040f3f..7384cf2d5 100644 --- a/src/libpttls/pt_tls.h +++ b/src/libpttls/pt_tls.h @@ -37,6 +37,11 @@ */ #define PT_TLS_HEADER_LEN 16 +/** + * Default PT-TLS port + */ +#define PT_TLS_PORT 271 + typedef enum pt_tls_message_type_t pt_tls_message_type_t; typedef enum pt_tls_sasl_result_t pt_tls_sasl_result_t; typedef enum pt_tls_auth_t pt_tls_auth_t; diff --git a/src/libpttls/pt_tls_client.c b/src/libpttls/pt_tls_client.c index d3ac936a2..76dd5ee44 100644 --- a/src/libpttls/pt_tls_client.c +++ b/src/libpttls/pt_tls_client.c @@ -437,19 +437,26 @@ METHOD(pt_tls_client_t, run_assessment, status_t, { if (!this->tls) { + DBG1(DBG_TNC, "entering PT-TLS setup phase"); if (!make_connection(this)) { return FAILED; } } + + DBG1(DBG_TNC, "entering PT-TLS negotiation phase"); if (!negotiate_version(this)) { return FAILED; } + + DBG1(DBG_TNC, "doing SASL client authentication"); if (!authenticate(this)) { return FAILED; } + + DBG1(DBG_TNC, "entering PT-TLS data transport phase"); if (!assess(this, (tls_t*)tnccs)) { return FAILED; diff --git a/src/libpttls/pt_tls_dispatcher.c b/src/libpttls/pt_tls_dispatcher.c index 469951616..5c306371c 100644 --- a/src/libpttls/pt_tls_dispatcher.c +++ b/src/libpttls/pt_tls_dispatcher.c @@ -185,7 +185,7 @@ pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address, .dispatch = _dispatch, .destroy = _destroy, }, - .server = id, + .server = id->clone(id), /* we currently don't authenticate the peer, use %any identity */ .peer = identification_create_from_encoding(ID_ANY, chunk_empty), .fd = -1, @@ -194,11 +194,9 @@ pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address, if (!open_socket(this, address)) { - address->destroy(address); destroy(this); return NULL; } - address->destroy(address); return &this->public; } diff --git a/src/libpttls/pt_tls_server.c b/src/libpttls/pt_tls_server.c index 3e134f0dd..2796e0dd0 100644 --- a/src/libpttls/pt_tls_server.c +++ b/src/libpttls/pt_tls_server.c @@ -478,7 +478,7 @@ METHOD(pt_tls_server_t, handle, status_t, } DBG1(DBG_TNC, "negotiated PT-TLS version %d", PT_TLS_VERSION); this->state = PT_TLS_SERVER_AUTH; - break; + /* fall through to next state */ case PT_TLS_SERVER_AUTH: if (!authenticate(this)) { diff --git a/src/pt-tls-client/Makefile.am b/src/pt-tls-client/Makefile.am new file mode 100644 index 000000000..2ce1a10f3 --- /dev/null +++ b/src/pt-tls-client/Makefile.am @@ -0,0 +1,21 @@ +ipsec_PROGRAMS = pt-tls-client + +pt_tls_client_SOURCES = pt-tls-client.c + +pt-tls-client.o : $(top_builddir)/config.status + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libpttls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs \ + -DIPSEC_CONFDIR=\"${sysconfdir}\" \ + -DPLUGINS="\"pem openssl nonce tnc-tnccs tnc-imc tnccs-20\"" + +pt_tls_client_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libtls/libtls.la \ + $(top_builddir)/src/libpttls/libpttls.la \ + $(top_builddir)/src/libtnccs/libtnccs.la + diff --git a/src/pt-tls-client/pt-tls-client b/src/pt-tls-client/pt-tls-client new file mode 100755 index 000000000..4e52d995e --- /dev/null +++ b/src/pt-tls-client/pt-tls-client @@ -0,0 +1,228 @@ +#! /bin/bash + +# pt-tls-client - temporary wrapper script for .libs/pt-tls-client +# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.2ubuntu1 +# +# The pt-tls-client program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /home/andreas/strongswan/src/pt-tls-client; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games; export PATH; gcc -g -O2 -Wall -Wno-format -Wno-pointer-sign -include /home/andreas/strongswan/config.h -o \$progdir/\$file pt-tls-client.o ../../src/libstrongswan/.libs/libstrongswan.so ../../src/libtls/.libs/libtls.so ../../src/libpttls/.libs/libpttls.so ../../src/libtnccs/.libs/libtnccs.so -Wl,-rpath -Wl,/home/andreas/strongswan/src/libstrongswan/.libs -Wl,-rpath -Wl,/home/andreas/strongswan/src/libtls/.libs -Wl,-rpath -Wl,/home/andreas/strongswan/src/libpttls/.libs -Wl,-rpath -Wl,/home/andreas/strongswan/src/libtnccs/.libs -Wl,-rpath -Wl,/usr/lib/ipsec)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.2' + notinst_deplibs=' ../../src/libstrongswan/libstrongswan.la ../../src/libtls/libtls.la ../../src/libpttls/libpttls.la ../../src/libtnccs/libtnccs.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "pt-tls-client:pt-tls-client:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.2ubuntu1" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "pt-tls-client:pt-tls-client:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "pt-tls-client:pt-tls-client:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'pt-tls-client' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + printf %s\n "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/src/pt-tls-client/pt-tls-client.c b/src/pt-tls-client/pt-tls-client.c new file mode 100644 index 000000000..2b104f8d5 --- /dev/null +++ b/src/pt-tls-client/pt-tls-client.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2010-2013 Martin Willi, revosec AG + * Copyright (C) 2013 Andreas Steffen, HSR Hochschule für 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 . + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** + * Print usage information + */ +static void usage(FILE *out, char *cmd) +{ + fprintf(out, "usage:\n"); + fprintf(out, " %s --connect
[--port ] [--cert ]+\n", cmd); + fprintf(out, " [--client ] [--secret ]\n"); +} + +/** + * Client routine + */ +static int client(char *address, u_int16_t port, char *identity) +{ + pt_tls_client_t *assessment; + tls_t *tnccs; + identification_t *server, *client; + host_t *host; + status_t status; + + host = host_create_from_dns(address, AF_UNSPEC, port); + if (!host) + { + return 1; + } + server = identification_create_from_string(address); + client = identification_create_from_string(identity); + tnccs = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, TNCCS_2_0, FALSE, + server, client, TNC_IFT_TLS_2_0); + if (!tnccs) + { + fprintf(stderr, "loading TNCCS failed: %s\n", PLUGINS); + host->destroy(host); + server->destroy(server); + client->destroy(client); + return 1; + } + assessment = pt_tls_client_create(host, server, client); + status = assessment->run_assessment(assessment, (tnccs_t*)tnccs); + assessment->destroy(assessment); + tnccs->destroy(tnccs); + return status; +} + + +/** + * In-Memory credential set + */ +static mem_cred_t *creds; + +/** + * Load certificate from file + */ +static bool load_certificate(char *filename) +{ + certificate_t *cert; + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, filename, BUILD_END); + if (!cert) + { + DBG1(DBG_TLS, "loading certificate from '%s' failed", filename); + return FALSE; + } + creds->add_cert(creds, TRUE, cert); + return TRUE; +} + +/** + * Load private key from file + */ +static bool load_key(char *filename) +{ + private_key_t *key; + + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + BUILD_FROM_FILE, filename, BUILD_END); + if (!key) + { + DBG1(DBG_TLS, "loading key from '%s' failed", filename); + return FALSE; + } + creds->add_key(creds, key); + return TRUE; +} + +/** + * Debug level + */ +static level_t pt_tls_level = 2; + +static void dbg_pt_tls(debug_t group, level_t level, char *fmt, ...) +{ + if (level <= pt_tls_level) + { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +/** + * Cleanup + */ +static void cleanup() +{ + lib->processor->cancel(lib->processor); + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + libtnccs_deinit(); + library_deinit(); +} + +/** + * Initialize library + */ +static void init() +{ + library_init(NULL); + libtnccs_init(); + + dbg = dbg_pt_tls; + + if (!lib->plugins->load(lib->plugins, + lib->settings->get_str(lib->settings, "pt-tls-client.load", PLUGINS))) + { + exit(SS_RC_INITIALIZATION_FAILED); + } + + creds = mem_cred_create(); + lib->credmgr->add_set(lib->credmgr, &creds->set); + + atexit(cleanup); +} + +int main(int argc, char *argv[]) +{ + char *address = NULL, *identity = "%any", *secret = NULL; + int port = PT_TLS_PORT; + + init(); + + while (TRUE) + { + struct option long_opts[] = { + {"help", no_argument, NULL, 'h' }, + {"connect", required_argument, NULL, 'c' }, + {"client", required_argument, NULL, 'i' }, + {"secret", required_argument, NULL, 's' }, + {"port", required_argument, NULL, 'p' }, + {"cert", required_argument, NULL, 'x' }, + {"key", required_argument, NULL, 'k' }, + {"debug", required_argument, NULL, 'd' }, + {0,0,0,0 } + }; + switch (getopt_long(argc, argv, "", long_opts, NULL)) + { + case EOF: + break; + case 'h': + usage(stdout, argv[0]); + return 0; + case 'x': + if (!load_certificate(optarg)) + { + return 1; + } + continue; + case 'k': + if (!load_key(optarg)) + { + return 1; + } + continue; + case 'c': + if (address) + { + usage(stderr, argv[0]); + return 1; + } + address = optarg; + continue; + case 'i': + identity = optarg; + continue; + case 's': + secret = optarg; + continue; + case 'p': + port = atoi(optarg); + continue; + case 'd': + pt_tls_level = atoi(optarg); + continue; + default: + usage(stderr, argv[0]); + return 1; + } + break; + } + if (!address) + { + usage(stderr, argv[0]); + return 1; + } + if (secret) + { + creds->add_shared(creds, shared_key_create(SHARED_EAP, + chunk_clone(chunk_from_str(secret))), + identification_create_from_string(identity), NULL); + } + + return client(address, port, identity); +}