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>
(cherry picked from commit 03b637a730e4a298c360cc143de7564060c06324)
This commit is contained in:
Alok Menghrajani 2014-11-14 10:39:41 -08:00 committed by Richard Levitte
parent 2db95e094d
commit 26d7cb400e

View File

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