Blame doc/admin/pkinit.rst

Packit fd8b60
.. _pkinit:
Packit fd8b60
Packit fd8b60
PKINIT configuration
Packit fd8b60
====================
Packit fd8b60
Packit fd8b60
PKINIT is a preauthentication mechanism for Kerberos 5 which uses
Packit fd8b60
X.509 certificates to authenticate the KDC to clients and vice versa.
Packit fd8b60
PKINIT can also be used to enable anonymity support, allowing clients
Packit fd8b60
to communicate securely with the KDC or with application servers
Packit fd8b60
without authenticating as a particular client principal.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Creating certificates
Packit fd8b60
---------------------
Packit fd8b60
Packit fd8b60
PKINIT requires an X.509 certificate for the KDC and one for each
Packit fd8b60
client principal which will authenticate using PKINIT.  For anonymous
Packit fd8b60
PKINIT, a KDC certificate is required, but client certificates are
Packit fd8b60
not.  A commercially issued server certificate can be used for the KDC
Packit fd8b60
certificate, but generally cannot be used for client certificates.
Packit fd8b60
Packit fd8b60
The instruction in this section describe how to establish a
Packit fd8b60
certificate authority and create standard PKINIT certificates.  Skip
Packit fd8b60
this section if you are using a commercially issued server certificate
Packit fd8b60
as the KDC certificate for anonymous PKINIT, or if you are configuring
Packit fd8b60
a client to use an Active Directory KDC.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Generating a certificate authority certificate
Packit fd8b60
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit fd8b60
Packit fd8b60
You can establish a new certificate authority (CA) for use with a
Packit fd8b60
PKINIT deployment with the commands::
Packit fd8b60
Packit fd8b60
    openssl genrsa -out cakey.pem 2048
Packit fd8b60
    openssl req -key cakey.pem -new -x509 -out cacert.pem -days 3650
Packit fd8b60
Packit fd8b60
The second command will ask for the values of several certificate
Packit fd8b60
fields.  These fields can be set to any values.  You can adjust the
Packit fd8b60
expiration time of the CA certificate by changing the number after
Packit fd8b60
``-days``.  Since the CA certificate must be deployed to client
Packit fd8b60
machines each time it changes, it should normally have an expiration
Packit fd8b60
time far in the future; however, expiration times after 2037 may cause
Packit fd8b60
interoperability issues in rare circumstances.
Packit fd8b60
Packit fd8b60
The result of these commands will be two files, cakey.pem and
Packit fd8b60
cacert.pem.  cakey.pem will contain a 2048-bit RSA private key, which
Packit fd8b60
must be carefully protected.  cacert.pem will contain the CA
Packit fd8b60
certificate, which must be placed in the filesystems of the KDC and
Packit fd8b60
each client host.  cakey.pem will be required to create KDC and client
Packit fd8b60
certificates.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Generating a KDC certificate
Packit fd8b60
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit fd8b60
Packit fd8b60
A KDC certificate for use with PKINIT is required to have some unusual
Packit fd8b60
fields, which makes generating them with OpenSSL somewhat complicated.
Packit fd8b60
First, you will need a file containing the following::
Packit fd8b60
Packit fd8b60
    [kdc_cert]
Packit fd8b60
    basicConstraints=CA:FALSE
Packit fd8b60
    keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
Packit fd8b60
    extendedKeyUsage=1.3.6.1.5.2.3.5
Packit fd8b60
    subjectKeyIdentifier=hash
Packit fd8b60
    authorityKeyIdentifier=keyid,issuer
Packit fd8b60
    issuerAltName=issuer:copy
Packit fd8b60
    subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name
Packit fd8b60
Packit fd8b60
    [kdc_princ_name]
Packit fd8b60
    realm=EXP:0,GeneralString:${ENV::REALM}
Packit fd8b60
    principal_name=EXP:1,SEQUENCE:kdc_principal_seq
Packit fd8b60
Packit fd8b60
    [kdc_principal_seq]
Packit fd8b60
    name_type=EXP:0,INTEGER:2
Packit fd8b60
    name_string=EXP:1,SEQUENCE:kdc_principals
