Quiero leer el nombre de usuario del ticket de Kerberos en la cabecera HTTP de Autorización. Estoy usando Java.

He pasado días tratando de lograr esto por medio de la lectura a través de un montón de sitios sobre el tema, pero no han sido capaces de hacer esto. Kerberos es nuevo/extraño para mí.

Esto es lo que he conseguido:

  • Que cuando un usuario accede al sitio sin la Autorización de cabecera, el servidor responde con 401 + encabezado WWW-Authenticate=Negociar.
  • Todo tipo de cosas mágicas suceden en el lado del cliente.
  • Usuario regresa con una petición HTTP que contiene el encabezado de Autorización con un valor como: «Negociar YHcGB…==»
  • Decodificación base64 billete a una matriz de bytes.

De aquí en adelante es un aterrador viaje a través de lo desconocido. Por lo que puedo contar, los siguientes pasos deben ser:

  • De inicio de sesión a la AD/Kerberos/Servidor con un usuario.
  • Decodificar el billete.

Esto es lo que tengo:

de inicio de sesión.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;
}

El inicio de sesión en JavaClass.java funciona ok, así que estoy asumiendo que el inicio de sesión.conf está bien. En «GSSCredential serviceCredentials = gssManager.createCredential(…» en el ServiceTicketDecoder.java se produce la excepción siguiente:

java.security.PrivilegedActionException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)

No estoy seguro de si este es el enfoque correcto. Yo tampoco sé cuál es el valor de la «Cadena de servicio» debe ser o cómo obtener esa información. Me pueden ayudar?


EDITAR:
de inicio de sesión.conf

 ServicePrincipalLoginContext
{
      com.sun.security.auth.module.Krb5LoginModule 
      required 
      principal="HTTP/[email protected]" 
      doNotPrompt=true
      useTicketCache=true
      keyTab="C:/server-http.keytab" 
      debug=true;
};

He recibido un archivo keytab. Al parecer, el HTTP/algunos.servidor.com de la cuenta del usuario ya era un principal de servicio de la cuenta. Ahora tengo un problema en JavaClass.java en 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)

El archivo keytab está cifrado con des-cbc-md5 y tengo el siguiente define en el krb.conf archivo:

[libdefaults]
default_realm = MY.DOMAIN.COM
default_tkt_enctypes = des-cbc-md5
default_tgs_enctypes = des-cbc-md5

Si puedo cambiar el valor predeterminado enctypes, por ejemplo, aes128-cts, tengo la siguiente excepción:

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

No entiendo lo que está mal…

OriginalEl autor user1982861 | 2013-01-16

2 Comentarios

  1. 4

    Kerberos es un de terceros de confianza sistema de seguridad: el token de seguridad que usted recibe del cliente es decryptable sólo por usted, y sin entrar en contacto con cualquier Kerberos servidores de infraestructura (tales como el KDC). Usted está en el camino correcto; sin embargo, parece que te falta esta pieza de fondo de Kerberos conocimiento para guiar a usted en su investigación.

    La forma de lograrlo es que en el servidor necesita un keytab archivo que contiene el servidor de la clave secreta. El servidor Kerberos (Microsoft Windows Server, supongo) debe tener un principal de servicio de la cuenta creado para su servicio. Un administrador puede suministrar con el archivo de clave generada para esta cuenta, que contendrá la clave secreta.

    A continuación, debe configurar el servidor para encontrar este archivo keytab; se utiliza en el lado del servidor paso de LoginContext.login. El código que acepta el contexto de seguridad debe ser ejecutado dentro de un doPrivileged segmento de código dentro de la cual su servidor-lado credenciales están en efecto.

    La clave no debe DES de uso y, al parecer, el KDC se configura que no lo apoyan. Esta es una opción configurable en el Servicio de la Cuenta Principal para la compatibilidad con servidores que no soportan los modernos estándares de encriptación. Es el llamado «Uso de cifrado DES» o similar, y debe ser desactivada. Después de que una nueva clave debe ser generado.
    Cambiar el cifrado de la clave se ha solucionado el problema y todo funciona ahora. Gracias!!

    OriginalEl autor Marko Topolnik

Dejar respuesta

Please enter your comment!
Please enter your name here