30 #define SECURITY_WIN32
35 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
36 #define SCHANNEL_FREE_BUFFER_SIZE 1024
39 #ifndef SECBUFFER_ALERT
40 #define SECBUFFER_ALERT 17
64 SecPkgContext_StreamSizes
sizes;
74 buffer->cbBuffer =
size;
75 buffer->BufferType =
type;
76 buffer->pvBuffer =
data;
80 unsigned long buffer_count)
82 desc->ulVersion = SECBUFFER_VERSION;
84 desc->cBuffers = buffer_count;
94 SecBufferDesc BuffDesc;
96 SECURITY_STATUS sspi_ret;
98 SecBufferDesc outbuf_desc;
100 DWORD dwshut = SCHANNEL_SHUTDOWN;
104 sspi_ret = ApplyControlToken(&c->
ctxt_handle, &BuffDesc);
105 if (sspi_ret != SEC_E_OK)
114 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
116 FreeContextBuffer(outbuf.pvBuffer);
117 if (ret < 0 || ret != outbuf.cbBuffer)
150 SECURITY_STATUS sspi_ret;
152 SecBufferDesc outbuf_desc;
154 SecBufferDesc inbuf_desc;
198 if (inbuf[0].pvBuffer ==
NULL) {
217 if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
224 if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
233 if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
234 for (i = 0; i < 3; i++) {
235 if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
237 if (ret < 0 || ret != outbuf[i].cbBuffer) {
244 if (outbuf[i].pvBuffer !=
NULL) {
245 FreeContextBuffer(outbuf[i].pvBuffer);
246 outbuf[i].pvBuffer =
NULL;
250 if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
258 if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
263 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
272 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
284 for (i = 0; i < 3; i++) {
285 if (outbuf[i].pvBuffer !=
NULL) {
286 FreeContextBuffer(outbuf[i].pvBuffer);
287 outbuf[i].pvBuffer =
NULL;
299 SecBufferDesc outbuf_desc;
300 SECURITY_STATUS sspi_ret;
306 c->
request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
307 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
313 if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
314 av_log(h,
AV_LOG_ERROR,
"Unable to create initial security context (0x%lx)\n", sspi_ret);
320 FreeContextBuffer(outbuf.pvBuffer);
321 if (ret < 0 || ret != outbuf.cbBuffer) {
338 SECURITY_STATUS sspi_ret;
339 SCHANNEL_CRED schannel_cred = { 0 };
352 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
355 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
356 SCH_CRED_REVOCATION_CHECK_CHAIN;
358 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
359 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
360 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
363 sspi_ret = AcquireCredentialsHandle(
NULL, (
TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
366 if (sspi_ret != SEC_E_OK) {
367 av_log(h,
AV_LOG_ERROR,
"Unable to acquire security credentials (0x%lx)\n", sspi_ret);
389 SECURITY_STATUS sspi_ret = SEC_E_OK;
391 SecBufferDesc inbuf_desc;
395 if (len <= c->dec_buf_offset)
436 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
437 sspi_ret == SEC_I_CONTEXT_EXPIRED) {
439 if (inbuf[1].BufferType == SECBUFFER_DATA) {
441 size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
455 size = inbuf[1].cbBuffer;
461 if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
470 if (sspi_ret == SEC_I_RENEGOTIATE) {
484 }
else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
493 }
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
518 return ret < 0 ? ret : 0;
525 SECURITY_STATUS sspi_ret;
526 int ret = 0, data_size;
529 SecBufferDesc outbuf_desc;
531 if (c->
sizes.cbMaximumMessage == 0) {
532 sspi_ret = QueryContextAttributes(&c->
ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->
sizes);
533 if (sspi_ret != SEC_E_OK)
540 data_size = c->
sizes.cbHeader + len + c->
sizes.cbTrailer;
546 data, c->
sizes.cbHeader);
548 data + c->
sizes.cbHeader, len);
550 data + c->
sizes.cbHeader + len,
555 memcpy(outbuf[1].pvBuffer, buf, len);
557 sspi_ret = EncryptMessage(&c->
ctxt_handle, 0, &outbuf_desc, 0);
558 if (sspi_ret == SEC_E_OK) {
559 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
561 if (ret < 0 || ret != len) {
568 if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
577 return ret < 0 ? ret : outbuf[1].cbBuffer;
600 .priv_data_class = &tls_class,
#define URL_PROTOCOL_FLAG_NETWORK
ptrdiff_t const GLvoid * data
static const AVClass tls_class
#define LIBAVUTIL_VERSION_INT
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
#define SCHANNEL_FREE_BUFFER_SIZE
static const AVOption options[]
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static int tls_read(URLContext *h, uint8_t *buf, int len)
static int tls_write(URLContext *h, const uint8_t *buf, int len)
miscellaneous OS support macros and functions.
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
static int read_data(void *opaque, uint8_t *buf, int buf_size)
#define AV_LOG_VERBOSE
Detailed information.
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const URLProtocol ff_tls_schannel_protocol
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static int tls_close(URLContext *h)
SecPkgContext_StreamSizes sizes
#define TLS_COMMON_OPTIONS(pstruct, options_field)
static int tls_shutdown_client(URLContext *h)
Describe the class of an AVClass context structure.
#define SCHANNEL_INITIAL_BUFFER_SIZE
static int tls_client_handshake(URLContext *h)
int ffurl_close(URLContext *h)
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
static int tls_client_handshake_loop(URLContext *h, int initial)
unbuffered private I/O API
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
static av_cold void cleanup(FlashSV2Context *s)