Packit fd8b60
Packit fd8b60
    [kdc_principals]
Packit fd8b60
    princ1=GeneralString:krbtgt
Packit fd8b60
    princ2=GeneralString:${ENV::REALM}
Packit fd8b60
Packit fd8b60
If the above contents are placed in extensions.kdc, you can generate
Packit fd8b60
and sign a KDC certificate with the following commands::
Packit fd8b60
Packit fd8b60
    openssl genrsa -out kdckey.pem 2048
Packit fd8b60
    openssl req -new -out kdc.req -key kdckey.pem
Packit fd8b60
    env REALM=YOUR_REALMNAME openssl x509 -req -in kdc.req \
Packit fd8b60
        -CAkey cakey.pem -CA cacert.pem -out kdc.pem -days 365 \
Packit fd8b60
        -extfile extensions.kdc -extensions kdc_cert -CAcreateserial
Packit fd8b60
    rm kdc.req
Packit fd8b60
Packit fd8b60
The second command will ask for the values of certificate fields,
Packit fd8b60
which can be set to any values.  In the third command, substitute your
Packit fd8b60
KDC's realm name for YOUR_REALMNAME.  You can adjust the certificate's
Packit fd8b60
expiration date by changing the number after ``-days``.  Remember to
Packit fd8b60
create a new KDC certificate before the old one expires.
Packit fd8b60
Packit fd8b60
The result of this operation will be in two files, kdckey.pem and
Packit fd8b60
kdc.pem.  Both files must be placed in the KDC's filesystem.
Packit fd8b60
kdckey.pem, which contains the KDC's private key, must be carefully
Packit fd8b60
protected.
Packit fd8b60
Packit fd8b60
If you examine the KDC certificate with ``openssl x509 -in kdc.pem
Packit fd8b60
-text -noout``, OpenSSL will not know how to display the KDC principal
Packit fd8b60
name in the Subject Alternative Name extension, so it will appear as
Packit fd8b60
``othername:<unsupported>``.  This is normal and does not mean
Packit fd8b60
anything is wrong with the KDC certificate.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Generating client certificates
Packit fd8b60
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packit fd8b60
Packit fd8b60
PKINIT client certificates also must have some unusual certificate
Packit fd8b60
fields.  To generate a client certificate with OpenSSL for a
Packit fd8b60
single-component principal name, you will need an extensions file
Packit fd8b60
(different from the KDC extensions file above) containing::
Packit fd8b60
Packit fd8b60
    [client_cert]
Packit fd8b60
    basicConstraints=CA:FALSE
Packit fd8b60
    keyUsage=digitalSignature,keyEncipherment,keyAgreement
Packit fd8b60
    extendedKeyUsage=1.3.6.1.5.2.3.4
Packit fd8b60
    subjectKeyIdentifier=hash
Packit fd8b60
    authorityKeyIdentifier=keyid,issuer
Packit fd8b60
    issuerAltName=issuer:copy
Packit fd8b60
    subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name
Packit fd8b60
Packit fd8b60
    [princ_name]
Packit fd8b60
    realm=EXP:0,GeneralString:${ENV::REALM}
Packit fd8b60
    principal_name=EXP:1,SEQUENCE:principal_seq
Packit fd8b60
Packit fd8b60
    [principal_seq]
Packit fd8b60
    name_type=EXP:0,INTEGER:1
Packit fd8b60
    name_string=EXP:1,SEQUENCE:principals
Packit fd8b60
Packit fd8b60
    [principals]
Packit fd8b60
    princ1=GeneralString:${ENV::CLIENT}
Packit fd8b60
Packit fd8b60
If the above contents are placed in extensions.client, you can
Packit fd8b60
generate and sign a client certificate with the following commands::
Packit fd8b60
Packit fd8b60
    openssl genrsa -out clientkey.pem 2048
Packit fd8b60
    openssl req -new -key clientkey.pem -out client.req
Packit fd8b60
    env REALM=YOUR_REALMNAME CLIENT=YOUR_PRINCNAME openssl x509 \
Packit fd8b60
        -CAkey cakey.pem -CA cacert.pem -req -in client.req \
Packit fd8b60
        -extensions client_cert -extfile extensions.client \
