diff options
author | levitte <levitte> | 2005-04-09 16:06:41 +0000 |
---|---|---|
committer | levitte <levitte> | 2005-04-09 16:06:41 +0000 |
commit | 8a4ac9d8ed559e8b216b93ab99622cfa13acba2b (patch) | |
tree | da5271be7f15fd46d3a78a079f4ed274ef013b72 | |
parent | aaf73698cb13e0e4427d733510978095f90e54bd (diff) | |
download | openssl-8a4ac9d8ed559e8b216b93ab99622cfa13acba2b.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-- | CHANGES | 6 | ||||
-rw-r--r-- | crypto/x509/x509_txt.c | 2 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.c | 15 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.h | 5 | ||||
-rw-r--r-- | crypto/x509v3/v3_purp.c | 4 | ||||
-rw-r--r-- | doc/HOWTO/proxy_certificates.txt | 46 | ||||
-rw-r--r-- | doc/standards.txt | 4 | ||||
-rw-r--r-- | ssl/ssltest.c | 17 | ||||
-rw-r--r-- | test/testsslproxy | 2 |
9 files changed, 95 insertions, 6 deletions
@@ -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 29c524803..f19e66a23 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 fa6bfff5c..56d41fff8 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 f1d1b05fb..7fd1f0bc4 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 7281106fd..bbdf6da49 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 fbb6e953b..3d36b02f6 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 edbe2f3a5..f6675b574 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 c868baaa5..02878981f 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 70cf12342..58bbda8ab 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 |