You can subscribe to this list here.
| 2002 | Jan | Feb | Mar | Apr (24) | May (14) | Jun (29) | Jul (33) | Aug (3) | Sep (8) | Oct (18) | Nov (1) | Dec (10) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 | Jan (3) | Feb (33) | Mar (7) | Apr (28) | May (30) | Jun (5) | Jul (10) | Aug (7) | Sep (32) | Oct (41) | Nov (20) | Dec (10) |
| 2004 | Jan (24) | Feb (18) | Mar (57) | Apr (40) | May (55) | Jun (48) | Jul (77) | Aug (15) | Sep (56) | Oct (80) | Nov (74) | Dec (52) |
| 2005 | Jan (38) | Feb (42) | Mar (39) | Apr (56) | May (79) | Jun (73) | Jul (16) | Aug (23) | Sep (68) | Oct (77) | Nov (52) | Dec (27) |
| 2006 | Jan (27) | Feb (18) | Mar (51) | Apr (62) | May (28) | Jun (50) | Jul (36) | Aug (33) | Sep (47) | Oct (50) | Nov (77) | Dec (13) |
| 2007 | Jan (15) | Feb (8) | Mar (14) | Apr (18) | May (25) | Jun (16) | Jul (16) | Aug (19) | Sep (32) | Oct (17) | Nov (5) | Dec (5) |
| 2008 | Jan (64) | Feb (25) | Mar (25) | Apr (6) | May (28) | Jun (20) | Jul (10) | Aug (27) | Sep (28) | Oct (59) | Nov (37) | Dec (43) |
| 2009 | Jan (40) | Feb (25) | Mar (12) | Apr (57) | May (46) | Jun (29) | Jul (39) | Aug (10) | Sep (20) | Oct (42) | Nov (50) | Dec (57) |
| 2010 | Jan (82) | Feb (165) | Mar (256) | Apr (260) | May (36) | Jun (87) | Jul (53) | Aug (89) | Sep (107) | Oct (51) | Nov (88) | Dec (117) |
| 2011 | Jan (69) | Feb (60) | Mar (113) | Apr (71) | May (67) | Jun (90) | Jul (88) | Aug (90) | Sep (48) | Oct (64) | Nov (69) | Dec (118) |
| 2012 | Jan (49) | Feb (528) | Mar (351) | Apr (190) | May (238) | Jun (193) | Jul (104) | Aug (100) | Sep (57) | Oct (41) | Nov (47) | Dec (51) |
| 2013 | Jan (94) | Feb (57) | Mar (96) | Apr (105) | May (77) | Jun (102) | Jul (27) | Aug (81) | Sep (32) | Oct (53) | Nov (127) | Dec (65) |
| 2014 | Jan (113) | Feb (59) | Mar (104) | Apr (259) | May (70) | Jun (70) | Jul (146) | Aug (45) | Sep (58) | Oct (149) | Nov (77) | Dec (83) |
| 2015 | Jan (53) | Feb (66) | Mar (86) | Apr (50) | May (135) | Jun (76) | Jul (151) | Aug (83) | Sep (97) | Oct (262) | Nov (245) | Dec (231) |
| 2016 | Jan (131) | Feb (233) | Mar (97) | Apr (138) | May (221) | Jun (254) | Jul (92) | Aug (248) | Sep (168) | Oct (275) | Nov (477) | Dec (445) |
| 2017 | Jan (218) | Feb (217) | Mar (146) | Apr (172) | May (216) | Jun (252) | Jul (164) | Aug (192) | Sep (190) | Oct (143) | Nov (255) | Dec (182) |
| 2018 | Jan (295) | Feb (164) | Mar (113) | Apr (147) | May (64) | Jun (262) | Jul (184) | Aug (90) | Sep (69) | Oct (364) | Nov (102) | Dec (101) |
| 2019 | Jan (119) | Feb (64) | Mar (64) | Apr (102) | May (57) | Jun (154) | Jul (84) | Aug (81) | Sep (76) | Oct (102) | Nov (233) | Dec (89) |
| 2020 | Jan (38) | Feb (170) | Mar (155) | Apr (172) | May (120) | Jun (223) | Jul (461) | Aug (227) | Sep (268) | Oct (113) | Nov (56) | Dec (124) |
| 2021 | Jan (121) | Feb (48) | Mar (334) | Apr (345) | May (207) | Jun (136) | Jul (71) | Aug (112) | Sep (122) | Oct (173) | Nov (184) | Dec (223) |
| 2022 | Jan (197) | Feb (206) | Mar (156) | Apr (212) | May (192) | Jun (170) | Jul (143) | Aug (380) | Sep (182) | Oct (148) | Nov (128) | Dec (269) |
| 2023 | Jan (248) | Feb (196) | Mar (264) | Apr (36) | May (123) | Jun (66) | Jul (120) | Aug (48) | Sep (157) | Oct (198) | Nov (300) | Dec (273) |
| 2024 | Jan (271) | Feb (147) | Mar (207) | Apr (78) | May (107) | Jun (168) | Jul (151) | Aug (51) | Sep (438) | Oct (221) | Nov (302) | Dec (357) |
| 2025 | Jan (451) | Feb (219) | Mar (326) | Apr (232) | May (306) | Jun (181) | Jul (452) | Aug (282) | Sep (620) | Oct (793) | Nov (682) | Dec |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| | | | | | | 1 |
| 2 (11) | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 (3) | 11 (1) | 12 (2) | 13 (1) | 14 (2) | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 (2) | 22 (6) |
| 23 (1) | 24 | 25 | 26 (1) | 27 (2) | 28 | 29 |
| 30 | | | | | | |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-27 20:57:17 |
On 9/27/07, Faidon Liambotis <par...@de...> wrote: > Alon, ping? Oh... missed your post. Please don't keep change the subject line. And replay all to every correction. > I'd really like to have this patch merged this time. > If you don't, just say so, so it can get merged. Only James can merge patches... I only review this as I can help you improve it. > If you have any more comments or objections, just say so so I can fix them. Some more notes: 1. For CertGetCertificateChain() you should use the following flags: CERT_CHAIN_REVOCATION_CHECK_CHAIN So that CA may suicide. 2. CertVerifyCertificateChainPolicy() PolicyPara extra should be set: fdwChecks should be SECURITY_FLAG_IGNORE_CERT_CN_INVALID as we check subject name within OpenVPN. dwAuthType should be AUTHTYPE_CLIENT or AUTHTYPE_SERVER depending on the configuration. I think that peer-to-peer should be AUTHTYPE_SERVER. 3. I am not sure you require: ChainPara.RequestedUsage = <something> Have you tried to leave it zero? 4. I guess a cleaner code would load crypt32.dll once in the module, moving the LoadLibrary and GetProcAddress to a single function, calling it from initialization code. Also if you already mess with this module, I guess a cleanup code should be added to free the library during termination... :) Best Regards, Alon Bar-Lev. |
| From: Faidon L. <par...@de...> - 2007-09-27 12:41:46 |
Faidon Liambotis wrote: > Alon Bar-Lev wrote: >> 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. Alon, ping? I'd really like to have this patch merged this time. If you have any more comments or objections, just say so so I can fix them. If you don't, just say so, so it can get merged. Thanks, Faidon |
| From: Jacob W. <jwi...@ap...> - 2007-09-26 18:59:10 |
Howdy, OpenSSL has been FIPS 140-2 validated for a few months now. The "fips mode" within OpenSSL is not automatic, and requires some invocation from within the calling app. See here for details: http://www.openssl.org/docs/fips/UserGuide-1.1.1.pdf Running in this mode disables all ciphers besides AES and 3DES. Are these features feasible for OpenVPN? If so, our company would like to see support added, and could be willing to fund the development. If anyone is interested in a contract for this project, please contact me directly. Thanks, Jacob Wilkins, CISSP Appriss, Inc |
| From: Faidon L. <par...@de...> - 2007-09-23 08:17:23 |
Alon Bar-Lev wrote: > On 9/22/07, Faidon Liambotis <par...@de...> 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.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/cryptoapi.c 2007-09-23 11:07:14.000000000 +0300 @@ -45,9 +45,15 @@ #define CERT_STORE_READONLY_FLAG 0x00008000 #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 #define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 0x00000004 +#define CERT_CHAIN_REVOCATION_CHECK_END_CERT 0x10000000 +#define CERT_CHAIN_REVOCATION_CHECK_CHAIN 0x20000000 +#define CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT 0x40000000 +#define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY 0x80000000 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_HASH 106 #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_CHAIN 110 +#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 **) &cd->cert_context->pbCertEncoded, + cert = d2i_X509(NULL, (const unsigned char **) &cd->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, &buf); + 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, &ChainPara, + CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, + NULL, &pChainContext)) { + CRYPTOAPIerr(CRYPTOAPI_F_CERT_GET_CERT_CHAIN); + goto err; + } + + PolicyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA); + PolicyPara.dwFlags = 0; + PolicyPara.pvExtraPolicyPara = NULL; + + PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS); + + if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, pChainContext, + &PolicyPara, &PolicyStatus)) { + CRYPTOAPIerr(CRYPTOAPI_F_CERT_VERIFY_CERT_CHAIN_POLICY); + goto err; + } + + /* return 1 when the certificate is trusted, 0 when it's not */ + ret = !PolicyStatus.dwError; + + err: + if (buf) + OPENSSL_free(buf); + if (pChainContext) + CertFreeCertificateChain(pChainContext); + if (pCertContext) + CertFreeCertificateContext(pCertContext); + + return ret; +} diff -urp openvpn-2.1_rc4.orig/cryptoapi.h openvpn-2.1_rc4/cryptoapi.h --- openvpn-2.1_rc4.orig/cryptoapi.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/cryptoapi.h 2007-09-23 11:06:05.000000000 +0300 @@ -2,6 +2,7 @@ #define _CRYPTOAPI_H_ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop); +int CryptoAPI_verify_certificate(X509 *x509); #endif /* !_CRYPTOAPI_H_ */ diff -urp openvpn-2.1_rc4.orig/init.c openvpn-2.1_rc4/init.c --- openvpn-2.1_rc4.orig/init.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/init.c 2007-09-23 11:06:05.000000000 +0300 @@ -1558,6 +1558,10 @@ do_init_crypto_tls (struct context *c, c to.remote_cert_eku = options->remote_cert_eku; to.es = c->c2.es; +#ifdef WIN32 + to.cryptoapi_ca = options->cryptoapi_ca; +#endif + #ifdef ENABLE_DEBUG to.gremlin = c->options.gremlin; #endif diff -urp openvpn-2.1_rc4.orig/openvpn.8 openvpn-2.1_rc4/openvpn.8 --- openvpn-2.1_rc4.orig/openvpn.8 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/openvpn.8 2007-09-23 11:06:05.000000000 +0300 @@ -124,6 +124,7 @@ openvpn \- secure IP tunnel daemon. [\ \fB\-\-connect\-retry\-max\fR\ \fIn\fR\ ] [\ \fB\-\-crl\-verify\fR\ \fIcrl\fR\ ] [\ \fB\-\-cryptoapicert\fR\ \fIselect\-string\fR\ ] +[\ \fB\-\-cryptoapica\fR\ ] [\ \fB\-\-daemon\fR\ \fI[progname]\fR\ ] [\ \fB\-\-dev\-node\fR\ \fInode\fR\ ] [\ \fB\-\-dev\-type\fR\ \fIdevice\-type\fR\ ] @@ -3769,7 +3770,26 @@ To select a certificate, based on certif The thumbprint hex string can easily be copy-and-pasted from the Windows Certificate Store GUI. +.\"********************************************************* +.TP +.B --cryptoapica +Use the Windows Certficate System Store to verify presented certificates +(Windows Only). + +Use this option instead of or in addition to +.B --ca. + +This makes it possible to verify certificates against the Certificate Store +instead of having OpenVPN read the certificate authority (CA) file. +Windows Certificate Store checks Certificate Revocation Lists (CRLs) +automatically and will reject revoked certificates. +The Certificate Store includes by default many known Certificate Authorities. +Use this setting with extreme caution and preferrably in combination with +.B --tls-verify +or +.B --tls-remote +options. .\"********************************************************* .TP .B --key-method m diff -urp openvpn-2.1_rc4.orig/options.c openvpn-2.1_rc4/options.c --- openvpn-2.1_rc4.orig/options.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/options.c 2007-09-23 11:06:05.000000000 +0300 @@ -450,6 +450,8 @@ static const char usage_message[] = #ifdef WIN32 "--cryptoapicert select-string : Load the certificate and private key from the\n" " Windows Certificate System Store.\n" + "--cryptoapica : Check against Certificate Authorities stored in Windows\n" + " Certificate System Store.\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" @@ -1236,6 +1238,7 @@ show_settings (const struct options *o) SHOW_STR (pkcs12_file); #ifdef WIN32 SHOW_STR (cryptoapi_cert); + SHOW_BOOL (cryptoapi_ca); #endif SHOW_STR (cipher_list); SHOW_STR (tls_verify); @@ -1809,8 +1812,8 @@ options_postprocess (struct options *opt #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)) && (!(options->ca_path)) && (!(options->cryptoapi_ca))) + msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath) or CryptoAPI CA (--cryptoapica)"); if (options->cert_file) msg(M_USAGE, "Parameter --cert cannot be used when --cryptoapicert is also specified."); if (options->priv_key_file) @@ -1831,8 +1834,13 @@ options_postprocess (struct options *opt } else { +#ifdef WIN32 + if ((!(options->ca_file)) && (!(options->ca_path)) && (!(options->cryptoapi_ca))) + msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath) or CryptoAPI CAs (--cryptoapica)"); +#else if ((!(options->ca_file)) && (!(options->ca_path))) msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)"); +#endif if (pull) { const int sum = (options->cert_file != NULL) + (options->priv_key_file != NULL); @@ -4889,6 +4897,11 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_GENERAL); options->cryptoapi_cert = p[1]; } + else if (streq (p[0], "cryptoapica")) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->cryptoapi_ca = true; + } #endif else if (streq (p[0], "key") && p[1]) { diff -urp openvpn-2.1_rc4.orig/options.h openvpn-2.1_rc4/options.h --- openvpn-2.1_rc4.orig/options.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/options.h 2007-09-23 11:06:05.000000000 +0300 @@ -424,6 +424,7 @@ struct options #ifdef WIN32 const char *cryptoapi_cert; + bool cryptoapi_ca; #endif /* data channel key exchange method */ diff -urp openvpn-2.1_rc4.orig/proxy.c openvpn-2.1_rc4/proxy.c --- openvpn-2.1_rc4.orig/proxy.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/proxy.c 2007-09-23 11:06:05.000000000 +0300 @@ -39,7 +39,7 @@ #include "base64.h" #include "ntlm.h" -#ifdef WIN32 +#if defined(WIN32) && !defined(__MINGW32__) #include "ieproxy.h" #endif diff -urp openvpn-2.1_rc4.orig/ssl.c openvpn-2.1_rc4/ssl.c --- openvpn-2.1_rc4.orig/ssl.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/ssl.c 2007-09-23 11:06:05.000000000 +0300 @@ -543,13 +543,19 @@ verify_callback (int preverify_ok, X509_ msg (D_LOW, "X509: %s", subject); #endif - /* did peer present cert which was signed our root cert? */ + /* did peer present cert which was signed by our root cert? */ if (!preverify_ok) { - /* Remote site specified a certificate, but it's not correct */ - msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", - ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); - goto err; /* Reject connection */ +#ifdef WIN32 + /* if cryptoapica was not enabled, fail; otherwise check against the CA Store */ + if (!(opt->cryptoapi_ca && CryptoAPI_verify_certificate(ctx->current_cert))) +#endif + { + /* Remote site specified a certificate, but it's not correct */ + msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", + ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); + goto err; /* Reject connection */ + } } /* warn if cert chain is too deep */ diff -urp openvpn-2.1_rc4.orig/ssl.h openvpn-2.1_rc4/ssl.h --- openvpn-2.1_rc4.orig/ssl.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/ssl.h 2007-09-23 11:06:05.000000000 +0300 @@ -415,6 +415,9 @@ struct tls_options int ns_cert_type; unsigned remote_cert_ku[MAX_PARMS]; const char *remote_cert_eku; +#ifdef WIN32 + bool cryptoapi_ca; +#endif /* allow openvpn config info to be passed over control channel */ |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-22 19:26:30 |
On 9/22/07, Faidon Liambotis <par...@de...> 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. Alon. |
| From: Faidon L. <par...@de...> - 2007-09-22 19:22:39 |
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 |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-22 19:06:15 |
On 9/22/07, Faidon Liambotis <par...@de...> wrote: > It seems that is much better to ask Windows to check whether the > presented certificate is trusted or not than try to build the trust path > yourself and import it to OpenSSL. OK... So you need to use CertVerifyCertificateChainPolicy() with CERT_CHAIN_POLICY_SSL Alon. |
| From: Faidon L. <par...@de...> - 2007-09-22 18:47:01 |
Alon Bar-Lev wrote: > Why not use SSL_CTX_add_client_CA and add all CAPI root store into > OpenSSL context? My initial approach (v1) was that (albeit not with SSL_CTX_add_client_CA but with X509_STORE_add_cert). This was flawed, for the reasons I mentioned in v2 changelog (which btw, you have seen and commented on :-): - CRLs are not handled that way. - It is hard, if not impossible, to build proper chains from the imported CAs. e.g. you can have an intermediate CA in Windows Certificate Store that is *not* trusted by Windows because the root CA doesn't exist in the respective store. - It felt like a gross hack. It seems that is much better to ask Windows to check whether the presented certificate is trusted or not than try to build the trust path yourself and import it to OpenSSL. Regards, Faidon |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-22 18:04:50 |
On 9/22/07, Faidon Liambotis <par...@de...> wrote: > 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 Why not use SSL_CTX_add_client_CA and add all CAPI root store into OpenSSL context? Alon. |
| From: Faidon L. <par...@de...> - 2007-09-22 17:41:45 |
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.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/cryptoapi.c 2007-09-22 14:08:09.000000000 +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_HASH 106 #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_CHAIN 110 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 **) &cd->cert_context->pbCertEncoded, + cert = d2i_X509(NULL, (const unsigned char **) &cd->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, &buf); + 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, &ChainPara, + 0, NULL, &pChainContext)) { + 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 == CERT_TRUST_NO_ERROR); + + err: + if (buf) + OPENSSL_free(buf); + if (pChainContext) + CertFreeCertificateChain(pChainContext); + if (pCertContext) + CertFreeCertificateContext(pCertContext); + + return ret; +} diff -urp openvpn-2.1_rc4.orig/cryptoapi.h openvpn-2.1_rc4/cryptoapi.h --- openvpn-2.1_rc4.orig/cryptoapi.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/cryptoapi.h 2007-09-22 14:08:09.000000000 +0300 @@ -2,6 +2,7 @@ #define _CRYPTOAPI_H_ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop); +int CryptoAPI_verify_certificate(X509 *x509); #endif /* !_CRYPTOAPI_H_ */ diff -urp openvpn-2.1_rc4.orig/init.c openvpn-2.1_rc4/init.c --- openvpn-2.1_rc4.orig/init.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/init.c 2007-09-22 14:08:09.000000000 +0300 @@ -1558,6 +1558,10 @@ do_init_crypto_tls (struct context *c, c to.remote_cert_eku = options->remote_cert_eku; to.es = c->c2.es; +#ifdef WIN32 + to.cryptoapi_ca = options->cryptoapi_ca; +#endif + #ifdef ENABLE_DEBUG to.gremlin = c->options.gremlin; #endif diff -urp openvpn-2.1_rc4.orig/openvpn.8 openvpn-2.1_rc4/openvpn.8 --- openvpn-2.1_rc4.orig/openvpn.8 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/openvpn.8 2007-09-22 14:33:27.000000000 +0300 @@ -124,6 +124,7 @@ openvpn \- secure IP tunnel daemon. [\ \fB\-\-connect\-retry\-max\fR\ \fIn\fR\ ] [\ \fB\-\-crl\-verify\fR\ \fIcrl\fR\ ] [\ \fB\-\-cryptoapicert\fR\ \fIselect\-string\fR\ ] +[\ \fB\-\-cryptoapica\fR\ ] [\ \fB\-\-daemon\fR\ \fI[progname]\fR\ ] [\ \fB\-\-dev\-node\fR\ \fInode\fR\ ] [\ \fB\-\-dev\-type\fR\ \fIdevice\-type\fR\ ] @@ -3769,7 +3770,26 @@ To select a certificate, based on certif The thumbprint hex string can easily be copy-and-pasted from the Windows Certificate Store GUI. +.\"********************************************************* +.TP +.B --cryptoapica +Use the Windows Certficate System Store to verify presented certificates +(Windows Only). + +Use this option instead of or in addition to +.B --ca. + +This makes it possible to verify certificates against the Certificate Store +instead of having OpenVPN read the certificate authority (CA) file. +Windows Certificate Store checks Certificate Revocation Lists (CRLs) +automatically and will reject revoked certificates. +The Certificate Store includes by default many known Certificate Authorities. +Use this setting with extreme caution and preferrably in combination with +.B --tls-verify +or +.B --tls-remote +options. .\"********************************************************* .TP .B --key-method m diff -urp openvpn-2.1_rc4.orig/options.c openvpn-2.1_rc4/options.c --- openvpn-2.1_rc4.orig/options.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/options.c 2007-09-22 14:15:41.000000000 +0300 @@ -450,6 +450,8 @@ static const char usage_message[] = #ifdef WIN32 "--cryptoapicert select-string : Load the certificate and private key from the\n" " Windows Certificate System Store.\n" + "--cryptoapica : Check against Certificate Authorities stored in Windows\n" + " Certificate System Store.\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" @@ -1236,6 +1238,7 @@ show_settings (const struct options *o) SHOW_STR (pkcs12_file); #ifdef WIN32 SHOW_STR (cryptoapi_cert); + SHOW_BOOL (cryptoapi_ca); #endif SHOW_STR (cipher_list); SHOW_STR (tls_verify); @@ -1809,8 +1812,8 @@ options_postprocess (struct options *opt #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)) && (!(options->ca_path)) && (!(options->cryptoapi_ca))) + msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath) or CryptoAPI CA (--cryptoapica)"); if (options->cert_file) msg(M_USAGE, "Parameter --cert cannot be used when --cryptoapicert is also specified."); if (options->priv_key_file) @@ -1831,8 +1834,13 @@ options_postprocess (struct options *opt } else { +#ifdef WIN32 + if ((!(options->ca_file)) && (!(options->ca_path)) && (!(options->cryptoapi_ca))) + msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath) or CryptoAPI CAs (--cryptoapica)"); +#else if ((!(options->ca_file)) && (!(options->ca_path))) msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)"); +#endif if (pull) { const int sum = (options->cert_file != NULL) + (options->priv_key_file != NULL); @@ -4889,6 +4897,11 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_GENERAL); options->cryptoapi_cert = p[1]; } + else if (streq (p[0], "cryptoapica")) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->cryptoapi_ca = true; + } #endif else if (streq (p[0], "key") && p[1]) { diff -urp openvpn-2.1_rc4.orig/options.h openvpn-2.1_rc4/options.h --- openvpn-2.1_rc4.orig/options.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/options.h 2007-09-22 14:08:09.000000000 +0300 @@ -424,6 +424,7 @@ struct options #ifdef WIN32 const char *cryptoapi_cert; + bool cryptoapi_ca; #endif /* data channel key exchange method */ diff -urp openvpn-2.1_rc4.orig/proxy.c openvpn-2.1_rc4/proxy.c --- openvpn-2.1_rc4.orig/proxy.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/proxy.c 2007-09-22 14:08:09.000000000 +0300 @@ -39,7 +39,7 @@ #include "base64.h" #include "ntlm.h" -#ifdef WIN32 +#if defined(WIN32) && !defined(__MINGW32__) #include "ieproxy.h" #endif diff -urp openvpn-2.1_rc4.orig/ssl.c openvpn-2.1_rc4/ssl.c --- openvpn-2.1_rc4.orig/ssl.c 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/ssl.c 2007-09-22 14:20:24.000000000 +0300 @@ -543,13 +543,19 @@ verify_callback (int preverify_ok, X509_ msg (D_LOW, "X509: %s", subject); #endif - /* did peer present cert which was signed our root cert? */ + /* did peer present cert which was signed by our root cert? */ if (!preverify_ok) { - /* Remote site specified a certificate, but it's not correct */ - msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", - ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); - goto err; /* Reject connection */ +#ifdef WIN32 + /* if cryptoapica was not enabled, fail; otherwise check against the CA Store */ + if (!(opt->cryptoapi_ca && CryptoAPI_verify_certificate(ctx->current_cert))) +#endif + { + /* Remote site specified a certificate, but it's not correct */ + msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", + ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); + goto err; /* Reject connection */ + } } /* warn if cert chain is too deep */ diff -urp openvpn-2.1_rc4.orig/ssl.h openvpn-2.1_rc4/ssl.h --- openvpn-2.1_rc4.orig/ssl.h 2007-04-26 00:38:46.000000000 +0300 +++ openvpn-2.1_rc4/ssl.h 2007-09-22 14:21:06.000000000 +0300 @@ -415,6 +415,9 @@ struct tls_options int ns_cert_type; unsigned remote_cert_ku[MAX_PARMS]; const char *remote_cert_eku; +#ifdef WIN32 + bool cryptoapi_ca; +#endif /* allow openvpn config info to be passed over control channel */ |
| From: Timothy B. <T.E...@me...> - 2007-09-21 20:21:27 |
<posted & mailed> In message <46E...@cy...>, Jeff Wiegley <je...@cy...> wrote: > Basically... > > # tunctl -u jeffw > # ifconfig tap0 10.10.0.1 netmask 255.255.255.0 > $ ./tapwatcher tap0 > > Then from another window I want to be able to do > "ping 10.10.0.1" and tapwatcher should spew the > raw Ethernet frames that would be generated on > tap0. No, that won't work as 10.10.0.1 is a local IP address. Try pinging 10.10.0.2, your program should then receive some ARP packets. > Am I missing something fundamental? LOL The address of an interface is an address of the host which the interface belongs to, and hosts process traffic addressed to them. Jeff Wiegley, I suggest you forward this message to je...@cy... so that he can read it. |
| From: Timothy B. <T.E...@me...> - 2007-09-21 20:12:50 |
<posted & mailed> In message <46E...@cy...>, Jeff Wiegley <je...@cy...> wrote: > Basically... > > # tunctl -u jeffw > # ifconfig tap0 10.10.0.1 netmask 255.255.255.0 > $ ./tapwatcher tap0 > > Then from another window I want to be able to do > "ping 10.10.0.1" and tapwatcher should spew the > raw Ethernet frames that would be generated on > tap0. No, that won't work as 10.10.0.1 is a local IP address. Try pinging 10.10.0.2, your program should then receive some ARP packets. > Am I missing something fundamental? LOL The address of an interface is an address of the host which the interface belongs to, and hosts process traffic addressed to them. Jeff Wiegley, I suggest you forward this message to je...@cy... so that he can read it. -- OpenPGP key fingerprint: D0A6 F403 9745 CED4 6B3B 94CC 8D74 8FC9 9F7F CFE4 |
| From: Arash Y. <ar...@bl...> - 2007-09-14 13:49:24 |
Hi Jeff, Last year, I had exactly the same situation. (every single bit of it!). I'd almost tried everywhere, TUN/TAP Author (Maxim K.), VTun mailing list and also here, OpenVPN-devel list, But no chance. :( In my case, this problem wasn't vital and I could carry on without having it solved, But I still have no idea why in the earth those ping requests should be replied to, while my select() even doesn't know about it! This time, I hope we can find a proper answer here and sorry for a useless reply. :) Regards, Arash On Thu, 2007-09-13 at 19:52 -0700, Jeff Wiegley wrote: > I know this is off-topic, sorry. The email address for > Max K. the creator of the tun/tap driver, simply bounces > and I'm beating my head against the wall. Since OpenVPN > uses tap devices in a raw state I hoped that maybe > somebody here would be able to help. Yeah, That address is abandoned for years! > > I want a very simply program that opens a tap device > and then displays all the Ethernet frames that come > through it. Basically I want something that delivers > Ethernet frames up to a userspace program. > > Basically... > > # tunctl -u jeffw > # ifconfig tap0 10.10.0.1 netmask 255.255.255.0 > $ ./tapwatcher tap0 > > Then from another window I want to be able to do > "ping 10.10.0.1" and tapwatcher should spew the > raw Ethernet frames that would be generated on > tap0. > > To that end I have written the program appended > here but it doesn't do anything. It starts up, it > reports it opened the tap and I get a decent > file descriptor value but the select hangs. > there is never anything present to read. > The weird thing that does happen is the pings are > responded to! Shouldn't the kernel be simply passing > the frames on to my tapwatcher program and not > processing them itself??? I can even SSH to the > stupid tap0 and I get logged into localhost. > Why is the kernel attached to tap0 and not my > tapwatcher program? > > Am I missing something fundamental? I would be happy > to contribute my result back to the kernel sources > to replace/augment the tuntap.txt Documentation that > is weak and doesn't really give a new tun/tap user > what he needs to get something working. (the examples > in vtun are also both broken and don't compile/run > on my 64-bit machine.) > > Thanks, here's the program I wrote. > > - Jeff > ------------------------------------------------------- > #include <stdio.h> > #include <sys/types.h> > #include <sys/stat.h> > #include <fcntl.h> > > #include <string.h> > > #include <sys/ioctl.h> > #include <net/if.h> > #include <netinet/if_ether.h> > #include <linux/if_tun.h> > > #include <errno.h> > #include <signal.h> > > #include <sys/select.h> > > int tun_alloc(char *dev) > { > struct ifreq ifr; > int result = -1; > int err; > > if( (result = open("/dev/net/tun", O_RDWR)) >= 0 ) > return result; > > memset(&ifr, 0, sizeof(ifr)); > > ifr.ifr_flags = IFF_TAP; > if( *dev ) > strncpy(ifr.ifr_name, dev, IFNAMSIZ); > > if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) > { > close(result); > return err; > } > > strcpy(dev, ifr.ifr_name); > > return result; > } > > int continue_running; > > void handler(int num, siginfo_t *info, void *context) > { > continue_running = 0; > } > > int main(int argc, char *argv[]) > { > continue_running = 0; > > struct sigaction action; > > action.sa_sigaction = handler; > sigemptyset (&action.sa_mask); > action.sa_flags = SA_SIGINFO; > > sigaction(SIGINT, &action, NULL); > > char name[128]; > strcpy(name,argv[1]); > int tap = tun_alloc(name); > > if (tap < 0) > perror("TAP failed: "); > else > { > continue_running = 1; > fprintf(stderr,"tap = %d, name = \"%s\"\n",tap,name); > while (continue_running) > { > fd_set watch; > FD_ZERO(&watch); > FD_SET(tap,&watch); > errno = 0; > select(tap+1,&watch, NULL, NULL, NULL); > fprintf(stderr,"ready\n"); > if (errno && (errno != EINTR)) > break; > } > close(tap); > } > } > ------------------------------------------------------------- > |
| From: Jeff W. <je...@cy...> - 2007-09-14 02:52:37 |
I know this is off-topic, sorry. The email address for Max K. the creator of the tun/tap driver, simply bounces and I'm beating my head against the wall. Since OpenVPN uses tap devices in a raw state I hoped that maybe somebody here would be able to help. I want a very simply program that opens a tap device and then displays all the Ethernet frames that come through it. Basically I want something that delivers Ethernet frames up to a userspace program. Basically... # tunctl -u jeffw # ifconfig tap0 10.10.0.1 netmask 255.255.255.0 $ ./tapwatcher tap0 Then from another window I want to be able to do "ping 10.10.0.1" and tapwatcher should spew the raw Ethernet frames that would be generated on tap0. To that end I have written the program appended here but it doesn't do anything. It starts up, it reports it opened the tap and I get a decent file descriptor value but the select hangs. there is never anything present to read. The weird thing that does happen is the pings are responded to! Shouldn't the kernel be simply passing the frames on to my tapwatcher program and not processing them itself??? I can even SSH to the stupid tap0 and I get logged into localhost. Why is the kernel attached to tap0 and not my tapwatcher program? Am I missing something fundamental? I would be happy to contribute my result back to the kernel sources to replace/augment the tuntap.txt Documentation that is weak and doesn't really give a new tun/tap user what he needs to get something working. (the examples in vtun are also both broken and don't compile/run on my 64-bit machine.) Thanks, here's the program I wrote. - Jeff ------------------------------------------------------- #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #include <net/if.h> #include <netinet/if_ether.h> #include <linux/if_tun.h> #include <errno.h> #include <signal.h> #include <sys/select.h> int tun_alloc(char *dev) { struct ifreq ifr; int result = -1; int err; if( (result = open("/dev/net/tun", O_RDWR)) >= 0 ) return result; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP; if( *dev ) strncpy(ifr.ifr_name, dev, IFNAMSIZ); if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { close(result); return err; } strcpy(dev, ifr.ifr_name); return result; } int continue_running; void handler(int num, siginfo_t *info, void *context) { continue_running = 0; } int main(int argc, char *argv[]) { continue_running = 0; struct sigaction action; action.sa_sigaction = handler; sigemptyset (&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGINT, &action, NULL); char name[128]; strcpy(name,argv[1]); int tap = tun_alloc(name); if (tap < 0) perror("TAP failed: "); else { continue_running = 1; fprintf(stderr,"tap = %d, name = \"%s\"\n",tap,name); while (continue_running) { fd_set watch; FD_ZERO(&watch); FD_SET(tap,&watch); errno = 0; select(tap+1,&watch, NULL, NULL, NULL); fprintf(stderr,"ready\n"); if (errno && (errno != EINTR)) break; } close(tap); } } ------------------------------------------------------------- -- Jeff Wiegley, PhD Cyte.Com, LLC |
| From: Ross C. <ros...@li...> - 2007-09-13 08:28:36 |
Sorry for cross posting across the users and devel lists. I'm thinking of adding a port knocking (and in time SPA - Single Packet Authentication) module to OpenVPN. And before anyone asks,.... we're using port knocking as a thin layer to obscure the devices from automated script kiddy scans. I am aware that it should not (and indeed is not) relied on as a security measure,... but it serves the purpose of making life a little harder for those without inside information to find the device/system service. So far I have a VERY cludgy implementation that does what I need it to do in the lab,... but I'd like to build a proper module for this. What I need the module to do is as follows... ================================ Whenever the OpenVPN service wants to connect to a remote OpenVPN server installation it need to take the address or hostname of the device it wants to connect to,... Parse that against a config file,... or config section of the current OpenVPN config file,... and collect the port knock sequence. Run the port knock sequence against the target host,... wait one (1) second to allow for the remote port opening,... and then run the standard OpenVPN protocol from there on. The opened port is opened ONLY to the host/IP from which the knock came and also only for 15seconds (reconfigurable). Thereafter the successfully initialized VPN traffic will be allowed through the ESTABLISHED rules of the firewall. This should work for multiple upstream servers and each port knock should be uniquely configurable per upstream server. And the port knock should be run regardless of the reason for the tunnel being brought down,... and it must be run whenever OpenVPN tries to recover from a stale or locked up tunnel as well. Any advice??? Anyone want to work on a project like this??? Any and all assistance more than gratefully accepted. |
| From: Pieter T. <pie...@gm...> - 2007-09-12 09:18:55 |
Hi All. I successfully setup my OpenVPN environment to connect from home to the office. (Congrats for the tool by the way, I love it). When I am the only connected person, then the connection works flawlessly, however, as soon as another person starts using the VPN at the same time (with different account), both our connections start stalling. This is, I am not able anymore to contact any service on our corporate network and I see the VPN client gets a timeout and reconnects to the server after about 1 minute. After this, the connection works again for a minute or less and the same thing happens. One thing I noticed is that when my VPN connection stalls, I cannot even connect to the VPN server machine with ssh (not over VPN). As soon as close my VPN client, I can connect to the VPN server again over SSH (no VPN). This is not something related to my machine, since I was able to reproduce from different machines. We are using a 2Mbit synchrone DSL connection, which should be more than enough to let two people connect to a webserver over VPN. Please find attached my server.conf and client.conf files for your convenience. I have been looking at logs and tcpdumps for days now, and I have absolutely no clue where the problem might be coming from. Any help would be kindly appreciated. Kind Regards, Pieter |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-12 03:48:28 |
On 9/12/07, Richard Hartmann <ric...@gm...> wrote: > would I want to do so even if I could. Still, I would want to ask you > _why_ you think this is a bad idea, especially in light of exactly the > same thing being available for the established certificate storage > system. The compile time option was released before the management interface was introduced... I guess that if the management interface would have been available this feature would have never implemented as well. Alon. |
| From: Richard H. <ric...@gm...> - 2007-09-11 21:47:06 |
On 10/09/2007, Alon Bar-Lev <alo...@gm...> wrote: > You can always provide your own management interface program that > supply static PIN. No need to change anything in OpenVPN. Yes, that is what I am doing at the moment. Still, I feel that it would be more reliable, less error prone and, yes, more secure to do it via config file. The argument that you could use the management interface holds true for the passphrase for normal certificates as well, still, after some discussion, the OpenVPN team decided to offer the option with the safety guard of it being a compile time option. I can, of course, not force anyone's hand and make them code or agree to anything, nor would I want to do so even if I could. Still, I would want to ask you _why_ you think this is a bad idea, especially in light of exactly the same thing being available for the established certificate storage system. Best regards, Richard |
| From: Alon Bar-L. <alo...@gm...> - 2007-09-10 20:23:17 |
You can always provide your own management interface program that supply static PIN. No need to change anything in OpenVPN. Alon. On 9/10/07, Richard Hartmann <ric...@gm...> wrote: > Hi all, > > > as most, if not all, of you will be aware, there is an option to pass > the certificate passphrase into OpenVPN if you compile OpenVPN with the > correct option, yourself. This Molly Guard enables people who know what > they are doing to automate the process a little bit more than would be > possible, otherwise. > > My request is that the same thing should be offered for the PKCS#11 > interface of 2.1. The discussion about the relative merits of the > management console and compiling your own OpenVPN binaries > notwithstanding, I feel that this approach is more secure, less prone to > failure and eases the overall process a _lot_. Furthermore, this > question has already been discussed in the mailing list archives and, > back then, it was decided to go the path of Bake Your Own to safeguard > people against themselves, at least for the passphrase. > > Is there any chance that this feature sees the light of day and if yes, > is anyone able and/or willing to venture a guess as to when this might > be the case? > > > Thank you for all the work on OpenVPN! > Richard > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2005. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Openvpn-devel mailing list > Ope...@li... > https://lists.sourceforge.net/lists/listinfo/openvpn-devel > |
| From: Maximilian W. <ma...@rf...> - 2007-09-10 16:55:46 |
Am Monday, den 3 September hub Maximilian Wilhelm folgendes in die Tasten: Hi! > This is an initial attempt to let OpenVPN 2.1 write a wtmp log of all > connections including the username, it's VPN IP and the real remote IP > the user connected from. [...] Is nobody interested in this? That would be very sad. Ciao Max -- Follow the white penguin. |
| From: Richard H. <ric...@gm...> - 2007-09-10 10:22:36 |
Hi all, as most, if not all, of you will be aware, there is an option to pass the certificate passphrase into OpenVPN if you compile OpenVPN with the correct option, yourself. This Molly Guard enables people who know what they are doing to automate the process a little bit more than would be possible, otherwise. My request is that the same thing should be offered for the PKCS#11 interface of 2.1. The discussion about the relative merits of the management console and compiling your own OpenVPN binaries notwithstanding, I feel that this approach is more secure, less prone to failure and eases the overall process a _lot_. Furthermore, this question has already been discussed in the mailing list archives and, back then, it was decided to go the path of Bake Your Own to safeguard people against themselves, at least for the passphrase. Is there any chance that this feature sees the light of day and if yes, is anyone able and/or willing to venture a guess as to when this might be the case? Thank you for all the work on OpenVPN! Richard |
| From: Maximilian W. <ma...@rf...> - 2007-09-02 23:14:08 |
Now wtmp_init() does try to lookup the uid for "username" and the gid for "groupname" if configured and - if successfull - chown the wtmp file to this combination. (The lookup of uid/gid is neccessary here as 'context->c0' is no yet initialized at the point wtmp_init() is called.) Signed-off-by: Maximilian Wilhelm <ma...@rf...> --- wtmp.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 43 insertions(+), 4 deletions(-) diff --git a/wtmp.c b/wtmp.c index 50dd5f9..374cf53 100644 --- a/wtmp.c +++ b/wtmp.c @@ -12,14 +12,16 @@ #define _GNU_SOURCE -#include <assert.h> +#include <assert.h> /* assert() */ #include <dirent.h> /* opendir() */ +#include <pwd.h> /* struct passwd */ #include <stdio.h> /* fopen() */ #include <stdlib.h> /* *alloc(), free() */ #include <string.h> /* strncpy(), strlen() */ #include <sys/stat.h> /* stat() */ #include <sys/time.h> /* struct timeval */ -#include <sys/types.h> /* opendir() */ +#include <sys/types.h> /* opendir() chown() */ +#include <unistd.h> /* chown() */ #include <utmp.h> /* utmp foo */ #include "openvpn.h" /* struct context* */ @@ -46,12 +48,20 @@ wtmp_init (const struct options *vpn_options) struct stat wtmp_stat; + /* These will be used when getting the uid/gid to chown the wtmp file */ + struct passwd *pw; + struct group *grp; + unsigned short do_chmod = 2; + uid_t uid = -1; + gid_t gid = -1; + + /* The wtmp file we're going to write to */ char *wtmp_file_path; char *wtmp_file_dirname; char *wtmp_file_path_copy; - assert (options); + assert (vpn_options); /* Only initialize once */ if (wtmp_active == 1) @@ -66,6 +76,24 @@ wtmp_init (const struct options *vpn_options) wtmp_file_path_copy = strdup (wtmp_file_path); wtmp_file_dirname = dirname (wtmp_file_path_copy); + /* Get UID and GID of the configured user and group */ + if (vpn_options->username) { + pw = getpwnam (vpn_options->username); + if (pw) + uid = pw->pw_uid; + else + do_chmod -= 1; + } + + if (vpn_options->groupname) { + grp = getgrnam (vpn_options->groupname); + if (grp) + gid = grp->gr_gid; + else + do_chmod -= 1; + + } + /* Check if WTMP_DIR exists and try to create it if not */ if (! opendir (wtmp_file_dirname)) { fprintf (stderr, "%s: wtmp_file_dirname %s does not exist. Trying to create it.\n", @@ -99,6 +127,17 @@ wtmp_init (const struct options *vpn_options) __FUNCTION__, wtmp_file_path); } /* [ ! -f wtmp_file ] */ + /* Maybe one changed "username" and "group" config options */ + if (do_chmod == 2) { + if (chown (wtmp_file_path, uid, gid)) { + fprintf (stderr, "%s: Could not set owner/group of wtmp file %s.\n", + __FUNCTION__, wtmp_file_path); + wtmp_active = 0; + goto out; + } + } + + /* OK wtmp_file is (now) there, use it */ utmpname (wtmp_file_path); @@ -223,7 +262,7 @@ set_utmp_line (const struct multi_instance *mi, struct utmp *entry) struct gc_arena gc = gc_new (); char *temp; - unsigned int server_id + unsigned int server_id; assert (mi); assert (entry); -- 1.5.2.4 |
| From: Maximilian W. <ma...@rf...> - 2007-09-02 23:14:07 |
This change introduces the ability to figure out as which user OpenVPN will run after dropping privileges. This is very usefull when creating the wtmp file, which by default is owned by root resulting in OpenVPN not being able to write to it. So now the owner and group can be changed to the names specified in the configuration. Signed-off-by: Maximilian Wilhelm <ma...@rf...> --- multi.c | 2 +- options.c | 3 ++- wtmp.c | 13 +++++++++---- wtmp.h | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/multi.c b/multi.c index 5d8c80e..1453399 100644 --- a/multi.c +++ b/multi.c @@ -2306,7 +2306,7 @@ tunnel_server (struct context *top) #ifdef ENABLE_WTMP if (top->options.log_wtmp == 1) - wtmp_init(top->options.wtmp_server_id, top->options.wtmp_file); + wtmp_init (&top->options); #endif switch (top->options.proto) { diff --git a/options.c b/options.c index a8c0073..ed269c6 100644 --- a/options.c +++ b/options.c @@ -3500,7 +3500,8 @@ add_option (struct options *options, /* User specified wtmp file if set */ if (p[2]) options->wtmp_file = p[2]; - } + + } #endif else if (streq (p[0], "suppress-timestamps")) diff --git a/wtmp.c b/wtmp.c index 39822df..3887220 100644 --- a/wtmp.c +++ b/wtmp.c @@ -32,28 +32,33 @@ int wtmp_active = 0; -#define HAVE_ENDUTENT 1 - -#define OVPN_WTMP_DEBUG 1 +// #define OVPN_WTMP_DEBUG 1 /* * Initialize wtmp subsystem */ int -wtmp_init (unsigned int server_id, const char *wtmp_file_path) +wtmp_init (const struct options *vpn_options) { #ifdef OVPN_WTMP_DEBUG fprintf (stderr, "%s() called.\n", __FUNCTION__); #endif struct stat wtmp_stat; + + char *wtmp_file_path; + char *wtmp_file_dirname; char *wtmp_file_path_copy; + assert (options); + /* Only initialize once */ if (wtmp_active == 1) return 1; + wtmp_file_path = vpn_options->wtmp_file; + #ifdef OVPN_WTMP_DEBUG fprintf (stderr, "wtmp_file_path = %s\n", wtmp_file_path); #endif diff --git a/wtmp.h b/wtmp.h index c43b472..7fd3927 100644 --- a/wtmp.h +++ b/wtmp.h @@ -10,7 +10,7 @@ enum local_remote { LOCAL, REMOTE }; -int wtmp_init (); +int wtmp_init (const struct options *vpn_options); void wtmp_start (const struct multi_instance *mi); void wtmp_stop (const struct multi_instance *mi); -- 1.5.2.4 |
| From: Maximilian W. <ma...@rf...> - 2007-09-02 23:14:07 |
Signed-off-by: Maximilian Wilhelm <ma...@rf...> --- wtmp.c | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wtmp.h | 27 +++++ 2 files changed, 360 insertions(+), 0 deletions(-) create mode 100644 wtmp.c create mode 100644 wtmp.h diff --git a/wtmp.c b/wtmp.c new file mode 100644 index 0000000..39822df --- /dev/null +++ b/wtmp.c @@ -0,0 +1,333 @@ +/* + * OpenVPN wtmp support + * + * Copyright: 2007 Maximilian Wilhelm <ma...@rf...> + * + */ + +#include "config.h" +#include "syshead.h" + +#ifdef ENABLE_WTMP + +#define _GNU_SOURCE + +#include <assert.h> +#include <dirent.h> /* opendir() */ +#include <stdio.h> /* fopen() */ +#include <stdlib.h> /* *alloc(), free() */ +#include <string.h> /* strncpy(), strlen() */ +#include <sys/stat.h> /* stat() */ +#include <sys/time.h> /* struct timeval */ +#include <sys/types.h> /* opendir() */ +#include <utmp.h> /* utmp foo */ + +#include "openvpn.h" /* struct context* */ +#include "forward.h" +#include "forward-inline.h" +#include "multi.h" /* struct multi_instance */ +#include "buffer.h" /* struct buffer */ + +#include "wtmp.h" + +int wtmp_active = 0; + +#define HAVE_ENDUTENT 1 + +#define OVPN_WTMP_DEBUG 1 + +/* + * Initialize wtmp subsystem + */ +int +wtmp_init (unsigned int server_id, const char *wtmp_file_path) +{ +#ifdef OVPN_WTMP_DEBUG + fprintf (stderr, "%s() called.\n", __FUNCTION__); +#endif + + struct stat wtmp_stat; + char *wtmp_file_dirname; + char *wtmp_file_path_copy; + + /* Only initialize once */ + if (wtmp_active == 1) + return 1; + +#ifdef OVPN_WTMP_DEBUG + fprintf (stderr, "wtmp_file_path = %s\n", wtmp_file_path); +#endif + + wtmp_file_path_copy = strdup (wtmp_file_path); + wtmp_file_dirname = dirname (wtmp_file_path_copy); + + /* Check if WTMP_DIR exists and try to create it if not */ + if (! opendir (wtmp_file_dirname)) { + fprintf (stderr, "%s: wtmp_file_dirname %s does not exist. Trying to create it.\n", + __FUNCTION__, wtmp_file_dirname); + + if (mkdir (wtmp_file_dirname, 0700)) { + fprintf (stderr, "%s: Could not create directory %s\n", + __FUNCTION__, wtmp_file_dirname); + wtmp_active = 0; + goto out; + } + + fprintf (stderr, "%s: Successfully created wtmp_file_dirname %s.\n", + __FUNCTION__, wtmp_file_dirname); + } + + /* Check if wtmp_file_path exists and try to create it if not */ + if (stat (wtmp_file_path, &wtmp_stat)) { + fprintf (stderr, "%s: wtmp_file %s does not exist or is not accessable. Trying to create it.\n", + __FUNCTION__, wtmp_file_path); + + /* Touch wtmp_file */ + if (! fopen (wtmp_file_path, "a")) { + fprintf (stderr, "%s: Could not create file %s.\n", + __FUNCTION__, wtmp_file_path); + wtmp_active = 0; + goto out; + } + + fprintf (stderr, "%s: Successfully created wtmp_file %s.\n", + __FUNCTION__, wtmp_file_path); + } /* [ ! -f wtmp_file ] */ + + /* OK wtmp_file is (now) there, use it */ + utmpname (wtmp_file_path); + + /* Everything is fine */ + wtmp_active = 1; + +out: + free (wtmp_file_path_copy); + + return wtmp_active; +} + + +void +wtmp_start (const struct multi_instance *mi) +{ +#ifdef OVPN_WTMP_DEBUG + fprintf (stderr, "%s() called.\n", __FUNCTION__); +#endif + + struct utmp entry; + struct sockaddr_in *remote_addr; + + char *temp; + + if (wtmp_active == 0) + return; + + /* Get IP address of this connection + * FIXME: IPv6?! + */ + remote_addr = get_remote_sockaddr_from_multi_instance (mi); + if (! remote_addr) { + fprintf (stderr, "%s: get_remote_sockaddr_from_multi_instance (mi) failed.\n", + __FUNCTION__); + } + + /* Clear entry */ + memset(&entry, '\0', sizeof (entry)); + + /* This entry is a user process */ + entry.ut_type = USER_PROCESS; + + /* The connection started now, so set epoch time */ + set_utmp_time (&entry); + + /* Set the user name */ + set_utmp_username (mi, &entry); + + /* Set the line */ + set_utmp_line (mi, &entry); + + /* Store the IP we gave this client as the hostname */ + set_utmp_hostname (mi, &entry); + + /* Use the first 4 chars of the session ID as id */ + set_utmp_id (mi, &entry); + + /* Store the remote client IP(v4), if available */ + entry.ut_addr = remote_addr->sin_addr.s_addr; + +#ifdef OVPN_WTMP_DEBUG +fprintf (stderr, "%s: entry.ut_line = \"%s\"\n", __FUNCTION__, entry.ut_line); +fprintf (stderr, "%s: entry.ut_id = \"%s\"\n", __FUNCTION__, entry.ut_id); +fprintf (stderr, "%s: entry.ut_user = \"%s\"\n", __FUNCTION__, entry.ut_user); +fprintf (stderr, "%s: entry.ut_host = \"%s\"\n", __FUNCTION__, entry.ut_host); + +unsigned int ip = ntohl (entry.ut_addr); +fprintf (stderr, "%s: entry.ut_addr = %d.%d.%d.%d\n", __FUNCTION__, ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, (ip >> 0) & 0xff); +#endif + + updwtmp (mi->context.options.wtmp_file, &entry); +} + + +void +wtmp_stop (const struct multi_instance *mi) +{ +#ifdef OVPN_WTMP_DEBUG + fprintf (stderr, "%s() called.\n", __FUNCTION__); +#endif + + struct utmp entry; + + if (wtmp_active == 0) + return; + + /* Clear entry */ + memset (&entry, '\0', sizeof (entry)); + + /* The connection stopped now, so set epoch time */ + set_utmp_time (&entry); + + /* He's dead jim */ + entry.ut_type = DEAD_PROCESS; + + /* Set current epoch time */ + set_utmp_time (&entry); + + /* Set the line */ + set_utmp_line (mi, &entry); + + /* Use the first 4 chars of the session ID as id */ + set_utmp_id (mi, &entry); + + entry.ut_host[0] = 0; + +#ifdef OVPN_WTMP_DEBUG +fprintf (stderr, "%s: entry.ut_line = %s\n", __FUNCTION__, entry.ut_line); +fprintf (stderr, "%s: entry.ut_id = %s\n", __FUNCTION__, entry.ut_id); +#endif + + updwtmp (mi->context.options.wtmp_file, &entry); +} + + + + + +/* Build up and store an utmp line */ +void +set_utmp_line (const struct multi_instance *mi, struct utmp *entry) +{ + struct gc_arena gc = gc_new (); + char *temp; + + char line[UT_LINESIZE]; + + /* Should be config option */ + unsigned int server_num = 1; + + assert (mi); + assert (entry); + + temp = format_hex_ex (mi->context.c2.tls_multi->session[TM_ACTIVE].session_id.id, SID_SIZE, 0, 4, "", &gc); + + if (temp) { + snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d-%s", server_num, temp); + } else { + snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d", server_num); + } +} + + +/* Store the first 4 chars of the session_id as the utmp id */ +void +set_utmp_id (const struct multi_instance *mi, struct utmp *entry) +{ + struct gc_arena gc = gc_new (); + char *temp; + + assert (mi); + assert (entry); + + temp = format_hex_ex (mi->context.c2.tls_multi->session[TM_ACTIVE].session_id.id, SID_SIZE, 0, 4, " ", &gc); + if (temp) { + snprintf (entry->ut_id, 4, "%s", temp); + } +} + + +/* Store a human readable format of the VPN ip address we gave to the client as utmp hostname */ +void +set_utmp_hostname (const struct multi_instance *mi, struct utmp *entry) +{ + unsigned int ip; + + assert (mi); + assert (entry); + + memset (entry->ut_host, '\0', UT_HOSTSIZE); + + ip = mi->context.c2.push_ifconfig_local; + snprintf (entry->ut_host, UT_HOSTSIZE, "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, (ip >> 0) & 0xff); +} + + +/* Store the username of the current session in the utmp entry */ +void +set_utmp_username (const struct multi_instance *mi, struct utmp *entry) +{ + const char *username; + + assert (mi); + assert (entry); + + username = tls_common_name (mi->context.c2.tls_multi, false); + if (username) { + snprintf (entry->ut_user, UT_NAMESIZE, "%s", username); + } else { + snprintf (entry->ut_user, UT_NAMESIZE, "unknown"); + } +} + + +/* Get a sockaddr_in struct containing the real IP of the remote host */ +static struct sockaddr_in * +get_remote_sockaddr_from_multi_instance (const struct multi_instance *mi) +{ + struct buffer buf ; + struct link_socket_actual *lsa; + + assert (mi); + + lsa = calloc (1, sizeof (struct link_socket_actual)); + if (! lsa) + return NULL; + + link_socket_get_outgoing_addr (&buf, get_link_socket_info (&mi->context), &lsa); + + return &lsa->dest.sa; +} + + +/* + * Some helper functions, partly stolen from OpenSSH/loginrec.c + * + */ + + +/* Store the current time in utmp struct */ +static void +set_utmp_time (struct utmp *ut) +{ + struct timeval tv; + + assert (ut); + + gettimeofday(&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; + + ut->ut_time = tv.tv_sec; +} +#endif /* ENABLE_WTMP */ + + diff --git a/wtmp.h b/wtmp.h new file mode 100644 index 0000000..c43b472 --- /dev/null +++ b/wtmp.h @@ -0,0 +1,27 @@ +#ifndef _OPENVPN_WTMP_H +#define _OPENVPN_WTMP_H + +#include <utmp.h> + +#include "multi.h" + +#define OVPN_WTMP_DIR "/tmp" +#define OVPN_WTMP_FILENAME "ovpnwtmp" + +enum local_remote { LOCAL, REMOTE }; + +int wtmp_init (); + +void wtmp_start (const struct multi_instance *mi); +void wtmp_stop (const struct multi_instance *mi); + +static void set_utmp_time (struct utmp *ut); + +void set_utmp_hostname (const struct multi_instance *mi, struct utmp *entry); +void set_utmp_id (const struct multi_instance *mi, struct utmp *entry); +void set_utmp_line (const struct multi_instance *mi, struct utmp *entry); +void set_utmp_username (const struct multi_instance *mi, struct utmp *entry); + +static struct sockaddr_in * get_remote_sockaddr_from_multi_instance (const struct multi_instance *mi); + +#endif /* _OPENVPN_WTMP_H */ -- 1.5.2.4 |
| From: Maximilian W. <ma...@rf...> - 2007-09-02 23:14:07 |
Now every utmp line will look like "ovpn%d-%s" where %d are the two last digits of the server_id and %s some chars of the session_id (as many as fit into the remaining space in 'ut_line'. This provides the ability to let at most 100 OpenVPN instances on one single maschine write to the same wtmp file and you are still able to distinguish which instance created which entry. Signed-off-by: Maximilian Wilhelm <ma...@rf...> --- wtmp.c | 14 +++++--------- 1 files changed, 5 insertions(+), 9 deletions(-) diff --git a/wtmp.c b/wtmp.c index 3887220..50dd5f9 100644 --- a/wtmp.c +++ b/wtmp.c @@ -216,29 +216,25 @@ fprintf (stderr, "%s: entry.ut_id = %s\n", __FUNCTION__, entry.ut_id); - - /* Build up and store an utmp line */ void set_utmp_line (const struct multi_instance *mi, struct utmp *entry) { struct gc_arena gc = gc_new (); - char *temp; - char line[UT_LINESIZE]; - - /* Should be config option */ - unsigned int server_num = 1; + char *temp; + unsigned int server_id assert (mi); assert (entry); + server_id = mi->context.options.wtmp_server_id % 100; temp = format_hex_ex (mi->context.c2.tls_multi->session[TM_ACTIVE].session_id.id, SID_SIZE, 0, 4, "", &gc); if (temp) { - snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d-%s", server_num, temp); + snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d-%s", server_id, temp); } else { - snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d", server_num); + snprintf (entry->ut_line, UT_LINESIZE, "ovpn%02d", server_id); } } -- 1.5.2.4 |