Packit fd8b60
        -days 365 -out client.pem
Packit fd8b60
    rm client.req
Packit fd8b60
Packit fd8b60
Normally, the first two commands should be run on the client host, and
Packit fd8b60
the resulting client.req file transferred to the certificate authority
Packit fd8b60
host for the third command.  As in the previous steps, the second
Packit fd8b60
command will ask for the values of certificate fields, which can be
Packit fd8b60
set to any values.  In the third command, substitute your realm's name
Packit fd8b60
for YOUR_REALMNAME and the client's principal name (without realm) for
Packit fd8b60
YOUR_PRINCNAME.  You can adjust the certificate's expiration date by
Packit fd8b60
changing the number after ``-days``.
Packit fd8b60
Packit fd8b60
The result of this operation will be two files, clientkey.pem and
Packit fd8b60
client.pem.  Both files must be present on the client's host;
Packit fd8b60
clientkey.pem, which contains the client's private key, must be
Packit fd8b60
protected from access by others.
Packit fd8b60
Packit fd8b60
As in the KDC certificate, OpenSSL will display the client principal
Packit fd8b60
name as ``othername:<unsupported>`` in the Subject Alternative Name
Packit fd8b60
extension of a PKINIT client certificate.
Packit fd8b60
Packit fd8b60
If the client principal name contains more than one component
Packit fd8b60
(e.g. ``host/example.com@REALM``), the ``[principals]`` section of
Packit fd8b60
``extensions.client`` must be altered to contain multiple entries.
Packit fd8b60
(Simply setting ``CLIENT`` to ``host/example.com`` would generate a
Packit fd8b60
certificate for ``host\/example.com@REALM`` which would not match the
Packit fd8b60
multi-component principal name.)  For a two-component principal, the
Packit fd8b60
section should read::
Packit fd8b60
Packit fd8b60
    [principals]
Packit fd8b60
    princ1=GeneralString:${ENV::CLIENT1}
Packit fd8b60
    princ2=GeneralString:${ENV::CLIENT2}
Packit fd8b60
Packit fd8b60
The environment variables ``CLIENT1`` and ``CLIENT2`` must then be set
Packit fd8b60
to the first and second components when running ``openssl x509``.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Configuring the KDC
Packit fd8b60
-------------------
Packit fd8b60
Packit fd8b60
The KDC must have filesystem access to the KDC certificate (kdc.pem)
Packit fd8b60
and the KDC private key (kdckey.pem).  Configure the following
Packit fd8b60
relation in the KDC's :ref:`kdc.conf(5)` file, either in the
Packit fd8b60
:ref:`kdcdefaults` section or in a :ref:`kdc_realms` subsection (with
Packit fd8b60
appropriate pathnames)::
Packit fd8b60
Packit fd8b60
    pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem
Packit fd8b60
Packit fd8b60
If any clients will authenticate using regular (as opposed to
Packit fd8b60
anonymous) PKINIT, the KDC must also have filesystem access to the CA
Packit fd8b60
certificate (cacert.pem), and the following configuration (with the
Packit fd8b60
appropriate pathname)::
Packit fd8b60
Packit fd8b60
    pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem
Packit fd8b60
Packit fd8b60
Because of the larger size of requests and responses using PKINIT, you
Packit fd8b60
may also need to allow TCP access to the KDC::
Packit fd8b60
Packit fd8b60
    kdc_tcp_listen = 88
Packit fd8b60
Packit fd8b60
Restart the :ref:`krb5kdc(8)` daemon to pick up the configuration
Packit fd8b60
changes.
Packit fd8b60
Packit fd8b60
The principal entry for each PKINIT-using client must be configured to
Packit fd8b60
require preauthentication.  Ensure this with the command::
Packit fd8b60
Packit fd8b60
    kadmin -q 'modprinc +requires_preauth YOUR_PRINCNAME'
Packit fd8b60
Packit fd8b60
Starting with release 1.12, it is possible to remove the long-term
Packit fd8b60
keys of a principal entry, which can save some space in the database
Packit fd8b60
and help to clarify some PKINIT-related error conditions by not asking
Packit fd8b60
for a password::
Packit fd8b60
Packit fd8b60
    kadmin -q 'purgekeys -all YOUR_PRINCNAME'
