¿Un nombre principal de servicio (SPN) está vinculado a una máquina específica?

StackOverflow https://stackoverflow.com/questions/435091

  •  10-07-2019
  •  | 
  •  

Pregunta

En este momento recibo una KrbException: la comprobación de integridad en el campo descifrado falló (31) con mi aplicación de demostración GSS (en el lado del servidor). Ahora estoy buscando la razón de esto. Tengo la sospecha de que proviene del hecho de que

  1. el cliente y la aplicación del servidor se ejecutan en la misma máquina (localhost) y / o
  2. el SPN se generó para otra máquina (computadora)

El segundo significa que el principal de servicio se generó para una máquina xxx0815.domain.net, por lo que el SPN es HTTP/xxx0815.domain.net@DOMAIN.NET. Y mi máquina no es esa, pero tengo el archivo de tabla de claves para que el método de inicio de sesión del servidor tenga éxito.

¿Sospecho correctamente o estoy cometiendo otro error?

Configuración del servidor y código fuente:
server.conf

Server { 
    com.sun.security.auth.module.Krb5LoginModule 
        required 
        isInitiator=false 
        doNotPrompt=true 
        useKeyTab=true 
        keyTab="gssdemo.keytab" 
        storeKey=true 
        principal="HTTP/xxx0815.domain.net@DOMAIN.NET" 
        debug=true; 
};

GSSServer.java (se omitieron las cosas repetitivas)

    GSSManager manager = GSSManager.getInstance();
    GSSName serverName = manager.createName(getServerName(), null);
    GSSCredential serverCred = manager.createCredential(serverName,
                                                        GSSCredential.INDEFINITE_LIFETIME,
                                                        createKerberosOid(),
                                                        GSSCredential.ACCEPT_ONLY);
    GSSContext context = manager.createContext(serverCred);
    System.out.println("Context created successfully. Now incoming tokens could be accepted.");

    ServerSocket serverSocket = new ServerSocket(55555);
    SocketAdapter ca = new SocketAdapter(serverSocket.accept());

    while (!context.isEstablished()) {
        byte[] inToken = ca.readToken();
        byte[] outToken = context.acceptSecContext(inToken, 0, inToken.length);

        if (outToken != null) {
            ca.sendToken(outToken);
        }
    }

    System.out.println("Context established");
    System.out.println("Connected user is: " + context.getSrcName());
    context.dispose();

Configuración del cliente y código fuente:
client.conf

Client {
    com.sun.security.auth.module.Krb5LoginModule
        required
        useTicketCache=true
        debug=true;
};

GssClient.java (repetitivo omitido)

    GSSManager manager = GSSManager.getInstance();
    GSSName clientName = manager.createName(getClientName(), null);
    GSSCredential clientCred = manager.createCredential(clientName,
                                                        8 * 3600,
                                                        createKerberosOid(),
                                                        GSSCredential.INITIATE_ONLY);
    GSSName serviceName = manager.createName("HTTP/xxx0815.domain.net@DOMAIN.NET", null);

    GSSContext context = manager.createContext(serviceName,
                                               createKerberosOid(),
                                               clientCred,
                                               GSSContext.DEFAULT_LIFETIME);
    context.requestMutualAuth(true);
    context.requestConf(false);
    context.requestInteg(true);

    System.out.println("Establishing context");
    SocketAdapter ca = new SocketAdapter(new Socket("localhost", 55555));

    byte[] inToken = new byte[0];
    while (true) {
        byte[] outToken = context.initSecContext(inToken, 0, inToken.length);

        if (outToken != null) {
            ca.sendToken(outToken);
        }

        if (context.isEstablished()) {
            break;
        }

        inToken = ca.readToken();
    }

    System.out.println("Context established: " + context.isEstablished());

    context.dispose();

He verificado los datos de la red entrante y saliente: es lo mismo en ambos lados, así que puedo descartar un problema allí (codifiqué BASE64 en la salida y luego la envié a través de las secuencias. Creo que no hay mucho eso puede salir mal allí ...).

La excepción que obtengo:

Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Integrity check on decrypted field failed (31))
    at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:741)
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:323)
    at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267)
    at de.westlb.mrm.sandbox.gss.GssServer.acceptAndEstablish(GssServer.java:88)
    at de.westlb.mrm.sandbox.gss.GssServer.run(GssServer.java:66)
    ... 4 more
Caused by: KrbException: Integrity check on decrypted field failed (31)
    at sun.security.krb5.internal.crypto.DesCbcEType.decrypt(DesCbcEType.java:154)
    at sun.security.krb5.internal.crypto.DesCbcMd5EType.decrypt(DesCbcMd5EType.java:33)
    at sun.security.krb5.internal.crypto.DesCbcEType.decrypt(DesCbcEType.java:125)
    at sun.security.krb5.internal.crypto.DesCbcMd5EType.decrypt(DesCbcMd5EType.java:33)
    at sun.security.krb5.EncryptedData.decrypt(EncryptedData.java:168)
    at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:267)
    at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:134)
    at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:79)
    at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:724)
    ... 8 more
¿Fue útil?

Solución

Si la comprobación de integridad falla, eso sugiere que los datos no se están enviando / recibiendo correctamente (eso o esto es un mensaje de error incorrecto). En otras palabras, se ha producido alguna modificación.

Sé que dice que ha verificado que los datos enviados coinciden con los datos recibidos a nivel de red, sin embargo, ¿está seguro de que no están dañados antes del envío o después de la recepción? Te sugiero que revises tu código para esto primero.

editar: en respuesta a su pregunta, un director de servicio (realmente, cualquier ticket) puede estar vinculado a una máquina específica, pero esto normalmente se hace en términos de dirección IP. En cualquier caso, algo así debería dar como resultado un error de nivel superior diferente.

El error que está recibiendo parece que está teniendo problemas para descifrar el ticket en primer lugar. Una posible causa de eso es que está usando la clave incorrecta, lo que puede estar relacionado con la copia de la tabla de claves. Una clave incorrecta también puede ser causada al usar el ticket incorrecto (ya que kerberos básicamente proporciona un protocolo de administración de claves). ¿Es posible que haya almacenado en caché un ticket antiguo / incorrecto?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top