summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2005-04-09 16:06:45 +0000
committerRichard Levitte <levitte@openssl.org>2005-04-09 16:06:45 +0000
commite12a911846bbff9a0383c494c86b9f5ad35b1dfe (patch)
tree9fc9a1d1604b782f97eef9cc6f33c0fc5d6579ae
parent49d35083ca3deefabe362c2f3ee1b6f6e700bee8 (diff)
downloadopenssl-new-e12a911846bbff9a0383c494c86b9f5ad35b1dfe.tar.gz
Added restrictions on the use of proxy certificates, as they may pose
a security threat on unexpecting applications. Document and test.
-rw-r--r--CHANGES6
-rw-r--r--crypto/x509/x509_txt.c2
-rw-r--r--crypto/x509/x509_vfy.c15
-rw-r--r--crypto/x509/x509_vfy.h5
-rw-r--r--crypto/x509v3/v3_purp.c4
-rw-r--r--doc/HOWTO/proxy_certificates.txt46
-rw-r--r--doc/standards.txt4
-rw-r--r--ssl/ssltest.c17
-rw-r--r--test/testsslproxy2
9 files changed, 95 insertions, 6 deletions
diff --git a/CHANGES b/CHANGES
index 619684e186..95e0a92e20 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,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
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 29c524803b..f19e66a238 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -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:
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index fa6bfff5cb..56d41fff8d 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -381,6 +381,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
int (*cb)();
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
@@ -391,6 +392,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++)
{
@@ -405,6 +412,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)
{
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index f1d1b05fb5..7fd1f0bc4d 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -276,7 +276,7 @@ struct x509_store_ctx_st /* X509_STORE_CTX */
#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
@@ -309,6 +309,7 @@ struct x509_store_ctx_st /* X509_STORE_CTX */
#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
/* The application is not happy */
#define X509_V_ERR_APPLICATION_VERIFICATION 50
@@ -327,6 +328,8 @@ struct x509_store_ctx_st /* X509_STORE_CTX */
#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
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
X509_NAME *name);
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 7281106fd4..bbdf6da493 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -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;
}
PROXY_CERT_INFO_EXTENSION_free(pci);
diff --git a/doc/HOWTO/proxy_certificates.txt b/doc/HOWTO/proxy_certificates.txt
index fbb6e953b5..3d36b02f6b 100644
--- a/doc/HOWTO/proxy_certificates.txt
+++ b/doc/HOWTO/proxy_certificates.txt
@@ -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)
diff --git a/doc/standards.txt b/doc/standards.txt
index edbe2f3a57..f6675b574b 100644
--- a/doc/standards.txt
+++ b/doc/standards.txt
@@ -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:
--------
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index c868baaa5d..02878981f1 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -176,6 +176,7 @@ struct app_verify_arg
{
char *string;
int app_verify;
+ int allow_proxy_certs;
char *proxy_auth;
char *proxy_cond;
};
@@ -212,6 +213,7 @@ static void sv_usage(void)
#endif
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");
@@ -364,7 +366,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;
@@ -556,6 +558,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);
@@ -1546,17 +1552,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;
}
}
@@ -1958,6 +1969,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
diff --git a/test/testsslproxy b/test/testsslproxy
index 70cf12342d..58bbda8ab7 100644
--- a/test/testsslproxy
+++ b/test/testsslproxy
@@ -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