Я извиняюсь, если есть что-то действительно прямолинейное, с чем я ошибаюсь - мне было очень трудно найти много информации о 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, кто может это подтвердить?