1.. _pkinit:
2
3PKINIT configuration
4====================
5
6PKINIT is a preauthentication mechanism for Kerberos 5 which uses
7X.509 certificates to authenticate the KDC to clients and vice versa.
8PKINIT can also be used to enable anonymity support, allowing clients
9to communicate securely with the KDC or with application servers
10without authenticating as a particular client principal.
11
12
13Creating certificates
14---------------------
15
16PKINIT requires an X.509 certificate for the KDC and one for each
17client principal which will authenticate using PKINIT.  For anonymous
18PKINIT, a KDC certificate is required, but client certificates are
19not.  A commercially issued server certificate can be used for the KDC
20certificate, but generally cannot be used for client certificates.
21
22The instruction in this section describe how to establish a
23certificate authority and create standard PKINIT certificates.  Skip
24this section if you are using a commercially issued server certificate
25as the KDC certificate for anonymous PKINIT, or if you are configuring
26a client to use an Active Directory KDC.
27
28
29Generating a certificate authority certificate
30~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31
32You can establish a new certificate authority (CA) for use with a
33PKINIT deployment with the commands::
34
35    openssl genrsa -out cakey.pem 2048
36    openssl req -key cakey.pem -new -x509 -out cacert.pem -days 3650
37
38The second command will ask for the values of several certificate
39fields.  These fields can be set to any values.  You can adjust the
40expiration time of the CA certificate by changing the number after
41``-days``.  Since the CA certificate must be deployed to client
42machines each time it changes, it should normally have an expiration
43time far in the future; however, expiration times after 2037 may cause
44interoperability issues in rare circumstances.
45
46The result of these commands will be two files, cakey.pem and
47cacert.pem.  cakey.pem will contain a 2048-bit RSA private key, which
48must be carefully protected.  cacert.pem will contain the CA
49certificate, which must be placed in the filesystems of the KDC and
50each client host.  cakey.pem will be required to create KDC and client
51certificates.
52
53
54Generating a KDC certificate
55~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56
57A KDC certificate for use with PKINIT is required to have some unusual
58fields, which makes generating them with OpenSSL somewhat complicated.
59First, you will need a file containing the following::
60
61    [kdc_cert]
62    basicConstraints=CA:FALSE
63    keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
64    extendedKeyUsage=1.3.6.1.5.2.3.5
65    subjectKeyIdentifier=hash
66    authorityKeyIdentifier=keyid,issuer
67    issuerAltName=issuer:copy
68    subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name
69
70    [kdc_princ_name]
71    realm=EXP:0,GeneralString:${ENV::REALM}
72    principal_name=EXP:1,SEQUENCE:kdc_principal_seq
73
74    [kdc_principal_seq]
75    name_type=EXP:0,INTEGER:2
76    name_string=EXP:1,SEQUENCE:kdc_principals
77
78    [kdc_principals]
79    princ1=GeneralString:krbtgt
80    princ2=GeneralString:${ENV::REALM}
81
82If the above contents are placed in extensions.kdc, you can generate
83and sign a KDC certificate with the following commands::
84
85    openssl genrsa -out kdckey.pem 2048
86    openssl req -new -out kdc.req -key kdckey.pem
87    env REALM=YOUR_REALMNAME openssl x509 -req -in kdc.req \
88        -CAkey cakey.pem -CA cacert.pem -out kdc.pem -days 365 \
89        -extfile extensions.kdc -extensions kdc_cert -CAcreateserial
90    rm kdc.req
91
92The second command will ask for the values of certificate fields,
93which can be set to any values.  In the third command, substitute your
94KDC's realm name for YOUR_REALMNAME.  You can adjust the certificate's
95expiration date by changing the number after ``-days``.  Remember to
96create a new KDC certificate before the old one expires.
97
98The result of this operation will be in two files, kdckey.pem and
99kdc.pem.  Both files must be placed in the KDC's filesystem.
100kdckey.pem, which contains the KDC's private key, must be carefully
101protected.
102
103If you examine the KDC certificate with ``openssl x509 -in kdc.pem
104-text -noout``, OpenSSL will not know how to display the KDC principal
105name in the Subject Alternative Name extension, so it will appear as
106``othername:<unsupported>``.  This is normal and does not mean
107anything is wrong with the KDC certificate.
108
109
110Generating client certificates
111~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112
113PKINIT client certificates also must have some unusual certificate
114fields.  To generate a client certificate with OpenSSL for a
115single-component principal name, you will need an extensions file
116(different from the KDC extensions file above) containing::
117
118    [client_cert]
119    basicConstraints=CA:FALSE
120    keyUsage=digitalSignature,keyEncipherment,keyAgreement
121    extendedKeyUsage=1.3.6.1.5.2.3.4
122    subjectKeyIdentifier=hash
123    authorityKeyIdentifier=keyid,issuer
124    issuerAltName=issuer:copy
125    subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name
126
127    [princ_name]
128    realm=EXP:0,GeneralString:${ENV::REALM}
129    principal_name=EXP:1,SEQUENCE:principal_seq
130
131    [principal_seq]
132    name_type=EXP:0,INTEGER:1
133    name_string=EXP:1,SEQUENCE:principals
134
135    [principals]
136    princ1=GeneralString:${ENV::CLIENT}
137
138If the above contents are placed in extensions.client, you can
139generate and sign a client certificate with the following commands::
140
141    openssl genrsa -out clientkey.pem 2048
142    openssl req -new -key clientkey.pem -out client.req
143    env REALM=YOUR_REALMNAME CLIENT=YOUR_PRINCNAME openssl x509 \
144        -CAkey cakey.pem -CA cacert.pem -req -in client.req \
145        -extensions client_cert -extfile extensions.client \
146        -days 365 -out client.pem
147    rm client.req
148
149Normally, the first two commands should be run on the client host, and
150the resulting client.req file transferred to the certificate authority
151host for the third command.  As in the previous steps, the second
152command will ask for the values of certificate fields, which can be
153set to any values.  In the third command, substitute your realm's name
154for YOUR_REALMNAME and the client's principal name (without realm) for
155YOUR_PRINCNAME.  You can adjust the certificate's expiration date by
156changing the number after ``-days``.
157
158The result of this operation will be two files, clientkey.pem and
159client.pem.  Both files must be present on the client's host;
160clientkey.pem, which contains the client's private key, must be
161protected from access by others.
162
163As in the KDC certificate, OpenSSL will display the client principal
164name as ``othername:<unsupported>`` in the Subject Alternative Name
165extension of a PKINIT client certificate.
166
167If the client principal name contains more than one component
168(e.g. ``host/example.com@REALM``), the ``[principals]`` section of
169``extensions.client`` must be altered to contain multiple entries.
170(Simply setting ``CLIENT`` to ``host/example.com`` would generate a
171certificate for ``host\/example.com@REALM`` which would not match the
172multi-component principal name.)  For a two-component principal, the
173section should read::
174
175    [principals]
176    princ1=GeneralString:${ENV::CLIENT1}
177    princ2=GeneralString:${ENV::CLIENT2}
178
179The environment variables ``CLIENT1`` and ``CLIENT2`` must then be set
180to the first and second components when running ``openssl x509``.
181
182
183Configuring the KDC
184-------------------
185
186The KDC must have filesystem access to the KDC certificate (kdc.pem)
187and the KDC private key (kdckey.pem).  Configure the following
188relation in the KDC's :ref:`kdc.conf(5)` file, either in the
189:ref:`kdcdefaults` section or in a :ref:`kdc_realms` subsection (with
190appropriate pathnames)::
191
192    pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem
193
194If any clients will authenticate using regular (as opposed to
195anonymous) PKINIT, the KDC must also have filesystem access to the CA
196certificate (cacert.pem), and the following configuration (with the
197appropriate pathname)::
198
199    pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem
200
201Because of the larger size of requests and responses using PKINIT, you
202may also need to allow TCP access to the KDC::
203
204    kdc_tcp_listen = 88
205
206Restart the :ref:`krb5kdc(8)` daemon to pick up the configuration
207changes.
208
209The principal entry for each PKINIT-using client must be configured to
210require preauthentication.  Ensure this with the command::
211
212    kadmin -q 'modprinc +requires_preauth YOUR_PRINCNAME'
213
214Starting with release 1.12, it is possible to remove the long-term
215keys of a principal entry, which can save some space in the database
216and help to clarify some PKINIT-related error conditions by not asking
217for a password::
218
219    kadmin -q 'purgekeys -all YOUR_PRINCNAME'
220
221These principal options can also be specified at principal creation
222time as follows::
223
224    kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME'
225
226By default, the KDC requires PKINIT client certificates to have the
227standard Extended Key Usage and Subject Alternative Name attributes
228for PKINIT.  Starting in release 1.16, it is possible to authorize
229client certificates based on the subject or other criteria instead of
230the standard PKINIT Subject Alternative Name, by setting the
231**pkinit_cert_match** string attribute on each client principal entry.
232For example::
233
234    kadmin set_string user@REALM pkinit_cert_match "<SUBJECT>CN=user@REALM$"
235
236The **pkinit_cert_match** string attribute follows the syntax used by
237the :ref:`krb5.conf(5)` **pkinit_cert_match** relation.  To allow the
238use of non-PKINIT client certificates, it will also be necessary to
239disable key usage checking using the **pkinit_eku_checking** relation;
240for example::
241
242    [kdcdefaults]
243        pkinit_eku_checking = none
244
245
246
247Configuring the clients
248-----------------------
249
250Client hosts must be configured to trust the issuing authority for the
251KDC certificate.  For a newly established certificate authority, the
252client host must have filesystem access to the CA certificate
253(cacert.pem) and the following relation in :ref:`krb5.conf(5)` in the
254appropriate :ref:`realms` subsection (with appropriate pathnames)::
255
256    pkinit_anchors = FILE:/etc/krb5/cacert.pem
257
258If the KDC certificate is a commercially issued server certificate,
259the issuing certificate is most likely included in a system directory.
260You can specify it by filename as above, or specify the whole
261directory like so::
262
263    pkinit_anchors = DIR:/etc/ssl/certs
264
265A commercially issued server certificate will usually not have the
266standard PKINIT principal name or Extended Key Usage extensions, so
267the following additional configuration is required::
268
269    pkinit_eku_checking = kpServerAuth
270    pkinit_kdc_hostname = hostname.of.kdc.certificate
271
272Multiple **pkinit_kdc_hostname** relations can be configured to
273recognize multiple KDC certificates.  If the KDC is an Active
274Directory domain controller, setting **pkinit_kdc_hostname** is
275necessary, but it should not be necessary to set
276**pkinit_eku_checking**.
277
278To perform regular (as opposed to anonymous) PKINIT authentication, a
279client host must have filesystem access to a client certificate
280(client.pem), and the corresponding private key (clientkey.pem).
281Configure the following relations in the client host's
282:ref:`krb5.conf(5)` file in the appropriate :ref:`realms` subsection
283(with appropriate pathnames)::
284
285    pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem
286
287If the KDC and client are properly configured, it should now be
288possible to run ``kinit username`` without entering a password.
289
290
291.. _anonymous_pkinit:
292
293Anonymous PKINIT
294----------------
295
296Anonymity support in Kerberos allows a client to obtain a ticket
297without authenticating as any particular principal.  Such a ticket can
298be used as a FAST armor ticket, or to securely communicate with an
299application server anonymously.
300
301To configure anonymity support, you must generate or otherwise procure
302a KDC certificate and configure the KDC host, but you do not need to
303generate any client certificates.  On the KDC, you must set the
304**pkinit_identity** variable to provide the KDC certificate, but do
305not need to set the **pkinit_anchors** variable or store the issuing
306certificate if you won't have any client certificates to verify.  On
307client hosts, you must set the **pkinit_anchors** variable (and
308possibly **pkinit_kdc_hostname** and **pkinit_eku_checking**) in order
309to trust the issuing authority for the KDC certificate, but do not
310need to set the **pkinit_identities** variable.
311
312Anonymity support is not enabled by default.  To enable it, you must
313create the principal ``WELLKNOWN/ANONYMOUS`` using the command::
314
315    kadmin -q 'addprinc -randkey WELLKNOWN/ANONYMOUS'
316
317Some Kerberos deployments include application servers which lack
318proper access control, and grant some level of access to any user who
319can authenticate.  In such an environment, enabling anonymity support
320on the KDC would present a security issue.  If you need to enable
321anonymity support for TGTs (for use as FAST armor tickets) without
322enabling anonymous authentication to application servers, you can set
323the variable **restrict_anonymous_to_tgt** to ``true`` in the
324appropriate :ref:`kdc_realms` subsection of the KDC's
325:ref:`kdc.conf(5)` file.
326
327To obtain anonymous credentials on a client, run ``kinit -n``, or
328``kinit -n @REALMNAME`` to specify a realm.  The resulting tickets
329will have the client name ``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``.
330
331
332Freshness tokens
333----------------
334
335Freshness tokens can ensure that the client has recently had access to
336its certificate private key.  If freshness tokens are not required by
337the KDC, a client program with temporary possession of the private key
338can compose requests for future timestamps and use them later.
339
340In release 1.17 and later, freshness tokens are supported by the
341client and are sent by the KDC when the client indicates support for
342them.  Because not all clients support freshness tokens yet, they are
343not required by default.  To check if freshness tokens are supported
344by a realm's clients, look in the KDC logs for the lines::
345
346    PKINIT: freshness token received from <client principal>
347    PKINIT: no freshness token received from <client principal>
348
349To require freshness tokens for all clients in a realm (except for
350clients authenticating anonymously), set the
351**pkinit_require_freshness** variable to ``true`` in the appropriate
352:ref:`kdc_realms` subsection of the KDC's :ref:`kdc.conf(5)` file.  To
353test that this option is in effect, run ``kinit -X disable_freshness``
354and verify that authentication is unsuccessful.
355