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

时间:2009-01-12 10:56:17

标签: java kerberos gssapi

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

这个事实
  1. 客户端和服务器应用程序在同一台机器(localhost)和/或
  2. 上运行
  3. 为另一台计算机(计算机)生成SPN
  4. 第二个意味着为机器xxx0815.domain.net生成服务主体,因此SPN是HTTP / xxx0815.domain.net@DOMAIN.NET。我的机器不是那个,但我有keytab文件,以便服务器的登录方法成功。

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

    服务器配置和源代码:
    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(省略了样板文件)

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

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

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

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

    我得到的例外:

    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 个答案:

答案 0 :(得分:1)

如果完整性检查失败,则表明数据未正确发送/接收(或者这是错误的错误消息)。换句话说,已经发生了一些修改。

我知道您说您已经检查过发送的数据是否与网络级别的接收数据匹配,但是您确定它在发送之前或收到之后没有损坏吗?我建议你先查看你的代码。

编辑:在回答您的问题时,可以将服务主体(实际上是任何故障单)绑定到特定计算机,但这通常是根据IP地址完成的。在任何情况下,这样的事情都会导致不同的更高级错误。

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