Hi all!

Let me first say how impressed with the smooth functionality of this
excellent piece of software! I have evaluated some other, commercial,
SSL/TLS VPN solutions, but this is the best one, and at a much lower
price... :-)

What I really wanted to use with OpenVPN, is smart cards for user
authentication, on the Microsoft Windows platform. I have written some
code that adds the option of using certificates (and their private
keys), that resides in the Windows Certificate System Store. That makes
it possible to use any smart card, supported by Windows, but also any
kind of certificate, residing in the Cert Store, that you have access to
the private key of. I have tested this code with a couple of different
smart cards (GemSAFE, Cryptoflex and Swedish Post Office eID) on the
client side, and also an imported PKCS12 software certificate on the
server side.

The code adds a new config option: cryptoapicert
To select a certificate, based on a substring search in the
certificate's subject:

cryptoapicert "SUBJ:Peter Runestig"

To select a certificate, based on certificate's thumbprint:

cryptoapicert "THUMB:f6 49 24 41 01 b4 ..."

The thumbprint hex string can easily be copy-and-pasted from the Windows
Certificate Store GUI.

Unfortunately, this code don't build with MinGW; e.g. the
CryptAcquireCertificatePrivateKey() isn't implemented in MinGW, so I had
to use Microsoft Visual C++ 6.0. So the patch included in this post is
actually my hack to build OpenVPN using MSVC++, which must be applied
before the actual CryptoAPI patch, which will be in my next post (I
split it in two, so the posts don't get so big).

To build this, using MSVC 6.0:

o Unpack openvpn-2.0_beta11.zip, apply the MSVC patch in this post, and
the CryptoAPI patch in my next post.

o If the OpenSSL and/or LZO libraries (built with MSVC or something else
that gives you .LIB files) isn't reachable using the INCLUDE and LIB
environment variables, edit the 'makefile.w32-vc' file to point them out.

o nmake -f makefile.w32-vc

Here is the MSVC patch:
-----8<----------8<----------8<----------8<----------8<----------8<----------8<-----
diff -uN openvpn-2.0_beta11.orig/config-win32.h 
openvpn-2.0_beta11.msvc/config-win32.h
--- openvpn-2.0_beta11.orig/config-win32.h      2004-08-17 17:32:44.000000000 
+0200
+++ openvpn-2.0_beta11.msvc/config-win32.h      2004-10-12 15:34:12.000000000 
+0200
@@ -88,7 +88,9 @@
 #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 <ctype.h> header file. */
 #define HAVE_CTYPE_H 1
@@ -125,7 +127,9 @@
 #define HAVE_STDARG_H 1

 /* Define to 1 if you have the <stdint.h> header file. */
+#ifndef _MSC_VER
 #define HAVE_STDINT_H 1
+#endif

 /* Define to 1 if you have the <stdio.h> header file. */
 #define HAVE_STDIO_H 1
@@ -146,13 +150,17 @@
 #define HAVE_SYSTEM 1

 /* Define to 1 if you have the <sys/file.h> header file. */
+#ifndef _MSC_VER
 #define HAVE_SYS_FILE_H 1
+#endif

 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1

 /* Define to 1 if you have the <sys/time.h> header file. */
+#ifndef _MSC_VER
 #define HAVE_SYS_TIME_H 1
+#endif

 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
@@ -161,7 +169,9 @@
 #define HAVE_TIME 1

 /* Define to 1 if you have the <unistd.h> header file. */
+#ifndef _MSC_VER
 #define HAVE_UNISTD_H 1
+#endif

 /* Define to 1 if you have the `vsnprintf' function. */
 #define HAVE_VSNPRINTF 1
@@ -204,10 +214,16 @@
 #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 <sys/time.h> and <time.h>. */
+#ifndef _MSC_VER
 #define TIME_WITH_SYS_TIME 1
+#endif

 /* Use OpenSSL crypto library */
 #define USE_CRYPTO 1
@@ -244,3 +260,21 @@
 #ifdef USE_PTHREAD
 #error The Windows version of OpenVPN does not support PTHREAD yet
 #endif
+
+#ifdef _MSC_VER
+/* MSVC++ hacks */
+#include <io.h>
+#include <direct.h>
+#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 -uN openvpn-2.0_beta11.orig/error.h openvpn-2.0_beta11.msvc/error.h
--- openvpn-2.0_beta11.orig/error.h     2004-08-15 07:28:36.000000000 +0200
+++ openvpn-2.0_beta11.msvc/error.h     2004-10-12 15:31:57.000000000 +0200
@@ -135,7 +135,9 @@
 #define HAVE_VARARG_MACROS
 #define msg(flags, args...) do { if (MSG_TEST(flags)) x_msg((flags), args); } 
while (false)
 #else
-#warning this compiler appears to lack vararg macros which will cause a 
significant degradation in efficiency (you can ignore this warning if you are 
using LCLINT)
+# ifndef _MSC_VER      /* MSVC++ doesn't have #warning... */
+# warning this compiler appears to lack vararg macros which will cause a 
significant degradation in efficiency (you can ignore this warning if you are 
using LCLINT)
+# endif
 #define msg x_msg
 #endif

diff -uN openvpn-2.0_beta11.orig/makefile.w32-vc 
openvpn-2.0_beta11.msvc/makefile.w32-vc
--- openvpn-2.0_beta11.orig/makefile.w32-vc     1970-01-01 01:00:00.000000000 
+0100
+++ openvpn-2.0_beta11.msvc/makefile.w32-vc     2004-10-12 13:29:04.000000000 
+0200
@@ -0,0 +1,167 @@
+# This makefile builds the user-mode component
+# of OpenVPN for WIN32 in the MSVC++ environment.
+#
+# Build Dependencies:
+#      OpenSSL         (SSL/TLS/crypto library)
+#      LZO             (real-time compression library)
+#
+# Targets:
+#      static -- link statically with OpenSSL
+#      dynamic -- link dynamically with OpenSSL
+#
+# Note that LZO is always linked statically.
+
+# Change these to point to your OpenSSL and LZO top-level
+# directories.
+
+OPENSSL = \src\openssl-0.9.7d
+OPENSSL_STATIC = libeay32s.lib ssleay32s.lib
+#OPENSSL_STATIC = libeay32sd.lib ssleay32sd.lib
+OPENSSL_DYNAMIC = libeay32.lib ssleay32.lib
+#OPENSSL_DYNAMIC = libeay32d.lib ssleay32d.lib
+
+LZO = \src\lzo-1.08.vc
+
+INCLUDE_DIRS = -I$(OPENSSL)/include -I$(LZO)/include
+
+LIBS = lzo.lib ws2_32.lib iphlpapi.lib winmm.lib gdi32.lib advapi32.lib
+
+LIB_DIRS = -LIBPATH:$(OPENSSL)\out -LIBPATH:$(LZO)
+
+EXE = openvpn.exe
+
+CPP=cl.exe
+# release:
+CPP_PROJ=/nologo /MD /W3 /G5 /O2 -DNDEBUG -DWIN32 -DWIN32_LEAN_AND_MEAN 
-D_CONSOLE -D_MBCS $(INCLUDE_DIRS) /FD /c
+# debug:
+#CPP_PROJ=/nologo /MDd /W3 /G5 /Zi /Od -D_DEBUG -DWIN32 -DWIN32_LEAN_AND_MEAN 
-D_CONSOLE -D_MBCS $(INCLUDE_DIRS) /FD /c
+
+LINK32=link.exe
+# release:
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /out:"$(EXE)"
+# debug:
+#LINK32_FLAGS=/nologo /subsystem:console /incremental:no /debug /out:"$(EXE)"
+
+# Stuff below this point usually doesn't need to be changed
+
+HEADERS = \
+       basic.h \
+       buffer.h \
+       circ_list.h common.h \
+       tap-win32/common.h \
+        config-win32.h \
+       crypto.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 \
+       lzo.h \
+       mbuf.h \
+       memdbg.h \
+       misc.h \
+       mroute.h \
+       mss.h \
+       mtcp.h \
+       mtu.h \
+       mudp.h \
+       multi.h \
+       occ-inline.h \
+       occ.h \
+        openvpn.h \
+       options.h \
+       otime.h \
+       packet_id.h \
+       perf.h \
+       ping-inline.h \
+       ping.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 =  buffer.obj \
+       crypto.obj \
+       error.obj \
+       event.obj \
+       fdmisc.obj \
+       forward.obj \
+        fragment.obj \
+       gremlin.obj \
+       helper.obj \
+       inet_aton.obj \
+       init.obj \
+       interval.obj \
+        list.obj \
+       lzo.obj \
+       mbuf.obj \
+       misc.obj \
+       mroute.obj \
+       mss.obj \
+       mtcp.obj \
+       mtu.obj \
+       mudp.obj \
+       multi.obj \
+       occ.obj \
+        openvpn.obj \
+       options.obj \
+       otime.obj \
+       packet_id.obj \
+       perf.obj \
+       ping.obj \
+        pool.obj \
+       proxy.obj \
+       push.obj \
+       reliable.obj \
+        route.obj \
+       schedule.obj \
+       session_id.obj \
+       shaper.obj \
+       sig.obj \
+       socket.obj \
+        socks.obj \
+       ssl.obj \
+       status.obj \
+       thread.obj \
+       tun.obj \
+       win32.obj
+
+dynamic : $(OBJS)
+       $(LINK32) @<<
+       $(LINK32_FLAGS) $(LIB_DIRS) $(LIBS) $(OPENSSL_DYNAMIC) $(OBJS)
+<<
+
+static : $(OBJS)
+       $(LINK32) @<<
+       $(LINK32_FLAGS) $(LIB_DIRS) $(LIBS) $(OPENSSL_STATIC) $(OBJS)
+<<
+
+clean :
+       del /Q $(OBJS) $(EXE) *.idb *.pdb
+
+.c.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
diff -uN openvpn-2.0_beta11.orig/otime.c openvpn-2.0_beta11.msvc/otime.c
--- openvpn-2.0_beta11.orig/otime.c     2004-08-15 07:28:36.000000000 +0200
+++ openvpn-2.0_beta11.msvc/otime.c     2004-10-11 12:23:35.000000000 +0200
@@ -176,7 +176,7 @@

       QueryPerformanceFrequency((LARGE_INTEGER *) &frequency);

-      counterPerMicrosecond = (double)frequency / 1000000.0f;
+      counterPerMicrosecond = (double) ((__int64) frequency) / 1000000.0f;

       time(&t);
       QueryPerformanceCounter((LARGE_INTEGER *) &counter);
@@ -191,7 +191,7 @@
     }

   tv->tv_sec = (counter / frequency) + timeSecOffset;
-  tv->tv_usec = ((__int64)(counter / counterPerMicrosecond) % 1000000);
+  tv->tv_usec = ((__int64) (((__int64) counter) / counterPerMicrosecond) % 
1000000);

   return 0;
 }
diff -uN openvpn-2.0_beta11.orig/tun.c openvpn-2.0_beta11.msvc/tun.c
--- openvpn-2.0_beta11.orig/tun.c       2004-08-15 16:59:10.000000000 +0200
+++ openvpn-2.0_beta11.msvc/tun.c       2004-10-11 12:21:48.000000000 +0200
@@ -2303,9 +2303,9 @@
 static bool
 get_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, 
in_addr_t *netmask)
 {
+  bool ret = false;
   *ip = 0;
   *netmask = 0;
-  bool ret = false;

   if (ai)
     {
-----8<----------8<----------8<----------8<----------8<----------8<----------8<-----

-- 
Peter 'Luna' Runestig (fd. Altberg), Sweden <pe...@runestig.com>
PGP Key ID: 0xD07BBE13
Fingerprint: 7B5C 1F48 2997 C061 DE4B  42EA CB99 A35C D07B BE13
AOL Instant Messenger Screen name: PRunestig
Yahoo! Messenger profile name: altberg


Reply via email to