¿Alguien sabe cómo conseguir un vale de servicio desde el Centro de Distribución de Claves (KDC) mediante el Java GSS-API?

Tengo un cliente grueso de la aplicación que se autentica por primera vez a través de JAAS el uso de la Krb5LoginModule para ir a buscar el TGT de la caché de ticket (de fondo: por ejemplo, Windows utiliza una implementación de kerberos y almacena el vale de concesión de vales la seguridad en la zona de la memoria). A partir de los roles loginmanager puedo conseguir el Tema objeto que contiene la TGT. Ahora me espera cuando me de crear una específica GSSCredential objeto de mi servicio, los boletos se pondrán en el Sujeto privado de credenciales (he leído en algún lugar en la web). Así que he intentado lo siguiente:

//Exception handling ommitted
LoginContext lc = new LoginContext("HelloEjbClient", new DialogCallbackHandler());
lc.login()
Subject.doAs(lc.getSubject(), new PrivilegedAction() {

    public Object run() {
        GSSManager manager = GSSManager.getInstance();
        GSSName clientName = manager.createName("clientUser", GSSName.NT_USER_NAME);
        GSSCredential clientCreds = manager.createCredential(clientName, 8 * 3600, createKerberosOid(), GSSCredential.INITIATE_ONLY);

        GSSName serverName = manager.createName("[email protected]", GSSName.NT_HOSTBASED_SERVICE);
        manager.createCredential(serverName, GSSCredential.INDEFINITE_LIFETIME, createKerberosOid(), GSSCredential.INITIATE_ONLY);
        return null;
    }

    private Oid createKerberosOid() {
        return new Oid("1.2.840.113554.1.2.2");
    }

});

Por desgracia tengo un GSSException: No válido con las credenciales proporcionadas (Mecanismo de nivel: no se pudo encontrar ningún Kerberos tgt).

OriginalEl autor Roland Schneider | 2008-12-16

