Tengo el siguiente código:

public static void main(String args[]){
    try {
        //String ticket = "Negotiate YIGCBg...==";
        //byte[] kerberosTicket = ticket.getBytes();
        byte[] kerberosTicket = Base64.decode("YIGCBg...==");
        GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null);
        context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length);
        String user = context.getSrcName().toString();
        context.dispose();
    } catch (GSSException e) {
        e.printStackTrace();
    } catch (Base64DecodingException e) {
        e.printStackTrace();
    }
}

De curso se produce un error. Aquí está la excepción:

GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)

No sé qué se supone que debo hacer para solucionar esto. Honestamente, yo no entiendo realmente Kerberos.

Tengo este billete mediante el envío de un 401 con el encabezado correspondiente WWW-Authenticate con ‘Negociar’ como el valor. El navegador de inmediato emitió la misma solicitud de nuevo con un authorization de encabezado que contiene este pasaje.

Tenía la esperanza de que yo pudiera validar el billete y determinar quién es el usuario.

Necesito un archivo keytab? Si es así, ¿qué credenciales habría de ejecutar este bajo? Estoy tratando de utilizar el vale de Kerberos para la autenticación de un sitio web. Serían las credenciales las credenciales de IIS?

Lo que me estoy perdiendo?


Actualización de 1
Desde Michael-O la respuesta, hice un poco más de googlear y encontré este artículo, lo que me llevó a este artículo.

Sobre table 3, he encontrado 1.3.6.1.5.5.2 SPNEGO.

Ahora he añadido a mis credenciales siguiendo con el ejemplo de la primer artículo. Aquí está mi código:

public static void main(String args[]){
    try {            
        Oid mechOid = new Oid("1.3.6.1.5.5.2");

        GSSManager manager = GSSManager.getInstance();

        GSSCredential myCred = manager.createCredential(null,
                GSSCredential.DEFAULT_LIFETIME,
                mechOid,
                GSSCredential.ACCEPT_ONLY);

        GSSContext context = manager.createContext(myCred);

        byte[] ticket = Base64.decode("YIGCBg...==");
        context.acceptSecContext(ticket, 0, ticket.length);
        String user = context.getSrcName().toString();
        context.dispose();
    } catch (GSSException e) {
        e.printStackTrace();
    } catch (Base64DecodingException e) {
        e.printStackTrace();
    }
}

Pero ahora el código está fallando en createCredential con este error:

GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails)

Aquí está el billete completo: YIGCBgYrBgEFBQKgeDB2oDAwLgYKKwYBBAGCNwICCgYJKoZIgvcSAQICBgkqhkiG9xIBAgIGCisGAQQBgjcCAh6iQgRATlRMTVNTUAABAAAAl7II4g4ADgAyAAAACgAKACgAAAAGAbEdAAAAD0xBUFRPUC0yNDVMSUZFQUNDT1VOVExMQw==

OriginalEl autor Josh C. | 2014-08-13

