views:

1169

answers:

1

At the moment I am getting a KrbException: Integrity check on decrypted field failed (31) with my GSS demo application (on the server side). Now I am looking for the reason for this. I have the suspicion, that it comes from the fact that

  1. the client and the server application run on the same machine (localhost) and/or
  2. the SPN was generated for another machine (computer)

The second means that the service principal was generated for a machine xxx0815.domain.net, so the SPN is HTTP/[email protected]. And my machine is not that one, but I have got the keytab file so that the server's login method succeeds.

Do I suspect correctly or am I making another mistake?

Server configuration and source code:
server.conf

Server { 
    com.sun.security.auth.module.Krb5LoginModule 
        required 
        isInitiator=false 
        doNotPrompt=true 
        useKeyTab=true 
        keyTab="gssdemo.keytab" 
        storeKey=true 
        principal="HTTP/[email protected]" 
        debug=true; 
};

GSSServer.java (omitted the boilerplate stuff)

    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();

Client configuration and source code:
client.conf

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

GssClient.java (boilerplate omitted)

    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/[email protected]", 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();

I have checked the outgoing and incoming network data - it's the same on both sides so I can rule out a problem there (I have BASE64-encoded the output and then just send it through the streams. I think there is not much that can go wrong there...).

The exception I get:

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
+1  A: 

If the integrity check fails that suggests that the data is not being sent / received correctly (that or this is an incorrect error message). In other words some modification has occurred.

I know you say you have checked that the sent data matches the received data at the network level, however are you sure it is not corrupted prior to send, or after receipt? I would suggest you review your code for this first.

edit: In answer to your question, a service principal (really, any ticket) can be bound to a specific machine, but this is normally done in terms of IP address. In any case something like that should result in a different higher level error.

The error you're getting sounds like it is having trouble decrypting the ticket in the first place. A possible cause of that is that it is using the wrong key, which may be related to your copying the keytab. A wrong key can also be caused by using the wrong ticket (as kerberos basically provides a key management protocol). Is it possible you have cached an old/incorrect ticket?

frankodwyer
I edited the part with the data check - I'm afraid there is not much that can go wrong there. Nevertheless I double check this. But I guess it's going into the keytab/keys direction...
Roland Schneider
Yes, in that case it sounds like there is some mismatch at the ticket/configuration level which is stopping Kerberos coming up with the right key to decrypt the ticket. Judging by the stack trace this seems to be happening before it even gets to interpret the ticket.
frankodwyer
I am going to accept this answer because it really was a problem with the key/keytab file.
Roland Schneider
@Roland - Do you remember how you fixed it? I'm currently getting "Integrity check on decrypted field failed (31)" and try as I might, I can't find a way to construct a fully working keytab file.
Alohci
If I remember correctly there was indeed a problem with the server keytab. I didn't create the keytab file myself and I didn't have control over the kdc. However the SPN/Key I tried to use seemed to be out of sync (keytab and kdc). After requesting a new SPN the problem disappeared. It could also have something to do with the encryption algorithms used when creating the key. I think the key I had was created using some DES algorithm only.Hope it helps.
Roland Schneider