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

Patch openvpn for cygwin

parent 873ba777
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include "buffer.h" #include "buffer.h"
#include "misc.h" #include "misc.h"
#ifdef WIN32 #if defined (WIN32) && !defined (CYGWIN)
#include "win32.h" #include "win32.h"
...@@ -201,7 +201,7 @@ get_console_input (const char *prompt, const bool echo, char *input, const int c ...@@ -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); return get_console_input_systemd (prompt, echo, input, capacity);
#endif #endif
#if defined(WIN32) #if defined(WIN32) && !defined(CYGWIN)
return get_console_input_win32 (prompt, echo, input, capacity); return get_console_input_win32 (prompt, echo, input, capacity);
#elif defined(HAVE_GETPASS) #elif defined(HAVE_GETPASS)
if (echo) if (echo)
......
...@@ -470,7 +470,7 @@ get_orig_stderr (void) ...@@ -470,7 +470,7 @@ get_orig_stderr (void)
void void
redirect_stdout_stderr (const char *file, bool append) redirect_stdout_stderr (const char *file, bool append)
{ {
#if defined(WIN32) #if defined(WIN32) && !defined(CYGWIN)
if (!std_redir) if (!std_redir)
{ {
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
......
...@@ -1254,6 +1254,10 @@ process_outgoing_tun (struct context *c) ...@@ -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)); size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun));
#endif #endif
#if defined(CYGWIN)
/* do_multicast_ipv6_packets(c, &c->c2.to_tun); */
#endif
if (size > 0) if (size > 0)
c->c2.tun_write_bytes += size; c->c2.tun_write_bytes += size;
check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap); check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap);
...@@ -1555,3 +1559,54 @@ process_io (struct context *c) ...@@ -1555,3 +1559,54 @@ process_io (struct context *c)
process_incoming_tun (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) ...@@ -1036,7 +1036,11 @@ absolute_pathname (const char *pathname)
{ {
const int c = pathname[0]; const int c = pathname[0];
#ifdef WIN32 #ifdef WIN32
#if defined(CYGWIN)
return c == '/' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '/');
#else
return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\'); return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\');
#endif
#else #else
return c == '/'; return c == '/';
#endif #endif
......
...@@ -49,7 +49,6 @@ process_signal_p2p (struct context *c) ...@@ -49,7 +49,6 @@ process_signal_p2p (struct context *c)
} }
/**************************************************************************/ /**************************************************************************/
/** /**
* Main event loop for OpenVPN in client mode, where only one VPN tunnel * Main event loop for OpenVPN in client mode, where only one VPN tunnel
...@@ -138,7 +137,7 @@ openvpn_main (int argc, char *argv[]) ...@@ -138,7 +137,7 @@ openvpn_main (int argc, char *argv[])
return 1; return 1;
#endif #endif
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
SetConsoleOutputCP (CP_UTF8); SetConsoleOutputCP (CP_UTF8);
#endif #endif
...@@ -291,7 +290,8 @@ openvpn_main (int argc, char *argv[]) ...@@ -291,7 +290,8 @@ openvpn_main (int argc, char *argv[])
return 0; /* NOTREACHED */ return 0; /* NOTREACHED */
} }
#ifdef WIN32 #if defined(WIN32) && !defined (CYGWIN)
int int
wmain (int argc, wchar_t *wargv[]) { wmain (int argc, wchar_t *wargv[]) {
char **argv; char **argv;
......
...@@ -859,7 +859,7 @@ init_options (struct options *o, const bool init_gc) ...@@ -859,7 +859,7 @@ init_options (struct options *o, const bool init_gc)
/* tmp is only used in P2MP server context */ /* tmp is only used in P2MP server context */
#if P2MP_SERVER #if P2MP_SERVER
/* Set default --tmp-dir */ /* Set default --tmp-dir */
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
/* On Windows, find temp dir via enviroment variables */ /* On Windows, find temp dir via enviroment variables */
o->tmp_dir = win_get_tempdir(); o->tmp_dir = win_get_tempdir();
#else #else
......
...@@ -158,7 +158,7 @@ platform_nice (int niceval) ...@@ -158,7 +158,7 @@ platform_nice (int niceval)
unsigned int unsigned int
platform_getpid () platform_getpid ()
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
return (unsigned int) GetCurrentProcessId (); return (unsigned int) GetCurrentProcessId ();
#else #else
#ifdef HAVE_GETPID #ifdef HAVE_GETPID
...@@ -190,7 +190,7 @@ int ...@@ -190,7 +190,7 @@ int
platform_chdir (const char* dir) platform_chdir (const char* dir)
{ {
#ifdef HAVE_CHDIR #ifdef HAVE_CHDIR
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
int res; int res;
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
res = _wchdir (wide_string (dir, &gc)); res = _wchdir (wide_string (dir, &gc));
...@@ -210,7 +210,7 @@ platform_chdir (const char* dir) ...@@ -210,7 +210,7 @@ platform_chdir (const char* dir)
bool bool
platform_system_ok (int stat) platform_system_ok (int stat)
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
return stat == 0; return stat == 0;
#else #else
return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0; return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
...@@ -220,7 +220,7 @@ platform_system_ok (int stat) ...@@ -220,7 +220,7 @@ platform_system_ok (int stat)
int int
platform_access (const char *path, int mode) platform_access (const char *path, int mode)
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
int ret = _waccess (wide_string (path, &gc), mode & ~X_OK); int ret = _waccess (wide_string (path, &gc), mode & ~X_OK);
gc_free (&gc); gc_free (&gc);
...@@ -263,7 +263,7 @@ platform_sleep_until_signal (void) ...@@ -263,7 +263,7 @@ platform_sleep_until_signal (void)
bool bool
platform_unlink (const char *filename) platform_unlink (const char *filename)
{ {
#if defined(WIN32) #if defined(WIN32) & !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
BOOL ret = DeleteFileW (wide_string (filename, &gc)); BOOL ret = DeleteFileW (wide_string (filename, &gc));
gc_free (&gc); gc_free (&gc);
...@@ -278,7 +278,7 @@ platform_unlink (const char *filename) ...@@ -278,7 +278,7 @@ platform_unlink (const char *filename)
int platform_putenv(char *string) int platform_putenv(char *string)
{ {
int status; int status;
#if defined(WIN32) #if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
char *s = string_alloc(string, &gc); char *s = string_alloc(string, &gc);
char *value = strchr(s, '='); char *value = strchr(s, '=');
...@@ -306,7 +306,7 @@ int platform_putenv(char *string) ...@@ -306,7 +306,7 @@ int platform_putenv(char *string)
FILE * FILE *
platform_fopen (const char *path, const char *mode) platform_fopen (const char *path, const char *mode)
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
FILE *f = _wfopen (wide_string (path, &gc), wide_string (mode, &gc)); FILE *f = _wfopen (wide_string (path, &gc), wide_string (mode, &gc));
gc_free (&gc); gc_free (&gc);
...@@ -319,7 +319,7 @@ platform_fopen (const char *path, const char *mode) ...@@ -319,7 +319,7 @@ platform_fopen (const char *path, const char *mode)
int int
platform_open (const char *path, int flags, int mode) platform_open (const char *path, int flags, int mode)
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
int fd = _wopen (wide_string (path, &gc), flags, mode); int fd = _wopen (wide_string (path, &gc), flags, mode);
gc_free (&gc); gc_free (&gc);
...@@ -332,7 +332,7 @@ platform_open (const char *path, int flags, int mode) ...@@ -332,7 +332,7 @@ platform_open (const char *path, int flags, int mode)
int int
platform_stat (const char *path, platform_stat_t *buf) platform_stat (const char *path, platform_stat_t *buf)
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
struct gc_arena gc = gc_new (); struct gc_arena gc = gc_new ();
int res = _wstat (wide_string (path, &gc), buf); int res = _wstat (wide_string (path, &gc), buf);
gc_free (&gc); gc_free (&gc);
......
...@@ -130,7 +130,7 @@ int platform_putenv (char *string); ...@@ -130,7 +130,7 @@ int platform_putenv (char *string);
FILE *platform_fopen (const char *path, const char *mode); FILE *platform_fopen (const char *path, const char *mode);
int platform_open (const char *path, int flags, int mode); int platform_open (const char *path, int flags, int mode);
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
typedef struct _stat platform_stat_t; typedef struct _stat platform_stat_t;
#else #else
typedef struct stat platform_stat_t; typedef struct stat platform_stat_t;
......
...@@ -239,6 +239,8 @@ struct link_socket ...@@ -239,6 +239,8 @@ struct link_socket
/* used to get/set TOS. */ /* used to get/set TOS. */
#if defined(TARGET_LINUX) #if defined(TARGET_LINUX)
uint8_t ptos; uint8_t ptos;
#elif defined(CYGWIN)
char ptos;
#else /* all the BSDs, Solaris, MacOS use plain "int" -> see "man ip" there */ #else /* all the BSDs, Solaris, MacOS use plain "int" -> see "man ip" there */
int ptos; int ptos;
#endif #endif
......
...@@ -38,12 +38,14 @@ ...@@ -38,12 +38,14 @@
#endif #endif
#ifdef WIN32 #ifdef WIN32
#include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include <windows.h>
#ifndef CYGWIN
#define sleep(x) Sleep((x)*1000) #define sleep(x) Sleep((x)*1000)
#define random rand #define random rand
#define srandom srand #define srandom srand
#endif #endif
#endif
#if defined(__APPLE__) #if defined(__APPLE__)
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070 #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070
...@@ -448,7 +450,7 @@ ...@@ -448,7 +450,7 @@
/* /*
* Directory separation char * Directory separation char
*/ */
#ifdef WIN32 #if defined(WIN32) && !defined(CYGWIN)
#define OS_SPECIFIC_DIRSEP '\\' #define OS_SPECIFIC_DIRSEP '\\'
#else #else
#define OS_SPECIFIC_DIRSEP '/' #define OS_SPECIFIC_DIRSEP '/'
...@@ -615,7 +617,7 @@ socket_defined (const socket_descriptor_t sd) ...@@ -615,7 +617,7 @@ socket_defined (const socket_descriptor_t sd)
* Do we have CryptoAPI capability? * Do we have CryptoAPI capability?
*/ */
#if defined(WIN32) && defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL) #if defined(WIN32) && defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL)
#define ENABLE_CRYPTOAPI /* #define ENABLE_CRYPTOAPI */
#endif #endif
/* /*
......
...@@ -3650,7 +3650,11 @@ get_adapter_index_method_1 (const char *guid) ...@@ -3650,7 +3650,11 @@ get_adapter_index_method_1 (const char *guid)
DWORD index; DWORD index;
ULONG aindex; ULONG aindex;
wchar_t wbuf[256]; 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); _snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
#endif
wbuf [SIZE(wbuf) - 1] = 0; wbuf [SIZE(wbuf) - 1] = 0;
if (GetAdapterIndex (wbuf, &aindex) != NO_ERROR) if (GetAdapterIndex (wbuf, &aindex) != NO_ERROR)
index = TUN_ADAPTER_INDEX_INVALID; index = TUN_ADAPTER_INDEX_INVALID;
...@@ -4480,10 +4484,10 @@ fork_dhcp_action (struct tuntap *tt) ...@@ -4480,10 +4484,10 @@ fork_dhcp_action (struct tuntap *tt)
buf_printf (&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep); buf_printf (&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep);
if (tt->options.dhcp_pre_release) if (tt->options.dhcp_pre_release)
buf_printf (&cmd, " --dhcp-pre-release"); buf_printf (&cmd, " --dhcp-pre-release");
if (tt->options.dhcp_renew) if (tt->options.dhcp_renew)
buf_printf (&cmd, " --dhcp-renew"); buf_printf (&cmd, " --dhcp-renew");
buf_printf (&cmd, " --dhcp-internal %u", (unsigned int)tt->adapter_index); buf_printf (&cmd, " --dhcp-internal %u", (unsigned int)tt->adapter_index);
fork_to_self (BSTR (&cmd)); fork_to_self (BSTR (&cmd));
gc_free (&gc); gc_free (&gc);
} }
......
...@@ -27,9 +27,15 @@ ...@@ -27,9 +27,15 @@
#ifdef WIN32 #ifdef WIN32
#include <winioctl.h> #include <winioctl.h>
#ifdef CYGWIN
#include "tap-windows.h"
#else
#include <tap-windows.h> #include <tap-windows.h>
#endif #endif
#endif
#include "buffer.h" #include "buffer.h"
#include "error.h" #include "error.h"
#include "mtu.h" #include "mtu.h"
......
...@@ -764,7 +764,6 @@ static char * ...@@ -764,7 +764,6 @@ static char *
env_block (const struct env_set *es) env_block (const struct env_set *es)
{ {
char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem"; char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem";
if (es) if (es)
{ {
struct env_item *e; struct env_item *e;
...@@ -849,6 +848,116 @@ wide_cmd_line (const struct argv *a, struct gc_arena *gc) ...@@ -849,6 +848,116 @@ wide_cmd_line (const struct argv *a, struct gc_arena *gc)
return wide_string (BSTR (&buf), 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 * 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 ...@@ -909,6 +1018,7 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
} }
return ret; return ret;
} }
#endif /* CYGWIN */
WCHAR * WCHAR *
wide_string (const char* utf8, struct gc_arena *gc) wide_string (const char* utf8, struct gc_arena *gc)
...@@ -986,6 +1096,12 @@ set_win_sys_path_via_env (struct env_set *es) ...@@ -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); msg (M_ERR, "Cannot find environmental variable %s", SYS_PATH_ENV_VAR_NAME);
if (status > sizeof (buf) - 1) if (status > sizeof (buf) - 1)
msg (M_FATAL, "String overflow attempting to read environmental variable %s", SYS_PATH_ENV_VAR_NAME); 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); set_win_sys_path (buf, es);
} }
...@@ -1008,4 +1124,5 @@ win_get_tempdir() ...@@ -1008,4 +1124,5 @@ win_get_tempdir()
} }
return tmpdir; return tmpdir;
} }
#endif #endif
...@@ -28,12 +28,20 @@ ...@@ -28,12 +28,20 @@
#include "mtu.h" #include "mtu.h"
#if !defined(CYGWIN)
/* location of executables */ /* location of executables */
#define SYS_PATH_ENV_VAR_NAME "SystemRoot" /* environmental variable name that normally contains the system path */ #define SYS_PATH_ENV_VAR_NAME "SystemRoot" /* environmental variable name that normally contains the system path */
#define NETSH_PATH_SUFFIX "\\system32\\netsh.exe" #define NETSH_PATH_SUFFIX "\\system32\\netsh.exe"
#define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe" #define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe"
#define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe" #define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe"
#define WIN_NET_PATH_SUFFIX "\\system32\\net.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 * 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