summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2015-06-30 08:22:29 +0200
committerAlberto Gonzalez Iniesta <agi@inittab.org>2015-06-30 08:22:29 +0200
commit6149d88c5a2c58a9cc943ca02c36e8ee4e5d1751 (patch)
tree0fdc36dba5e216faf7ade9d7b327090b4a20bd2b /src
parent63862ed15e1abb4b29c5a43b469321c928613c62 (diff)
Imported Upstream version 2.3.7upstream/2.3.7
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in6
-rw-r--r--src/compat/Makefile.in6
-rw-r--r--src/openvpn/Makefile.in6
-rw-r--r--src/openvpn/crypto.c27
-rw-r--r--src/openvpn/crypto.h72
-rw-r--r--src/openvpn/crypto_backend.h12
-rw-r--r--src/openvpn/crypto_openssl.c4
-rw-r--r--src/openvpn/crypto_polarssl.c4
-rw-r--r--src/openvpn/forward.c1
-rw-r--r--src/openvpn/helper.c2
-rw-r--r--src/openvpn/init.c86
-rw-r--r--src/openvpn/init.h2
-rw-r--r--src/openvpn/mtu.h6
-rw-r--r--src/openvpn/openvpn.c4
-rw-r--r--src/openvpn/options.c110
-rw-r--r--src/openvpn/options.h4
-rw-r--r--src/openvpn/pkcs11.c5
-rw-r--r--src/openvpn/pkcs11.h3
-rw-r--r--src/openvpn/route.c23
-rw-r--r--src/openvpn/socket.c12
-rw-r--r--src/openvpn/ssl.c54
-rw-r--r--src/openvpn/ssl.h3
-rw-r--r--src/openvpn/ssl_backend.h2
-rw-r--r--src/openvpn/ssl_common.h16
-rw-r--r--src/openvpn/ssl_openssl.c39
-rw-r--r--src/openvpn/ssl_polarssl.c82
-rw-r--r--src/openvpn/ssl_verify.c6
-rw-r--r--src/openvpn/syshead.h4
-rw-r--r--src/openvpn/tun.c119
-rw-r--r--src/openvpn/tun.h3
-rw-r--r--src/openvpnserv/Makefile.in6
-rw-r--r--src/plugins/Makefile.in6
-rw-r--r--src/plugins/auth-pam/Makefile.in6
-rw-r--r--src/plugins/down-root/Makefile.in6
-rw-r--r--src/plugins/down-root/down-root.c696
35 files changed, 902 insertions, 541 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 2cd864f..d019af9 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -257,6 +257,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -361,9 +363,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/Makefile
+ $(AUTOMAKE) --foreign src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/compat/Makefile.in b/src/compat/Makefile.in
index 4f2fcb3..8c5111e 100644
--- a/src/compat/Makefile.in
+++ b/src/compat/Makefile.in
@@ -249,6 +249,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -368,9 +370,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/compat/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/compat/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/compat/Makefile
+ $(AUTOMAKE) --foreign src/compat/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/openvpn/Makefile.in b/src/openvpn/Makefile.in
index 686f79b..ea9547c 100644
--- a/src/openvpn/Makefile.in
+++ b/src/openvpn/Makefile.in
@@ -319,6 +319,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -470,9 +472,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/ltrc.inc $(am_
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/openvpn/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/openvpn/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/openvpn/Makefile
+ $(AUTOMAKE) --foreign src/openvpn/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index 0a5e83f..aa93a7b 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -403,11 +403,27 @@ crypto_adjust_frame_parameters(struct frame *frame,
bool packet_id,
bool packet_id_long_form)
{
- frame_add_to_extra_frame (frame,
- (packet_id ? packet_id_size (packet_id_long_form) : 0) +
- ((cipher_defined && use_iv) ? cipher_kt_iv_size (kt->cipher) : 0) +
- (cipher_defined ? cipher_kt_block_size (kt->cipher) : 0) + /* worst case padding expansion */
- kt->hmac_length);
+ size_t crypto_overhead = 0;
+
+ if (packet_id)
+ crypto_overhead += packet_id_size (packet_id_long_form);
+
+ if (cipher_defined)
+ {
+ if (use_iv)
+ crypto_overhead += cipher_kt_iv_size (kt->cipher);
+
+ if (cipher_kt_mode_cbc (kt->cipher))
+ /* worst case padding expansion */
+ crypto_overhead += cipher_kt_block_size (kt->cipher);
+ }
+
+ crypto_overhead += kt->hmac_length;
+
+ frame_add_to_extra_frame (frame, crypto_overhead);
+
+ msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %zu bytes",
+ __func__, crypto_overhead);
}
/*
@@ -787,6 +803,7 @@ get_tls_handshake_key (const struct key_type *key_type,
msg (M_INFO,
"Control Channel Authentication: using '%s' as a free-form passphrase file",
passphrase_file);
+ msg (M_WARN, "DEPRECATED OPTION: Using freeform files for tls-auth is deprecated and is not supported in OpenVPN 2.4 or newer versions");
}
}
/* handle key direction */
diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
index bf2f802..e489827 100644
--- a/src/openvpn/crypto.h
+++ b/src/openvpn/crypto.h
@@ -6,7 +6,7 @@
* packet compression.
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
- * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ * Copyright (C) 2010-2014 Fox Crypto B.V. <openvpn@fox-it.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -25,6 +25,76 @@
/**
* @file Data Channel Cryptography Module
+ *
+ * @addtogroup data_crypto Data Channel Crypto module
+ *
+ * @par Crypto packet formats
+ * The Data Channel Crypto module supports a number of crypto modes and
+ * configurable options. The actual packet format depends on these options. A
+ * Data Channel packet can consist of:
+ * - \b Opcode, one byte specifying the packet type (see @ref network_protocol
+ * "Network protocol").
+ * - \b Peer-id, if using the v2 data channel packet format (see @ref
+ * network_protocol "Network protocol").
+ * - \b HMAC, covering the ciphertext IV + ciphertext. The HMAC size depends
+ * on the \c \-\-auth option. If \c \-\-auth \c none is specified, there is no
+ * HMAC at all.
+ * - \b Ciphertext \b IV, if not disabled by \c \-\-no-iv. The IV size depends on
+ * the \c \-\-cipher option.
+ * - \b Packet \b ID, a 32-bit incrementing packet counter that provides replay
+ * protection (if not disabled by \c \-\-no-replay).
+ * - \b Timestamp, a 32-bit timestamp of the current time.
+ * - \b Payload, the plain text network packet to be encrypted (unless
+ * encryption is disabled by using \c \-\-cipher \c none). The payload might
+ * already be compressed (see @ref compression "Compression module").
+ *
+ * @par
+ * This section does not discuss the opcode and peer-id, since those do not
+ * depend on the data channel crypto. See @ref network_protocol
+ * "Network protocol" for more information on those.
+ *
+ * @par
+ * \e Legenda \n
+ * <tt>[ xxx ]</tt> = unprotected \n
+ * <tt>[ - xxx - ]</tt> = authenticated \n
+ * <tt>[ * xxx * ]</tt> = encrypted and authenticated
+ *
+ * @par
+ * <b>CBC data channel cypto format</b> \n
+ * In CBC mode, both TLS-mode and static key mode are supported. The IV
+ * consists of random bits to provide unpredictable IVs. \n
+ * <i>CBC IV format:</i> \n
+ * <tt> [ - random - ] </tt> \n
+ * <i>CBC data channel crypto format in TLS-mode:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ] </tt> \n
+ * <i>CBC data channel crypto format in static key mode:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * timestamp * ]
+ * [ * packet payload * ] </tt>
+ *
+ * @par
+ * <b>CFB/OFB data channel crypto format</b> \n
+ * CFB and OFB modes are only supported in TLS mode. In these modes, the IV
+ * consists of the packet counter and a timestamp. If the IV is more than 8
+ * bytes long, the remaining space is filled with zeroes. The packet counter may
+ * not roll over within a single TLS sessions. This results in a unique IV for
+ * each packet, as required by the CFB and OFB cipher modes.
+ *
+ * @par
+ * <i>CFB/OFB IV format:</i> \n
+ * <tt> [ - packet ID - ] [ - timestamp - ] [ - opt: zero-padding - ] </tt>\n
+ * <i>CFB/OFB data channel crypto format:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet payload * ] </tt>
+ *
+ * @par
+ * <b>No-crypto data channel format</b> \n
+ * In no-crypto mode (\c \-\-cipher \c none is specified), both TLS-mode and
+ * static key mode are supported. No encryption will be performed on the packet,
+ * but packets can still be authenticated. This mode does not require an IV.\n
+ * <i>No-crypto data channel crypto format in TLS-mode:</i> \n
+ * <tt> [ HMAC ] [ - packet ID - ] [ - packet payload - ] </tt> \n
+ * <i>No-crypto data channel crypto format in static key mode:</i> \n
+ * <tt> [ HMAC ] [ - packet ID - ] [ - timestamp - ] [ - packet payload - ] </tt>
+ *
*/
#ifndef CRYPTO_H
diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h
index bc067a7..4e45df0 100644
--- a/src/openvpn/crypto_backend.h
+++ b/src/openvpn/crypto_backend.h
@@ -223,7 +223,7 @@ int cipher_kt_block_size (const cipher_kt_t *cipher_kt);
/**
* Returns the mode that the cipher runs in.
*
- * @param cipher_kt Static cipher parameters
+ * @param cipher_kt Static cipher parameters. May not be NULL.
*
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
@@ -233,22 +233,20 @@ int cipher_kt_mode (const cipher_kt_t *cipher_kt);
/**
* Check if the supplied cipher is a supported CBC mode cipher.
*
- * @param cipher Static cipher parameters. May not be NULL.
+ * @param cipher Static cipher parameters.
*
* @return true iff the cipher is a CBC mode cipher.
*/
-bool cipher_kt_mode_cbc(const cipher_kt_t *cipher)
- __attribute__((nonnull));
+bool cipher_kt_mode_cbc(const cipher_kt_t *cipher);
/**
* Check if the supplied cipher is a supported OFB or CFB mode cipher.
*
- * @param cipher Static cipher parameters. May not be NULL.
+ * @param cipher Static cipher parameters.
*
* @return true iff the cipher is a OFB or CFB mode cipher.
*/
-bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
- __attribute__((nonnull));
+bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher);
/**
diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
index 4067701..348bdee 100644
--- a/src/openvpn/crypto_openssl.c
+++ b/src/openvpn/crypto_openssl.c
@@ -527,7 +527,7 @@ cipher_kt_mode (const EVP_CIPHER *cipher_kt)
bool
cipher_kt_mode_cbc(const cipher_kt_t *cipher)
{
- return cipher_kt_mode(cipher) == OPENVPN_MODE_CBC
+ return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC
#ifdef EVP_CIPH_FLAG_AEAD_CIPHER
/* Exclude AEAD cipher modes, they require a different API */
&& !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
@@ -538,7 +538,7 @@ cipher_kt_mode_cbc(const cipher_kt_t *cipher)
bool
cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
{
- return (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB ||
+ return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB ||
cipher_kt_mode(cipher) == OPENVPN_MODE_CFB)
#ifdef EVP_CIPH_FLAG_AEAD_CIPHER
/* Exclude AEAD cipher modes, they require a different API */
diff --git a/src/openvpn/crypto_polarssl.c b/src/openvpn/crypto_polarssl.c
index 8bf8d8d..af79029 100644
--- a/src/openvpn/crypto_polarssl.c
+++ b/src/openvpn/crypto_polarssl.c
@@ -419,13 +419,13 @@ cipher_kt_mode (const cipher_info_t *cipher_kt)
bool
cipher_kt_mode_cbc(const cipher_kt_t *cipher)
{
- return cipher_kt_mode(cipher) == OPENVPN_MODE_CBC;
+ return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC;
}
bool
cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
{
- return (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB ||
+ return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB ||
cipher_kt_mode(cipher) == OPENVPN_MODE_CFB);
}
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 7f0d083..217fbb3 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -331,6 +331,7 @@ void
check_server_poll_timeout_dowork (struct context *c)
{
event_timeout_reset (&c->c2.server_poll_interval);
+ ASSERT(c->c2.tls_multi);
if (!tls_initial_packet_received (c->c2.tls_multi))
{
msg (M_INFO, "Server poll timeout, restarting");
diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c
index 0ed0b2b..339e2ae 100644
--- a/src/openvpn/helper.c
+++ b/src/openvpn/helper.c
@@ -534,7 +534,7 @@ helper_tcp_nodelay (struct options *o)
}
else
{
- ASSERT (0);
+ o->sockflags |= SF_TCP_NODELAY;
}
}
#endif
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 18f506c..c99e775 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -910,7 +910,6 @@ do_genkey (const struct options * options)
bool
do_persist_tuntap (const struct options *options)
{
-#ifdef ENABLE_FEATURE_TUN_PERSIST
if (options->persist_config)
{
/* sanity check on options for --mktun or --rmtun */
@@ -926,14 +925,21 @@ do_persist_tuntap (const struct options *options)
)
msg (M_FATAL|M_OPTERR,
"options --mktun or --rmtun should only be used together with --dev");
+#ifdef ENABLE_FEATURE_TUN_PERSIST
tuncfg (options->dev, options->dev_type, options->dev_node,
options->persist_mode,
options->username, options->groupname, &options->tuntap_options);
if (options->persist_mode && options->lladdr)
set_lladdr(options->dev, options->lladdr, NULL);
return true;
- }
+#else
+ msg( M_FATAL|M_OPTERR,
+ "options --mktun and --rmtun are not available on your operating "
+ "system. Please check 'man tun' (or 'tap'), whether your system "
+ "supports using 'ifconfig %s create' / 'destroy' to create/remove "
+ "persistant tunnel interfaces.", options->dev );
#endif
+ }
return false;
}
@@ -941,23 +947,20 @@ do_persist_tuntap (const struct options *options)
* Should we become a daemon?
* Return true if we did it.
*/
-static bool
-possibly_become_daemon (const struct options *options, const bool first_time)
+bool
+possibly_become_daemon (const struct options *options)
{
bool ret = false;
- if (first_time && options->daemon)
+ if (options->daemon)
{
ASSERT (!options->inetd);
- if (daemon (options->cd_dir != NULL, options->log) < 0)
+ /* Don't chdir immediately, but the end of the init sequence, if needed */
+ if (daemon (1, options->log) < 0)
msg (M_ERR, "daemon() failed or unsupported");
restore_signal_state ();
if (options->log)
set_std_files_to_null (true);
-#if defined(ENABLE_PKCS11)
- pkcs11_forkFixup ();
-#endif
-
ret = true;
}
return ret;
@@ -1483,6 +1486,9 @@ do_open_tun (struct context *c)
msg (M_INFO, "Preserving previous TUN/TAP instance: %s",
c->c1.tuntap->actual_name);
+ /* explicitly set the ifconfig_* env vars */
+ do_ifconfig_setenv(c->c1.tuntap, c->c2.es);
+
/* run the up script if user specified --up-restart */
if (c->options.up_restart)
run_up_down (c->options.up_script,
@@ -1711,7 +1717,8 @@ pull_permission_mask (const struct context *c)
| OPT_P_MESSAGES
| OPT_P_EXPLICIT_NOTIFY
| OPT_P_ECHO
- | OPT_P_PULL_MODE;
+ | OPT_P_PULL_MODE
+ | OPT_P_PEER_ID;
if (!c->options.route_nopull)
flags |= (OPT_P_ROUTE | OPT_P_IPWIN32);
@@ -1790,21 +1797,39 @@ do_deferred_options (struct context *c, const unsigned int found)
msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified");
if (found & OPT_P_SETENV)
msg (D_PUSH, "OPTIONS IMPORT: environment modified");
+
+#ifdef ENABLE_SSL
+ if (found & OPT_P_PEER_ID)
+ {
+ msg (D_PUSH, "OPTIONS IMPORT: peer-id set");
+ c->c2.tls_multi->use_peer_id = true;
+ c->c2.tls_multi->peer_id = c->options.peer_id;
+ frame_add_to_extra_frame(&c->c2.frame, +3); /* peer-id overhead */
+ if ( !c->options.ce.link_mtu_defined )
+ {
+ frame_add_to_link_mtu(&c->c2.frame, +3);
+ msg (D_PUSH, "OPTIONS IMPORT: adjusting link_mtu to %d",
+ EXPANDED_SIZE(&c->c2.frame));
+ }
+ else
+ {
+ msg (M_WARN, "OPTIONS IMPORT: WARNING: peer-id set, but link-mtu"
+ " fixed by config - reducing tun-mtu to %d, expect"
+ " MTU problems", TUN_MTU_SIZE(&c->c2.frame) );
+ }
+ }
+#endif
}
/*
* Possible hold on initialization
*/
static bool
-do_hold (struct context *c)
+do_hold (void)
{
#ifdef ENABLE_MANAGEMENT
if (management)
{
- /* if c is defined, daemonize before hold */
- if (c && c->options.daemon && management_should_daemonize (management))
- do_init_first_time (c);
-
/* block until management hold is released */
if (management_hold (management))
return true;
@@ -1870,7 +1895,7 @@ socket_restart_pause (struct context *c)
c->persist.restart_sleep_seconds = 0;
/* do managment hold on context restart, i.e. second, third, fourth, etc. initialization */
- if (do_hold (NULL))
+ if (do_hold ())
sec = 0;
if (sec)
@@ -1889,7 +1914,7 @@ do_startup_pause (struct context *c)
if (!c->first_time)
socket_restart_pause (c);
else
- do_hold (NULL); /* do management hold on first context initialization */
+ do_hold (); /* do management hold on first context initialization */
}
/*
@@ -2244,6 +2269,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
to.tmp_dir = options->tmp_dir;
if (options->ccd_exclusive)
to.client_config_dir_exclusive = options->client_config_dir;
+ to.auth_user_pass_file = options->auth_user_pass_file;
#endif
#ifdef ENABLE_X509_TRACK
@@ -2390,6 +2416,17 @@ do_init_frame (struct context *c)
*/
frame_finalize_options (c, NULL);
+ /* packets with peer-id (P_DATA_V2) need 3 extra bytes in frame (on client)
+ * and need link_mtu+3 bytes on socket reception (on server).
+ *
+ * accomodate receive path in f->extra_link
+ * send path in f->extra_buffer (+leave room for alignment)
+ *
+ * f->extra_frame is adjusted when peer-id option is push-received
+ */
+ frame_add_to_extra_link(&c->c2.frame, 3);
+ frame_add_to_extra_buffer(&c->c2.frame, 8);
+
#ifdef ENABLE_FRAGMENT
/*
* Set frame parameter for fragment code. This is necessary because
@@ -2726,7 +2763,7 @@ do_compute_occ_strings (struct context *c)
static void
do_init_first_time (struct context *c)
{
- if (c->first_time && !c->did_we_daemonize && !c->c0)
+ if (c->first_time && !c->c0)
{
struct context_0 *c0;
@@ -2741,12 +2778,9 @@ do_init_first_time (struct context *c)
/* get --writepid file descriptor */
get_pid_file (c->options.writepid, &c0->pid_state);
- /* become a daemon if --daemon */
- c->did_we_daemonize = possibly_become_daemon (&c->options, c->first_time);
-
- /* should we disable paging? */
- if (c->options.mlock && c->did_we_daemonize)
- platform_mlockall (true); /* call again in case we daemonized */
+ /* perform postponed chdir if --daemon */
+ if (c->did_we_daemonize && c->options.cd_dir == NULL)
+ platform_chdir("/");
/* save process ID in a file */
write_pid (&c0->pid_state);
@@ -3187,7 +3221,7 @@ open_management (struct context *c)
}
/* initial management hold, called early, before first context initialization */
- do_hold (c);
+ do_hold ();
if (IS_SIG (c))
{
msg (M_WARN, "Signal received from management interface, exiting");
diff --git a/src/openvpn/init.h b/src/openvpn/init.h
index 5a1d1dc..d1908ed 100644
--- a/src/openvpn/init.h
+++ b/src/openvpn/init.h
@@ -55,6 +55,8 @@ bool do_genkey (const struct options *options);
bool do_persist_tuntap (const struct options *options);
+bool possibly_become_daemon (const struct options *options);
+
void pre_setup (const struct options *options);
void init_instance_handle_signals (struct context *c, const struct env_set *env, const unsigned int flags);
diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h
index 29ec21f..bccd681 100644
--- a/src/openvpn/mtu.h
+++ b/src/openvpn/mtu.h
@@ -258,6 +258,12 @@ frame_headroom (const struct frame *f, const unsigned int flag_mask)
*/
static inline void
+frame_add_to_link_mtu (struct frame *frame, const int increment)
+{
+ frame->link_mtu += increment;
+}
+
+static inline void
frame_add_to_extra_frame (struct frame *frame, const int increment)
{
frame->extra_frame += increment;
diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c
index fd87fc1..2f327f3 100644
--- a/src/openvpn/openvpn.c
+++ b/src/openvpn/openvpn.c
@@ -229,6 +229,10 @@ openvpn_main (int argc, char *argv[])
if (do_test_crypto (&c.options))
break;
+ /* become a daemon if --daemon */
+ if (c.first_time)
+ c.did_we_daemonize = possibly_become_daemon (&c.options);
+
#ifdef ENABLE_MANAGEMENT
/* open management subsystem */
if (!open_management (&c))
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index fa53a17..ff4b07b 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -572,6 +572,7 @@ static const char usage_message[] =
"--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n"
" will accept from the peer. If version is unrecognized and 'or-highest'\n"
" is specified, require max TLS version supported by SSL implementation.\n"
+ "--tls-version-max <version> : sets the maximum TLS version we will use.\n"
#ifndef ENABLE_CRYPTO_POLARSSL
"--pkcs12 file : PKCS#12 file containing local private key, local certificate\n"
" and optionally the root CA certificate.\n"
@@ -739,7 +740,11 @@ static const char usage_message[] =
#ifdef ENABLE_PKCS11
"\n"
"PKCS#11 standalone options:\n"
- "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n"
+#ifdef DEFAULT_PKCS11_MODULE
+ "--show-pkcs11-ids [provider] [cert_private] : Show PKCS#11 available ids.\n"
+#else
+ "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n"
+#endif
" --verb option can be added *BEFORE* this.\n"
#endif /* ENABLE_PKCS11 */
"\n"
@@ -1266,7 +1271,7 @@ option_iroute_ipv6 (struct options *o,
ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc);
- if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ) < 0 )
+ if ( !get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ))
{
msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification",
prefix_str);
@@ -2125,7 +2130,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (options->ssl_flags & SSLF_OPT_VERIFY)
msg (M_USAGE, "--opt-verify requires --mode server");
if (options->server_flags & SF_TCP_NODELAY_HELPER)
- msg (M_USAGE, "--tcp-nodelay requires --mode server");
+ msg (M_WARN, "WARNING: setting tcp-nodelay on the client side will not "
+ "affect the server. To have TCP_NODELAY in both direction use "
+ "tcp-nodelay in the server configuration instead.");
if (options->auth_user_pass_verify_script)
msg (M_USAGE, "--auth-user-pass-verify requires --mode server");
#if PORT_SHARE
@@ -2330,6 +2337,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
MUST_BE_UNDEF (pkcs11_id);
MUST_BE_UNDEF (pkcs11_id_management);
#endif
+#if P2MP
+ MUST_BE_UNDEF (server_poll_timeout);
+#endif
if (pull)
msg (M_USAGE, err, "--pull");
@@ -2393,7 +2403,7 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
{
#ifdef ENABLE_FRAGMENT
if (ce->fragment)
- o->ce.mssfix = ce->fragment;
+ ce->mssfix = ce->fragment;
#else
msg (M_USAGE, "--mssfix must specify a parameter");
#endif
@@ -2463,6 +2473,15 @@ options_postprocess_mutate_invariant (struct options *options)
#endif
}
#endif
+
+#ifdef DEFAULT_PKCS11_MODULE
+ /* If p11-kit is present on the system then load its p11-kit-proxy.so
+ by default if the user asks for PKCS#11 without otherwise specifying
+ the module to use. */
+ if (!options->pkcs11_providers[0] &&
+ (options->pkcs11_id || options->pkcs11_id_management))
+ options->pkcs11_providers[0] = DEFAULT_PKCS11_MODULE;
+#endif
}
static void
@@ -2537,6 +2556,24 @@ options_postprocess_mutate (struct options *o)
else
options_postprocess_mutate_ce (o, &o->ce);
+#ifdef ENABLE_CRYPTOAPI
+ if (o->cryptoapi_cert)
+ {
+ const int tls_version_max =
+ (o->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
+ SSLF_TLS_VERSION_MAX_MASK;
+
+ if (tls_version_max == TLS_VER_UNSPEC || tls_version_max > TLS_VER_1_1)
+ {
+ msg(M_WARN, "Warning: cryptapicert used, setting maximum TLS "
+ "version to 1.1.");
+ o->ssl_flags &= ~(SSLF_TLS_VERSION_MAX_MASK <<
+ SSLF_TLS_VERSION_MAX_SHIFT);
+ o->ssl_flags |= (TLS_VER_1_1 << SSLF_TLS_VERSION_MAX_SHIFT);
+ }
+ }
+#endif /* ENABLE_CRYPTOAPI */
+
#if P2MP
/*
* Save certain parms before modifying options via --pull
@@ -3718,12 +3755,21 @@ static char *
read_inline_file (struct in_src *is, const char *close_tag, struct gc_arena *gc)
{
char line[OPTION_LINE_SIZE];
- struct buffer buf = alloc_buf (10000);
+ struct buffer buf = alloc_buf (8*OPTION_LINE_SIZE);
char *ret;
while (in_src_get (is, line, sizeof (line)))
{
if (!strncmp (line, close_tag, strlen (close_tag)))
break;
+ if (!buf_safe (&buf, strlen(line)))
+ {
+ /* Increase buffer size */
+ struct buffer buf2 = alloc_buf (buf.capacity * 2);
+ ASSERT (buf_copy (&buf2, &buf));
+ buf_clear (&buf);
+ free_buf (&buf);
+ buf = buf2;
+ }
buf_printf (&buf, "%s", line);
}
ret = string_alloc (BSTR (&buf), gc);
@@ -6570,14 +6616,29 @@ add_option (struct options *options,
{
int ver;
VERIFY_PERMISSION (OPT_P_GENERAL);
- ver = tls_version_min_parse(p[1], p[2]);
+ ver = tls_version_parse(p[1], p[2]);
if (ver == TLS_VER_BAD)
{
msg (msglevel, "unknown tls-version-min parameter: %s", p[1]);
goto err;
}
- options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT);
- options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT);
+ options->ssl_flags &=
+ ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT);
+ options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT);
+ }
+ else if (streq (p[0], "tls-version-max") && p[1])
+ {
+ int ver;
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ ver = tls_version_parse(p[1], NULL);
+ if (ver == TLS_VER_BAD)
+ {
+ msg (msglevel, "unknown tls-version-max parameter: %s", p[1]);
+ goto err;
+ }
+ options->ssl_flags &=
+ ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT);
+ options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT);
}
#ifndef ENABLE_CRYPTO_POLARSSL
else if (streq (p[0], "pkcs12") && p[1])
@@ -6903,11 +6964,34 @@ add_option (struct options *options,
#endif /* ENABLE_SSL */
#endif /* ENABLE_CRYPTO */
#ifdef ENABLE_PKCS11
- else if (streq (p[0], "show-pkcs11-ids") && p[1])
+ else if (streq (p[0], "show-pkcs11-ids"))
{
char *provider = p[1];
bool cert_private = (p[2] == NULL ? false : ( atoi (p[2]) != 0 ));
+#ifdef DEFAULT_PKCS11_MODULE
+ if (!provider)
+ provider = DEFAULT_PKCS11_MODULE;
+ else if (!p[2])
+ {
+ char *endp = NULL;
+ int i = strtol(provider, &endp, 10);
+
+ if (*endp == 0)
+ {
+ /* There was one argument, and it was purely numeric.
+ Interpret it as the cert_private argument */
+ provider = DEFAULT_PKCS11_MODULE;
+ cert_private = i;
+ }
+ }
+#else
+ if (!provider)
+ {
+ msg (msglevel, "--show-pkcs11-ids requires a provider parameter");
+ goto err;
+ }
+#endif
VERIFY_PERMISSION (OPT_P_GENERAL);
set_debug_level (options->verbosity, SDL_CONSTRAIN);
@@ -6966,7 +7050,6 @@ add_option (struct options *options,
options->pkcs11_id_management = true;
}
#endif
-#ifdef ENABLE_FEATURE_TUN_PERSIST
else if (streq (p[0], "rmtun"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
@@ -6979,7 +7062,12 @@ add_option (struct options *options,
options->persist_config = true;
options->persist_mode = 1;
}
-#endif
+ else if (streq (p[0], "peer-id") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_PEER_ID);
+ options->use_peer_id = true;
+ options->peer_id = atoi(p[1]);
+ }
else
{
int i;
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 2c18838..af9a47f 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -594,6 +594,9 @@ struct options
bool show_net_up;
int route_method;
#endif
+
+ bool use_peer_id;
+ uint32_t peer_id;
};
#define streq(x, y) (!strcmp((x), (y)))
@@ -629,6 +632,7 @@ struct options
#define OPT_P_SOCKBUF (1<<25)
#define OPT_P_SOCKFLAGS (1<<26)
#define OPT_P_CONNECTION (1<<27)
+#define OPT_P_PEER_ID (1<<28)
#define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c
index 3a15ef6..a1f13c5 100644
--- a/src/openvpn/pkcs11.c
+++ b/src/openvpn/pkcs11.c
@@ -336,11 +336,6 @@ pkcs11_terminate () {
);
}
-void
-pkcs11_forkFixup () {
- pkcs11h_forkFixup ();
-}
-
bool
pkcs11_addProvider (
const char * const provider,
diff --git a/src/openvpn/pkcs11.h b/src/openvpn/pkcs11.h
index 4261871..b49401c 100644
--- a/src/openvpn/pkcs11.h
+++ b/src/openvpn/pkcs11.h
@@ -38,9 +38,6 @@ pkcs11_initialize (
void
pkcs11_terminate ();
-void
-pkcs11_forkFixup ();
-
bool
pkcs11_addProvider (
const char * const provider,
diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index cc85e4d..2acfbe8 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -838,7 +838,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
if ( rl && rl->flags & RG_ENABLE )
{
- if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT))
+ if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT) && (rl->flags & RG_REROUTE_GW))
{
msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
}
@@ -2601,7 +2601,7 @@ get_default_gateway (struct route_gateway_info *rgi)
gc_free (&gc);
}
-#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)||defined(TARGET_SOLARIS)
#include <sys/types.h>
#include <sys/socket.h>
@@ -2629,6 +2629,8 @@ get_default_gateway (struct route_gateway_info *rgi)
struct sockaddr *gate = NULL, *sa;
struct rt_msghdr *rtm_aux;
+#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+
#define NEXTADDR(w, u) \
if (rtm_addrs & (w)) {\
l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
@@ -2636,6 +2638,18 @@ get_default_gateway (struct route_gateway_info *rgi)
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+#else /* TARGET_SOLARIS */
+
+#define NEXTADDR(w, u) \
+ if (rtm_addrs & (w)) {\
+ l = ROUNDUP(sizeof(struct sockaddr_in)); memmove(cp, &(u), l); cp += l;\
+ }
+
+#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in)))
+
+#endif
+
+
#define rtm m_rtmsg.m_rtm
CLEAR(*rgi);
@@ -2655,9 +2669,12 @@ get_default_gateway (struct route_gateway_info *rgi)
rtm.rtm_addrs = rtm_addrs;
so_dst.sa_family = AF_INET;
- so_dst.sa_len = sizeof(struct sockaddr_in);
so_mask.sa_family = AF_INET;
+
+#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+ so_dst.sa_len = sizeof(struct sockaddr_in);
so_mask.sa_len = sizeof(struct sockaddr_in);
+#endif
NEXTADDR(RTA_DST, so_dst);
NEXTADDR(RTA_NETMASK, so_mask);
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 6e68c18..0424c0b 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -137,10 +137,6 @@ openvpn_getaddrinfo (unsigned int flags,
ASSERT(res);
-#if defined(HAVE_RES_INIT)
- res_init ();
-#endif
-
if (!hostname)
hostname = "::";
@@ -197,6 +193,9 @@ openvpn_getaddrinfo (unsigned int flags,
*/
while (true)
{
+#ifndef WIN32
+ res_init ();
+#endif
/* try hostname lookup */
hints.ai_flags = 0;
dmsg (D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d",
@@ -215,10 +214,13 @@ openvpn_getaddrinfo (unsigned int flags,
}
else
{
+ /* turn success into failure (interrupted syscall) */
if (0 == status) {
ASSERT(res);
freeaddrinfo(*res);
- res = NULL;
+ *res = NULL;
+ status = EAI_AGAIN; /* = temporary failure */
+ errno = EINTR;
}
goto done;
}
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index ac6818e..a17c738 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -271,7 +271,7 @@ tls_get_cipher_name_pair (const char * cipher_name, size_t len) {
* Max number of bytes we will add
* for data structures common to both
* data and control channel packets.
- * (opcode only).
+ * (opcode only).
*/
void
tls_adjust_frame_parameters(struct frame *frame)
@@ -458,7 +458,7 @@ ssl_put_auth_challenge (const char *cr_str)
* return tls_version_max().
*/
int
-tls_version_min_parse(const char *vstr, const char *extra)
+tls_version_parse(const char *vstr, const char *extra)
{
const int max_version = tls_version_max();
if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version)
@@ -627,6 +627,8 @@ packet_opcode_name (int op)
return "P_ACK_V1";
case P_DATA_V1:
return "P_DATA_V1";
+ case P_DATA_V2:
+ return "P_DATA_V2";
default:
return "P_???";
}
@@ -1053,6 +1055,9 @@ tls_multi_init (struct tls_options *tls_options)
ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK];
ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];
+ /* By default not use P_DATA_V2 */
+ ret->use_peer_id = false;
+
return ret;
}
@@ -1828,6 +1833,8 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
#ifdef ENABLE_LZO_STUB
buf_printf (&out, "IV_LZO_STUB=1\n");
#endif
+ /* support for P_DATA_V2 */
+ buf_printf(&out, "IV_PROTO=2\n");
if (session->opt->push_peer_info_detail >= 2)
{
@@ -1898,9 +1905,9 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
if (auth_user_pass_enabled)
{
#ifdef ENABLE_CLIENT_CR
- auth_user_pass_setup (NULL, session->opt->sci);
+ auth_user_pass_setup (session->opt->auth_user_pass_file, session->opt->sci);
#else
- auth_user_pass_setup (NULL, NULL);
+ auth_user_pass_setup (session->opt->auth_user_pass_file, NULL);
#endif
if (!write_string (buf, auth_user_pass.username, -1))
goto error;
@@ -2028,7 +2035,11 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
ASSERT (session->opt->key_method == 2);
/* discard leading uint32 */
- ASSERT (buf_advance (buf, 4));
+ if (!buf_advance (buf, 4)) {
+ msg (D_TLS_ERRORS, "TLS ERROR: Plaintext buffer too short (%d bytes).",
+ buf->len);
+ goto error;
+ }
/* get key method */
key_method_flags = buf_read_u8 (buf);
@@ -2777,8 +2788,9 @@ tls_pre_decrypt (struct tls_multi *multi,
key_id = c & P_KEY_ID_MASK;
}
- if (op == P_DATA_V1)
- { /* data channel packet */
+ if ((op == P_DATA_V1) || (op == P_DATA_V2))
+ {
+ /* data channel packet */
for (i = 0; i < KEY_SCAN_SIZE; ++i)
{
struct key_state *ks = multi->key_scan[i];
@@ -2810,7 +2822,19 @@ tls_pre_decrypt (struct tls_multi *multi,
opt->pid_persist = NULL;
opt->flags &= multi->opt.crypto_flags_and;
opt->flags |= multi->opt.crypto_flags_or;
+
ASSERT (buf_advance (buf, 1));
+ if (op == P_DATA_V2)
+ {
+ if (buf->len < 4)
+ {
+ msg (D_TLS_ERRORS, "Protocol error: received P_DATA_V2 from %s but length is < 4",
+ print_link_socket_actual (from, &gc));
+ goto error;
+ }
+ ASSERT (buf_advance (buf, 3));
+ }
+
++ks->n_packets;
ks->n_bytes += buf->len;
dmsg (D_TLS_KEYSELECT,
@@ -3375,14 +3399,24 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf)
{
struct key_state *ks;
uint8_t *op;
+ uint32_t peer;
ks = multi->save_ks;
multi->save_ks = NULL;
if (buf->len > 0)
{
ASSERT (ks);
- ASSERT (op = buf_prepend (buf, 1));
- *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
+
+ if (!multi->opt.server && multi->use_peer_id)
+ {
+ peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF));
+ ASSERT (buf_write_prepend (buf, &peer, 4));
+ }
+ else
+ {
+ ASSERT (op = buf_prepend (buf, 1));
+ *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
+ }
++ks->n_packets;
ks->n_bytes += buf->len;
}
@@ -3489,7 +3523,7 @@ protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc)
key_id = c & P_KEY_ID_MASK;
buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id);
- if (op == P_DATA_V1)
+ if ((op == P_DATA_V1) || (op == P_DATA_V2))
goto print_data;
/*
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index cd7cae2..6a14768 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -61,6 +61,7 @@
#define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */
#define P_ACK_V1 5 /* acknowledgement for packets received */
#define P_DATA_V1 6 /* data channel packet */
+#define P_DATA_V2 9 /* data channel packet with peer-id */
/* indicates key_method >= 2 */
#define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */
@@ -68,7 +69,7 @@
/* define the range of legal opcodes */
#define P_FIRST_OPCODE 1
-#define P_LAST_OPCODE 8
+#define P_LAST_OPCODE 9
/* Should we aggregate TLS
* acknowledgements, and tack them onto
diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h
index fc23175..6d47bd0 100644
--- a/src/openvpn/ssl_backend.h
+++ b/src/openvpn/ssl_backend.h
@@ -114,7 +114,7 @@ void tls_clear_error();
#define TLS_VER_1_0 1
#define TLS_VER_1_1 2
#define TLS_VER_1_2 3
-int tls_version_min_parse(const char *vstr, const char *extra);
+int tls_version_parse(const char *vstr, const char *extra);
/**
* Return the maximum TLS version (as a TLS_VER_x constant)
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index 66b6492..449172d 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -277,6 +277,7 @@ struct tls_options
const char *auth_user_pass_verify_script;
bool auth_user_pass_verify_script_via_file;
const char *tmp_dir;
+ const char *auth_user_pass_file;
/* use the client-config-dir as a positive authenticator */
const char *client_config_dir_exclusive;
@@ -291,8 +292,10 @@ struct tls_options
# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2)
# define SSLF_OPT_VERIFY (1<<4)
# define SSLF_CRL_VERIFY_DIR (1<<5)
-# define SSLF_TLS_VERSION_SHIFT 6
-# define SSLF_TLS_VERSION_MASK 0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MIN_SHIFT 6
+# define SSLF_TLS_VERSION_MIN_MASK 0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MAX_SHIFT 10
+# define SSLF_TLS_VERSION_MAX_MASK 0xF /* (uses bit positions 10 to 13) */
unsigned int ssl_flags;
#ifdef MANAGEMENT_DEF_AUTH
@@ -488,6 +491,10 @@ struct tls_multi
time_t tas_last;
#endif
+ /* For P_DATA_V2 */
+ uint32_t peer_id;
+ bool use_peer_id;
+
/*
* Our session objects.
*/
@@ -498,4 +505,9 @@ struct tls_multi
};
+#define SHOW_TLS_CIPHER_LIST_WARNING \
+ "Be aware that that whether a cipher suite in this list can actually work\n" \
+ "depends on the specific setup of both peers. See the man page entries of\n" \
+ "--tls-cipher and --show-tls for more details.\n\n"
+
#endif /* SSL_COMMON_H_ */
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index e77b736..be33caa 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -121,14 +121,15 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength)
void
tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
{
- const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
+ const int tls_version_max =
+ (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK;
ASSERT(NULL != ctx);
- if (tls_version_min > TLS_VER_UNSPEC)
- ctx->ctx = SSL_CTX_new (SSLv23_server_method ());
- else
+ if (tls_version_max == TLS_VER_1_0)
ctx->ctx = SSL_CTX_new (TLSv1_server_method ());
+ else
+ ctx->ctx = SSL_CTX_new (SSLv23_server_method ());
if (ctx->ctx == NULL)
msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method");
@@ -139,14 +140,15 @@ tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
void
tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
{
- const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
+ const int tls_version_max =
+ (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK;
ASSERT(NULL != ctx);
- if (tls_version_min > TLS_VER_UNSPEC)
- ctx->ctx = SSL_CTX_new (SSLv23_client_method ());
- else
+ if (tls_version_max == TLS_VER_1_0)
ctx->ctx = SSL_CTX_new (TLSv1_client_method ());
+ else
+ ctx->ctx = SSL_CTX_new (SSLv23_client_method ());
if (ctx->ctx == NULL)
msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method");
@@ -218,17 +220,28 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)
/* process SSL options including minimum TLS version we will accept from peer */
{
long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
- const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
- if (tls_version_min > TLS_VER_1_0)
+ const int tls_ver_min =
+ (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
+ int tls_ver_max =
+ (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK;
+
+ if (tls_ver_max <= TLS_VER_UNSPEC)
+ tls_ver_max = tls_version_max();
+
+ if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0)
sslopt |= SSL_OP_NO_TLSv1;
#ifdef SSL_OP_NO_TLSv1_1
- if (tls_version_min > TLS_VER_1_1)
+ if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1)
sslopt |= SSL_OP_NO_TLSv1_1;
#endif
#ifdef SSL_OP_NO_TLSv1_2
- if (tls_version_min > TLS_VER_1_2)
+ if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2)
sslopt |= SSL_OP_NO_TLSv1_2;
#endif
+#ifdef SSL_OP_NO_COMPRESSION
+ /* Disable compression - flag not available in OpenSSL 0.9.8 */
+ sslopt |= SSL_OP_NO_COMPRESSION;
+#endif
SSL_CTX_set_options (ctx->ctx, sslopt);
}
@@ -1327,7 +1340,7 @@ show_available_tls_ciphers (const char *cipher_list)
}
}
- printf ("\n");
+ printf ("\n" SHOW_TLS_CIPHER_LIST_WARNING);
SSL_free (ssl);
SSL_CTX_free (tls_ctx.ctx);
diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
index 5718c8c..30c7395 100644
--- a/src/openvpn/ssl_polarssl.c
+++ b/src/openvpn/ssl_polarssl.c
@@ -654,6 +654,40 @@ tls_version_max(void)
#endif
}
+/**
+ * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and
+ * minor ssl version number).
+ *
+ * @param tls_ver The tls-version variable to convert.
+ * @param major Returns the TLS major version in polarssl format.
+ * Must be a valid pointer.
+ * @param minor Returns the TLS minor version in polarssl format.
+ * Must be a valid pointer.
+ */
+static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) {
+ ASSERT(major);
+ ASSERT(minor);
+
+ switch (tls_ver)
+ {
+ case TLS_VER_1_0:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_1;
+ break;
+ case TLS_VER_1_1:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_2;
+ break;
+ case TLS_VER_1_2:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_3;
+ break;
+ default:
+ msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver);
+ break;
+ }
+}
+
void key_state_ssl_init(struct key_state_ssl *ks_ssl,
const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)
{
@@ -712,30 +746,32 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
/* Initialize minimum TLS version */
{
- const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
- int polar_major;
- int polar_minor;
- switch (tls_version_min)
+ const int tls_version_min =
+ (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) &
+ SSLF_TLS_VERSION_MIN_MASK;
+
+ /* default to TLS 1.0 */
+ int major = SSL_MAJOR_VERSION_3;
+ int minor = SSL_MINOR_VERSION_1;
+
+ if (tls_version_min > TLS_VER_UNSPEC)
+ tls_version_to_major_minor(tls_version_min, &major, &minor);
+
+ ssl_set_min_version(ks_ssl->ctx, major, minor);
+ }
+
+ /* Initialize maximum TLS version */
+ {
+ const int tls_version_max =
+ (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
+ SSLF_TLS_VERSION_MAX_MASK;
+
+ if (tls_version_max > TLS_VER_UNSPEC)
{
- case TLS_VER_1_0:
- default:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_1;
- break;
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2)
- case TLS_VER_1_1:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_2;
- break;
-#endif
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3)
- case TLS_VER_1_2:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_3;
- break;
-#endif
+ int major, minor;
+ tls_version_to_major_minor(tls_version_max, &major, &minor);
+ ssl_set_max_version(ks_ssl->ctx, major, minor);
}
- ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
}
/* Initialise BIOs */
@@ -1059,7 +1095,7 @@ show_available_tls_ciphers (const char *cipher_list)
printf ("%s\n", ssl_get_ciphersuite_name(*ciphers));
ciphers++;
}
- printf ("\n");
+ printf ("\n" SHOW_TLS_CIPHER_LIST_WARNING);
}
void
diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c
index c90c2c3..9693b81 100644
--- a/src/openvpn/ssl_verify.c
+++ b/src/openvpn/ssl_verify.c
@@ -596,7 +596,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep
{
result_t ret = FAILURE;
char *subject = NULL;
- char common_name[TLS_USERNAME_LEN] = {0};
+ char common_name[TLS_USERNAME_LEN+1] = {0}; /* null-terminated */
const struct tls_options *opt;
struct gc_arena gc = gc_new();
@@ -619,7 +619,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep
string_replace_leading (subject, '-', '_');
/* extract the username (default is CN) */
- if (SUCCESS != x509_get_username (common_name, TLS_USERNAME_LEN,
+ if (SUCCESS != x509_get_username (common_name, sizeof(common_name),
opt->x509_username_field, cert))
{
if (!cert_depth)
@@ -1165,7 +1165,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
s2 = verify_user_pass_script (session, up);
/* check sizing of username if it will become our common name */
- if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN)
+ if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) > TLS_USERNAME_LEN)
{
msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN);
s1 = OPENVPN_PLUGIN_FUNC_ERROR;
diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h
index f957a10..7075b96 100644
--- a/src/openvpn/syshead.h
+++ b/src/openvpn/syshead.h
@@ -214,10 +214,6 @@
#ifdef TARGET_LINUX
-#if defined(HAVE_NETINET_IF_ETHER_H)
-#include <netinet/if_ether.h>
-#endif
-
#ifdef HAVE_LINUX_IF_TUN_H
#include <linux/if_tun.h>
#endif
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index ba4b15e..285e774 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -396,6 +396,49 @@ is_tun_p2p (const struct tuntap *tt)
}
/*
+ * Set the ifconfig_* environment variables, both for IPv4 and IPv6
+ */
+void
+do_ifconfig_setenv (const struct tuntap *tt, struct env_set *es)
+{
+ struct gc_arena gc = gc_new ();
+ const char *ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
+ const char *ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
+
+ /*
+ * Set environmental variables with ifconfig parameters.
+ */
+ if (tt->did_ifconfig_setup)
+ {
+ bool tun = is_tun_p2p (tt);
+
+ setenv_str (es, "ifconfig_local", ifconfig_local);
+ if (tun)
+ {
+ setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask);
+ }
+ else
+ {
+ const char *ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
+ setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask);
+ setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast);
+ }
+ }
+
+ if (tt->did_ifconfig_ipv6_setup)
+ {
+ const char *ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
+ const char *ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
+
+ setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
+ setenv_int (es, "ifconfig_ipv6_netbits", tt->netbits_ipv6);
+ setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
+ }
+
+ gc_free (&gc);
+}
+
+/*
* Init tun/tap object.
*
* Set up tuntap structure for ifconfig,
@@ -427,9 +470,6 @@ init_tun (const char *dev, /* --dev option */
if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
{
bool tun = false;
- const char *ifconfig_local = NULL;
- const char *ifconfig_remote_netmask = NULL;
- const char *ifconfig_broadcast = NULL;
/*
* We only handle TUN/TAP devices here, not --dev null devices.
@@ -491,44 +531,19 @@ init_tun (const char *dev, /* --dev option */
}
/*
- * Set ifconfig parameters
- */
- ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
- ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
-
- /*
* If TAP-style interface, generate broadcast address.
*/
if (!tun)
{
tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask);
- ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
}
- /*
- * Set environmental variables with ifconfig parameters.
- */
- if (es)
- {
- setenv_str (es, "ifconfig_local", ifconfig_local);
- if (tun)
- {
- setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask);
- }
- else
- {
- setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask);
- setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast);
- }
- }
tt->did_ifconfig_setup = true;
}
if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm)
{
- const char *ifconfig_ipv6_local = NULL;
- const char *ifconfig_ipv6_remote = NULL;
/*
* Convert arguments to binary IPv6 addresses.
@@ -541,24 +556,14 @@ init_tun (const char *dev, /* --dev option */
}
tt->netbits_ipv6 = ifconfig_ipv6_netbits_parm;
- /*
- * Set ifconfig parameters
- */
- ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
- ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
-
- /*
- * Set environmental variables with ifconfig parameters.
- */
- if (es)
- {
- setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
- setenv_int (es, "ifconfig_ipv6_netbits", tt->netbits_ipv6);
- setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
- }
tt->did_ifconfig_ipv6_setup = true;
}
+ /*
+ * Set environmental variables with ifconfig parameters.
+ */
+ if (es) do_ifconfig_setenv(tt, es);
+
gc_free (&gc);
return tt;
}
@@ -618,6 +623,28 @@ void delete_route_connected_v6_net(struct tuntap * tt,
}
#endif
+#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+/* we can't use true subnet mode on tun on all platforms, as that
+ * conflicts with IPv6 (wants to use ND then, which we don't do),
+ * but the OSes want "a remote address that is different from ours"
+ * - so we construct one, normally the first in the subnet, but if
+ * this is the same as ours, use the second one.
+ * The actual address does not matter at all, as the tun interface
+ * is still point to point and no layer 2 resolution is done...
+ */
+
+char *
+create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc )
+{
+ in_addr_t remote;
+
+ remote = (tt->local & tt->remote_netmask) +1;
+
+ if ( remote == tt->local ) remote ++;
+
+ return print_in_addr_t (remote, 0, &gc);
+}
+#endif
/* execute the ifconfig command through the shell */
void
@@ -1114,7 +1141,7 @@ do_ifconfig (struct tuntap *tt,
IFCONFIG_PATH,
actual,
ifconfig_local,
- ifconfig_local,
+ create_arbitrary_remote( tt, &gc ),
tun_mtu,
ifconfig_remote_netmask
);
@@ -1710,9 +1737,9 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len)
pi.flags = 0;
if(iph->version == 6)
- pi.proto = htons(ETH_P_IPV6);
+ pi.proto = htons(OPENVPN_ETH_P_IPV6);
else
- pi.proto = htons(ETH_P_IP);
+ pi.proto = htons(OPENVPN_ETH_P_IPV4);
vect[0].iov_len = sizeof(pi);
vect[0].iov_base = &pi;
diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
index 1931c52..7089f7c 100644
--- a/src/openvpn/tun.h
+++ b/src/openvpn/tun.h
@@ -241,6 +241,9 @@ void init_tun_post (struct tuntap *tt,
const struct frame *frame,
const struct tuntap_options *options);
+void do_ifconfig_setenv (const struct tuntap *tt,
+ struct env_set *es);
+
void do_ifconfig (struct tuntap *tt,
const char *actual, /* actual device name */
int tun_mtu,
diff --git a/src/openvpnserv/Makefile.in b/src/openvpnserv/Makefile.in
index 272fd90..495b569 100644
--- a/src/openvpnserv/Makefile.in
+++ b/src/openvpnserv/Makefile.in
@@ -261,6 +261,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -376,9 +378,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/ltrc.inc $(am_
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/openvpnserv/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/openvpnserv/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/openvpnserv/Makefile
+ $(AUTOMAKE) --foreign src/openvpnserv/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
index 8b73edc..de927c9 100644
--- a/src/plugins/Makefile.in
+++ b/src/plugins/Makefile.in
@@ -257,6 +257,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -361,9 +363,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/plugins/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/plugins/Makefile
+ $(AUTOMAKE) --foreign src/plugins/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/plugins/auth-pam/Makefile.in b/src/plugins/auth-pam/Makefile.in
index 1e1547a..aee6561 100644
--- a/src/plugins/auth-pam/Makefile.in
+++ b/src/plugins/auth-pam/Makefile.in
@@ -281,6 +281,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -404,9 +406,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/plugins/auth-pam/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/auth-pam/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/plugins/auth-pam/Makefile
+ $(AUTOMAKE) --foreign src/plugins/auth-pam/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/plugins/down-root/Makefile.in b/src/plugins/down-root/Makefile.in
index 26c4912..f19e012 100644
--- a/src/plugins/down-root/Makefile.in
+++ b/src/plugins/down-root/Makefile.in
@@ -280,6 +280,8 @@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@
OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
+P11KIT_CFLAGS = @P11KIT_CFLAGS@
+P11KIT_LIBS = @P11KIT_LIBS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -398,9 +400,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/plugins/down-root/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/down-root/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/plugins/down-root/Makefile
+ $(AUTOMAKE) --foreign src/plugins/down-root/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/src/plugins/down-root/down-root.c b/src/plugins/down-root/down-root.c
index d51d0e5..6931bec 100644
--- a/src/plugins/down-root/down-root.c
+++ b/src/plugins/down-root/down-root.c
@@ -5,7 +5,8 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2013 David Sommerseth <davids@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -40,14 +41,16 @@
#include <fcntl.h>
#include <signal.h>
#include <syslog.h>
+#include <errno.h>
+#include <err.h>
#include <openvpn-plugin.h>
#define DEBUG(verb) ((verb) >= 7)
/* Command codes for foreground -> background communication */
-#define COMMAND_RUN_SCRIPT 0
-#define COMMAND_EXIT 1
+#define COMMAND_RUN_SCRIPT 1
+#define COMMAND_EXIT 2
/* Response codes for background -> foreground communication */
#define RESPONSE_INIT_SUCCEEDED 10
@@ -56,24 +59,24 @@
#define RESPONSE_SCRIPT_FAILED 13
/* Background process function */
-static void down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb);
+static void down_root_server (const int fd, char * const * argv, char * const *envp, const int verb);
/*
* Plugin state, used by foreground
*/
struct down_root_context
{
- /* Foreground's socket to background process */
- int foreground_fd;
+ /* Foreground's socket to background process */
+ int foreground_fd;
- /* Process ID of background process */
- pid_t background_pid;
+ /* Process ID of background process */
+ pid_t background_pid;
- /* Verbosity level of OpenVPN */
- int verb;
+ /* Verbosity level of OpenVPN */
+ int verb;
- /* down command */
- char *command;
+ /* down command */
+ char **command;
};
/*
@@ -84,21 +87,21 @@ struct down_root_context
static const char *
get_env (const char *name, const char *envp[])
{
- if (envp)
+ if (envp)
{
- int i;
- const int namelen = strlen (name);
- for (i = 0; envp[i]; ++i)
- {
- if (!strncmp (envp[i], name, namelen))
- {
- const char *cp = envp[i] + namelen;
- if (*cp == '=')
- return cp + 1;
- }
- }
+ int i;
+ const int namelen = strlen (name);
+ for (i = 0; envp[i]; ++i)
+ {
+ if (!strncmp (envp[i], name, namelen))
+ {
+ const char *cp = envp[i] + namelen;
+ if (*cp == '=')
+ return cp + 1;
+ }
+ }
}
- return NULL;
+ return NULL;
}
/*
@@ -107,13 +110,13 @@ get_env (const char *name, const char *envp[])
static int
string_array_len (const char *array[])
{
- int i = 0;
- if (array)
+ int i = 0;
+ if (array)
{
- while (array[i])
- ++i;
+ while (array[i])
+ ++i;
}
- return i;
+ return i;
}
/*
@@ -123,23 +126,23 @@ string_array_len (const char *array[])
static int
recv_control (int fd)
{
- unsigned char c;
- const ssize_t size = read (fd, &c, sizeof (c));
- if (size == sizeof (c))
- return c;
- else
- return -1;
+ unsigned char c;
+ const ssize_t size = read (fd, &c, sizeof (c));
+ if (size == sizeof (c))
+ return c;
+ else
+ return -1;
}
static int
send_control (int fd, int code)
{
- unsigned char c = (unsigned char) code;
- const ssize_t size = write (fd, &c, sizeof (c));
- if (size == sizeof (c))
- return (int) size;
- else
- return -1;
+ unsigned char c = (unsigned char) code;
+ const ssize_t size = write (fd, &c, sizeof (c));
+ if (size == sizeof (c))
+ return (int) size;
+ else
+ return -1;
}
/*
@@ -150,22 +153,22 @@ send_control (int fd, int code)
static void
daemonize (const char *envp[])
{
- const char *daemon_string = get_env ("daemon", envp);
- if (daemon_string && daemon_string[0] == '1')
+ const char *daemon_string = get_env ("daemon", envp);
+ if (daemon_string && daemon_string[0] == '1')
{
- const char *log_redirect = get_env ("daemon_log_redirect", envp);
- int fd = -1;
- if (log_redirect && log_redirect[0] == '1')
- fd = dup (2);
- if (daemon (0, 0) < 0)
- {
- fprintf (stderr, "DOWN-ROOT: daemonization failed\n");
- }
- else if (fd >= 3)
- {
- dup2 (fd, 2);
- close (fd);
- }
+ const char *log_redirect = get_env ("daemon_log_redirect", envp);
+ int fd = -1;
+ if (log_redirect && log_redirect[0] == '1')
+ fd = dup (2);
+ if (daemon (0, 0) < 0)
+ {
+ warn ("DOWN-ROOT: daemonization failed");
+ }
+ else if (fd >= 3)
+ {
+ dup2 (fd, 2);
+ close (fd);
+ }
}
}
@@ -182,12 +185,12 @@ daemonize (const char *envp[])
static void
close_fds_except (int keep)
{
- int i;
- closelog ();
- for (i = 3; i <= 100; ++i)
+ int i;
+ closelog ();
+ for (i = 3; i <= 100; ++i)
{
- if (i != keep)
- close (i);
+ if (i != keep)
+ close (i);
}
}
@@ -198,254 +201,261 @@ close_fds_except (int keep)
static void
set_signals (void)
{
- signal (SIGTERM, SIG_DFL);
+ signal (SIGTERM, SIG_DFL);
- signal (SIGINT, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- signal (SIGUSR1, SIG_IGN);
- signal (SIGUSR2, SIG_IGN);
- signal (SIGPIPE, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+ signal (SIGPIPE, SIG_IGN);
}
-/*
- * convert system() return into a success/failure value
- */
-int
-system_ok (int stat)
+
+static void
+free_context (struct down_root_context *context)
{
-#ifdef WIN32
- return stat == 0;
-#else
- return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
-#endif
+ if (context)
+ {
+ if (context->command)
+ {
+ free (context->command);
+ }
+ free (context);
+ }
}
-static char *
-build_command_line (const char *argv[])
+/* Run the script using execve(). As execve() replaces the
+ * current process with the new one, do a fork first before
+ * calling execve()
+ */
+static int
+run_script(char * const *argv, char * const *envp)
{
- int size = 0;
- int n = 0;
- int i;
- char *string;
+ pid_t pid;
+ int ret = 0;
- /* precompute size */
- if (argv)
+ pid = fork();
+ if (pid == (pid_t)0) /* child side */
{
- for (i = 0; argv[i]; ++i)
- {
- size += (strlen (argv[i]) + 1); /* string length plus trailing space */
- ++n;
- }
+ execve(argv[0], argv, envp);
+ /* If execve() fails to run, exit child with exit code 127 */
+ err(127, "DOWN-ROOT: Failed execute: %s", argv[0]);
}
- ++size; /* for null terminator */
-
- /* allocate memory */
- string = (char *) malloc (size);
- if (!string)
+ else if (pid < (pid_t)0 )
{
- fprintf (stderr, "DOWN-ROOT: out of memory\n");
- exit (1);
+ warn ("DOWN-ROOT: Failed to fork child to run %s", argv[0]);
+ return -1;
}
- string[0] = '\0';
-
- /* build string */
- for (i = 0; i < n; ++i)
+ else /* parent side */
{
- strcat (string, argv[i]);
- if (i + 1 < n)
- strcat (string, " ");
+ if( waitpid (pid, &ret, 0) != pid )
+ {
+ /* waitpid does not return error information via errno */
+ fprintf(stderr, "DOWN-ROOT: waitpid() failed, don't know exit code of child (%s)\n", argv[0]);
+ return -1;
+ }
}
- return string;
+ return ret;
}
-static void
-free_context (struct down_root_context *context)
+OPENVPN_EXPORT openvpn_plugin_handle_t
+openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
{
- if (context)
+ struct down_root_context *context;
+ int i = 0;
+
+ /*
+ * Allocate our context
+ */
+ context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
+ if (!context)
{
- if (context->command)
- free (context->command);
- free (context);
+ warn ("DOWN-ROOT: Could not allocate memory for plug-in context");
+ goto error;
+ }
+ context->foreground_fd = -1;
+
+ /*
+ * Intercept the --up and --down callbacks
+ */
+ *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);
+
+ /*
+ * Make sure we have two string arguments: the first is the .so name,
+ * the second is the script command.
+ */
+ if (string_array_len (argv) < 2)
+ {
+ fprintf (stderr, "DOWN-ROOT: need down script command\n");
+ goto error;
}
-}
-OPENVPN_EXPORT openvpn_plugin_handle_t
-openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
-{
- struct down_root_context *context;
-
- /*
- * Allocate our context
- */
- context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
- if (!context)
- goto error;
- context->foreground_fd = -1;
-
- /*
- * Intercept the --up and --down callbacks
- */
- *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);
-
- /*
- * Make sure we have two string arguments: the first is the .so name,
- * the second is the script command.
- */
- if (string_array_len (argv) < 2)
+ /*
+ * Save the arguments in our context
+ */
+ context->command = calloc(string_array_len(argv), sizeof(char *));
+ if (!context->command)
+ {
+ warn ("DOWN-ROOT: Could not allocate memory for command array");
+ goto error;
+ }
+
+ /* Ignore argv[0], as it contains just the plug-in file name */
+ for (i = 1; i < string_array_len(argv); i++)
+ {
+ context->command[i-1] = (char *) argv[i];
+ }
+
+ /*
+ * Get verbosity level from environment
+ */
{
- fprintf (stderr, "DOWN-ROOT: need down script command\n");
- goto error;
+ const char *verb_string = get_env ("verb", envp);
+ if (verb_string)
+ context->verb = atoi (verb_string);
}
- /*
- * Save our argument in context
- */
- context->command = build_command_line (&argv[1]);
-
- /*
- * Get verbosity level from environment
- */
- {
- const char *verb_string = get_env ("verb", envp);
- if (verb_string)
- context->verb = atoi (verb_string);
- }
-
- return (openvpn_plugin_handle_t) context;
-
- error:
- free_context (context);
- return NULL;
+ return (openvpn_plugin_handle_t) context;
+
+error:
+ free_context (context);
+ return NULL;
}
OPENVPN_EXPORT int
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */
+ if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */
{
- pid_t pid;
- int fd[2];
-
- /*
- * Make a socket for foreground and background processes
- * to communicate.
- */
- if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: socketpair call failed\n");
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
-
- /*
- * Fork off the privileged process. It will remain privileged
- * even after the foreground process drops its privileges.
- */
- pid = fork ();
-
- if (pid)
- {
- int status;
-
- /*
- * Foreground Process
- */
-
- context->background_pid = pid;
-
- /* close our copy of child's socket */
- close (fd[1]);
-
- /* don't let future subprocesses inherit child socket */
- if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
- fprintf (stderr, "DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed\n");
-
- /* wait for background child process to initialize */
- status = recv_control (fd[0]);
- if (status == RESPONSE_INIT_SUCCEEDED)
- {
- context->foreground_fd = fd[0];
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- }
- else
- {
- /*
- * Background Process
- */
-
- /* close all parent fds except our socket back to parent */
- close_fds_except (fd[1]);
-
- /* Ignore most signals (the parent will receive them) */
- set_signals ();
-
- /* Daemonize if --daemon option is set. */
- daemonize (envp);
-
- /* execute the event loop */
- down_root_server (fd[1], context->command, argv, envp, context->verb);
-
- close (fd[1]);
- exit (0);
- return 0; /* NOTREACHED */
- }
+ pid_t pid;
+ int fd[2];
+
+ /*
+ * Make a socket for foreground and background processes
+ * to communicate.
+ */
+ if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
+ {
+ warn ("DOWN-ROOT: socketpair call failed");
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+
+ /*
+ * Fork off the privileged process. It will remain privileged
+ * even after the foreground process drops its privileges.
+ */
+ pid = fork ();
+
+ if (pid)
+ {
+ int status;
+
+ /*
+ * Foreground Process
+ */
+
+ context->background_pid = pid;
+
+ /* close our copy of child's socket */
+ close (fd[1]);
+
+ /* don't let future subprocesses inherit child socket */
+ if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
+ {
+ warn ("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
+ }
+
+ /* wait for background child process to initialize */
+ status = recv_control (fd[0]);
+ if (status == RESPONSE_INIT_SUCCEEDED)
+ {
+ context->foreground_fd = fd[0];
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ }
+ }
+ else
+ {
+ /*
+ * Background Process
+ */
+
+ /* close all parent fds except our socket back to parent */
+ close_fds_except (fd[1]);
+
+ /* Ignore most signals (the parent will receive them) */
+ set_signals ();
+
+ /* Daemonize if --daemon option is set. */
+ daemonize (envp);
+
+ /* execute the event loop */
+ down_root_server (fd[1], context->command, (char * const *) envp, context->verb);
+
+ close (fd[1]);
+ exit (0);
+ return 0; /* NOTREACHED */
+ }
}
- else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
+ else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
{
- if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: Error sending script execution signal to background process\n");
- }
- else
- {
- const int status = recv_control (context->foreground_fd);
- if (status == RESPONSE_SCRIPT_SUCCEEDED)
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- if (status == -1)
- fprintf (stderr, "DOWN-ROOT: Error receiving script execution confirmation from background process\n");
- }
+ if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
+ {
+ warn ("DOWN-ROOT: Error sending script execution signal to background process");
+ }
+ else
+ {
+ const int status = recv_control (context->foreground_fd);
+ if (status == RESPONSE_SCRIPT_SUCCEEDED)
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ if (status == -1)
+ {
+ warn ("DOWN-ROOT: Error receiving script execution confirmation from background process");
+ }
+ }
}
- return OPENVPN_PLUGIN_FUNC_ERROR;
+ return OPENVPN_PLUGIN_FUNC_ERROR;
}
OPENVPN_EXPORT void
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (DEBUG (context->verb))
- fprintf (stderr, "DOWN-ROOT: close\n");
+ if (DEBUG (context->verb))
+ fprintf (stderr, "DOWN-ROOT: close\n");
- if (context->foreground_fd >= 0)
+ if (context->foreground_fd >= 0)
{
- /* tell background process to exit */
- if (send_control (context->foreground_fd, COMMAND_EXIT) == -1)
- fprintf (stderr, "DOWN-ROOT: Error signaling background process to exit\n");
-
- /* wait for background process to exit */
- if (context->background_pid > 0)
- waitpid (context->background_pid, NULL, 0);
-
- close (context->foreground_fd);
- context->foreground_fd = -1;
+ /* tell background process to exit */
+ if (send_control (context->foreground_fd, COMMAND_EXIT) == -1)
+ {
+ warn ("DOWN-ROOT: Error signalling background process to exit");
+ }
+
+ /* wait for background process to exit */
+ if (context->background_pid > 0)
+ waitpid (context->background_pid, NULL, 0);
+
+ close (context->foreground_fd);
+ context->foreground_fd = -1;
}
- free_context (context);
+ free_context (context);
}
OPENVPN_EXPORT void
openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (context && context->foreground_fd >= 0)
+ if (context && context->foreground_fd >= 0)
{
- /* tell background process to exit */
- send_control (context->foreground_fd, COMMAND_EXIT);
- close (context->foreground_fd);
- context->foreground_fd = -1;
+ /* tell background process to exit */
+ send_control (context->foreground_fd, COMMAND_EXIT);
+ close (context->foreground_fd);
+ context->foreground_fd = -1;
}
}
@@ -453,105 +463,85 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
* Background process -- runs with privilege.
*/
static void
-down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb)
+down_root_server (const int fd, char * const *argv, char * const *envp, const int verb)
{
- const char *p[3];
- char *command_line = NULL;
- char *argv_cat = NULL;
- int i;
-
- /*
- * Do initialization
- */
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", command);
-
- /*
- * Tell foreground that we initialized successfully
- */
- if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
+ /*
+ * Do initialization
+ */
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", argv[0]);
+
+ /*
+ * Tell foreground that we initialized successfully
+ */
+ if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
{
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [1]\n");
- goto done;
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [1]");
+ goto done;
}
- /*
- * Build command line
- */
- if (string_array_len (argv) >= 2)
- argv_cat = build_command_line (&argv[1]);
- else
- argv_cat = build_command_line (NULL);
- p[0] = command;
- p[1] = argv_cat;
- p[2] = NULL;
- command_line = build_command_line (p);
-
- /*
- * Save envp in environment
- */
- for (i = 0; envp[i]; ++i)
+ /*
+ * Event loop
+ */
+ while (1)
{
- putenv ((char *)envp[i]);
+ int command_code;
+ int exit_code = -1;
+
+ /* get a command from foreground process */
+ command_code = recv_control (fd);
+
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
+
+ switch (command_code)
+ {
+ case COMMAND_RUN_SCRIPT:
+ if ( (exit_code = run_script(argv, envp)) == 0 ) /* Succeeded */
+ {
+ if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
+ {
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [2]");
+ goto done;
+ }
+ }
+ else /* Failed */
+ {
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n", argv[0], exit_code);
+ if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
+ {
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [3]");
+ goto done;
+ }
+ }
+ break;
+
+ case COMMAND_EXIT:
+ goto done;
+
+ case -1:
+ warn ("DOWN-ROOT: BACKGROUND: read error on command channel");
+ goto done;
+
+ default:
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
+ command_code);
+ goto done;
+ }
}
- /*
- * Event loop
- */
- while (1)
- {
- int command_code;
- int status;
-
- /* get a command from foreground process */
- command_code = recv_control (fd);
-
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
-
- switch (command_code)
- {
- case COMMAND_RUN_SCRIPT:
- status = system (command_line);
- if (system_ok (status)) /* Succeeded */
- {
- if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [2]\n");
- goto done;
- }
- }
- else /* Failed */
- {
- if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [3]\n");
- goto done;
- }
- }
- break;
-
- case COMMAND_EXIT:
- goto done;
-
- case -1:
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: read error on command channel\n");
- goto done;
-
- default:
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
- command_code);
- goto done;
- }
- }
+done:
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
- done:
- if (argv_cat)
- free (argv_cat);
- if (command_line)
- free (command_line);
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
-
- return;
+ return;
}
+
+
+/*
+Local variables:
+c-file-style: "bsd"
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/