3 Comentarios

  1. 24

    La validación de un SPNEGO billete de Java es un poco complicado proceso. Aquí está un breve resumen, pero ten en cuenta que el proceso puede tener toneladas de trampas. Usted realmente necesita para entender cómo se Active Directory, Kerberos, SPNEGO, y JAAS todos funcionan para diagnosticar correctamente los problemas.

    Antes de empezar, asegúrese de que usted sabe que su reino kerberos nombre para el dominio de windows. Para los efectos de esta respuesta voy a asumir que es MIDOMINIO. Usted puede obtener el nombre de su reino mediante la ejecución de echo %userdnsdomain% de una ventana de cmd. Tenga en cuenta que kerberos es caso sensibles y el reino es casi siempre TODO en mayúsculas.

    Paso 1 – Obtener una Clave Kerberos

    A fin de que un cliente kerberos para acceder a un servicio, se solicita una entrada para el Nombre Principal de Servicio [SPN] que representa el servicio. Spn son generalmente deriva del nombre de la máquina y el tipo de servicio al que se accede (por ejemplo,HTTP/www.my-domain.com). Con el fin de validar un ticket de kerberos para un determinado SPN, debe tener un archivo keytab que contiene un secreto compartido que conocen tanto el Controlador de Dominio Kerberos [KDC] vale de Concesión de vales [VALE] servicio y el proveedor del servicio (usted).

    En términos de Active Directory, el KDC es el Controlador de Dominio, y el secreto compartido es sólo la contraseña de texto sin formato de la cuenta que posee el SPN. Un SPN puede ser poseído por un Ordenador o un objeto de Usuario en el AD.

    La forma más sencilla de configurar un SPN en el ANUNCIO si está definiendo un servicio es la instalación de un usuario basado en SPN así:

    1. Crear un unpriviledged de la cuenta de servicio en el ANUNCIO cuya contraseña no caduca por ejemplo, SVC_HTTP_MYSERVER con contraseña ReallyLongRandomPass
    2. Enlazar el servicio (SPN) para la cuenta usando el windows setspn utilidad. La mejor práctica es definir varios Spn, tanto a corto nombre y el nombre completo del host:

      setspn -U -S HTTP/[email protected] SVC_HTTP_MYSERVER
      setspn -U -S HTTP/myserver.my-domain.[email protected] SVC_HTTP_MYSERVER
    3. Generar una clave de la cuenta a través de Java ktab utilidad.

      ktab -k FILE:http_myserver.ktab -a HTTP/[email protected] ReallyLongRandomPass
      ktab -k FILE:http_myserver.ktab -a HTTP/myserver.my-domain.[email protected] ReallyLongRandomPass

    Si usted está tratando de autenticar a un pre-existentes de SPN que está enlazado a una cuenta de Equipo o a una cuenta de Usuario que no se controla, la de arriba no va a funcionar. Usted tendrá que extraer la clave de ActiveDirectory sí mismo. El Wireshark Kerberos En La Página tiene algunos buenos consejos para este.

    Paso 2 – Instalación de su krb5.conf

    En %JAVA_HOME%/jre/lib/security crear un krb5.conf que describe su dominio. Asegúrese de que el reino de definir aquí coincide con lo que la instalación para el SPN. Si usted no pone el archivo en la JVM de directorio, se puede señalar mediante el establecimiento de -Djava.security.krb5.conf=C:\path\to\krb5.conf en la línea de comandos.

    Ejemplo:

    [libdefaults]
      default_realm = MYDOMAIN
    
    [realms]
      MYDOMAIN = {
        kdc = dc1.my-domain.com
        default_domain = my-domain.com
      }
    
    [domain_realm]
      .my-domain.com = MYDOMAIN
      my-domain.com = MYDOMAIN

    Paso 3 – Configuración de inicio de sesión JAAS.conf

    Su JAAS login.conf debe definir un inicio de sesión de configuración que establece la Krb5LoginModule como un aceptor. Aquí un ejemplo en el que se supone que la clave que hemos creado anteriormente es en C:\http_myserver.ktab. Seleccione la JASS archivo de configuración mediante la configuración de -Djava.security.auth.login.config=C:\path\to\login.conf en la línea de comandos.

    http_myserver_mydomain {
      com.sun.security.auth.module.Krb5LoginModule required
      principal="HTTP/[email protected]"
      doNotPrompt="true" 
      useKeyTab="true" 
      keyTab="C:/http_myserver.ktab"
      storeKey="true"
      isInitiator="false";
    };

    Alternativamente, usted puede generar un JAAS de configuración en tiempo de ejecución, así:

    public static Configuration getJaasKrb5TicketCfg(
        final String principal, final String realm, final File keytab) {
      return new Configuration() {
        @Override
        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
          Map<String, String> options = new HashMap<String, String>();
          options.put("principal",    principal);
          options.put("keyTab",       keytab.getAbsolutePath());
          options.put("doNotPrompt", "true");
          options.put("useKeyTab",   "true");
          options.put("storeKey",    "true");
          options.put("isInitiator", "false");
    
          return new AppConfigurationEntry[] {
            new AppConfigurationEntry(
              "com.sun.security.auth.module.Krb5LoginModule",
              LoginModuleControlFlag.REQUIRED, options)
          };
        }
      };
    }

    Tendría que crear un LoginContext para esta configuración:

    LoginContext ctx = new LoginContext("doesn't matter", subject, null, 
      getJaasKrbValidationCfg("HTTP/[email protected]", "MYDOMAIN", 
        new File("C:/path/to/my.ktab")));

    Paso 4 – Aceptar el billete

    Esto es un poco improvisada, pero la idea general es definir una PriviledgedAction que realiza el SPNEGO protocolo con el billete. Observe que en este ejemplo no se compruebe que SPNEGO protocolo es completa. Por ejemplo, si el cliente solicita la autenticación del servidor, tendrá que devolver el token generado por acceptSecContext() en el encabezado de autenticación en la respuesta HTTP.

    public class Krb5TicketValidateAction implements PrivilegedExceptionAction<String> {
      public Krb5TicketValidateAction(byte[] ticket, String spn) {
        this.ticket = ticket;
        this.spn = spn;
      }
    
      @Override
      public String run() throws Exception {
        final Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
    
        GSSManager gssmgr = GSSManager.getInstance();
    
        //tell the GSSManager the Kerberos name of the service
        GSSName serviceName = gssmgr.createName(this.spn, GSSName.NT_USER_NAME);
    
        //get the service's credentials. note that this run() method was called by Subject.doAs(),
        //so the service's credentials (Service Principal Name and password) are already 
        //available in the Subject
        GSSCredential serviceCredentials = gssmgr.createCredential(serviceName,
          GSSCredential.INDEFINITE_LIFETIME, spnegoOid, GSSCredential.ACCEPT_ONLY);
    
        //create a security context for decrypting the service ticket
        GSSContext gssContext = gssmgr.createContext(serviceCredentials);
    
        //decrypt the service ticket
        System.out.println("Entering accpetSecContext...");
        gssContext.acceptSecContext(this.ticket, 0, this.ticket.length);
    
        //get the client name from the decrypted service ticket
        //note that Active Directory created the service ticket, so we can trust it
        String clientName = gssContext.getSrcName().toString();
    
        //clean up the context
        gssContext.dispose();
    
        //return the authenticated client name
        return clientName;
      }
    
      private final byte[] ticket;
      private final String spn;
    }

    A continuación, para autenticar el billete, puede hacer algo similar a la siguiente. Suponga que ticket contiene el ya-base-64-decodificado de entradas de la cabecera de autenticación. El spn debe ser derivada a partir de la Host cabecera de la petición HTTP si el formato de HTTP/<HOST>@<REALM>. E. g. si el Host encabezado fue myserver.my-domain.com luego spn debe ser HTTP/[email protected].

    También, ¿por qué la kerberos mech id "1.2.840.113554.1.2.2"? Pensé que esto era spnego.
    gracias por la información útil. Tengo una duda sobre el fragmento de código que genera el Krb de configuración, puede establecer el «reino» de la opción, pero no puedo ver esta opción en Oracle Krb5LoginModule documentación. Es este un error o de indocumentados interna’?
    estás en lo correcto. El ámbito de la propiedad es no tener ningún efecto. Creo que usted necesita para especificar reino a través de la java.security.krb5.realm sistema de propiedad, o, como en este caso, el reino puede ser derivado de la @ sintaxis en el nombre del principal.
    Tengo escribió el código, inspirado en el fragmento y que «simplemente funciona» sin el reino opción. Actualmente me ofrecen un director con un nombre completo ([email protected]). Supongo que tienes derecho sobre el dominio de ser extraído por las propiedades del sistema o principal nombre completo. Saludos
    /MTDOMAIN/MIDOMINIO/

    OriginalEl autor Dominic A.

  2. 6

    Esto no es un ticket de Kerberos, pero un SPNEGO billete. Su contexto se ha equivocado mecanismo.

    Edit: Aunque, ahora tiene la correcta mech, el cliente envía un token NTLM que el GSS-API no es capaz de procesar. Tome la Base de 64 token, decodificar a raw bytes y mostrar caracteres ASCII. Si se inicia con NTLMSSP, no va a funcionar y que se han roto Kerberos setup.

    Edit 2: Esta es su entrada:

    Esta es una envuelto NTLM token dentro de un token SPNEGO. lo que simplemente significa que Kerberos ha fallado por alguna razón, por ejemplo,

    • SPN no registrado
    • Clockskew
    • No permitido para Kerberos
    • Incorrecto registros DNS

    Mejor opción es utilizar Wireshark en el cliente para encontrar la causa raíz.

    Por favor, tenga en cuenta que Java hace no apoyo NTLM como un SPNEGO submechanism. NTLM sólo es compatible con SSPI y Heimdal.

    Puedes publicar de todo el boleto?
    ver mi segunda edición.
    Así que, me puse este boleto por ver el tráfico http para un sitio de trabajo que está utilizando la Autenticación de Windows en IIS. Yo no especificar mi WWW-Authenticate el valor del encabezado. Es Negotiate. Habría que hacer una diferencia? De nuevo, estoy tratando de utilizar un sitio de trabajo como un ejemplo y la ingeniería inversa de este para trabajar con open-source de tecnología.
    no es posible lo que usted está tratando. Respecto de lo que el JGSS es capaz de, usted no puede descifrar el billete sin las credenciales del aceptor, que es la máquina y no a usted.
    Permítanos continuar esta discusión en el chat.

    OriginalEl autor Michael-O

  3. 1

    Si el servidor no tiene una clave y la clave asociada a la registrada el KDC, usted nunca será capaz de utilizar kerberos para validar un boleto.

    Llegar SPNEGO al trabajo es difícil en el mejor y va a ser casi imposible sin al menos un entendimiento superficial de cómo funciona kerberos. Trate de leer este cuadro de diálogo y ver si usted puede conseguir una mejor comprensión.

    http://web.mit.edu/kerberos/dialogue.html

    SPNEGO requiere un SPN de la forma de HTTP/servidor.ejemplo.com y tendrás que decirle a la GSS bibliotecas que lo que keytab es cuando se inicia el servidor.

    Me estoy quedando esta en localhost. Cómo puedo saber si tiene un archivo de clave o de donde es?
    Si no sabes donde es probable que no la tienen. Keytabs para SPNEGO no se instalan por defecto. Usted puede utilizar ktutil a mirar en /etc/krb5.keytab, pero eso es sólo una conjetura.
    Tengo un .Net sitio que admite la Autenticación de Windows. Cuando me tire de la fuente y de depuración a nivel local, funciona correctamente. Ahora, estoy tratando de hacer la misma cosa fuera de .Net. Hay un «defecto» archivo keytab que las aplicaciones pueden compartir?
    Lo siento, no una pista. Yo sólo sé acerca de estas cosas de la Unix/Apache lado de las cosas.

    OriginalEl autor Fred the Magic Wonder Dog

Dejar respuesta

Please enter your comment!
Please enter your name here