Packit fd8b60
Packit fd8b60
These principal options can also be specified at principal creation
Packit fd8b60
time as follows::
Packit fd8b60
Packit fd8b60
    kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME'
Packit fd8b60
Packit fd8b60
By default, the KDC requires PKINIT client certificates to have the
Packit fd8b60
standard Extended Key Usage and Subject Alternative Name attributes
Packit fd8b60
for PKINIT.  Starting in release 1.16, it is possible to authorize
Packit fd8b60
client certificates based on the subject or other criteria instead of
Packit fd8b60
the standard PKINIT Subject Alternative Name, by setting the
Packit fd8b60
**pkinit_cert_match** string attribute on each client principal entry.
Packit fd8b60
For example::
Packit fd8b60
Packit fd8b60
    kadmin set_string user@REALM pkinit_cert_match "<SUBJECT>CN=user@REALM$"
Packit fd8b60
Packit fd8b60
The **pkinit_cert_match** string attribute follows the syntax used by
Packit fd8b60
the :ref:`krb5.conf(5)` **pkinit_cert_match** relation.  To allow the
Packit fd8b60
use of non-PKINIT client certificates, it will also be necessary to
Packit fd8b60
disable key usage checking using the **pkinit_eku_checking** relation;
Packit fd8b60
for example::
Packit fd8b60
Packit fd8b60
    [kdcdefaults]
Packit fd8b60
        pkinit_eku_checking = none
Packit fd8b60
Packit fd8b60
Packit fd8b60
Packit fd8b60
Configuring the clients
Packit fd8b60
-----------------------
Packit fd8b60
Packit fd8b60
Client hosts must be configured to trust the issuing authority for the
Packit fd8b60
KDC certificate.  For a newly established certificate authority, the
Packit fd8b60
client host must have filesystem access to the CA certificate
Packit fd8b60
(cacert.pem) and the following relation in :ref:`krb5.conf(5)` in the
Packit fd8b60
appropriate :ref:`realms` subsection (with appropriate pathnames)::
Packit fd8b60
Packit fd8b60
    pkinit_anchors = FILE:/etc/krb5/cacert.pem
Packit fd8b60
Packit fd8b60
If the KDC certificate is a commercially issued server certificate,
Packit fd8b60
the issuing certificate is most likely included in a system directory.
Packit fd8b60
You can specify it by filename as above, or specify the whole
Packit fd8b60
directory like so::
Packit fd8b60
Packit fd8b60
    pkinit_anchors = DIR:/etc/ssl/certs
Packit fd8b60
Packit fd8b60
A commercially issued server certificate will usually not have the
Packit fd8b60
standard PKINIT principal name or Extended Key Usage extensions, so
Packit fd8b60
the following additional configuration is required::
Packit fd8b60
Packit fd8b60
    pkinit_eku_checking = kpServerAuth
Packit fd8b60
    pkinit_kdc_hostname = hostname.of.kdc.certificate
Packit fd8b60
Packit fd8b60
Multiple **pkinit_kdc_hostname** relations can be configured to
Packit fd8b60
recognize multiple KDC certificates.  If the KDC is an Active
Packit fd8b60
Directory domain controller, setting **pkinit_kdc_hostname** is
Packit fd8b60
necessary, but it should not be necessary to set
Packit fd8b60
**pkinit_eku_checking**.
Packit fd8b60
Packit fd8b60
To perform regular (as opposed to anonymous) PKINIT authentication, a
Packit fd8b60
client host must have filesystem access to a client certificate
Packit fd8b60
(client.pem), and the corresponding private key (clientkey.pem).
Packit fd8b60
Configure the following relations in the client host's
Packit fd8b60
:ref:`krb5.conf(5)` file in the appropriate :ref:`realms` subsection
Packit fd8b60
(with appropriate pathnames)::
Packit fd8b60
Packit fd8b60
    pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem
