Improves the proxy certificates howto doc.

The current documentation contains a bunch of spelling and grammar mistakes. I also
found it hard to understand some paragraphs, so here is my attempt to improve its
readability.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
This commit is contained in:
Alok Menghrajani 2014-11-14 10:39:41 -08:00 committed by Richard Levitte
parent f9ea4deba0
commit 03b637a730

View File

@ -3,72 +3,68 @@
0. WARNING
NONE OF THE CODE PRESENTED HERE HAVE BEEN CHECKED! They are just an
example to show you how things can be done. There may be typos or
type conflicts, and you will have to resolve them.
NONE OF THE CODE PRESENTED HERE HAS BEEN CHECKED! The code is just examples to
show you how things could be done. There might be typos or type conflicts, and
you will have to resolve them.
1. Introduction
Proxy certificates are defined in RFC 3820. They are really usual
certificates with the mandatory extension proxyCertInfo.
Proxy certificates are defined in RFC 3820. They are really usual certificates
with the mandatory extension proxyCertInfo.
Proxy certificates are issued by an End Entity (typically a user),
either directly with the EE certificate as issuing certificate, or by
extension through an already issued proxy certificate.. They are used
to extend rights to some other entity (a computer process, typically,
or sometimes to the user itself), so it can perform operations in the
name of the owner of the EE certificate.
Proxy certificates are issued by an End Entity (typically a user), either
directly with the EE certificate as issuing certificate, or by extension through
an already issued proxy certificate. Proxy certificates are used to extend
rights to some other entity (a computer process, typically, or sometimes to the
user itself). This allows the entity to perform operations on behalf of the
owner of the EE certificate.
See http://www.ietf.org/rfc/rfc3820.txt for more information.
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.
No one seems to have tested proxy certificates with security in mind. To this
date, it seems that proxy certificates have only been used in a context highly
aware of 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.
Existing applications might misbehave when trying to validate a chain of
certificates which use a proxy certificate. They might incorrectly consider the
leaf to be the certificate to check for authorisation data, which is controlled
by the EE certificate owner.
Possible threats are, as far as has been imagined so far:
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 we can think of at this time include:
- 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.
- 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:
For these reasons, OpenSSL requires that the use of proxy certificates be
explicitly 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()):
- if the application directly calls X509_verify_cert(), it can first call:
X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
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_CERTS with some non-empty value.
Where ctx is the pointer which then gets passed to X509_verify_cert().
There are thoughts to allow proxy certificates with a line in the
default openssl.cnf, but that's still in the future.
- proxy certificate validation can be enabled before starting the application
by setting the environment variable OPENSSL_ALLOW_PROXY_CERTS.
In the future, it might be possible to enable proxy certificates by editing
openssl.cnf.
3. How to create proxy cerificates
3. How to create proxy certificates
It's quite easy to create proxy certificates, by taking advantage of
the lack of checks of the 'openssl x509' application (*ahem*). But
first, you need to create a configuration section that contains a
definition of the proxyCertInfo extension, a little like this:
Creating proxy certificates is quite easy, by taking advantage of a lack of
checks in the 'openssl x509' application (*ahem*). You must first create a
configuration section that contains a definition of the proxyCertInfo extension,
for example:
[ v3_proxy ]
# A proxy certificate MUST NEVER be a CA certificate.
@ -77,10 +73,10 @@ definition of the proxyCertInfo extension, a little like this:
# Usual authority key ID
authorityKeyIdentifier=keyid,issuer:always
# Now, for the extension that marks this certificate as a proxy one
# The extension which marks this certificate as a proxy
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:1,policy:text:AB
It's also possible to give the proxy extension in a separate section:
It's also possible to specify the proxy extension in a separate section:
proxyCertInfo=critical,@proxy_ext
@ -89,38 +85,32 @@ It's also possible to give the proxy extension in a separate section:
pathlen=0
policy=text:BC
The policy value has a specific syntax, {syntag}:{string}, where the
syntag determines what will be done with the string. The recognised
syntags are as follows:
The policy value has a specific syntax, {syntag}:{string}, where the syntag
determines what will be done with the string. The following syntags are
recognised:
text indicates that the string is simply the bytes, not
encoded in any kind of way:
text indicates that the string is simply bytes, without any encoding:
policy=text:räksmörgås
policy=text:räksmörgås
Previous versions of this design had a specific tag
for UTF-8 text. However, since the bytes are copied
as-is anyway, there's no need for it. Instead, use
the text: tag, like this:
Previous versions of this design had a specific tag for UTF-8 text.
However, since the bytes are copied as-is anyway, there is no need for
such a specific tag.
policy=text:räksmörgås
hex indicates the string is encoded in hex, with colons between each byte
(every second hex digit):
hex indicates the string is encoded in hex, with colons
between each byte (every second hex digit):
policy=hex:72:E4:6B:73:6D:F6:72:67:E5:73
policy=hex:72:E4:6B:73:6D:F6:72:67:E5:73
Previous versions of this design had a tag to insert a complete DER
blob. However, the only legal use for this would be to surround the
bytes that would go with the hex: tag with whatever is needed to
construct a correct OCTET STRING. The DER tag therefore felt
superfluous, and was removed.
Previous versions of this design had a tag to insert a
complete DER blob. However, the only legal use for
this would be to surround the bytes that would go with
the hex: tag with what's needed to construct a correct
OCTET STRING. Since hex: does that, the DER tag felt
superfluous, and was therefore removed.
file indicates that the text of the policy should really be
taken from a file. The string is then really a file
name. This is useful for policies that are large
(more than a few of lines) XML documents, for example.
file indicates that the text of the policy should really be taken from a
file. The string is then really a file name. This is useful for
policies that are large (more than a few lines, e.g. XML documents).
The 'policy' setting can be split up in multiple lines like this:
@ -128,57 +118,52 @@ The 'policy' setting can be split up in multiple lines like this:
1.polisy= a multi-
2.policy=line policy.
NOTE: the proxy policy value is the part that determines the rights
granted to the process using the proxy certificate. The value is
completely dependent on the application reading and interpretting it!
NOTE: the proxy policy value is the part which determines the rights granted to
the process using the proxy certificate. The value is completely dependent on
the application reading and interpreting it!
Now that you have created an extension section for your proxy
certificate, you can now easily create a proxy certificate like this:
Now that you have created an extension section for your proxy certificate, you
can easily create a proxy certificate by doing:
openssl req -new -config openssl.cnf \
-out proxy.req -keyout proxy.key
openssl x509 -req -CAcreateserial -in proxy.req -days 7 \
-out proxy.crt -CA user.crt -CAkey user.key \
-extfile openssl.cnf -extensions v3_proxy
openssl req -new -config openssl.cnf -out proxy.req -keyout proxy.key
openssl x509 -req -CAcreateserial -in proxy.req -days 7 -out proxy.crt \
-CA user.crt -CAkey user.key -extfile openssl.cnf -extensions v3_proxy
It's just as easy to create a proxy certificate using another proxy
certificate as issuer (note that I'm using a different configuration
section for it):
You can also create a proxy certificate using another proxy certificate as
issuer (note: I'm using a different configuration section for it):
openssl req -new -config openssl.cnf \
-out proxy2.req -keyout proxy2.key
openssl x509 -req -CAcreateserial -in proxy2.req -days 7 \
-out proxy2.crt -CA proxy.crt -CAkey proxy.key \
-extfile openssl.cnf -extensions v3_proxy2
openssl req -new -config openssl.cnf -out proxy2.req -keyout proxy2.key
openssl x509 -req -CAcreateserial -in proxy2.req -days 7 -out proxy2.crt \
-CA proxy.crt -CAkey proxy.key -extfile openssl.cnf -extensions v3_proxy2
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
of proxy certificates, user certificate and CA certificates, and see
what rights came out by the end. Sounds easy, huh? It almost is.
The basic way to interpret proxy policies is to start with some default rights,
then compute the resulting rights by checking the proxy certificate against
the chain of proxy certificates, user certificate and CA certificates. You then
use the final computed rights. Sounds easy, huh? It almost is.
The slightly complicated part is how to pass data between your
The slightly complicated part is figuring out how to pass data between your
application and the certificate validation procedure.
You need the following ingredients:
- a callback routing that will be called for every certificate that's
validated. It will be called several times for each certificates,
so you must be attentive to when it's a good time to do the proxy
policy interpretation and check, as well as to fill in the defaults
when the EE certificate is checked.
- a callback function that will be called for every certificate being
validated. The callback be called several times for each certificate,
so you must be careful to do the proxy policy interpretation at the right
time. You also need to fill in the defaults when the EE certificate is
checked.
- a structure of data that's shared between your application code and
the callback.
- a data structure that is shared between your application code and the
callback.
- a wrapper function that sets it all up.
- an ex_data index function that creates an index into the generic
ex_data store that's attached to an X509 validation context.
- an ex_data index function that creates an index into the generic ex_data
store that is attached to an X509 validation context.
This is some cookbook code for you to fill in:
Here is some skeleton code you can fill in:
/* In this example, I will use a view of granted rights as a bit
array, one bit for each possible right. */
@ -210,7 +195,7 @@ This is some cookbook code for you to fill in:
static int verify_callback(int ok, X509_STORE_CTX *ctx)
{
if (ok == 1) /* It's REALLY important you keep the proxy policy
check within this secion. It's important to know
check within this section. It's important to know
that when ok is 1, the certificates are checked
from top to bottom. You get the CA root first,
followed by the possible chain of intermediate
@ -250,7 +235,7 @@ This is some cookbook code for you to fill in:
bit array and fill it with the rights granted by
the current proxy certificate, then use it as a
mask on the accumulated rights bit array, and
voilà, you now have a new accumulated rights bit
voilà, you now have a new accumulated rights bit
array. */
{
int i;