Связано ли имя участника-службы (SPN) с конкретной машиной?

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

  •  10-07-2019
  •  | 
  •  

Вопрос

В настоящее время я получаю KrbException: проверка целостности дешифрованного поля завершилась неудачно (31) с моим демонстрационным приложением GSS (на стороне сервера). Сейчас я ищу причину для этого. У меня есть подозрение, что это связано с тем, что

<Ол>
  • клиент и серверное приложение работают на одном компьютере (localhost) и / или
  • имя участника-службы было создано для другого компьютера (компьютера)
  • Второй означает, что субъект службы был создан для машины xxx0815.domain.net, поэтому имя участника-службы является 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
    
    Это было полезно?

    Решение

    Если проверка целостности завершается неудачно, это говорит о том, что данные отправляются / не принимаются правильно (это неверное сообщение об ошибке). Другими словами, произошли некоторые изменения.

    Я знаю, что вы сказали, что проверили, что отправленные данные соответствуют полученным данным на сетевом уровне, однако вы уверены, что они не повреждены до отправки или после получения? Я бы посоветовал вам сначала проверить свой код.

    edit: в ответ на ваш вопрос, участник службы (на самом деле, любой билет) может быть привязан к конкретной машине, но обычно это делается с точки зрения IP-адреса. В любом случае что-то подобное должно привести к другой ошибке более высокого уровня.

    Ошибка, которую вы получаете, звучит так, будто сначала возникла проблема с расшифровкой билета. Возможная причина этого заключается в том, что он использует неправильный ключ, что может быть связано с копированием таблицы ключей. Неправильный ключ также может быть вызван использованием неправильного билета (поскольку Kerberos в основном предоставляет протокол управления ключами). Возможно, вы кэшировали старый / неправильный билет?

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top