Дефектный билет GSSAPI

Я извиняюсь, если есть что-то действительно прямолинейное, с чем я ошибаюсь - мне было очень трудно найти много информации о GSSAPI и JAAS.

Я пишу программу, которая отправляет запрос на сервер IIS и аутентифицируется с помощью Kerberos.

У меня две виртуальные машины: первая — это контроллер домена Active Directory. Другой другой работает сервер IIS.

На моей машине я запускаю программу, которая использует GSSAPI и JAAS для аутентификации. Он в значительной степени основан на учебниках Oracle для GSSAPI, так как на данном этапе я просто пытаюсь разобраться в этом. Он входит в систему, используя KrbLoginModule для создания темы на основе определенного тестового пользователя из домена, который, похоже, работает нормально. В сетевой трассировке есть AS-REQ, AS-REP, TGS-REQ и TGS-REP (что, если я прав, так и должно быть) между моей машиной и виртуальной машиной контроллера домена.

Затем моя программа использует тему, сгенерированную выше, для запуска некоторого кода GSSAPI, который в основном основан на код из руководства по GSSAPI/JAAS. Он создает имена/учетные данные/контекст без каких-либо ошибок, но когда он пытается установить контекст, все начинает идти не так.

Первоначально я выполнял цикл контекста, как это делается в учебнике (ссылка выше), но когда он попытался начать чтение токена с сервера (т.е. token = new byte[inStream.readInt()];), прочитанное length int было огромным (1213486160, несколько раз я проверял это - казалось, что так было каждый раз). Это вызвало ошибку OutOfMemoryError.

Затем я начал использовать «потоковую версию» файла initSecContext, который принимает входной и выходной потоки (я передал входящие/исходящие потоки сокета, которые я открыл на своем сервере - я предполагаю, что это чего хочет). Поначалу кажется, что это работает очень хорошо. Это устанавливается за одну итерацию, но когда вы пытаетесь обернуть/развернуть сообщения, все снова начинает идти не так. При попытке распаковать сообщение выдает ошибку:

org.ietf.jgss.GSSException, major code: 10, minor code: 0
    major string: Defective token
    minor string: Bad token tag: 7284

Сетевая трассировка для этого показывает TCP-сообщение той же длины, что и сгенерированный токен (я предполагаю, что это будет отправленный обернутый токен). Тогда есть перенаправление ICMP. Я не уверен, что это ничего, но я подумал, что упомяну об этом (я заметил, что он содержит почти все первое сообщение TCP).

Затем следует HTTP-ответ. Это 400 Bad Request. В теле ответа говорится, что это недопустимый глагол (я предполагаю, что когда он произносит глагол, он означает «ПОЛУЧИТЬ» или «ПОСТАТЬ» и т. д. Так ли это?) Трассировка также отмечает, что это подтверждение первое TCP-сообщение. Погуглив, я нашел человек, у которого была аналогичная проблема. Оказалось, что дело было в том, что антивирус возился с заголовками отправляемого запроса (может быть, это связано с редиректом?).

Затем есть еще несколько TCP-сообщений (три подряд) с моей машины (они содержат данные, которые я отправляю в сообщении с помощью метода переноса), за которыми следует TCP-подтверждение длины = 0 от сервера.

Поэтому я не уверен, что это может быть (может быть, это перенаправление, но это маловероятно).

ОБНОВЛЕНИЕ:

Я запускаю его на другой виртуальной машине (в том же домене Active Directory), но все еще получаю ответ HTTP 400 Bad Request. В отличие от предыдущего, теперь он определенно использует Kerberos (ранее он отправлял запросы NTLM).

Трассировка сети показывает запросы и ответы AS и TGS, а затем отправляемый билет. Затем сервер IIS возвращает 400 Bad Request (опять же, недопустимый глагол). Есть небольшая разница: ответ Bad Request больше не является подтверждением отправки токена, хотя есть пустое TCP-сообщение с подтверждением, которое приходит непосредственно перед 400.

Программа по-прежнему считает, что ее контекст установлен, но если вы попытаетесь обернуть сообщение, она обрывается:

General failure, unspecified at GSSAPI level
    minor string: Error in method wrap, error: java.net.SocketException:
        Unrecognized Windows Sockets error: 0: socket write error

ОБНОВЛЕНИЕ:

Как упоминалось ранее, когда я читаю токен с помощью initSecContext, я сначала ожидаю длину (т.е. token = new byte[inStream.readInt()];) на основе руководства. Я получаю 1213486160, что вызвало ошибку OutOfMemoryError. Однако я понял, что 1213486160 - это 0x48545450, что в ASCII означает «HTTP». Итак, я прочитал следующую связку символов, и «токен ответа» — это неверный запрос HTTP 400.

Это заставляет меня задаться вопросом, должен ли я читать целое число для длины, как показано в учебнике. Я чувствую, что этот вопрос несколько отличается, поэтому я создал новый вопрос здесь . Однако это может быть не проблема (например, не то, что заставляет его отправлять «Неверный запрос» в первую очередь), поэтому я пока оставлю этот вопрос открытым.

ДРУГОЕ ОБНОВЛЕНИЕ:

Итак, я посмотрел на токен, который выплевывается initSecContext и кодируется в Base64, это YII... (т.е. токен переговоров).

Я также внимательно изучил сетевую трассировку, когда я вхожу в систему через Chrome, и после сообщений AS и TGS он отправляет HTTP-запрос GET со строкой заголовка Authorization: Negotiate YII....., в отличие от моя программа, которая отправляет TCP-сообщение с длиной токена, затем токен.

Это говорит мне о том, что мне не нужно выполнять шаг установки контекста (по крайней мере, как показано в руководстве) или что мне нужно получить токен и отправить его в HTTP-запросе, а не в прямом TCP-сообщении. Есть ли кто-нибудь (или какие-либо примеры людей - я не могу найти никого), кто использовал GSSAPI/Kerberos для аутентификации для IIS, кто может это подтвердить?


person dram    schedule 22.12.2016    source источник
comment
Я был тем, кто только что проголосовал за ваш вопрос. Отличная детализация. Теперь мой вопрос к вам: вы сказали, что у вас есть две виртуальные машины: первая является контроллером домена Active Directory, а другая работает сервером IIS. Просто проверьте здесь — ваш клиентский компьютер также присоединен к этому домену Active Directory? Это должно быть для работы проверки подлинности Kerberos. Дефектный токен обычно означает, что клиентский компьютер отправил токен проверки подлинности NTLM, в то время как серверу требовался токен Kerberos.   -  person T-Heron    schedule 22.12.2016
comment
Он не находится в том же домене, но в настоящее время использует контроллер домена для своего DNS. Я не уверен, что это что-то значит, но когда я перехожу к серверу IIS в Chrome, он, кажется, использует Kerberos (все AS/TGS - REQ/REP и что-то еще).   -  person dram    schedule 22.12.2016
comment
Я только что снова проверил Chrome, и он использует NTLM! Может быть, я что-то изменил недавно — я изо всех сил пытался заставить его работать и перепробовал кучу разных параметров конфигурации, а затем избавился от многих из них, когда я заставил его работать. Я бы сказал, что это, вероятно, все.   -  person dram    schedule 22.12.2016
comment
Ох, ну ладно. Я не думаю, что у меня они настроены :/ Похоже, это все.   -  person dram    schedule 22.12.2016
comment
Итак, я запустил его с новой виртуальной машины, которая является частью этого домена, и ошибка исчезла (у меня появилась новая ошибка, но это прогресс, ха-ха)!   -  person dram    schedule 22.12.2016
comment
Я только что понял, что это не так :( Я добавлю редактирование к моему вопросу   -  person dram    schedule 22.12.2016
comment
Я посмотрю завтра, сейчас для меня поздняя ночь в Восточном стандартном часовом поясе.   -  person T-Heron    schedule 22.12.2016


Ответы (2)


Убедитесь, что клиентский компьютер присоединен к тому же домену Active Directory, что и сервер IIS, чтобы проверка подлинности Kerberos работала. «Дефектный токен» обычно означает, что клиентская машина отправила токен проверки подлинности NTLM, в то время как серверу требовался токен Kerberos. Существуют причины, по которым возникает такое нежелательное поведение.

  1. Если клиентский компьютер не находится в том же домене AD, то он должен находиться в домене, имеющем двусторонние доверительные отношения с доменом сервера IIS. Это происходит по умолчанию, если домены AD находятся в одном лесу.
  2. Необходимо настроить разрешения на доступ к серверу IIS из другого домена. Резюме. Если ответы на эти вопросы нет, это объясняет, почему происходит откат Basic Auth. Обычная проверка подлинности выполняется только после сбоя проверки подлинности Kerberos.
person T-Heron    schedule 22.12.2016

Итак, есть пара вещей, которые нужно проверить. Сначала убедитесь, что слова @T-Heron подтверждены. Если это так, и он все еще не работает, рассмотрите следующие вещи:

  1. Убедитесь, что вы вообще получили токен kerberos, используя команду klist в cmd. (Вы должны увидеть запись HTTP/[email protected], соответствующую вашему хосту IIS)
  2. Убедитесь, что KDC активен и знает, какую услугу вы запрашиваете.
  3. Убедитесь, что IIS знает свой субъект-службу
  4. Дважды проверьте ваш login.conf и ваш krb5.conf (или эти части в исходном коде, если вы установили их программно)

Это лучший ответ для Kerberos, который я когда-либо находил, поэтому обязательно ознакомьтесь с ним: SO answer

person Nico    schedule 22.12.2016
comment
Я запустил klist, и их было много, поэтому я очистил, а затем запустил свою программу, и там не было ни одной (или после посещения ее в Chrome), но я определенно получаю ее по сети, и она определенно использует Kerberos ( есть все сообщения AS и TGS для обоих). KDC определенно активен (мы говорим с ним), и IIS должен знать, кто это (все настроено — мы даже убедились в этом в активном каталоге). Думаю, что-то не так с конфигами login/krb. Я должен перепроверить их. - person dram; 22.12.2016
comment
Это хороший прогресс. Я не знаю, должен ли он быть в кеше для токенов kerberos, поскольку он может быть отправлен not_cachable или как пересылаемый. Конфигурация этих файлов тоже забрала у меня нервы. Поскольку я использую wildfly, мне пришлось настроить конфигурацию одного узла, на котором он работал, чтобы иметь домен безопасности с моими конфигурациями jaas. krb5.conf передается моему приложению в качестве аргумента java. Хотя это можно сделать несколькими способами. - person Nico; 22.12.2016