Packit fd8b60
Packit fd8b60
If the KDC and client are properly configured, it should now be
Packit fd8b60
possible to run ``kinit username`` without entering a password.
Packit fd8b60
Packit fd8b60
Packit fd8b60
.. _anonymous_pkinit:
Packit fd8b60
Packit fd8b60
Anonymous PKINIT
Packit fd8b60
----------------
Packit fd8b60
Packit fd8b60
Anonymity support in Kerberos allows a client to obtain a ticket
Packit fd8b60
without authenticating as any particular principal.  Such a ticket can
Packit fd8b60
be used as a FAST armor ticket, or to securely communicate with an
Packit fd8b60
application server anonymously.
Packit fd8b60
Packit fd8b60
To configure anonymity support, you must generate or otherwise procure
Packit fd8b60
a KDC certificate and configure the KDC host, but you do not need to
Packit fd8b60
generate any client certificates.  On the KDC, you must set the
Packit fd8b60
**pkinit_identity** variable to provide the KDC certificate, but do
Packit fd8b60
not need to set the **pkinit_anchors** variable or store the issuing
Packit fd8b60
certificate if you won't have any client certificates to verify.  On
Packit fd8b60
client hosts, you must set the **pkinit_anchors** variable (and
Packit fd8b60
possibly **pkinit_kdc_hostname** and **pkinit_eku_checking**) in order
Packit fd8b60
to trust the issuing authority for the KDC certificate, but do not
Packit fd8b60
need to set the **pkinit_identities** variable.
Packit fd8b60
Packit fd8b60
Anonymity support is not enabled by default.  To enable it, you must
Packit fd8b60
create the principal ``WELLKNOWN/ANONYMOUS`` using the command::
Packit fd8b60
Packit fd8b60
    kadmin -q 'addprinc -randkey WELLKNOWN/ANONYMOUS'
Packit fd8b60
Packit fd8b60
Some Kerberos deployments include application servers which lack
Packit fd8b60
proper access control, and grant some level of access to any user who
Packit fd8b60
can authenticate.  In such an environment, enabling anonymity support
Packit fd8b60
on the KDC would present a security issue.  If you need to enable
Packit fd8b60
anonymity support for TGTs (for use as FAST armor tickets) without
Packit fd8b60
enabling anonymous authentication to application servers, you can set
Packit fd8b60
the variable **restrict_anonymous_to_tgt** to ``true`` in the
Packit fd8b60
appropriate :ref:`kdc_realms` subsection of the KDC's
Packit fd8b60
:ref:`kdc.conf(5)` file.
Packit fd8b60
Packit fd8b60
To obtain anonymous credentials on a client, run ``kinit -n``, or
Packit fd8b60
``kinit -n @REALMNAME`` to specify a realm.  The resulting tickets
Packit fd8b60
will have the client name ``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``.
Packit fd8b60
Packit fd8b60
Packit fd8b60
Freshness tokens
Packit fd8b60
----------------
Packit fd8b60
Packit fd8b60
Freshness tokens can ensure that the client has recently had access to
Packit fd8b60
its certificate private key.  If freshness tokens are not required by
Packit fd8b60
the KDC, a client program with temporary possession of the private key
Packit fd8b60
can compose requests for future timestamps and use them later.
Packit fd8b60
Packit fd8b60
In release 1.17 and later, freshness tokens are supported by the
Packit fd8b60
client and are sent by the KDC when the client indicates support for
Packit fd8b60
them.  Because not all clients support freshness tokens yet, they are
Packit fd8b60
not required by default.  To check if freshness tokens are supported
Packit fd8b60
by a realm's clients, look in the KDC logs for the lines::
Packit fd8b60
Packit fd8b60
    PKINIT: freshness token received from <client principal>
Packit fd8b60
    PKINIT: no freshness token received from <client principal>
Packit fd8b60
Packit fd8b60
To require freshness tokens for all clients in a realm (except for
Packit fd8b60
clients authenticating anonymously), set the
Packit fd8b60
**pkinit_require_freshness** variable to ``true`` in the appropriate
Packit fd8b60
:ref:`kdc_realms` subsection of the KDC's :ref:`kdc.conf(5)` file.  To
Packit fd8b60
test that this option is in effect, run ``kinit -X disable_freshness``
Packit fd8b60
and verify that authentication is unsuccessful.