SChannel SSP возвращает SEC_E_INCOMPLETE_MESSAGE
из InitializeSecurityContext
и DecryptMessage
, когда недостаточно данных прочитано.
Тип сообщения SECBUFFER_MISSING
возвращается из DecryptMessage
со значением cbBuffer
количества требуемых байтов.
Но на практике я не использовал значение «отсутствующие данные». В документации указано, что значение не гарантируется, что оно является правильным, и является лишь подсказкой, которую разработчики могут использовать для сокращения вызовов.
InitalizeSecurityContext MSDN doc :
Хотя этот номер не всегда точен, его использование может помочь повысить производительность, избегая многократных вызовов этой функции.
Поэтому я безоговорочно считываю больше данных в тот же буфер каждый раз, когда возвращается SEC_E_INCOMPLETE_MESSAGE
. Чтение нескольких байтов одновременно из сокета.
Требовалось дополнительное управление входным буфером, чтобы добавить больше прочитанных данных и сохранить правильную длину. DecryptMessage
изменит свойства cbBuffer
входных буферов при сбое, что меня удивило.
Распечатка буферов и возвращаемый результат после вызова InitializeSecurityContext
показывает следующее:
read socket:bytes(5).
InitializeSecurityContext:result(80090318). // SEC_E_INCOMPLETE_MESSAGE
inBuffers[0]:type(2),bytes(5).
inBuffers[1]:type(0),bytes(0). // no indication of missing data
outBuffer[0]:type(2),bytes(0).
read socket:bytes(74).
InitializeSecurityContext:result(00090312). // SEC_I_CONTINUE_NEEDED
inBuffers[0]:type(2),bytes(79). // notice 74 + 5 from before
inBuffers[1]:type(0),bytes(0).
outBuffer[0]:type(2),bytes(0).
А для функции DecryptMessage
вход всегда находится в dataBuf[0]
, остальные обнуляются.
read socket:bytes(5).
DecryptMessage:len 5, bytes(17030201). // SEC_E_INCOMPLETE_MESSAGE
DecryptMessage:dataBuf[0].BufferType 4, 8 // notice input buffer modified
DecryptMessage:dataBuf[1].BufferType 4, 8
DecryptMessage:dataBuf[2].BufferType 0, 0
DecryptMessage:dataBuf[3].BufferType 0, 0
read socket:bytes(8).
DecryptMessage:len 13, bytes(17030201). // SEC_E_INCOMPLETE_MESSAGE
DecryptMessage:dataBuf[0].BufferType 4, 256
DecryptMessage:dataBuf[1].BufferType 4, 256
DecryptMessage:dataBuf[2].BufferType 0, 0
DecryptMessage:dataBuf[3].BufferType 0, 0
read socket:bytes(256).
DecryptMessage:len 269, bytes(17030201). // SEC_E_OK
Мы видим, что мой узел TLS-сервера отправляет заголовки TLS (5 байт) в одном пакете, а затем сообщение TLS (8 для данных приложения), а затем полезную нагрузку данных приложения в третьем.