From 1bda73a7b0f45a2502ae93e33e30b98152d893f3 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 12 May 2008 20:31:43 +0000 Subject: Moved branch into official BETA21 position. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@2959 e7ae566f-a301-0410-adde-c780ea21d3b5 --- .svnignore | 1 + Makefile.am | 95 +++--- acinclude.m4 | 11 +- base64.c | 10 +- buffer.c | 6 - config-win32.h | 321 ------------------- config-win32.h.in | 326 +++++++++++++++++++ configure.ac | 231 ++++++++++---- crypto.c | 8 +- cryptoapi.c | 13 +- doclean | 67 +++- domake-win | 11 +- error.c | 6 - error.h | 4 + event.c | 6 - fdmisc.c | 6 - forward.c | 6 - fragment.c | 6 - gentoo/openvpn.init | 111 ------- gremlin.c | 6 - helper.c | 6 - ieproxy.c | 10 +- images/.svnignore | 2 + images/Makefile.am | 41 +++ init.c | 6 - install-win32/.svnignore | 4 + install-win32/Makefile.am | 74 +++++ install-win32/getpkcs11helper | 2 +- install-win32/makeopenvpn | 30 +- install-win32/makeservice | 32 -- install-win32/settings.in | 12 +- interval.c | 6 - list.c | 6 - lladdr.c | 6 - lzo.c | 8 +- makefile.w32 | 204 ------------ manage.c | 78 ++++- manage.h | 1 + management/management-notes.txt | 53 ++- mbuf.c | 6 - misc.c | 14 +- misc.h | 7 +- mroute.c | 6 - mss.c | 6 - mtcp.c | 6 - mtu.c | 6 - mudp.c | 6 - multi.c | 6 - ntlm.c | 264 ++++++++++++--- occ.c | 6 - openvpn.8 | 8 + openvpn.c | 6 - options.c | 27 +- options.h | 1 + otime.c | 6 - packet_id.c | 8 +- perf.c | 6 - ping.c | 6 - pkcs11.c | 284 ++++++++++++++-- pkcs11.h | 11 + plugin.c | 6 - pool.c | 6 - proto.c | 6 - proxy.c | 30 +- proxy.h | 1 + ps.c | 6 - push.c | 6 - reliable.c | 8 +- route.c | 35 +- schedule.c | 6 - service-win32/.svnignore | 8 + service-win32/Makefile | 25 -- service-win32/Makefile.am | 41 +++ service-win32/mkpatch | 4 - service-win32/openvpnserv.c | 13 +- service-win32/service.c | 693 ++++++++++++++++++++++++++++++++++++++++ service-win32/service.h | 141 ++++++++ service-win32/service.patch | 359 --------------------- session_id.c | 8 +- shaper.c | 5 - sig.c | 6 - socket.c | 11 +- socks.c | 8 +- ssl.c | 10 +- status.c | 6 - syshead.h | 48 ++- tap-win32/common.h | 12 +- thread.c | 6 - tun.c | 93 +++++- version.m4 | 6 +- win32.c | 4 +- 91 files changed, 2556 insertions(+), 1589 deletions(-) delete mode 100644 config-win32.h create mode 100644 config-win32.h.in delete mode 100755 gentoo/openvpn.init create mode 100644 images/.svnignore create mode 100644 images/Makefile.am create mode 100644 install-win32/Makefile.am delete mode 100644 install-win32/makeservice delete mode 100755 makefile.w32 create mode 100644 service-win32/.svnignore delete mode 100755 service-win32/Makefile create mode 100644 service-win32/Makefile.am delete mode 100755 service-win32/mkpatch create mode 100644 service-win32/service.c create mode 100644 service-win32/service.h delete mode 100755 service-win32/service.patch diff --git a/.svnignore b/.svnignore index 9bc4b41..5dd7a46 100644 --- a/.svnignore +++ b/.svnignore @@ -3,6 +3,7 @@ *.patch *.diff *.tmp +*.html tmp* log* files diff --git a/Makefile.am b/Makefile.am index 84a89c2..f8ce6f5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,18 +22,55 @@ # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +LDADD = @LIBOBJS@ +.PHONY: plugin + # This option prevents autoreconf from overriding our COPYING and # INSTALL targets: AUTOMAKE_OPTIONS = foreign -sbin_PROGRAMS = openvpn +MAINTAINERCLEANFILES = \ + config.log config.status \ + $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \ + $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \ + $(srcdir)/depcomp $(srcdir)/aclocal.m4 \ + $(srcdir)/config.guess $(srcdir)/config.sub \ + $(srcdir)/config-win32.h $(srcdir)/openvpn.spec +CLEANFILES = openvpn.8.html -nodist_openvpn_SOURCES = config.h +EXTRA_DIST = \ + easy-rsa \ + sample-config-files \ + sample-keys \ + sample-scripts \ + suse \ + tap-win32 \ + contrib \ + debug \ + plugin + +SUBDIRS = \ + images \ + service-win32 \ + install-win32 TESTS = t_lpback.sh t_cltsrv.sh -dist_noinst_SCRIPTS = $(TESTS) +sbin_PROGRAMS = openvpn -.PHONY: plugin +dist_noinst_HEADERS = \ + config-win32.h + +dist_noinst_SCRIPTS = \ + $(TESTS) \ + doclean \ + domake-win + +dist_noinst_DATA = \ + openvpn.spec \ + COPYRIGHT.GPL \ + PORTS \ + INSTALL-win32.txt openvpn_SOURCES = \ base64.c base64.h \ @@ -80,6 +117,7 @@ openvpn_SOURCES = \ pool.c pool.h \ proto.c proto.h \ proxy.c proxy.h \ + ieproxy.h ieproxy.c \ ps.c ps.h \ push.c push.h \ reliable.c reliable.h \ @@ -94,44 +132,19 @@ openvpn_SOURCES = \ status.c status.h \ syshead.h \ thread.c thread.h \ - tun.c tun.h - -LDADD = @LIBOBJS@ - -man_MANS = openvpn.8 + tun.c tun.h \ + win32.h win32.c \ + cryptoapi.h cryptoapi.c -EXTRA_DIST = \ - doclean \ - $(man_MANS) \ - COPYRIGHT.GPL \ - PORTS \ - openvpn.spec \ - easy-rsa \ - sample-config-files \ - sample-keys \ - sample-scripts \ - gentoo \ - suse \ - openvpn.spec.in \ - config-win32.h \ - win32.h \ - win32.c \ - cryptoapi.h \ - cryptoapi.c \ - makefile.w32 \ - makefile.w32-vc \ - INSTALL-win32.txt \ - tap-win32 \ - install-win32 \ - service-win32 \ - contrib \ - debug \ - plugin \ - management \ - images \ - ieproxy.c \ - ieproxy.h \ - domake-win dist-hook: cd $(distdir) && for i in $(EXTRA_DIST) ; do find $$i -name .svn -type d -prune -exec rm -rf '{}' ';' ; rm -f `find $$i -type f | grep -E '(^|\/)\.?\#|\~$$|\.s?o$$'` ; done + +if WIN32 +dist_noinst_DATA += openvpn.8 +nodist_html_DATA = openvpn.8.html +openvpn.8.html: $(srcdir)/openvpn.8 + $(MAN2HTML) < $(srcdir)/openvpn.8 > openvpn.8.html +else +dist_man_MANS = openvpn.8 +endif diff --git a/acinclude.m4 b/acinclude.m4 index f164bac..f099de5 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -96,10 +96,19 @@ AC_DEFUN([TYPE_SOCKLEN_T], for arg2 in "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do AC_TRY_COMPILE([ + #ifdef _WIN32 + #include + #define PREFIX1 WINSOCK_API_LINKAGE + #define PREFIX2 PASCAL + #else #include #include + #define PREFIX1 + #define PREFIX2 + #define SOCKET int + #endif - int getpeername (int, $arg2 *, $t *); + PREFIX1 int PREFIX2 getpeername (SOCKET, $arg2 *, $t *); ],[ $t len; getpeername(0,0,&len); diff --git a/base64.c b/base64.c index a69633d..7d876a6 100644 --- a/base64.c +++ b/base64.c @@ -31,15 +31,9 @@ * SUCH DAMAGE. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" -#ifdef ENABLE_HTTP_PROXY +#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_PKCS11) #include "base64.h" @@ -143,7 +137,7 @@ base64_decode(const char *str, void *data) return q - (unsigned char *) data; } -#endif /* NTLM */ +#endif /* NTLM, PKCS#11 */ #else static void dummy(void) {} diff --git a/buffer.c b/buffer.c index 64307ef..93c7930 100644 --- a/buffer.c +++ b/buffer.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "common.h" diff --git a/config-win32.h b/config-win32.h deleted file mode 100644 index 4fe1d07..0000000 --- a/config-win32.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * OpenVPN -- An application to securely tunnel IP networks - * over a single UDP port, with support for SSL/TLS-based - * session authentication and key exchange, - * packet encryption, packet authentication, and - * packet compression. - * - * Copyright (C) 2002-2005 OpenVPN Solutions LLC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Configuration header for Win32 using the mingw environment. - * Manually edited based on linux version as generated by autoconf. - * - * config-win32.h is normally generated by copying - * config-win32.h.in -> config-win32.h and replacing - * [ampersand] VERSION [ampersand] - * with the appropriate version #. This is normally - * done automatically by configure.ac - */ - -#include -#include -#include "autodefs/defs.h" - -#define sleep(x) Sleep((x)*1000) - -#define random rand -#define srandom srand - -typedef unsigned long in_addr_t; - -#ifndef _SSIZE_T_ -#define _SSIZE_T_ - typedef unsigned int ssize_t; -#endif - -/* Append a label to program startup title */ -/*#define DEBUG_LABEL "DEBUG1"*/ - -/* Should we print debug info from driver? */ -#ifdef PRODUCT_TAP_DEBUG -#define TAP_WIN32_DEBUG -#endif - -/* - * Minimum TAP-Win32 version number expected by userspace - * - * The TAP-Win32 version number is defined in tap-win32/SOURCES - */ -#define TAP_WIN32_MIN_MAJOR 9 -#define TAP_WIN32_MIN_MINOR 1 - -/* Enable client/server capability */ -#define ENABLE_CLIENT_SERVER 1 - -/* Enable client capability only */ -/* #undef ENABLE_CLIENT_ONLY */ - -/* Enable management server capability */ -#define ENABLE_MANAGEMENT 1 - -/* Enable PKCS#11 support */ -#define USE_PKCS11 1 - -/* Enable HTTP proxy support */ -#define ENABLE_HTTP_PROXY 1 - -/* Enable Socks proxy support */ -#define ENABLE_SOCKS 1 - -/* Enable internal fragmentation support */ -#define ENABLE_FRAGMENT 1 - -/* Enable smaller executable size */ -/* #undef ENABLE_SMALL */ - -/* Enable debugging support */ -#define ENABLE_DEBUG 1 - -/* if defined, will allow usage of the --plugin directive */ -#define USE_LOAD_LIBRARY - -/* Dimension size to use for empty array declaration */ -#define EMPTY_ARRAY_SIZE 0 - -/* Define to 1 if you have the `getsockname' function. */ -#define HAVE_GETSOCKNAME 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_ENGINE_H 1 - -/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ -#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 - -/* Define to 1 if you have the `ENGINE_register_all_complete' function. */ -#define HAVE_ENGINE_REGISTER_ALL_COMPLETE 1 - -/* Define to 1 if you have the `ENGINE_cleanup' function. */ -#define HAVE_ENGINE_CLEANUP 1 - -/* gettimeofday() is implemented in otime.c for Windows */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the 'chsize' function. */ -#define HAVE_CHSIZE 1 - -/* Define to 1 if you have the `chdir' function. */ -#define HAVE_CHDIR 1 - -/* Define to 1 if your compiler supports GNU GCC-style variadic macros */ -#ifndef _MSC_VER /* Defines MSFT compiler version. Defined as 1200 for MSVC++ 6.0. */ -#define HAVE_CPP_VARARG_MACRO_GCC 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the `EVP_CIPHER_CTX_set_key_length' function. */ -#define HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `getsockopt' function. */ -#define HAVE_GETSOCKOPT 1 - -/* Define to 1 if you have the `inet_ntoa' function. */ -#define HAVE_INET_NTOA 1 - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the `memset' function. */ -#define HAVE_MEMSET 1 - -/* Define to 1 if you have the `setsockopt' function. */ -#define HAVE_SETSOCKOPT 1 - -/* Define to 1 if you have the `socket' function. */ -#define HAVE_SOCKET 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -#define HAVE_STDINT_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `system' function. */ -#define HAVE_SYSTEM 1 - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -#define HAVE_SYS_FILE_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -#define HAVE_SYS_TIME_H 1 -#endif - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the `time' function. */ -#define HAVE_TIME 1 - -/* Define to 1 if you have the header file. */ -#ifndef _MSC_VER -#define HAVE_UNISTD_H 1 -#endif - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Special Windows version of getpass() defined in io.c */ -#define HAVE_GETPASS 1 - -/* Name of package */ -#define PACKAGE PRODUCT_UNIX_NAME - -/* Define to the address where bug reports for this package should be sent. */ -//#define PACKAGE_BUGREPORT "openvpn-users@lists.sourceforge.net" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME PRODUCT_NAME - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME PACKAGE - -/* Define to the version of this package. */ -#define PACKAGE_VERSION PRODUCT_VERSION - -/* Define to the full name and version of this package. */ -#ifdef DEBUG_LABEL -#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION " " DEBUG_LABEL -#else -#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION -#endif - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* The size of a `unsigned int', as computed by sizeof. */ -#define SIZEOF_UNSIGNED_INT 4 - -/* The size of a `unsigned long', as computed by sizeof. */ -#define SIZEOF_UNSIGNED_LONG 4 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* A string representing our target */ -#ifdef _MSC_VER -#define TARGET_ALIAS "Win32-MSVC++" -#else -#define TARGET_ALIAS "Win32-MinGW" -#endif - -/* Define to 1 if you can safely include both and . */ -#ifndef _MSC_VER -#define TIME_WITH_SYS_TIME 1 -#endif - -/* Use OpenSSL crypto library */ -#define USE_CRYPTO 1 - -/* Use LZO compression library */ -#define USE_LZO 1 - -/* LZO version number */ -#define LZO_VERSION_NUM "2" - -/* Use lzo/ directory prefix for LZO header files (for LZO 2.0) */ -#define LZO_HEADER_DIR 1 - -/* Use OpenSSL SSL library */ -#define USE_SSL 1 - -/* Version number of package */ -#define VERSION PACKAGE_VERSION - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#define inline __inline - -/* type to use in place of socklen_t if not defined */ -#define socklen_t unsigned int - -/* 32-bit unsigned type */ -#define uint32_t unsigned int - -/* 16-bit unsigned type */ -#define uint16_t unsigned short - -/* 8-bit unsigned type */ -#define uint8_t unsigned char - -/* Route command */ -#define ROUTE_PATH "route" - -/* Windows doesn't support PTHREAD yet */ -#ifdef USE_PTHREAD -#error The Windows version of OpenVPN does not support PTHREAD yet -#endif - -#ifdef _MSC_VER -/* MSVC++ hacks */ -#include -#include -#define vsnprintf _vsnprintf -#define vsnwprintf _vsnwprintf -#define snwprintf _snwprintf -#define write _write -#define open _open -#define read _read -#define close _close -#define chdir _chdir -#define S_IRUSR 0 -#define S_IWUSR 0 -typedef int intptr_t; -#undef S_NORMAL -#endif diff --git a/config-win32.h.in b/config-win32.h.in new file mode 100644 index 0000000..44d9f30 --- /dev/null +++ b/config-win32.h.in @@ -0,0 +1,326 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Configuration header for Win32 using the mingw environment. + * Manually edited based on linux version as generated by autoconf. + * + * config-win32.h is normally generated by copying + * config-win32.h.in -> config-win32.h and replacing + * [ampersand] VERSION [ampersand] + * with the appropriate version #. This is normally + * done automatically by configure.ac + */ + +#include +#include +#include "autodefs/defs.h" + +#define sleep(x) Sleep((x)*1000) + +#define random rand +#define srandom srand + +typedef unsigned long in_addr_t; + +#ifndef _SSIZE_T_ +#define _SSIZE_T_ + typedef unsigned int ssize_t; +#endif + +/* Append a label to program startup title */ +/*#define DEBUG_LABEL "DEBUG1"*/ + +/* Should we print debug info from driver? */ +#ifdef PRODUCT_TAP_DEBUG +#define TAP_WIN32_DEBUG +#endif + +/* + * Minimum TAP-Win32 version number expected by userspace + * + * The TAP-Win32 version number is defined in tap-win32/SOURCES + */ +#define TAP_ID @TAP_ID@ +#define TAP_WIN32_MIN_MAJOR @TAP_WIN32_MIN_MAJOR@ +#define TAP_WIN32_MIN_MINOR @TAP_WIN32_MIN_MINOR@ + +/* Enable client/server capability */ +#define ENABLE_CLIENT_SERVER 1 + +/* Enable client capability only */ +/* #undef ENABLE_CLIENT_ONLY */ + +/* Enable management server capability */ +#define ENABLE_MANAGEMENT 1 + +/* Enable PKCS#11 support */ +#define USE_PKCS11 1 + +/* Enable HTTP proxy support */ +#define ENABLE_HTTP_PROXY 1 + +/* Enable Socks proxy support */ +#define ENABLE_SOCKS 1 + +/* Enable internal fragmentation support */ +#define ENABLE_FRAGMENT 1 + +/* Enable smaller executable size */ +/* #undef ENABLE_SMALL */ + +/* Enable debugging support */ +#define ENABLE_DEBUG 1 + +/* if defined, will allow usage of the --plugin directive */ +#define USE_LOAD_LIBRARY + +/* Dimension size to use for empty array declaration */ +#define EMPTY_ARRAY_SIZE 0 + +/* Define to 1 if you have the `getsockname' function. */ +#define HAVE_GETSOCKNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the `ENGINE_register_all_complete' function. */ +#define HAVE_ENGINE_REGISTER_ALL_COMPLETE 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +#define HAVE_ENGINE_CLEANUP 1 + +/* gettimeofday() is implemented in otime.c for Windows */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the 'chsize' function. */ +#define HAVE_CHSIZE 1 + +/* Define to 1 if you have the `chdir' function. */ +#define HAVE_CHDIR 1 + +/* Define to 1 if your compiler supports GNU GCC-style variadic macros */ +#ifndef _MSC_VER /* Defines MSFT compiler version. Defined as 1200 for MSVC++ 6.0. */ +#define HAVE_CPP_VARARG_MACRO_GCC 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `EVP_CIPHER_CTX_set_key_length' function. */ +#define HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getsockopt' function. */ +#define HAVE_GETSOCKOPT 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#define HAVE_INET_NTOA 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `setsockopt' function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `system' function. */ +#define HAVE_SYSTEM 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_SYS_FILE_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_SYS_TIME_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `time' function. */ +#define HAVE_TIME 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +#define HAVE_UNISTD_H 1 +#endif + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Special Windows version of getpass() defined in io.c */ +#define HAVE_GETPASS 1 + +/* Name of package */ +#define PACKAGE @PACKAGE@ + +/* Define to the address where bug reports for this package should be sent. */ +//#define PACKAGE_BUGREPORT "openvpn-users@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME @PACKAGE_NAME@ + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME @PACKAGE_TARNAME@ + +/* Define to the version of this package. */ +#define PACKAGE_VERSION @PACKAGE_VERSION@ + +/* Define to the full name and version of this package. */ +#ifdef DEBUG_LABEL +#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION " " DEBUG_LABEL +#else +#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION +#endif + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of a `unsigned int', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The size of a `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* A string representing our target */ +#ifdef _MSC_VER +#define TARGET_ALIAS "Win32-MSVC++" +#else +#define TARGET_ALIAS "Win32-MinGW" +#endif + +/* Define to 1 if you can safely include both and . */ +#ifndef _MSC_VER +#define TIME_WITH_SYS_TIME 1 +#endif + +/* Use OpenSSL crypto library */ +#define USE_CRYPTO 1 + +/* Use LZO compression library */ +#define USE_LZO 1 + +/* LZO version number */ +#define LZO_VERSION_NUM "2" + +/* Use lzo/ directory prefix for LZO header files (for LZO 2.0) */ +#define LZO_HEADER_DIR 1 + +/* Use OpenSSL SSL library */ +#define USE_SSL 1 + +/* Version number of package */ +#define VERSION PACKAGE_VERSION + +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +#define inline __inline + +/* type to use in place of socklen_t if not defined */ +#define socklen_t unsigned int + +/* 32-bit unsigned type */ +#define uint32_t unsigned int + +/* 16-bit unsigned type */ +#define uint16_t unsigned short + +/* 8-bit unsigned type */ +#define uint8_t unsigned char + +/* Route command */ +#define ROUTE_PATH "route" + +/* Windows doesn't support PTHREAD yet */ +#ifdef USE_PTHREAD +#error The Windows version of OpenVPN does not support PTHREAD yet +#endif + +#ifdef _MSC_VER +/* MSVC++ hacks */ +#include +#include +#define vsnprintf _vsnprintf +#define vsnwprintf _vsnwprintf +#define snwprintf _snwprintf +#define write _write +#define open _open +#define read _read +#define close _close +#define chdir _chdir +#define S_IRUSR 0 +#define S_IWUSR 0 +typedef int intptr_t; +#undef S_NORMAL +/* Visual Studio 2005 supports vararg macros */ +#if _MSC_VER >= 1400 +#define HAVE_CPP_VARARG_MACRO_ISO 1 +#endif +#endif diff --git a/configure.ac b/configure.ac index 1302494..ee8ae0b 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,39 @@ AC_INIT([OpenVPN], [PRODUCT_VERSION], [openvpn-users@lists.sourceforge.net], [op AM_CONFIG_HEADER(config.h) AC_CONFIG_SRCDIR(syshead.h) +dnl Guess host type. +AC_CANONICAL_HOST +AC_CANONICAL_SYSTEM +AM_INIT_AUTOMAKE(openvpn, [$PACKAGE_VERSION]) + +AC_ARG_WITH(cygwin-native, + [ --with-cygwin-native Compile native win32], + [CYGWIN_NATIVE="${withval}"], + [CYGWIN_NATIVE="no"] +) + +WIN32="no" +CYGWIN="no" +case "${host}" in + *-mingw32*) + WIN32="yes" + cross_compiling="yes" + ;; + *-cygwin*) + AC_MSG_CHECKING([cygwin mode to use]) + if test "${CYGWIN_NATIVE}" = "yes"; then + AC_MSG_RESULT([Using native win32]) + CFLAGS="${CFLAGS} -mno-cygwin" + CYGWIN="yes" + WIN32="yes" + else + AC_MSG_RESULT([Using cygwin]) + fi + ;; + *) + ;; +esac + AC_ARG_ENABLE(lzo, [ --disable-lzo Disable LZO compression support], [LZO="$enableval"], @@ -183,6 +216,17 @@ AC_ARG_WITH(lzo-lib, [LDFLAGS="$LDFLAGS -L$withval"] ) +AC_ARG_WITH(pkcs11-helper-headers, + [ --with-pkcs11-helper-headers=DIR pkcs11-helper Include files location], + [PKCS11_HELPER_HDR_DIR="$withval"] + [CPPFLAGS="$CPPFLAGS -I$withval"] +) + +AC_ARG_WITH(pkcs11-helper-lib, + [ --with-pkcs11-helper-lib=DIR pkcs11-helper Library location], + [LDFLAGS="$LDFLAGS -L$withval"] +) + AC_ARG_WITH(ifconfig-path, [ --with-ifconfig-path=PATH Path to ifconfig tool], [IFCONFIG="$withval"], @@ -210,11 +254,6 @@ AC_ARG_WITH(mem-check, [MEMCHECK="$withval"] ) -dnl Guess host type. -AC_CANONICAL_HOST -AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE(openvpn, [$PACKAGE_VERSION]) - dnl fix search path, to allow compilers to find syshead.h CPPFLAGS="$CPPFLAGS -I${srcdir}" @@ -250,10 +289,16 @@ case "$target" in CPPFLAGS="$CPPFLAGS -no-cpp-precomp" ;; *mingw*) - AC_MSG_RESULT([WARNING: configure support for mingw is incomplete]) - AC_MSG_RESULT([WARNING: use makefile.w32 instead]) + AC_DEFINE(TARGET_WIN32, 1, [Are we running WIN32?]) OPENVPN_ADD_LIBS(-lgdi32) - OPENVPN_ADD_LIBS(-lwsock32) + OPENVPN_ADD_LIBS(-lws2_32) + OPENVPN_ADD_LIBS(-lwininet) + OPENVPN_ADD_LIBS(-lcrypt32) + OPENVPN_ADD_LIBS(-liphlpapi) + OPENVPN_ADD_LIBS(-lwinmm) + ;; +*dragonfly*) + AC_DEFINE(TARGET_DRAGONFLY, 1, [Are we running on DragonFlyBSD?]) ;; esac @@ -263,6 +308,12 @@ AC_PROG_CC AC_PROG_INSTALL AC_PROG_GCC_TRADITIONAL +if test "${WIN32}" = "yes"; then + AC_ARG_VAR([MAN2HTML], [man2html utility]) + AC_CHECK_PROGS([MAN2HTML], [man2html]) + test -z "${MAN2HTML}" && AC_MSG_ERROR([man2html is required for win32]) +fi + dnl Checks for header files. AC_HEADER_STDC @@ -274,29 +325,36 @@ AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_UID_T +TYPE_SOCKLEN_T AC_HEADER_TIME AX_CPP_VARARG_MACRO_ISO AX_CPP_VARARG_MACRO_GCC AX_EMPTY_ARRAY dnl Check for more header files. -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/ioctl.h sys/stat.h dnl +AC_CHECK_HEADERS(fcntl.h stdlib.h dnl + stdarg.h stdio.h string.h dnl + strings.h ctype.h errno.h dnl +) + +if test "${WIN32}" != "yes"; then + AC_HEADER_SYS_WAIT + AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/ioctl.h sys/stat.h dnl sys/mman.h fcntl.h sys/file.h stdlib.h stdint.h dnl stdarg.h unistd.h signal.h stdio.h string.h dnl strings.h ctype.h errno.h syslog.h pwd.h grp.h dnl - net/if_tun.h stropts.h sys/sockio.h dnl + net/if_tun.h net/tun/if_tun.h stropts.h sys/sockio.h dnl netinet/in.h netinet/in_systm.h dnl netinet/tcp.h arpa/inet.h dnl netdb.h sys/uio.h linux/if_tun.h linux/sockios.h dnl linux/types.h sys/poll.h sys/epoll.h err.h dnl -) -AC_CHECK_HEADERS(net/if.h,,, + ) + AC_CHECK_HEADERS(net/if.h,,, [#ifdef HAVE_SYS_SOCKET_H # include #endif ]) -AC_CHECK_HEADERS(netinet/ip.h,,, + AC_CHECK_HEADERS(netinet/ip.h,,, [#ifdef HAVE_SYS_TYPES_H # include #endif @@ -307,7 +365,7 @@ AC_CHECK_HEADERS(netinet/ip.h,,, # include #endif ]) -AC_CHECK_HEADERS(netinet/if_ether.h,,, + AC_CHECK_HEADERS(netinet/if_ether.h,,, [#ifdef HAVE_SYS_TYPES_H # include #endif @@ -318,16 +376,18 @@ AC_CHECK_HEADERS(netinet/if_ether.h,,, # include #endif ]) -AC_CHECK_HEADERS(resolv.h,,, + AC_CHECK_HEADERS(resolv.h,,, [#ifdef HAVE_NETINET_IN_H # include #endif ]) -AC_CHECK_HEADERS(linux/errqueue.h,,, + AC_CHECK_HEADERS(linux/errqueue.h,,, [#ifdef HAVE_LINUX_TYPES_H # include #endif ]) +fi + AC_CACHE_SAVE dnl check that in_addr_t is defined @@ -398,35 +458,59 @@ AC_CHECK_SIZEOF(unsigned long) AC_CACHE_SAVE -dnl check for other types -TYPE_SOCKLEN_T -AC_TYPE_SIGNAL - -dnl Check for libsocket -AC_SEARCH_LIBS(socket, socket) - -dnl Check for libnsl -AC_SEARCH_LIBS(inet_ntoa, nsl) - -dnl Check for libresolv -AC_SEARCH_LIBS(gethostbyname, resolv nsl) - -dnl optional library functions -AC_FUNC_FORK AC_CHECK_FUNCS(daemon chroot getpwnam setuid nice system getpid dup dup2 dnl getpass strerror syslog openlog mlockall getgrnam setgid dnl setgroups stat flock readv writev setsockopt getsockopt dnl - setsid chdir gettimeofday putenv getpeername unlink dnl - poll chsize ftruncate sendmsg recvmsg getsockname) + setsid chdir putenv getpeername unlink dnl + poll chsize ftruncate sendmsg recvmsg getsockname) AC_CACHE_SAVE +if test "${WIN32}" = "yes"; then + + AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [We fake gettimeofday for win32 at otime.c]) + +else + + dnl check for other types + AC_TYPE_SIGNAL + + dnl Check for libsocket + AC_SEARCH_LIBS(socket, socket) + + dnl Check for libnsl + AC_SEARCH_LIBS(inet_ntoa, nsl) + + dnl Check for libresolv + AC_SEARCH_LIBS(gethostbyname, resolv nsl) + + dnl optional library functions + AC_FUNC_FORK + + AC_CHECK_FUNCS(gettimeofday) + + AC_CHECK_FUNCS(socket recv recvfrom send sendto listen dnl + accept connect bind select gethostbyname dnl + inet_ntoa time ctime memset vsnprintf strdup, [], + [AC_MSG_ERROR([Required library function not found])]) + +fi + dnl Required library functions AC_FUNC_MEMCMP -AC_CHECK_FUNCS(socket recv recvfrom send sendto listen dnl - accept connect bind select gethostbyname dnl - inet_ntoa time ctime memset vsnprintf strdup, [], - [AC_MSG_ERROR([Required library function not found])]) +dnl +dnl Check for res_init +dnl +AC_TRY_LINK([ + #include + ], [ + res_init (); + ], [ + AC_MSG_RESULT([res_init DEFINED]) + AC_DEFINE([HAVE_RES_INIT], 1, [Indicates if res_init is available]) + ], [ + AC_MSG_RESULT([res_init UNDEFINED]) + ]) dnl dnl check libraries @@ -505,21 +589,23 @@ fi dnl dnl Check for dlopen -- first try libc then libdl. dnl -if test "$PLUGINS" = "yes"; then - AC_CHECKING([for libdl Library and Header files]) - AC_CHECK_HEADER(dlfcn.h, - [AC_CHECK_FUNC(dlopen, - [AC_DEFINE(USE_LIBDL, 1, [Use libdl for dynamic library loading])], - [AC_CHECK_LIB(dl, dlopen, - [ - OPENVPN_ADD_LIBS(-ldl) - AC_DEFINE(USE_LIBDL, 1, [Use libdl for dynamic library loading]) - ], - [AC_MSG_RESULT([libdl library not found.])] - )], - )], - [AC_MSG_RESULT([libdl headers not found.])] - ) +if test "${WIN32}" != "yes"; then + if test "$PLUGINS" = "yes"; then + AC_CHECKING([for libdl Library and Header files]) + AC_CHECK_HEADER(dlfcn.h, + [AC_CHECK_FUNC(dlopen, + [AC_DEFINE(USE_LIBDL, 1, [Use libdl for dynamic library loading])], + [AC_CHECK_LIB(dl, dlopen, + [ + OPENVPN_ADD_LIBS(-ldl) + AC_DEFINE(USE_LIBDL, 1, [Use libdl for dynamic library loading]) + ], + [AC_MSG_RESULT([libdl library not found.])] + )], + )], + [AC_MSG_RESULT([libdl headers not found.])] + ) + fi fi dnl @@ -572,7 +658,7 @@ if test "$CRYPTO" = "yes"; then AC_CHECKING([that OpenSSL Library is at least version 0.9.6]) AC_EGREP_CPP(yes, [ - #include "openssl/evp.h" + #include #if SSLEAY_VERSION_NUMBER >= 0x00906000L yes #endif @@ -692,7 +778,7 @@ fi dnl enable strict compiler warnings if test "$STRICT" = "yes"; then - CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wsign-compare -Wno-unused-parameter -Wno-unused-function" + CFLAGS="$CFLAGS -Wall -Wno-unused-parameter -Wno-unused-function" fi dnl enable pedantic compiler warnings @@ -715,4 +801,37 @@ if test "$PASSWORD_SAVE" = "yes"; then AC_DEFINE(ENABLE_PASSWORD_SAVE, 1, [Allow --askpass and --auth-user-pass passwords to be read from a file]) fi -AC_OUTPUT(Makefile openvpn.spec) +TAP_ID="PRODUCT_TAP_ID" +TAP_WIN32_MIN_MAJOR="PRODUCT_TAP_WIN32_MIN_MAJOR" +TAP_WIN32_MIN_MINOR="PRODUCT_TAP_WIN32_MIN_MINOR" +AC_DEFINE_UNQUOTED(TAP_ID, "${TAP_ID}", [The TAP-Win32 id defined in tap-win32/SOURCES]) +AC_DEFINE_UNQUOTED(TAP_WIN32_MIN_MAJOR, ${TAP_WIN32_MIN_MAJOR}, [The TAP-Win32 version number is defined in tap-win32/SOURCES]) +AC_DEFINE_UNQUOTED(TAP_WIN32_MIN_MINOR, ${TAP_WIN32_MIN_MINOR}, [The TAP-Win32 version number is defined in tap-win32/SOURCES]) +AC_SUBST(TAP_ID) +AC_SUBST(TAP_WIN32_MIN_MAJOR) +AC_SUBST(TAP_WIN32_MIN_MINOR) + +win32datadir="\${datadir}/${PACKAGE}-win32" +AC_SUBST(win32datadir) +AM_CONDITIONAL(WIN32, test "${WIN32}" = "yes") + +# workaround for +#include #include #include #include #include #include -#include -#include #ifdef __MINGW32_VERSION /* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 3.1 @@ -461,3 +466,7 @@ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) } return 0; } + +#else +static void dummy (void) {} +#endif /* WIN32 */ diff --git a/doclean b/doclean index 5ffde4e..63bf5ae 100755 --- a/doclean +++ b/doclean @@ -1,16 +1,71 @@ #!/bin/sh -# Let's have a fresh start. Remove all files -# which are not source files. +# Let's have a fresh start. Remove all +# generated files. # # Run this script, then: -# touch * -# [apply any patches here] # autoreconf -i -v # ./configure # make # make install -rm -f *.o openvpn config.cache configure Makefile Makefile.in stamp-h* config.guess config.sub depcomp missing mkinstalldirs config.log config.status config.h config.h.in aclocal.m4 openvpn.spec install-sh +rm -f \ + *.o \ + service-win32/*.o \ + service-win32/*.exe \ + *.exe \ + openvpn \ + config.cache \ + configure \ + Makefile \ + Makefile.in \ + stamp-h* \ + config.guess \ + config.sub \ + depcomp \ + missing \ + mkinstalldirs \ + config.log \ + config.status \ + config.h \ + config.h.in \ + aclocal.m4 \ + openvpn.spec \ + install-sh \ + openvpn.8.html \ + config-win32.h \ + install-win32/*.exe \ + install-win32/makensis.log \ + install-win32/settings \ + install-win32/Makefile \ + install-win32/Makefile.in \ + images/Makefile \ + images/Makefile.in \ + service-win32/Makefile \ + service-win32/Makefile.in -rm -rf autom4te*.cache .deps +rm -rf \ + autom4te*.cache \ + .deps \ + */.deps \ + windest \ + autodefs \ + gen \ + tapinstall \ + install-win32/tmp + +rm -rf \ + tap-win32/objfre_w2k_x86 \ + tap-win32/dist \ + tap-win32/SOURCES \ + tap-win32/tapdrvr.cod \ + tap-win32/buildfre_wnet_amd64.wrn \ + tap-win32/buildfre_w2k_x86.wrn \ + tap-win32/objfre_wnet_amd64 \ + tap-win32/buildfre_wnet_amd64.log \ + tap-win32/buildfre_w2k_x86.log \ + tap-win32/amd64 \ + tap-win32/i386/tap0901.pdb \ + tap-win32/i386/OemWin2k.inf \ + tap-win32/i386/tap0901.map \ + tap-win32/i386/tap0901.sys diff --git a/domake-win b/domake-win index 2758656..a6fb194 100644 --- a/domake-win +++ b/domake-win @@ -6,8 +6,14 @@ # 2000 and higher, and x64 on Windows 2003 and higher. # For quick start options, see pre-built notes below. # +# Note that if you are only looking to build the +# openvpn user-space binaries (openvpn.exe +# and openvpnserv.exe) you can use the +# provided autoconf/automake build environment. +# # See top-level build configuration and settings in: # +# version.m4 # install-win32/settings.in # # Mandatory prerequisites: @@ -105,12 +111,9 @@ install-win32/getprebuilt # The exception is the last script which gathers together all files from # GENOUT and builds the installer. -# Make the OpenVPN user-space component (openvpn.exe) +# Make the OpenVPN user-space components (OpenVPN and service) install-win32/makeopenvpn -# Make the OpenVPN service -install-win32/makeservice - # Make the OpenVPN TAP driver install-win32/maketap diff --git a/error.c b/error.c index de23b3d..bb5909a 100644 --- a/error.c +++ b/error.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "error.h" diff --git a/error.h b/error.h index 148ca61..f2eaa12 100644 --- a/error.h +++ b/error.h @@ -30,7 +30,11 @@ /* #define ABORT_ON_ERROR */ +#ifdef ENABLE_PKCS11 +#define ERR_BUF_SIZE 8192 +#else #define ERR_BUF_SIZE 1024 +#endif struct gc_arena; diff --git a/event.c b/event.c index 4d82fd3..35c31e7 100644 --- a/event.c +++ b/event.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "buffer.h" diff --git a/fdmisc.c b/fdmisc.c index eb7a6fc..08fb275 100644 --- a/fdmisc.c +++ b/fdmisc.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "fdmisc.h" diff --git a/forward.c b/forward.c index 6887a3c..a38dd14 100644 --- a/forward.c +++ b/forward.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "forward.h" diff --git a/fragment.c b/fragment.c index ead098a..992b8c8 100644 --- a/fragment.c +++ b/fragment.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef ENABLE_FRAGMENT diff --git a/gentoo/openvpn.init b/gentoo/openvpn.init deleted file mode 100755 index 99fa8b2..0000000 --- a/gentoo/openvpn.init +++ /dev/null @@ -1,111 +0,0 @@ -#!/sbin/runscript - -# OpenVPN start/stop script -# Adapted to Gentoo by James Yonan - -# Originally Contributed to the OpenVPN project by -# Douglas Keller -# 2002.05.15 - -# This script does the following: -# -# - Starts an openvpn process for each .conf file it finds in -# /etc/openvpn. -# -# - If /etc/openvpn/xxx.sh exists for a xxx.conf file then it executes -# it before starting openvpn (useful for doing openvpn --mktun...). - -# - In addition to start/stop you can do: -# -# service openvpn reload - SIGHUP -# service openvpn reopen - SIGUSR1 -# service openvpn status - SIGUSR2 - -# Location of openvpn binary -openvpn=/usr/local/sbin/openvpn - -# PID directory -piddir=/var/run/openvpn - -# Our working directory (.conf files should be here) -work=/etc/openvpn - -# Our options -opts="start stop restart condrestart" - -depend() { - need net - use dns -} - -start() { - ebegin "Starting OpenVPN" - - # Load the TUN/TAP module - /sbin/modprobe tun >/dev/null 2>&1 - - if [ ! -d $piddir ]; then - mkdir $piddir - fi - - cd $work - - # Start every .conf in $work and run .sh if exists - local errors=0 - local successes=0 - local retstatus=0 - for c in `/bin/ls *.conf 2>/dev/null`; do - bn=${c%%.conf} - if [ -f "$bn.sh" ]; then - . $bn.sh - fi - rm -f $piddir/$bn.pid - $openvpn --daemon openvpn-$bn --writepid $piddir/$bn.pid --config $c --cd $work - if [ $? = 0 ]; then - successes=1 - else - errors=1 - fi - done - - # Decide status based on errors/successes. - # If at least one tunnel succeeded, we return success. - # If some tunnels succeeded and some failed, we return - # success but give a warning. - if [ $successes = 1 ]; then - if [ $errors = 1 ]; then - ewarn "Note: At least one OpenVPN tunnel failed to start" - fi - else - retstatus=1 - if [ $errors = 0 ]; then - ewarn "Note: No OpenVPN configuration files were found in $work" - fi - fi - eend $retstatus "Error starting OpenVPN" -} - -stop() { - ebegin "Stopping OpenVPN" - for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do - if [ -s $pidf ]; then - kill `cat $pidf` >/dev/null 2>&1 - fi - rm -f $pidf - done - eend 0 -} - -# this should really be in runscript.sh -started() { - if [ -L "${svcdir}/started/${myservice}" ]; then - return 1 - else - return 0 - fi -} - -# attempt to restart ONLY if we are already started -condrestart() { - started || restart -} diff --git a/gremlin.c b/gremlin.c index 0a3cf19..93b7320 100644 --- a/gremlin.c +++ b/gremlin.c @@ -27,12 +27,6 @@ * network outages when the --gremlin option is used. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef ENABLE_DEBUG diff --git a/helper.c b/helper.c index d2b3d6f..a216687 100644 --- a/helper.c +++ b/helper.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "forward.h" diff --git a/ieproxy.c b/ieproxy.c index 42b067b..89977a8 100644 --- a/ieproxy.c +++ b/ieproxy.c @@ -17,7 +17,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#include "syshead.h" + +#ifdef WIN32 + +#include #include LPCTSTR getIeHttpProxyError=NULL; @@ -135,3 +139,7 @@ LPCTSTR getIeHttpProxy() return(NULL); } } + +#else +static void dummy (void) {} +#endif /* WIN32 */ diff --git a/images/.svnignore b/images/.svnignore new file mode 100644 index 0000000..282522d --- /dev/null +++ b/images/.svnignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/images/Makefile.am b/images/Makefile.am new file mode 100644 index 0000000..d633e4d --- /dev/null +++ b/images/Makefile.am @@ -0,0 +1,41 @@ +# +# OpenVPN -- An application to securely tunnel IP networks +# over a single UDP port, with support for SSL/TLS-based +# session authentication and key exchange, +# packet encryption, packet authentication, and +# packet compression. +# +# Copyright (C) 2002-2005 OpenVPN Solutions LLC +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program (see the file COPYING included with this +# distribution); if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +images = \ + install-whirl.bmp \ + icon.ico + +if WIN32 + +imagedir = $(win32datadir)/images +dist_image_DATA = $(images) + +else + +dist_noinst_DATA = $(images) + +endif + diff --git a/init.c b/init.c index ab736f1..c7aa7be 100644 --- a/init.c +++ b/init.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "win32.h" diff --git a/install-win32/.svnignore b/install-win32/.svnignore index f3e2006..6bf320b 100644 --- a/install-win32/.svnignore +++ b/install-win32/.svnignore @@ -1 +1,5 @@ openvpn.nsi +settings +Makefile +Makefile.in +tmp diff --git a/install-win32/Makefile.am b/install-win32/Makefile.am new file mode 100644 index 0000000..80fd4be --- /dev/null +++ b/install-win32/Makefile.am @@ -0,0 +1,74 @@ +# +# OpenVPN -- An application to securely tunnel IP networks +# over a single UDP port, with support for SSL/TLS-based +# session authentication and key exchange, +# packet encryption, packet authentication, and +# packet compression. +# +# Copyright (C) 2002-2005 OpenVPN Solutions LLC +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program (see the file COPYING included with this +# distribution); if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + openvpn.nsi \ + setpath.nsi + +if WIN32 + +nodist_doc_DATA = tmp/license.txt + +confdir = $(win32datadir)/config +nodist_conf_DATA = \ + tmp/openssl.cnf.sample \ + tmp/client.ovpn \ + tmp/server.ovpn +dist_conf_DATA = \ + sample.ovpn + +easyrsadir = $(win32datadir)/easy-rsa/Windows +nodist_easyrsa_DATA = \ + $(top_srcdir)/easy-rsa/Windows/* + +keysdir = $(win32datadir)/sample-keys +nodist_keys_DATA = \ + $(top_srcdir)/sample-keys/* + +tmp: + mkdir tmp + +tmp/client.ovpn: tmp $(top_srcdir)/sample-config-files/client.conf + cp $(top_srcdir)/sample-config-files/client.conf tmp/client.ovpn + +tmp/server.ovpn: tmp $(top_srcdir)/sample-config-files/server.conf + cp $(top_srcdir)/sample-config-files/server.conf tmp/server.ovpn + +tmp/license.txt: tmp $(top_srcdir)/COPYING $(top_srcdir)/COPYRIGHT.GPL + cat $(top_srcdir)/COPYING $(top_srcdir)/COPYRIGHT.GPL > tmp/license.txt + +tmp/openssl.cnf.sample: tmp $(top_srcdir)/easy-rsa/2.0/openssl.cnf + cp $(top_srcdir)/easy-rsa/2.0/openssl.cnf tmp/openssl.cnf.sample + +clean-local: + -rm -fr tmp + +else + +dist_noinst_DATA += sample.ovpn + +endif + diff --git a/install-win32/getpkcs11helper b/install-win32/getpkcs11helper index 2a34c6e..8fcfdd4 100644 --- a/install-win32/getpkcs11helper +++ b/install-win32/getpkcs11helper @@ -7,7 +7,7 @@ if [ -d "$PKCS11_HELPER_DIR" ] ; then mkdir -p $GENOUT/lib &>/dev/null for f in libpkcs11-helper-1.dll ; do - cp $PKCS11_HELPER_DIR/bin/$f $GENOUT/lib + cp $PKCS11_HELPER_DIR/usr/local/bin/$f $GENOUT/lib if [ -z "$NO_STRIP" ]; then strip $GENOUT/lib/$f fi diff --git a/install-win32/makeopenvpn b/install-win32/makeopenvpn index e3aef48..c1a805d 100644 --- a/install-win32/makeopenvpn +++ b/install-win32/makeopenvpn @@ -1,19 +1,37 @@ #!/bin/sh +H=`pwd` + # get version.nsi definitions . autodefs/defs.sh if gcc --version &>/dev/null && [ -d "$OPENSSL_DIR" ] && [ -d "$LZO_DIR" ] && [ -d "$PKCS11_HELPER_DIR" ]; then # build OpenVPN binary - [ "$CLEAN" = "yes" ] && make -f makefile.w32 clean - make -f makefile.w32 -j $MAKE_JOBS - # copy OpenVPN executable to GENOUT/bin + if ! [ -f Makefile ]; then + autoreconf -i -v \ + && ./configure \ + --enable-strict \ + --prefix=$H/windest \ + MAN2HTML=true \ + --with-ssl-headers=$H/$OPENSSL_DIR/include \ + --with-ssl-lib=$H/$OPENSSL_DIR/out \ + --with-lzo-headers=$H/$LZO_DIR/include \ + --with-lzo-lib=$H/$LZO_DIR \ + --with-pkcs11-helper-headers=$H/$PKCS11_HELPER_DIR/usr/local/include \ + --with-pkcs11-helper-lib=$H/$PKCS11_HELPER_DIR/usr/local/lib + fi + + make -j $MAKE_JOBS && make install + + # copy OpenVPN and service executables to GENOUT/bin mkdir -p $GENOUT/bin &>/dev/null - cp $PRODUCT_UNIX_NAME.exe $GENOUT/bin + cp windest/sbin/openvpn.exe $GENOUT/bin + cp windest/sbin/openvpnserv.exe $GENOUT/bin if [ -z "$NO_STRIP" ]; then - strip $GENOUT/bin/$PRODUCT_UNIX_NAME.exe + strip $GENOUT/bin/openvpn.exe + strip $GENOUT/bin/openvpnserv.exe fi else - echo DID NOT BUILD openvpn.exe because one or more of gcc, OPENSSL_DIR, LZO_DIR, or PKCS11_HELPER_DIR directories were missing + echo DID NOT BUILD openvpn.exe and openvpnserv.exe because one or more of gcc, OPENSSL_DIR, LZO_DIR, or PKCS11_HELPER_DIR directories were missing fi diff --git a/install-win32/makeservice b/install-win32/makeservice deleted file mode 100644 index 647e178..0000000 --- a/install-win32/makeservice +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -# get version.nsi definitions -. autodefs/defs.sh - -# build OpenVPN service (openvpnserv.exe) -if [ -d "$SVC_TEMPLATE" ] ; then - # silly vista security theatre - PATCH="/tmp/p.exe" - cp `which patch` $PATCH - - # build service sources - cp $SVC_TEMPLATE/service.[ch] service-win32 - cd service-win32 - cp service.c service.c.orig - cp service.h service.h.orig - $PATCH /dev/null - cp service-win32/${PRODUCT_UNIX_NAME}serv.exe $GENOUT/bin - if [ -z "$NO_STRIP" ]; then - strip $GENOUT/bin/${PRODUCT_UNIX_NAME}serv.exe - fi -else - echo OpenVPN service not built -- template directory $SVC_TEMPLATE NOT FOUND -fi diff --git a/install-win32/settings.in b/install-win32/settings.in index b6789ee..ecf7a2c 100644 --- a/install-win32/settings.in +++ b/install-win32/settings.in @@ -19,12 +19,12 @@ # Include the OpenVPN XML-based GUI exe in the installer. # May be undefined. -!define OPENVPN_XGUI_DIR "../ovpnxml" +;!define OPENVPN_XGUI_DIR "../ovpnxml" # Prebuilt libraries. DMALLOC is optional. !define OPENSSL_DIR "../openssl-0.9.7m" !define LZO_DIR "../lzo-2.02" -!define PKCS11_HELPER_DIR "../pkcs11-helper/usr/local" +!define PKCS11_HELPER_DIR "../pkcs11-helper" !define DMALLOC_DIR "../dmalloc-5.4.2" # Optional directory of prebuilt OpenVPN binary components, @@ -36,10 +36,10 @@ # Not needed if DRVBINSRC is defined. !define TISRC "../tapinstall" -# TAP Adapter parameters. +# TAP Adapter parameters. Note that PRODUCT_TAP_ID is +# defined in version.m4. !define PRODUCT_TAP_DEVICE_DESCRIPTION "TAP-Win32 Adapter V9" !define PRODUCT_TAP_PROVIDER "TAP-Win32 Provider V9" -!define PRODUCT_TAP_ID "tap0901" !define PRODUCT_TAP_MAJOR_VER 9 !define PRODUCT_TAP_MINOR_VER 4 !define PRODUCT_TAP_RELDATE "01/22/2008" @@ -50,10 +50,6 @@ # Build debugging version of TAP driver ;!define PRODUCT_TAP_DEBUG -# Service template files service.[ch] (get from Platform SDK). -# If undefined, don't build openvpnserv.exe -!define SVC_TEMPLATE "../svc-template" - # DDK Version. # DDK distribution is assumed to be in C:\WINDDK\${DDKVER} !define DDKVER 6001.17121 diff --git a/interval.c b/interval.c index 7221e03..d9aa1e9 100644 --- a/interval.c +++ b/interval.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "interval.h" diff --git a/list.c b/list.c index bdd1608..8849957 100644 --- a/list.c +++ b/list.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/lladdr.c b/lladdr.c index 1daa379..ad28dcf 100644 --- a/lladdr.c +++ b/lladdr.c @@ -2,12 +2,6 @@ * Support routine for configuring link layer address */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "error.h" #include "misc.h" diff --git a/lzo.c b/lzo.c index c16e035..536e21e 100644 --- a/lzo.c +++ b/lzo.c @@ -22,16 +22,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #ifdef USE_LZO -#include "syshead.h" - #include "lzo.h" #include "error.h" #include "otime.h" diff --git a/makefile.w32 b/makefile.w32 deleted file mode 100755 index 1623ec8..0000000 --- a/makefile.w32 +++ /dev/null @@ -1,204 +0,0 @@ -# This Makefile builds the user-mode component -# of OpenVPN for WIN32 in the MinGW environment. -# -# Build Dependencies: -# mingw (GNU C compiler for windows) -# msys (GNU utilities and shell for windows) -# OpenSSL (SSL/TLS/crypto library) -# LZO (real-time compression library) -# Dmalloc (debugging only) -# -# Targets: -# static -- link statically with OpenSSL -# dynamic -- link dynamically with OpenSSL -# dmalloc -- enable memory debugging using the dmalloc library -# -# Note that LZO is always linked statically. -# -# To build openssl-0.9.7d, remember to edit ms\mw.bat -# adding '--win32' flag to make command: -# -# make --win32 -f ms/mingw32.mak -# -# Now cd to top level openssl directory in a Windows -# command-prompt window, and type: -# -# ms\mw -# -# See additional .bat scripts in install-win32 for OpenSSL -# build setup. -# -# If you are building with dmalloc debugging support -# see windbg.h for additional dmalloc notes. - -######################################################### -# Change these to point to your OpenSSL, LZO, and -# (optionally) dmalloc top-level directories. -# Normally set as environmental variables before calling -# make. -# -#OPENSSL_DIR = -#LZO_DIR = -#DMALLOC_DIR = -#PKCS11_HELPER_DIR = - -######################################################### - -CC = gcc -g -O2 -Wall -Wno-unused-function -Wno-unused-variable -mno-cygwin - -CC_DMALLOC = gcc -g -O2 -Wall -Wno-unused-function -Wno-unused-variable -mno-cygwin -fno-inline -DDMALLOC - -INCLUDE_DIRS = -I${OPENSSL_DIR}/include -I${LZO_DIR}/include -I${PKCS11_HELPER_DIR}/include - -INCLUDE_DIRS_DMALLOC = ${INCLUDE_DIRS} -I${DMALLOC_DIR} - -LIBS = -llzo2 -lcrypt32 -lWinInet -lws2_32 -lgdi32 -liphlpapi -lwinmm -lpkcs11-helper - -LIBS_DMALLOC = ${LIBS} -ldmalloc - -LIB_DIRS = -L${OPENSSL_DIR}/out -L${LZO_DIR} -L${PKCS11_HELPER_DIR}/lib - -LIB_DIRS_DMALLOC = ${LIB_DIRS} -L${DMALLOC_DIR} - -EXE = ${PRODUCT_UNIX_NAME}.exe - -HEADERS = \ - base64.h \ - basic.h \ - buffer.h \ - circ_list.h \ - common.h \ - tap-win32/common.h \ - config-win32.h \ - crypto.h \ - cryptoapi.h \ - errlevel.h \ - error.h \ - event.h \ - fdmisc.h \ - forward-inline.h \ - forward.h \ - fragment.h \ - gremlin.h \ - helper.h \ - init.h \ - integer.h \ - interval.h \ - list.h \ - lladdr.h \ - lzo.h \ - manage.h \ - mbuf.h \ - memdbg.h \ - misc.h \ - mroute.h \ - mss.h \ - mtcp.h \ - mtu.h \ - mudp.h \ - multi.h \ - ntlm.h \ - occ-inline.h \ - occ.h \ - pkcs11.h \ - openvpn.h \ - openvpn-plugin.h \ - options.h \ - otime.h \ - packet_id.h \ - perf.h \ - ping-inline.h \ - ping.h \ - plugin.h \ - pool.h \ - proto.h \ - proxy.h \ - push.h \ - reliable.h \ - route.h \ - schedule.h \ - session_id.h \ - shaper.h \ - sig.h \ - socket.h \ - socks.h \ - ssl.h \ - status.h \ - syshead.h \ - thread.h \ - tun.h \ - win32.h - -OBJS = base64.o \ - buffer.o \ - crypto.o \ - cryptoapi.o \ - error.o \ - event.o \ - fdmisc.o \ - forward.o \ - fragment.o \ - gremlin.o \ - helper.o \ - init.o \ - interval.o \ - list.o \ - lladdr.o \ - lzo.o \ - manage.o \ - mbuf.o \ - misc.o \ - mroute.o \ - mss.o \ - mtcp.o \ - mtu.o \ - mudp.o \ - multi.o \ - ntlm.o \ - occ.o \ - pkcs11.o \ - openvpn.o \ - options.o \ - otime.o \ - packet_id.o \ - perf.o \ - ping.o \ - plugin.o \ - pool.o \ - proto.o \ - proxy.o \ - push.o \ - reliable.o \ - route.o \ - schedule.o \ - session_id.o \ - shaper.o \ - sig.o \ - socket.o \ - socks.o \ - ssl.o \ - status.o \ - thread.o \ - tun.o \ - win32.o - -dynamic : MY_CC = ${CC} -dynamic : MY_INCLUDE_DIRS = ${INCLUDE_DIRS} -dynamic : ${OBJS} - ${MY_CC} -o ${EXE} ${OBJS} ${LIB_DIRS} -lssl32 -leay32 ${LIBS} - -static : MY_CC = ${CC} -static : MY_INCLUDE_DIRS = ${INCLUDE_DIRS} -static : ${OBJS} - ${CC} -o ${EXE} ${OBJS} ${LIB_DIRS} -lssl -lcrypto ${LIBS} - -dmalloc : MY_CC = ${CC_DMALLOC} -dmalloc : MY_INCLUDE_DIRS = ${INCLUDE_DIRS_DMALLOC} -dmalloc : ${OBJS} - ${MY_CC} -o ${EXE} ${OBJS} ${LIB_DIRS_DMALLOC} -lssl32 -leay32 ${LIBS_DMALLOC} - -clean : - rm -f ${OBJS} ${EXE} - -%.o : %.c ${HEADERS} - ${MY_CC} ${MY_INCLUDE_DIRS} -c $< -o $@ diff --git a/manage.c b/manage.c index 558b01b..090f691 100644 --- a/manage.c +++ b/manage.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef ENABLE_MANAGEMENT @@ -45,6 +39,10 @@ #include "memdbg.h" +#ifdef ENABLE_PKCS11 +#include "pkcs11.h" +#endif + #define MANAGEMENT_ECHO_PULL_INFO 0 #if MANAGEMENT_ECHO_PULL_INFO @@ -82,8 +80,14 @@ man_help () msg (M_CLIENT, "mute [n] : Set log mute level to n, or show level if n is absent."); msg (M_CLIENT, "needok type action : Enter confirmation for NEED-OK request of 'type',"); msg (M_CLIENT, " where action = 'ok' or 'cancel'."); + msg (M_CLIENT, "needstr type action : Enter confirmation for NEED-STR request of 'type',"); + msg (M_CLIENT, " where action is reply string."); msg (M_CLIENT, "net : (Windows only) Show network info and routing table."); msg (M_CLIENT, "password type p : Enter password p for a queried OpenVPN password."); +#ifdef ENABLE_PKCS11 + msg (M_CLIENT, "pkcs11-id-count : Get number of available PKCS#11 identities."); + msg (M_CLIENT, "pkcs11-id-get index : Get PKCS#11 identity at index."); +#endif msg (M_CLIENT, "signal s : Send signal s to daemon,"); msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2."); msg (M_CLIENT, "state [on|off] [N|all] : Like log, but show state history."); @@ -541,6 +545,10 @@ man_up_finalize (struct management *man) if (strlen (man->connection.up_query.password)) man->connection.up_query.defined = true; break; + case UP_QUERY_NEED_STR: + if (strlen (man->connection.up_query.password)) + man->connection.up_query.defined = true; + break; default: ASSERT (0); } @@ -603,6 +611,13 @@ man_query_need_ok (struct management *man, const char *type, const char *action) man_query_user_pass (man, type, action, needed, "needok-confirmation", man->connection.up_query.password, USER_PASS_LEN); } +static void +man_query_need_str (struct management *man, const char *type, const char *action) +{ + const bool needed = ((man->connection.up_query_mode == UP_QUERY_NEED_STR) && man->connection.up_query_type); + man_query_user_pass (man, type, action, needed, "needstr-string", man->connection.up_query.password, USER_PASS_LEN); +} + static void man_forget_passwords (struct management *man) { @@ -623,6 +638,33 @@ man_net (struct management *man) } } +#ifdef ENABLE_PKCS11 + +static void +man_pkcs11_id_count (struct management *man) +{ + msg (M_CLIENT, ">PKCS11ID-COUNT:%d", pkcs11_management_id_count ()); +} + +static void +man_pkcs11_id_get (struct management *man, const int index) +{ + char *id = NULL; + char *base64 = NULL; + + if (pkcs11_management_id_get (index, &id, &base64)) + msg (M_CLIENT, ">PKCS11ID-ENTRY:'%d', ID:'%s', BLOB:'%s'", index, id, base64); + else + msg (M_CLIENT, ">PKCS11ID-ENTRY:'%d'", index); + + if (id != NULL) + free (id); + if (base64 != NULL) + free (base64); +} + +#endif + static void man_hold (struct management *man, const char *cmd) { @@ -807,6 +849,11 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch if (man_need (man, p, 2, 0)) man_query_need_ok (man, p[1], p[2]); } + else if (streq (p[0], "needstr")) + { + if (man_need (man, p, 2, 0)) + man_query_need_str (man, p[1], p[2]); + } else if (streq (p[0], "net")) { man_net (man); @@ -820,6 +867,17 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch if (man_need (man, p, 1, 0)) man_bytecount (man, atoi(p[1])); } +#ifdef ENABLE_PKCS11 + else if (streq (p[0], "pkcs11-id-count")) + { + man_pkcs11_id_count (man); + } + else if (streq (p[0], "pkcs11-id-get")) + { + if (man_need (man, p, 1, 0)) + man_pkcs11_id_get (man, atoi(p[1])); + } +#endif #if 1 else if (streq (p[0], "test")) { @@ -2037,6 +2095,12 @@ management_query_user_pass (struct management *man, prefix= "NEED-OK"; alert_type = "confirmation"; } + else if (flags & GET_USER_PASS_NEED_STR) + { + up_query_mode = UP_QUERY_NEED_STR; + prefix= "NEED-STR"; + alert_type = "string"; + } else if (flags & GET_USER_PASS_PASSWORD_ONLY) { up_query_mode = UP_QUERY_PASS; @@ -2054,7 +2118,7 @@ management_query_user_pass (struct management *man, type, alert_type); - if (flags & GET_USER_PASS_NEED_OK) + if (flags & (GET_USER_PASS_NEED_OK | GET_USER_PASS_NEED_STR)) buf_printf (&alert_msg, " MSG:%s", up->username); man_wait_for_client_connection (man, &signal_received, 0, MWCC_PASSWORD_WAIT); diff --git a/manage.h b/manage.h index 9150fb1..fed14b7 100644 --- a/manage.h +++ b/manage.h @@ -222,6 +222,7 @@ struct man_settings { #define UP_QUERY_USER_PASS 1 #define UP_QUERY_PASS 2 #define UP_QUERY_NEED_OK 3 +#define UP_QUERY_NEED_STR 4 /* states */ #define MS_INITIAL 0 /* all sockets are closed */ diff --git a/management/management-notes.txt b/management/management-notes.txt index dcbc7ce..73f82a5 100644 --- a/management/management-notes.txt +++ b/management/management-notes.txt @@ -382,7 +382,7 @@ Command examples: Query for new input and retry. COMMAND -- needok (OpenVPN 2.1 or higher) --------------------------------------- +------------------------------------------ Confirm a ">NEED-OK" real-time notification, normally used by OpenVPN to block while waiting for a specific user action. @@ -403,6 +403,47 @@ Example: or needok token-insertion-request cancel +COMMAND -- needstr (OpenVPN 2.1 or higher) +------------------------------------------- + +Confirm a ">NEED-STR" real-time notification, normally used by +OpenVPN to block while waiting for a specific user input. + +Example: + + OpenVPN needs the user to specify some input, so it sends a + real-time notification: + + >NEED-STR:Need 'name' input MSG:Please specify your name + + The management client, if it is a GUI, can flash a dialog + box containing the text after the "MSG:" marker to the user. + When the user acknowledges the dialog box, + the management client can issue this command: + + needstr name "John" + +COMMAND -- pkcs11-id-count (OpenVPN 2.1 or higher) +--------------------------------------------------- + +Retrieve available number of certificates. + +Example: + + pkcs11-id-count + >PKCS11ID-COUNT:5 + +COMMAND -- pkcs11-id-get (OpenVPN 2.1 or higher) +------------------------------------------------- + +Retrieve certificate by index, the ID string should be provided +as PKCS#11 identity, the blob is BASE64 encoded certificate. + +Example: + + pkcs11-id-get 1 + PKCS11ID-ENTRY:'1', ID:'', BLOB:'' + OUTPUT FORMAT ------------- @@ -445,6 +486,10 @@ NEED-OK -- OpenVPN needs the end user to do something, such as insert a cryptographic token. The "needok" command can be used to tell OpenVPN to continue. +NEED-STR -- OpenVPN needs information from end, such as + a certificate to use. The "needstr" command can + be used to tell OpenVPN to continue. + PASSWORD -- Used to tell the management client that OpenVPN needs a password, also to indicate password verification failure. @@ -460,11 +505,11 @@ as is used by the OpenVPN config file parser. Whitespace is a parameter separator. -Double quotation characters ("") can be used to enclose -parameters containing whitespace. +Double quotation or single quotation characters ("", '') can be used +to enclose parameters containing whitespace. Backslash-based shell escaping is performed, using the following -mappings: +mappings, when not in single quotations: \\ Maps to a single backslash character (\). \" Pass a literal doublequote character ("), don't diff --git a/mbuf.c b/mbuf.c index 871bdba..ac348ab 100644 --- a/mbuf.c +++ b/mbuf.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP diff --git a/misc.c b/misc.c index 2821408..f4edefa 100644 --- a/misc.c +++ b/misc.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "buffer.h" @@ -206,7 +200,7 @@ run_up_down (const char *command, ASSERT (arg); buf_printf (&cmd, - "%s %d %d %s %s %s", + "\"%s\" %d %d %s %s %s", arg, tun_mtu, link_mtu, ifconfig_local, ifconfig_remote, @@ -225,7 +219,7 @@ run_up_down (const char *command, setenv_str (es, "script_type", script_type); buf_printf (&cmd, - "%s %s %d %d %s %s %s", + "%s \"%s\" %d %d %s %s %s", command, arg, tun_mtu, link_mtu, @@ -438,6 +432,7 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag void warn_if_group_others_accessible (const char* filename) { +#ifndef WIN32 #ifdef HAVE_STAT #if ENABLE_INLINE_FILES if (strcmp (filename, INLINE_FILE_TAG)) @@ -455,6 +450,7 @@ warn_if_group_others_accessible (const char* filename) } } #endif +#endif } /* @@ -1230,7 +1226,7 @@ get_user_pass (struct user_pass *up, if ((flags & GET_USER_PASS_NOFATAL) != 0) return false; else - msg (M_FATAL, "ERROR: could not read %s username/password/ok from management interface", prefix); + msg (M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix); } } else diff --git a/misc.h b/misc.h index 5b7f227..f01695f 100644 --- a/misc.h +++ b/misc.h @@ -227,7 +227,11 @@ struct user_pass bool nocache; /* max length of username/password */ -# define USER_PASS_LEN 128 +# ifdef ENABLE_PKCS11 +# define USER_PASS_LEN 4096 +# else +# define USER_PASS_LEN 128 +# endif char username[USER_PASS_LEN]; char password[USER_PASS_LEN]; }; @@ -242,6 +246,7 @@ bool get_console_input (const char *prompt, const bool echo, char *input, const #define GET_USER_PASS_PASSWORD_ONLY (1<<2) #define GET_USER_PASS_NEED_OK (1<<3) #define GET_USER_PASS_NOFATAL (1<<4) +#define GET_USER_PASS_NEED_STR (1<<5) bool get_user_pass (struct user_pass *up, const char *auth_file, diff --git a/mroute.c b/mroute.c index a7d1215..5922b8a 100644 --- a/mroute.c +++ b/mroute.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/mss.c b/mss.c index 25e77b0..deaa02e 100644 --- a/mss.c +++ b/mss.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "error.h" #include "mss.h" diff --git a/mtcp.c b/mtcp.c index 6ec9974..555b1e8 100644 --- a/mtcp.c +++ b/mtcp.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/mtu.c b/mtu.c index 14df3b6..1b93bf0 100644 --- a/mtu.c +++ b/mtu.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "common.h" diff --git a/mudp.c b/mudp.c index fa2ae17..a430d60 100644 --- a/mudp.c +++ b/mudp.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/multi.c b/multi.c index fa924f1..2a74cda 100644 --- a/multi.c +++ b/multi.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/ntlm.c b/ntlm.c index 4e12047..ff4e2f5 100644 --- a/ntlm.c +++ b/ntlm.c @@ -3,6 +3,8 @@ * * Copyright (C) 2004 William Preston * + * *NTLMv2 support and domain name parsing by Miroslav Zajic, Nextsoft s.r.o.* + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -19,12 +21,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if NTLM @@ -41,6 +37,21 @@ #include "memdbg.h" + +/* 64bit datatype macros */ +#ifdef _MSC_VER + /* MS compilers */ +# define UINTEGER64 __int64 +# define UINT64(c) c ## Ui64 +#else + /* Non MS compilers */ +# define UINTEGER64 unsigned long long +# define UINT64(c) c ## LL +#endif + + + + static void create_des_keys(const unsigned char *hash, unsigned char *key) { @@ -70,6 +81,61 @@ gen_md4_hash (const char* data, int data_len, char *result) memcpy (result, md, 16); } +static void +gen_hmac_md5 (const char* data, int data_len, const char* key, int key_len,char *result) +{ + unsigned int len; + + HMAC_CTX c; + HMAC_Init (&c, key, key_len, EVP_md5()); + HMAC_Update (&c, data, data_len); + HMAC_Final (&c, result, &len); + HMAC_CTX_cleanup(&c); +} + +static void +gen_timestamp (unsigned char *timestamp) +{ + /* Copies 8 bytes long timestamp into "timestamp" buffer. + * Timestamp is Little-endian, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601. + */ + + UINTEGER64 timestamp_ull; + + timestamp_ull = openvpn_time(NULL); + timestamp_ull = (timestamp_ull + UINT64(11644473600)) * UINT64(10000000); + + /* store little endian value */ + timestamp[0]= timestamp_ull & UINT64(0xFF); + timestamp[1]= (timestamp_ull >> 8) & UINT64(0xFF); + timestamp[2]= (timestamp_ull >> 16) & UINT64(0xFF); + timestamp[3]= (timestamp_ull >> 24) & UINT64(0xFF); + timestamp[4]= (timestamp_ull >> 32) & UINT64(0xFF); + timestamp[5]= (timestamp_ull >> 40) & UINT64(0xFF); + timestamp[6]= (timestamp_ull >> 48) & UINT64(0xFF); + timestamp[7]= (timestamp_ull >> 56) & UINT64(0xFF); +} + +static void +gen_nonce (unsigned char *nonce) +{ + /* Generates 8 random bytes to be used as client nonce */ + int i; + + for(i=0;i<8;i++){ + nonce[i] = (unsigned char)get_random(); + } +} + +unsigned char *my_strupr(unsigned char *str) +{ + /* converts string to uppercase in place */ + unsigned char *tmp = str;; + + do *str = toupper(*str); while (*(++str)); + return tmp; +} + static int unicodize (char *dst, const char *src) { @@ -85,6 +151,18 @@ unicodize (char *dst, const char *src) return i; } +static void +add_security_buffer(int sb_offset, void *data, int length, unsigned char *msg_buf, int *msg_bufpos) +{ + /* Adds security buffer data to a message and sets security buffer's offset and length */ + msg_buf[sb_offset] = (unsigned char)length; + msg_buf[sb_offset + 2] = msg_buf[sb_offset]; + msg_buf[sb_offset + 4] = (unsigned char)(*msg_bufpos & 0xff); + msg_buf[sb_offset + 5] = (unsigned char)((*msg_bufpos >> 8) & 0xff); + memcpy(&msg_buf[*msg_bufpos], data, msg_buf[sb_offset]); + *msg_bufpos += length; +} + const char * ntlm_phase_1 (const struct http_proxy_info *p, struct gc_arena *gc) { @@ -105,23 +183,56 @@ ntlm_phase_1 (const struct http_proxy_info *p, struct gc_arena *gc) const char * ntlm_phase_3 (const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc) { + /* NTLM handshake + * + * http://davenport.sourceforge.net/ntlm.html + * + */ + char pwbuf[sizeof (p->up.password) * 2]; /* for unicode password */ char buf2[128]; /* decoded reply from proxy */ - char phase3[146]; + unsigned char phase3[464]; char md4_hash[21]; - char challenge[8], response[24]; - int i, ret_val, buflen; + char challenge[8], ntlm_response[24]; + int i, ret_val; des_cblock key1, key2, key3; des_key_schedule sched1, sched2, sched3; - /* try a minimal NTLM handshake - * - * http://davenport.sourceforge.net/ntlm.html - * - */ + char ntlmv2_response[144]; + char userdomain_u[256]; /* for uppercase unicode username and domain */ + char userdomain[128]; /* the same as previous but ascii */ + char ntlmv2_hash[16]; + char ntlmv2_hmacmd5[16]; + char *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */ + int ntlmv2_blob_size=0; + int phase3_bufpos = 0x40; /* offset to next security buffer data to be added */ + int len; + + char domain[128]; + char username[128]; + char *separator; + + bool ntlmv2_enabled = (p->auth_method == HTTP_AUTH_NTLM2); + ASSERT (strlen (p->up.username) > 0); ASSERT (strlen (p->up.password) > 0); + + /* username parsing */ + separator = strchr(p->up.username, '\\'); + if (separator == NULL) { + strncpy(username, p->up.username, sizeof(username)-1); + username[sizeof(username)-1]=0; + domain[0]=0; + } else { + strncpy(username, separator+1, sizeof(username)-1); + username[sizeof(username)-1]=0; + len = separator - p->up.username; + if (len > sizeof(domain) - 1) len = sizeof(domain) - 1; + strncpy(domain, p->up.username, len); + domain[len]=0; + } + /* fill 1st 16 bytes with md4 hash, disregard terminating null */ gen_md4_hash (pwbuf, unicodize (pwbuf, p->up.password) - 2, md4_hash); @@ -139,48 +250,95 @@ ntlm_phase_3 (const struct http_proxy_info *p, const char *phase_2, struct gc_ar challenge[i] = buf2[i+24]; } - create_des_keys ((unsigned char *)md4_hash, key1); - des_set_key_unchecked ((des_cblock *)key1, sched1); - des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)response, sched1, DES_ENCRYPT); - - create_des_keys ((unsigned char *)&(md4_hash[7]), key2); - des_set_key_unchecked ((des_cblock *)key2, sched2); - des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(response[8]), sched2, DES_ENCRYPT); - - create_des_keys ((unsigned char *)&(md4_hash[14]), key3); - des_set_key_unchecked ((des_cblock *)key3, sched3); - des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(response[16]), sched3, DES_ENCRYPT); - - /* clear reply */ - memset (phase3, 0, sizeof (phase3)); - - strcpy (phase3, "NTLMSSP\0"); - phase3[8] = 3; /* type 3 */ - - buflen = 0x58 + strlen (p->up.username); - if (buflen > (int) sizeof (phase3)) - buflen = sizeof (phase3); - - phase3[0x10] = buflen; /* lm not used */ - phase3[0x20] = buflen; /* default domain (i.e. proxy's domain) */ - phase3[0x30] = buflen; /* no workstation name supplied */ - phase3[0x38] = buflen; /* no session key */ - - phase3[0x14] = 24; /* ntlm response is 24 bytes long */ - phase3[0x16] = phase3[0x14]; - phase3[0x18] = 0x40; /* ntlm offset */ - memcpy (&(phase3[0x40]), response, 24); - - - phase3[0x24] = strlen (p->up.username); /* username in ascii */ - phase3[0x26] = phase3[0x24]; - phase3[0x28] = 0x58; - strncpy (&(phase3[0x58]), p->up.username, sizeof (phase3) - 0x58); - + if (ntlmv2_enabled){ /* Generate NTLMv2 response */ + + /* NTLMv2 hash */ + my_strupr(strcpy(userdomain, username)); + if (strlen(username) + strlen(domain) < sizeof(userdomain)) + strcat(userdomain, domain); + else + msg (M_INFO, "Warning: Username or domain too long"); + unicodize (userdomain_u, userdomain); + gen_hmac_md5(userdomain_u, 2 * strlen(userdomain), md4_hash, 16, ntlmv2_hash); + + /* NTLMv2 Blob */ + memset(ntlmv2_blob, 0, 128); /* Clear blob buffer */ + ntlmv2_blob[0x00]=1; /* Signature */ + ntlmv2_blob[0x01]=1; /* Signature */ + ntlmv2_blob[0x04]=0; /* Reserved */ + gen_timestamp(&ntlmv2_blob[0x08]); /* 64-bit Timestamp */ + gen_nonce(&ntlmv2_blob[0x10]); /* 64-bit Client Nonce */ + ntlmv2_blob[0x18]=0; /* Unknown, zero should work */ + + /* Add target information block to the blob */ + int tib_len; + if (( *((long *)&buf2[0x14]) & 0x00800000) == 0x00800000){ /* Check for Target Information block */ + tib_len = buf2[0x28];/* Get Target Information block size */ + if (tib_len > 96) tib_len = 96; + char *tib_ptr = buf2 + buf2[0x2c]; /* Get Target Information block pointer */ + memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); /* Copy Target Information block into the blob */ + } else { + tib_len = 0; + } + + ntlmv2_blob[0x1c + tib_len] = 0; /* Unknown, zero works */ + + /* Get blob length */ + ntlmv2_blob_size = 0x20 + tib_len; + + /* Add challenge from message 2 */ + memcpy(&ntlmv2_response[8], challenge, 8); + + /* hmac-md5 */ + gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash, 16, ntlmv2_hmacmd5); + + /* Add hmac-md5 result to the blob */ + memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16); /* Note: This overwrites challenge previously written at ntlmv2_response[8..15] */ + + } else { /* Generate NTLM response */ + + create_des_keys ((unsigned char *)md4_hash, key1); + des_set_key_unchecked ((des_cblock *)key1, sched1); + des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)ntlm_response, sched1, DES_ENCRYPT); + + create_des_keys ((unsigned char *)&(md4_hash[7]), key2); + des_set_key_unchecked ((des_cblock *)key2, sched2); + des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(ntlm_response[8]), sched2, DES_ENCRYPT); + + create_des_keys ((unsigned char *)&(md4_hash[14]), key3); + des_set_key_unchecked ((des_cblock *)key3, sched3); + des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(ntlm_response[16]), sched3, DES_ENCRYPT); + } + + + memset (phase3, 0, sizeof (phase3)); /* clear reply */ + + strcpy (phase3, "NTLMSSP\0"); /* signature */ + phase3[8] = 3; /* type 3 */ + + if (ntlmv2_enabled){ /* NTLMv2 response */ + add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, phase3, &phase3_bufpos); + }else{ /* NTLM response */ + add_security_buffer(0x14, ntlm_response, 24, phase3, &phase3_bufpos); + } + + /* username in ascii */ + add_security_buffer(0x24, username, strlen (username), phase3, &phase3_bufpos); + + /* Set domain. If is empty, default domain will be used (i.e. proxy's domain) */ + add_security_buffer(0x1c, domain, strlen (domain), phase3, &phase3_bufpos); + + + /* other security buffers will be empty */ + phase3[0x10] = phase3_bufpos; /* lm not used */ + phase3[0x30] = phase3_bufpos; /* no workstation name supplied */ + phase3[0x38] = phase3_bufpos; /* no session key */ + + /* flags */ phase3[0x3c] = 0x02; /* negotiate oem */ phase3[0x3d] = 0x02; /* negotiate ntlm */ - return ((const char *)make_base64_string2 ((unsigned char *)phase3, buflen, gc)); + return ((const char *)make_base64_string2 ((unsigned char *)phase3, phase3_bufpos, gc)); } #else diff --git a/occ.c b/occ.c index 6b136dc..1add9d0 100644 --- a/occ.c +++ b/occ.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef ENABLE_OCC diff --git a/openvpn.8 b/openvpn.8 index cf818b3..8a239f9 100644 --- a/openvpn.8 +++ b/openvpn.8 @@ -213,6 +213,7 @@ openvpn \- secure IP tunnel daemon. [\ \fB\-\-ping\fR\ \fIn\fR\ ] [\ \fB\-\-pkcs11\-cert\-private\fR\ \fI[0|1]...\fR\ ] [\ \fB\-\-pkcs11\-id\fR\ \fIname\fR\ ] +[\ \fB\-\-pkcs11\-id\-management\fR\ ] [\ \fB\-\-pkcs11\-pin\-cache\fR\ \fIseconds\fR\ ] [\ \fB\-\-pkcs11\-private\-mode\fR\ \fImode...\fR\ ] [\ \fB\-\-pkcs11\-protected\-authentication\fR\ \fI[0|1]...\fR\ ] @@ -3691,6 +3692,13 @@ by the standalone option. .\"********************************************************* .TP +.B --pkcs11-id-management +Acquire PKCS#11 id from management interface. In this case a NEED-STR 'pkcs11-id-request' +real-time message will be triggered, application may use pkcs11-id-count command to +retrieve available number of certificates, and pkcs11-id-get command to retrieve certificate +id and certificate body. +.\"********************************************************* +.TP .B --pkcs11-pin-cache seconds Specify how many seconds the PIN can be cached, the default is until the token is removed. .\"********************************************************* diff --git a/openvpn.c b/openvpn.c index 66ade22..d3c36f9 100644 --- a/openvpn.c +++ b/openvpn.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "init.h" diff --git a/options.c b/options.c index 944c84f..1acfd6b 100644 --- a/options.c +++ b/options.c @@ -27,12 +27,6 @@ * (Christof Meerwald, http://cmeerw.org) */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "buffer.h" @@ -516,10 +510,11 @@ static const char usage_message[] = " 4 : Use Decrypt.\n" " 8 : Use Unwrap.\n" "--pkcs11-cert-private [0|1] ... : Set if login should be performed before\n" - " certificate can be accessed. Set for each provider.\n" - "--pkcs11-pin-cache seconds : Number of seconds to cache PIN. The default is -1\n" - " cache until token is removed.\n" - "--pkcs11-id serialized-id : Identity to use, get using standalone --show-pkcs11-ids\n" + " certificate can be accessed. Set for each provider.\n" + "--pkcs11-pin-cache seconds : Number of seconds to cache PIN. The default is -1\n" + " cache until token is removed.\n" + "--pkcs11-id-management : Acquire identity from management interface.\n" + "--pkcs11-id serialized-id 'id' : Identity to use, get using standalone --show-pkcs11-ids\n" #endif /* ENABLE_PKCS11 */ "\n" "SSL Library information:\n" @@ -1293,6 +1288,7 @@ show_settings (const struct options *o) } SHOW_INT (pkcs11_pin_cache_period); SHOW_STR (pkcs11_id); + SHOW_BOOL (pkcs11_id_management); #endif /* ENABLE_PKCS11 */ #if P2MP @@ -1766,8 +1762,11 @@ options_postprocess (struct options *options, bool first_time) if (options->pkcs11_providers[0]) { notnull (options->ca_file, "CA file (--ca)"); - notnull (options->pkcs11_id, "PKCS#11 id (--pkcs11-id)"); + if (options->pkcs11_id_management && options->pkcs11_id != NULL) + msg(M_USAGE, "Parameter --pkcs11-id cannot be used when --pkcs11-id-management is also specified."); + if (!options->pkcs11_id_management && options->pkcs11_id == NULL) + msg(M_USAGE, "Parameter --pkcs11-id or --pkcs11-id-management should be specified."); if (options->cert_file) msg(M_USAGE, "Parameter --cert cannot be used when --pkcs11-provider is also specified."); if (options->priv_key_file) @@ -1870,6 +1869,7 @@ options_postprocess (struct options *options, bool first_time) MUST_BE_UNDEF (pkcs11_providers[0]); MUST_BE_UNDEF (pkcs11_private_mode[0]); MUST_BE_UNDEF (pkcs11_id); + MUST_BE_UNDEF (pkcs11_id_management); #endif if (pull) @@ -5137,6 +5137,11 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_GENERAL); options->pkcs11_id = p[1]; } + else if (streq (p[0], "pkcs11-id-management")) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->pkcs11_id_management = true; + } #endif #ifdef TUNSETPERSIST else if (streq (p[0], "rmtun")) diff --git a/options.h b/options.h index 2667b71..607df0f 100644 --- a/options.h +++ b/options.h @@ -419,6 +419,7 @@ struct options bool pkcs11_cert_private[MAX_PARMS]; int pkcs11_pin_cache_period; const char *pkcs11_id; + bool pkcs11_id_management; #endif #ifdef WIN32 diff --git a/otime.c b/otime.c index d21b08b..394eea3 100644 --- a/otime.c +++ b/otime.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "otime.h" diff --git a/packet_id.c b/packet_id.c index 6bc5b6b..08e5974 100644 --- a/packet_id.c +++ b/packet_id.c @@ -31,16 +31,10 @@ * to IPSec. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #ifdef USE_CRYPTO -#include "syshead.h" - #include "packet_id.h" #include "misc.h" #include "integer.h" diff --git a/perf.c b/perf.c index 3abf8c5..85dea45 100644 --- a/perf.c +++ b/perf.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "perf.h" diff --git a/ping.c b/ping.c index bee3543..622408f 100644 --- a/ping.c +++ b/ping.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "ping.h" diff --git a/pkcs11.c b/pkcs11.c index 9a6ed77..da8e8fd 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#if defined(WIN32) -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if defined(ENABLE_PKCS11) @@ -37,6 +31,7 @@ #include "basic.h" #include "error.h" #include "manage.h" +#include "base64.h" #include "pkcs11.h" static @@ -168,7 +163,7 @@ _pkcs11_openvpn_token_prompt ( const pkcs11h_token_id_t token, const unsigned retry ) { - static struct user_pass token_resp; + struct user_pass token_resp; (void)global_data; (void)user_data; @@ -211,7 +206,7 @@ _pkcs11_openvpn_pin_prompt ( char * const pin, const size_t pin_max ) { - static struct user_pass token_pass; + struct user_pass token_pass; char prompt[1024]; (void)global_data; @@ -388,9 +383,225 @@ pkcs11_logout() { return pkcs11h_logout () == CKR_OK; } +int +pkcs11_management_id_count () { + pkcs11h_certificate_id_list_t id_list = NULL; + pkcs11h_certificate_id_list_t t = NULL; + CK_RV rv = CKR_OK; + int count = 0; + + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: pkcs11_management_id_count - entered" + ); + + if ( + (rv = pkcs11h_certificate_enumCertificateIds ( + PKCS11H_ENUM_METHOD_CACHE_EXIST, + NULL, + PKCS11H_PROMPT_MASK_ALLOW_ALL, + NULL, + &id_list + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + for (count = 0, t = id_list; t != NULL; t = t->next) { + count++; + } + +cleanup: + + if (id_list != NULL) { + pkcs11h_certificate_freeCertificateIdList (id_list); + id_list = NULL; + } + + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: pkcs11_management_id_count - return count=%d", + count + ); + + return count; +} + +bool +pkcs11_management_id_get ( + const int index, + char ** id, + char **base64 +) { + pkcs11h_certificate_id_list_t id_list = NULL; + pkcs11h_certificate_id_list_t entry = NULL; + pkcs11h_certificate_id_t certificate_id = NULL; + pkcs11h_certificate_t certificate = NULL; + CK_RV rv = CKR_OK; + char *certificate_blob = NULL; + size_t certificate_blob_size = 0; + size_t max; + char *internal_id = NULL; + char *internal_base64 = NULL; + int count = 0; + bool success = false; + + ASSERT (id!=NULL); + ASSERT (base64!=NULL); + + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: pkcs11_management_id_get - entered index=%d", + index + ); + + *id = NULL; + *base64 = NULL; + + if ( + (rv = pkcs11h_certificate_enumCertificateIds ( + PKCS11H_ENUM_METHOD_CACHE_EXIST, + NULL, + PKCS11H_PROMPT_MASK_ALLOW_ALL, + NULL, + &id_list + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + entry = id_list; + count = 0; + while (entry != NULL && count != index) { + count++; + entry = entry->next; + } + + if (entry == NULL) { + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: pkcs11_management_id_get - no certificate at index=%d", + index + ); + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_serializeCertificateId ( + NULL, + &max, + entry->certificate_id + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + if ((internal_id = (char *)malloc (max)) == NULL) { + msg (M_FATAL, "PKCS#11: Cannot allocate memory"); + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_serializeCertificateId ( + internal_id, + &max, + entry->certificate_id + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_create ( + entry->certificate_id, + NULL, + PKCS11H_PROMPT_MASK_ALLOW_ALL, + PKCS11H_PIN_CACHE_INFINITE, + &certificate + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_getCertificateBlob ( + certificate, + NULL, + &certificate_blob_size + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + if ((certificate_blob = (char *)malloc (certificate_blob_size)) == NULL) { + msg (M_FATAL, "PKCS#11: Cannot allocate memory"); + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_getCertificateBlob ( + certificate, + certificate_blob, + &certificate_blob_size + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + + if (base64_encode (certificate_blob, certificate_blob_size, &internal_base64) == -1) { + msg (M_WARN, "PKCS#11: Cannot encode certificate"); + goto cleanup; + } + + *id = internal_id; + internal_id = NULL; + *base64 = internal_base64; + internal_base64 = NULL; + success = true; + +cleanup: + + if (id_list != NULL) { + pkcs11h_certificate_freeCertificateIdList (id_list); + id_list = NULL; + } + + if (internal_id != NULL) { + free (internal_id); + internal_id = NULL; + } + + if (internal_base64 != NULL) { + free (internal_base64); + internal_base64 = NULL; + } + + if (certificate_blob != NULL) { + free (certificate_blob); + certificate_blob = NULL; + } + + dmsg ( + D_PKCS11_DEBUG, + "PKCS#11: pkcs11_management_id_get - return success=%d, id='%s'", + success ? 1 : 0, + *id + ); + + return success; +} + int SSL_CTX_use_pkcs11 ( SSL_CTX * const ssl_ctx, + bool pkcs11_id_management, const char * const pkcs11_id ) { X509 *x509 = NULL; @@ -403,23 +614,60 @@ SSL_CTX_use_pkcs11 ( bool ok = false; ASSERT (ssl_ctx!=NULL); - ASSERT (pkcs11_id!=NULL); + ASSERT (pkcs11_id_management || pkcs11_id!=NULL); dmsg ( D_PKCS11_DEBUG, - "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id='%s'", + "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'", (void *)ssl_ctx, + pkcs11_id_management ? 1 : 0, pkcs11_id ); - if ( - (rv = pkcs11h_certificate_deserializeCertificateId ( - &certificate_id, - pkcs11_id - )) != CKR_OK - ) { - msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); - goto cleanup; + if (pkcs11_id_management) { + struct user_pass id_resp; + + CLEAR (id_resp); + + id_resp.defined = false; + id_resp.nocache = true; + openvpn_snprintf ( + id_resp.username, + sizeof (id_resp.username), + "Please specify PKCS#11 id to use" + ); + + if ( + !get_user_pass ( + &id_resp, + NULL, + "pkcs11-id-request", + GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_STR|GET_USER_PASS_NOFATAL + ) + ) { + goto cleanup; + } + + if ( + (rv = pkcs11h_certificate_deserializeCertificateId ( + &certificate_id, + id_resp.password + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } + } + else { + if ( + (rv = pkcs11h_certificate_deserializeCertificateId ( + &certificate_id, + pkcs11_id + )) != CKR_OK + ) { + msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); + goto cleanup; + } } if ( diff --git a/pkcs11.h b/pkcs11.h index 4b207e7..14dd178 100644 --- a/pkcs11.h +++ b/pkcs11.h @@ -52,9 +52,20 @@ pkcs11_addProvider ( int pkcs11_logout(); +int +pkcs11_management_id_count (); + +bool +pkcs11_management_id_get ( + const int index, + char ** id, + char **base64 +); + int SSL_CTX_use_pkcs11 ( SSL_CTX * const ssl_ctx, + bool pkcs11_id_management, const char * const pkcs11_id ); diff --git a/plugin.c b/plugin.c index 7bf6912..a337e46 100644 --- a/plugin.c +++ b/plugin.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef ENABLE_PLUGIN diff --git a/pool.c b/pool.c index cb666b8..6f19d79 100644 --- a/pool.c +++ b/pool.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "pool.h" diff --git a/proto.c b/proto.c index 4e8a309..20eb9d5 100644 --- a/proto.c +++ b/proto.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "proto.h" diff --git a/proxy.c b/proxy.c index 8b208a6..620f23c 100644 --- a/proxy.c +++ b/proxy.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "common.h" @@ -294,19 +288,21 @@ new_http_proxy (const struct http_proxy_options *o, p->auth_method = HTTP_AUTH_BASIC; else if (!strcmp (o->auth_method_string, "ntlm")) p->auth_method = HTTP_AUTH_NTLM; + else if (!strcmp (o->auth_method_string, "ntlm2")) + p->auth_method = HTTP_AUTH_NTLM2; else - msg (M_FATAL, "ERROR: unknown HTTP authentication method: '%s' -- only the 'none', 'basic', or 'ntlm' methods are currently supported", + msg (M_FATAL, "ERROR: unknown HTTP authentication method: '%s' -- only the 'none', 'basic', 'ntlm', or 'ntlm2' methods are currently supported", o->auth_method_string); } - /* only basic and NTLM authentication supported so far */ - if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM) + /* only basic and NTLM/NTLMv2 authentication supported so far */ + if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) { get_user_pass_http (p, true); } #if !NTLM - if (p->auth_method == HTTP_AUTH_NTLM) + if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) msg (M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support."); #endif @@ -374,6 +370,12 @@ establish_http_proxy_passthru (struct http_proxy_info *p, #if NTLM case HTTP_AUTH_NTLM: + case HTTP_AUTH_NTLM2: + /* keep-alive connection */ + openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); + if (!send_line_crlf (sd, buf)) + goto error; + openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", ntlm_phase_1 (p, &gc)); msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1"); @@ -411,7 +413,7 @@ establish_http_proxy_passthru (struct http_proxy_info *p, msg (D_PROXY, "Proxy requires authentication"); /* check for NTLM */ - if (p->auth_method == HTTP_AUTH_NTLM) + if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) { #if NTLM /* look for the phase 2 response */ @@ -456,6 +458,12 @@ establish_http_proxy_passthru (struct http_proxy_info *p, if (!send_line_crlf (sd, buf)) goto error; + /* keep-alive connection */ + openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); + if (!send_line_crlf (sd, buf)) + goto error; + + /* send HOST etc, */ openvpn_sleep (1); openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); diff --git a/proxy.h b/proxy.h index 235f5f0..1417dbc 100644 --- a/proxy.h +++ b/proxy.h @@ -59,6 +59,7 @@ void show_win_proxy_settings (const int msglevel); #define HTTP_AUTH_BASIC 1 #define HTTP_AUTH_NTLM 2 #define HTTP_AUTH_N 3 +#define HTTP_AUTH_NTLM2 4 struct http_proxy_options { const char *server; diff --git a/ps.c b/ps.c index 49b1a2c..430a138 100644 --- a/ps.c +++ b/ps.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if PORT_SHARE diff --git a/push.c b/push.c index a725eb5..d5a757a 100644 --- a/push.c +++ b/push.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "push.h" diff --git a/reliable.c b/reliable.c index 01e1d0a..854e2b0 100644 --- a/reliable.c +++ b/reliable.c @@ -27,16 +27,10 @@ * so that SSL/TLS can be run over UDP. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #if defined(USE_CRYPTO) && defined(USE_SSL) -#include "syshead.h" - #include "buffer.h" #include "error.h" #include "common.h" diff --git a/route.c b/route.c index 507ef38..0a7e032 100644 --- a/route.c +++ b/route.c @@ -26,12 +26,6 @@ * Support routines for adding/deleting network routes. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "common.h" @@ -871,6 +865,23 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s msg (D_ROUTE, "%s", BSTR (&buf)); status = system_check (BSTR (&buf), es, 0, "ERROR: FreeBSD route add command failed"); +#elif defined(TARGET_DRAGONFLY) + + buf_printf (&buf, ROUTE_PATH " add"); + +#if 0 + if (r->metric_defined) + buf_printf (&buf, " -rtt %d", r->metric); +#endif + + buf_printf (&buf, " -net %s %s %s", + network, + gateway, + netmask); + + msg (D_ROUTE, "%s", BSTR (&buf)); + status = system_check (BSTR (&buf), es, 0, "ERROR: DragonFly route add command failed"); + #elif defined(TARGET_DARWIN) buf_printf (&buf, ROUTE_PATH " add"); @@ -1007,6 +1018,16 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags msg (D_ROUTE, "%s", BSTR (&buf)); system_check (BSTR (&buf), es, 0, "ERROR: FreeBSD route delete command failed"); +#elif defined(TARGET_DRAGONFLY) + + buf_printf (&buf, ROUTE_PATH " delete -net %s %s %s", + network, + gateway, + netmask); + + msg (D_ROUTE, "%s", BSTR (&buf)); + system_check (BSTR (&buf), es, 0, "ERROR: DragonFly route delete command failed"); + #elif defined(TARGET_DARWIN) buf_printf (&buf, ROUTE_PATH " delete -net %s %s %s", @@ -1462,7 +1483,7 @@ get_default_gateway (in_addr_t *gateway) return ret; } -#elif defined(TARGET_FREEBSD) +#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) #include #include diff --git a/schedule.c b/schedule.c index 25aec20..af32e83 100644 --- a/schedule.c +++ b/schedule.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #if P2MP_SERVER diff --git a/service-win32/.svnignore b/service-win32/.svnignore new file mode 100644 index 0000000..df25b75 --- /dev/null +++ b/service-win32/.svnignore @@ -0,0 +1,8 @@ +*.exe +*.obj +*.o +.deps +Makefile.in +Makefile +service.h +service.c diff --git a/service-win32/Makefile b/service-win32/Makefile deleted file mode 100755 index 9a3cb5d..0000000 --- a/service-win32/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# This makefile builds the OpenVPN win32 service -# wrapper using the mingw environment. -# -# service.c and service.h should be generated by -# applying service.patch to the Platform -# SDK service sample. - -EXE = ${PRODUCT_UNIX_NAME}serv.exe - -HEADERS = service.h - -OBJS = openvpnserv.o service.o - -INCLUDE_DIRS = - -CC = gcc -g -O2 -Wall -Wno-unused-function -Wno-unused-variable -mno-cygwin - -all : ${OBJS} - ${CC} -o ${EXE} ${OBJS} - -clean : - rm -f ${OBJS} ${EXE} - -%.o : %.c ${HEADERS} - ${CC} ${INCLUDE_DIRS} -c $< -o $@ diff --git a/service-win32/Makefile.am b/service-win32/Makefile.am new file mode 100644 index 0000000..97c5ef6 --- /dev/null +++ b/service-win32/Makefile.am @@ -0,0 +1,41 @@ +# +# OpenVPN -- An application to securely tunnel IP networks +# over a single UDP port, with support for SSL/TLS-based +# session authentication and key exchange, +# packet encryption, packet authentication, and +# packet compression. +# +# Copyright (C) 2002-2005 OpenVPN Solutions LLC +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program (see the file COPYING included with this +# distribution); if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +if WIN32 + +sbin_PROGRAMS = openvpnserv + +openvpnserv_SOURCES = \ + openvpnserv.c \ + service.h service.c + +else + +dist_noinst_DATA = \ + openvpnserv.c \ + service.h service.c + +endif diff --git a/service-win32/mkpatch b/service-win32/mkpatch deleted file mode 100755 index 83652e1..0000000 --- a/service-win32/mkpatch +++ /dev/null @@ -1,4 +0,0 @@ -# build service.[ch] patch against original -# SDK sample -diff -ub service.c.orig service.c | u2d >service.patch -diff -ub service.h.orig service.h | u2d >>service.patch diff --git a/service-win32/openvpnserv.c b/service-win32/openvpnserv.c index 76323ca..6cdce26 100755 --- a/service-win32/openvpnserv.c +++ b/service-win32/openvpnserv.c @@ -33,6 +33,11 @@ * This code is designed to be built with the mingw compiler. */ +#ifdef _MSC_VER +#include "config-win32.h" +#else +#include "config.h" +#endif #include #include #include @@ -65,13 +70,13 @@ struct security_attributes * Control Manager which will cause an asynchronous call * of ServiceStop below. */ -#define EXIT_EVENT_NAME PRODUCT_UNIX_NAME "_exit_1" +#define EXIT_EVENT_NAME PACKAGE "_exit_1" /* * Which registry key in HKLM should * we get config info from? */ -#define REG_KEY "SOFTWARE\\" PRODUCT_NAME +#define REG_KEY "SOFTWARE\\" PACKAGE_NAME static HANDLE exit_event = NULL; @@ -398,7 +403,7 @@ VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) mysnprintf (log_path, "%s\\%s", log_dir, log_file); /* construct command line */ - mysnprintf (command_line, PRODUCT_UNIX_NAME " --service %s 1 --config \"%s\"", + mysnprintf (command_line, PACKAGE " --service %s 1 --config \"%s\"", EXIT_EVENT_NAME, find_obj.cFileName); @@ -406,7 +411,7 @@ VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) be inherited. */ if (!init_security_attributes_allow_all (&sa)) { - MSG (M_SYSERR, "InitializeSecurityDescriptor start_" PRODUCT_UNIX_NAME " failed"); + MSG (M_SYSERR, "InitializeSecurityDescriptor start_" PACKAGE " failed"); goto finish; } diff --git a/service-win32/service.c b/service-win32/service.c new file mode 100644 index 0000000..d5211bd --- /dev/null +++ b/service-win32/service.c @@ -0,0 +1,693 @@ +/*--------------------------------------------------------------------------- +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. + +MODULE: service.c + +PURPOSE: Implements functions required by all Windows NT services + +FUNCTIONS: + main(int argc, char **argv); + service_ctrl(DWORD dwCtrlCode); + service_main(DWORD dwArgc, LPTSTR *lpszArgv); + CmdInstallService(); + CmdRemoveService(); + CmdStartService(); + CmdDebugService(int argc, char **argv); + ControlHandler ( DWORD dwCtrlType ); + GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); + +---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include "service.h" + +// internal variables +SERVICE_STATUS ssStatus; // current status of the service +SERVICE_STATUS_HANDLE sshStatusHandle; +DWORD dwErr = 0; +BOOL bDebug = FALSE; +TCHAR szErr[256]; + +// internal function prototypes +VOID WINAPI service_ctrl(DWORD dwCtrlCode); +VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv); +int CmdInstallService(); +int CmdRemoveService(); +int CmdStartService(); +VOID CmdDebugService(int argc, char **argv); +BOOL WINAPI ControlHandler ( DWORD dwCtrlType ); +LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); + +// +// FUNCTION: main +// +// PURPOSE: entrypoint for service +// +// PARAMETERS: +// argc - number of command line arguments +// argv - array of command line arguments +// +// RETURN VALUE: +// none +// +// COMMENTS: +// main() either performs the command line task, or +// call StartServiceCtrlDispatcher to register the +// main service thread. When the this call returns, +// the service has stopped, so exit. +// +int __cdecl main(int argc, char **argv) +{ + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, + { NULL, NULL} + }; + + if ( (argc > 1) && + ((*argv[1] == '-') || (*argv[1] == '/')) ) + { + if ( _stricmp( "install", argv[1]+1 ) == 0 ) + { + return CmdInstallService(); + } + else if ( _stricmp( "remove", argv[1]+1 ) == 0 ) + { + return CmdRemoveService(); + } + else if ( _stricmp( "start", argv[1]+1 ) == 0) + { + return CmdStartService(); + } + else if ( _stricmp( "debug", argv[1]+1 ) == 0 ) + { + bDebug = TRUE; + CmdDebugService(argc, argv); + } + else + { + goto dispatch; + } + return 0; + } + + // if it doesn't match any of the above parameters + // the service control manager may be starting the service + // so we must call StartServiceCtrlDispatcher + dispatch: + // this is just to be friendly + printf( "%s -install to install the service\n", SZAPPNAME ); + printf( "%s -start to start the service\n", SZAPPNAME ); + printf( "%s -remove to remove the service\n", SZAPPNAME ); + printf( "%s -debug to run as a console app for debugging\n", SZAPPNAME ); + printf( "\nStartServiceCtrlDispatcher being called.\n" ); + printf( "This may take several seconds. Please wait.\n" ); + + if (!StartServiceCtrlDispatcher(dispatchTable)) + AddToMessageLog(MSG_FLAGS_ERROR, TEXT("StartServiceCtrlDispatcher failed.")); + + return 0; +} + + + +// +// FUNCTION: service_main +// +// PURPOSE: To perform actual initialization of the service +// +// PARAMETERS: +// dwArgc - number of command line arguments +// lpszArgv - array of command line arguments +// +// RETURN VALUE: +// none +// +// COMMENTS: +// This routine performs the service initialization and then calls +// the user defined ServiceStart() routine to perform majority +// of the work. +// +void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv) +{ + + // register our service control handler: + // + sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl); + + if (!sshStatusHandle) + goto cleanup; + + // SERVICE_STATUS members that don't change in example + // + ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ssStatus.dwServiceSpecificExitCode = 0; + + + // report the status to the service control manager. + // + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto cleanup; + + + ServiceStart( dwArgc, lpszArgv ); + + cleanup: + + // try to report the stopped status to the service control manager. + // + if (sshStatusHandle) + (VOID)ReportStatusToSCMgr( + SERVICE_STOPPED, + dwErr, + 0); + + return; +} + + + +// +// FUNCTION: service_ctrl +// +// PURPOSE: This function is called by the SCM whenever +// ControlService() is called on this service. +// +// PARAMETERS: +// dwCtrlCode - type of control requested +// +// RETURN VALUE: +// none +// +// COMMENTS: +// +VOID WINAPI service_ctrl(DWORD dwCtrlCode) +{ + // Handle the requested control code. + // + switch (dwCtrlCode) + { + // Stop the service. + // + // SERVICE_STOP_PENDING should be reported before + // setting the Stop Event - hServerStopEvent - in + // ServiceStop(). This avoids a race condition + // which may result in a 1053 - The Service did not respond... + // error. + case SERVICE_CONTROL_STOP: + ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); + ServiceStop(); + return; + + // Update the service status. + // + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + + } + + ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); +} + + + +// +// FUNCTION: ReportStatusToSCMgr() +// +// PURPOSE: Sets the current status of the service and +// reports it to the Service Control Manager +// +// PARAMETERS: +// dwCurrentState - the state of the service +// dwWin32ExitCode - error code to report +// dwWaitHint - worst case estimate to next checkpoint +// +// RETURN VALUE: +// TRUE - success +// FALSE - failure +// +// COMMENTS: +// +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + BOOL fResult = TRUE; + + + if ( !bDebug ) // when debugging we don't report to the SCM + { + if (dwCurrentState == SERVICE_START_PENDING) + ssStatus.dwControlsAccepted = 0; + else + ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + ssStatus.dwCurrentState = dwCurrentState; + ssStatus.dwWin32ExitCode = dwWin32ExitCode; + ssStatus.dwWaitHint = dwWaitHint; + + if ( ( dwCurrentState == SERVICE_RUNNING ) || + ( dwCurrentState == SERVICE_STOPPED ) ) + ssStatus.dwCheckPoint = 0; + else + ssStatus.dwCheckPoint = dwCheckPoint++; + + + // Report the status of the service to the service control manager. + // + if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) + { + AddToMessageLog(MSG_FLAGS_ERROR, TEXT("SetServiceStatus")); + } + } + return fResult; +} + + + +// +// FUNCTION: AddToMessageLog(LPTSTR lpszMsg) +// +// PURPOSE: Allows any thread to log an error message +// +// PARAMETERS: +// lpszMsg - text for message +// +// RETURN VALUE: +// none +// +// COMMENTS: +// +void AddToMessageLog(DWORD flags, LPTSTR lpszMsg) +{ + TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100 ]; + HANDLE hEventSource; + LPCSTR lpszStrings[2]; + + if ( !bDebug ) + { + if (flags & MSG_FLAGS_SYS_CODE) + dwErr = GetLastError(); + else + dwErr = 0; + + // Use event logging to log the error. + // + hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); + + _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), (int)dwErr); + lpszStrings[0] = szMsg; + lpszStrings[1] = lpszMsg; + + if (hEventSource != NULL) + { + ReportEvent(hEventSource, // handle of event source + // event type + (flags & MSG_FLAGS_ERROR) + ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, + 0, // event category + 0, // event ID + NULL, // current user's SID + 2, // strings in lpszStrings + 0, // no bytes of raw data + lpszStrings, // array of error strings + NULL); // no raw data + + (VOID) DeregisterEventSource(hEventSource); + } + } +} + +void ResetError (void) +{ + dwErr = 0; +} + +/////////////////////////////////////////////////////////////////// +// +// The following code handles service installation and removal +// + + +// +// FUNCTION: CmdInstallService() +// +// PURPOSE: Installs the service +// +// PARAMETERS: +// none +// +// RETURN VALUE: +// 0 if success +// +// COMMENTS: +// +int CmdInstallService() +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + TCHAR szPath[512]; + + int ret = 0; + + if ( GetModuleFileName( NULL, szPath, 512 ) == 0 ) + { + _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256)); + return 1; + } + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE // access required + ); + if ( schSCManager ) + { + schService = CreateService( + schSCManager, // SCManager database + TEXT(SZSERVICENAME), // name of service + TEXT(SZSERVICEDISPLAYNAME), // name to display + SERVICE_QUERY_STATUS, // desired access + SERVICE_WIN32_OWN_PROCESS, // service type + SERVICE_DEMAND_START, // start type -- alternative: SERVICE_AUTO_START + SERVICE_ERROR_NORMAL, // error control type + szPath, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + TEXT(SZDEPENDENCIES), // dependencies + NULL, // LocalSystem account + NULL); // no password + + if ( schService ) + { + _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); + CloseServiceHandle(schService); + } + else + { + _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256)); + ret = 1; + } + + CloseServiceHandle(schSCManager); + } + else + { + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + return ret; +} + +// +// FUNCTION: CmdStartService() +// +// PURPOSE: Start the service +// +// PARAMETERS: +// none +// +// RETURN VALUE: +// 0 if success +// +// COMMENTS: + +int CmdStartService() +{ + int ret = 0; + + SC_HANDLE schSCManager; + SC_HANDLE schService; + + + // Open a handle to the SC Manager database. + schSCManager = OpenSCManager( + NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (NULL == schSCManager) { + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + + schService = OpenService( + schSCManager, // SCM database + SZSERVICENAME, // service name + SERVICE_ALL_ACCESS); + + if (schService == NULL) { + _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + + if (!StartService( + schService, // handle to service + 0, // number of arguments + NULL) ) // no arguments + { + _tprintf(TEXT("StartService failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + else + { + _tprintf(TEXT("Service Started\n")); + ret = 0; + } + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + return ret; +} + +// +// FUNCTION: CmdRemoveService() +// +// PURPOSE: Stops and removes the service +// +// PARAMETERS: +// none +// +// RETURN VALUE: +// 0 if success +// +// COMMENTS: +// +int CmdRemoveService() +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + int ret = 0; + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_CONNECT // access required + ); + if ( schSCManager ) + { + schService = OpenService(schSCManager, TEXT(SZSERVICENAME), DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS); + + if (schService) + { + // try to stop the service + if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) + { + _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME)); + Sleep( 1000 ); + + while ( QueryServiceStatus( schService, &ssStatus ) ) + { + if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) + { + _tprintf(TEXT(".")); + Sleep( 1000 ); + } + else + break; + } + + if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) + _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) ); + else + { + _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) ); + ret = 1; + } + + } + + // now remove the service + if ( DeleteService(schService) ) + _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); + else + { + _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + + + CloseServiceHandle(schService); + } + else + { + _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + + CloseServiceHandle(schSCManager); + } + else + { + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); + ret = 1; + } + return ret; +} + + + + +/////////////////////////////////////////////////////////////////// +// +// The following code is for running the service as a console app +// + + +// +// FUNCTION: CmdDebugService(int argc, char ** argv) +// +// PURPOSE: Runs the service as a console application +// +// PARAMETERS: +// argc - number of command line arguments +// argv - array of command line arguments +// +// RETURN VALUE: +// none +// +// COMMENTS: +// +void CmdDebugService(int argc, char ** argv) +{ + DWORD dwArgc; + LPTSTR *lpszArgv; + +#ifdef UNICODE + lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) ); + if (NULL == lpszArgv) + { + // CommandLineToArvW failed!! + _tprintf(TEXT("CmdDebugService CommandLineToArgvW returned NULL\n")); + return; + } +#else + dwArgc = (DWORD) argc; + lpszArgv = argv; +#endif + + _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); + + SetConsoleCtrlHandler( ControlHandler, TRUE ); + + ServiceStart( dwArgc, lpszArgv ); + +#ifdef UNICODE +// Must free memory allocated for arguments + + GlobalFree(lpszArgv); +#endif // UNICODE + +} + + +// +// FUNCTION: ControlHandler ( DWORD dwCtrlType ) +// +// PURPOSE: Handled console control events +// +// PARAMETERS: +// dwCtrlType - type of control event +// +// RETURN VALUE: +// True - handled +// False - unhandled +// +// COMMENTS: +// +BOOL WINAPI ControlHandler ( DWORD dwCtrlType ) +{ + switch ( dwCtrlType ) + { + case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate + case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode + _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME)); + ServiceStop(); + return TRUE; + break; + + } + return FALSE; +} + +// +// FUNCTION: GetLastErrorText +// +// PURPOSE: copies error message text to string +// +// PARAMETERS: +// lpszBuf - destination buffer +// dwSize - size of buffer +// +// RETURN VALUE: +// destination buffer +// +// COMMENTS: +// +LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ) +{ + DWORD dwRet; + LPTSTR lpszTemp = NULL; + + dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, + GetLastError(), + LANG_NEUTRAL, + (LPTSTR)&lpszTemp, + 0, + NULL ); + + // supplied buffer is not long enough + if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) + lpszBuf[0] = TEXT('\0'); + else + { + lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character + _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, (int)GetLastError() ); + } + + if ( lpszTemp ) + LocalFree((HLOCAL) lpszTemp ); + + return lpszBuf; +} diff --git a/service-win32/service.h b/service-win32/service.h new file mode 100644 index 0000000..028d075 --- /dev/null +++ b/service-win32/service.h @@ -0,0 +1,141 @@ +/*--------------------------------------------------------------------------- +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. + + MODULE: service.h + + Comments: The use of this header file and the accompanying service.c + file simplifies the process of writting a service. You as a developer + simply need to follow the TODO's outlined in this header file, and + implement the ServiceStart() and ServiceStop() functions. + + There is no need to modify the code in service.c. Just add service.c + to your project and link with the following libraries... + + libcmt.lib kernel32.lib advapi.lib shell32.lib + + This code also supports unicode. Be sure to compile both service.c and + and code #include "service.h" with the same Unicode setting. + + Upon completion, your code will have the following command line interface + + -? to display this list + -install to install the service + -remove to remove the service + -debug to run as a console app for debugging + + Note: This code also implements Ctrl+C and Ctrl+Break handlers + when using the debug option. These console events cause + your ServiceStop routine to be called + + Also, this code only handles the OWN_SERVICE service type + running in the LOCAL_SYSTEM security context. + + To control your service ( start, stop, etc ) you may use the + Services control panel applet or the NET.EXE program. + + To aid in writing/debugging service, the + SDK contains a utility (MSTOOLS\BIN\SC.EXE) that + can be used to control, configure, or obtain service status. + SC displays complete status for any service/driver + in the service database, and allows any of the configuration + parameters to be easily changed at the command line. + For more information on SC.EXE, type SC at the command line. + + +------------------------------------------------------------------------------*/ + +#ifndef _SERVICE_H +#define _SERVICE_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "config.h" + +////////////////////////////////////////////////////////////////////////////// +//// todo: change to desired strings +//// +// name of the executable +#define SZAPPNAME PACKAGE "serv" +// internal name of the service +#define SZSERVICENAME PACKAGE_NAME "Service" +// displayed name of the service +#define SZSERVICEDISPLAYNAME PACKAGE_NAME " Service" +// list of service dependencies - "dep1\0dep2\0\0" +#define SZDEPENDENCIES TAP_ID "\0Dhcp\0\0" +////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////////////// +//// todo: ServiceStart()must be defined by in your code. +//// The service should use ReportStatusToSCMgr to indicate +//// progress. This routine must also be used by StartService() +//// to report to the SCM when the service is running. +//// +//// If a ServiceStop procedure is going to take longer than +//// 3 seconds to execute, it should spawn a thread to +//// execute the stop code, and return. Otherwise, the +//// ServiceControlManager will believe that the service has +//// stopped responding +//// + VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv); + VOID ServiceStop(); +////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////////////// +//// The following are procedures which +//// may be useful to call within the above procedures, +//// but require no implementation by the user. +//// They are implemented in service.c + +// +// FUNCTION: ReportStatusToSCMgr() +// +// PURPOSE: Sets the current status of the service and +// reports it to the Service Control Manager +// +// PARAMETERS: +// dwCurrentState - the state of the service +// dwWin32ExitCode - error code to report +// dwWaitHint - worst case estimate to next checkpoint +// +// RETURN VALUE: +// TRUE - success +// FALSE - failure +// + BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); + + +// +// FUNCTION: AddToMessageLog(LPTSTR lpszMsg) +// +// PURPOSE: Allows any thread to log an error message +// +// PARAMETERS: +// lpszMsg - text for message +// +// RETURN VALUE: +// none +// +# define MSG_FLAGS_ERROR (1<<0) +# define MSG_FLAGS_SYS_CODE (1<<1) + void AddToMessageLog(DWORD flags, LPTSTR lpszMsg); + void ResetError (void); +////////////////////////////////////////////////////////////////////////////// + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/service-win32/service.patch b/service-win32/service.patch deleted file mode 100755 index 8e4ddf9..0000000 --- a/service-win32/service.patch +++ /dev/null @@ -1,359 +0,0 @@ ---- service.c.orig Tue Apr 24 14:49:30 2007 -+++ service.c Tue Apr 24 12:20:08 2007 -@@ -16,6 +16,7 @@ - service_main(DWORD dwArgc, LPTSTR *lpszArgv); - CmdInstallService(); - CmdRemoveService(); -+ CmdStartService(); - CmdDebugService(int argc, char **argv); - ControlHandler ( DWORD dwCtrlType ); - GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); -@@ -40,8 +41,9 @@ - // internal function prototypes - VOID WINAPI service_ctrl(DWORD dwCtrlCode); - VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv); --VOID CmdInstallService(); --VOID CmdRemoveService(); -+int CmdInstallService(); -+int CmdRemoveService(); -+int CmdStartService(); - VOID CmdDebugService(int argc, char **argv); - BOOL WINAPI ControlHandler ( DWORD dwCtrlType ); - LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize ); -@@ -64,7 +66,7 @@ - // main service thread. When the this call returns, - // the service has stopped, so exit. - // --void __cdecl main(int argc, char **argv) -+int __cdecl main(int argc, char **argv) - { - SERVICE_TABLE_ENTRY dispatchTable[] = - { -@@ -77,11 +79,15 @@ - { - if ( _stricmp( "install", argv[1]+1 ) == 0 ) - { -- CmdInstallService(); -+ return CmdInstallService(); - } - else if ( _stricmp( "remove", argv[1]+1 ) == 0 ) - { -- CmdRemoveService(); -+ return CmdRemoveService(); -+ } -+ else if ( _stricmp( "start", argv[1]+1 ) == 0) -+ { -+ return CmdStartService(); - } - else if ( _stricmp( "debug", argv[1]+1 ) == 0 ) - { -@@ -92,7 +98,7 @@ - { - goto dispatch; - } -- exit(0); -+ return 0; - } - - // if it doesn't match any of the above parameters -@@ -101,13 +107,16 @@ - dispatch: - // this is just to be friendly - printf( "%s -install to install the service\n", SZAPPNAME ); -+ printf( "%s -start to start the service\n", SZAPPNAME ); - printf( "%s -remove to remove the service\n", SZAPPNAME ); - printf( "%s -debug to run as a console app for debugging\n", SZAPPNAME ); - printf( "\nStartServiceCtrlDispatcher being called.\n" ); - printf( "This may take several seconds. Please wait.\n" ); - - if (!StartServiceCtrlDispatcher(dispatchTable)) -- AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed.")); -+ AddToMessageLog(MSG_FLAGS_ERROR, TEXT("StartServiceCtrlDispatcher failed.")); -+ -+ return 0; - } - - -@@ -267,7 +276,7 @@ - // - if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) - { -- AddToMessageLog(TEXT("SetServiceStatus")); -+ AddToMessageLog(MSG_FLAGS_ERROR, TEXT("SetServiceStatus")); - } - } - return fResult; -@@ -288,28 +297,33 @@ - // - // COMMENTS: - // --VOID AddToMessageLog(LPTSTR lpszMsg) -+void AddToMessageLog(DWORD flags, LPTSTR lpszMsg) - { - TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) + 100 ]; - HANDLE hEventSource; -- LPTSTR lpszStrings[2]; -+ LPCSTR lpszStrings[2]; - - if ( !bDebug ) - { -+ if (flags & MSG_FLAGS_SYS_CODE) - dwErr = GetLastError(); -+ else -+ dwErr = 0; - - // Use event logging to log the error. - // - hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME)); - -- _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr); -+ _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), (int)dwErr); - lpszStrings[0] = szMsg; - lpszStrings[1] = lpszMsg; - - if (hEventSource != NULL) - { - ReportEvent(hEventSource, // handle of event source -- EVENTLOG_ERROR_TYPE, // event type -+ // event type -+ (flags & MSG_FLAGS_ERROR) -+ ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, - 0, // event category - 0, // event ID - NULL, // current user's SID -@@ -323,8 +337,10 @@ - } - } - -- -- -+void ResetError (void) -+{ -+ dwErr = 0; -+} - - /////////////////////////////////////////////////////////////////// - // -@@ -341,21 +357,23 @@ - // none - // - // RETURN VALUE: --// none -+// 0 if success - // - // COMMENTS: - // --void CmdInstallService() -+int CmdInstallService() - { - SC_HANDLE schService; - SC_HANDLE schSCManager; - - TCHAR szPath[512]; - -+ int ret = 0; -+ - if ( GetModuleFileName( NULL, szPath, 512 ) == 0 ) - { - _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256)); -- return; -+ return 1; - } - - schSCManager = OpenSCManager( -@@ -371,7 +389,7 @@ - TEXT(SZSERVICEDISPLAYNAME), // name to display - SERVICE_QUERY_STATUS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type -- SERVICE_DEMAND_START, // start type -+ SERVICE_DEMAND_START, // start type -- alternative: SERVICE_AUTO_START - SERVICE_ERROR_NORMAL, // error control type - szPath, // service's binary - NULL, // no load ordering group -@@ -388,16 +406,79 @@ - else - { - _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256)); -+ ret = 1; - } - - CloseServiceHandle(schSCManager); - } - else -+ { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } -+ return ret; - } - -+// -+// FUNCTION: CmdStartService() -+// -+// PURPOSE: Start the service -+// -+// PARAMETERS: -+// none -+// -+// RETURN VALUE: -+// 0 if success -+// -+// COMMENTS: -+ -+int CmdStartService() -+{ -+ int ret = 0; -+ -+ SC_HANDLE schSCManager; -+ SC_HANDLE schService; - - -+ // Open a handle to the SC Manager database. -+ schSCManager = OpenSCManager( -+ NULL, // local machine -+ NULL, // ServicesActive database -+ SC_MANAGER_ALL_ACCESS); // full access rights -+ -+ if (NULL == schSCManager) { -+ _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } -+ -+ schService = OpenService( -+ schSCManager, // SCM database -+ SZSERVICENAME, // service name -+ SERVICE_ALL_ACCESS); -+ -+ if (schService == NULL) { -+ _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } -+ -+ if (!StartService( -+ schService, // handle to service -+ 0, // number of arguments -+ NULL) ) // no arguments -+ { -+ _tprintf(TEXT("StartService failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } -+ else -+ { -+ _tprintf(TEXT("Service Started\n")); -+ ret = 0; -+ } -+ CloseServiceHandle(schService); -+ CloseServiceHandle(schSCManager); -+ return ret; -+} -+ - // - // FUNCTION: CmdRemoveService() - // -@@ -407,15 +488,17 @@ - // none - // - // RETURN VALUE: --// none -+// 0 if success - // - // COMMENTS: - // --void CmdRemoveService() -+int CmdRemoveService() - { - SC_HANDLE schService; - SC_HANDLE schSCManager; - -+ int ret = 0; -+ - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) -@@ -447,7 +530,10 @@ - if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) - _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - else -+ { - _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) ); -+ ret = 1; -+ } - - } - -@@ -455,18 +541,28 @@ - if ( DeleteService(schService) ) - _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) ); - else -+ { - _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } - - - CloseServiceHandle(schService); - } - else -+ { - _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } - - CloseServiceHandle(schSCManager); - } - else -+ { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256)); -+ ret = 1; -+ } -+ return ret; - } - - -@@ -587,7 +683,7 @@ - else - { - lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character -- _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() ); -+ _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, (int)GetLastError() ); - } - - if ( lpszTemp ) ---- service.h.orig Tue Apr 24 14:49:30 2007 -+++ service.h Tue Apr 24 11:58:48 2007 -@@ -57,18 +57,19 @@ - extern "C" { - #endif - -+#include "../autodefs/defs.h" - - ////////////////////////////////////////////////////////////////////////////// - //// todo: change to desired strings - //// - // name of the executable --#define SZAPPNAME "Simple" -+#define SZAPPNAME PRODUCT_UNIX_NAME "serv" - // internal name of the service --#define SZSERVICENAME "SimpleService" -+#define SZSERVICENAME PRODUCT_NAME "Service" - // displayed name of the service --#define SZSERVICEDISPLAYNAME "Simple Service" -+#define SZSERVICEDISPLAYNAME PRODUCT_NAME " Service" - // list of service dependencies - "dep1\0dep2\0\0" --#define SZDEPENDENCIES "" -+#define SZDEPENDENCIES PRODUCT_TAP_ID "\0Dhcp\0\0" - ////////////////////////////////////////////////////////////////////////////// - - -@@ -126,7 +127,10 @@ - // RETURN VALUE: - // none - // -- void AddToMessageLog(LPTSTR lpszMsg); -+# define MSG_FLAGS_ERROR (1<<0) -+# define MSG_FLAGS_SYS_CODE (1<<1) -+ void AddToMessageLog(DWORD flags, LPTSTR lpszMsg); -+ void ResetError (void); - ////////////////////////////////////////////////////////////////////////////// - - diff --git a/session_id.c b/session_id.c index 66c2442..158a6cf 100644 --- a/session_id.c +++ b/session_id.c @@ -31,16 +31,10 @@ * it is called the key_id and is currently 2 bits long. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #if defined(USE_CRYPTO) && defined(USE_SSL) -#include "syshead.h" - #include "error.h" #include "common.h" #include "crypto.h" diff --git a/shaper.c b/shaper.c index f3b06cb..2024cda 100644 --- a/shaper.c +++ b/shaper.c @@ -22,11 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif #include "syshead.h" #include "shaper.h" #include "memdbg.h" diff --git a/sig.c b/sig.c index 9d8756b..58c37b3 100644 --- a/sig.c +++ b/sig.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "buffer.h" diff --git a/socket.c b/socket.c index e9cc1ae..78686ef 100644 --- a/socket.c +++ b/socket.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "socket.h" @@ -138,6 +132,9 @@ getaddr (unsigned int flags, while (true) { /* try hostname lookup */ +#if defined(HAVE_RES_INIT) + res_init (); +#endif h = gethostbyname (hostname); if (signal_received) @@ -2121,11 +2118,13 @@ link_socket_read_tcp (struct link_socket *sock, #if ENABLE_IP_PKTINFO +#pragma pack(1) /* needed to keep structure size consistent for 32 vs. 64-bit architectures */ struct openvpn_pktinfo { struct cmsghdr cmsghdr; struct in_pktinfo in_pktinfo; }; +#pragma pack() static socklen_t link_socket_read_udp_posix_recvmsg (struct link_socket *sock, diff --git a/socks.c b/socks.c index cc9d82f..79e1170 100644 --- a/socks.c +++ b/socks.c @@ -29,16 +29,10 @@ * see RFC 1928, only supports "no authentication" */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #ifdef ENABLE_SOCKS -#include "syshead.h" - #include "common.h" #include "misc.h" #include "win32.h" diff --git a/ssl.c b/ssl.c index c587b8c..4cc6b76 100644 --- a/ssl.c +++ b/ssl.c @@ -30,16 +30,10 @@ * over the same TCP/UDP port. */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif +#include "syshead.h" #if defined(USE_CRYPTO) && defined(USE_SSL) -#include "syshead.h" - #include "ssl.h" #include "error.h" #include "common.h" @@ -1210,7 +1204,7 @@ init_ssl (const struct options *options) if (options->pkcs11_providers[0]) { /* Load Certificate and Private Key */ - if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_id)) + if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_id_management, options->pkcs11_id)) { msg (M_WARN, "Cannot load certificate \"%s\" using PKCS#11 interface", options->pkcs11_id); goto err; diff --git a/status.c b/status.c index da1be14..d18641e 100644 --- a/status.c +++ b/status.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "status.h" diff --git a/syshead.h b/syshead.h index 2a29ee0..58e59c6 100644 --- a/syshead.h +++ b/syshead.h @@ -25,6 +25,28 @@ #ifndef SYSHEAD_H #define SYSHEAD_H +/* + * Only include if not during configure + */ +#ifndef PACKAGE_NAME +#ifdef _MSC_VER +#include "config-win32.h" +#else +#include "config.h" +#endif +#endif + +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 +#endif + +#ifdef WIN32 +#include +#define sleep(x) Sleep((x)*1000) +#define random rand +#define srandom srand +#endif + #ifdef HAVE_SYS_TYPES_H #include #endif @@ -133,6 +155,10 @@ #include #endif +#ifdef HAVE_RESOLV_H +#include +#endif + #ifdef HAVE_SYS_POLL_H #include #endif @@ -272,9 +298,29 @@ #endif /* TARGET_NETBSD */ +#ifdef TARGET_DRAGONFLY + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_TUN_IF_TUN_H +#include +#endif + +#endif /* TARGET_DRAGONFLY */ + #ifdef WIN32 #include -#include +#include #endif #ifdef HAVE_SYS_MMAN_H diff --git a/tap-win32/common.h b/tap-win32/common.h index df2024d..93e4750 100755 --- a/tap-win32/common.h +++ b/tap-win32/common.h @@ -32,7 +32,15 @@ // common to both. //=============================================== -#include "../autodefs/defs.h" +#if defined(HAVE_CONFIG_H) +#include "config.h" +#else +#if defined(_MSC_VER) && !defined(TAP_DRIVER_MAJOR_VERSION) +#include "config-win32.h" +#else +#include "../config.h" +#endif +#endif //============= // TAP IOCTLs @@ -81,4 +89,4 @@ // simultaneously. //========================================================= -#define TAP_COMPONENT_ID PRODUCT_TAP_ID +#define TAP_COMPONENT_ID TAP_ID diff --git a/thread.c b/thread.c index dc246c1..e8d9247 100644 --- a/thread.c +++ b/thread.c @@ -22,12 +22,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #ifdef USE_PTHREAD diff --git a/tun.c b/tun.c index 349a4de..3877ca8 100644 --- a/tun.c +++ b/tun.c @@ -30,12 +30,6 @@ * from VTun by Maxim Krasnyansky . */ -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - #include "syshead.h" #include "tun.h" @@ -799,7 +793,7 @@ do_ifconfig (struct tuntap *tt, add_route (&r, tt, 0, es); } -#elif defined(TARGET_FREEBSD) +#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ if (tun) @@ -1248,7 +1242,7 @@ close_tun (struct tuntap *tt) } #else openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH "%s addr 0.0.0.0", + IFCONFIG_PATH " %s 0.0.0.0", tt->actual_name ); #endif @@ -1753,6 +1747,89 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) return read (tt->fd, buf, len); } +#elif defined(TARGET_DRAGONFLY) + +static inline int +dragonfly_modify_read_write_return (int len) +{ + if (len > 0) + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; + else + return len; +} + +void +open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) +{ + open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); + + if (tt->fd >= 0) + { + int i = 0; + + /* Disable extended modes */ + ioctl (tt->fd, TUNSLMODE, &i); + i = 1; + ioctl (tt->fd, TUNSIFHEAD, &i); + } +} + +void +close_tun (struct tuntap *tt) +{ + if (tt) + { + close_tun_generic (tt); + free (tt); + } +} + +int +write_tun (struct tuntap* tt, uint8_t *buf, int len) +{ + if (tt->type == DEV_TYPE_TUN) + { + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if (tt->ipv6 && iph->ip_v == 6) + type = htonl (AF_INET6); + else + type = htonl (AF_INET); + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = len; + + return dragonfly_modify_read_write_return (writev (tt->fd, iv, 2)); + } + else + return write (tt->fd, buf, len); +} + +int +read_tun (struct tuntap* tt, uint8_t *buf, int len) +{ + if (tt->type == DEV_TYPE_TUN) + { + u_int32_t type; + struct iovec iv[2]; + + iv[0].iov_base = (char *)&type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = len; + + return dragonfly_modify_read_write_return (readv (tt->fd, iv, 2)); + } + else + return read (tt->fd, buf, len); +} + #elif defined(WIN32) int diff --git a/version.m4 b/version.m4 index fd4de2d..4a1335c 100644 --- a/version.m4 +++ b/version.m4 @@ -1,2 +1,6 @@ dnl define the OpenVPN version -define(PRODUCT_VERSION,[2.1_rc7b]) +define(PRODUCT_VERSION,[2.1_rc7c]) +dnl define the TAP version +define(PRODUCT_TAP_ID,[tap0901]) +define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9]) +define(PRODUCT_TAP_WIN32_MIN_MINOR,[1]) diff --git a/win32.c b/win32.c index f9a80fc..dde1ef7 100644 --- a/win32.c +++ b/win32.c @@ -26,12 +26,10 @@ * Win32-specific OpenVPN code, targetted at the mingw * development environment. */ +#include "syshead.h" #ifdef WIN32 -#include "config-win32.h" - -#include "syshead.h" #include "buffer.h" #include "error.h" #include "mtu.h" -- cgit