2 Comentarios

  1. 16

    Mi comprensión de conseguir el boleto del servicio fue malo. No necesito para obtener las credenciales del servicio – esto no es posible en el cliente, porque el cliente no tiene realmente un TGT para el servidor y por lo tanto no tiene los derechos para recibir el servicio de credenciales.
    Lo que sólo falta aquí es crear una nueva GSSContext y para inicializarlo. El valor devuelto por este método contiene el vale de servicio, si he entendido correctamente. Aquí es un ejemplo de código. Se debe ejecutar en un PrivilegedAction en nombre de un iniciado en el tema:

        GSSManager manager = GSSManager.getInstance();
        GSSName clientName = manager.createName("clientUser", GSSName.NT_USER_NAME);
        GSSCredential clientCred = manager.createCredential(clientName,
                                                            8 * 3600,
                                                            createKerberosOid(),
                                                            GSSCredential.INITIATE_ONLY);
    
        GSSName serverName = manager.createName("[email protected]", GSSName.NT_HOSTBASED_SERVICE);
    
        GSSContext context = manager.createContext(serverName,
                                                   createKerberosOid(),
                                                   clientCred,
                                                   GSSContext.DEFAULT_LIFETIME);
        context.requestMutualAuth(true);
        context.requestConf(false);
        context.requestInteg(true);
    
        byte[] outToken = context.initSecContext(new byte[0], 0, 0);
        System.out.println(new BASE64Encoder().encode(outToken));
        context.dispose();

    La outToken contiene contiene el vale de Servicio. Sin embargo, esta no es la forma en que el GSS-API estaba destinado a ser usado. Su objetivo era ocultar los detalles para el código, así que es mejor establecer un GSSContext el uso de la GSS-API en ambos lados. De lo contrario, usted debe saber lo que está haciendo, debido a los posibles agujeros de seguridad.
    Para más información lea el Sol SSO tutorial con kerberos más cuidadosamente de lo que hice.

    EDITAR:
    Sólo se olvidó de que yo estoy usando Windows XP con SP2. Hay una nueva «característica» en esta versión de Windows que no permite el uso de la TGT en la RAM de Windows. Tienes que editar el registro para permitir esto. Para obtener más información, eche un vistazo a la JGSS página de Solución de problemas tema en caso de que la experiencia de un «KrbException: KDC no tiene soporte para el tipo de cifrado (14)» como yo lo hice.

    Gracias por su contribución. Como usted puede ver, esto lo escribí hace bastante tiempo, así que no recuerdo los detalles exactos, pero estoy bastante seguro de que esto solo significaba como un ejemplo. Qué crees que puede hacer para mejorar esta respuesta?
    compruebe el enlace al Sol SSO tutorial con kerberos y tener una mirada en la figura 6. No es el lazo que escribió acerca de.
    Yo creo que no incluyen el bucle porque yo no podía entender lo que el readToken() y sendToken(…) los métodos se supone que deben hacer.
    en el caso de HTTP readToken solicitud de una respuesta HTTP y extrae el token, sendToken realiza el contrario.

    OriginalEl autor Roland Schneider

  2. 9

    Yo tenía un montón de problemas para utilizar este código, pero tengo al menos una solución. He puesto aquí, tal vez esto ayude a algunos de ustedes…

    /**
    * Tool to retrieve a kerberos ticket. This one will not be stored in the windows ticket cache.
    */
    public final class KerberosTicketRetriever
    {
    private final static Oid KERB_V5_OID;
    private final static Oid KRB5_PRINCIPAL_NAME_OID;
    static {
    try
    {
    KERB_V5_OID = new Oid("1.2.840.113554.1.2.2");
    KRB5_PRINCIPAL_NAME_OID = new Oid("1.2.840.113554.1.2.2.1");
    } catch (final GSSException ex)
    {
    throw new Error(ex);
    }
    }
    /**
    * Not to be instanciated
    */
    private KerberosTicketRetriever() {};
    /**
    *
    */
    private static class TicketCreatorAction implements PrivilegedAction
    {
    final String userPrincipal;
    final String applicationPrincipal;
    private StringBuffer outputBuffer;
    /**
    *
    * @param userPrincipal  p.ex. <tt>[email protected]</tt>
    * @param applicationPrincipal  p.ex. <tt>HTTP/webserver.myfirm.com</tt>
    */
    private TicketCreatorAction(final String userPrincipal, final String applicationPrincipal)
    {
    this.userPrincipal = userPrincipal;
    this.applicationPrincipal = applicationPrincipal;
    }
    private void setOutputBuffer(final StringBuffer newOutputBuffer)
    {
    outputBuffer = newOutputBuffer;
    }
    /**
    * Only calls {@link #createTicket()}
    * @return <tt>null</tt>
    */
    public Object run()
    {
    try
    {
    createTicket();
    }
    catch (final GSSException  ex)
    {
    throw new Error(ex);
    }
    return null;
    }
    /**
    *
    * @throws GSSException
    */
    private void createTicket () throws GSSException
    {
    final GSSManager manager = GSSManager.getInstance();
    final GSSName clientName = manager.createName(userPrincipal, KRB5_PRINCIPAL_NAME_OID);
    final GSSCredential clientCred = manager.createCredential(clientName,
    8 * 3600,
    KERB_V5_OID,
    GSSCredential.INITIATE_ONLY);
    final GSSName serverName = manager.createName(applicationPrincipal, KRB5_PRINCIPAL_NAME_OID);
    final GSSContext context = manager.createContext(serverName,
    KERB_V5_OID,
    clientCred,
    GSSContext.DEFAULT_LIFETIME);
    context.requestMutualAuth(true);
    context.requestConf(false);
    context.requestInteg(true);
    final byte[] outToken = context.initSecContext(new byte[0], 0, 0);
    if (outputBuffer !=null)
    {
    outputBuffer.append(String.format("Src Name: %s\n", context.getSrcName()));
    outputBuffer.append(String.format("Target  : %s\n", context.getTargName()));
    outputBuffer.append(new BASE64Encoder().encode(outToken));
    outputBuffer.append("\n");
    }
    context.dispose();
    }
    }
    /**
    *
    * @param realm p.ex. <tt>MYFIRM.COM</tt>
    * @param kdc p.ex. <tt>kerbserver.myfirm.com</tt>
    * @param applicationPrincipal   cf. {@link #TicketCreatorAction(String, String)}
    * @throws GSSException
    * @throws LoginException
    */
    static public String retrieveTicket(
    final String realm,
    final String kdc,
    final String applicationPrincipal)
    throws GSSException, LoginException
    {
    //create the jass-config-file
    final File jaasConfFile;
    try
    {
    jaasConfFile = File.createTempFile("jaas.conf", null);
    final PrintStream bos = new PrintStream(new FileOutputStream(jaasConfFile));
    bos.print(String.format(
    "Krb5LoginContext { com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useTicketCache=true debug=true ; };"
    ));
    bos.close();
    jaasConfFile.deleteOnExit();
    }
    catch (final IOException ex)
    {
    throw new IOError(ex);
    }
    //set the properties
    System.setProperty("java.security.krb5.realm", realm);
    System.setProperty("java.security.krb5.kdc", kdc);
    System.setProperty("java.security.auth.login.config",jaasConfFile.getAbsolutePath());
    //get the Subject(), i.e. the current user under Windows
    final Subject subject = new Subject();
    final LoginContext lc = new LoginContext("Krb5LoginContext", subject, new DialogCallbackHandler());
    lc.login();
    //extract our principal
    final Set<Principal> principalSet = subject.getPrincipals();
    if (principalSet.size() != 1)
    throw new AssertionError("No or several principals: " + principalSet);
    final Principal userPrincipal = principalSet.iterator().next();
    //now try to execute the SampleAction as the authenticated Subject
    //action.run() without doAsPrivileged leads to
    //  No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
    final TicketCreatorAction action = new TicketCreatorAction(userPrincipal.getName(), applicationPrincipal);
    final StringBuffer outputBuffer = new StringBuffer();
    action.setOutputBuffer(outputBuffer);
    Subject.doAsPrivileged(lc.getSubject(), action, null);
    return outputBuffer.toString();
    }
    public static void main (final String args[]) throws Throwable
    {
    final String ticket = retrieveTicket("MYFIRM.COM", "kerbserver", "HTTP/webserver.myfirm.com");
    System.out.println(ticket);
    }
    }

    OriginalEl autor Olivier Faucheux

Dejar respuesta

Please enter your comment!
Please enter your name here