mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 12:02:28 +02:00
Added new "extra-certs" and "verify-hash" options (see man page for
details). Increase the timeout after SIGUSR1 restart when restart is not due to server_poll_timeout. Version 2.1.3v git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7215 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
d5497262ae
commit
7966d75a9d
3
init.c
3
init.c
@ -1706,8 +1706,10 @@ socket_restart_pause (struct context *c)
|
||||
if (auth_retry_get () == AR_NOINTERACT)
|
||||
sec = 10;
|
||||
|
||||
#if 0 /* not really needed because of c->persist.restart_sleep_seconds */
|
||||
if (c->options.server_poll_timeout && sec > 1)
|
||||
sec = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (c->persist.restart_sleep_seconds > 0 && c->persist.restart_sleep_seconds > sec)
|
||||
@ -2057,6 +2059,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
||||
to.ns_cert_type = options->ns_cert_type;
|
||||
memmove (to.remote_cert_ku, options->remote_cert_ku, sizeof (to.remote_cert_ku));
|
||||
to.remote_cert_eku = options->remote_cert_eku;
|
||||
to.verify_hash = options->verify_hash;
|
||||
to.es = c->c2.es;
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
27
openvpn.8
27
openvpn.8
@ -3887,6 +3887,22 @@ that for certificate authority functions, you must set up the files
|
||||
).
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --extra-certs file
|
||||
Specify a
|
||||
.B file
|
||||
containing one or more PEM certs (concatenated together)
|
||||
that complete the
|
||||
local certificate chain.
|
||||
|
||||
This option is useful for "split" CAs, where the CA for server
|
||||
certs is different than the CA for client certs. Putting certs
|
||||
in this file allows them to be used to complete the local
|
||||
certificate chain without trusting them to verify the peer-submitted
|
||||
certificate, as would be the case if the certs were placed in the
|
||||
.B ca
|
||||
file.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --key file
|
||||
Local peer's private key in .pem format. Use the private key which was generated
|
||||
when you built your peer's certificate (see
|
||||
@ -3903,6 +3919,17 @@ and
|
||||
.B --key.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --verify-hash hash
|
||||
Specify SHA1 fingerprint for level-1 cert. The level-1 cert is the
|
||||
CA (or intermediate cert) that signs the leaf certificate, and is
|
||||
one removed from the leaf certificate in the direction of the root.
|
||||
When accepting a connection from a peer, the level-1 cert
|
||||
fingerprint must match
|
||||
.B hash
|
||||
or certificate verification will fail. Hash is specified
|
||||
as XX:XX:... For example: AD:B0:95:D8:09:C8:36:45:12:A9:89:C8:90:09:CB:13:72:A6:AD:16
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --pkcs11-cert-private [0|1]...
|
||||
Set if access to certificate object should be performed after login.
|
||||
Every provider has its own setting.
|
||||
|
52
options.c
52
options.c
@ -507,9 +507,11 @@ static const char usage_message[] =
|
||||
" Use \"openssl dhparam -out dh1024.pem 1024\" to generate.\n"
|
||||
"--cert file : Local certificate in .pem format -- must be signed\n"
|
||||
" by a Certificate Authority in --ca file.\n"
|
||||
"--extra-certs file : one or more PEM certs that complete the cert chain.\n"
|
||||
"--key file : Local private key in .pem format.\n"
|
||||
"--pkcs12 file : PKCS#12 file containing local private key, local certificate\n"
|
||||
" and optionally the root CA certificate.\n"
|
||||
"--verify-hash : Specify SHA1 fingerprint for level-1 cert.\n"
|
||||
#ifdef WIN32
|
||||
"--cryptoapicert select-string : Load the certificate and private key from the\n"
|
||||
" Windows Certificate System Store.\n"
|
||||
@ -894,6 +896,40 @@ is_stateful_restart (const struct options *o)
|
||||
return is_persist_option (o) || connection_list_defined (o);
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
static uint8_t *
|
||||
parse_hash_fingerprint(const char *str, int nbytes, int msglevel, struct gc_arena *gc)
|
||||
{
|
||||
int i;
|
||||
const char *cp = str;
|
||||
uint8_t *ret = (uint8_t *) gc_malloc (nbytes, true, gc);
|
||||
char term = 1;
|
||||
int byte;
|
||||
char bs[3];
|
||||
|
||||
for (i = 0; i < nbytes; ++i)
|
||||
{
|
||||
if (strlen(cp) < 2)
|
||||
msg (msglevel, "format error in hash fingerprint: %s", str);
|
||||
bs[0] = *cp++;
|
||||
bs[1] = *cp++;
|
||||
bs[2] = 0;
|
||||
byte = 0;
|
||||
if (sscanf(bs, "%x", &byte) != 1)
|
||||
msg (msglevel, "format error in hash fingerprint hex byte: %s", str);
|
||||
ret[i] = (uint8_t)byte;
|
||||
term = *cp++;
|
||||
if (term != ':' && term != 0)
|
||||
msg (msglevel, "format error in hash fingerprint delimiter: %s", str);
|
||||
if (term == 0)
|
||||
break;
|
||||
}
|
||||
if (term != 0 || i != nbytes-1)
|
||||
msg (msglevel, "hash fingerprint is different length than expected (%d bytes): %s", nbytes, str);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
@ -5758,6 +5794,22 @@ add_option (struct options *options,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (streq (p[0], "extra-certs") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->extra_certs_file = p[1];
|
||||
#if ENABLE_INLINE_FILES
|
||||
if (streq (p[1], INLINE_FILE_TAG) && p[2])
|
||||
{
|
||||
options->extra_certs_file_inline = p[2];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (streq (p[0], "verify-hash") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->verify_hash = parse_hash_fingerprint(p[1], SHA_DIGEST_LENGTH, msglevel, &options->gc);
|
||||
}
|
||||
#ifdef WIN32
|
||||
else if (streq (p[0], "cryptoapicert") && p[1])
|
||||
{
|
||||
|
@ -477,6 +477,7 @@ struct options
|
||||
const char *ca_path;
|
||||
const char *dh_file;
|
||||
const char *cert_file;
|
||||
const char *extra_certs_file;
|
||||
const char *priv_key_file;
|
||||
const char *pkcs12_file;
|
||||
const char *cipher_list;
|
||||
@ -487,6 +488,7 @@ struct options
|
||||
#if ENABLE_INLINE_FILES
|
||||
const char *ca_file_inline;
|
||||
const char *cert_file_inline;
|
||||
const char *extra_certs_file_inline;
|
||||
char *priv_key_file_inline;
|
||||
const char *dh_file_inline;
|
||||
const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
|
||||
@ -495,6 +497,7 @@ struct options
|
||||
int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
|
||||
unsigned remote_cert_ku[MAX_PARMS];
|
||||
const char *remote_cert_eku;
|
||||
uint8_t *verify_hash;
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
const char *pkcs11_providers[MAX_PARMS];
|
||||
|
41
ssl.c
41
ssl.c
@ -910,6 +910,16 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
||||
goto err; /* Reject connection */
|
||||
}
|
||||
|
||||
/* verify level 1 cert, i.e. the CA that signed our leaf cert */
|
||||
if (ctx->error_depth == 1 && opt->verify_hash)
|
||||
{
|
||||
if (memcmp (ctx->current_cert->sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
|
||||
{
|
||||
msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* save common name in session object */
|
||||
if (ctx->error_depth == 0)
|
||||
set_common_name (session, common_name);
|
||||
@ -2140,6 +2150,37 @@ init_ssl (const struct options *options)
|
||||
msg (M_SSLERR, "Cannot load certificate chain file %s (SSL_use_certificate_chain_file)", options->cert_file);
|
||||
}
|
||||
|
||||
/* Load extra certificates that are part of our own certificate
|
||||
chain but shouldn't be included in the verify chain */
|
||||
if (options->extra_certs_file || options->extra_certs_file_inline)
|
||||
{
|
||||
BIO *bio;
|
||||
X509 *cert;
|
||||
#if ENABLE_INLINE_FILES
|
||||
if (!strcmp (options->extra_certs_file, INLINE_FILE_TAG) && options->extra_certs_file_inline)
|
||||
{
|
||||
bio = BIO_new_mem_buf ((char *)options->extra_certs_file_inline, -1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(bio, options->extra_certs_file) <= 0)
|
||||
msg (M_SSLERR, "Cannot load extra-certs file: %s", options->extra_certs_file);
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
cert = NULL;
|
||||
if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
|
||||
break;
|
||||
if (!cert)
|
||||
msg (M_SSLERR, "Error reading extra-certs certificate");
|
||||
if (SSL_CTX_add_extra_chain_cert(ctx, cert) != 1)
|
||||
msg (M_SSLERR, "Error adding extra-certs certificate");
|
||||
}
|
||||
BIO_free (bio);
|
||||
}
|
||||
|
||||
/* Require peer certificate verification */
|
||||
#if P2MP_SERVER
|
||||
if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
|
||||
|
1
ssl.h
1
ssl.h
@ -466,6 +466,7 @@ struct tls_options
|
||||
int ns_cert_type;
|
||||
unsigned remote_cert_ku[MAX_PARMS];
|
||||
const char *remote_cert_eku;
|
||||
uint8_t *verify_hash;
|
||||
|
||||
/* allow openvpn config info to be
|
||||
passed over control channel */
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1.3u])
|
||||
define(PRODUCT_VERSION,[2.1.3v])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
Loading…
Reference in New Issue
Block a user