Getting Started with Kerberos
Requirements: IPWorks Auth
Introduction
The Kerberos component can be used to implement a Kerberos 5.0 client, facilitating secure authentication within a network environment. This component enables seamless integration into various network architectures, allowing users to securely authenticate across distributed systems. This guide will cover the basics of performing such authentication.
Contents
Authentication
Before authenticating, the following properties must be set:
Property Name | Description |
---|---|
KDCHost | This property must be set to the IP address of the KDC host. |
KDCPort | This property must be set to the port the KDCHost is listening on. This is set to 88 by default. |
SPN | This property must be set to the SPN (Service Principal Name) of the service the user is attempting to access. |
User | This property must be set to the user attempting access to the service. |
Password | This property must be set to the password of the set user. |
After the above properties are set, Authenticate can be called to retrieve an authentication token. This token may then be used to access protected resources. Please see below for a simple example of the authentication process:
Kerberos kerberos = new Kerberos();
kerberos.KDCHost "10.0.1.226";
kerberos.User = "testuser@EXAMPLE.COM";
kerberos.Password = "testpassword";
kerberos.SPN = "ldap/ldap-server.example.com";
kerberos.Authenticate();
Console.WriteLine(kerberos.AuthToken);
Credential Cache
As an alternative to providing credentials via the User and Password properties, the component supports reading credentials from both FILE and DIR credential cache types.
To read from a FILE credential cache type, the CredentialsCacheFile configuration setting should be set to the local file containing the relevant credentials.
To read from a DIR credential cache type, the CredentialsCacheFile configuration setting should be set to the local directory containing the relevant credentials. In this case, DIR: should prefix the directory path. Please see below for an example of both cases:
Kerberos kerberos = new Kerberos();
kerberos.KDCHost "10.0.1.226";
kerberos.SPN = "ldap/ldap-server.example.com";
//kerberos.User = "testuser" // optional
// FILE
kerberos.Config("CredentialsCacheFile=C:\\CacheFile.txt");
kerberos.Authenticate();
Console.WriteLine("Token obtained from FILE: " + kerberos.AuthToken);
// DIR
kerberos.Config("CredentialsCacheFile=DIR:C:\\CacheDir\\");
kerberos.Authenticate();
Console.WriteLine("Token obtained from DIR: " + kerberos.AuthToken);
In some cases, a credential cache can contain entries for multiple users. In these cases, the User property can be set to locate the cache entry associated with the user. If User is not specified, or no user is matched, then the first entry in the cache will be used instead.
Keytab File
As an alternative to setting the Password property, the component also supports setting a keytab file via the KeytabFile property. Assuming an entry exists for the specified user and the server supports the relevant encryption type, this could look like the following:
Kerberos kerberos = new Kerberos();
kerberos.KDCHost "10.0.1.226";
kerberos.User = "testuser@EXAMPLE.COM";
kerberos.SPN = "ldap/ldap-server.example.com";
kerberos.KeytabFile = "C:\\testuser.keytab";
kerberos.Authenticate();
Console.WriteLine(kerberos.AuthToken);
Cross-Realm Authentication
In the previous examples, the user is attempting to access a service hosted within their realm. It may be that the user wishes to access a service within a separate realm. In this case, the component must be configured for cross-realm authentication.
Basic Trusts
There are a few different scenarios when performing cross-realm authentication. This depends on existing trusts between the realm of the user and the realm of the service. The most basic scenario of cross-realm authentication occurs when a user in one realm attempts to access a service in another realm, and a trust exists between said realms. To configure the component for this scenario, the following configuration settings should be set:
Config Name | Description |
---|---|
TGSRealm | This config must be set to domain or realm the SPN (or service) exists within. |
TGSKDCHost | This config must be set to the IP address of the KDC host existing within the TGSRealm. |
TGSKDCPort | This config must be set to the port the TGSKDCHost is listening on. This is set to 88 by default. |
As an example, say a user in the realm example1.com wishes to access a service in the realm example2.com. To perform cross-realm authentication, the component should be configured like so:
Kerberos kerberos = new Kerberos();
kerberos.KDCHost "10.0.1.226"; // KDC host in example1.com
kerberos.User = "testuser@EXAMPLE1.COM"; // User in example1.com
kerberos.Password = "testpassword";
kerberos.SPN = "ldap/ldap-server.example2.com"; // Service in example2.com
// Location of service
kerberos.Config("TGSRealm=example2.com");
kerberos.Config("TGSKDCHost=10.0.1.227");
kerberos.Config("TGSKDCPort=88");
kerberos.Authenticate();
Console.WriteLine(kerberos.AuthToken);
In the above case, the component will first communicate with the KDC in the local realm, example1.com. Assuming a trust is set up between example1.com and example2.com, the KDCHost will return an inter-realm trust key. Afterward, the component will authenticate with the KDC host identified by the TGS* configuration settings. If successful, the user may access the service within example2.com.
Complex Trusts
More complex cases of cross-realm authentication may arise when a direct trust is not set up between the realm of the user and the realm of the service. As an example, let's say realms example1.com, example2.com, and example3.com exist. One trust is set up between example1.com and example2.com, another between example2.com and example3.com.
A user within example1.com wishes to access a service within example3.com, however, no direct trust exists between these two realms. That said, the user may still access the service by first obtaining the credentials from example2.com. Then, using those credentials, they can then obtain the credentials from example3.com, which are necessary for accessing the service. In this case, example2.com is considered to be an intermediate realm, or a realm facilitating cross-realm authentication between a user's realm and a service's realm. A separate set of configuration settings exist to specify intermediate realms:
Config Name | Description |
---|---|
IntermediateTGSCount | This config specifies the number of intermediate realms. |
IntermediateTGSRealms[i] | This config must be set to the name of the intermediate realm. |
IntermediateTGSKDCHosts[i] | This config must be set to the IP address of the KDC host of the intermediate realm. |
IntermediateTGSKDCPorts[i] | This config must be set to the port the intermediate realm's KDC is listening on. This is set to 88 by default. |
Note that the TGS* configuration settings must be set to the realm of the SPN for cross-realm authentication to occur. For example:
Kerberos kerberos = new Kerberos();
kerberos.KDCHost "10.0.1.226"; // KDC host in example1.com
kerberos.User = "testuser@EXAMPLE1.COM"; // User in example1.com
kerberos.Password = "testpassword";
kerberos.SPN = "ldap/ldap-server.example3.com"; // Service in example3.com
// Intermediate realms
kerberos.Config("IntermediateTGSCount=1");
kerberos.Config("IntermediateTGSRealms[0]=example2.com")
kerberos.Config("IntermediateTGSKDCHosts[0]=10.0.1.227");
kerberos.Config("IntermediateTGSKDCPorts[0]=88");
// Location of service
kerberos.Config("TGSRealm=example3.com");
kerberos.Config("TGSKDCHost=10.0.1.228");
kerberos.Config("TGSKDCPort=88");
kerberos.Authenticate();
Console.WriteLine(kerberos.AuthToken);
Kerberos Configuration Files
The component supports reading various client configurations from a Kerberos configuration file (krb5.conf) as defined by MIT. To do so, the Krb5Config configuration setting should be set to the local configuration file.
When specified, the component will first attempt to resolve the default_realm entry present in the configuration file. The default realm will be used during authentication unless a domain/realm is specified in the User property. Note that in this case, the User property may be set to only a username to allow the component to use the appropriate default realm.
Assuming a default realm is found, the primary KDC associated with this realm will be used during authentication, assuming KDCHost is not specified. Additional KDCs associated with this realm will be used only if authentication with the primary KDC fails. If no KDCs are specified for a given realm, and the dns_lookup_kdc entry is set to true, the component will perform a DNS query in an attempt to resolve the realm's KDC hostnames and ports. To clarify, the component will attempt to look up the SRV records stored on the realms administration server, identified by the admin_server entry.
All additional realms found within the file will be stored as intermediate realms in the case cross-realm authentication is required.
The below example portrays the case described in the Complex Trusts section, simplified with the associated krb5.conf file.
Kerberos kerberos = new Kerberos();
kerberos.User = "testuser"; // User in example1.com
kerberos.Password = "testpassword";
kerberos.SPN = "ldap/ldap-server.example3.com"; // Service in example3.com
kerberos.Config("Krb5Config=C:\\krb5.conf"); // See below
// Location of service
kerberos.Config("TGSRealm=example3.com");
kerberos.Authenticate();
Console.WriteLine(kerberos.AuthToken);
Below is the sample krb5.conf associated with the above code.
[libdefaults]
default_realm = EXAMPLE1.COM
dns_lookup_kdc = true
[realms]
EXAMPLE1.COM = {
kdc = kdc01.example1.com
kdc = kdc02.example1.com
admin_server = example1.com
}
EXAMPLE2.COM = {
admin_server = example2.com # DNS lookup will occur here, as no KDC is defined
}
EXAMPLE3.COM = {
kdc = kdc01.example3.com
admin_server = example3.com
}
[domain_realm]
.example1.com = EXAMPLE1.COM
example1.com = EXAMPLE1.COM
.example2.com = EXAMPLE2.COM
example2.com = EXAMPLE2.COM
.example3.com = EXAMPLE3.COM
example3.com = EXAMPLE3.COM
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.