Привязано ли имя участника-службы (SPN) к конкретному компьютеру?

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

  1. клиентское и серверное приложения работают на одном компьютере (localhost) и/или
  2. имя участника-службы было создано для другой машины (компьютера)

Второе означает, что субъект-служба был создан для машины xxx0815.domain.net, поэтому имя участника-службы — HTTP/[email protected]. И моя машина не та, но у меня есть файл keytab, чтобы метод входа на сервер прошел успешно.

Правильно ли я подозреваю или совершаю очередную ошибку?

Конфигурация сервера и исходный код:
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 (опущен шаблонный материал)

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

Я проверил исходящие и входящие сетевые данные - они одинаковы с обеих сторон, поэтому я могу исключить проблему там (у меня есть 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

person Roland Schneider    schedule 12.01.2009    source источник


Ответы (1)


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

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

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

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

person frankodwyer    schedule 12.01.2009
comment
Отредактировал часть с проверкой данных - боюсь там мало что может пойти не так. Тем не менее, я дважды проверяю это. Но я предполагаю, что это идет в направлении keytab/keys... - person Roland Schneider; 12.01.2009
comment
Да, в этом случае похоже, что есть какое-то несоответствие на уровне билета/конфигурации, которое мешает Kerberos найти правильный ключ для расшифровки билета. Судя по трассировке стека, это происходит еще до того, как он интерпретирует билет. - person frankodwyer; 12.01.2009
comment
Я собираюсь принять этот ответ, потому что это действительно была проблема с файлом key/keytab. - person Roland Schneider; 27.01.2009
comment
@Roland - Ты помнишь, как ты это исправил? В настоящее время я получаю проверку целостности в расшифрованном поле с ошибкой (31), и, как я ни пытался, я не могу найти способ создать полностью рабочий файл keytab. - person Alohci; 15.06.2010
comment
Если я правильно помню, действительно была проблема с таблицей ключей сервера. Я не создавал файл keytab сам и не имел контроля над kdc. Однако SPN/ключ, который я пытался использовать, оказался не синхронизированным (keytab и kdc). После запроса нового SPN проблема исчезла. Это также может быть связано с алгоритмами шифрования, используемыми при создании ключа. Я думаю, что ключ, который у меня был, был создан только с использованием какого-то алгоритма DES. Надеюсь, поможет. - person Roland Schneider; 22.06.2010