Как с помощью SSPI отправить токен Kerberos на прокси-сервер HTTP с поддержкой GSSAPI?

У меня есть простое приложение клиентского сокета, с помощью которого я хочу получить доступ к веб-сайту. Чтобы получить доступ к Интернету, мой клиент должен пройти через прокси-сервер HTTP (я использую Microsoft Forefront Threat Management Gateway). Прокси-сервер требует аутентификации и настроен на прием Kerberos через GSSAPI.

В моем клиенте я использую Microsoft SSPI:

Сначала я вызываю AcquireCredentialsHandle, который завершается успешно и возвращает SEC_E_OK

Затем я вызываю InitializeSecurityContext, который также завершается успешно и возвращает SEC_E_OK

Все идет нормально. Но теперь мне нужно отправить токен на прокси-сервер для авторизации, и это та часть, которая вызывает у меня проблемы.

Если я подключаюсь к своему прокси-серверу с помощью Internet Explorer, я могу наблюдать за обменом пакетами через Wireshark. IE согласовывает билет с Kerberos и, похоже, отправляет его через заголовок Proxy-Authorization. Кажется, что содержимое заголовка закодировано в base64.

Если я просто возьму токен, который возвращается из InitializeSecurityContext, base64 закодирует его и отправлю результат на прокси-сервер через заголовок типа Proxy-Authorization: Negotiate <base64Data>, аутентификация не удастся.

Я чувствую, что близок, но все еще чего-то не хватает. На одном сайте обсуждалось использование EncryptMessage для токена перед его отправкой. Другой обсуждает использование взаимной аутентификации (я не думаю, что IE использует взаимную аутентификацию, потому что кажется, что клиент отправляет авторизацию только один раз, и нет данных обратной связи с сервера (с помощью которых можно вызвать InitializeSecurityContext во второй раз). Другой сайт обрисовал в общих чертах размещение токена с различными SEC_BUFFER типами (заполнение, данные и т. д.) и шифрованием. Я подозреваю, что это именно то, что мне нужно сделать, поскольку я не нахожу много документации о том, как это сделать.

Будем признательны за любые идеи или предложения.

ОБНОВЛЕНИЕ 19.07.2014: Для ясности, я спрашиваю, как использовать SSPI для вычисления поля «base64Data» (как указано выше). При вычислении base64, кодирующего содержимое, содержащееся в буфере SECBUFFER_TOKEN, было моим первоначальным предположением, сервер не принимает результат, поэтому он явно недействителен.

Дальнейшие исследования показывают, что токен должен быть «обернут» (он же «EncryptMessage» через SSPI) и для шифрования способом, совместимым с GSSAPI, необходимо использовать три буфера (в порядке: SECBUFFER_TOKEN, SECBUFFER_DATA и SECBUFFER_PADDING). это вчера, но успеха не имел.

http://msdn.microsoft.com/en-us/library/ms995352.aspx

http://msdn.microsoft.com/en-us/magazine/cc301890.aspx


person charunnera    schedule 18.07.2014    source источник


Ответы (1)


Вы действительно хотите самостоятельно кодировать взаимодействие через прокси? Я бы рекомендовал использовать libcurl в Windows. Здесь на работе это прекрасно работает с TMG.

Причина, по которой ваша копия и вставка не работает, заключается в том, что accept обнаруживает, что вы повторно отправляете в качестве ответа. Kerberos защищен от повторного воспроизведения. Вы не можете украсть билет и использовать его повторно.

Предположим, вы вызвали InitializeSecurityContext и получили при успешном вызове SEC_E_OK указатель на SecBufferDesc. Вы должны получить доступ к включенному массиву, прочитать структуру PSecBuffer, получить доступ к элементу pvBuffer и передать этот void*, преобразованный в unsigned char*, в функцию, которая преобразует unsigned char* (шестнадцатеричные байты) в base64 в char*. Не забудьте указать длину cbBuffer. Тогда ты этого не сделаешь. Это билет в кодировке base64 для вашего HTTP-прокси.

Вы можете использовать EncryptMessage, но не с HTTP. HTTP использует TLS. Если вы хотите использовать EncryptMessage, используйте простые сокеты. EncryptMessage будет прозрачно шифровать весь ваш трафик между вашим клиентом и сервером.

Кстати: прокси вернет билет в IE, потому что я всегда запрашиваю взаимную аутентификацию. Тебе следует заняться делом. Следовательно, вы должны смотреть контекст инициализации, пока не получите OK, а не CONTINUE_NEEDED.

person Michael-O    schedule 18.07.2014
comment
Привет, спасибо, что предложили альтернативный подход. Однако мне интересно узнать, как этого добиться, используя только библиотеку Microsoft SSPI. - person charunnera; 19.07.2014
comment
У вас не получится, потому что вам понадобится много кода: 1. Код SSPI, 2. Обмен данными через сокеты, 3. Реализация HTTP для связи с прокси-сервером и т. Д. Вы действительно хотите это сделать? - person Michael-O; 19.07.2014
comment
Привет, у меня уже есть обширный код для областей, которые вы обрисовали. Я обновлю вопрос, уточню свои намерения. - person charunnera; 19.07.2014