logo_kerberos.gif

Difference between revisions of "Pkinit configuration"

From K5Wiki
Jump to: navigation, search
(some initial thoughts)
 
(Debugging Pkinit)
 
(25 intermediate revisions by 7 users not shown)
Line 16: Line 16:
   
 
Pkinit requires a public key infrastructure. The simplest use of
 
Pkinit requires a public key infrastructure. The simplest use of
Pkinit ([[anonymous kerberos]] requires a certificate authority (CA)
+
Pkinit ([[anonymous kerberos]]) requires a certificate authority (CA)
 
certificate and a KDC certificate. The certificate authority
 
certificate and a KDC certificate. The certificate authority
 
certificate is known by all clients; any certificates signed by this
 
certificate is known by all clients; any certificates signed by this
Line 28: Line 28:
 
This document discusses how to set up Pkinit for the EXAMPLE.COM realm by hand. This sort of by-hand setup may be appropriate for anonymous usage. However if a realm is going to provide certificates to each client then some sort of automated certificate authority will be required to manage certificates. Configuring an automated certificate authority will depend on what certificate authority is chosen.
 
This document discusses how to set up Pkinit for the EXAMPLE.COM realm by hand. This sort of by-hand setup may be appropriate for anonymous usage. However if a realm is going to provide certificates to each client then some sort of automated certificate authority will be required to manage certificates. Configuring an automated certificate authority will depend on what certificate authority is chosen.
   
== Generating the certifate authority certifitae ==
+
== Generating the certificate authority certificate ==
   
In this document we will use Open SSL to generate a simple self-signed certificate to use for the certificate authority.
+
In this document we will use OpenSSL to generate a simple self-signed certificate to use for the certificate authority.
   
   
 
First, generate a private key:
 
First, generate a private key:
 
<pre> openssl genrsa -out cakey.pem 2048 </pre>
 
<pre> openssl genrsa -out cakey.pem 2048 </pre>
This will generate a 2048-bit RSA key and write it to afile <ttcakey.pem</tt> In a production environment, this private key should be carefully protected.
+
This will generate a 2048-bit RSA key and write it to file <tt>cakey.pem</tt>. In a production environment, this private key should be carefully protected.
 
Now, generate the CA certificate:
 
Now, generate the CA certificate:
 
<pre>
 
<pre>
Line 53: Line 53:
 
types of names in certificates that were not part of the original
 
types of names in certificates that were not part of the original
 
X.509 architecture. Unfortunately, including these elements in a
 
X.509 architecture. Unfortunately, including these elements in a
certificate requires the use of an Open SSL extensions file. This
+
certificate requires the use of an OpenSSL extensions file. This
 
file provides configuration for the certificate generation process. However the mechanisms for providing user data such as the name of the realm and the client principal to the otherName component are primitive.
 
file provides configuration for the certificate generation process. However the mechanisms for providing user data such as the name of the realm and the client principal to the otherName component are primitive.
   
This article includes a sample Open SSL extensions file; see [[#Extensions file]]. That file uses environment variables to set the client and realm name.
+
This article includes a sample OpenSSL extensions file; see
  +
[[#Extensions file]]. Paste that section of the article into a filed called <tt>pkinit_extensions</tt>. That file uses environment variables to set the
  +
client and realm name.
   
 
=== Generating KDC certificate ===
 
=== Generating KDC certificate ===
Line 72: Line 72:
 
<pre>
 
<pre>
 
REALM=EXAMPLE.COM; export REALM
 
REALM=EXAMPLE.COM; export REALM
CLIENT=krbtgt; export CLIENT
+
CLIENT=<kdc-name.example.com>; export CLIENT
openssl x509 -req -in kdc.req -CAkey cakey.pem -out kdc.pem -extfile pkinit_extensions -extensions kdc-cert
+
  +
openssl x509 -req -in kdc.req -CAkey cakey.pem -CA cacert.pem -out kdc.pem -extfile pkinit_extensions -extensions kdc_cert -CAcreateserial
 
</pre>
 
</pre>
This will generate <tt>kdc.pem</tt> a certificate for the KDC. The
+
This will generate a certificate, <tt>kdc.pem</tt>, for the KDC. The
 
first two lines set environment variables used by the extensions
 
first two lines set environment variables used by the extensions
 
file. The <i>REALM</i> variable should be set to the name of your
 
file. The <i>REALM</i> variable should be set to the name of your
 
realm.
 
realm.
  +
  +
=== Generating client certificates ===
  +
  +
For use with anonymous Kerberos, no additional certificates are needed. For other uses of Pkinit, generate a certificate for each client. Typically on the client machine, the private key is generated:
  +
<pre>
  +
openssl genrsa -out clientkey.pem 2048
  +
</pre>
  +
The certificate request is also typically generated on the client machine:
  +
<pre>
  +
openssl req -new -key clientkey.pem -out client.req
  +
</pre>
  +
The <tt>client.req</tt> file needs to be copied to the machine with the certificate authority key. Then, sign the certificate:
  +
<pre>
  +
REALM=EXAMPLE.COM; export REALM
  +
CLIENT=alice; export CLIENT
  +
openssl x509 -CAkey cakey.pem -CA cacert.pem -req -in client.req -extensions client_cert -extfile pkinit_extensions -out client.pem
  +
</pre>
  +
That will sign a certificate for <tt>alice@EXAMPLE.COM</tt>. The resulting <tt>client.pem</tt> needs to be copied back to the client.
  +
  +
== Configuring a KDC ==
  +
Insert the following entries into the <i>kdcdefaults</i> or a <i>realms</i> section of the <tt>kdc.conf</tt> or <tt>krb5.conf</tt> used by the KDC:
  +
<pre>
  +
pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem
  +
pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem
  +
kdc_tcp_ports = 88
  +
</pre>
  +
Of course, adjust the directory to where the files are stored on your system. The <i>kdc_tcp_ports</i> setting might be needed if your certificates don't fit in a non-fragmented UDP packet.
  +
Then, for each client principal that uses pkinit, set the <i>requires_preauth</i> attribute from within <b>kadmin</b>:
  +
<pre>
  +
modprinc +requires_preauth alice@EXAMPLE.COM
  +
</pre>
  +
  +
== Configuring a client ==
  +
Add the following to the appropriate realm section of <tt>krb5.conf</tt>
  +
<pre>
  +
[realms]
  +
EXAMPLE.COM = {
  +
pkinit_anchors = FILE:/etc/krb5/cacert.pem
  +
  +
pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem
  +
}
  +
</pre>
  +
Of course, <tt>clientkey.pem</tt> needs to be protected .
  +
After this point, using <b>kinit</b> as the appropriate client principal should not require a password.
  +
  +
== Advanced Configuration ==
  +
=== Including pkinit options in a certificate request ===
  +
Note that in the above example, the client name was not actually set
  +
in the certificate request but was
  +
set when the certificate was
  +
generated. In a production
  +
situation, it would be desirable
  +
to include the client name in a
  +
certificate request. There is an
  +
option to do this: the
  +
<b>-extensions</b> option to the
  +
<b>openssl req</b> command is
  +
intended for this purpose.
  +
Unfortunately, the <b>openssl
  +
req</b> command does not have a
  +
<b>-extfile</b> option. It seems
  +
that a special file for input to
  +
the <b>-config</b> option could be
  +
constructed to accomplish this.
  +
  +
In theory, if the options were included in the certificate request,
  +
then a traditional certificate authority could be used to issue the
  +
certificate. Common practice is not to copy the requested extensions
  +
into the issued certificate, so special configuration would probably
  +
be required on the part of the certificate authority.
  +
  +
=== Client identity on the command line ===
  +
The <b>-X X509_user_identity</b> option to <b>kinit</b> allows users
  +
to specify what Pkinit idenity and key should be used. It provides an
  +
alternative to specifying this information in <tt>krb5.conf</tt>.
  +
  +
=== Smart card configuration ===
  +
The [http://web.mit.edu/Kerberos/krb5-1.9/krb5-1.9.1/doc/krb5-admin.html#pkinit-client-options Kerberos administration manual]
  +
describes how to configure Pkinit to use PKCS11 smart cards and how to configure the selection of the correct identity.
  +
  +
== Debugging Pkinit ==
  +
By default, the MIT Kerberos Pkinit plugin does not support debugging output. Debugging can be enabled but requires changing the source and rebuilding the plugin. Add the following line to the top of <tt>src/plugins/preauth/pkinit/pkinit.h</tt>
  +
<pre>
  +
#define DEBUG
  +
</pre>
  +
Then, rebuild the sources. Copy the generated <tt>pkinit.so</tt> into place to get debugging output.
  +
  +
Alternatively, in the <code>plugins/preauth/pkinit</code> directory:
  +
  +
<pre>
  +
make clean
  +
make CPPFLAGS=-DDEBUG
  +
</pre>
  +
  +
==Extensions file==
  +
<pre>
  +
[ kdc_cert ]
  +
basicConstraints=CA:FALSE
  +
  +
# Here are some examples of the usage of nsCertType. If it is omitted
  +
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
  +
  +
#Pkinit EKU
  +
extendedKeyUsage = 1.3.6.1.5.2.3.5
  +
  +
subjectKeyIdentifier=hash
  +
authorityKeyIdentifier=keyid,issuer
  +
  +
# Copy subject details
  +
  +
issuerAltName=issuer:copy
  +
  +
# Add id-pkinit-san (pkinit subjectAlternativeName)
  +
subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name
  +
  +
[kdc_princ_name]
  +
realm = EXP:0, GeneralString:${ENV::REALM}
  +
principal_name = EXP:1, SEQUENCE:kdc_principal_seq
  +
  +
[kdc_principal_seq]
  +
name_type = EXP:0, INTEGER:1
  +
name_string = EXP:1, SEQUENCE:kdc_principals
  +
  +
[kdc_principals]
  +
princ1 = GeneralString:krbtgt
  +
princ2 = GeneralString:${ENV::REALM}
  +
  +
[ client_cert ]
  +
  +
# These extensions are added when 'ca' signs a request.
  +
  +
basicConstraints=CA:FALSE
  +
  +
keyUsage = digitalSignature, keyEncipherment, keyAgreement
  +
  +
extendedKeyUsage = 1.3.6.1.5.2.3.4
  +
subjectKeyIdentifier=hash
  +
authorityKeyIdentifier=keyid,issuer
  +
  +
  +
subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name
  +
  +
  +
# Copy subject details
  +
  +
issuerAltName=issuer:copy
  +
  +
[princ_name]
  +
realm = EXP:0, GeneralString:${ENV::REALM}
  +
principal_name = EXP:1, SEQUENCE:principal_seq
  +
  +
[principal_seq]
  +
name_type = EXP:0, INTEGER:1
  +
name_string = EXP:1, SEQUENCE:principals
  +
  +
[principals]
  +
princ1 = GeneralString:${ENV::CLIENT}
  +
</pre>

Latest revision as of 21:32, 8 October 2013

Pkinit provides support for using public-key authentication with Kerberos. Pkinit is useful in the following situations:

  1. Using smart cards for Kerberos authentication
  2. Authentication based on soft tokens (or certificates stored on a computer) instead of passwords
  3. In conjunction with anonymous kerberos and FAST protecting password exchanges to remove the possibility of dictionary attacks

This article describes minimal Pkinit configuration for a KDC and clients. It assumes you already have a Kerberos realm functioning and that you have the openssl command available.

The following steps are involved:

  1. Setting up a certificate authority
  2. Generating a KDC certificate
  3. Generating client certificates
  4. Configuring the KDC and clients
  5. Testing

Background

Pkinit requires a public key infrastructure. The simplest use of Pkinit (anonymous kerberos) requires a certificate authority (CA) certificate and a KDC certificate. The certificate authority certificate is known by all clients; any certificates signed by this certificate are trusted by the clients. The KDC certificate is signed by the certificate authority certificate (and thus trusted by the clients) and identifies the KDC.


If Pkinit is used with smart cards or for other forms of user authentication, then each user will need a certificate as well.

This document discusses how to set up Pkinit for the EXAMPLE.COM realm by hand. This sort of by-hand setup may be appropriate for anonymous usage. However if a realm is going to provide certificates to each client then some sort of automated certificate authority will be required to manage certificates. Configuring an automated certificate authority will depend on what certificate authority is chosen.

Generating the certificate authority certificate

In this document we will use OpenSSL to generate a simple self-signed certificate to use for the certificate authority.


First, generate a private key:

 openssl genrsa -out cakey.pem 2048 

This will generate a 2048-bit RSA key and write it to file cakey.pem. In a production environment, this private key should be carefully protected. Now, generate the CA certificate:

openssl req -key cakey.pem -new -x509 -out cacert.pem

This command will ask for the name of the CA and output a CA certificate into cacert.pem using the previously generated key.

Generating Kerberos certificates

Kerberos certificates take advantage of two uncommon features of certificates. First, an extended key usage is used to indicate that the certificate should be used with Pkinit. An extended key usage is an object identifier placed in a certificate to indicate what the public key should be used for. Secondly, an otherName form of a subjectAlternativeName is used to describe the Kerberos principal associated with the certificate. An otherName is a way of including types of names in certificates that were not part of the original X.509 architecture. Unfortunately, including these elements in a certificate requires the use of an OpenSSL extensions file. This file provides configuration for the certificate generation process. However the mechanisms for providing user data such as the name of the realm and the client principal to the otherName component are primitive.

This article includes a sample OpenSSL extensions file; see #Extensions file. Paste that section of the article into a filed called pkinit_extensions. That file uses environment variables to set the client and realm name.

Generating KDC certificate

First, generate the KDC key:

openssl genrsa -out kdckey.pem 2048 

Then, generate a certificate request

openssl req -new -out kdc.req -key kdckey.pem

Enter in the KDC name information. To generate the certificate:

REALM=EXAMPLE.COM; export REALM
CLIENT=<kdc-name.example.com>; export CLIENT

openssl x509 -req -in kdc.req -CAkey cakey.pem -CA cacert.pem -out kdc.pem -extfile pkinit_extensions -extensions kdc_cert -CAcreateserial

This will generate a certificate, kdc.pem, for the KDC. The first two lines set environment variables used by the extensions file. The REALM variable should be set to the name of your realm.

Generating client certificates

For use with anonymous Kerberos, no additional certificates are needed. For other uses of Pkinit, generate a certificate for each client. Typically on the client machine, the private key is generated:

openssl genrsa -out clientkey.pem 2048

The certificate request is also typically generated on the client machine:

openssl req -new -key clientkey.pem -out client.req

The client.req file needs to be copied to the machine with the certificate authority key. Then, sign the certificate:

REALM=EXAMPLE.COM; export REALM
CLIENT=alice; export CLIENT
openssl x509 -CAkey cakey.pem -CA cacert.pem -req -in client.req -extensions client_cert -extfile pkinit_extensions  -out client.pem

That will sign a certificate for alice@EXAMPLE.COM. The resulting client.pem needs to be copied back to the client.

Configuring a KDC

Insert the following entries into the kdcdefaults or a realms section of the kdc.conf or krb5.conf used by the KDC:

pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem
pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem
kdc_tcp_ports = 88

Of course, adjust the directory to where the files are stored on your system. The kdc_tcp_ports setting might be needed if your certificates don't fit in a non-fragmented UDP packet. Then, for each client principal that uses pkinit, set the requires_preauth attribute from within kadmin:

modprinc +requires_preauth alice@EXAMPLE.COM

Configuring a client

Add the following to the appropriate realm section of krb5.conf

[realms]
	EXAMPLE.COM = {
		    pkinit_anchors = FILE:/etc/krb5/cacert.pem

		    pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem
		    		    }

Of course, clientkey.pem needs to be protected . After this point, using kinit as the appropriate client principal should not require a password.

Advanced Configuration

Including pkinit options in a certificate request

Note that in the above example, the client name was not actually set in the certificate request but was set when the certificate was generated. In a production situation, it would be desirable to include the client name in a certificate request. There is an option to do this: the -extensions option to the openssl req command is intended for this purpose. Unfortunately, the openssl req command does not have a -extfile option. It seems that a special file for input to the -config option could be constructed to accomplish this.

In theory, if the options were included in the certificate request, then a traditional certificate authority could be used to issue the certificate. Common practice is not to copy the requested extensions into the issued certificate, so special configuration would probably be required on the part of the certificate authority.

Client identity on the command line

The -X X509_user_identity option to kinit allows users to specify what Pkinit idenity and key should be used. It provides an alternative to specifying this information in krb5.conf.

Smart card configuration

The Kerberos administration manual describes how to configure Pkinit to use PKCS11 smart cards and how to configure the selection of the correct identity.

Debugging Pkinit

By default, the MIT Kerberos Pkinit plugin does not support debugging output. Debugging can be enabled but requires changing the source and rebuilding the plugin. Add the following line to the top of src/plugins/preauth/pkinit/pkinit.h

#define DEBUG

Then, rebuild the sources. Copy the generated pkinit.so into place to get debugging output.

Alternatively, in the plugins/preauth/pkinit directory:

make clean
make CPPFLAGS=-DDEBUG

Extensions file

[ kdc_cert ]
basicConstraints=CA:FALSE

# Here are some examples of the usage of nsCertType. If it is omitted
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement

#Pkinit EKU
extendedKeyUsage = 1.3.6.1.5.2.3.5

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# Copy subject details

issuerAltName=issuer:copy

# Add id-pkinit-san (pkinit subjectAlternativeName)
subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name

[kdc_princ_name]
realm = EXP:0, GeneralString:${ENV::REALM}
principal_name = EXP:1, SEQUENCE:kdc_principal_seq

[kdc_principal_seq]
name_type = EXP:0, INTEGER:1
name_string = EXP:1, SEQUENCE:kdc_principals

[kdc_principals]
princ1 = GeneralString:krbtgt
princ2 = GeneralString:${ENV::REALM}

[ client_cert ]

# These extensions are added when 'ca' signs a request.

basicConstraints=CA:FALSE

keyUsage = digitalSignature, keyEncipherment, keyAgreement

extendedKeyUsage =  1.3.6.1.5.2.3.4
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer


subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name


# Copy subject details

issuerAltName=issuer:copy

[princ_name]
realm = EXP:0, GeneralString:${ENV::REALM}
principal_name = EXP:1, SEQUENCE:principal_seq

[principal_seq]
name_type = EXP:0, INTEGER:1
name_string = EXP:1, SEQUENCE:principals

[principals]
princ1 = GeneralString:${ENV::CLIENT}