Signed-off-by: Nikos Mavrogiannopoulos <n...@gnutls.org> --- libs/openconnect/Makefile | 49 ++++++++ libs/openconnect/files/openconnect.sh | 56 +++++++++ libs/openconnect/files/vpnc-script | 156 ++++++++++++++++++++++++++ net/openconnect/Config.in | 18 +++ net/openconnect/Makefile | 17 ++- net/openconnect/files/openconnect.sh | 4 +- net/openconnect/patches/100-passwd_file.patch | 100 ----------------- 7 files changed, 294 insertions(+), 106 deletions(-) create mode 100644 libs/openconnect/Makefile create mode 100755 libs/openconnect/files/openconnect.sh create mode 100755 libs/openconnect/files/vpnc-script create mode 100644 net/openconnect/Config.in delete mode 100644 net/openconnect/patches/100-passwd_file.patch
diff --git a/libs/openconnect/Makefile b/libs/openconnect/Makefile new file mode 100644 index 0000000..3ab09f1 --- /dev/null +++ b/libs/openconnect/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=openconnect +PKG_VERSION:=5.03 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/ +PKG_MD5SUM:=ff43ed1dbaccd2537fd7c5bfb04295a6 + +include $(INCLUDE_DIR)/package.mk + +define Package/openconnect + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libxml2 +gnutls +kmod-tun +resolveip + TITLE:=VPN client for Cisco's AnyConnect SSL VPN + URL:=http://www.infradead.org/openconnect/ + SUBMENU:=VPN +endef + +define Package/openconnect/description + A VPN client compatible with Cisco's AnyConnect SSL VPN and ocserv. + + OpenConnect is a client for Cisco's AnyConnect SSL VPN, which is + supported by IOS 12.4(9)T or later on Cisco SR500, 870, 880, 1800, 2800, + 3800, 7200 Series and Cisco 7301 Routers. +endef + +CONFIGURE_ARGS += \ + --disable-shared \ + --with-vpnc-script=/lib/netifd/vpnc-script + +define Package/openconnect/install + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/openconnect.sh $(1)/lib/netifd/proto/ + $(INSTALL_BIN) ./files/vpnc-script $(1)/lib/netifd/ + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/openconnect $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,openconnect)) diff --git a/libs/openconnect/files/openconnect.sh b/libs/openconnect/files/openconnect.sh new file mode 100755 index 0000000..2610194 --- /dev/null +++ b/libs/openconnect/files/openconnect.sh @@ -0,0 +1,56 @@ +#!/bin/sh +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_openconnect_init_config() { + proto_config_add_string "server" + proto_config_add_int "port" + proto_config_add_string "username" + proto_config_add_string "cookie" + proto_config_add_string "password" + no_device=1 + available=1 +} + +proto_openconnect_setup() { + local config="$1" + + json_get_vars server port username cookie password + + grep -q tun /proc/modules || insmod tun + + serv_addr= + for ip in $(resolveip -t 5 "$server"); do + proto_add_host_dependency "$config" "$server" + serv_addr=1 + done + [ -n "$serv_addr" ] || { + echo "Could not resolve server address" + sleep 5 + proto_setup_failed "$config" + exit 1 + } + + [ -n "$port" ] && port=":$port" + + cmdline="$server$port -i vpn-$config --no-cert-check --non-inter --syslog --script /lib/netifd/vpnc-script" + + [ -n "$cookie" ] && append cmdline "-C $cookie" + [ -n "$username" ] && append cmdline "-u $username" + [ -n "$password" ] && { + umask 077 + pwfile="/var/run/openconnect-$config.passwd" + echo "$password" > "$pwfile" + append cmdline "--passwd-on-stdin" + } + + proto_export INTERFACE="$config" + proto_run_command "$config" /usr/sbin/openconnect $cmdline <$pwfile +} + +proto_openconnect_teardown() { + proto_kill_command "$config" +} + +add_protocol openconnect diff --git a/libs/openconnect/files/vpnc-script b/libs/openconnect/files/vpnc-script new file mode 100755 index 0000000..4d12d7e --- /dev/null +++ b/libs/openconnect/files/vpnc-script @@ -0,0 +1,156 @@ +#!/bin/sh +# List of parameters passed through environment +#* reason -- why this script was called, one of: pre-init connect disconnect +#* VPNGATEWAY -- vpn gateway address (always present) +#* TUNDEV -- tunnel device (always present) +#* INTERNAL_IP4_ADDRESS -- address (always present) +#* INTERNAL_IP4_MTU -- mtu (often unset) +#* INTERNAL_IP4_NETMASK -- netmask (often unset) +#* INTERNAL_IP4_NETMASKLEN -- netmask length (often unset) +#* INTERNAL_IP4_NETADDR -- address of network (only present if netmask is set) +#* INTERNAL_IP4_DNS -- list of dns servers +#* INTERNAL_IP4_NBNS -- list of wins servers +#* INTERNAL_IP6_ADDRESS -- IPv6 address +#* INTERNAL_IP6_NETMASK -- IPv6 netmask +#* INTERNAL_IP6_DNS -- IPv6 list of dns servers +#* CISCO_DEF_DOMAIN -- default domain name +#* CISCO_BANNER -- banner from server +#* CISCO_SPLIT_INC -- number of networks in split-network-list +#* CISCO_SPLIT_INC_%d_ADDR -- network address +#* CISCO_SPLIT_INC_%d_MASK -- subnet mask (for example: 255.255.255.0) +#* CISCO_SPLIT_INC_%d_MASKLEN -- subnet masklen (for example: 24) +#* CISCO_SPLIT_INC_%d_PROTOCOL -- protocol (often just 0) +#* CISCO_SPLIT_INC_%d_SPORT -- source port (often just 0) +#* CISCO_SPLIT_INC_%d_DPORT -- destination port (often just 0) +#* CISCO_IPV6_SPLIT_INC -- number of networks in IPv6 split-network-list +#* CISCO_IPV6_SPLIT_INC_%d_ADDR -- IPv6 network address +#* CISCO_IPV6_SPLIT_INC_$%d_MASKLEN -- IPv6 subnet masklen + +# FIXMEs: + +# Section A: route handling + +# 1) The 3 values CISCO_SPLIT_INC_%d_PROTOCOL/SPORT/DPORT are currently being ignored +# In order to use them, we'll probably need os specific solutions +# * Linux: iptables -t mangle -I PREROUTING <conditions> -j ROUTE --oif $TUNDEV +# This would be an *alternative* to changing the routes (and thus 2) and 3) +# shouldn't be relevant at all) +# 2) There are two different functions to set routes: generic routes and the +# default route. Why isn't the defaultroute handled via the generic route case? +# 3) In the split tunnel case, all routes but the default route might get replaced +# without getting restored later. We should explicitely check and save them just +# like the defaultroute +# 4) Replies to a dhcp-server should never be sent into the tunnel + +# Section B: Split DNS handling + +# 1) Maybe dnsmasq can do something like that +# 2) Parse dns packets going out via tunnel and redirect them to original dns-server + +do_connect() { + if [ -n "$CISCO_BANNER" ]; then + echo "Connect Banner:" + echo "$CISCO_BANNER" | while read LINE ; do echo "|" "$LINE" ; done + echo + fi + + proto_init_update "$TUNDEV" 1 + + if [ -n "$INTERNAL_IP4_MTU" ]; then + MTU=$INTERNAL_IP4_MTU + fi + + if [ -z "$MTU" ]; then + MTU=1412 + fi + + proto_add_ipv4_address "$INTERNAL_IP4_ADDRESS" 32 "" "$INTERNAL_IP4_ADDRESS" + + if [ -n "$INTERNAL_IP4_NETMASKLEN" ]; then + proto_add_ipv4_route "$INTERNAL_IP4_NETADDR" "$INTERNAL_IP4_NETMASKLEN" + fi + + # If the netmask is provided, it contains the address _and_ netmask + if [ -n "$INTERNAL_IP6_ADDRESS" ] && [ -z "$INTERNAL_IP6_NETMASK" ]; then + INTERNAL_IP6_NETMASK="$INTERNAL_IP6_ADDRESS/128" + fi + + if [ -n "$INTERNAL_IP6_NETMASK" ]; then + addr="${INTERNAL_IP6_NETMASK%%/*}" + mask="${INTERNAL_IP6_NETMASK##*/}" + [[ "$addr" != "$mask" ]] && proto_add_ipv6_address "$addr" "$mask" + fi + + [ -n "$INTERNAL_IP4_DNS" ] && proto_add_dns_server "$INTERNAL_IP4_DNS" + [ -n "$CISCO_DEF_DOMAIN" ] && proto_add_dns_search "$CISCO_DEF_DOMAIN" + + if [ -n "$CISCO_SPLIT_INC" ]; then + i=0 + while [ $i -lt $CISCO_SPLIT_INC ] ; do + eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}" + eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}" + eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}" + if [ $NETWORK != "0.0.0.0" ]; then + proto_add_ipv4_route "$NETWORK" "$NETMASKLEN" + else + proto_add_ipv4_route "0.0.0.0" 0 + fi + i=$(($i + 1)) + done + elif [ -n "$INTERNAL_IP4_ADDRESS" ]; then + proto_add_ipv4_route "0.0.0.0" 0 + fi + if [ -n "$CISCO_IPV6_SPLIT_INC" ]; then + i=0 + while [ $i -lt $CISCO_IPV6_SPLIT_INC ] ; do + eval NETWORK="\${CISCO_IPV6_SPLIT_INC_${i}_ADDR}" + eval NETMASKLEN="\${CISCO_IPV6_SPLIT_INC_${i}_MASKLEN}" + if [ $NETMASKLEN -lt 128 ]; then + proto_add_ipv6_route "$NETWORK" "$NETMASKLEN" + else + proto_add_ipv6_route "::0" 0 + fi + i=$(($i + 1)) + done + elif [ -n "$INTERNAL_IP6_NETMASK" -o -n "$INTERNAL_IP6_ADDRESS" ]; then + proto_add_ipv6_route "::0" 0 + fi + proto_send_update "$INTERFACE" +} + +do_disconnect() { + proto_init_update "$TUNDEV" 0 + proto_send_update "$INTERFACE" +} + +#### Main + +if [ -z "$reason" ]; then + echo "this script must be called from vpnc" 1>&2 + exit 1 +fi +if [ -z "$INTERFACE" ]; then + echo "this script must be called for an active interface" + exit 1 +fi + +. /lib/netifd/netifd-proto.sh + +case "$reason" in + pre-init) + ;; + connect) + do_connect + ;; + disconnect) + do_disconnect + ;; + reconnect) + ;; + *) + echo "unknown reason '$reason'. Maybe vpnc-script is out of date" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/net/openconnect/Config.in b/net/openconnect/Config.in new file mode 100644 index 0000000..1daaeaa --- /dev/null +++ b/net/openconnect/Config.in @@ -0,0 +1,18 @@ +# openconnect avanced configuration + +menu "Configuration" + depends on PACKAGE_openconnect + +choice + prompt "SSL library" + default OPENCONNECT_GNUTLS + +config OPENCONNECT_GNUTLS + bool "GnuTLS support" + +config OPENCONNECT_OPENSSL + bool "OpenSSL" + +endchoice + +endmenu diff --git a/net/openconnect/Makefile b/net/openconnect/Makefile index 4eff613..0672dd1 100644 --- a/net/openconnect/Makefile +++ b/net/openconnect/Makefile @@ -8,26 +8,30 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openconnect -PKG_VERSION:=4.08 +PKG_VERSION:=5.03 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/ -PKG_MD5SUM:=3dd065194d87c08084675d255c8e29ef +PKG_MD5SUM:=ff43ed1dbaccd2537fd7c5bfb04295a6 include $(INCLUDE_DIR)/package.mk +define Package/openconnect/config + source "$(SOURCE)/Config.in" +endef + define Package/openconnect SECTION:=net CATEGORY:=Network - DEPENDS:=+libxml2 +libopenssl +kmod-tun +resolveip + DEPENDS:=+libxml2 +kmod-tun +resolveip +OPENCONNECT_OPENSSL:libopenssl +OPENCONNECT_GNUTLS:libgnutls TITLE:=VPN client for Cisco's AnyConnect SSL VPN URL:=http://www.infradead.org/openconnect/ SUBMENU:=VPN endef define Package/openconnect/description - A VPN client compatible with Cisco's AnyConnect SSL VPN. + A VPN client compatible with Cisco's AnyConnect SSL VPN and ocserv. OpenConnect is a client for Cisco's AnyConnect SSL VPN, which is supported by IOS 12.4(9)T or later on Cisco SR500, 870, 880, 1800, 2800, @@ -38,6 +42,11 @@ CONFIGURE_ARGS += \ --disable-shared \ --with-vpnc-script=/lib/netifd/vpnc-script +ifeq ($(CONFIG_OPENCONNECT_OPENSSL),y) +CONFIGURE_ARGS += \ + --without-gnutls +endif + define Package/openconnect/install $(INSTALL_DIR) $(1)/lib/netifd/proto $(INSTALL_BIN) ./files/openconnect.sh $(1)/lib/netifd/proto/ diff --git a/net/openconnect/files/openconnect.sh b/net/openconnect/files/openconnect.sh index 2110067..2610194 100755 --- a/net/openconnect/files/openconnect.sh +++ b/net/openconnect/files/openconnect.sh @@ -42,11 +42,11 @@ proto_openconnect_setup() { umask 077 pwfile="/var/run/openconnect-$config.passwd" echo "$password" > "$pwfile" - append cmdline "--passwd-file=$pwfile" + append cmdline "--passwd-on-stdin" } proto_export INTERFACE="$config" - proto_run_command "$config" /usr/sbin/openconnect $cmdline + proto_run_command "$config" /usr/sbin/openconnect $cmdline <$pwfile } proto_openconnect_teardown() { diff --git a/net/openconnect/patches/100-passwd_file.patch b/net/openconnect/patches/100-passwd_file.patch deleted file mode 100644 index 3e074d5..0000000 --- a/net/openconnect/patches/100-passwd_file.patch +++ /dev/null @@ -1,100 +0,0 @@ ---- a/main.c -+++ b/main.c -@@ -77,6 +77,7 @@ enum { - OPT_CAFILE, - OPT_COOKIEONLY, - OPT_COOKIE_ON_STDIN, -+ OPT_COOKIE_FILE, - OPT_CSD_USER, - OPT_CSD_WRAPPER, - OPT_DISABLE_IPV6, -@@ -91,6 +92,7 @@ enum { - OPT_NO_PROXY, - OPT_PIDFILE, - OPT_PASSWORD_ON_STDIN, -+ OPT_PASSWORD_FILE, - OPT_PRINTCOOKIE, - OPT_RECONNECT_TIMEOUT, - OPT_SERVERCERT, -@@ -139,7 +141,9 @@ static struct option long_options[] = { - OPTION("queue-len", 1, 'Q'), - OPTION("xmlconfig", 1, 'x'), - OPTION("cookie-on-stdin", 0, OPT_COOKIE_ON_STDIN), -+ OPTION("cookie-file", 1, OPT_COOKIE_FILE), - OPTION("passwd-on-stdin", 0, OPT_PASSWORD_ON_STDIN), -+ OPTION("passwd-file", 1, OPT_PASSWORD_FILE), - OPTION("no-passwd", 0, OPT_NO_PASSWD), - OPTION("reconnect-timeout", 1, OPT_RECONNECT_TIMEOUT), - OPTION("dtls-ciphers", 1, OPT_DTLS_CIPHERS), -@@ -177,6 +181,7 @@ static void usage(void) - printf(" -K, --key-type=TYPE %s\n", _("Private key type (PKCS#12 / TPM / PEM)")); - printf(" -C, --cookie=COOKIE %s\n", _("Use WebVPN cookie COOKIE")); - printf(" --cookie-on-stdin %s\n", _("Read cookie from standard input")); -+ printf(" --cookie-file=FILE %s\n", _("Read cookie from a file")); - printf(" -d, --deflate %s\n", _("Enable compression (default)")); - printf(" -D, --no-deflate %s\n", _("Disable compression")); - printf(" --force-dpd=INTERVAL %s\n", _("Set minimum Dead Peer Detection interval")); -@@ -217,6 +222,7 @@ static void usage(void) - printf(" --no-cert-check %s\n", _("Do not require server SSL cert to be valid")); - printf(" --non-inter %s\n", _("Do not expect user input; exit if it is required")); - printf(" --passwd-on-stdin %s\n", _("Read password from standard input")); -+ printf(" --passwd-file=FILE %s\n", _("Read password from a file")); - printf(" --reconnect-timeout %s\n", _("Connection retry timeout in seconds")); - printf(" --servercert=FINGERPRINT %s\n", _("Server's certificate SHA1 fingerprint")); - printf(" --useragent=STRING %s\n", _("HTTP header User-Agent: field")); -@@ -226,15 +232,28 @@ static void usage(void) - exit(1); - } - --static void read_stdin(char **string) -+static void read_file(const char *file, char **string) - { - char *c = malloc(100); -+ FILE *f; -+ -+ if (file) { -+ f = fopen(file, "r"); -+ if (!f) { -+ fprintf(stderr, _("Failed to open password file\n")); -+ exit(1); -+ } -+ } else { -+ file = "stdin"; -+ f = stdin; -+ } -+ - if (!c) { -- fprintf(stderr, _("Allocation failure for string from stdin\n")); -+ fprintf(stderr, _("Allocation failure for string from %s\n"), file); - exit(1); - } -- if (!fgets(c, 100, stdin)) { -- perror(_("fgets (stdin)")); -+ if (!fgets(c, 100, f)) { -+ perror(_("fgets")); - exit(1); - } - -@@ -332,14 +351,20 @@ int main(int argc, char **argv) - cookieonly = 2; - break; - case OPT_COOKIE_ON_STDIN: -- read_stdin(&vpninfo->cookie); -+ optarg = NULL; -+ /* fall through */ -+ case OPT_COOKIE_FILE: -+ read_file(optarg, &vpninfo->cookie); - /* If the cookie is empty, ignore it */ - if (! *vpninfo->cookie) { - vpninfo->cookie = NULL; - } - break; - case OPT_PASSWORD_ON_STDIN: -- read_stdin(&vpninfo->password); -+ optarg = NULL; -+ /* fall through */ -+ case OPT_PASSWORD_FILE: -+ read_file(optarg, &vpninfo->password); - break; - case OPT_NO_PASSWD: - vpninfo->nopasswd = 1; -- 1.8.5.3 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel