服务主体名称(SPN)是否绑定到特定计算机?

时间:2022-10-18 20:45:19

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

目前我收到KrbException:使用我的GSS演示应用程序(在服务器端)对解密字段的完整性检查失败(31)。现在我正在寻找原因。我有怀疑,它来自于这个事实

  1. the client and the server application run on the same machine (localhost) and/or
  2. 客户端和服务器应用程序在同一台机器(localhost)上运行和/或

  3. the SPN was generated for another machine (computer)
  4. SPN是为另一台机器(计算机)生成的

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

第二个意味着为机器xxx0815.domain.net生成了服务主体,因此SPN是HTTP /xxx0815.domain.net@DOMAIN.NET。我的机器不是那个,但我有keytab文件,以便服务器的登录方法成功。

Do I suspect correctly or am I making another mistake?

我怀疑是正确还是我犯了另一个错误?

Server configuration and source code:
server.conf

服务器配置和源代码: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 (omitted the boilerplate stuff)

GSSServer.java(省略了样板文件)

    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.conf

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

GssClient.java (boilerplate omitted)

GssClient.java(省略了样板)

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

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...).

我检查了传出和传入的网络数据 - 两边都是一样的,所以我可以排除那里的问题(我有BASE64编码输出然后只是通过流发送它。我认为没有太多可以去那里错了...)。

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 个解决方案

#1


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.

编辑:在回答您的问题时,服务主体(实际上是任何票证)可以绑定到特定的机器,但这通常是根据IP地址完成的。在任何情况下,类似的东西都会导致更高级别的错误。

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?

您收到的错误听起来像是在首先解密票证时遇到问题。可能的原因是它使用了错误的密钥,这可能与您复制密钥表有关。使用错误的票证也可能导致错误的密钥(因为kerberos基本上提供密钥管理协议)。您是否有可能缓存旧的/不正确的票证?

#1


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.

编辑:在回答您的问题时,服务主体(实际上是任何票证)可以绑定到特定的机器,但这通常是根据IP地址完成的。在任何情况下,类似的东西都会导致更高级别的错误。

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?

您收到的错误听起来像是在首先解密票证时遇到问题。可能的原因是它使用了错误的密钥,这可能与您复制密钥表有关。使用错误的票证也可能导致错误的密钥(因为kerberos基本上提供密钥管理协议)。您是否有可能缓存旧的/不正确的票证?