Merge branch 'android-ndk'

This branch comes with some preliminary changes for the user-land IPsec
implementation and the Android App.

One important change is that the UDP ports used by the socket-default plugin
were made configurable (either via ./configure or strongswan.conf).
Also, the plugin does randomly allocate a port if it is configured to 0,
which is useful for client implementations.  A consequence of these
changes is that the local UDP port used when creating ike_cfg_t objects has
to be fetched from the socket.
This commit is contained in:
Tobias Brunner
2012-08-13 10:45:39 +02:00
82 changed files with 1462 additions and 332 deletions
+4
View File
@@ -8,6 +8,10 @@ if USE_LIBHYDRA
SUBDIRS += libhydra
endif
if USE_LIBIPSEC
SUBDIRS += libipsec
endif
if USE_SIMAKA
SUBDIRS += libsimaka
endif
+2 -1
View File
@@ -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, IKEV2_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,
+2 -1
View File
@@ -387,7 +387,7 @@ static void usage(const char *msg)
" [--version]\n"
" [--use-syslog]\n"
" [--debug-<type> <level>]\n"
" <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib)\n"
" <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
" <level>: 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 }
};
+5
View File
@@ -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
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
+4
View File
@@ -0,0 +1,4 @@
bin/
gen/
libs/
obj/
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.strongswan.android"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".strongSwanActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".CharonVpnService" android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService"/>
</intent-filter>
</service>
</application>
</manifest>
+22
View File
@@ -0,0 +1,22 @@
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 (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
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 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.
+4
View File
@@ -0,0 +1,4 @@
openssl
strongswan
vstr/libvstr.a
vstr/include
+65
View File
@@ -0,0 +1,65 @@
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=0 \
-DCHARON_NATT_PORT=0 \
-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 \
libandroidbridge \
strongswan/src/libipsec \
strongswan/src/libcharon \
strongswan/src/libhydra \
strongswan/src/libstrongswan \
))
@@ -0,0 +1,34 @@
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/libipsec \
$(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 libipsec libcharon
include $(BUILD_SHARED_LIBRARY)
@@ -0,0 +1,124 @@
/*
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include <android/log.h>
#include <jni.h>
#include <hydra.h>
#include <ipsec.h>
#include <daemon.h>
#include <library.h>
#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 (!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;
}
/* 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();
libipsec_deinit();
libhydra_deinit();
library_deinit();
}
+11
View File
@@ -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)
+40
View File
@@ -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 <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(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 *;
}
+11
View File
@@ -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-14
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, strongSwanActivity!</string>
<string name="app_name">strongSwan</string>
</resources>
@@ -0,0 +1,57 @@
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("ipsec");
System.loadLibrary("androidbridge");
}
}
@@ -0,0 +1,40 @@
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
{
@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);
}
}
}
+5
View File
@@ -130,6 +130,11 @@ LOCAL_C_INCLUDES += frameworks/base/cmds/keystore
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)
+7
View File
@@ -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
+17 -2
View File
@@ -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.
*/
+16 -3
View File
@@ -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,
},
+10
View File
@@ -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.
*
+82 -1
View File
@@ -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
@@ -27,6 +27,7 @@
#include <processing/jobs/process_message_job.h>
#include <processing/jobs/callback_job.h>
#include <crypto/hashers/hasher.h>
#include <threading/mutex.h>
/** 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
*/
@@ -400,8 +414,10 @@ 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;
chunk_t data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
/* read in a packet */
status = charon->socket->receive(charon->socket, &packet);
@@ -415,6 +431,46 @@ 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);
src = packet->get_source(packet);
if (dst->get_port(dst) != IKEV2_UDP_PORT &&
src->get_port(src) != IKEV2_UDP_PORT)
{
if (memeq(data.ptr, marker.ptr, marker.len))
{ /* remove Non-ESP marker */
packet->skip_bytes(packet, marker.len);
}
else
{ /* this seems to be an ESP 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;
}
}
/* parse message header */
message = message_create_from_packet(packet);
if (message->parse_header(message) != SUCCESS)
@@ -513,11 +569,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);
}
@@ -531,8 +609,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,
);
+37 -5
View File
@@ -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 <library.h>
#include <network/packet.h>
#include <utils/host.h>
/**
* 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);
};
/**
+24 -2
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -79,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;
@@ -115,10 +116,30 @@ 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 data, marker = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
data = chunk_cat("cc", marker, packet->get_data(packet));
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;
bool oldstate;
@@ -176,6 +197,7 @@ sender_t * sender_create()
INIT(this,
.public = {
.send = _send_,
.send_no_marker = _send_no_marker,
.flush = _flush,
.destroy = _destroy,
},
+9 -1
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -28,7 +29,7 @@ typedef struct sender_t sender_t;
#include <network/packet.h>
/**
* Thread responsible for sending packets over the socket.
* Callback job responsible for sending IKE packets over the socket.
*/
struct sender_t {
@@ -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.
*
+9 -1
View File
@@ -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.
*/
+15 -1
View File
@@ -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,
+9 -1
View File
@@ -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.
*
@@ -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
@@ -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);
@@ -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, IKEV2_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));
@@ -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
@@ -16,23 +16,23 @@
#include <string.h>
#include <android/log.h>
#include "android_logger.h"
#include "android_log_logger.h"
#include <library.h>
#include <daemon.h>
#include <threading/mutex.h>
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;
@@ -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 <bus/bus.h>
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_ @}*/
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "android_log_plugin.h"
#include "android_log_logger.h"
#include <daemon.h>
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;
}
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup 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 <plugins/plugin.h>
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_ @}*/
+2 -1
View File
@@ -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, IKEV2_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,
@@ -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->socket->get_port(charon->socket, FALSE),
this->remote, FALSE, IKEV2_UDP_PORT);
}
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
@@ -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,
},
},
+2 -1
View File
@@ -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, IKEV2_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));
+2 -2
View File
@@ -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->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, IKEV2_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));
+1 -1
View File
@@ -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->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));
@@ -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
@@ -40,9 +40,6 @@
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <net/if.h>
#ifdef __APPLE__
#include <sys/sysctl.h>
#endif
#include <hydra.h>
#include <daemon.h>
@@ -51,18 +48,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
/* 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 +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 */
@@ -101,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;
@@ -124,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,
@@ -133,7 +130,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;
@@ -171,22 +168,22 @@ METHOD(socket_t, receiver, status_t,
if (FD_ISSET(this->ipv4, &rfds))
{
port = IKEV2_UDP_PORT;
port = this->port;
selected = this->ipv4;
}
if (FD_ISSET(this->ipv4_natt, &rfds))
{
port = IKEV2_NATT_PORT;
port = this->natt;
selected = this->ipv4_natt;
}
if (FD_ISSET(this->ipv6, &rfds))
{
port = IKEV2_UDP_PORT;
port = this->port;
selected = this->ipv6;
}
if (FD_ISSET(this->ipv6_natt, &rfds))
{
port = IKEV2_NATT_PORT;
port = this->natt;
selected = this->ipv6_natt;
}
if (selected)
@@ -222,13 +219,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))
@@ -297,17 +287,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) == IKEV2_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
{
@@ -324,7 +305,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,7 +320,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 == 0 || sport == this->port)
{
if (family == AF_INET)
{
@@ -350,7 +331,7 @@ METHOD(socket_t, sender, status_t,
skt = this->ipv6;
}
}
else if (sport == IKEV2_NATT_PORT)
else if (sport == this->natt)
{
if (family == AF_INET)
{
@@ -360,17 +341,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
{
@@ -387,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)
{
@@ -450,11 +420,17 @@ 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 ? 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;
@@ -471,7 +447,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
@@ -485,7 +461,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;
@@ -516,6 +492,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)
{
@@ -532,18 +534,6 @@ 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 */
int type = UDP_ENCAP_ESPINUDP;
if (family == AF_INET && port == IKEV2_NATT_PORT &&
setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
{
DBG1(DBG_NET, "unable to set UDP_ENCAP: %s", strerror(errno));
}
}
#endif
return skt;
}
@@ -581,59 +571,72 @@ socket_default_socket_t *socket_default_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
.get_port = _get_port,
.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),
.set_source = lib->settings->get_bool(lib->settings,
"%s.plugins.socket-default.set_source", TRUE,
charon->name),
);
#ifdef __APPLE__
if (this->port && this->port == this->natt)
{
int natt_port = IKEV2_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, IKEV2_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);
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, IKEV2_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, IKEV2_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;
}
@@ -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
@@ -45,18 +45,6 @@
/* Maximum size of a packet */
#define MAX_PACKET 10000
/* 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 +52,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 */
@@ -237,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))
@@ -297,12 +276,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;
}
@@ -358,7 +331,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;
@@ -430,10 +403,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;
}
@@ -483,7 +458,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;
@@ -492,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)
{
@@ -501,19 +477,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);
@@ -572,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)
{
@@ -605,6 +576,7 @@ socket_dynamic_socket_t *socket_dynamic_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
.get_port = _get_port,
.destroy = _destroy,
},
},
@@ -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
@@ -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
@@ -181,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);
@@ -203,16 +194,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) == IKEV2_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))
{
@@ -242,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);
@@ -290,16 +274,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) == IKEV2_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
{
@@ -317,7 +294,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;
@@ -332,7 +309,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 == 0 || sport == CHARON_UDP_PORT)
{
if (family == AF_INET)
{
@@ -343,7 +320,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)
{
@@ -353,17 +330,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
{
@@ -437,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;
@@ -488,25 +453,29 @@ 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;
}
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
*/
@@ -541,8 +510,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),
@@ -653,6 +622,7 @@ socket_raw_socket_t *socket_raw_socket_create()
.socket = {
.send = _sender,
.receive = _receiver,
.get_port = _get_port,
.destroy = _destroy,
},
},
@@ -667,7 +637,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 +645,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 +660,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 +668,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");
+1 -1
View File
@@ -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->socket->get_port(charon->socket, FALSE),
remote, FALSE, IKEV2_UDP_PORT);
add_ike_proposals(this, ike_cfg, id);
return ike_cfg;
+5 -1
View File
@@ -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,14 @@ 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->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,
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);
+2 -2
View File
@@ -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->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, IKEV2_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));
+1 -1
View File
@@ -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->socket->get_port(charon->socket, FALSE));
ike_sa->set_my_host(ike_sa, host);
host = this->remote->clone(this->remote);
+8 -5
View File
@@ -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);
@@ -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) == IKEV2_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, IKEV2_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, IKEV2_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, IKEV2_UDP_PORT);
this->my_host->set_port(this->my_host,
charon->socket->get_port(charon->socket, FALSE));
if (!this->task_manager || !this->keymat)
{
+2 -1
View File
@@ -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, IKEV2_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);
+8 -4
View File
@@ -271,13 +271,17 @@ 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 (local && port == charon->socket->get_port(charon->socket, FALSE))
{
port = charon->socket->get_port(charon->socket, TRUE);
}
else if (!local && port == IKEV2_UDP_PORT)
{
port = IKEV2_NATT_PORT;
}
@@ -314,9 +318,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);
+12 -1
View File
@@ -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,
+14 -2
View File
@@ -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
*/
+12 -1
View File
@@ -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.
*/
@@ -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,
},
},
@@ -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,
},
},
@@ -51,6 +51,9 @@
#include <unistd.h>
#include <time.h>
#include <errno.h>
#ifdef __APPLE__
#include <sys/sysctl.h>
#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,
},
},
+29
View File
@@ -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)
+20
View File
@@ -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
+69
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "ipsec.h"
#include <debug.h>
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;
}
+56
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup libipsec libipsec
*
* @addtogroup libipsec
* @{
*/
#ifndef IPSEC_H_
#define IPSEC_H_
typedef struct ipsec_t ipsec_t;
#include <library.h>
/**
* 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_ @}*/
+1 -1
View File
@@ -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
+2
View File
@@ -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",
);
+2
View File
@@ -64,6 +64,8 @@ enum debug_t {
DBG_TLS,
/** applications other than daemons */
DBG_APP,
/** libipsec */
DBG_ESP,
/** libstrongswan */
DBG_LIB,
/** number of groups */
+15 -6
View File
@@ -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)
{
+9 -2
View File
@@ -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);
+1 -1
View File
@@ -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");