От Java-6 до Java-7 Kerberos - изменение поведения при нарушении sessionKey теперь AP-REQ.Authenticator.subkey

Я работаю над проектом, в котором мы используем JAAS/Krb5LoginModule с useTicketCache & doNotPrompt, а также изменение реестра allowtgtsessionkey, чтобы включить нашу аутентификацию при входе в Windows на компьютере, присоединенном к домену.

Затем мы используем jgss/kerberos для получения токена Kerberos API GSS (rfc1964), который мы используем для защиты сообщения SOAP с использованием профиля токена WSS Kerberos 1.1.1 при взаимодействии со службой. Это включает включение токена GSS в кодировке b64 в элемент Security конверта / заголовка SOAP и использование sessionKey client/service для подписи компонента элемента.

Мы получаем client/sessionKey, запрашивая частные учетные данные javax.security.auth.Subject, которые возвращает JAAS/Krb5LoginModule, и ищем javax.security.auth.kerberos.KerberosTicket, который соответствует имени нашего сервисного партнера, и вызывая его getSessionKey. ().

Все это прекрасно работает в Java-6, однако клиенты Java-7 не работают, так как, похоже, произошли изменения в сообщении Kerberos KRB_AP_REQ, которое создает Java-7. Аутентификатор KRB_AP_REQ Java-7 содержит вложенный ключ, который отличается от sessionKey. Поскольку в спецификации Kerberos (см. Выдержку ниже) говорится, что этот подраздел заменяет sessionKey, наше поведение Java-6 по использованию sessionKey для подписи больше не является правильным.

RFC1510 - служба сетевой аутентификации Kerberos (V5)

5.3.2. аутентификаторы

subkey  This field contains the client's choice for an encryption
        key which is to be used to protect this specific
        application session. Unless an application specifies
        otherwise, if this field is left out the session key from
        the ticket will be used.

Я не видел нигде, где это изменение задокументировано, но подтвердил поведение по крайней мере в Java(TM) SE Runtime Environment (сборка 1.7.0_11-b21).

На данный момент, если я не пропустил что-то явно очевидное (и я надеюсь, что у меня есть), наши варианты выглядят так:

  1. Измените конфигурацию Java-7 Kerberos, чтобы вернуться к поведению Java-6 - к сожалению, я не видел ничего в документации, которая, кажется, предполагает, что это возможно.

  2. Найдите способ получить доступ к подразделу. Для этих вариантов я исследовал

    а. Декодируйте кодированный B64 токен GSS, извлеките зашифрованный аутентификатор, расшифруйте его с помощью sessionKey, расшифруйте кодировку ASN.1 DER и извлеките подключ.

    б. Используйте то, что кажется нестандартным GSS API Extensions и используйте метод ExtendedGSSContext.inquireSecContext() с KRB5_GET_SESSION_KEY, чтобы получить subKey.

Любые предложения / понимание этих или других возможных вариантов?

2 ответа

Решение

Мы также сталкиваемся с этой проблемой при использовании JGSS Api в Java 1.7 для получения ключа сеанса клиента. По-видимому, в Java 1.6 подраздел был всегда клонирован из ключа сеанса, см. sun.security.krb5.EncryptionKey конструктор:

EncryptionKey(EncryptionKey encryptionkey)
    throws KrbCryptoException
{
    keyValue = (byte[])(byte[])encryptionkey.keyValue.clone();
    keyType = encryptionkey.keyType;
}

Начиная с Java 1.7.0_b07, этот конструктор использует java.security.SecureRandom создать новый подраздел. Я думаю, что это было сделано как часть JDK-4460771: Kerberos должен быть в состоянии генерировать ключи подсессии. Кажется, что com.sun.security.jgss.ExtendedGSSContext с этого момента предоставляет "стандартный" способ доступа к подразделу (в Sun JVM), поэтому, я думаю, нам следует использовать этот класс, если он доступен (в базовой JVM), см.

JDK-6710360: экспорт ключа сеанса Kerberos в приложения

Спасибо, Детелин

Я ничего не вижу в документе ExtendedGSSContext.inquireSecContext(), чтобы указать, что он возвращает подключ, если он присутствует для KRB5_GET_SESSION_KEY; Вы знаете из какого-то другого источника, что это делает?

В любом случае, использование подключа - это то, что вам нужно сделать. Я бы посмотрел на это так: ваша первоначальная реализация была неправильной, потому что в документе WSS Kerberos четко указано, что этот раздел должен использоваться, если он есть. Это просто сработало, потому что библиотека Java 6 Kerberos не генерировала подключ. Теперь, когда он появился, ваша ошибка обнаружена, и вы должны ее исправить.

Я не знаком с WSS, но документ, кажется, указывает, что вы можете выбрать различные кодировки для токена, и один из них - использовать GSSAPI вместо Kerberos AP-REQ напрямую. Возможно, если бы вы использовали GSSAPI для начала, это изолировало бы вас от этого изменения - и, возможно, переключение на него сейчас было бы самым простым решением.

Другие вопросы по тегам