Commit 8e0927f9 authored by Jondy Zhao's avatar Jondy Zhao

Patch openvpn for cygwin

parent 873ba777
......@@ -34,7 +34,7 @@
#include "buffer.h"
#include "misc.h"
#ifdef WIN32
#if defined (WIN32) && !defined (CYGWIN)
#include "win32.h"
......@@ -201,7 +201,7 @@ get_console_input (const char *prompt, const bool echo, char *input, const int c
return get_console_input_systemd (prompt, echo, input, capacity);
#endif
#if defined(WIN32)
#if defined(WIN32) && !defined(CYGWIN)
return get_console_input_win32 (prompt, echo, input, capacity);
#elif defined(HAVE_GETPASS)
if (echo)
......
......@@ -470,7 +470,7 @@ get_orig_stderr (void)
void
redirect_stdout_stderr (const char *file, bool append)
{
#if defined(WIN32)
#if defined(WIN32) && !defined(CYGWIN)
if (!std_redir)
{
struct gc_arena gc = gc_new ();
......
......@@ -1254,6 +1254,10 @@ process_outgoing_tun (struct context *c)
size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun));
#endif
#if defined(CYGWIN)
/* do_multicast_ipv6_packets(c, &c->c2.to_tun); */
#endif
if (size > 0)
c->c2.tun_write_bytes += size;
check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap);
......@@ -1555,3 +1559,54 @@ process_io (struct context *c)
process_incoming_tun (c);
}
}
#if defined(CYGWIN)
/*
* IPv6/ICMPv6 Multicast Packet:
*
* We'll filter all the ipmpv6 multicast packets, and rewrite to all
* the other netword devices. Openvpn writes these packets only to its
* own tun/tap device. So other netword devices in this node could
* receive the multicase message.
*
*/
static void
do_multicast_ipv6_packets(struct context *c, struct buffer *buf)
{
int offset;
TUNNEL_TYPE tunnel_type;
unsigned char *p = buf;
const struct openvpn_ipv6hdr *pip6;
struct buffer newbuf;
int i;
tunnel_type = TUNNEL_TYPE (c->c1.tuntap);
if (!is_ipv6 (tunnel_type, buf))
return;
offset = tunnel_type == DEV_TYPE_TUN ? 0 : sizeof (struct openvpn_ethhdr);
pip6 = (struct openvpn_ipv6hdr *) (BPTR (buf) + offset);
/* do we have the full IPv6 packet?
* "payload_len" does not include IPv6 header (+40 bytes)
*/
if (BLEN (buf) != (int) ntohs(pip6->payload_len)+40 )
return;
/* follow header chain until we reach final header, then check for TCP
*
* An IPv6 packet could, theoretically, have a chain of multiple headers
* before the final header (TCP, UDP, ...), so we'd need to walk that
* chain (see RFC 2460 and RFC 6564 for details).
*
* In practice, "most typically used" extention headers (AH, routing,
* fragment, mobility) are very unlikely to be seen inside an OpenVPN
* tun, so for now, we only handle the case of "single next header = TCP"
*/
if ( pip6->nexthdr != 58 ) /* IP_PROTO_ICMPV6 */
return;
/* Check it's multicast message */
}
#endif /* CYGWIN */
......@@ -1036,7 +1036,11 @@ absolute_pathname (const char *pathname)
{
const int c = pathname[0];
#ifdef WIN32
#if defined(CYGWIN)
return c == '/' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '/');
#else
return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\');
#endif
#else
return c == '/';
#endif
......
......@@ -49,7 +49,6 @@ process_signal_p2p (struct context *c)
}
/**************************************************************************/
/**
* Main event loop for OpenVPN in client mode, where only one VPN tunnel
......@@ -138,7 +137,7 @@ openvpn_main (int argc, char *argv[])
return 1;
#endif
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
SetConsoleOutputCP (CP_UTF8);
#endif
......@@ -291,7 +290,8 @@ openvpn_main (int argc, char *argv[])
return 0; /* NOTREACHED */
}
#ifdef WIN32
#if defined(WIN32) && !defined (CYGWIN)
int
wmain (int argc, wchar_t *wargv[]) {
char **argv;
......
......@@ -859,7 +859,7 @@ init_options (struct options *o, const bool init_gc)
/* tmp is only used in P2MP server context */
#if P2MP_SERVER
/* Set default --tmp-dir */
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
/* On Windows, find temp dir via enviroment variables */
o->tmp_dir = win_get_tempdir();
#else
......
......@@ -158,7 +158,7 @@ platform_nice (int niceval)
unsigned int
platform_getpid ()
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
return (unsigned int) GetCurrentProcessId ();
#else
#ifdef HAVE_GETPID
......@@ -190,7 +190,7 @@ int
platform_chdir (const char* dir)
{
#ifdef HAVE_CHDIR
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
int res;
struct gc_arena gc = gc_new ();
res = _wchdir (wide_string (dir, &gc));
......@@ -210,7 +210,7 @@ platform_chdir (const char* dir)
bool
platform_system_ok (int stat)
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
return stat == 0;
#else
return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
......@@ -220,7 +220,7 @@ platform_system_ok (int stat)
int
platform_access (const char *path, int mode)
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new ();
int ret = _waccess (wide_string (path, &gc), mode & ~X_OK);
gc_free (&gc);
......@@ -263,7 +263,7 @@ platform_sleep_until_signal (void)
bool
platform_unlink (const char *filename)
{
#if defined(WIN32)
#if defined(WIN32) & !defined(CYGWIN)
struct gc_arena gc = gc_new ();
BOOL ret = DeleteFileW (wide_string (filename, &gc));
gc_free (&gc);
......@@ -278,7 +278,7 @@ platform_unlink (const char *filename)
int platform_putenv(char *string)
{
int status;
#if defined(WIN32)
#if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new ();
char *s = string_alloc(string, &gc);
char *value = strchr(s, '=');
......@@ -306,7 +306,7 @@ int platform_putenv(char *string)
FILE *
platform_fopen (const char *path, const char *mode)
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new ();
FILE *f = _wfopen (wide_string (path, &gc), wide_string (mode, &gc));
gc_free (&gc);
......@@ -319,7 +319,7 @@ platform_fopen (const char *path, const char *mode)
int
platform_open (const char *path, int flags, int mode)
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new ();
int fd = _wopen (wide_string (path, &gc), flags, mode);
gc_free (&gc);
......@@ -332,7 +332,7 @@ platform_open (const char *path, int flags, int mode)
int
platform_stat (const char *path, platform_stat_t *buf)
{
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new ();
int res = _wstat (wide_string (path, &gc), buf);
gc_free (&gc);
......
......@@ -130,7 +130,7 @@ int platform_putenv (char *string);
FILE *platform_fopen (const char *path, const char *mode);
int platform_open (const char *path, int flags, int mode);
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
typedef struct _stat platform_stat_t;
#else
typedef struct stat platform_stat_t;
......
......@@ -239,6 +239,8 @@ struct link_socket
/* used to get/set TOS. */
#if defined(TARGET_LINUX)
uint8_t ptos;
#elif defined(CYGWIN)
char ptos;
#else /* all the BSDs, Solaris, MacOS use plain "int" -> see "man ip" there */
int ptos;
#endif
......
......@@ -38,12 +38,14 @@
#endif
#ifdef WIN32
#include <windows.h>
#include <winsock2.h>
#include <windows.h>
#ifndef CYGWIN
#define sleep(x) Sleep((x)*1000)
#define random rand
#define srandom srand
#endif
#endif
#if defined(__APPLE__)
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070
......@@ -448,7 +450,7 @@
/*
* Directory separation char
*/
#ifdef WIN32
#if defined(WIN32) && !defined(CYGWIN)
#define OS_SPECIFIC_DIRSEP '\\'
#else
#define OS_SPECIFIC_DIRSEP '/'
......@@ -615,7 +617,7 @@ socket_defined (const socket_descriptor_t sd)
* Do we have CryptoAPI capability?
*/
#if defined(WIN32) && defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL)
#define ENABLE_CRYPTOAPI
/* #define ENABLE_CRYPTOAPI */
#endif
/*
......
......@@ -3650,7 +3650,11 @@ get_adapter_index_method_1 (const char *guid)
DWORD index;
ULONG aindex;
wchar_t wbuf[256];
#if defined(CYGWIN)
swprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
#else
_snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
#endif
wbuf [SIZE(wbuf) - 1] = 0;
if (GetAdapterIndex (wbuf, &aindex) != NO_ERROR)
index = TUN_ADAPTER_INDEX_INVALID;
......@@ -4480,10 +4484,10 @@ fork_dhcp_action (struct tuntap *tt)
buf_printf (&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep);
if (tt->options.dhcp_pre_release)
buf_printf (&cmd, " --dhcp-pre-release");
if (tt->options.dhcp_renew)
buf_printf (&cmd, " --dhcp-renew");
buf_printf (&cmd, " --dhcp-internal %u", (unsigned int)tt->adapter_index);
fork_to_self (BSTR (&cmd));
gc_free (&gc);
}
......
......@@ -27,9 +27,15 @@
#ifdef WIN32
#include <winioctl.h>
#ifdef CYGWIN
#include "tap-windows.h"
#else
#include <tap-windows.h>
#endif
#endif
#include "buffer.h"
#include "error.h"
#include "mtu.h"
......
......@@ -764,7 +764,6 @@ static char *
env_block (const struct env_set *es)
{
char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem";
if (es)
{
struct env_item *e;
......@@ -849,6 +848,116 @@ wide_cmd_line (const struct argv *a, struct gc_arena *gc)
return wide_string (BSTR (&buf), gc);
}
#if defined(CYGWIN)
/*
* Run execve() inside a fork(). Designed to replicate the semantics of system() but
* in a safer way that doesn't require the invocation of a shell or the risks
* assocated with formatting and parsing a command line.
*/
const char **
make_env_array_p (const struct env_set *es,
const bool check_allowed,
struct gc_arena *gc)
{
char **ret = NULL;
struct env_item *e = NULL;
int i = 0, n = 0;
bool path_seen = false;
/* figure length of es */
if (es)
{
for (e = es->list; e != NULL; e = e->next)
++n;
}
/* alloc return array */
ALLOC_ARRAY_CLEAR_GC (ret, char *, n+2, gc);
/* fill return array */
if (es)
{
i = 0;
for (e = es->list; e != NULL; e = e->next)
{
if (!check_allowed || env_allowed (e->string))
{
ASSERT (i < n);
ret[i++] = e->string;
if ( strncmp(e->string, "PATH=", 5 ) == 0 )
path_seen = true;
}
}
}
/* PATH */
char * p = NULL ;
if ( !path_seen )
{
char * s = getenv("PATH");
n = strlen(s);
ALLOC_ARRAY_CLEAR_GC (p, char, n+6, gc);
memcpy(p, "PATH=", 5);
memcpy(p + 5, s, n);
*(p + n + 5) = 0;
}
ret[i++] = p;
ret[i] = NULL;
return (const char **)ret;
}
int
openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags)
{
struct gc_arena gc = gc_new ();
int ret = -1;
static bool warn_shown = false;
if (a && a->argv[0])
{
#if defined(ENABLE_FEATURE_EXECVE)
if (openvpn_execve_allowed (flags))
{
const char *cmd = a->argv[0];
char *const *argv = a->argv;
char *const *envp = (char *const *)make_env_array_p (es, true, &gc);
pid_t pid;
pid = fork ();
if (pid == (pid_t)0) /* child side */
{
/* Miss PATH */
execve (cmd, argv, envp);
exit (127);
}
else if (pid < (pid_t)0) /* fork failed */
msg (M_ERR, "openvpn_execve: unable to fork");
else /* parent side */
{
if (waitpid (pid, &ret, 0) != pid)
ret = -1;
}
}
else if (!warn_shown && (script_security < SSEC_SCRIPTS))
{
msg (M_WARN, SCRIPT_SECURITY_WARNING);
warn_shown = true;
}
#else
msg (M_WARN, "openvpn_execve: execve function not available");
#endif
}
else
{
msg (M_FATAL, "openvpn_execve: called with empty argv");
}
gc_free (&gc);
return ret;
}
#else
/*
* Attempt to simulate fork/execve on Windows
*/
......@@ -909,6 +1018,7 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
}
return ret;
}
#endif /* CYGWIN */
WCHAR *
wide_string (const char* utf8, struct gc_arena *gc)
......@@ -986,6 +1096,12 @@ set_win_sys_path_via_env (struct env_set *es)
msg (M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
if (status > sizeof (buf) - 1)
msg (M_FATAL, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME);
#if defined(CYGWIN)
while(status) {
if (buf[status] == '\\') buf[status] = '/';
status --;
}
#endif
set_win_sys_path (buf, es);
}
......@@ -1008,4 +1124,5 @@ win_get_tempdir()
}
return tmpdir;
}
#endif
......@@ -28,12 +28,20 @@
#include "mtu.h"
#if !defined(CYGWIN)
/* location of executables */
#define SYS_PATH_ENV_VAR_NAME "SystemRoot" /* environmental variable name that normally contains the system path */
#define NETSH_PATH_SUFFIX "\\system32\\netsh.exe"
#define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe"
#define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe"
#define WIN_NET_PATH_SUFFIX "\\system32\\net.exe"
#else
#define SYS_PATH_ENV_VAR_NAME "SYSTEMROOT"
#define NETSH_PATH_SUFFIX "/System32/netsh.exe"
#define WIN_ROUTE_PATH_SUFFIX "/System32/route.exe"
#define WIN_IPCONFIG_PATH_SUFFIX "/System32/ipconfig.exe"
#define WIN_NET_PATH_SUFFIX "net.exe"
#endif
/*
* Win32-specific OpenVPN code, targetted at the mingw
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment