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

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

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

Мы получаем 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. Измените конфигурацию Kerberos Java-7, чтобы вернуться к поведению Java-6 - к сожалению, я не видел в документах ничего, что могло бы предположить, что это возможно.

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

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

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

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


person Kaveh Goudarzi    schedule 24.07.2013    source источник


Ответы (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 в приложения

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

person Detelin    schedule 20.08.2013
comment
Детелин - спасибо за ответ. Подобно вам, мы выбрали путь 2.b в моем первоначальном вопросе, а именно использование класса ExtendedGSSContext. Однако это некрасиво, так как нам пришлось добавить код, зависящий от поставщика + версии, с отражением, чтобы решить эту проблему и при этом быть совместимым с JDK 6 и JDK других поставщиков. - person Kaveh Goudarzi; 24.08.2013

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

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

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

person Richard E. Silverman    schedule 27.07.2013
comment
Я убедился, что функция ExtendedGSSContext.inquireSecContext() с KRB5_GET_SESSION_KEY возвращает подраздел в Oracle JDK 7. Я просмотрел документы metro 2.3. (см. com.sun.xml.ws.security.impl.kerberos.KerberosLogin.java), чтобы узнать, как они решают эту проблему, и увидеть использование ExtendedGSSContext. Что касается WSS, я использую GSSAPI Kerberos, но проблема связана с тем, что базовый билет Java 7 AP-REQ Kerberos генерирует аутентификатор с подключом и, по-видимому, не имеет стандартного Java API, обеспечивающего средства доступа к нему. - person Kaveh Goudarzi; 29.07.2013