Added restrictions on the use of proxy certificates, as they may pose
a security threat on unexpecting applications. Document and test.
This commit is contained in:
parent
dc0ed30cfe
commit
d9bfe4f97c
6
CHANGES
6
CHANGES
@ -783,6 +783,12 @@
|
||||
*) Undo Cygwin change.
|
||||
[Ulf Möller]
|
||||
|
||||
*) Added support for proxy certificates according to RFC 3820.
|
||||
Because they may be a security thread to unaware applications,
|
||||
they must be explicitely allowed in run-time. See
|
||||
docs/HOWTO/proxy_certificates.txt for further information.
|
||||
[Richard Levitte]
|
||||
|
||||
Changes between 0.9.7e and 0.9.7f [22 Mar 2005]
|
||||
|
||||
*) Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating
|
||||
|
@ -128,6 +128,8 @@ const char *X509_verify_cert_error_string(long n)
|
||||
return ("path length constraint exceeded");
|
||||
case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
|
||||
return("proxy path length constraint exceeded");
|
||||
case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
|
||||
return("proxy cerificates not allowed, please set the appropriate flag");
|
||||
case X509_V_ERR_INVALID_PURPOSE:
|
||||
return ("unsupported certificate purpose");
|
||||
case X509_V_ERR_CERT_UNTRUSTED:
|
||||
|
@ -391,6 +391,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
int (*cb)(int ok,X509_STORE_CTX *ctx);
|
||||
int proxy_path_length = 0;
|
||||
cb=ctx->verify_cb;
|
||||
int allow_proxy_certs = !!(ctx->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
|
||||
|
||||
/* must_be_ca can have 1 of 3 values:
|
||||
-1: we accept both CA and non-CA certificates, to allow direct
|
||||
@ -401,6 +402,12 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
all certificates in the chain except the leaf certificate.
|
||||
*/
|
||||
must_be_ca = -1;
|
||||
|
||||
/* A hack to keep people who don't want to modify their software
|
||||
happy */
|
||||
if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
|
||||
allow_proxy_certs = 1;
|
||||
|
||||
/* Check all untrusted certificates */
|
||||
for (i = 0; i < ctx->last_untrusted; i++)
|
||||
{
|
||||
@ -415,6 +422,14 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
ok=cb(0,ctx);
|
||||
if (!ok) goto end;
|
||||
}
|
||||
if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
|
||||
{
|
||||
ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok=cb(0,ctx);
|
||||
if (!ok) goto end;
|
||||
}
|
||||
ret = X509_check_ca(x);
|
||||
switch(must_be_ca)
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
|
||||
#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
|
||||
#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
|
||||
#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
|
||||
#define X509_V_ERR_CERT_NOT_YET_VALID 9
|
||||
#define X509_V_ERR_CERT_NOT_YET_VALID 9
|
||||
#define X509_V_ERR_CERT_HAS_EXPIRED 10
|
||||
#define X509_V_ERR_CRL_NOT_YET_VALID 11
|
||||
#define X509_V_ERR_CRL_HAS_EXPIRED 12
|
||||
@ -325,10 +325,11 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
|
||||
#define X509_V_ERR_INVALID_NON_CA 37
|
||||
#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
|
||||
#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
|
||||
#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
|
||||
|
||||
#define X509_V_ERR_INVALID_EXTENSION 40
|
||||
#define X509_V_ERR_INVALID_POLICY_EXTENSION 41
|
||||
#define X509_V_ERR_NO_EXPLICIT_POLICY 42
|
||||
#define X509_V_ERR_INVALID_EXTENSION 41
|
||||
#define X509_V_ERR_INVALID_POLICY_EXTENSION 42
|
||||
#define X509_V_ERR_NO_EXPLICIT_POLICY 43
|
||||
|
||||
|
||||
/* The application is not happy */
|
||||
@ -348,14 +349,16 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
|
||||
#define X509_V_FLAG_IGNORE_CRITICAL 0x10
|
||||
/* Disable workarounds for broken certificates */
|
||||
#define X509_V_FLAG_X509_STRICT 0x20
|
||||
/* Enable proxy certificate validation */
|
||||
#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
|
||||
/* Enable policy checking */
|
||||
#define X509_V_FLAG_POLICY_CHECK 0x40
|
||||
#define X509_V_FLAG_POLICY_CHECK 0x80
|
||||
/* Policy variable require-explicit-policy */
|
||||
#define X509_V_FLAG_EXPLICIT_POLICY 0x80
|
||||
#define X509_V_FLAG_EXPLICIT_POLICY 0x100
|
||||
/* Policy variable inhibit-any-policy */
|
||||
#define X509_V_FLAG_INHIBIT_ANY 0x100
|
||||
#define X509_V_FLAG_INHIBIT_ANY 0x200
|
||||
/* Policy variable inhibit-policy-mapping */
|
||||
#define X509_V_FLAG_INHIBIT_MAP 0x200
|
||||
#define X509_V_FLAG_INHIBIT_MAP 0x400
|
||||
/* Notify callback that policy is OK */
|
||||
#define X509_V_FLAG_NOTIFY_POLICY 0x800
|
||||
|
||||
|
@ -338,7 +338,9 @@ static void x509v3_cache_extensions(X509 *x)
|
||||
}
|
||||
/* Handle proxy certificates */
|
||||
if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
|
||||
if (x->ex_flags & EXFLAG_CA) {
|
||||
if (x->ex_flags & EXFLAG_CA
|
||||
|| X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0
|
||||
|| X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) {
|
||||
x->ex_flags |= EXFLAG_INVALID;
|
||||
}
|
||||
if (pci->pcPathLengthConstraint) {
|
||||
|
@ -22,7 +22,48 @@ name of the owner of the EE certificate.
|
||||
See http://www.ietf.org/rfc/rfc3820.txt for more information.
|
||||
|
||||
|
||||
2. How to create proxy cerificates
|
||||
2. A warning about proxy certificates
|
||||
|
||||
Noone seems to have tested proxy certificates with security in mind.
|
||||
Basically, to this date, it seems that proxy certificates have only
|
||||
been used in a world that's highly aware of them. What would happen
|
||||
if an unsuspecting application is to validate a chain of certificates
|
||||
that contains proxy certificates? It would usually consider the leaf
|
||||
to be the certificate to check for authorisation data, and since proxy
|
||||
certificates are controlled by the EE certificate owner alone, it's
|
||||
would be normal to consider what the EE certificate owner could do
|
||||
with them.
|
||||
|
||||
subjectAltName and issuerAltName are forbidden in proxy certificates,
|
||||
and this is enforced in OpenSSL. The subject must be the same as the
|
||||
issuer, with one commonName added on.
|
||||
|
||||
Possible threats are, as far as has been imagined so far:
|
||||
|
||||
- impersonation through commonName (think server certificates).
|
||||
- use of additional extensions, possibly non-standard ones used in
|
||||
certain environments, that would grant extra or different
|
||||
authorisation rights.
|
||||
|
||||
For this reason, OpenSSL requires that the use of proxy certificates
|
||||
be explicitely allowed. Currently, this can be done using the
|
||||
following methods:
|
||||
|
||||
- if the application calls X509_verify_cert() itself, it can do the
|
||||
following prior to that call (ctx is the pointer passed in the call
|
||||
to X509_verify_cert()):
|
||||
|
||||
X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
|
||||
|
||||
- in all other cases, proxy certificate validation can be enabled
|
||||
before starting the application by setting the envirnoment variable
|
||||
OPENSSL_ALLOW_PROXY with some non-empty value.
|
||||
|
||||
There are thoughts to allow proxy certificates with a line in the
|
||||
default openssl.cnf, but that's still in the future.
|
||||
|
||||
|
||||
3. How to create proxy cerificates
|
||||
|
||||
It's quite easy to create proxy certificates, by taking advantage of
|
||||
the lack of checks of the 'openssl x509' application (*ahem*). But
|
||||
@ -111,7 +152,7 @@ section for it):
|
||||
-extfile openssl.cnf -extensions v3_proxy2
|
||||
|
||||
|
||||
3. How to have your application interpret the policy?
|
||||
4. How to have your application interpret the policy?
|
||||
|
||||
The basic way to interpret proxy policies is to prepare some default
|
||||
rights, then do a check of the proxy certificate against the a chain
|
||||
@ -258,6 +299,7 @@ This is some cookbook code for you to fill in:
|
||||
|
||||
X509_STORE_CTX_set_verify_cb(ctx, verify_callback);
|
||||
X509_STORE_CTX_set_ex_data(ctx, get_proxy_auth_ex_data_idx(), &rights);
|
||||
X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
|
||||
ok = X509_verify_cert(ctx);
|
||||
|
||||
if (ok == 1)
|
||||
|
@ -88,6 +88,10 @@ PKCS#12: Personal Information Exchange Syntax Standard, version 1.0.
|
||||
(Format: TXT=143173 bytes) (Obsoletes RFC2437) (Status:
|
||||
INFORMATIONAL)
|
||||
|
||||
3820 Internet X.509 Public Key Infrastructure (PKI) Proxy Certificate
|
||||
Profile. S. Tuecke, V. Welch, D. Engert, L. Pearlman, M. Thompson.
|
||||
June 2004. (Format: TXT=86374 bytes) (Status: PROPOSED STANDARD)
|
||||
|
||||
|
||||
Related:
|
||||
--------
|
||||
|
@ -190,6 +190,7 @@ struct app_verify_arg
|
||||
{
|
||||
char *string;
|
||||
int app_verify;
|
||||
int allow_proxy_certs;
|
||||
char *proxy_auth;
|
||||
char *proxy_cond;
|
||||
};
|
||||
@ -223,6 +224,7 @@ static void sv_usage(void)
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -server_auth - check server certificate\n");
|
||||
fprintf(stderr," -client_auth - do client authentication\n");
|
||||
fprintf(stderr," -proxy - allow proxy certificates\n");
|
||||
fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n");
|
||||
fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n");
|
||||
fprintf(stderr," -v - more output\n");
|
||||
@ -383,7 +385,7 @@ int main(int argc, char *argv[])
|
||||
int client_auth=0;
|
||||
int server_auth=0,i;
|
||||
struct app_verify_arg app_verify_arg =
|
||||
{ APP_CALLBACK_STRING, 0, NULL, NULL };
|
||||
{ APP_CALLBACK_STRING, 0, 0, NULL, NULL };
|
||||
char *server_cert=TEST_SERVER_CERT;
|
||||
char *server_key=NULL;
|
||||
char *client_cert=TEST_CLIENT_CERT;
|
||||
@ -580,6 +582,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
app_verify_arg.app_verify = 1;
|
||||
}
|
||||
else if (strcmp(*argv,"-proxy") == 0)
|
||||
{
|
||||
app_verify_arg.allow_proxy_certs = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"unknown option %s\n",*argv);
|
||||
@ -1606,17 +1612,22 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
|
||||
fprintf(stderr,"depth=%d %s\n",
|
||||
ctx->error_depth,buf);
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"depth=%d error=%d %s\n",
|
||||
ctx->error_depth,ctx->error,buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
fprintf(stderr,"Error string: %s\n",
|
||||
X509_verify_cert_error_string(ctx->error));
|
||||
switch (ctx->error)
|
||||
{
|
||||
case X509_V_ERR_CERT_NOT_YET_VALID:
|
||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
fprintf(stderr," ... ignored.\n");
|
||||
ok=1;
|
||||
}
|
||||
}
|
||||
@ -2018,6 +2029,10 @@ static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
|
||||
X509_STORE_CTX_set_ex_data(ctx,
|
||||
get_proxy_auth_ex_data_idx(),letters);
|
||||
}
|
||||
if (cb_arg->allow_proxy_certs)
|
||||
{
|
||||
X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_X509_VERIFY
|
||||
# ifdef OPENSSL_FIPS
|
||||
|
@ -4,7 +4,7 @@ echo 'Testing a lot of proxy conditions.'
|
||||
echo 'Some of them may turn out being invalid, which is fine.'
|
||||
for auth in A B C BC; do
|
||||
for cond in A B C 'A|B&!C'; do
|
||||
sh ./testssl $1 $2 $3 "-proxy_auth $auth -proxy_cond $cond"
|
||||
sh ./testssl $1 $2 $3 "-proxy -proxy_auth $auth -proxy_cond $cond"
|
||||
if [ $? = 3 ]; then exit 1; fi
|
||||
done
|
||||
done
|
||||
|
Loading…
x
Reference in New Issue
Block a user