0
0
mirror of https://github.com/OpenVPN/openvpn.git synced 2024-09-20 12:02:28 +02:00

Added 'dir' flag to "crl-verify" (see man page for info).

Don't call SSL_CTX_set_client_CA_list or SSL_CTX_set_client_CA_list
if not running in server mode (these functions are only useful for
TLS/SSL servers).

Modified openvpn_snprintf to return false on overflow, and true
otherwise.

When AUTH_FAILED,... is received, log the full string.


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7213 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
James Yonan 2011-04-24 00:59:28 +00:00 committed by David Sommerseth
parent cf906790a8
commit d5497262ae
7 changed files with 100 additions and 65 deletions

View File

@ -218,20 +218,21 @@ buf_printf (struct buffer *buf, const char *format, ...)
/*
* This is necessary due to certain buggy implementations of snprintf,
* that don't guarantee null termination for size > 0.
* Return false on overflow.
*/
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
bool openvpn_snprintf(char *str, size_t size, const char *format, ...)
{
va_list arglist;
int ret = 0;
int len = -1;
if (size > 0)
{
va_start (arglist, format);
ret = vsnprintf (str, size, format, arglist);
len = vsnprintf (str, size, format, arglist);
va_end (arglist);
str[size - 1] = 0;
}
return ret;
return (len >= 0 && len < size);
}
/*

View File

@ -280,7 +280,7 @@ bool buf_printf (struct buffer *buf, const char *format, ...)
/*
* Like snprintf but guarantees null termination for size > 0
*/
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
bool openvpn_snprintf(char *str, size_t size, const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 3, 4)))
#endif

View File

@ -4457,7 +4457,7 @@ or
.B --tls-verify.
.\"*********************************************************
.TP
.B --crl-verify crl
.B --crl-verify crl ['dir']
Check peer certificate against the file
.B crl
in PEM format.
@ -4473,6 +4473,16 @@ overall integrity of the PKI.
The only time when it would be necessary to rebuild the entire PKI from scratch would be
if the root certificate key itself was compromised.
If the optional
.B dir
flag is specified, enable a different mode where
.B crl
is a directory containing files named as revoked serial numbers
(the files may be empty, the contents are never read). If a client
requests a connection, where the client certificate serial number
(decimal string) is the name of a file present in the directory,
it will be rejected.
.\"*********************************************************
.SS SSL Library information:
.\"*********************************************************

View File

@ -534,7 +534,7 @@ static const char usage_message[] =
" see --secret option for more info.\n"
"--askpass [file]: Get PEM password from controlling tty before we daemonize.\n"
"--auth-nocache : Don't cache --askpass or --auth-user-pass passwords.\n"
"--crl-verify crl: Check peer certificate against a CRL.\n"
"--crl-verify crl ['dir']: Check peer certificate against a CRL.\n"
"--tls-verify cmd: Execute shell command cmd to verify the X509 name of a\n"
" pending TLS connection that has otherwise passed all other\n"
" tests of certification. cmd should return 0 to allow\n"
@ -5836,6 +5836,8 @@ add_option (struct options *options,
else if (streq (p[0], "crl-verify") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL);
if (p[2] && streq(p[2], "dir"))
options->ssl_flags |= SSLF_CRL_VERIFY_DIR;
options->crl_file = p[1];
}
else if (streq (p[0], "tls-verify") && p[1])

2
push.c
View File

