I want to read the user's name from the Kerberos ticket in the Authorization HTTP header. I am using Java.
I have spent days trying to achieve this by reading through a bunch of sites on the subject but have not been able to do this. Kerberos is new/foreign to me.
This is what I've achieved:
From here on it's a terrifying journey through the unknown. As far as I can tell, the next steps should be:
This is what I have:
login.conf
ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/[email protected]"
doNotPrompt=true
useTicketCache=true
password=mYpasSword
debug=true;
};
JavaClass.java
String encodedTicket = authorization.substring("Negotiate ".length());
byte[] ticket = Base64.decode(encodedTicket);
LoginContext lc = new LoginContext("ServicePrincipalLoginContext");
lc.login();
Subject serviceSubject = lc.getSubject();
Subject.doAs(serviceSubject, new ServiceTicketDecoder(ticket));
ServiceTicketDecoder.java
public String run() throws Exception {
Oid kerberos5Oid = new Oid("1.2.840.113554.1.2.2");
GSSManager gssManager = GSSManager.getInstance();
String service = "krbtgt/[email protected]";
GSSName serviceName = gssManager.createName(service, GSSName.NT_USER_NAME);
GSSCredential serviceCredentials = gssManager.createCredential(serviceName, GSSCredential.INDEFINITE_LIFETIME, kerberos5Oid, GSSCredential.ACCEPT_ONLY);
GSSContext gssContext = gssManager.createContext(serviceCredentials);
gssContext.acceptSecContext(this.serviceTicket, 0, this.serviceTicket.length);
GSSName srcName = gssContext.getSrcName();
return srcName.toString;
}
The login in JavaClass.java works ok, so I'm assuming the login.conf is ok. On "GSSCredential serviceCredentials = gssManager.createCredential(..." in the ServiceTicketDecoder.java the following exception is thrown:
java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)
I am not sure if this is the right approach. I also don't know what the value of the "String service" should be or how to get that information. Can you help me?
EDIT: login.conf
ServicePrincipalLoginContext
{
com.sun.security.auth.module.Krb5LoginModule
required
principal="HTTP/[email protected]"
doNotPrompt=true
useTicketCache=true
keyTab="C:/server-http.keytab"
debug=true;
};
I have received a keytab file. Apparently the HTTP/some.server.com user's account was already a service principal account. I now have a problem on JavaClass.java at lc.login():
javax.security.auth.login.LoginException: KDC has no support for encryption type (14)
Caused by: KrbException: KDC has no support for encryption type (14)
Caused by: KrbException: Identifier doesn't match expected value (906)
The keytab file is encrypted with des-cbc-md5 and I have the following defined in the krb.conf file:
[libdefaults]
default_realm = MY.DOMAIN.COM
default_tkt_enctypes = des-cbc-md5
default_tgs_enctypes = des-cbc-md5
If I change the default enctypes to e.g. aes128-cts, I get the following exception:
javax.security.auth.login.LoginException: Do not have keys of types listed in default_tkt_enctypes available; only have keys of following type: DES CBC mode with MD5
I don't understand what is wrong...
Among other information, the ticket contains the random session key that will be used for authentication of the principal to the verifier, the name of the principal to whom the session key was issued, and an expiration time after which the session key is no longer valid.
To view or delete Kerberos tickets you can use the Kerberos List (Klist.exe). The Klist.exe is a command-line tool you can find in the Kerberos resource kit. You can only use it to check and delete tickets from the current logon session.
Kerberos is a computer network security protocol that authenticates service requests between two or more trusted hosts across an untrusted network, like the internet. It uses secret-key cryptography and a trusted third party for authenticating client-server applications and verifying users' identities.
Kerberos is a trusted third-party security system: the security token you receive from the client is decryptable only by you, and without contacting any Kerberos infrastructure servers (such as the KDC). You are on the right track; however, it appears you are missing this piece of background Kerberos knowledge to guide you in your further research.
The way this is achieved is that on the server you need a keytab file that contains your server's secret key. The Kerberos server (Microsoft Windows Server, I presume) must have a service principal account created for your service. An administrator can supply you with the keytab file generated for this account, which will contain the secret key.
You then need to configure the server to find this keytab file; it is used in the server-side step involving LoginContext.login
. Your code that accepts the security context must be executed inside a doPrivileged
code segment within which your server-side credentials are in effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With