From a9f169f699c4ec297641656b6b1d2b3f737b88bd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 10 Feb 2012 14:11:19 +0100 Subject: [PATCH 01/32] Don't require PLUGINDIR to be defined. If it is not available, we just load monolithically built plugins. --- src/libstrongswan/plugins/plugin_loader.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index d5777e35b..95a0bfc02 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -250,8 +250,11 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file, this->plugins->insert_last(this->plugins, entry); return TRUE; case NOT_FOUND: - /* try to load the plugin from a file */ - break; + if (file) + { /* try to load the plugin from a file */ + break; + } + /* fall-through */ default: return FALSE; } @@ -651,16 +654,18 @@ METHOD(plugin_loader_t, load_plugins, bool, char *token; bool critical_failed = FALSE; +#ifdef PLUGINDIR if (path == NULL) { path = PLUGINDIR; } +#endif /* PLUGINDIR */ enumerator = enumerator_create_token(list, " ", " "); while (!critical_failed && enumerator->enumerate(enumerator, &token)) { bool critical = FALSE; - char file[PATH_MAX]; + char buf[PATH_MAX], *file = NULL; int len; token = strdup(token); @@ -675,10 +680,14 @@ METHOD(plugin_loader_t, load_plugins, bool, free(token); continue; } - if (snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", - path, token) >= sizeof(file)) + if (path) { - return FALSE; + if (snprintf(buf, sizeof(buf), "%s/libstrongswan-%s.so", + path, token) >= sizeof(buf)) + { + return FALSE; + } + file = buf; } if (!load_plugin(this, token, file, critical) && critical) { From 4528e74a5cd6ced7d6f7cb841e6f9a7d8d131719 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 10 Feb 2012 14:16:54 +0100 Subject: [PATCH 02/32] Don't require STRONGSWAN_CONF to be defined. --- src/libstrongswan/settings.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c index b26fbebb4..8977cd9ed 100644 --- a/src/libstrongswan/settings.c +++ b/src/libstrongswan/settings.c @@ -1117,14 +1117,21 @@ static bool load_files_internal(private_settings_t *this, section_t *parent, char *pattern, bool merge) { char *text; - linked_list_t *contents = linked_list_create(); - section_t *section = section_create(NULL); + linked_list_t *contents; + section_t *section; if (pattern == NULL) { +#ifdef STRONGSWAN_CONF pattern = STRONGSWAN_CONF; +#else + return FALSE; +#endif } + contents = linked_list_create(); + section = section_create(NULL); + if (!parse_files(contents, NULL, 0, pattern, section)) { contents->destroy_function(contents, (void*)free); From 73940eb71235f8ff8c3490d9f607db9c7defd19e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 10 Feb 2012 14:51:18 +0100 Subject: [PATCH 03/32] Make path to Android OpenSSL headers configurable. --- Android.mk.in | 1 + src/libstrongswan/Android.mk | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Android.mk.in b/Android.mk.in index a73981db0..a1ce1c571 100644 --- a/Android.mk.in +++ b/Android.mk.in @@ -50,6 +50,7 @@ strongswan_PATH := $(LOCAL_PATH) libvstr_PATH := external/strongswan-support/vstr/include libcurl_PATH := external/strongswan-support/libcurl/include libgmp_PATH := external/strongswan-support/gmp +openssl_PATH := external/openssl/include # some definitions strongswan_VERSION := "@PACKAGE_VERSION@" diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index ae5a7733e..8cba58816 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -58,7 +58,7 @@ LOCAL_SRC_FILES += $(call add_plugin, nonce) LOCAL_SRC_FILES += $(call add_plugin, openssl) ifneq ($(call plugin_enabled, openssl),) -LOCAL_C_INCLUDES += external/openssl/include +LOCAL_C_INCLUDES += $(openssl_PATH) LOCAL_SHARED_LIBRARIES += libcrypto endif From e7ea057fd2da33ff5b55e1cebb3b5b7e361a43d7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 13 Feb 2012 18:04:04 +0100 Subject: [PATCH 04/32] Make the UDP ports charon listens for packets on (and uses as source ports) configurable. --- configure.in | 23 ++++++++++++++++ src/charon-nm/nm/nm_service.c | 2 +- src/libcharon/daemon.h | 19 ++++++++++++-- .../plugins/android/android_service.c | 2 +- src/libcharon/plugins/ha/ha_tunnel.c | 2 +- .../plugins/load_tester/load_tester_config.c | 2 +- src/libcharon/plugins/maemo/maemo_service.c | 2 +- src/libcharon/plugins/medcli/medcli_config.c | 4 +-- src/libcharon/plugins/medsrv/medsrv_config.c | 2 +- .../socket_default/socket_default_socket.c | 26 +++++++++---------- .../plugins/socket_raw/socket_raw_socket.c | 20 +++++++------- src/libcharon/plugins/sql/sql_config.c | 2 +- src/libcharon/plugins/stroke/stroke_config.c | 5 +++- src/libcharon/plugins/uci/uci_config.c | 4 +-- src/libcharon/processing/jobs/migrate_job.c | 2 +- src/libcharon/sa/ike_sa.c | 8 +++--- src/libcharon/sa/ikev1/tasks/informational.c | 2 +- src/libcharon/sa/ikev2/tasks/ike_mobike.c | 10 +++---- 18 files changed, 89 insertions(+), 48 deletions(-) diff --git a/configure.in b/configure.in index c5fd1d3c6..0c288f82e 100644 --- a/configure.in +++ b/configure.in @@ -71,6 +71,29 @@ AC_ARG_WITH( [AC_SUBST(ipsecgroup, "root")] ) +AC_ARG_WITH( + [charon-udp-port], + AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500).]), + [AC_DEFINE_UNQUOTED(CHARON_UDP_PORT, [$withval], [UDP port used by charon locally]) + AC_SUBST(charon_udp_port, [$withval])], + [AC_SUBST(charon_udp_port, 500)] +) + +AC_ARG_WITH( + [charon-natt-port], + AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500)]), + [AC_DEFINE_UNQUOTED(CHARON_NATT_PORT, [$withval], [UDP post used by charon locally in case a NAT is detected]) + AC_SUBST(charon_natt_port, [$withval])], + [AC_SUBST(charon_natt_port, 4500)] +) + +AC_MSG_CHECKING([configured UDP ports ($charon_udp_port, $charon_natt_port)]) +if test x$charon_udp_port == x$charon_natt_port; then + AC_MSG_ERROR(the ports have to be different) +else + AC_MSG_RESULT(ok) +fi + # convert script name to uppercase AC_SUBST(ipsec_script_upper, [`echo -n "$ipsec_script" | tr a-z A-Z`]) diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c index 86d293d97..affe281fa 100644 --- a/src/charon-nm/nm/nm_service.c +++ b/src/charon-nm/nm/nm_service.c @@ -497,7 +497,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, /** * Set up configurations */ - ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE, IKEV2_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE, CHARON_UDP_PORT, (char*)address, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg, diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h index f42a9f078..b67de77b8 100644 --- a/src/libcharon/daemon.h +++ b/src/libcharon/daemon.h @@ -178,15 +178,30 @@ typedef struct daemon_t daemon_t; #define DEFAULT_THREADS 16 /** - * UDP Port on which the daemon will listen for incoming traffic. + * Primary UDP port used by IKE. */ #define IKEV2_UDP_PORT 500 /** - * UDP Port to which the daemon will float to if NAT is detected. + * UDP port defined for use in case a NAT is detected. */ #define IKEV2_NATT_PORT 4500 +/** + * UDP port on which the daemon will listen for incoming traffic (also used as + * source port for outgoing traffic). + */ +#ifndef CHARON_UDP_PORT +#define CHARON_UDP_PORT IKEV2_UDP_PORT +#endif + +/** + * UDP port used by the daemon in case a NAT is detected. + */ +#ifndef CHARON_NATT_PORT +#define CHARON_NATT_PORT IKEV2_NATT_PORT +#endif + /** * Main class of daemon, contains some globals. */ diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index 6ca7407ca..c5553f24f 100644 --- a/src/libcharon/plugins/android/android_service.c +++ b/src/libcharon/plugins/android/android_service.c @@ -264,7 +264,7 @@ static job_requeue_t initiate(private_android_service_t *this) this->creds->set_username_password(this->creds, user, password); } - ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, IKEV2_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, CHARON_UDP_PORT, hostname, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index d1edb3e55..200733cac 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -203,7 +203,7 @@ static void setup_tunnel(private_ha_tunnel_t *this, lib->credmgr->add_set(lib->credmgr, &this->creds.public); /* create config and backend */ - ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, IKEV2_UDP_PORT, + ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, CHARON_UDP_PORT, remote, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND, diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index d041d4cdc..2e02fb57c 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -257,7 +257,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) else { ike_cfg = ike_cfg_create(FALSE, FALSE, - this->local, FALSE, IKEV2_UDP_PORT, + this->local, FALSE, CHARON_UDP_PORT, this->remote, FALSE, IKEV2_UDP_PORT); } ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal)); diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index b5f50f1c6..9f1f16956 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -323,7 +323,7 @@ static gboolean initiate_connection(private_maemo_service_t *this, NULL); } - ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, IKEV2_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, CHARON_UDP_PORT, hostname, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 15d4ffa3f..6b28f751c 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -119,7 +119,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, return NULL; } ike_cfg = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, IKEV2_UDP_PORT, + "0.0.0.0", FALSE, CHARON_UDP_PORT, address, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); med_cfg = peer_cfg_create( @@ -396,7 +396,7 @@ medcli_config_t *medcli_config_create(database_t *db) .rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200), .dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300), .ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, IKEV2_UDP_PORT, + "0.0.0.0", FALSE, CHARON_UDP_PORT, "0.0.0.0", FALSE, IKEV2_UDP_PORT), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c index ef3b04497..b19847b87 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -141,7 +141,7 @@ medsrv_config_t *medsrv_config_create(database_t *db) .rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200), .dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300), .ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, IKEV2_UDP_PORT, + "0.0.0.0", FALSE, CHARON_UDP_PORT, "0.0.0.0", FALSE, IKEV2_UDP_PORT), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index d1c5626b7..0df040e85 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -171,22 +171,22 @@ METHOD(socket_t, receiver, status_t, if (FD_ISSET(this->ipv4, &rfds)) { - port = IKEV2_UDP_PORT; + port = CHARON_UDP_PORT; selected = this->ipv4; } if (FD_ISSET(this->ipv4_natt, &rfds)) { - port = IKEV2_NATT_PORT; + port = CHARON_NATT_PORT; selected = this->ipv4_natt; } if (FD_ISSET(this->ipv6, &rfds)) { - port = IKEV2_UDP_PORT; + port = CHARON_UDP_PORT; selected = this->ipv6; } if (FD_ISSET(this->ipv6_natt, &rfds)) { - port = IKEV2_NATT_PORT; + port = CHARON_NATT_PORT; selected = this->ipv6_natt; } if (selected) @@ -299,7 +299,7 @@ METHOD(socket_t, receiver, status_t, DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); data_offset = 0; /* remove non esp marker */ - if (dest->get_port(dest) == IKEV2_NATT_PORT) + if (dest->get_port(dest) == CHARON_NATT_PORT) { data_offset += MARKER_LEN; } @@ -339,7 +339,7 @@ METHOD(socket_t, sender, status_t, /* send data */ sport = src->get_port(src); family = dst->get_family(dst); - if (sport == IKEV2_UDP_PORT) + if (sport == CHARON_UDP_PORT) { if (family == AF_INET) { @@ -350,7 +350,7 @@ METHOD(socket_t, sender, status_t, skt = this->ipv6; } } - else if (sport == IKEV2_NATT_PORT) + else if (sport == CHARON_NATT_PORT) { if (family == AF_INET) { @@ -537,7 +537,7 @@ static int open_socket(private_socket_default_socket_t *this, { /* enable UDP decapsulation globally, only for one socket needed */ int type = UDP_ENCAP_ESPINUDP; - if (family == AF_INET && port == IKEV2_NATT_PORT && + if (family == AF_INET && port == CHARON_NATT_PORT && setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) { DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno)); @@ -590,7 +590,7 @@ socket_default_socket_t *socket_default_socket_create() #ifdef __APPLE__ { - int natt_port = IKEV2_NATT_PORT; + int natt_port = CHARON_NATT_PORT; if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port, sizeof(natt_port)) != 0) { @@ -600,28 +600,28 @@ socket_default_socket_t *socket_default_socket_create() } #endif - this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT); + this->ipv4 = open_socket(this, AF_INET, CHARON_UDP_PORT); if (this->ipv4 == 0) { DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled"); } else { - this->ipv4_natt = open_socket(this, AF_INET, IKEV2_NATT_PORT); + this->ipv4_natt = open_socket(this, AF_INET, CHARON_NATT_PORT); if (this->ipv4_natt == 0) { DBG1(DBG_NET, "could not open IPv4 NAT-T socket"); } } - this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT); + this->ipv6 = open_socket(this, AF_INET6, CHARON_UDP_PORT); if (this->ipv6 == 0) { DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled"); } else { - this->ipv6_natt = open_socket(this, AF_INET6, IKEV2_NATT_PORT); + this->ipv6_natt = open_socket(this, AF_INET6, CHARON_NATT_PORT); if (this->ipv6_natt == 0) { DBG1(DBG_NET, "could not open IPv6 NAT-T socket"); diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 6557fc12f..539411379 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -204,7 +204,7 @@ METHOD(socket_t, receiver, status_t, DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); data_offset = IP_LEN + UDP_LEN; /* remove non esp marker */ - if (dest->get_port(dest) == IKEV2_NATT_PORT) + if (dest->get_port(dest) == CHARON_NATT_PORT) { data_offset += MARKER_LEN; } @@ -291,7 +291,7 @@ METHOD(socket_t, receiver, status_t, DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); data_offset = UDP_LEN; /* remove non esp marker */ - if (dest->get_port(dest) == IKEV2_NATT_PORT) + if (dest->get_port(dest) == CHARON_NATT_PORT) { data_offset += MARKER_LEN; } @@ -332,7 +332,7 @@ METHOD(socket_t, sender, status_t, /* send data */ sport = src->get_port(src); family = dst->get_family(dst); - if (sport == IKEV2_UDP_PORT) + if (sport == CHARON_UDP_PORT) { if (family == AF_INET) { @@ -343,7 +343,7 @@ METHOD(socket_t, sender, status_t, skt = this->send6; } } - else if (sport == IKEV2_NATT_PORT) + else if (sport == CHARON_NATT_PORT) { if (family == AF_INET) { @@ -541,8 +541,8 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) { /* Destination Port must be either port or natt_port */ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 6, 14), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, CHARON_UDP_PORT, 1, 0), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, CHARON_NATT_PORT, 6, 14), /* port */ /* IKE version must be 2.x */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET), @@ -667,7 +667,7 @@ socket_raw_socket_t *socket_raw_socket_create() } else { - this->send4 = open_send_socket(this, AF_INET, IKEV2_UDP_PORT); + this->send4 = open_send_socket(this, AF_INET, CHARON_UDP_PORT); if (this->send4 == 0) { DBG1(DBG_NET, "could not open IPv4 send socket, IPv4 disabled"); @@ -675,7 +675,7 @@ socket_raw_socket_t *socket_raw_socket_create() } else { - this->send4_natt = open_send_socket(this, AF_INET, IKEV2_NATT_PORT); + this->send4_natt = open_send_socket(this, AF_INET, CHARON_NATT_PORT); if (this->send4_natt == 0) { DBG1(DBG_NET, "could not open IPv4 NAT-T send socket"); @@ -690,7 +690,7 @@ socket_raw_socket_t *socket_raw_socket_create() } else { - this->send6 = open_send_socket(this, AF_INET6, IKEV2_UDP_PORT); + this->send6 = open_send_socket(this, AF_INET6, CHARON_UDP_PORT); if (this->send6 == 0) { DBG1(DBG_NET, "could not open IPv6 send socket, IPv6 disabled"); @@ -698,7 +698,7 @@ socket_raw_socket_t *socket_raw_socket_create() } else { - this->send6_natt = open_send_socket(this, AF_INET6, IKEV2_NATT_PORT); + this->send6_natt = open_send_socket(this, AF_INET6, CHARON_NATT_PORT); if (this->send6_natt == 0) { DBG1(DBG_NET, "could not open IPv6 NAT-T send socket"); diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index dd9a0b09d..28b493e7a 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -259,7 +259,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, ike_cfg_t *ike_cfg; ike_cfg = ike_cfg_create(certreq, force_encap, - local, FALSE, IKEV2_UDP_PORT, + local, FALSE, CHARON_UDP_PORT, remote, FALSE, IKEV2_UDP_PORT); add_ike_proposals(this, ike_cfg, id); return ike_cfg; diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index c884da05d..83f04bd38 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -188,6 +188,7 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg ike_cfg_t *ike_cfg; char *interface; host_t *host; + u_int16_t ikeport; host = host_create_from_dns(msg->add_conn.other.address, 0, 0); if (host) @@ -224,11 +225,13 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg } } } + ikeport = msg->add_conn.me.ikeport; + ikeport = (ikeport == IKEV2_UDP_PORT) ? CHARON_UDP_PORT : ikeport; ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND, msg->add_conn.force_encap, msg->add_conn.me.address, msg->add_conn.me.allow_any, - msg->add_conn.me.ikeport, + ikeport, msg->add_conn.other.address, msg->add_conn.other.allow_any, msg->add_conn.other.ikeport); diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index 9b0fd73ad..9dc0cfcde 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -169,7 +169,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool, { DESTROY_IF(this->peer_cfg); ike_cfg = ike_cfg_create(FALSE, FALSE, - local_addr, FALSE, IKEV2_UDP_PORT, + local_addr, FALSE, CHARON_UDP_PORT, remote_addr, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); this->peer_cfg = peer_cfg_create( @@ -267,7 +267,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool, { DESTROY_IF(this->ike_cfg); this->ike_cfg = ike_cfg_create(FALSE, FALSE, - local_addr, FALSE, IKEV2_UDP_PORT, + local_addr, FALSE, CHARON_UDP_PORT, remote_addr, FALSE, IKEV2_UDP_PORT); this->ike_cfg->add_proposal(this->ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c index 45bac7cf8..6e5b4af0d 100644 --- a/src/libcharon/processing/jobs/migrate_job.c +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -97,7 +97,7 @@ METHOD(job_t, execute, job_requeue_t, ike_sa->set_kmaddress(ike_sa, this->local, this->remote); host = this->local->clone(this->local); - host->set_port(host, IKEV2_UDP_PORT); + host->set_port(host, CHARON_UDP_PORT); ike_sa->set_my_host(ike_sa, host); host = this->remote->clone(this->remote); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 0a7c52a74..5182da5aa 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -845,9 +845,9 @@ METHOD(ike_sa_t, float_ports, void, private_ike_sa_t *this) { /* do not switch if we have a custom port from MOBIKE/NAT */ - if (this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT) + if (this->my_host->get_port(this->my_host) == CHARON_UDP_PORT) { - this->my_host->set_port(this->my_host, IKEV2_NATT_PORT); + this->my_host->set_port(this->my_host, CHARON_NATT_PORT); } if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT) { @@ -1054,7 +1054,7 @@ static void resolve_hosts(private_ike_sa_t *this) if (this->local_host) { host = this->local_host->clone(this->local_host); - host->set_port(host, IKEV2_UDP_PORT); + host->set_port(host, CHARON_UDP_PORT); } else { @@ -2239,7 +2239,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, } this->task_manager = task_manager_create(&this->public); - this->my_host->set_port(this->my_host, IKEV2_UDP_PORT); + this->my_host->set_port(this->my_host, CHARON_UDP_PORT); if (!this->task_manager || !this->keymat) { diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c index 8228d016a..eee716c85 100644 --- a/src/libcharon/sa/ikev1/tasks/informational.c +++ b/src/libcharon/sa/ikev1/tasks/informational.c @@ -116,7 +116,7 @@ METHOD(task_t, process_r, status_t, notify_type_names, type, redirect); /* Cisco boxes reject the first message from 4500 */ me = this->ike_sa->get_my_host(this->ike_sa); - me->set_port(me, IKEV2_UDP_PORT); + me->set_port(me, CHARON_UDP_PORT); this->ike_sa->set_other_host(this->ike_sa, redirect); this->ike_sa->reauth(this->ike_sa); enumerator->destroy(enumerator); diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c index 90c38666b..388b45c68 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c +++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c @@ -271,15 +271,15 @@ static void update_children(private_ike_mobike_t *this) /** * Apply the port of the old host, if its ip equals the new, use port otherwise. */ -static void apply_port(host_t *host, host_t *old, u_int16_t port) +static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local) { if (host->ip_equals(host, old)) { port = old->get_port(old); } - else if (port == IKEV2_UDP_PORT) + else if (port == (local ? CHARON_UDP_PORT : IKEV2_UDP_PORT)) { - port = IKEV2_NATT_PORT; + port = (local ? CHARON_NATT_PORT : IKEV2_NATT_PORT); } host->set_port(host, port); } @@ -314,9 +314,9 @@ METHOD(ike_mobike_t, transmit, void, continue; } /* reuse port for an active address, 4500 otherwise */ - apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg)); + apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE); other = other->clone(other); - apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg)); + apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE); DBG1(DBG_IKE, "checking path %#H - %#H", me, other); copy = packet->clone(packet); copy->set_source(copy, me); From 657a3ba60907bffa943320621ecff7b45c89c156 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 16 Feb 2012 17:13:37 +0100 Subject: [PATCH 05/32] Link android plugin against liblog in the NDK. Doesn't seem to hurt the build within the source tree. --- src/libcharon/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index db05d3db0..87a2e2240 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -127,6 +127,7 @@ processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h LOCAL_SRC_FILES += $(call add_plugin, android) ifneq ($(call plugin_enabled, android),) LOCAL_C_INCLUDES += frameworks/base/cmds/keystore +LOCAL_LDLIBS += -llog LOCAL_SHARED_LIBRARIES += libcutils endif From 162621ed573b73daa63f77c30c283bd5dcac9b2f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 16 Feb 2012 18:17:09 +0100 Subject: [PATCH 06/32] Moved Android specific logger to separate plugin. This is mainly because the other parts of the existing android plugin can not be built in the NDK (access to keystore and system properties are not part of the stable NDK libraries). --- Android.mk.in | 4 +- configure.in | 4 + man/strongswan.conf.5.in | 2 +- src/libcharon/Android.mk | 6 +- src/libcharon/Makefile.am | 7 ++ src/libcharon/plugins/android/Makefile.am | 1 - .../plugins/android/android_plugin.c | 10 --- src/libcharon/plugins/android_log/Makefile.am | 17 +++++ .../android_log_logger.c} | 24 +++--- .../android_log_logger.h} | 18 ++--- .../plugins/android_log/android_log_plugin.c | 76 +++++++++++++++++++ .../plugins/android_log/android_log_plugin.h | 42 ++++++++++ 12 files changed, 175 insertions(+), 36 deletions(-) create mode 100644 src/libcharon/plugins/android_log/Makefile.am rename src/libcharon/plugins/{android/android_logger.c => android_log/android_log_logger.c} (77%) rename src/libcharon/plugins/{android/android_logger.h => android_log/android_log_logger.h} (71%) create mode 100644 src/libcharon/plugins/android_log/android_log_plugin.c create mode 100644 src/libcharon/plugins/android_log/android_log_plugin.h diff --git a/Android.mk.in b/Android.mk.in index a1ce1c571..19048b9e7 100644 --- a/Android.mk.in +++ b/Android.mk.in @@ -16,8 +16,8 @@ include $(CLEAR_VARS) # this is the list of plugins that are built into libstrongswan and charon # also these plugins are loaded by default (if not changed in strongswan.conf) -strongswan_CHARON_PLUGINS := openssl fips-prf random nonce pubkey pkcs1 \ - pem xcbc hmac kernel-netlink socket-default android \ +strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ + pkcs1 pem xcbc hmac kernel-netlink socket-default android \ stroke eap-identity eap-mschapv2 eap-md5 ifneq ($(strongswan_BUILD_SCEPCLIENT),) diff --git a/configure.in b/configure.in index 0c288f82e..96b1fe373 100644 --- a/configure.in +++ b/configure.in @@ -206,6 +206,7 @@ ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.]) ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.]) ARG_ENABL_SET([android], [enable Android specific plugin.]) +ARG_ENABL_SET([android-log], [enable Android specific logger plugin.]) ARG_ENABL_SET([maemo], [enable Maemo specific plugin.]) ARG_ENABL_SET([nm], [enable NetworkManager backend.]) ARG_ENABL_SET([ha], [enable high availability cluster plugin.]) @@ -935,6 +936,7 @@ ADD_PLUGIN([medsrv], [c charon]) ADD_PLUGIN([medcli], [c charon]) ADD_PLUGIN([dhcp], [c charon]) ADD_PLUGIN([android], [c charon]) +ADD_PLUGIN([android-log], [c charon]) ADD_PLUGIN([ha], [c charon]) ADD_PLUGIN([whitelist], [c charon]) ADD_PLUGIN([certexpire], [c charon]) @@ -1016,6 +1018,7 @@ AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue) AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue) AM_CONDITIONAL(USE_UCI, test x$uci = xtrue) AM_CONDITIONAL(USE_ANDROID, test x$android = xtrue) +AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue) AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue) AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) @@ -1253,6 +1256,7 @@ AC_OUTPUT( src/libcharon/plugins/coupling/Makefile src/libcharon/plugins/radattr/Makefile src/libcharon/plugins/android/Makefile + src/libcharon/plugins/android_log/Makefile src/libcharon/plugins/maemo/Makefile src/libcharon/plugins/stroke/Makefile src/libcharon/plugins/updown/Makefile diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 1a4da0016..ee8f8a8dc 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -272,7 +272,7 @@ Section to define syslog loggers, see LOGGER CONFIGURATION Number of worker threads in charon .SS charon.plugins subsection .TP -.BR charon.plugins.android.loglevel " [1]" +.BR charon.plugins.android_log.loglevel " [1]" Loglevel for logging to Android specific logger .TP .BR charon.plugins.attr diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 87a2e2240..5e93e235f 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -127,10 +127,14 @@ processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h LOCAL_SRC_FILES += $(call add_plugin, android) ifneq ($(call plugin_enabled, android),) LOCAL_C_INCLUDES += frameworks/base/cmds/keystore -LOCAL_LDLIBS += -llog LOCAL_SHARED_LIBRARIES += libcutils endif +LOCAL_SRC_FILES += $(call add_plugin, android-log) +ifneq ($(call plugin_enabled, android-log),) +LOCAL_LDLIBS += -llog +endif + LOCAL_SRC_FILES += $(call add_plugin, attr) LOCAL_SRC_FILES += $(call add_plugin, eap-aka) diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index a254c0336..df23e22f6 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -456,6 +456,13 @@ if MONOLITHIC endif endif +if USE_ANDROID_LOG + SUBDIRS += plugins/android_log +if MONOLITHIC + libcharon_la_LIBADD += plugins/android_log/libstrongswan-android-log.la +endif +endif + if USE_MAEMO SUBDIRS += plugins/maemo if MONOLITHIC diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am index b922ef4af..b10cd9527 100644 --- a/src/libcharon/plugins/android/Makefile.am +++ b/src/libcharon/plugins/android/Makefile.am @@ -14,7 +14,6 @@ libstrongswan_android_la_SOURCES = \ android_plugin.c android_plugin.h \ android_service.c android_service.h \ android_handler.c android_handler.h \ - android_logger.c android_logger.h \ android_creds.c android_creds.h libstrongswan_android_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c index bad8bc042..c0f58e9b4 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android/android_plugin.c @@ -15,7 +15,6 @@ */ #include "android_plugin.h" -#include "android_logger.h" #include "android_handler.h" #include "android_creds.h" #include "android_service.h" @@ -35,11 +34,6 @@ struct private_android_plugin_t { */ android_plugin_t public; - /** - * Android specific logger - */ - android_logger_t *logger; - /** * Android specific DNS handler */ @@ -68,10 +62,8 @@ METHOD(plugin_t, destroy, void, hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); lib->credmgr->remove_set(lib->credmgr, &this->creds->set); - charon->bus->remove_logger(charon->bus, &this->logger->logger); this->creds->destroy(this->creds); this->handler->destroy(this->handler); - this->logger->destroy(this->logger); DESTROY_IF(this->service); free(this); } @@ -91,14 +83,12 @@ plugin_t *android_plugin_create() .destroy = _destroy, }, }, - .logger = android_logger_create(), .creds = android_creds_create(), ); this->service = android_service_create(this->creds); this->handler = android_handler_create(this->service != NULL); - charon->bus->add_logger(charon->bus, &this->logger->logger); lib->credmgr->add_set(lib->credmgr, &this->creds->set); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am new file mode 100644 index 000000000..3c180f1db --- /dev/null +++ b/src/libcharon/plugins/android_log/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-android-log.la +else +plugin_LTLIBRARIES = libstrongswan-android-log.la +endif + +libstrongswan_android_log_la_SOURCES = \ + android_log_plugin.c android_log_plugin.h \ + android_log_logger.c android_log_logger.h + +libstrongswan_android_log_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android_log/android_log_logger.c similarity index 77% rename from src/libcharon/plugins/android/android_logger.c rename to src/libcharon/plugins/android_log/android_log_logger.c index 0c5f609f7..48bcaa577 100644 --- a/src/libcharon/plugins/android/android_logger.c +++ b/src/libcharon/plugins/android_log/android_log_logger.c @@ -16,23 +16,23 @@ #include #include -#include "android_logger.h" +#include "android_log_logger.h" #include #include #include -typedef struct private_android_logger_t private_android_logger_t; +typedef struct private_android_log_logger_t private_android_log_logger_t; /** - * Private data of an android_logger_t object + * Private data of an android_log_logger_t object */ -struct private_android_logger_t { +struct private_android_log_logger_t { /** * Public interface */ - android_logger_t public; + android_log_logger_t public; /** * logging level @@ -46,7 +46,7 @@ struct private_android_logger_t { }; METHOD(logger_t, log_, void, - private_android_logger_t *this, debug_t group, level_t level, + private_android_log_logger_t *this, debug_t group, level_t level, int thread, ike_sa_t* ike_sa, const char *message) { int prio = level > 1 ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO; @@ -71,13 +71,13 @@ METHOD(logger_t, log_, void, } METHOD(logger_t, get_level, level_t, - private_android_logger_t *this, debug_t group) + private_android_log_logger_t *this, debug_t group) { return this->level; } -METHOD(android_logger_t, destroy, void, - private_android_logger_t *this) +METHOD(android_log_logger_t, destroy, void, + private_android_log_logger_t *this) { this->mutex->destroy(this->mutex); free(this); @@ -86,9 +86,9 @@ METHOD(android_logger_t, destroy, void, /** * Described in header. */ -android_logger_t *android_logger_create() +android_log_logger_t *android_log_logger_create() { - private_android_logger_t *this; + private_android_log_logger_t *this; INIT(this, .public = { @@ -100,7 +100,7 @@ android_logger_t *android_logger_create() }, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .level = lib->settings->get_int(lib->settings, - "%s.plugins.android.loglevel", 1, charon->name), + "%s.plugins.android_log.loglevel", 1, charon->name), ); return &this->public; diff --git a/src/libcharon/plugins/android/android_logger.h b/src/libcharon/plugins/android_log/android_log_logger.h similarity index 71% rename from src/libcharon/plugins/android/android_logger.h rename to src/libcharon/plugins/android_log/android_log_logger.h index 15abbb43f..ed271bf6c 100644 --- a/src/libcharon/plugins/android/android_logger.h +++ b/src/libcharon/plugins/android_log/android_log_logger.h @@ -14,21 +14,21 @@ */ /** - * @defgroup android_logger android_logger - * @{ @ingroup android + * @defgroup android_log_logger android_log_logger + * @{ @ingroup android_log */ -#ifndef ANDROID_LOGGER_H_ -#define ANDROID_LOGGER_H_ +#ifndef ANDROID_LOG_LOGGER_H_ +#define ANDROID_LOG_LOGGER_H_ #include -typedef struct android_logger_t android_logger_t; +typedef struct android_log_logger_t android_log_logger_t; /** * Android specific logger. */ -struct android_logger_t { +struct android_log_logger_t { /** * Implements logger_t interface @@ -38,7 +38,7 @@ struct android_logger_t { /** * Destroy the logger. */ - void (*destroy)(android_logger_t *this); + void (*destroy)(android_log_logger_t *this); }; @@ -47,6 +47,6 @@ struct android_logger_t { * * @return logger instance */ -android_logger_t *android_logger_create(); +android_log_logger_t *android_log_logger_create(); -#endif /** ANDROID_LOGGER_H_ @}*/ +#endif /** ANDROID_LOG_LOGGER_H_ @}*/ diff --git a/src/libcharon/plugins/android_log/android_log_plugin.c b/src/libcharon/plugins/android_log/android_log_plugin.c new file mode 100644 index 000000000..6757c2210 --- /dev/null +++ b/src/libcharon/plugins/android_log/android_log_plugin.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 . + * + * 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 "android_log_plugin.h" +#include "android_log_logger.h" + +#include + +typedef struct private_android_log_plugin_t private_android_log_plugin_t; + +/** + * Private data of an android_log_plugin_t object. + */ +struct private_android_log_plugin_t { + + /** + * Public android_log_plugin_t interface. + */ + android_log_plugin_t public; + + /** + * Android specific logger + */ + android_log_logger_t *logger; + +}; + +METHOD(plugin_t, get_name, char*, + private_android_log_plugin_t *this) +{ + return "android-log"; +} + +METHOD(plugin_t, destroy, void, + private_android_log_plugin_t *this) +{ + charon->bus->remove_logger(charon->bus, &this->logger->logger); + this->logger->destroy(this->logger); + free(this); +} + +/** + * See header + */ +plugin_t *android_log_plugin_create() +{ + private_android_log_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .logger = android_log_logger_create(), + ); + + charon->bus->add_logger(charon->bus, &this->logger->logger); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/android_log/android_log_plugin.h b/src/libcharon/plugins/android_log/android_log_plugin.h new file mode 100644 index 000000000..32c4dc10b --- /dev/null +++ b/src/libcharon/plugins/android_log/android_log_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 . + * + * 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 android_log android_log + * @ingroup cplugins + * + * @defgroup android_log_plugin android_log_plugin + * @{ @ingroup android_log + */ + +#ifndef ANDROID_LOG_PLUGIN_H_ +#define ANDROID_LOG_PLUGIN_H_ + +#include + +typedef struct android_log_plugin_t android_log_plugin_t; + +/** + * Plugin providing an Android specific logger implementation. + */ +struct android_log_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** ANDROID_LOG_PLUGIN_H_ @}*/ From 80b267f9e3baccdf636e8302efd5cf277147d97e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 16 Feb 2012 18:41:10 +0100 Subject: [PATCH 07/32] Use filter instead of findstring to check for enabled plugins in Android.mk. findstring is not prefix-safe (i.e. android matches android-log). On the other hand filter matches words separated by whitespace and if no wildcard (%) is used the full word has to match. --- Android.mk.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk.in b/Android.mk.in index 19048b9e7..2b51d3ea1 100644 --- a/Android.mk.in +++ b/Android.mk.in @@ -34,7 +34,7 @@ strongswan_PLUGINS := $(sort $(strongswan_CHARON_PLUGINS) \ # helper macros to only add source files for plugins included in the list above # source files are relative to the android.mk that called the macro -plugin_enabled = $(findstring $(1), $(strongswan_PLUGINS)) +plugin_enabled = $(filter $(1), $(strongswan_PLUGINS)) add_plugin = $(if $(call plugin_enabled,$(1)), \ $(patsubst $(LOCAL_PATH)/%,%, \ $(wildcard \ From 3fa8d7738e7441c9bcbb39a88e38102a77a90071 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Feb 2012 15:39:25 +0100 Subject: [PATCH 08/32] Extracted some parts from Android.mk.in which can be used for NDK builds. --- .gitignore | 2 +- Android.common.mk.in | 19 +++++++++++++++++++ Android.mk.in => Android.mk | 14 +------------- Makefile.am | 8 ++++---- 4 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 Android.common.mk.in rename Android.mk.in => Android.mk (85%) diff --git a/.gitignore b/.gitignore index 34d3ee667..29adedde6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/Android.mk +/Android.common.mk Makefile Makefile.in aclocal.m4 diff --git a/Android.common.mk.in b/Android.common.mk.in new file mode 100644 index 000000000..1bc8a8304 --- /dev/null +++ b/Android.common.mk.in @@ -0,0 +1,19 @@ +# some common definitions used by the main and the NDK-specific Android.mk +# include this after strongswan_PLUGINS has been defined + +# helper macros to only add source files for plugins included in the list above +# source files are relative to the android.mk that called the macro +plugin_enabled = $(filter $(1), $(strongswan_PLUGINS)) +add_plugin = $(if $(call plugin_enabled,$(1)), \ + $(patsubst $(LOCAL_PATH)/%,%, \ + $(wildcard \ + $(subst %,$(subst -,_,$(strip $(1))), \ + $(LOCAL_PATH)/plugins/%/%*.c \ + ) \ + ) \ + ) \ + ) + +# strongSwan version, replaced by top Makefile +strongswan_VERSION := "@PACKAGE_VERSION@" + diff --git a/Android.mk.in b/Android.mk similarity index 85% rename from Android.mk.in rename to Android.mk index 2b51d3ea1..edfdef397 100644 --- a/Android.mk.in +++ b/Android.mk @@ -32,18 +32,7 @@ strongswan_PLUGINS := $(sort $(strongswan_CHARON_PLUGINS) \ $(strongswan_STARTER_PLUGINS) \ $(strongswan_SCEPCLIENT_PLUGINS)) -# helper macros to only add source files for plugins included in the list above -# source files are relative to the android.mk that called the macro -plugin_enabled = $(filter $(1), $(strongswan_PLUGINS)) -add_plugin = $(if $(call plugin_enabled,$(1)), \ - $(patsubst $(LOCAL_PATH)/%,%, \ - $(wildcard \ - $(subst %,$(subst -,_,$(strip $(1))), \ - $(LOCAL_PATH)/plugins/%/%*.c \ - ) \ - ) \ - ) \ - ) +include $(LOCAL_PATH)/Android.common.mk # includes strongswan_PATH := $(LOCAL_PATH) @@ -53,7 +42,6 @@ libgmp_PATH := external/strongswan-support/gmp openssl_PATH := external/openssl/include # some definitions -strongswan_VERSION := "@PACKAGE_VERSION@" strongswan_DIR := "/system/bin" strongswan_SBINDIR := "/system/bin" strongswan_PIDDIR := "/data/misc/vpn" diff --git a/Makefile.am b/Makefile.am index 908afca44..8a558c150 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,17 +6,17 @@ endif ACLOCAL_AMFLAGS = -I m4/config -EXTRA_DIST = Doxyfile.in LICENSE Android.mk.in Android.mk +EXTRA_DIST = Doxyfile.in LICENSE Android.common.mk.in Android.common.mk Android.mk CLEANFILES = Doxyfile -BUILT_SOURCES = Android.mk -MAINTAINERCLEANFILES = Android.mk +BUILT_SOURCES = Android.common.mk +MAINTAINERCLEANFILES = Android.common.mk if USE_DEV_HEADERS config_includedir = $(ipseclibdir)/include nodist_config_include_HEADERS = config.h endif -Android.mk : Android.mk.in configure.in +Android.common.mk : Android.common.mk.in configure.in sed \ -e "s:\@PACKAGE_VERSION\@:$(PACKAGE_VERSION):" \ $(srcdir)/$@.in > $@ From 2f203aee0efadd8b631fba62148da1480537e19a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Feb 2012 15:40:57 +0100 Subject: [PATCH 09/32] Android.mk for NDK build added. --- src/frontends/android/README.ndk | 19 +++++++ src/frontends/android/jni/.gitignore | 4 ++ src/frontends/android/jni/Android.mk | 62 +++++++++++++++++++++++ src/frontends/android/jni/vstr/Android.mk | 11 ++++ 4 files changed, 96 insertions(+) create mode 100644 src/frontends/android/README.ndk create mode 100644 src/frontends/android/jni/.gitignore create mode 100644 src/frontends/android/jni/Android.mk create mode 100644 src/frontends/android/jni/vstr/Android.mk diff --git a/src/frontends/android/README.ndk b/src/frontends/android/README.ndk new file mode 100644 index 000000000..dc0df1ffd --- /dev/null +++ b/src/frontends/android/README.ndk @@ -0,0 +1,19 @@ +To build this within the NDK several things have to be added in the jni +folder: + + - strongswan: The strongSwan sources. This can either be an extracted tarball, + or a symlink to the Git repository. To build from the repository the sources + have to be prepared first: ./autogen && ./configure && make && make distclean + + - openssl: The OpenSSL sources. Since the sources need to be changed to be + built on Android (and especially in the NDK), we provide a modified mirror + of the official Android OpenSSL version on git.strongswan.org. + + - vstr: The Vstr string library. Since cross-compiling this library is not + that easy with the configure script and Makefiles included in the tarball, + the easiest way to build it is still to use droid-gcc (as described on + wiki.strongswan.org). The build script provided on the wiki builds the + library and copies the required header files to the configured installation + directory. Please note that the Android.mk provided on the wiki (vstr.mk) + does not work in the NDK. A replacement is already in place in jni/vstr. + diff --git a/src/frontends/android/jni/.gitignore b/src/frontends/android/jni/.gitignore new file mode 100644 index 000000000..90fd652f0 --- /dev/null +++ b/src/frontends/android/jni/.gitignore @@ -0,0 +1,4 @@ +openssl +strongswan +vstr/libvstr.a +vstr/include diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk new file mode 100644 index 000000000..74c6c6a42 --- /dev/null +++ b/src/frontends/android/jni/Android.mk @@ -0,0 +1,62 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ + pkcs1 pem xcbc hmac socket-default \ + eap-identity eap-mschapv2 eap-md5 + +strongswan_PLUGINS := $(strongswan_CHARON_PLUGINS) + +include $(LOCAL_PATH)/strongswan/Android.common.mk + +# includes +strongswan_PATH := $(LOCAL_PATH)/strongswan +libvstr_PATH := $(LOCAL_PATH)/vstr/include +openssl_PATH := $(LOCAL_PATH)/openssl/include + +# CFLAGS (partially from a configure run using droid-gcc) +strongswan_CFLAGS := \ + -Wno-format \ + -Wno-pointer-sign \ + -Wno-pointer-arith \ + -Wno-sign-compare \ + -Wno-strict-aliasing \ + -DHAVE___BOOL \ + -DHAVE_STDBOOL_H \ + -DHAVE_ALLOCA_H \ + -DHAVE_ALLOCA \ + -DHAVE_CLOCK_GETTIME \ + -DHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC \ + -DHAVE_PRCTL \ + -DHAVE_LINUX_UDP_H \ + -DHAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY \ + -DHAVE_IPSEC_MODE_BEET \ + -DHAVE_IPSEC_DIR_FWD \ + -DOPENSSL_NO_EC \ + -DOPENSSL_NO_ECDSA \ + -DOPENSSL_NO_ECDH \ + -DOPENSSL_NO_ENGINE \ + -DCONFIG_H_INCLUDED \ + -DCAPABILITIES \ + -DCAPABILITIES_NATIVE \ + -DMONOLITHIC \ + -DUSE_IKEV1 \ + -DUSE_IKEV2 \ + -DUSE_VSTR \ + -DDEBUG \ + -DCHARON_UDP_PORT=4000 \ + -DVERSION=\"$(strongswan_VERSION)\" \ + -DDEV_RANDOM=\"/dev/random\" \ + -DDEV_URANDOM=\"/dev/urandom\" + +# only for Android 2.0+ +strongswan_CFLAGS += \ + -DHAVE_IN6ADDR_ANY + +include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ + vstr \ + openssl \ + strongswan/src/libcharon \ + strongswan/src/libhydra \ + strongswan/src/libstrongswan \ +)) diff --git a/src/frontends/android/jni/vstr/Android.mk b/src/frontends/android/jni/vstr/Android.mk new file mode 100644 index 000000000..87355a671 --- /dev/null +++ b/src/frontends/android/jni/vstr/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := libvstr.a + +LOCAL_MODULE := libvstr + +LOCAL_PRELINK_MODULE := false + +include $(PREBUILT_STATIC_LIBRARY) From da848ab894358f3db6f069989702a49308a1c2a2 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Feb 2012 16:59:23 +0100 Subject: [PATCH 10/32] Added Android shell app created with Android SDK. --- src/frontends/android/.classpath | 8 ++++ src/frontends/android/.gitignore | 4 ++ src/frontends/android/AndroidManifest.xml | 23 ++++++++++ src/frontends/android/proguard.cfg | 40 ++++++++++++++++++ src/frontends/android/project.properties | 11 +++++ .../android/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 4147 bytes .../android/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 1723 bytes .../android/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2574 bytes src/frontends/android/res/layout/main.xml | 12 ++++++ src/frontends/android/res/values/strings.xml | 7 +++ .../android/strongSwanActivity.java | 13 ++++++ 11 files changed, 118 insertions(+) create mode 100644 src/frontends/android/.classpath create mode 100644 src/frontends/android/.gitignore create mode 100644 src/frontends/android/AndroidManifest.xml create mode 100644 src/frontends/android/proguard.cfg create mode 100644 src/frontends/android/project.properties create mode 100644 src/frontends/android/res/drawable-hdpi/ic_launcher.png create mode 100644 src/frontends/android/res/drawable-ldpi/ic_launcher.png create mode 100644 src/frontends/android/res/drawable-mdpi/ic_launcher.png create mode 100644 src/frontends/android/res/layout/main.xml create mode 100644 src/frontends/android/res/values/strings.xml create mode 100644 src/frontends/android/src/org/strongswan/android/strongSwanActivity.java diff --git a/src/frontends/android/.classpath b/src/frontends/android/.classpath new file mode 100644 index 000000000..a4763d1ee --- /dev/null +++ b/src/frontends/android/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/frontends/android/.gitignore b/src/frontends/android/.gitignore new file mode 100644 index 000000000..a031dba58 --- /dev/null +++ b/src/frontends/android/.gitignore @@ -0,0 +1,4 @@ +bin/ +gen/ +libs/ +obj/ diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml new file mode 100644 index 000000000..702a15d21 --- /dev/null +++ b/src/frontends/android/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/frontends/android/proguard.cfg b/src/frontends/android/proguard.cfg new file mode 100644 index 000000000..b1cdf17b5 --- /dev/null +++ b/src/frontends/android/proguard.cfg @@ -0,0 +1,40 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/src/frontends/android/project.properties b/src/frontends/android/project.properties new file mode 100644 index 000000000..8da376af8 --- /dev/null +++ b/src/frontends/android/project.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-15 diff --git a/src/frontends/android/res/drawable-hdpi/ic_launcher.png b/src/frontends/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8074c4c571b8cd19e27f4ee5545df367420686d7 GIT binary patch literal 4147 zcmV-35X|q1P)OwvMs$Q8_8nISM!^>PxsujeDCl4&hPxrxkp%Qc^^|l zp6LqAcf3zf1H4aA1Gv-O6ha)ktct9Y+VA@N^9i;p0H%6v>ZJZYQ`zEa396z-gi{r_ zDz)D=vgRv62GCVeRjK{15j7V@v6|2nafFX6W7z2j1_T0a zLyT3pGTubf1lB5)32>bl0*BflrA!$|_(WD2)iJIfV}37=ZKAC zSe3boYtQ=;o0i>)RtBvsI#iT{0!oF1VFeW`jDjF2Q4aE?{pGCAd>o8Kg#neIh*AMY zLl{;F!vLiem7s*x0<9FKAd6LoPz3~G32P+F+cuGOJ5gcC@pU_?C2fmix7g2)SUaQO$NS07~H)#fn!Q<}KQWtX}wW`g2>cMld+`7Rxgq zChaey66SG560JhO66zA!;sK1cWa2AG$9k~VQY??6bOmJsw9@3uL*z;WWa7(Nm{^TA zilc?y#N9O3LcTo2c)6d}SQl-v-pE4^#wb=s(RxaE28f3FQW(yp$ulG9{KcQ7r>7mQ zE!HYxUYex~*7IinL+l*>HR*UaD;HkQhkL(5I@UwN%Wz504M^d!ylo>ANvKPF_TvA< zkugG5;F6x}$s~J8cnev->_(Ic7%lGQgUi3n#XVo36lUpcS9s z)ympRr7}@|6WF)Ae;D{owN1;aZSR50al9h~?-WhbtKK%bDd zhML131oi1Bu1&Qb$Cp199LJ#;j5d|FhW8_i4KO1OI>}J^p2DfreMSVGY9aFlr&90t zyI2FvxQiKMFviSQeP$Ixh#70qj5O%I+O_I2t2XHWqmh2!1~tHpN3kA4n=1iHj?`@c<~3q^X6_Q$AqTDjBU`|!y<&lkqL|m5tG(b z8a!z&j^m(|;?SW(l*?tZ*{m2H9d&3jqBtXh>O-5e4Qp-W*a5=2NL&Oi62BUM)>zE3 zbSHb>aU3d@3cGggA`C-PsT9^)oy}%dHCaO~nwOrm5E54=aDg(&HR4S23Oa#-a^=}w%g?ZP-1iq8PSjE8jYaGZu z$I)?YN8he?F9>)2d$G6a*zm0XB*Rf&gZAjq(8l@CUDSY1tB#!i> zW$VfG%#SYSiZ};)>pHA`qlfDTEYQEwN6>NNEp+uxuqx({Fgr zjI@!4xRc?vk^9+~eU|mzH__dCDI=xb{Cd}4bELS9xRaS!*FXMwtMR-RR%SLMh0Cjl zencr8#Su<4(%}$yGVBU-HX{18v=yPH*+%^Vtknc>2A;%-~DrYFx^3XfuVgvZ{#1tA== zm3>IzAM2{3Iv_d1XG{P6^tN3|PkJMnjs&CWN7%7_CmjoVakUhsa&dMv==2~^ri?&x zVdv*rnfVyM+I1^Kg*S=23mR@+0T9BWFZUu~@toA8d)fw6be=`Yb6DSX6D?jB%2YT~ z*aHjtIOozfMhA!Jd*?u5_n!SnX>vX`=Ti-1HA4RiE>eI3vTn zz+>Ccf0HX6Ans-ebOB>RJST-Cyr#4XAk+mAlJgdQnoE{^iIN)OcYFSpgJUmXtl@tT z-^ZuUeSj5hSFrQwqX>~EtZ*{>Gi8Bu9_|o06oNtaXP?E936!a@DsvS*tsB@fa6kEA z5GkjwmH?EgpiG&itsB_Tb1NxtFnvxh_s@9KYX1Sttf?AlI~)z zT=6Y7ulx=}<8Scr_UqU-_z)5gPo%050PsbM*ZLno;_-ow&k?FZJtYmb2hPA$LkP)8 z=^d0Q6PImh6Y|QT?{grxj)S=uBKvY2EQUbm@ns9^yKiP~$DcD)c$5Em`zDSScH%iH zVov&m=cMo`1tYwA=!a}vb_ef_{)Q2?FUqn>BR$6phXQRv^1%=YfyE-F$AR4Q?9D!f zCzB^^#td~4u&l~l#rp2QLfe3+_ub9@+|x+m;=2(sQ`s%gO|j$XBb>A7Q(UydipiMw%igcweV#Cr~SP);q>w`bxts_4} znKHg?X==JDkQl3Y>Ckt%`s{n?Nq-1Fw5~%Mq$CAsi-`yu_bKm zxs#QdE7&vgJD%M84f4SNzSDv)S|V?|$!d5a#lhT5>>YWE4NGqa9-fbmV$=)@k&32kdEYetna>=j@0>V8+wRsL;po!3ivVwh<9tn z2S<1u9DAAQ>x1Sn=fk`)At|quvleV($B|#Kap_lB-F^*yV=wZ{9baUu(uXfokr95^ zA*!*W=5a>$2Ps`-F^+qRQT^{*cN>vipT*4!r#p%{(#I7s z0NN94*q?ib$KJjfDI_sjHNdmEVp5wB&j54O#VoFqBwy)gfA$%)4d_X4q${L9Xom2R3xy&ZBSNgt4a1d7K^CDWa9r zVb-_52m}Vp)`9;ZSKd#|U4ZYj5}Gp49{4utST|=c`~(#>KHF6}CCov1iHYw zt{bWo)A@yF2$~c(nR$rSAaFQ$(Wh{vkG1AlutDMw=mM`C`T=X&|Ad9fb5Od}ROt1z zOpczHqrb4Jo^rSCiW#&o(m7jFamnrsTpQb;*h4o8r#$aZ}2RaT-x2u^^ z%u@YyIv$U^u~@9(XGbSwU@fk6SikH>j+D1jQrYTKGJpW%vUT{!d}7THI5&Sa?~MKy zS0-mvMl+BOcroEJ@hN!2H_?coTEJ5Q<;Nd?yx;eIj4{$$E2?YUO|NtNPJ-PdDf;s} zab;}Mz0kbOI}5*w@3gROcnl#5)wQnEhDBfn!Xhy`u>C}*E~vWpO^HS)FC>8^umI=+ z&H;LW6w#;EF`}vQd_9Muru`KnQVPI9U?(sD)&Dg-0j3#(!fNKVZ_GoYH{la~d*1Yh$TI-TL>mI4vpNb@sU2=IZ8vL%AXUx0 zz{K0|nK(yizLHaeW#ZhRfQXoK^}1$=$#1{Yn002ovPDHLkV1n#w+^+xt literal 0 HcmV?d00001 diff --git a/src/frontends/android/res/drawable-ldpi/ic_launcher.png b/src/frontends/android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1095584ec21f71cd0afc9e0993aa2209671b590c GIT binary patch literal 1723 zcmV;s21NOZP)AReP91Tc8>~sHP8V>Ys(CF=aT`Sk=;|pS}XrJPb~T1dys{sdO&0YpQBSz*~us zcN*3-J_EnE1cxrXiq*F~jZje~rkAe3vf3>;eR)3?Ox=jK*jEU7Do|T`2NqP{56w(* zBAf)rvPB_7rsfeKd0^!CaR%BHUC$tsP9m8a!i@4&TxxzagzsYHJvblx4rRUu#0Jlz zclZJwdC}7S3BvwaIMTiwb!98zRf|zoya>NudJkDGgEYs=q*HmC)>GExofw=92}s;l z_YgKLUT5`<1RBwq{f)K~I%M=gRE6d)b5BP`8{u9x0-wsG%H)w^ zRU7n9FwtlfsZSjiSB(k8~Y5+O>dyoSI477Ly?|FR?m))C!ci%BtY!2Sst8Uri#|SFX&)8{_Ou2 z9r5p3Vz9_GY#%D>%huqp_>U}K45YGy__TE!HZA@bMxX~@{;>cGYRgH~Ih*vd7EgV7h6Pg$#$lH+5=^lj{W80p{{l+;{7_t5cv3xVUy zl_BY4ht1JH*EEeRS{VwTC(QFIVu8zF&P8O$gJsMgsSO35SVvBrX`Vah$Yz2-5T>-`4DJNH;N zlSSY8-mfty+|1~*;BtTwLz_w5 z+lRv)J28~G%ouyvca(@|{2->WsPii&79&nju7ITE6hMX4AQc{|KqZN#)aAvemg3IZ zCr}Y+!r}JU&^>U1C2WyZC<=47itSYQ`?$5{VH?mtFMFFExfYTsfqK%*WzH@Onc#i` zI@a|rm-WbKk{5my{mF}H>Duc$bit&yLAgFfqo2vVbm~?FeG#0F?dSP*kxSo0Ff!o@ z(C}B;r&6pa-NY4;y~5lX8g&*MYQ>yLGd^tDWC4(sGy$Ow-*!eh%xt;>ve|J1q$*w< zh;B#cz!6l2=5bkX#nJ9PJQ`ew8t>7z$bxqf*QB=l2_UB$hK|1EIfloN-jQ=qcwChF zYAkkyp=;FwcnUB3v0=*tMYMA(HdyQ`Og{P|8RRXpj5bgrSmEzSMfBn+{{vpNxw?;5UX;iv9sYxy_`IQHs$i<61a_iv^L>h8s-`D(`e@|IgS*Fj zNGM876Gf;3D8*1UX9a%v>yJKD*QkCwW2AirU(L{qNA)JghmGItc;(H<$!ABY&gBy1vJIEUj-b8%el*o|VkG)LqNx#TG>Jvj^jIte!!+RY z)T4j$7+PoF1AkRBf}R#^T=-q|PaK1$c<4UH)Hpq3$4WA|xtr!ZQLC=*vNE>O6E9kp+5X0eKB$6>C(lPwI@3#oY zhS_%x7e|j!$yG?ECXmh~EH~^OeuK}+sWoJse3Z3?ha3n`MM9KvA?uqpEnBg4Q46)7 zM$p%a$@l;+O}vfvx%XjH`}a{(-HHth9!JaUwV0*VqGR48^gWNYN<&~7x)y$e!X>e` zZ5!6KZoxbKuV9XUDI%#M1~IVh?pNSdeb~6@$y`v|yk=XK+fHxnDqnUK4&=QRNyIVf zYbDM*cI>~qIy*a7=z7uqkw@agd(<=y-Q7L!ty_23SGdXmahO<;N=wB+j;lNm%=OHC zy zU|>La6h%92y4IPufI$9>Xu!@y`TaNgtg&41@PwMwBdmSm7)xAWDLoqjZ==P2#*k7! z3o1)cVSI3KP_!?d8G^Lg0FtLXC~JYdxi|c%h~lXEixY=%VSFF@!*3&&9>(Rb|iK54Cx5;s~PY5iaV1het%w`dgQFBAJ;aFK zImQC}(|QaCFYUm1JVfzSc)ebv=)ObI)0jwJb``}Zj9J0n0Xgn*Zc(rFM9$xh_makZbm-at_v5^SW zM1y1SW@%+FuIy*WR)i3A2N_q;(YO`O!A|Ts^%z}9ZepCj3ytlw#x%N_fNrKKtPh`< z|1{UqF`4LxHaCQ79+E=uUXCOZ35jAMRz%R%0(P!0FMv=sk>Nr8%+OzY^c-M9@+fz=G`qa@v4sF5u-2289-#$**LWnyNNDwDf1( zkUiMnw|y$tn>pQP=Vn!#|17L^5AGrjtBkN$D@v)Z7LXc5EFhLB4<;7Wehh)CMqX|W zqsiZaO^benJ_hwa&V0ub$-_HUk**?g6fm9|!@kguU6*zhK)$qn-<3*kFrYPIaqR=V zUaUvk>@F_89b@tHs8R!*QKY;INJ<2_U+K6Ca3e9Gsl2{qY0%a7J?uICWgHuLfj+MB z=GkAN1&ifT#2u}B+2S#~$5jA(Qn^;H%CCmIae4AE-Dsng|Hl*Ov!z72k3ZnJs{pp| z+pW`DDueC#mEWOf=ucJ!dTL}hzOeiS-i?m2E;`EKz4<&Lu~NnW?peqVU^@<+T3KKu z{yrI%Qy-Z%HEvLUz}n^~m?7x`xuCtNR#L2En!T>dQtIKdS#V-Hzt3RtwTeYtmQ&dR z6qXZvac*oc@BUYEH%@Ylv_1&tSjkbzzU6*h1(3^C`;1z;g_SmOtclS?KWk2VYE zM*oS<=C483XckW?GN|1jfh3Ro(h + + + + + \ No newline at end of file diff --git a/src/frontends/android/res/values/strings.xml b/src/frontends/android/res/values/strings.xml new file mode 100644 index 000000000..f4df7613e --- /dev/null +++ b/src/frontends/android/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Hello World, strongSwanActivity! + strongSwan + + \ No newline at end of file diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java new file mode 100644 index 000000000..16d4a0973 --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java @@ -0,0 +1,13 @@ +package org.strongswan.android; + +import android.app.Activity; +import android.os.Bundle; + +public class strongSwanActivity extends Activity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } +} \ No newline at end of file From 4a2081430056cebc760638bd96eb685e184835cb Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 17 Feb 2012 17:16:07 +0100 Subject: [PATCH 11/32] Added android.net.VpnService wrapper around charon (loaded via JNI). --- src/frontends/android/AndroidManifest.xml | 6 + src/frontends/android/jni/Android.mk | 1 + .../android/jni/libandroidbridge/Android.mk | 33 +++++ .../jni/libandroidbridge/charonservice.c | 113 ++++++++++++++++++ .../strongswan/android/CharonVpnService.java | 50 ++++++++ .../android/strongSwanActivity.java | 31 ++++- 6 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/frontends/android/jni/libandroidbridge/Android.mk create mode 100644 src/frontends/android/jni/libandroidbridge/charonservice.c create mode 100644 src/frontends/android/src/org/strongswan/android/CharonVpnService.java diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml index 702a15d21..63464e712 100644 --- a/src/frontends/android/AndroidManifest.xml +++ b/src/frontends/android/AndroidManifest.xml @@ -5,6 +5,7 @@ android:versionName="1.0" > + + + + + + \ No newline at end of file diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index 74c6c6a42..e5659a4df 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -56,6 +56,7 @@ strongswan_CFLAGS += \ include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ vstr \ openssl \ + libandroidbridge \ strongswan/src/libcharon \ strongswan/src/libhydra \ strongswan/src/libstrongswan \ diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk new file mode 100644 index 000000000..7f25a540a --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -0,0 +1,33 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# copy-n-paste from Makefile.am +LOCAL_SRC_FILES := \ +charonservice.c + +# build libandroidbridge ------------------------------------------------------- + +LOCAL_C_INCLUDES += \ + $(libvstr_PATH) \ + $(strongswan_PATH)/src/libhydra \ + $(strongswan_PATH)/src/libcharon \ + $(strongswan_PATH)/src/libstrongswan + +LOCAL_CFLAGS := $(strongswan_CFLAGS) \ + -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"' + +LOCAL_MODULE := libandroidbridge + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_PRELINK_MODULE := false + +LOCAL_LDLIBS := -llog + +LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libcharon + +include $(BUILD_SHARED_LIBRARY) + + diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c new file mode 100644 index 000000000..ecc243481 --- /dev/null +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 . + * + * 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 + +#define JNI_PACKAGE org_strongswan_android + +#define JNI_METHOD_PP(pack, klass, name, ret, ...) \ + ret Java_##pack##_##klass##_##name(JNIEnv *env, jobject this, ##__VA_ARGS__) + +#define JNI_METHOD_P(pack, klass, name, ret, ...) \ + JNI_METHOD_PP(pack, klass, name, ret, ##__VA_ARGS__) + +#define JNI_METHOD(klass, name, ret, ...) \ + JNI_METHOD_P(JNI_PACKAGE, klass, name, ret, ##__VA_ARGS__) + +/** + * hook in library for debugging messages + */ +extern void (*dbg) (debug_t group, level_t level, char *fmt, ...); + +/** + * Logging hook for library logs, using android specific logging + */ +static void dbg_android(debug_t group, level_t level, char *fmt, ...) +{ + va_list args; + + if (level <= 4) + { + char sgroup[16], buffer[8192]; + char *current = buffer, *next; + snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group); + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + while (current) + { /* log each line separately */ + next = strchr(current, '\n'); + if (next) + { + *(next++) = '\0'; + } + __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n", + sgroup, current); + current = next; + } + } +} + +/** + * Initialize charon and the libraries via JNI + */ +JNI_METHOD(CharonVpnService, initializeCharon, void) +{ + /* logging for library during initialization, as we have no bus yet */ + dbg = dbg_android; + + /* initialize library */ + if (!library_init(NULL)) + { + library_deinit(); + return; + } + + if (!libhydra_init("charon")) + { + libhydra_deinit(); + library_deinit(); + return; + } + + if (!libcharon_init("charon") || + !charon->initialize(charon, PLUGINS)) + { + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); + return; + } + + /* start daemon (i.e. the threads in the thread-pool) */ + charon->start(charon); +} + +/** + * Initialize charon and the libraries via JNI + */ +JNI_METHOD(CharonVpnService, deinitializeCharon, void) +{ + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); +} + diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java new file mode 100644 index 000000000..596372f9d --- /dev/null +++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java @@ -0,0 +1,50 @@ +package org.strongswan.android; + +import android.content.Intent; +import android.net.VpnService; + +public class CharonVpnService extends VpnService { + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // called whenever the service is started with startService + // create our own thread because we are running in the calling processes main thread + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onCreate() { + // onCreate is only called once + initializeCharon(); + super.onCreate(); + } + + @Override + public void onDestroy() { + // called once the service is to be destroyed + deinitializeCharon(); + super.onDestroy(); + } + + /** + * Initialization of charon, provided by libandroidbridge.so + */ + public native void initializeCharon(); + + /** + * Deinitialize charon, provided by libandroidbridge.so + */ + public native void deinitializeCharon(); + + /* + * The libraries are extracted to /data/data/org.strongswan.android/... + * during installation. + */ + static { + System.loadLibrary("crypto"); + System.loadLibrary("strongswan"); + System.loadLibrary("hydra"); + System.loadLibrary("charon"); + System.loadLibrary("androidbridge"); + } +} diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java index 16d4a0973..b4fb6f398 100644 --- a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java +++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java @@ -1,13 +1,32 @@ package org.strongswan.android; import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; import android.os.Bundle; public class strongSwanActivity extends Activity { - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + startVpnService(); + } + + private void startVpnService() { + Intent intent = VpnService.prepare(this); + if (intent != null) { + startActivityForResult(intent, 0); + } else { + onActivityResult(0, RESULT_OK, null); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + Intent intent = new Intent(this, CharonVpnService.class); + startService(intent); + } + } } \ No newline at end of file From 9ddc7cbfff8730398b1df22beb2ffabe366d19ae Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 22 Feb 2012 11:40:43 +0100 Subject: [PATCH 12/32] Changed minimal SDK/API level to 14. --- src/frontends/android/.classpath | 4 ++-- src/frontends/android/AndroidManifest.xml | 2 +- src/frontends/android/project.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/frontends/android/.classpath b/src/frontends/android/.classpath index a4763d1ee..3f9691c5d 100644 --- a/src/frontends/android/.classpath +++ b/src/frontends/android/.classpath @@ -1,8 +1,8 @@ - - + + diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml index 63464e712..5b1d03d7c 100644 --- a/src/frontends/android/AndroidManifest.xml +++ b/src/frontends/android/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + Date: Wed, 22 Feb 2012 12:05:38 +0100 Subject: [PATCH 13/32] Some NDK build info updated. --- src/frontends/android/README.ndk | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/frontends/android/README.ndk b/src/frontends/android/README.ndk index dc0df1ffd..e1dbac39c 100644 --- a/src/frontends/android/README.ndk +++ b/src/frontends/android/README.ndk @@ -3,7 +3,9 @@ folder: - strongswan: The strongSwan sources. This can either be an extracted tarball, or a symlink to the Git repository. To build from the repository the sources - have to be prepared first: ./autogen && ./configure && make && make distclean + have to be prepared first (see HACKING for a list of required tools): + + ./autogen.sh && ./configure && make && make distclean - openssl: The OpenSSL sources. Since the sources need to be changed to be built on Android (and especially in the NDK), we provide a modified mirror @@ -11,9 +13,10 @@ folder: - vstr: The Vstr string library. Since cross-compiling this library is not that easy with the configure script and Makefiles included in the tarball, - the easiest way to build it is still to use droid-gcc (as described on - wiki.strongswan.org). The build script provided on the wiki builds the - library and copies the required header files to the configured installation + the easiest way to build it is using either droid-gcc (as described on + wiki.strongswan.org) or a standalone toolchain built with the NDK. + The build script provided on the wiki builds the library with droid-gcc + and copies the required header files to the configured installation directory. Please note that the Android.mk provided on the wiki (vstr.mk) does not work in the NDK. A replacement is already in place in jni/vstr. From b70139fbfd942547a7b591db3e3f2c7f9e6666f2 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 22 Feb 2012 15:32:37 +0100 Subject: [PATCH 14/32] Stub library for user space IPsec implementation added. --- Doxyfile.in | 1 + configure.in | 3 ++ src/Makefile.am | 4 +++ src/checksum/Makefile.am | 5 +++ src/libipsec/Android.mk | 29 +++++++++++++++++ src/libipsec/Makefile.am | 20 ++++++++++++ src/libipsec/ipsec.c | 69 ++++++++++++++++++++++++++++++++++++++++ src/libipsec/ipsec.h | 56 ++++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+) create mode 100644 src/libipsec/Android.mk create mode 100644 src/libipsec/Makefile.am create mode 100644 src/libipsec/ipsec.c create mode 100644 src/libipsec/ipsec.h diff --git a/Doxyfile.in b/Doxyfile.in index 7fb516190..343f130b3 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -530,6 +530,7 @@ WARN_LOGFILE = INPUT = @SRC_DIR@/src/libstrongswan \ @SRC_DIR@/src/libhydra \ @SRC_DIR@/src/libcharon \ + @SRC_DIR@/src/libipsec \ @SRC_DIR@/src/libsimaka \ @SRC_DIR@/src/libtls \ @SRC_DIR@/src/libradius \ diff --git a/configure.in b/configure.in index 96b1fe373..5ee3b8723 100644 --- a/configure.in +++ b/configure.in @@ -174,6 +174,7 @@ ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.]) ARG_ENABL_SET([kernel-pfkey], [enable the PF_KEY kernel interface.]) ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.]) ARG_ENABL_SET([kernel-klips], [enable the KLIPS kernel interface.]) +ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.]) ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.]) ARG_ENABL_SET([socket-raw], [enable raw socket implementation of charon]) ARG_ENABL_SET([socket-dynamic], [enable dynamic socket implementation for charon]) @@ -1104,6 +1105,7 @@ AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue) AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue) AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue) AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue) +AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue) AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue) AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue) AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue) @@ -1195,6 +1197,7 @@ AC_OUTPUT( src/libhydra/plugins/kernel_pfkey/Makefile src/libhydra/plugins/kernel_pfroute/Makefile src/libhydra/plugins/resolve/Makefile + src/libipsec/Makefile src/libsimaka/Makefile src/libtls/Makefile src/libradius/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 452036b8b..e4c0374a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,10 @@ if USE_LIBHYDRA SUBDIRS += libhydra endif +if USE_LIBIPSEC + SUBDIRS += libipsec +endif + if USE_SIMAKA SUBDIRS += libsimaka endif diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am index 0d0da5acf..1405fcd05 100644 --- a/src/checksum/Makefile.am +++ b/src/checksum/Makefile.am @@ -40,6 +40,11 @@ if !MONOLITHIC endif endif +if USE_LIBIPSEC + deps += $(top_builddir)/src/libipsec/libipsec.la + libs += $(DESTDIR)$(ipseclibdir)/libipsec.so +endif + if USE_TLS deps += $(top_builddir)/src/libtls/libtls.la libs += $(DESTDIR)$(ipseclibdir)/libtls.so diff --git a/src/libipsec/Android.mk b/src/libipsec/Android.mk new file mode 100644 index 000000000..99ff69106 --- /dev/null +++ b/src/libipsec/Android.mk @@ -0,0 +1,29 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# copy-n-paste from Makefile.am +LOCAL_SRC_FILES := \ +ipsec.c ipsec.h + +# build libipsec --------------------------------------------------------------- + +LOCAL_C_INCLUDES += \ + $(libvstr_PATH) \ + $(strongswan_PATH)/src/include \ + $(strongswan_PATH)/src/libhydra \ + $(strongswan_PATH)/src/libstrongswan + +LOCAL_CFLAGS := $(strongswan_CFLAGS) + +LOCAL_MODULE := libipsec + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_PRELINK_MODULE := false + +LOCAL_SHARED_LIBRARIES += libstrongswan libhydra + +include $(BUILD_SHARED_LIBRARY) + diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am new file mode 100644 index 000000000..0b8faf724 --- /dev/null +++ b/src/libipsec/Makefile.am @@ -0,0 +1,20 @@ +ipseclib_LTLIBRARIES = libipsec.la + +libipsec_la_SOURCES = \ +ipsec.c ipsec.h + +libipsec_la_LIBADD = + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +EXTRA_DIST = Android.mk + +# build optional plugins +######################## + +if MONOLITHIC +SUBDIRS = +else +SUBDIRS = . +endif + diff --git a/src/libipsec/ipsec.c b/src/libipsec/ipsec.c new file mode 100644 index 000000000..add3b463a --- /dev/null +++ b/src/libipsec/ipsec.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 . + * + * 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 "ipsec.h" + +#include + +typedef struct private_ipsec_t private_ipsec_t; + +/** + * Private additions to ipsec_t. + */ +struct private_ipsec_t { + + /** + * Public members of ipsec_t. + */ + ipsec_t public; +}; + +/** + * Single instance of ipsec_t. + */ +ipsec_t *ipsec; + +/** + * Described in header. + */ +void libipsec_deinit() +{ + private_ipsec_t *this = (private_ipsec_t*)ipsec; + free(this); + ipsec = NULL; +} + +/** + * Described in header. + */ +bool libipsec_init() +{ + private_ipsec_t *this; + + INIT(this, + .public = { + }, + ); + ipsec = &this->public; + + if (lib->integrity && + !lib->integrity->check(lib->integrity, "libipsec", libipsec_init)) + { + DBG1(DBG_LIB, "integrity check of libipsec failed"); + return FALSE; + } + return TRUE; +} + diff --git a/src/libipsec/ipsec.h b/src/libipsec/ipsec.h new file mode 100644 index 000000000..80bef5426 --- /dev/null +++ b/src/libipsec/ipsec.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 . + * + * 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 libipsec libipsec + * + * @addtogroup libipsec + * @{ + */ + +#ifndef IPSEC_H_ +#define IPSEC_H_ + +typedef struct ipsec_t ipsec_t; + +#include + +/** + * User space IPsec implementation. + */ +struct ipsec_t { + +}; + +/** + * The single instance of ipsec_t. + * + * Set between calls to libipsec_init() and libipsec_deinit() calls. + */ +extern ipsec_t *ipsec; + +/** + * Initialize libipsec. + * + * @return FALSE if integrity check failed + */ +bool libipsec_init(); + +/** + * Deinitialize libipsec. + */ +void libipsec_deinit(); + +#endif /** IPSEC_H_ @}*/ From 06ed785e5ab9dfc0dedf04855c1ea5019c256d8e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 22 Feb 2012 15:36:33 +0100 Subject: [PATCH 15/32] Load libipsec in Android app. --- src/frontends/android/jni/Android.mk | 1 + src/frontends/android/jni/libandroidbridge/Android.mk | 3 ++- .../android/jni/libandroidbridge/charonservice.c | 11 +++++++++++ .../src/org/strongswan/android/CharonVpnService.java | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index e5659a4df..ad5ddd6d3 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -57,6 +57,7 @@ include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ vstr \ openssl \ libandroidbridge \ + strongswan/src/libipsec \ strongswan/src/libcharon \ strongswan/src/libhydra \ strongswan/src/libstrongswan \ diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk index 7f25a540a..3b8b98b86 100644 --- a/src/frontends/android/jni/libandroidbridge/Android.mk +++ b/src/frontends/android/jni/libandroidbridge/Android.mk @@ -9,6 +9,7 @@ charonservice.c LOCAL_C_INCLUDES += \ $(libvstr_PATH) \ + $(strongswan_PATH)/src/libipsec \ $(strongswan_PATH)/src/libhydra \ $(strongswan_PATH)/src/libcharon \ $(strongswan_PATH)/src/libstrongswan @@ -26,7 +27,7 @@ LOCAL_PRELINK_MODULE := false LOCAL_LDLIBS := -llog -LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libcharon +LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libipsec libcharon include $(BUILD_SHARED_LIBRARY) diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c index ecc243481..424d50d24 100644 --- a/src/frontends/android/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/jni/libandroidbridge/charonservice.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -88,10 +89,19 @@ JNI_METHOD(CharonVpnService, initializeCharon, void) return; } + if (!libipsec_init()) + { + libipsec_deinit(); + libhydra_deinit(); + library_deinit(); + return; + } + if (!libcharon_init("charon") || !charon->initialize(charon, PLUGINS)) { libcharon_deinit(); + libipsec_deinit(); libhydra_deinit(); library_deinit(); return; @@ -107,6 +117,7 @@ JNI_METHOD(CharonVpnService, initializeCharon, void) JNI_METHOD(CharonVpnService, deinitializeCharon, void) { libcharon_deinit(); + libipsec_deinit(); libhydra_deinit(); library_deinit(); } diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java index 596372f9d..52d427c2f 100644 --- a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java @@ -45,6 +45,7 @@ public class CharonVpnService extends VpnService { System.loadLibrary("strongswan"); System.loadLibrary("hydra"); System.loadLibrary("charon"); + System.loadLibrary("ipsec"); System.loadLibrary("androidbridge"); } } From a405760395b126c08cb77212acc3d823b9e27448 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 22 Feb 2012 15:36:51 +0100 Subject: [PATCH 16/32] Java code style fixed (analogous to C code). --- .../strongswan/android/CharonVpnService.java | 18 +++++++++----- .../android/strongSwanActivity.java | 24 ++++++++++++------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java index 52d427c2f..d917d3eae 100644 --- a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java +++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java @@ -3,24 +3,29 @@ package org.strongswan.android; import android.content.Intent; import android.net.VpnService; -public class CharonVpnService extends VpnService { +public class CharonVpnService extends VpnService +{ @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(Intent intent, int flags, int startId) + { // called whenever the service is started with startService - // create our own thread because we are running in the calling processes main thread + // create our own thread because we are running in the calling processes + // main thread return super.onStartCommand(intent, flags, startId); } @Override - public void onCreate() { + public void onCreate() + { // onCreate is only called once initializeCharon(); super.onCreate(); } @Override - public void onDestroy() { + public void onDestroy() + { // called once the service is to be destroyed deinitializeCharon(); super.onDestroy(); @@ -40,7 +45,8 @@ public class CharonVpnService extends VpnService { * The libraries are extracted to /data/data/org.strongswan.android/... * during installation. */ - static { + static + { System.loadLibrary("crypto"); System.loadLibrary("strongswan"); System.loadLibrary("hydra"); diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java index b4fb6f398..fabf71897 100644 --- a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java +++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java @@ -5,28 +5,36 @@ import android.content.Intent; import android.net.VpnService; import android.os.Bundle; -public class strongSwanActivity extends Activity { +public class strongSwanActivity extends Activity +{ @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) + { super.onCreate(savedInstanceState); setContentView(R.layout.main); startVpnService(); } - private void startVpnService() { + private void startVpnService() + { Intent intent = VpnService.prepare(this); - if (intent != null) { + if (intent != null) + { startActivityForResult(intent, 0); - } else { + } + else + { onActivityResult(0, RESULT_OK, null); } } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + if (resultCode == RESULT_OK) + { Intent intent = new Intent(this, CharonVpnService.class); startService(intent); } } -} \ No newline at end of file +} From 65da43e2fceb74f297a280c034000a7c01538703 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Feb 2012 11:35:16 +0100 Subject: [PATCH 17/32] Handle Non-ESP marker in receiver and not individual socket plugins. --- src/libcharon/network/receiver.c | 25 ++++++++++++++++++- .../socket_default/socket_default_socket.c | 17 +++---------- .../socket_dynamic/socket_dynamic_socket.c | 8 +----- .../plugins/socket_raw/socket_raw_socket.c | 24 ++++-------------- 4 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index dff76e245..6a39489b6 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2012 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -400,6 +400,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) ike_sa_id_t *id; packet_t *packet; message_t *message; + host_t *src, *dst; status_t status; bool supported = TRUE; @@ -415,6 +416,28 @@ static job_requeue_t receive_packets(private_receiver_t *this) return JOB_REQUEUE_FAIR; } + /* if neither source nor destination port is 500 we assume an IKE packet + * with Non-ESP marker or an ESP packet */ + dst = packet->get_destination(packet); + src = packet->get_source(packet); + if (dst->get_port(dst) != IKEV2_UDP_PORT && + src->get_port(src) != IKEV2_UDP_PORT) + { + chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; + + data = packet->get_data(packet); + if (memeq(data.ptr, marker.ptr, marker.len)) + { /* remove Non-ESP marker */ + data = chunk_skip(data, marker.len); + packet->set_data(packet, chunk_clone(data)); + } + else + { /* this seems to be an ESP packet */ + packet->destroy(packet); + return JOB_REQUEUE_DIRECT; + } + } + /* parse message header */ message = message_create_from_packet(packet); if (message->parse_header(message) != SUCCESS) diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 0df040e85..a0b8e0b98 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2010 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -133,7 +133,7 @@ METHOD(socket_t, receiver, status_t, chunk_t data; packet_t *pkt; host_t *source = NULL, *dest = NULL; - int bytes_read = 0, data_offset; + int bytes_read = 0; bool oldstate; fd_set rfds; @@ -297,17 +297,8 @@ METHOD(socket_t, receiver, status_t, pkt->set_source(pkt, source); pkt->set_destination(pkt, dest); DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); - data_offset = 0; - /* remove non esp marker */ - if (dest->get_port(dest) == CHARON_NATT_PORT) - { - data_offset += MARKER_LEN; - } - /* fill in packet */ - data.len = bytes_read - data_offset; - data.ptr = malloc(data.len); - memcpy(data.ptr, buffer + data_offset, data.len); - pkt->set_data(pkt, data); + data = chunk_create(buffer, bytes_read); + pkt->set_data(pkt, chunk_clone(data)); } else { diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index d4a9552f6..39ba4736c 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2010 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -297,12 +297,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this, packet = packet_create(); packet->set_source(packet, source); packet->set_destination(packet, dest); - /* we assume a non-ESP marker if none of the ports is on 500 */ - if (dest->get_port(dest) != IKEV2_UDP_PORT && - source->get_port(source) != IKEV2_UDP_PORT) - { - data = chunk_skip(data, MARKER_LEN); - } packet->set_data(packet, chunk_clone(data)); return packet; } diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 539411379..f363671c1 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2010 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter @@ -203,16 +203,9 @@ METHOD(socket_t, receiver, status_t, pkt->set_destination(pkt, dest); DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); data_offset = IP_LEN + UDP_LEN; - /* remove non esp marker */ - if (dest->get_port(dest) == CHARON_NATT_PORT) - { - data_offset += MARKER_LEN; - } - /* fill in packet */ data.len = bytes_read - data_offset; - data.ptr = malloc(data.len); - memcpy(data.ptr, buffer + data_offset, data.len); - pkt->set_data(pkt, data); + data.ptr = buffer + data_offset; + pkt->set_data(pkt, chunk_clone(data)); } else if (this->recv6 && FD_ISSET(this->recv6, &rfds)) { @@ -290,16 +283,9 @@ METHOD(socket_t, receiver, status_t, pkt->set_destination(pkt, dest); DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest); data_offset = UDP_LEN; - /* remove non esp marker */ - if (dest->get_port(dest) == CHARON_NATT_PORT) - { - data_offset += MARKER_LEN; - } - /* fill in packet */ data.len = bytes_read - data_offset; - data.ptr = malloc(data.len); - memcpy(data.ptr, buffer + data_offset, data.len); - pkt->set_data(pkt, data); + data.ptr = buffer + data_offset; + pkt->set_data(pkt, chunk_clone(data)); } else { From 064da8b96b24db331e37c93d8f857c8558d294bb Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Feb 2012 11:51:53 +0100 Subject: [PATCH 18/32] Add Non-ESP marker in sender and not individual socket plugins. --- src/libcharon/network/sender.c | 19 +++++++++++++++++++ src/libcharon/network/sender.h | 2 +- .../socket_default/socket_default_socket.c | 13 +------------ .../socket_dynamic/socket_dynamic_socket.c | 15 +-------------- .../plugins/socket_raw/socket_raw_socket.c | 13 +------------ 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c index 75635d2e3..b62185f8c 100644 --- a/src/libcharon/network/sender.c +++ b/src/libcharon/network/sender.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -121,6 +122,7 @@ METHOD(sender_t, send_, void, static job_requeue_t send_packets(private_sender_t * this) { packet_t *packet; + host_t *src, *dst; bool oldstate; this->mutex->lock(this->mutex); @@ -139,6 +141,23 @@ static job_requeue_t send_packets(private_sender_t * this) this->sent->signal(this->sent); this->mutex->unlock(this->mutex); + /* if neither source nor destination port is 500 we add a Non-ESP marker */ + dst = packet->get_destination(packet); + src = packet->get_source(packet); + if (dst->get_port(dst) != IKEV2_UDP_PORT && + src->get_port(src) != IKEV2_UDP_PORT) + { + chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; + + data = packet->get_data(packet); + /* NAT keepalives have no marker prepended */ + if (data.len != 1 || data.ptr[0] != 0xFF) + { + data = chunk_cat("cm", marker, data); + packet->set_data(packet, data); + } + } + charon->socket->send(charon->socket, packet); packet->destroy(packet); return JOB_REQUEUE_DIRECT; diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h index 6ee070435..d8ff8c892 100644 --- a/src/libcharon/network/sender.h +++ b/src/libcharon/network/sender.h @@ -28,7 +28,7 @@ typedef struct sender_t sender_t; #include /** - * Thread responsible for sending packets over the socket. + * Callback job responsible for sending IKE packets over the socket. */ struct sender_t { diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index a0b8e0b98..eba7219b2 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -315,7 +315,7 @@ METHOD(socket_t, sender, status_t, { int sport, skt, family; ssize_t bytes_sent; - chunk_t data, marked; + chunk_t data; host_t *src, *dst; struct msghdr msg; struct cmsghdr *cmsg; @@ -351,17 +351,6 @@ METHOD(socket_t, sender, status_t, { skt = this->ipv6_natt; } - /* NAT keepalives without marker */ - if (data.len != 1 || data.ptr[0] != 0xFF) - { - /* add non esp marker to packet */ - marked = chunk_alloc(data.len + MARKER_LEN); - memset(marked.ptr, 0, MARKER_LEN); - memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len); - /* let the packet do the clean up for us */ - packet->set_data(packet, marked); - data = marked; - } } else { diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index 39ba4736c..ec61e61c9 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -477,7 +477,7 @@ METHOD(socket_t, sender, status_t, host_t *src, *dst; int port, family; ssize_t len; - chunk_t data, marked; + chunk_t data; struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov; @@ -495,19 +495,6 @@ METHOD(socket_t, sender, status_t, data = packet->get_data(packet); DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst); - /* use non-ESP marker if none of the ports is 500, not for keep alives */ - if (port != IKEV2_UDP_PORT && dst->get_port(dst) != IKEV2_UDP_PORT && - !(data.len == 1 && data.ptr[0] == 0xFF)) - { - /* add non esp marker to packet */ - marked = chunk_alloc(data.len + MARKER_LEN); - memset(marked.ptr, 0, MARKER_LEN); - memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len); - /* let the packet do the clean up for us */ - packet->set_data(packet, marked); - data = marked; - } - memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = dst->get_sockaddr(dst);; msg.msg_namelen = *dst->get_sockaddr_len(dst); diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index f363671c1..600f5453d 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -303,7 +303,7 @@ METHOD(socket_t, sender, status_t, { int sport, skt, family; ssize_t bytes_sent; - chunk_t data, marked; + chunk_t data; host_t *src, *dst; struct msghdr msg; struct cmsghdr *cmsg; @@ -339,17 +339,6 @@ METHOD(socket_t, sender, status_t, { skt = this->send6_natt; } - /* NAT keepalives without marker */ - if (data.len != 1 || data.ptr[0] != 0xFF) - { - /* add non esp marker to packet */ - marked = chunk_alloc(data.len + MARKER_LEN); - memset(marked.ptr, 0, MARKER_LEN); - memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len); - /* let the packet do the clean up for us */ - packet->set_data(packet, marked); - data = marked; - } } else { From 08b2ce7aa7070674d756fefd365a96b600f3ebcb Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Feb 2012 15:36:02 +0100 Subject: [PATCH 19/32] Callback for ESP packets added to receiver. --- src/libcharon/network/receiver.c | 50 +++++++++++++++++++++++++++++++- src/libcharon/network/receiver.h | 42 +++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index 6a39489b6..81dfb7018 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -27,6 +27,7 @@ #include #include #include +#include /** lifetime of a cookie, in seconds */ #define COOKIE_LIFETIME 10 @@ -54,6 +55,19 @@ struct private_receiver_t { */ receiver_t public; + /** + * Registered callback for ESP packets + */ + struct { + receiver_esp_cb_t cb; + void *data; + } esp_cb; + + /** + * Mutex for ESP callback + */ + mutex_t *esp_cb_mutex; + /** * current secret to use for cookie calculation */ @@ -433,7 +447,16 @@ static job_requeue_t receive_packets(private_receiver_t *this) } else { /* this seems to be an ESP packet */ - packet->destroy(packet); + this->esp_cb_mutex->lock(this->esp_cb_mutex); + if (this->esp_cb.cb) + { + this->esp_cb.cb(this->esp_cb.data, packet); + } + else + { + packet->destroy(packet); + } + this->esp_cb_mutex->unlock(this->esp_cb_mutex); return JOB_REQUEUE_DIRECT; } } @@ -536,11 +559,33 @@ static job_requeue_t receive_packets(private_receiver_t *this) return JOB_REQUEUE_DIRECT; } +METHOD(receiver_t, add_esp_cb, void, + private_receiver_t *this, receiver_esp_cb_t callback, void *data) +{ + this->esp_cb_mutex->lock(this->esp_cb_mutex); + this->esp_cb.cb = callback; + this->esp_cb.data = data; + this->esp_cb_mutex->unlock(this->esp_cb_mutex); +} + +METHOD(receiver_t, del_esp_cb, void, + private_receiver_t *this, receiver_esp_cb_t callback) +{ + this->esp_cb_mutex->lock(this->esp_cb_mutex); + if (this->esp_cb.cb == callback) + { + this->esp_cb.cb = NULL; + this->esp_cb.data = NULL; + } + this->esp_cb_mutex->unlock(this->esp_cb_mutex); +} + METHOD(receiver_t, destroy, void, private_receiver_t *this) { this->rng->destroy(this->rng); this->hasher->destroy(this->hasher); + this->esp_cb_mutex->destroy(this->esp_cb_mutex); free(this); } @@ -554,8 +599,11 @@ receiver_t *receiver_create() INIT(this, .public = { + .add_esp_cb = _add_esp_cb, + .del_esp_cb = _del_esp_cb, .destroy = _destroy, }, + .esp_cb_mutex = mutex_create(MUTEX_TYPE_DEFAULT), .secret_switch = now, .secret_offset = random() % now, ); diff --git a/src/libcharon/network/receiver.h b/src/libcharon/network/receiver.h index 1d9d4871e..93b3d3c0c 100644 --- a/src/libcharon/network/receiver.h +++ b/src/libcharon/network/receiver.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -25,15 +26,28 @@ typedef struct receiver_t receiver_t; #include +#include #include +/** + * Callback called for any received UDP encapsulated ESP packet. + * + * Implementation should be quick as the receiver doesn't receive any packets + * while calling this function. + * + * @param data data supplied during registration of the callback + * @param packet decapsulated ESP packet + */ +typedef void (*receiver_esp_cb_t)(void *data, packet_t *packet); + /** * Receives packets from the socket and adds them to the job queue. * - * The receiver starts a thread, which reads on the blocking socket. A received - * packet is preparsed and a process_message_job is queued in the job queue. + * The receiver uses a callback job, which reads on the blocking socket. + * A received packet is preparsed and a process_message_job is queued in the + * job queue. * - * To endure DoS attacks, cookies are enabled when to many IKE_SAs are half + * To endure DoS attacks, cookies are enabled when too many IKE_SAs are half * open. The calculation of cookies is slightly different from the proposed * method in RFC4306. We do not include a nonce, because we think the advantage * we gain does not justify the overhead to parse the whole message. @@ -47,14 +61,32 @@ typedef struct receiver_t receiver_t; * secret is stored to allow a clean migration between secret changes. * * Further, the number of half-initiated IKE_SAs is limited per peer. This - * mades it impossible for a peer to flood the server with its real IP address. + * makes it impossible for a peer to flood the server with its real IP address. */ struct receiver_t { + /** + * Register a callback which is called for any incoming ESP packets. + * + * @note Only the last callback registered will receive any packets. + * + * @param callback callback to register + * @param data data provided to callback + */ + void (*add_esp_cb)(receiver_t *this, receiver_esp_cb_t callback, + void *data); + + /** + * Unregister a previously registered callback for ESP packets. + * + * @param callback previously registered callback + */ + void (*del_esp_cb)(receiver_t *this, receiver_esp_cb_t callback); + /** * Destroys a receiver_t object. */ - void (*destroy) (receiver_t *receiver); + void (*destroy)(receiver_t *this); }; /** From e49abcede093ded4d11de88a6d0c25f003c9771e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 11:07:34 +0100 Subject: [PATCH 20/32] Let kernel interfaces decide how to enable UDP decapsulation of ESP packets. --- .../plugins/load_tester/load_tester_ipsec.c | 9 +--- .../socket_default/socket_default_socket.c | 42 +++---------------- .../socket_dynamic/socket_dynamic_socket.c | 20 +++------ .../plugins/socket_raw/socket_raw_socket.c | 28 ++++--------- src/libhydra/kernel/kernel_interface.c | 13 +++++- src/libhydra/kernel/kernel_interface.h | 16 ++++++- src/libhydra/kernel/kernel_ipsec.h | 13 +++++- .../plugins/kernel_klips/kernel_klips_ipsec.c | 12 ++---- .../kernel_netlink/kernel_netlink_ipsec.c | 28 +++++++++++++ .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 42 +++++++++++++++++++ 10 files changed, 133 insertions(+), 90 deletions(-) diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index 440197260..ded6b2d20 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -108,12 +108,6 @@ METHOD(kernel_ipsec_t, del_policy, status_t, return SUCCESS; } -METHOD(kernel_ipsec_t, bypass_socket, bool, - private_load_tester_ipsec_t *this, int fd, int family) -{ - return TRUE; -} - METHOD(kernel_ipsec_t, destroy, void, private_load_tester_ipsec_t *this) { @@ -141,7 +135,8 @@ load_tester_ipsec_t *load_tester_ipsec_create() .query_policy = _query_policy, .del_policy = _del_policy, .flush_policies = (void*)return_failed, - .bypass_socket = _bypass_socket, + .bypass_socket = (void*)return_true, + .enable_udp_decap = (void*)return_true, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index eba7219b2..b035d575a 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -40,9 +40,6 @@ #include #include #include -#ifdef __APPLE__ -#include -#endif #include #include @@ -54,15 +51,6 @@ /* length of non-esp marker */ #define MARKER_LEN sizeof(u_int32_t) -/* from linux/udp.h */ -#ifndef UDP_ENCAP -#define UDP_ENCAP 100 -#endif /*UDP_ENCAP*/ - -#ifndef UDP_ENCAP_ESPINUDP -#define UDP_ENCAP_ESPINUDP 2 -#endif /*UDP_ENCAP_ESPINUDP*/ - /* these are not defined on some platforms */ #ifndef SOL_IP #define SOL_IP IPPROTO_IP @@ -70,9 +58,6 @@ #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 #endif -#ifndef SOL_UDP -#define SOL_UDP IPPROTO_UDP -#endif /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that * previously defined IPV6_PKTINFO */ @@ -513,17 +498,14 @@ static int open_socket(private_socket_default_socket_t *this, DBG1(DBG_NET, "installing IKE bypass policy failed"); } -#ifndef __APPLE__ + /* enable UDP decapsulation globally, only for one socket needed */ + if (family == AF_INET && port == CHARON_NATT_PORT && + !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, + skt, family, port)) { - /* enable UDP decapsulation globally, only for one socket needed */ - int type = UDP_ENCAP_ESPINUDP; - if (family == AF_INET && port == CHARON_NATT_PORT && - setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) - { - DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno)); - } + DBG1(DBG_NET, "enabling UDP decapsulation failed"); } -#endif + return skt; } @@ -568,18 +550,6 @@ socket_default_socket_t *socket_default_socket_create() "%s.max_packet", MAX_PACKET, charon->name), ); -#ifdef __APPLE__ - { - int natt_port = CHARON_NATT_PORT; - if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &natt_port, - sizeof(natt_port)) != 0) - { - DBG1(DBG_NET, "could not set net.inet.ipsec.esp_port to %d: %s", - natt_port, strerror(errno)); - } - } -#endif - this->ipv4 = open_socket(this, AF_INET, CHARON_UDP_PORT); if (this->ipv4 == 0) { diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index ec61e61c9..787f6f444 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -48,15 +48,6 @@ /* length of non-esp marker */ #define MARKER_LEN sizeof(u_int32_t) -/* from linux/udp.h */ -#ifndef UDP_ENCAP -#define UDP_ENCAP 100 -#endif /*UDP_ENCAP*/ - -#ifndef UDP_ENCAP_ESPINUDP -#define UDP_ENCAP_ESPINUDP 2 -#endif /*UDP_ENCAP_ESPINUDP*/ - /* these are not defined on some platforms */ #ifndef SOL_IP #define SOL_IP IPPROTO_IP @@ -64,9 +55,6 @@ #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 #endif -#ifndef SOL_UDP -#define SOL_UDP IPPROTO_UDP -#endif /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that * previously defined IPV6_PKTINFO */ @@ -352,7 +340,7 @@ METHOD(socket_t, receiver, status_t, static int open_socket(private_socket_dynamic_socket_t *this, int family, u_int16_t port) { - int on = TRUE, type = UDP_ENCAP_ESPINUDP; + int on = TRUE; struct sockaddr_storage addr; socklen_t addrlen; u_int sol, pktinfo = 0; @@ -424,10 +412,12 @@ static int open_socket(private_socket_dynamic_socket_t *this, } /* enable UDP decapsulation on each socket */ - if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, + fd, family, port)) { - DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno)); + DBG1(DBG_NET, "enabling UDP decapsulation failed"); } + return fd; } diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 600f5453d..8d0b4226c 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -55,15 +55,6 @@ #define IKE_VERSION_OFFSET 17 #define IKE_LENGTH_OFFSET 24 -/* from linux/udp.h */ -#ifndef UDP_ENCAP -#define UDP_ENCAP 100 -#endif /*UDP_ENCAP*/ - -#ifndef UDP_ENCAP_ESPINUDP -#define UDP_ENCAP_ESPINUDP 2 -#endif /*UDP_ENCAP_ESPINUDP*/ - /* needed for older kernel headers */ #ifndef IPV6_2292PKTINFO #define IPV6_2292PKTINFO 2 @@ -412,7 +403,6 @@ static int open_send_socket(private_socket_raw_socket_t *this, int family, u_int16_t port) { int on = TRUE; - int type = UDP_ENCAP_ESPINUDP; struct sockaddr_storage addr; int skt; @@ -463,22 +453,20 @@ static int open_send_socket(private_socket_raw_socket_t *this, return 0; } - if (family == AF_INET) - { - /* enable UDP decapsulation globally, only for one socket needed */ - if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) - { - DBG1(DBG_NET, "unable to set UDP_ENCAP: %s; NAT-T may fail", - strerror(errno)); - } - } - if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface, skt, family)) { DBG1(DBG_NET, "installing bypass policy on send socket failed"); } + /* enable UDP decapsulation globally, only for one socket needed */ + if (family == AF_INET && port == CHARON_NATT_PORT && + !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, + skt, family, port)) + { + DBG1(DBG_NET, "enabling UDP decapsulation failed"); + } + return skt; } diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c index b6bc5d92e..650cb1e9e 100644 --- a/src/libhydra/kernel/kernel_interface.c +++ b/src/libhydra/kernel/kernel_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 Tobias Brunner + * Copyright (C) 2008-2012 Tobias Brunner * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG @@ -294,6 +294,16 @@ METHOD(kernel_interface_t, bypass_socket, bool, return this->ipsec->bypass_socket(this->ipsec, fd, family); } +METHOD(kernel_interface_t, enable_udp_decap, bool, + private_kernel_interface_t *this, int fd, int family, u_int16_t port) +{ + if (!this->ipsec) + { + return FALSE; + } + return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port); +} + METHOD(kernel_interface_t, get_address_by_ts, status_t, private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip) { @@ -539,6 +549,7 @@ kernel_interface_t *kernel_interface_create() .add_route = _add_route, .del_route = _del_route, .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, .get_address_by_ts = _get_address_by_ts, .add_ipsec_interface = _add_ipsec_interface, diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h index 991cfafd0..37b72f8bb 100644 --- a/src/libhydra/kernel/kernel_interface.h +++ b/src/libhydra/kernel/kernel_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2011 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -361,10 +361,22 @@ struct kernel_interface_t { * * @param fd socket file descriptor to setup policy for * @param family protocol family of the socket - * @return TRUE of policy set up successfully + * @return TRUE if policy set up successfully */ bool (*bypass_socket)(kernel_interface_t *this, int fd, int family); + /** + * Enable decapsulation of ESP-in-UDP packets for the given port/socket. + * + * @param fd socket file descriptor + * @param family protocol family of the socket + * @param port the UDP port + * @return TRUE if UDP decapsulation was enabled successfully + */ + bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family, + u_int16_t port); + + /** * manager methods */ diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h index 852f0560c..500a77cad 100644 --- a/src/libhydra/kernel/kernel_ipsec.h +++ b/src/libhydra/kernel/kernel_ipsec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2011 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -402,6 +402,17 @@ struct kernel_ipsec_t { */ bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family); + /** + * Enable decapsulation of ESP-in-UDP packets for the given port/socket. + * + * @param fd socket file descriptor + * @param family protocol family of the socket + * @param port the UDP port + * @return TRUE if UDP decapsulation was enabled successfully + */ + bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family, + u_int16_t port); + /** * Destroy the implementation. */ diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c index 7e58cf30b..5f077b234 100644 --- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c +++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c @@ -2537,13 +2537,6 @@ static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8 return SUCCESS; } -METHOD(kernel_ipsec_t, bypass_socket, bool, - private_kernel_klips_ipsec_t *this, int fd, int family) -{ - /* KLIPS does not need a bypass policy for IKE */ - return TRUE; -} - METHOD(kernel_ipsec_t, destroy, void, private_kernel_klips_ipsec_t *this) { @@ -2585,7 +2578,10 @@ kernel_klips_ipsec_t *kernel_klips_ipsec_create() .query_policy = _query_policy, .del_policy = _del_policy, .flush_policies = (void*)return_failed, - .bypass_socket = _bypass_socket, + /* KLIPS does not need a bypass policy for IKE */ + .bypass_socket = (void*)return_true, + /* KLIPS does not need enabling UDP decap explicitly */ + .enable_udp_decap = (void*)return_true, .destroy = _destroy, }, }, diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index b46450c38..73d290051 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -58,6 +58,20 @@ #define IPV6_XFRM_POLICY 34 #endif /*IPV6_XFRM_POLICY*/ +/* from linux/udp.h */ +#ifndef UDP_ENCAP +#define UDP_ENCAP 100 +#endif + +#ifndef UDP_ENCAP_ESPINUDP +#define UDP_ENCAP_ESPINUDP 2 +#endif + +/* this is not defined on some platforms */ +#ifndef SOL_UDP +#define SOL_UDP IPPROTO_UDP +#endif + /** Default priority of installed policies */ #define PRIO_BASE 512 @@ -2607,6 +2621,19 @@ METHOD(kernel_ipsec_t, bypass_socket, bool, return TRUE; } +METHOD(kernel_ipsec_t, enable_udp_decap, bool, + private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port) +{ + int type = UDP_ENCAP_ESPINUDP; + + if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + { + DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno)); + return FALSE; + } + return TRUE; +} + METHOD(kernel_ipsec_t, destroy, void, private_kernel_netlink_ipsec_t *this) { @@ -2654,6 +2681,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() .del_policy = _del_policy, .flush_policies = _flush_policies, .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, .destroy = _destroy, }, }, diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index dfe10f93f..13422670a 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -51,6 +51,9 @@ #include #include #include +#ifdef __APPLE__ +#include +#endif #include "kernel_pfkey_ipsec.h" @@ -99,6 +102,20 @@ #define IPV6_IPSEC_POLICY 34 #endif +/* from linux/udp.h */ +#ifndef UDP_ENCAP +#define UDP_ENCAP 100 +#endif + +#ifndef UDP_ENCAP_ESPINUDP +#define UDP_ENCAP_ESPINUDP 2 +#endif + +/* this is not defined on some platforms */ +#ifndef SOL_UDP +#define SOL_UDP IPPROTO_UDP +#endif + /** default priority of installed policies */ #define PRIO_BASE 512 @@ -2488,6 +2505,30 @@ METHOD(kernel_ipsec_t, bypass_socket, bool, return TRUE; } +METHOD(kernel_ipsec_t, enable_udp_decap, bool, + private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port) +{ +#ifndef __APPLE__ + int type = UDP_ENCAP_ESPINUDP; + + if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) + { + DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno)); + return FALSE; + } +#else /* __APPLE__ */ + if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &port, + sizeof(port)) != 0) + { + DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s", + port, strerror(errno)); + return FALSE; + } +#endif /* __APPLE__ */ + + return TRUE; +} + METHOD(kernel_ipsec_t, destroy, void, private_kernel_pfkey_ipsec_t *this) { @@ -2532,6 +2573,7 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create() .del_policy = _del_policy, .flush_policies = _flush_policies, .bypass_socket = _bypass_socket, + .enable_udp_decap = _enable_udp_decap, .destroy = _destroy, }, }, From 896941d3654df69894c16c498d564eee2f615758 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 11:19:53 +0100 Subject: [PATCH 21/32] Improved how NAT-T keepalives are handled in sockets/receiver. --- src/libcharon/network/receiver.c | 17 ++++++++++++++--- .../socket_default/socket_default_socket.c | 10 ---------- .../socket_dynamic/socket_dynamic_socket.c | 9 --------- .../plugins/socket_raw/socket_raw_socket.c | 4 ++-- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index 81dfb7018..8240c2a9b 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -417,6 +417,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) host_t *src, *dst; status_t status; bool supported = TRUE; + chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00); /* read in a packet */ status = charon->socket->receive(charon->socket, &packet); @@ -430,6 +431,19 @@ static job_requeue_t receive_packets(private_receiver_t *this) return JOB_REQUEUE_FAIR; } + data = packet->get_data(packet); + if (data.len == 1 && data.ptr[0] == 0xFF) + { /* silently drop NAT-T keepalives */ + packet->destroy(packet); + return JOB_REQUEUE_DIRECT; + } + else if (data.len < marker.len) + { /* drop packets that are too small */ + DBG3(DBG_NET, "received packet is too short (%d bytes)", data.len); + packet->destroy(packet); + return JOB_REQUEUE_DIRECT; + } + /* if neither source nor destination port is 500 we assume an IKE packet * with Non-ESP marker or an ESP packet */ dst = packet->get_destination(packet); @@ -437,9 +451,6 @@ static job_requeue_t receive_packets(private_receiver_t *this) if (dst->get_port(dst) != IKEV2_UDP_PORT && src->get_port(src) != IKEV2_UDP_PORT) { - chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; - - data = packet->get_data(packet); if (memeq(data.ptr, marker.ptr, marker.len)) { /* remove Non-ESP marker */ data = chunk_skip(data, marker.len); diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index b035d575a..8da574a34 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -48,9 +48,6 @@ /* Maximum size of a packet */ #define MAX_PACKET 10000 -/* length of non-esp marker */ -#define MARKER_LEN sizeof(u_int32_t) - /* these are not defined on some platforms */ #ifndef SOL_IP #define SOL_IP IPPROTO_IP @@ -207,13 +204,6 @@ METHOD(socket_t, receiver, status_t, } DBG3(DBG_NET, "received packet %b", buffer, bytes_read); - if (bytes_read < MARKER_LEN) - { - DBG3(DBG_NET, "received packet too short (%d bytes)", - bytes_read); - return FAILED; - } - /* read ancillary data to get destination address */ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index 787f6f444..3c3b17bf3 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -45,9 +45,6 @@ /* Maximum size of a packet */ #define MAX_PACKET 10000 -/* length of non-esp marker */ -#define MARKER_LEN sizeof(u_int32_t) - /* these are not defined on some platforms */ #ifndef SOL_IP #define SOL_IP IPPROTO_IP @@ -225,12 +222,6 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this, } DBG3(DBG_NET, "received packet %b", buffer, (u_int)len); - if (len < MARKER_LEN) - { - DBG3(DBG_NET, "received packet too short (%d bytes)", len); - return NULL; - } - /* read ancillary data to get destination address */ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 8d0b4226c..37d13f13f 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -172,7 +172,7 @@ METHOD(socket_t, receiver, status_t, DBG3(DBG_NET, "received IPv4 packet %b", buffer, bytes_read); /* read source/dest from raw IP/UDP header */ - if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN) + if (bytes_read < IP_LEN + UDP_LEN) { DBG1(DBG_NET, "received IPv4 packet too short (%d bytes)", bytes_read); @@ -226,7 +226,7 @@ METHOD(socket_t, receiver, status_t, } DBG3(DBG_NET, "received IPv6 packet %b", buffer, bytes_read); - if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN) + if (bytes_read < IP_LEN + UDP_LEN) { DBG3(DBG_NET, "received IPv6 packet too short (%d bytes)", bytes_read); From 73470cfe57e92416b9c8cdc08bdc898e3fb38f2c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 11:42:32 +0100 Subject: [PATCH 22/32] Added packet_t.skip_bytes method to skip bytes at the start of a packet. --- src/libcharon/network/packet.c | 19 ++++++++++++++++--- src/libcharon/network/packet.h | 10 ++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/libcharon/network/packet.c b/src/libcharon/network/packet.c index 19db362f7..c817e00fb 100644 --- a/src/libcharon/network/packet.c +++ b/src/libcharon/network/packet.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -42,6 +43,11 @@ struct private_packet_t { * message data */ chunk_t data; + + /** + * actual chunk returned from get_data, adjusted when skip_bytes is called + */ + chunk_t adjusted_data; }; METHOD(packet_t, set_source, void, @@ -73,14 +79,20 @@ METHOD(packet_t, get_destination, host_t*, METHOD(packet_t, get_data, chunk_t, private_packet_t *this) { - return this->data; + return this->adjusted_data; } METHOD(packet_t, set_data, void, private_packet_t *this, chunk_t data) { free(this->data.ptr); - this->data = data; + this->adjusted_data = this->data = data; +} + +METHOD(packet_t, skip_bytes, void, + private_packet_t *this, size_t bytes) +{ + this->adjusted_data = chunk_skip(this->adjusted_data, bytes); } METHOD(packet_t, destroy, void, @@ -108,7 +120,7 @@ METHOD(packet_t, clone_, packet_t*, } if (this->data.ptr != NULL) { - other->set_data(other, chunk_clone(this->data)); + other->set_data(other, chunk_clone(this->adjusted_data)); } return other; } @@ -128,6 +140,7 @@ packet_t *packet_create(void) .get_source = _get_source, .set_destination = _set_destination, .get_destination = _get_destination, + .skip_bytes = _skip_bytes, .clone = _clone_, .destroy = _destroy, }, diff --git a/src/libcharon/network/packet.h b/src/libcharon/network/packet.h index 18d82c6fc..c53364104 100644 --- a/src/libcharon/network/packet.h +++ b/src/libcharon/network/packet.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -92,6 +93,15 @@ struct packet_t { */ void (*set_data) (packet_t *packet, chunk_t data); + /** + * Increase the offset where the actual packet data starts. + * + * @note The offset is reset to 0 when set_data() is called. + * + * @param bytes the number of additional bytes to skip + */ + void (*skip_bytes) (packet_t *packet, size_t bytes); + /** * Clones a packet_t object. * From fe4a152b85a6476da5812068989d8dc40844d7b2 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 11:44:05 +0100 Subject: [PATCH 23/32] Avoid unnecessary copy of packet data when removing Non-ESP marker. --- src/libcharon/network/receiver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index 8240c2a9b..3a52f8dc3 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -453,8 +453,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) { if (memeq(data.ptr, marker.ptr, marker.len)) { /* remove Non-ESP marker */ - data = chunk_skip(data, marker.len); - packet->set_data(packet, chunk_clone(data)); + packet->skip_bytes(packet, marker.len); } else { /* this seems to be an ESP packet */ From fb6c52adcdbc34ca16cdd9ad8f8adc097951f5d9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 13:01:51 +0100 Subject: [PATCH 24/32] Function added to send packets without Non-ESP marker. --- src/libcharon/network/sender.c | 48 ++++++++++++++++++++-------------- src/libcharon/network/sender.h | 8 ++++++ 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c index b62185f8c..c12941e25 100644 --- a/src/libcharon/network/sender.c +++ b/src/libcharon/network/sender.c @@ -80,7 +80,7 @@ struct private_sender_t { bool send_delay_response; }; -METHOD(sender_t, send_, void, +METHOD(sender_t, send_no_marker, void, private_sender_t *this, packet_t *packet) { host_t *src, *dst; @@ -116,13 +116,37 @@ METHOD(sender_t, send_, void, this->mutex->unlock(this->mutex); } +METHOD(sender_t, send_, void, + private_sender_t *this, packet_t *packet) +{ + host_t *src, *dst; + + /* if neither source nor destination port is 500 we add a Non-ESP marker */ + src = packet->get_source(packet); + dst = packet->get_destination(packet); + if (dst->get_port(dst) != IKEV2_UDP_PORT && + src->get_port(src) != IKEV2_UDP_PORT) + { + chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; + + data = packet->get_data(packet); + /* NAT keepalives have no marker prepended */ + if (data.len != 1 || data.ptr[0] != 0xFF) + { + data = chunk_cat("cm", marker, data); + packet->set_data(packet, data); + } + } + + send_no_marker(this, packet); +} + /** * Job callback function to send packets */ -static job_requeue_t send_packets(private_sender_t * this) +static job_requeue_t send_packets(private_sender_t *this) { packet_t *packet; - host_t *src, *dst; bool oldstate; this->mutex->lock(this->mutex); @@ -141,23 +165,6 @@ static job_requeue_t send_packets(private_sender_t * this) this->sent->signal(this->sent); this->mutex->unlock(this->mutex); - /* if neither source nor destination port is 500 we add a Non-ESP marker */ - dst = packet->get_destination(packet); - src = packet->get_source(packet); - if (dst->get_port(dst) != IKEV2_UDP_PORT && - src->get_port(src) != IKEV2_UDP_PORT) - { - chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; - - data = packet->get_data(packet); - /* NAT keepalives have no marker prepended */ - if (data.len != 1 || data.ptr[0] != 0xFF) - { - data = chunk_cat("cm", marker, data); - packet->set_data(packet, data); - } - } - charon->socket->send(charon->socket, packet); packet->destroy(packet); return JOB_REQUEUE_DIRECT; @@ -195,6 +202,7 @@ sender_t * sender_create() INIT(this, .public = { .send = _send_, + .send_no_marker = _send_no_marker, .flush = _flush, .destroy = _destroy, }, diff --git a/src/libcharon/network/sender.h b/src/libcharon/network/sender.h index d8ff8c892..c4f18d73b 100644 --- a/src/libcharon/network/sender.h +++ b/src/libcharon/network/sender.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -43,6 +44,13 @@ struct sender_t { */ void (*send) (sender_t *this, packet_t *packet); + /** + * The same as send() but does not add Non-ESP markers automatically. + * + * @param packet packet to send + */ + void (*send_no_marker) (sender_t *this, packet_t *packet); + /** * Enforce a flush of the send queue. * From 30dc7dff4d1c978323807e8e4c4aa478786de4da Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 13:04:16 +0100 Subject: [PATCH 25/32] Avoid double-free when prepending Non-ESP marker. --- src/libcharon/network/sender.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c index c12941e25..b3e8d29f5 100644 --- a/src/libcharon/network/sender.c +++ b/src/libcharon/network/sender.c @@ -133,7 +133,7 @@ METHOD(sender_t, send_, void, /* NAT keepalives have no marker prepended */ if (data.len != 1 || data.ptr[0] != 0xFF) { - data = chunk_cat("cm", marker, data); + data = chunk_cat("cc", marker, data); packet->set_data(packet, data); } } From 75f83163323bebbed363fe1ad57f1e6a6318e1d3 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Feb 2012 13:09:09 +0100 Subject: [PATCH 26/32] Use send_no_marker to send NAT keepalives. --- src/libcharon/network/sender.c | 11 +++-------- src/libcharon/sa/ike_sa.c | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c index b3e8d29f5..a919a0263 100644 --- a/src/libcharon/network/sender.c +++ b/src/libcharon/network/sender.c @@ -127,15 +127,10 @@ METHOD(sender_t, send_, void, if (dst->get_port(dst) != IKEV2_UDP_PORT && src->get_port(src) != IKEV2_UDP_PORT) { - chunk_t marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00), data; + chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00); - data = packet->get_data(packet); - /* NAT keepalives have no marker prepended */ - if (data.len != 1 || data.ptr[0] != 0xFF) - { - data = chunk_cat("cc", marker, data); - packet->set_data(packet, data); - } + data = chunk_cat("cc", marker, packet->get_data(packet)); + packet->set_data(packet, data); } send_no_marker(this, packet); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 5182da5aa..755e5d74d 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -489,7 +489,7 @@ METHOD(ike_sa_t, send_keepalive, void, data.len = 1; packet->set_data(packet, data); DBG1(DBG_IKE, "sending keep alive"); - charon->sender->send(charon->sender, packet); + charon->sender->send_no_marker(charon->sender, packet); diff = 0; } job = send_keepalive_job_create(this->ike_sa_id); From 56d07af3bed3a104a6c57a779e84fb41c1b143e4 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 28 Mar 2012 15:41:31 +0200 Subject: [PATCH 27/32] Added ESP log group for libipsec log messages. --- man/ipsec.conf.5.in | 3 ++- man/strongswan.conf.5.in | 3 +++ src/charon/charon.c | 3 ++- src/libstrongswan/debug.c | 2 ++ src/libstrongswan/debug.h | 2 ++ src/stroke/stroke.c | 2 +- 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index 1f88761be..ca77ee7de 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -1051,7 +1051,8 @@ A comma separated list containing type/level-pairs may be specified, e.g: .B dmn 3, ike 1, net -1. Acceptable values for types are -.B dmn, mgr, ike, chd, job, cfg, knl, net, asn, enc, lib, tls, tnc, imc, imv, pts +.B dmn, mgr, ike, chd, job, cfg, knl, net, asn, enc, lib, esp, tls, +.B tnc, imc, imv, pts and the level is one of .B -1, 0, 1, 2, 3, 4 (for silent, audit, control, controlmore, raw, private). By default, the level diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index ee8f8a8dc..4dd818b8a 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -920,6 +920,9 @@ Packet encoding/decoding encryption/decryption operations .B tls libtls library messages .TP +.B esp +libipsec library messages +.TP .B lib libstrongwan library messages .TP diff --git a/src/charon/charon.c b/src/charon/charon.c index be4a9548e..bd36c72f4 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -387,7 +387,7 @@ static void usage(const char *msg) " [--version]\n" " [--use-syslog]\n" " [--debug- ]\n" - " : log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib)\n" + " : log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n" " : log verbosity (-1 = silent, 0 = audit, 1 = control,\n" " 2 = controlmore, 3 = raw, 4 = private)\n" "\n" @@ -466,6 +466,7 @@ int main(int argc, char *argv[]) { "debug-imv", required_argument, &group, DBG_IMV }, { "debug-pts", required_argument, &group, DBG_PTS }, { "debug-tls", required_argument, &group, DBG_TLS }, + { "debug-esp", required_argument, &group, DBG_ESP }, { "debug-lib", required_argument, &group, DBG_LIB }, { 0,0,0,0 } }; diff --git a/src/libstrongswan/debug.c b/src/libstrongswan/debug.c index 985ce6a2a..e8c9e6b98 100644 --- a/src/libstrongswan/debug.c +++ b/src/libstrongswan/debug.c @@ -34,6 +34,7 @@ ENUM(debug_names, DBG_DMN, DBG_LIB, "PTS", "TLS", "APP", + "ESP", "LIB", ); @@ -54,6 +55,7 @@ ENUM(debug_lower_names, DBG_DMN, DBG_LIB, "pts", "tls", "app", + "esp", "lib", ); diff --git a/src/libstrongswan/debug.h b/src/libstrongswan/debug.h index 65e55a639..ff4b4a1e9 100644 --- a/src/libstrongswan/debug.h +++ b/src/libstrongswan/debug.h @@ -64,6 +64,8 @@ enum debug_t { DBG_TLS, /** applications other than daemons */ DBG_APP, + /** libipsec */ + DBG_ESP, /** libstrongswan */ DBG_LIB, /** number of groups */ diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 5dc7f0436..03890b517 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -407,7 +407,7 @@ static void exit_usage(char *error) printf(" where: START and optional END define the clients source IP\n"); printf(" Set loglevel for a logging type:\n"); printf(" stroke loglevel TYPE LEVEL\n"); - printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib\n"); + printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n"); printf(" LEVEL is -1|0|1|2|3|4\n"); printf(" Show connection status:\n"); printf(" stroke status\n"); From a7babe25ee22e1de91ace2549b122fee58de6911 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Apr 2012 10:38:31 +0200 Subject: [PATCH 28/32] Added get_port() method to socket_t to learn the listening port. --- src/libcharon/network/socket.h | 10 +++++++++- src/libcharon/network/socket_manager.c | 16 +++++++++++++++- src/libcharon/network/socket_manager.h | 10 +++++++++- .../socket_default/socket_default_socket.c | 9 ++++++++- .../socket_dynamic/socket_dynamic_socket.c | 10 ++++++++++ .../plugins/socket_raw/socket_raw_socket.c | 9 ++++++++- 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h index be875035b..4a4ef52e6 100644 --- a/src/libcharon/network/socket.h +++ b/src/libcharon/network/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2010 Tobias Brunner + * Copyright (C) 2006-2012 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter @@ -67,6 +67,14 @@ struct socket_t { */ status_t (*send) (socket_t *this, packet_t *packet); + /** + * Get the port this socket is listening on. + * + * @param nat_t TRUE to get the port used to float in case of NAT-T + * @return the port + */ + u_int16_t (*get_port) (socket_t *this, bool nat_t); + /** * Destroy a socket implementation. */ diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c index 72a454301..d2736de8e 100644 --- a/src/libcharon/network/socket_manager.c +++ b/src/libcharon/network/socket_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Tobias Brunner + * Copyright (C) 2010-2012 Tobias Brunner * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG @@ -89,6 +89,19 @@ METHOD(socket_manager_t, sender, status_t, return status; } +METHOD(socket_manager_t, get_port, u_int16_t, + private_socket_manager_t *this, bool nat_t) +{ + u_int16_t port = 0; + this->lock->read_lock(this->lock); + if (this->socket) + { + port = this->socket->get_port(this->socket, nat_t); + } + this->lock->unlock(this->lock); + return port; +} + static void create_socket(private_socket_manager_t *this) { socket_constructor_t create; @@ -153,6 +166,7 @@ socket_manager_t *socket_manager_create() .public = { .send = _sender, .receive = _receiver, + .get_port = _get_port, .add_socket = _add_socket, .remove_socket = _remove_socket, .destroy = _destroy, diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h index 94185d21c..1909d1f25 100644 --- a/src/libcharon/network/socket_manager.h +++ b/src/libcharon/network/socket_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Tobias Brunner + * Copyright (C) 2010-2012 Tobias Brunner * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG @@ -52,6 +52,14 @@ struct socket_manager_t { */ status_t (*send) (socket_manager_t *this, packet_t *packet); + /** + * Get the port the registered socket is listening on. + * + * @param nat_t TRUE to get the port used to float in case of NAT-T + * @return the port, or 0, if no socket is registered + */ + u_int16_t (*get_port) (socket_manager_t *this, bool nat_t); + /** * Register a socket constructor. * diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 8da574a34..beab3ea6b 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -305,7 +305,7 @@ METHOD(socket_t, sender, status_t, /* send data */ sport = src->get_port(src); family = dst->get_family(dst); - if (sport == CHARON_UDP_PORT) + if (sport == 0 || sport == CHARON_UDP_PORT) { if (family == AF_INET) { @@ -405,6 +405,12 @@ METHOD(socket_t, sender, status_t, return SUCCESS; } +METHOD(socket_t, get_port, u_int16_t, + private_socket_default_socket_t *this, bool nat_t) +{ + return nat_t ? CHARON_NATT_PORT : CHARON_UDP_PORT; +} + /** * open a socket to send and receive packets */ @@ -533,6 +539,7 @@ socket_default_socket_t *socket_default_socket_create() .socket = { .send = _sender, .receive = _receiver, + .get_port = _get_port, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index 3c3b17bf3..e0e0af6b6 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -467,6 +467,7 @@ METHOD(socket_t, sender, status_t, dst = packet->get_destination(packet); family = src->get_family(src); port = src->get_port(src); + port = port ?: CHARON_UDP_PORT; skt = find_socket(this, family, port); if (!skt) { @@ -534,6 +535,14 @@ METHOD(socket_t, sender, status_t, return SUCCESS; } +METHOD(socket_t, get_port, u_int16_t, + private_socket_dynamic_socket_t *this, bool nat_t) +{ + /* we return 0 here for users that have no explicit port configured, the + * sender will default to the default port in this case */ + return 0; +} + METHOD(socket_t, destroy, void, private_socket_dynamic_socket_t *this) { @@ -567,6 +576,7 @@ socket_dynamic_socket_t *socket_dynamic_socket_create() .socket = { .send = _sender, .receive = _receiver, + .get_port = _get_port, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 37d13f13f..1b3c9e126 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -309,7 +309,7 @@ METHOD(socket_t, sender, status_t, /* send data */ sport = src->get_port(src); family = dst->get_family(dst); - if (sport == CHARON_UDP_PORT) + if (sport == 0 || sport == CHARON_UDP_PORT) { if (family == AF_INET) { @@ -470,6 +470,12 @@ static int open_send_socket(private_socket_raw_socket_t *this, return skt; } +METHOD(socket_t, get_port, u_int16_t, + private_socket_raw_socket_t *this, bool nat_t) +{ + return nat_t ? CHARON_NATT_PORT : CHARON_UDP_PORT; +} + /** * open a socket to receive packets */ @@ -616,6 +622,7 @@ socket_raw_socket_t *socket_raw_socket_create() .socket = { .send = _sender, .receive = _receiver, + .get_port = _get_port, .destroy = _destroy, }, }, From b223d517c80924ee664238a48058d791e2d87c43 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Apr 2012 10:59:14 +0200 Subject: [PATCH 29/32] Replaced usages of CHARON_*_PORT with calls to get_port(). --- src/charon-nm/nm/nm_service.c | 3 ++- src/libcharon/plugins/android/android_service.c | 3 ++- src/libcharon/plugins/ha/ha_tunnel.c | 3 ++- .../plugins/load_tester/load_tester_config.c | 2 +- src/libcharon/plugins/maemo/maemo_service.c | 3 ++- src/libcharon/plugins/medcli/medcli_config.c | 4 ++-- src/libcharon/plugins/medsrv/medsrv_config.c | 2 +- src/libcharon/plugins/sql/sql_config.c | 2 +- src/libcharon/plugins/stroke/stroke_config.c | 3 ++- src/libcharon/plugins/uci/uci_config.c | 4 ++-- src/libcharon/processing/jobs/migrate_job.c | 2 +- src/libcharon/sa/ike_sa.c | 11 +++++++---- src/libcharon/sa/ikev1/tasks/informational.c | 3 ++- src/libcharon/sa/ikev2/tasks/ike_mobike.c | 8 ++++++-- 14 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c index affe281fa..ccfa210a0 100644 --- a/src/charon-nm/nm/nm_service.c +++ b/src/charon-nm/nm/nm_service.c @@ -497,7 +497,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, /** * Set up configurations */ - ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE, CHARON_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", FALSE, + charon->socket->get_port(charon->socket, FALSE), (char*)address, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg, diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index c5553f24f..f2d8ddce9 100644 --- a/src/libcharon/plugins/android/android_service.c +++ b/src/libcharon/plugins/android/android_service.c @@ -264,7 +264,8 @@ static job_requeue_t initiate(private_android_service_t *this) this->creds->set_username_password(this->creds, user, password); } - ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, CHARON_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, + charon->socket->get_port(charon->socket, FALSE), hostname, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index 200733cac..ad458caad 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -203,7 +203,8 @@ static void setup_tunnel(private_ha_tunnel_t *this, lib->credmgr->add_set(lib->credmgr, &this->creds.public); /* create config and backend */ - ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, CHARON_UDP_PORT, + ike_cfg = ike_cfg_create(FALSE, FALSE, local, FALSE, + charon->socket->get_port(charon->socket, FALSE), remote, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND, diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index 2e02fb57c..f5da8b892 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -257,7 +257,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) else { ike_cfg = ike_cfg_create(FALSE, FALSE, - this->local, FALSE, CHARON_UDP_PORT, + this->local, FALSE, charon->socket->get_port(charon->socket, FALSE), this->remote, FALSE, IKEV2_UDP_PORT); } ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal)); diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index 9f1f16956..f638a81b7 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -323,7 +323,8 @@ static gboolean initiate_connection(private_maemo_service_t *this, NULL); } - ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, CHARON_UDP_PORT, + ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", FALSE, + charon->socket->get_port(charon->socket, FALSE), hostname, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 6b28f751c..829c8f05e 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -119,7 +119,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, return NULL; } ike_cfg = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, CHARON_UDP_PORT, + "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), address, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); med_cfg = peer_cfg_create( @@ -396,7 +396,7 @@ medcli_config_t *medcli_config_create(database_t *db) .rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200), .dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300), .ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, CHARON_UDP_PORT, + "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), "0.0.0.0", FALSE, IKEV2_UDP_PORT), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c index b19847b87..ebc142de2 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -141,7 +141,7 @@ medsrv_config_t *medsrv_config_create(database_t *db) .rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200), .dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300), .ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", FALSE, CHARON_UDP_PORT, + "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), "0.0.0.0", FALSE, IKEV2_UDP_PORT), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index 28b493e7a..890077157 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -259,7 +259,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, ike_cfg_t *ike_cfg; ike_cfg = ike_cfg_create(certreq, force_encap, - local, FALSE, CHARON_UDP_PORT, + local, FALSE, charon->socket->get_port(charon->socket, FALSE), remote, FALSE, IKEV2_UDP_PORT); add_ike_proposals(this, ike_cfg, id); return ike_cfg; diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 83f04bd38..bf93f2c34 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -226,7 +226,8 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg } } ikeport = msg->add_conn.me.ikeport; - ikeport = (ikeport == IKEV2_UDP_PORT) ? CHARON_UDP_PORT : ikeport; + ikeport = (ikeport == IKEV2_UDP_PORT) ? + charon->socket->get_port(charon->socket, FALSE) : ikeport; ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND, msg->add_conn.force_encap, msg->add_conn.me.address, diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index 9dc0cfcde..5b698b8b2 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -169,7 +169,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool, { DESTROY_IF(this->peer_cfg); ike_cfg = ike_cfg_create(FALSE, FALSE, - local_addr, FALSE, CHARON_UDP_PORT, + local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), remote_addr, FALSE, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); this->peer_cfg = peer_cfg_create( @@ -267,7 +267,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool, { DESTROY_IF(this->ike_cfg); this->ike_cfg = ike_cfg_create(FALSE, FALSE, - local_addr, FALSE, CHARON_UDP_PORT, + local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), remote_addr, FALSE, IKEV2_UDP_PORT); this->ike_cfg->add_proposal(this->ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c index 6e5b4af0d..57f344980 100644 --- a/src/libcharon/processing/jobs/migrate_job.c +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -97,7 +97,7 @@ METHOD(job_t, execute, job_requeue_t, ike_sa->set_kmaddress(ike_sa, this->local, this->remote); host = this->local->clone(this->local); - host->set_port(host, CHARON_UDP_PORT); + host->set_port(host, charon->socket->get_port(charon->socket, FALSE)); ike_sa->set_my_host(ike_sa, host); host = this->remote->clone(this->remote); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 755e5d74d..d9e4ca582 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -845,9 +845,11 @@ METHOD(ike_sa_t, float_ports, void, private_ike_sa_t *this) { /* do not switch if we have a custom port from MOBIKE/NAT */ - if (this->my_host->get_port(this->my_host) == CHARON_UDP_PORT) + if (this->my_host->get_port(this->my_host) == + charon->socket->get_port(charon->socket, FALSE)) { - this->my_host->set_port(this->my_host, CHARON_NATT_PORT); + this->my_host->set_port(this->my_host, + charon->socket->get_port(charon->socket, TRUE)); } if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT) { @@ -1054,7 +1056,7 @@ static void resolve_hosts(private_ike_sa_t *this) if (this->local_host) { host = this->local_host->clone(this->local_host); - host->set_port(host, CHARON_UDP_PORT); + host->set_port(host, charon->socket->get_port(charon->socket, FALSE)); } else { @@ -2239,7 +2241,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, } this->task_manager = task_manager_create(&this->public); - this->my_host->set_port(this->my_host, CHARON_UDP_PORT); + this->my_host->set_port(this->my_host, + charon->socket->get_port(charon->socket, FALSE)); if (!this->task_manager || !this->keymat) { diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c index eee716c85..bda1d2afb 100644 --- a/src/libcharon/sa/ikev1/tasks/informational.c +++ b/src/libcharon/sa/ikev1/tasks/informational.c @@ -116,7 +116,8 @@ METHOD(task_t, process_r, status_t, notify_type_names, type, redirect); /* Cisco boxes reject the first message from 4500 */ me = this->ike_sa->get_my_host(this->ike_sa); - me->set_port(me, CHARON_UDP_PORT); + me->set_port(me, charon->socket->get_port( + charon->socket, FALSE)); this->ike_sa->set_other_host(this->ike_sa, redirect); this->ike_sa->reauth(this->ike_sa); enumerator->destroy(enumerator); diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c index 388b45c68..133bc296e 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c +++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c @@ -277,9 +277,13 @@ static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local) { port = old->get_port(old); } - else if (port == (local ? CHARON_UDP_PORT : IKEV2_UDP_PORT)) + else if (local && port == charon->socket->get_port(charon->socket, FALSE)) { - port = (local ? CHARON_NATT_PORT : IKEV2_NATT_PORT); + port = charon->socket->get_port(charon->socket, TRUE); + } + else if (!local && port == IKEV2_UDP_PORT) + { + port = IKEV2_NATT_PORT; } host->set_port(host, port); } From 224ab4c59b2b747f0ff1298dbb196ebfca561dca Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Apr 2012 14:58:02 +0200 Subject: [PATCH 30/32] socket-default plugin allocates random ports if configured to 0. Also added strongswan.conf options to change the ports. --- configure.in | 6 +- man/strongswan.conf.5.in | 9 ++ .../socket_default/socket_default_socket.c | 122 ++++++++++++------ 3 files changed, 97 insertions(+), 40 deletions(-) diff --git a/configure.in b/configure.in index 5ee3b8723..3a7d5b76c 100644 --- a/configure.in +++ b/configure.in @@ -73,7 +73,7 @@ AC_ARG_WITH( AC_ARG_WITH( [charon-udp-port], - AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500).]), + AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500). Set to 0 to allocate randomly.]), [AC_DEFINE_UNQUOTED(CHARON_UDP_PORT, [$withval], [UDP port used by charon locally]) AC_SUBST(charon_udp_port, [$withval])], [AC_SUBST(charon_udp_port, 500)] @@ -81,14 +81,14 @@ AC_ARG_WITH( AC_ARG_WITH( [charon-natt-port], - AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500)]), + AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500). Set to 0 to allocate randomly.]), [AC_DEFINE_UNQUOTED(CHARON_NATT_PORT, [$withval], [UDP post used by charon locally in case a NAT is detected]) AC_SUBST(charon_natt_port, [$withval])], [AC_SUBST(charon_natt_port, 4500)] ) AC_MSG_CHECKING([configured UDP ports ($charon_udp_port, $charon_natt_port)]) -if test x$charon_udp_port == x$charon_natt_port; then +if test x$charon_udp_port != x0 -a x$charon_udp_port = x$charon_natt_port; then AC_MSG_ERROR(the ports have to be different) else AC_MSG_RESULT(ok) diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 4dd818b8a..8fcba4a69 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -210,6 +210,15 @@ Enable multiple authentication exchanges (RFC 4739) .BR charon.nbns2 WINS servers assigned to peer via configuration payload (CP) .TP +.BR charon.port " [500]" +UDP port used locally. If set to 0 a random port will be allocated. +.TP +.BR charon.port_nat_t " [4500]" +UDP port used locally in case of NAT-T. If set to 0 a random port will be +allocated. Has to be different from +.BR charon.port , +otherwise a random port will be allocated. +.TP .BR charon.process_route " [yes]" Process RTM_NEWROUTE and RTM_DELROUTE events .TP diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index beab3ea6b..a7da2cc9c 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -83,22 +83,32 @@ struct private_socket_default_socket_t { socket_default_socket_t public; /** - * IPv4 socket (500) + * Configured port (or random, if initially 0) + */ + u_int16_t port; + + /** + * Configured port for NAT-T (or random, if initially 0) + */ + u_int16_t natt; + + /** + * IPv4 socket (500 or port) */ int ipv4; /** - * IPv4 socket for NATT (4500) + * IPv4 socket for NAT-T (4500 or natt) */ int ipv4_natt; /** - * IPv6 socket (500) + * IPv6 socket (500 or port) */ int ipv6; /** - * IPv6 socket for NATT (4500) + * IPv6 socket for NAT-T (4500 or natt) */ int ipv6_natt; @@ -153,22 +163,22 @@ METHOD(socket_t, receiver, status_t, if (FD_ISSET(this->ipv4, &rfds)) { - port = CHARON_UDP_PORT; + port = this->port; selected = this->ipv4; } if (FD_ISSET(this->ipv4_natt, &rfds)) { - port = CHARON_NATT_PORT; + port = this->natt; selected = this->ipv4_natt; } if (FD_ISSET(this->ipv6, &rfds)) { - port = CHARON_UDP_PORT; + port = this->port; selected = this->ipv6; } if (FD_ISSET(this->ipv6_natt, &rfds)) { - port = CHARON_NATT_PORT; + port = this->natt; selected = this->ipv6_natt; } if (selected) @@ -305,7 +315,7 @@ METHOD(socket_t, sender, status_t, /* send data */ sport = src->get_port(src); family = dst->get_family(dst); - if (sport == 0 || sport == CHARON_UDP_PORT) + if (sport == 0 || sport == this->port) { if (family == AF_INET) { @@ -316,7 +326,7 @@ METHOD(socket_t, sender, status_t, skt = this->ipv6; } } - else if (sport == CHARON_NATT_PORT) + else if (sport == this->natt) { if (family == AF_INET) { @@ -408,14 +418,14 @@ METHOD(socket_t, sender, status_t, METHOD(socket_t, get_port, u_int16_t, private_socket_default_socket_t *this, bool nat_t) { - return nat_t ? CHARON_NATT_PORT : CHARON_UDP_PORT; + return nat_t ? this->natt : this->port; } /** * open a socket to send and receive packets */ static int open_socket(private_socket_default_socket_t *this, - int family, u_int16_t port) + int family, u_int16_t *port) { int on = TRUE; struct sockaddr_storage addr; @@ -432,7 +442,7 @@ static int open_socket(private_socket_default_socket_t *this, { struct sockaddr_in *sin = (struct sockaddr_in *)&addr; htoun32(&sin->sin_addr.s_addr, INADDR_ANY); - htoun16(&sin->sin_port, port); + htoun16(&sin->sin_port, *port); addrlen = sizeof(struct sockaddr_in); sol = SOL_IP; #ifdef IP_PKTINFO @@ -446,7 +456,7 @@ static int open_socket(private_socket_default_socket_t *this, { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); - htoun16(&sin6->sin6_port, port); + htoun16(&sin6->sin6_port, *port); addrlen = sizeof(struct sockaddr_in6); sol = SOL_IPV6; pktinfo = IPV6_RECVPKTINFO; @@ -477,6 +487,32 @@ static int open_socket(private_socket_default_socket_t *this, return 0; } + /* retrieve randomly allocated port if needed */ + if (*port == 0) + { + if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0) + { + DBG1(DBG_NET, "unable to determine port: %s", strerror(errno)); + close(skt); + return 0; + } + switch (family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)&addr; + *port = untoh16(&sin->sin_port); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; + *port = untoh16(&sin6->sin6_port); + break; + } + } + } + /* get additional packet info on receive */ if (pktinfo > 0) { @@ -493,15 +529,6 @@ static int open_socket(private_socket_default_socket_t *this, { DBG1(DBG_NET, "installing IKE bypass policy failed"); } - - /* enable UDP decapsulation globally, only for one socket needed */ - if (family == AF_INET && port == CHARON_NATT_PORT && - !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, - skt, family, port)) - { - DBG1(DBG_NET, "enabling UDP decapsulation failed"); - } - return skt; } @@ -543,44 +570,65 @@ socket_default_socket_t *socket_default_socket_create() .destroy = _destroy, }, }, + .port = lib->settings->get_int(lib->settings, + "%s.port", CHARON_UDP_PORT, charon->name), + .natt = lib->settings->get_int(lib->settings, + "%s.port_nat_t", CHARON_NATT_PORT, charon->name), .max_packet = lib->settings->get_int(lib->settings, - "%s.max_packet", MAX_PACKET, charon->name), + "%s.max_packet", MAX_PACKET, charon->name), ); - this->ipv4 = open_socket(this, AF_INET, CHARON_UDP_PORT); - if (this->ipv4 == 0) + if (this->port && this->port == this->natt) { - DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled"); - } - else - { - this->ipv4_natt = open_socket(this, AF_INET, CHARON_NATT_PORT); - if (this->ipv4_natt == 0) - { - DBG1(DBG_NET, "could not open IPv4 NAT-T socket"); - } + DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T " + "port randomly"); + this->natt = 0; } - this->ipv6 = open_socket(this, AF_INET6, CHARON_UDP_PORT); + /* we allocate IPv6 sockets first as that will reserve randomly allocated + * ports also for IPv4 */ + this->ipv6 = open_socket(this, AF_INET6, &this->port); if (this->ipv6 == 0) { DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled"); } else { - this->ipv6_natt = open_socket(this, AF_INET6, CHARON_NATT_PORT); + this->ipv6_natt = open_socket(this, AF_INET6, &this->natt); if (this->ipv6_natt == 0) { DBG1(DBG_NET, "could not open IPv6 NAT-T socket"); } } + this->ipv4 = open_socket(this, AF_INET, &this->port); + if (this->ipv4 == 0) + { + DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled"); + } + else + { + this->ipv4_natt = open_socket(this, AF_INET, &this->natt); + if (this->ipv4_natt == 0) + { + DBG1(DBG_NET, "could not open IPv4 NAT-T socket"); + } + } + if (!this->ipv4 && !this->ipv6) { DBG1(DBG_NET, "could not create any sockets"); destroy(this); return NULL; } + + /* enable UDP decapsulation globally, only for one socket needed */ + if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface, + this->ipv6_natt ?: this->ipv4_natt, + this->ipv6_natt ? AF_INET6 : AF_INET, this->natt)) + { + DBG1(DBG_NET, "enabling UDP decapsulation failed"); + } return &this->public; } From 95dacbbc7076a1bd92b4732dcadc1bef67e28196 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 20 Apr 2012 15:16:51 +0200 Subject: [PATCH 31/32] Allocate UDP ports randomly in Android NDK build. --- src/frontends/android/jni/Android.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk index ad5ddd6d3..431415ae7 100644 --- a/src/frontends/android/jni/Android.mk +++ b/src/frontends/android/jni/Android.mk @@ -44,7 +44,8 @@ strongswan_CFLAGS := \ -DUSE_IKEV2 \ -DUSE_VSTR \ -DDEBUG \ - -DCHARON_UDP_PORT=4000 \ + -DCHARON_UDP_PORT=0 \ + -DCHARON_NATT_PORT=0 \ -DVERSION=\"$(strongswan_VERSION)\" \ -DDEV_RANDOM=\"/dev/random\" \ -DDEV_URANDOM=\"/dev/urandom\" From 6fbf4472ea785f3c75d278b1a7400534989bf26a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 8 Aug 2012 15:39:07 +0200 Subject: [PATCH 32/32] Added option to prevent socket-default from setting the source address on outbound packets --- man/strongswan.conf.5.in | 3 +++ .../plugins/socket_default/socket_default_socket.c | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 8fcba4a69..0c75bd026 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -496,6 +496,9 @@ is appended to this prefix to make it unique. The result has to be a valid interface name according to the rules defined by resolvconf. Also, it should have a high priority according to the order defined in interface-order(5). .TP +.BR charon.plugins.socket-default.set_source " [yes]" +Set source address on outbound packets, if possible. +.TP .BR charon.plugins.sql.database Database URI for charons SQL plugin .TP diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index a7da2cc9c..c2b073418 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -116,6 +116,11 @@ struct private_socket_default_socket_t { * Maximum packet size to receive */ int max_packet; + + /** + * TRUE if the source address should be set on outbound packets + */ + bool set_source; }; METHOD(socket_t, receiver, status_t, @@ -352,7 +357,7 @@ METHOD(socket_t, sender, status_t, msg.msg_iovlen = 1; msg.msg_flags = 0; - if (!src->is_anyaddr(src)) + if (this->set_source && !src->is_anyaddr(src)) { if (family == AF_INET) { @@ -576,6 +581,9 @@ socket_default_socket_t *socket_default_socket_create() "%s.port_nat_t", CHARON_NATT_PORT, charon->name), .max_packet = lib->settings->get_int(lib->settings, "%s.max_packet", MAX_PACKET, charon->name), + .set_source = lib->settings->get_bool(lib->settings, + "%s.plugins.socket-default.set_source", TRUE, + charon->name), ); if (this->port && this->port == this->natt)