@ -42,7 +42,7 @@
void
receive_auth_failed (struct context *c, const struct buffer *buffer)
{
msg (M_VERB0, "AUTH: Received AUTH_FAILED control message");
msg (M_VERB0, "AUTH: Received control message: %s", BSTR(buffer));
connection_list_set_no_advance(&c->options);
if (c->options.pull)
{

135
ssl.c
View File

@ -836,6 +836,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
const struct tls_options *opt;
const int max_depth = MAX_CERT_DEPTH;
struct argv argv = argv_new ();
char *serial = NULL;
/* get the tls_session pointer */
ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
@ -929,14 +930,12 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
{
ASN1_INTEGER *asn1_i;
BIGNUM *bignum;
char *dec;
asn1_i = X509_get_serialNumber(ctx->current_cert);
bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
dec = BN_bn2dec(bignum);
serial = BN_bn2dec(bignum);
openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", ctx->error_depth);
setenv_str (opt->es, envname, dec);
setenv_str (opt->es, envname, serial);
BN_free(bignum);
OPENSSL_free(dec);
}
/* export current untrusted IP */
@ -1060,67 +1059,89 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
/* check peer cert against CRL */
if (opt->crl_file)
{
X509_CRL *crl=NULL;
X509_REVOKED *revoked;
BIO *in=NULL;
int n,i,retval = 0;
in=BIO_new(BIO_s_file());
if (in == NULL) {
msg (M_ERR, "CRL: BIO err");
goto end;
}
if (BIO_read_filename(in, opt->crl_file) <= 0) {
msg (M_ERR, "CRL: cannot read: %s", opt->crl_file);
goto end;
}
crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
if (crl == NULL) {
msg (M_ERR, "CRL: cannot read CRL from file %s", opt->crl_file);
goto end;
}
if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(ctx->current_cert)) != 0) {
msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of certificate %s", opt->crl_file, subject);
retval = 1;
goto end;
}
n = sk_num(X509_CRL_get_REVOKED(crl));
for (i = 0; i < n; i++) {
revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(ctx->current_cert)) == 0) {
msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
goto end;
if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
{
char fn[256];
int fd;
if (!openvpn_snprintf(fn, sizeof(fn), "%s%c%s", opt->crl_file, OS_SPECIFIC_DIRSEP, serial))
{
msg (D_HANDSHAKE, "VERIFY CRL: filename overflow");
goto err;
}
fd = open (fn, O_RDONLY);
if (fd >= 0)
{
msg (D_HANDSHAKE, "VERIFY CRL: certificate serial number %s is revoked", serial);
close(fd);
goto err;
}
}
}
else
{
X509_CRL *crl=NULL;
X509_REVOKED *revoked;
BIO *in=NULL;
int n,i,retval = 0;
retval = 1;
msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);
in=BIO_new(BIO_s_file());
end:
if (in == NULL) {
msg (M_ERR, "CRL: BIO err");
goto end;
}
if (BIO_read_filename(in, opt->crl_file) <= 0) {
msg (M_ERR, "CRL: cannot read: %s", opt->crl_file);
goto end;
}
crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
if (crl == NULL) {
msg (M_ERR, "CRL: cannot read CRL from file %s", opt->crl_file);
goto end;
}
BIO_free(in);
if (crl)
X509_CRL_free (crl);
if (!retval)
goto err;
if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(ctx->current_cert)) != 0) {
msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of certificate %s", opt->crl_file, subject);
retval = 1;
goto end;
}
n = sk_num(X509_CRL_get_REVOKED(crl));
for (i = 0; i < n; i++) {
revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(ctx->current_cert)) == 0) {
msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
goto end;
}
}
retval = 1;
msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);
end:
BIO_free(in);
if (crl)
X509_CRL_free (crl);
if (!retval)
goto err;
}
}
msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", ctx->error_depth, subject);
session->verified = true;
done:
OPENSSL_free (subject);
if (serial)
OPENSSL_free(serial);
argv_reset (&argv);
return 1; /* Accept connection */
return (session->verified == true) ? 1 : 0;
err:
ERR_clear_error ();
OPENSSL_free (subject);
argv_reset (&argv);
return 0; /* Reject connection */
session->verified = false;
goto done;
}
void
@ -1954,7 +1975,7 @@ init_ssl (const struct options *options)
{
if (!X509_STORE_add_cert(ctx->cert_store,sk_X509_value(ca, i)))
msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");
if (!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i)))
if (options->tls_server && !SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i)))
msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");
}
}
@ -2066,11 +2087,11 @@ init_ssl (const struct options *options)
#endif
{
/* Load CA file for verifying peer supplied certificate */
status = SSL_CTX_load_verify_locations (ctx, options->ca_file, options->ca_path);
status = SSL_CTX_load_verify_locations (ctx, options->ca_file, NULL);
}
if (!status)
msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", options->ca_file, options->ca_path);
msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", np(options->ca_file), np(options->ca_path));
/* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
if (options->ca_path) {
@ -2094,7 +2115,7 @@ init_ssl (const struct options *options)
}
/* Load names of CAs from file and use it as a client CA list */
if (options->ca_file) {
if (options->ca_file && options->tls_server) {
STACK_OF(X509_NAME) *cert_names = NULL;
#if ENABLE_INLINE_FILES
if (!strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline)
@ -2108,7 +2129,7 @@ init_ssl (const struct options *options)
}
if (!cert_names)
msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", options->ca_file);
SSL_CTX_set_client_CA_list (ctx, cert_names);
SSL_CTX_set_client_CA_list (ctx, cert_names);
}
}

1
ssl.h
View File

@ -504,6 +504,7 @@ struct tls_options
# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2)
# define SSLF_NO_NAME_REMAPPING (1<<3)
# define SSLF_OPT_VERIFY (1<<4)
# define SSLF_CRL_VERIFY_DIR (1<<5)
unsigned int ssl_flags;
#ifdef MANAGEMENT_DEF_AUTH