Re: [Openvpn-devel] [PATCH v4] Use CryptoAPI CA store (was Re: [PATCH v3] Use CryptoAPI CA store)

2008-10-07 Thread Faidon Liambotis
Hi,

Alon Bar-Lev wrote:
> On 9/27/08, Alon Bar-Lev  wrote:
>>  I prefer to receive patches...
>>  Anyway, this is not exactly what I meant.
>>  Please review latest head.
>>  I did not test this, but it should be correct now as far as the
>>  changes are concerned.
>>  It may not work as the validation process was never tested.
>
> Any news?
Thanks for reviving this. I built it and tried it and seems to work.
I didn't test with revoked or expired certificates, however.

As for warnings there's just a trivial one:
cryptoapi.c:429: warning: passing arg 2 of `d2i_X509' from  
 incompatible pointer type

Regards,
Faidon



[Openvpn-devel] Merge status of OCSP support?

2008-06-16 Thread Faidon Liambotis

Hi,
In light of the Debian OpenSSL vulnerability, I was looking for a way to 
efficiently check for revoked certificates.

Updating CRLs is one way but it's not exactly efficient.

I've found that someone has actually implemented OCSP for OpenVPN[1].
Is there any specific reason that this hasn't been merged?

I saw evidence on the openvpn-devel archives that this was submitted 
almost a year ago but I didn't see any reviews or comments whatsoever.


James, perhaps this should be included in -rc9?

Regards,
Faidon

1: http://www.block64.net/



[Openvpn-devel] [PATCH v4] Use CryptoAPI CA store (was Re: [PATCH v3] Use CryptoAPI CA store)

2007-09-23 Thread Faidon Liambotis
Alon Bar-Lev wrote:
> On 9/22/07, Faidon Liambotis <parav...@debian.org> wrote:
>> Alon Bar-Lev wrote:
>>> So you need to use CertVerifyCertificateChainPolicy() with 
>>> CERT_CHAIN_POLICY_SSL
>> I'm no Microsoft developer (adn I don't want to be to be honest) but if
>> I understand it right, it's better to call CertGetCertificateChain() as
>> I am doing.
> 
> You need to use both, one for create the chain and the other to verify
> that it meets with system CTL for SSL.
Seems that you are right. Below you will find -v4 of the patch that does
that.

Also, my previous version didn't actually check for revocations,
contrary to what I documented.
I added CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT to the dwFlags of
CertGetCertificateChain.

Let me know what you think.

Thanks,
Faidon

--

diff -urp openvpn-2.1_rc4.orig/cryptoapi.c openvpn-2.1_rc4/cryptoapi.c
--- openvpn-2.1_rc4.orig/cryptoapi.c2007-04-26 00:38:46.0 +0300
+++ openvpn-2.1_rc4/cryptoapi.c 2007-09-23 11:07:14.0 +0300
@@ -45,9 +45,15 @@
 #define CERT_STORE_READONLY_FLAG 0x8000
 #define CERT_STORE_OPEN_EXISTING_FLAG 0x4000
 #define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 0x0004
+#define CERT_CHAIN_REVOCATION_CHECK_END_CERT   0x1000
+#define CERT_CHAIN_REVOCATION_CHECK_CHAIN  0x2000
+#define CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT 0x4000
+#define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY 0x8000
 static HINSTANCE crypt32dll = NULL;
 static BOOL WINAPI (*CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT pCert, 
DWORD dwFlags,
 void *pvReserved, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec, BOOL 
*pfCallerFreeProv) = NULL;
+static PCCERT_CONTEXT WINAPI (*CertCreateCertificateContext) (DWORD 
dwCertEncodingType,
+ const BYTE *pbCertEncoded, DWORD cbCertEncoded) = NULL;
 #endif

 /* Size of an SSL signature: MD5+SHA1 */
@@ -65,6 +71,9 @@ static BOOL WINAPI (*CryptAcquireCertifi
 #define CRYPTOAPI_F_CRYPT_SIGN_HASH106
 #define CRYPTOAPI_F_LOAD_LIBRARY   107
 #define CRYPTOAPI_F_GET_PROC_ADDRESS   108
+#define CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT   109
+#define CRYPTOAPI_F_CERT_GET_CERT_CHAIN110
+#define CRYPTOAPI_F_CERT_VERIFY_CERT_CHAIN_POLICY  111

 static ERR_STRING_DATA CRYPTOAPI_str_functs[] ={
 { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0),   
"microsoft cryptoapi"},
@@ -77,6 +86,9 @@ static ERR_STRING_DATA CRYPTOAPI_str_fun
 { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), 
"CryptSignHash" },
 { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0),
"LoadLibrary" },
 { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0),
"GetProcAddress" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT, 0),
"CertCreateCertificateContext" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_GET_CERT_CHAIN, 0), 
"CertGetCertificateChain" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_VERIFY_CERT_CHAIN_POLICY, 0),   
"CertVerifyCertificateChainPolicy" },
 { 0, NULL }
 };

@@ -364,7 +376,7 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
 }

 /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
-cert = d2i_X509(NULL, (unsigned char **) >cert_context->pbCertEncoded,
+cert = d2i_X509(NULL, (const unsigned char **) 
>cert_context->pbCertEncoded,
cd->cert_context->cbCertEncoded);
 if (cert == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
@@ -461,3 +473,96 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
 }
 return 0;
 }
+
+int CryptoAPI_verify_certificate(X509 *x509)
+{
+  int ret = -1;
+  int len;
+  unsigned char *buf = NULL;
+
+  PCCERT_CONTEXT pCertContext = NULL;
+  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+  CERT_ENHKEY_USAGE EnhkeyUsage;
+  CERT_USAGE_MATCH CertUsage;  
+  CERT_CHAIN_PARA ChainPara;
+  CERT_CHAIN_POLICY_PARA PolicyPara;
+  CERT_CHAIN_POLICY_STATUS PolicyStatus;
+
+  /* Convert from internal X509 format to DER */
+  len = i2d_X509(x509, );
+  if (len < 0) {
+   SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
+   goto err;
+  }
+
+#ifdef __MINGW32_VERSION
+/* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 
3.1
+ * anyway. This is a hack around that problem. */
+if (crypt32dll == NULL) {
+   crypt32dll = LoadLibrary("crypt32");
+   if (crypt32dll == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
+   goto err;
+   }
+}
+if (CertCreateCertificateContext == NULL) {
+   CertCreateCertificateContext = GetProcAddress(crypt32dll,
+   "CertCreateCertificateContext&quo

Re: [Openvpn-devel] [PATCH v3] Use CryptoAPI CA store

2007-09-22 Thread Faidon Liambotis
Alon Bar-Lev wrote:
> So you need to use CertVerifyCertificateChainPolicy() with 
> CERT_CHAIN_POLICY_SSL
I'm no Microsoft developer (adn I don't want to be to be honest) but if
I understand it right, it's better to call CertGetCertificateChain() as
I am doing.

MSDN for CertVerifyCertificateChainPolicy()[1] says on the remarks:
"Use the CertGetCertificateChain function to enable and perform
certificate revocation checking. The CertVerifyCertificateChainPolicy
function does not check if certificates in the certificate chain are
revoked."

I could be far off in reading the documentation; my tests however
suggest that I got it right.

If you disagree, can you explain in more words your objection? :)

Thanks,
Faidon

1: http://msdn2.microsoft.com/en-us/library/aa377163.aspx




[Openvpn-devel] [PATCH v3] Use CryptoAPI CA store

2007-09-22 Thread Faidon Liambotis
Hello,
Below you will find a revised version of a patch that I sent almost 9
months before.

It allows OpenVPN to verify certificates agains the Windows Certificate Store.

Changed since v2:
 * Replace the global variable by a TLS options variable
 * Added relevant man page entry
 * Minor bugfixes (more #ifdef WIN32 to guard the variable declaration,
   spelling error etc.)
 * diff against 2.1-rc4 instead of rc1

Please review and apply :-)

Regards,
Faidon

--

diff -urp openvpn-2.1_rc4.orig/cryptoapi.c openvpn-2.1_rc4/cryptoapi.c
--- openvpn-2.1_rc4.orig/cryptoapi.c2007-04-26 00:38:46.0 +0300
+++ openvpn-2.1_rc4/cryptoapi.c 2007-09-22 14:08:09.0 +0300
@@ -48,6 +48,8 @@
 static HINSTANCE crypt32dll = NULL;
 static BOOL WINAPI (*CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT pCert, 
DWORD dwFlags,
 void *pvReserved, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec, BOOL 
*pfCallerFreeProv) = NULL;
+static PCCERT_CONTEXT WINAPI (*CertCreateCertificateContext) (DWORD 
dwCertEncodingType,
+ const BYTE *pbCertEncoded, DWORD cbCertEncoded) = NULL;
 #endif

 /* Size of an SSL signature: MD5+SHA1 */
@@ -65,6 +67,8 @@ static BOOL WINAPI (*CryptAcquireCertifi
 #define CRYPTOAPI_F_CRYPT_SIGN_HASH106
 #define CRYPTOAPI_F_LOAD_LIBRARY   107
 #define CRYPTOAPI_F_GET_PROC_ADDRESS   108
+#define CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT   109
+#define CRYPTOAPI_F_CERT_GET_CERT_CHAIN110

 static ERR_STRING_DATA CRYPTOAPI_str_functs[] ={
 { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0),   
"microsoft cryptoapi"},
@@ -77,6 +81,8 @@ static ERR_STRING_DATA CRYPTOAPI_str_fun
 { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), 
"CryptSignHash" },
 { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0),
"LoadLibrary" },
 { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0),
"GetProcAddress" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT, 0),
"CertCreateCertificateContext" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_GET_CERT_CHAIN, 0), 
"CertGetCertificateChain" },
 { 0, NULL }
 };

@@ -364,7 +370,7 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
 }

 /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
-cert = d2i_X509(NULL, (unsigned char **) >cert_context->pbCertEncoded,
+cert = d2i_X509(NULL, (const unsigned char **) 
>cert_context->pbCertEncoded,
cd->cert_context->cbCertEncoded);
 if (cert == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
@@ -461,3 +467,81 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
 }
 return 0;
 }
+
+int CryptoAPI_verify_certificate(X509 *x509)
+{
+  int ret = -1;
+  int len;
+  unsigned char *buf = NULL;
+
+  PCCERT_CONTEXT pCertContext = NULL;
+  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+  CERT_ENHKEY_USAGE EnhkeyUsage;
+  CERT_USAGE_MATCH CertUsage;  
+  CERT_CHAIN_PARA ChainPara;
+
+  /* Convert from internal X509 format to DER */
+  len = i2d_X509(x509, );
+  if (len < 0) {
+   SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
+   goto err;
+  }
+
+#ifdef __MINGW32_VERSION
+/* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 
3.1
+ * anyway. This is a hack around that problem. */
+if (crypt32dll == NULL) {
+   crypt32dll = LoadLibrary("crypt32");
+   if (crypt32dll == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
+   goto err;
+   }
+}
+if (CertCreateCertificateContext == NULL) {
+   CertCreateCertificateContext = GetProcAddress(crypt32dll,
+   "CertCreateCertificateContext");
+   if (CertCreateCertificateContext == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
+   goto err;
+   }
+}
+#endif
+
+  /* Create a certificate context based on the above certificate */
+  pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | 
PKCS_7_ASN_ENCODING,
+   buf, len);
+  if (pCertContext == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT);
+   goto err;
+  }
+
+  /* Create an empty issuer list */
+  EnhkeyUsage.cUsageIdentifier = 0;
+  EnhkeyUsage.rgpszUsageIdentifier = NULL;
+  CertUsage.dwType = USAGE_MATCH_TYPE_AND;
+  CertUsage.Usage  = EnhkeyUsage;
+
+  /* Searching and matching criteria to be used when building the chain */
+  ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
+  ChainPara.RequestedUsage = CertUsage;
+
+  /* Get the certificate chain of our certificate */
+  if (!CertGetCertificateChain(NULL, pCertContext, NULL, NULL, ,
+   0, NULL, )) {
+   CRYPTOAPIerr(CRYPTOAPI_F_CERT_GET_CERT_CHAIN);
+   goto err;
+  }
+
+  /* return 1 when the certificate is trusted, 0 when it's not; -1 on error */
+  ret = (pChainContext->TrustStatus.dwErrorStatus == 

[Openvpn-devel] client-cert-not-required == client-cert-do-not-check

2007-01-04 Thread Faidon Liambotis
Hello again,
While fiddling with the OpenVPN code for the patch -look at my other
mail- I noticed the following:
When a server specifies client-cert-not-required and the client passes a
certificate, the server does not check this certificate for validity,
i.e. no trust verification (signed by the CA, not in a CRL etc.), no
tls-remote/ns-cert-type/tls-verify handling.
Right now there is a conditional that calls
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER |  
 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
 verify_callback);
when client-cert-not-required is not set and does nothing but warn when
it's set in the options.

I think that the proper thing to do would be to alter the behavior and call
SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_callback);
when the option is passed to OpenVPN and keep the current behavior for
the other case.

Is there a reason not to?
I can think of a reason to do that: allow a server that either accepts a
username/password _or_ a valid certificate -- to allow a migration for
example. This of course would need a clever hack with
auth-user-pass-verify/tls-verify scripts or may be a new environmental
variable TLS_VERIFIED.

Another reason to do it is because it's the obvious thing to do:
-not-required doesn't mean -do-not-check/-ignored, it means "I will not
fail if you don't provide it but I will fail if provide one that I can't
verify", IMHO.

Comments?

Regards,
Faidon



Re: [Openvpn-devel] [PATCH v2] Use CryptoAPI to verify certificates

2007-01-04 Thread Faidon Liambotis
Hi,
Thank you for your comments.

Alon Bar-Lev wrote:
> On 1/3/07, Faidon Liambotis <parav...@debian.org> wrote:
>> Ok, here's another try, even though I didn't get any comments on the
>> first one :-)
>>
>> This is a totally different approach; the previous one was flawed in at
>> least two aspects:
> 
> This is better.
> But you should use CertVerifyCertificateChainPolicy in order to verify
> chain, you should have two policies, one for server and one for
> client...
I've thought about it but didn't implement it because the only policy I
could think of was the nsCertType checking which is already being done
by OpenSSL if the user requested it.

> I think you can remove the global variable you added to ssl.c and put
> it in the session.
True, I will fix this.

Regards,
Faidon



[Openvpn-devel] [PATCH v2] Use CryptoAPI to verify certificates

2007-01-02 Thread Faidon Liambotis
Ok, here's another try, even though I didn't get any comments on the
first one :-)

This is a totally different approach; the previous one was flawed in at
least two aspects:
- A certificate signed by an CA stored in the "Intermediate CA store"
but not trusted would be considered acceptable by OpenVPN.
- There wasn't any CRL checking.

This time, instead of importing CryptoAPI stores into OpenSSL, I'm using
CryptoAPI functions to actually check for the trust status of the
certificate in OpenSSL's verify callback. This way, we are submitting
the server's certificate to the same criteria as any other native
Windows (i.e. non-OpenSSL) application would.

As always, the patch has been compile and runtime tested. No manpage
documentation yet -even though it's fairly obvious-, I'm still waiting for
comments.

Best regards,
Faidon

diff -Nurp openvpn-2.1_rc1/cryptoapi.c openvpn-2.1_rc1-void/cryptoapi.c
--- openvpn-2.1_rc1/cryptoapi.c Mon Oct 16 01:30:21 2006
+++ openvpn-2.1_rc1-void/cryptoapi.cWed Jan  3 09:09:52 2007
@@ -48,6 +48,8 @@
 static HINSTANCE crypt32dll = NULL;
 static BOOL WINAPI (*CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT pCert, 
DWORD dwFlags,
 void *pvReserved, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec, BOOL 
*pfCallerFreeProv) = NULL;
+static PCCERT_CONTEXT WINAPI (*CertCreateCertificateContext) (DWORD 
dwCertEncodingType,
+ const BYTE *pbCertEncoded, DWORD cbCertEncoded) = NULL;
 #endif

 /* Size of an SSL signature: MD5+SHA1 */
@@ -65,6 +67,8 @@ static BOOL WINAPI (*CryptAcquireCertifi
 #define CRYPTOAPI_F_CRYPT_SIGN_HASH106
 #define CRYPTOAPI_F_LOAD_LIBRARY   107
 #define CRYPTOAPI_F_GET_PROC_ADDRESS   108
+#define CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT   109
+#define CRYPTOAPI_F_CERT_GET_CERT_CHAIN110

 static ERR_STRING_DATA CRYPTOAPI_str_functs[] ={
 { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0),   
"microsoft cryptoapi"},
@@ -77,6 +81,8 @@ static ERR_STRING_DATA CRYPTOAPI_str_fun
 { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), 
"CryptSignHash" },
 { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0),
"LoadLibrary" },
 { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0),
"GetProcAddress" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT, 0),
"CertCreateCertificateContext" },
+{ ERR_PACK(0, CRYPTOAPI_F_CERT_GET_CERT_CHAIN, 0), 
"CertGetCertificateChain" },
 { 0, NULL }
 };

@@ -364,7 +370,7 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
 }

 /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
-cert = d2i_X509(NULL, (unsigned char **) >cert_context->pbCertEncoded,
+cert = d2i_X509(NULL, (const unsigned char **) 
>cert_context->pbCertEncoded,
cd->cert_context->cbCertEncoded);
 if (cert == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
@@ -460,4 +466,82 @@ int SSL_CTX_use_CryptoAPI_certificate(SS
}
 }
 return 0;
+}
+
+int CryptoAPI_verify_certificate(X509 *x509)
+{
+  int ret = -1;
+  int len;
+  unsigned char *buf = NULL;
+
+  PCCERT_CONTEXT pCertContext = NULL;
+  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+  CERT_ENHKEY_USAGE EnhkeyUsage;
+  CERT_USAGE_MATCH CertUsage;  
+  CERT_CHAIN_PARA ChainPara;
+
+  /* Convert from internal X509 format to DER */
+  len = i2d_X509(x509, );
+  if (len < 0) {
+   SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
+   goto err;
+  }
+
+#ifdef __MINGW32_VERSION
+/* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 
3.1
+ * anyway. This is a hack around that problem. */
+if (crypt32dll == NULL) {
+   crypt32dll = LoadLibrary("crypt32");
+   if (crypt32dll == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
+   goto err;
+   }
+}
+if (CertCreateCertificateContext == NULL) {
+   CertCreateCertificateContext = GetProcAddress(crypt32dll,
+   "CertCreateCertificateContext");
+   if (CertCreateCertificateContext == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
+   goto err;
+   }
+}
+#endif
+
+  /* Create a certificate context based on the above certificate */
+  pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | 
PKCS_7_ASN_ENCODING,
+   buf, len);
+  if (pCertContext == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT);
+   goto err;
+  }
+
+  /* Create an empty issuer list */
+  EnhkeyUsage.cUsageIdentifier = 0;
+  EnhkeyUsage.rgpszUsageIdentifier = NULL;
+  CertUsage.dwType = USAGE_MATCH_TYPE_AND;
+  CertUsage.Usage  = EnhkeyUsage;
+
+  /* Searching and matching criteria to be used when building the chain */
+  ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
+  ChainPara.RequestedUsage = CertUsage;
+
+  

[Openvpn-devel] [PATCH] Use CryptoAPI CA store

2006-12-24 Thread Faidon Liambotis
Hello,

Below you will find a patch that creates a new configuration option
--cryptoapicastore (the naming sucks, I know...) which enables certificate
verification using Windows Certificate Stores (CA and ROOT).
It can be used in addition to --cafile and --capath or standalone.
I have compile and briefly runtime tested it and it works as intended.
It should be used with care -and this should probably be noted
somewhere- and preferrably in conjuction with tls-verify or tls-remote
and/or password authentication.
I have a couple of improvements in mind (e.g. optionally filtering by
certificate subject) and the documentation for the manpage is missing,
but I'm posting this early since I will be on vacation for the next
week.

Happy holidays :-)

Best regards,
Faidon 

diff -Nur openvpn-2.1_rc1/cryptoapi.c openvpn-2.1_rc1-void/cryptoapi.c
--- openvpn-2.1_rc1/cryptoapi.c 2006-10-16 01:30:21.0 +0300
+++ openvpn-2.1_rc1-void/cryptoapi.c2006-12-22 19:20:34.0 +0200
@@ -48,6 +48,8 @@
 static HINSTANCE crypt32dll = NULL;
 static BOOL WINAPI (*CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT pCert, 
DWORD dwFlags,
 void *pvReserved, HCRYPTPROV *phCryptProv, DWORD *pdwKeySpec, BOOL 
*pfCallerFreeProv) = NULL;
+static PCCERT_CONTEXT WINAPI (*CertEnumCertificatesInStore) (HCERTSTORE 
hCertStore,
+ PCCERT_CONTEXT pPrevCertContext) = NULL;
 #endif

 /* Size of an SSL signature: MD5+SHA1 */
@@ -364,7 +366,8 @@
 }

 /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
-cert = d2i_X509(NULL, (unsigned char **) >cert_context->pbCertEncoded,
+cert = d2i_X509(NULL,
+   (const unsigned char **) >cert_context->pbCertEncoded,
cd->cert_context->cbCertEncoded);
 if (cert == NULL) {
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
@@ -461,3 +464,57 @@
 }
 return 0;
 }
+
+int SSL_CTX_add_CryptoAPI_certificate_store(SSL_CTX *ssl_ctx, const char 
*store)
+{
+HCERTSTORE cs;
+PCCERT_CONTEXT ctx = NULL;
+X509 *cert = NULL;
+
+cs = CertOpenSystemStore(0, store);
+if (cs == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
+   goto err;
+}
+
+#ifdef __MINGW32_VERSION
+/* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 
3.1
+ * anyway. This is a hack around that problem. */
+if (crypt32dll == NULL) {
+   crypt32dll = LoadLibrary("crypt32");
+   if (crypt32dll == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
+   goto err;
+   }
+}
+if (CertEnumCertificatesInStore == NULL) {
+   CertEnumCertificatesInStore = GetProcAddress(crypt32dll,
+   "CertEnumCertificatesInStore");
+   if (CertEnumCertificatesInStore == NULL) {
+   CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
+   goto err;
+   }
+}
+#endif
+
+while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
+   cert = d2i_X509(NULL, (const unsigned char **) >pbCertEncoded,
+   ctx->cbCertEncoded);
+   if (cert == NULL) {
+   SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
+   goto err;
+   }
+
+   if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+ goto err;
+   }
+   X509_free(cert);
+}
+CertCloseStore(cs, 0);
+return 1;
+
+  err:
+if (cert)
+   X509_free(cert);
+return 0;
+}
diff -Nur openvpn-2.1_rc1/cryptoapi.h openvpn-2.1_rc1-void/cryptoapi.h
--- openvpn-2.1_rc1/cryptoapi.h 2006-10-16 01:30:21.0 +0300
+++ openvpn-2.1_rc1-void/cryptoapi.h2006-12-22 05:24:19.0 +0200
@@ -2,6 +2,7 @@
 #define _CRYPTOAPI_H_

 int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop);
+int SSL_CTX_add_CryptoAPI_certificate_store(SSL_CTX *ssl_ctx, const char 
*store);


 #endif /* !_CRYPTOAPI_H_ */
diff -Nur openvpn-2.1_rc1/options.c openvpn-2.1_rc1-void/options.c
--- openvpn-2.1_rc1/options.c   2006-10-16 01:30:21.0 +0300
+++ openvpn-2.1_rc1-void/options.c  2006-12-22 06:51:37.0 +0200
@@ -447,6 +447,7 @@
 #ifdef WIN32
   "--cryptoapicert select-string : Load the certificate and private key from 
the\n"
   "  Windows Certificate System Store.\n"
+  "--cryptoapicastore : Add Windows Certificate Store Certificate 
Authorities.\n"
 #endif
   "--tls-cipher l  : A list l of allowable TLS ciphers separated by : 
(optional).\n"
   ": Use --show-tls to see a list of supported TLS ciphers.\n"
@@ -1233,6 +1234,7 @@
   SHOW_STR (pkcs12_file);
 #ifdef WIN32
   SHOW_STR (cryptoapi_cert);
+  SHOW_BOOL (cryptoapi_castore);
 #endif
   SHOW_STR (cipher_list);
   SHOW_STR (tls_verify);
@@ -1806,8 +1808,8 @@
 #ifdef WIN32
   if (options->cryptoapi_cert)
{
- if ((!(options->ca_file)) && (!(options->ca_path)))
-   msg(M_USAGE, "You must define CA file (--ca) or CA path 
(--capath)");
+ if ((!(options->ca_file)) &&