FFmpeg
tls_schannel.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Hendrik Leppkes
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /** Based on the CURL SChannel module */
22 
23 #include "avformat.h"
24 #include "internal.h"
25 #include "network.h"
26 #include "os_support.h"
27 #include "url.h"
28 #include "tls.h"
29 
30 #define SECURITY_WIN32
31 #include <windows.h>
32 #include <security.h>
33 #include <schnlsp.h>
34 
35 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
36 #define SCHANNEL_FREE_BUFFER_SIZE 1024
37 
38 /* mingw does not define this symbol */
39 #ifndef SECBUFFER_ALERT
40 #define SECBUFFER_ALERT 17
41 #endif
42 
43 typedef struct TLSContext {
44  const AVClass *class;
46 
47  CredHandle cred_handle;
48  TimeStamp cred_timestamp;
49 
50  CtxtHandle ctxt_handle;
51  TimeStamp ctxt_timestamp;
52 
55 
59 
63 
64  SecPkgContext_StreamSizes sizes;
65 
66  int connected;
69 } TLSContext;
70 
71 static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
72  void *data, unsigned long size)
73 {
74  buffer->cbBuffer = size;
75  buffer->BufferType = type;
76  buffer->pvBuffer = data;
77 }
78 
79 static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers,
80  unsigned long buffer_count)
81 {
82  desc->ulVersion = SECBUFFER_VERSION;
83  desc->pBuffers = buffers;
84  desc->cBuffers = buffer_count;
85 }
86 
88 {
89  TLSContext *c = h->priv_data;
90  TLSShared *s = &c->tls_shared;
91  int ret;
92 
93  if (c->connected) {
94  SecBufferDesc BuffDesc;
95  SecBuffer Buffer;
96  SECURITY_STATUS sspi_ret;
97  SecBuffer outbuf;
98  SecBufferDesc outbuf_desc;
99 
100  DWORD dwshut = SCHANNEL_SHUTDOWN;
101  init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
102  init_sec_buffer_desc(&BuffDesc, &Buffer, 1);
103 
104  sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
105  if (sspi_ret != SEC_E_OK)
106  av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");
107 
108  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
109  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
110 
111  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
112  c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
113  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
114  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
115  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
116  FreeContextBuffer(outbuf.pvBuffer);
117  if (ret < 0 || ret != outbuf.cbBuffer)
118  av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
119  }
120 
121  c->connected = 0;
122  }
123  return 0;
124 }
125 
126 static int tls_close(URLContext *h)
127 {
128  TLSContext *c = h->priv_data;
129 
131 
132  DeleteSecurityContext(&c->ctxt_handle);
133  FreeCredentialsHandle(&c->cred_handle);
134 
135  av_freep(&c->enc_buf);
136  c->enc_buf_size = c->enc_buf_offset = 0;
137 
138  av_freep(&c->dec_buf);
139  c->dec_buf_size = c->dec_buf_offset = 0;
140 
141  if (c->tls_shared.tcp)
143  return 0;
144 }
145 
146 static int tls_client_handshake_loop(URLContext *h, int initial)
147 {
148  TLSContext *c = h->priv_data;
149  TLSShared *s = &c->tls_shared;
150  SECURITY_STATUS sspi_ret;
151  SecBuffer outbuf[3] = { 0 };
152  SecBufferDesc outbuf_desc;
153  SecBuffer inbuf[2];
154  SecBufferDesc inbuf_desc;
155  int i, ret = 0, read_data = initial;
156 
157  if (c->enc_buf == NULL) {
158  c->enc_buf_offset = 0;
160  if (ret < 0)
161  goto fail;
163  }
164 
165  if (c->dec_buf == NULL) {
166  c->dec_buf_offset = 0;
168  if (ret < 0)
169  goto fail;
171  }
172 
173  while (1) {
176  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
177  if (ret < 0) {
178  c->enc_buf_size = c->enc_buf_offset = 0;
179  goto fail;
180  }
181  }
182 
183  if (read_data) {
184  ret = ffurl_read(c->tls_shared.tcp, c->enc_buf + c->enc_buf_offset,
185  c->enc_buf_size - c->enc_buf_offset);
186  if (ret < 0) {
187  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
188  goto fail;
189  }
190  c->enc_buf_offset += ret;
191  }
192 
193  /* input buffers */
194  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
195  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
196  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
197 
198  if (inbuf[0].pvBuffer == NULL) {
199  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
200  ret = AVERROR(ENOMEM);
201  goto fail;
202  }
203 
204  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
205 
206  /* output buffers */
207  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
208  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
209  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
210  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
211 
212  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags,
213  0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &c->context_flags,
214  &c->ctxt_timestamp);
215  av_freep(&inbuf[0].pvBuffer);
216 
217  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
218  av_log(h, AV_LOG_DEBUG, "Received incomplete handshake, need more data\n");
219  read_data = 1;
220  continue;
221  }
222 
223  /* remote requests a client certificate - attempt to continue without one anyway */
224  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
225  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
226  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
227  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
228  read_data = 0;
229  continue;
230  }
231 
232  /* continue handshake */
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) {
236  ret = ffurl_write(c->tls_shared.tcp, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
237  if (ret < 0 || ret != outbuf[i].cbBuffer) {
238  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
239  ret = AVERROR(EIO);
240  goto fail;
241  }
242  }
243 
244  if (outbuf[i].pvBuffer != NULL) {
245  FreeContextBuffer(outbuf[i].pvBuffer);
246  outbuf[i].pvBuffer = NULL;
247  }
248  }
249  } else {
250  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
251  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
252  else
253  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
254  ret = AVERROR_UNKNOWN;
255  goto fail;
256  }
257 
258  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
259  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
260  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
261  inbuf[1].cbBuffer);
262  c->enc_buf_offset = inbuf[1].cbBuffer;
263  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
264  read_data = 0;
265  continue;
266  }
267  }
268  } else {
269  c->enc_buf_offset = 0;
270  }
271 
272  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
273  read_data = 1;
274  continue;
275  }
276 
277  break;
278  }
279 
280  return 0;
281 
282 fail:
283  /* free any remaining output data */
284  for (i = 0; i < 3; i++) {
285  if (outbuf[i].pvBuffer != NULL) {
286  FreeContextBuffer(outbuf[i].pvBuffer);
287  outbuf[i].pvBuffer = NULL;
288  }
289  }
290 
291  return ret;
292 }
293 
295 {
296  TLSContext *c = h->priv_data;
297  TLSShared *s = &c->tls_shared;
298  SecBuffer outbuf;
299  SecBufferDesc outbuf_desc;
300  SECURITY_STATUS sspi_ret;
301  int ret;
302 
303  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
304  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
305 
306  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
307  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
308  ISC_REQ_STREAM;
309 
310  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
311  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
312  &c->ctxt_timestamp);
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);
315  ret = AVERROR_UNKNOWN;
316  goto fail;
317  }
318 
319  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
320  FreeContextBuffer(outbuf.pvBuffer);
321  if (ret < 0 || ret != outbuf.cbBuffer) {
322  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
323  ret = AVERROR(EIO);
324  goto fail;
325  }
326 
327  return tls_client_handshake_loop(h, 1);
328 
329 fail:
330  DeleteSecurityContext(&c->ctxt_handle);
331  return ret;
332 }
333 
334 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
335 {
336  TLSContext *c = h->priv_data;
337  TLSShared *s = &c->tls_shared;
338  SECURITY_STATUS sspi_ret;
339  SCHANNEL_CRED schannel_cred = { 0 };
340  int ret;
341 
342  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
343  goto fail;
344 
345  if (s->listen) {
346  av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n");
347  ret = AVERROR(EINVAL);
348  goto fail;
349  }
350 
351  /* SChannel Options */
352  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
353 
354  if (s->verify)
355  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
356  SCH_CRED_REVOCATION_CHECK_CHAIN;
357  else
358  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
359  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
360  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
361 
362  /* Get credential handle */
363  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
364  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
365  &c->cred_timestamp);
366  if (sspi_ret != SEC_E_OK) {
367  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
368  ret = AVERROR_UNKNOWN;
369  goto fail;
370  }
371 
372  ret = tls_client_handshake(h);
373  if (ret < 0)
374  goto fail;
375 
376  c->connected = 1;
377 
378  return 0;
379 
380 fail:
381  tls_close(h);
382  return ret;
383 }
384 
385 static int tls_read(URLContext *h, uint8_t *buf, int len)
386 {
387  TLSContext *c = h->priv_data;
388  TLSShared *s = &c->tls_shared;
389  SECURITY_STATUS sspi_ret = SEC_E_OK;
390  SecBuffer inbuf[4];
391  SecBufferDesc inbuf_desc;
392  int size, ret;
393  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
394 
395  if (len <= c->dec_buf_offset)
396  goto cleanup;
397 
398  if (c->sspi_close_notify)
399  goto cleanup;
400 
401  if (!c->connection_closed) {
402  size = c->enc_buf_size - c->enc_buf_offset;
405  if (c->enc_buf_size < min_enc_buf_size)
406  c->enc_buf_size = min_enc_buf_size;
407  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
408  if (ret < 0) {
409  c->enc_buf_size = c->enc_buf_offset = 0;
410  return ret;
411  }
412  }
413 
414  ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset,
415  c->enc_buf_size - c->enc_buf_offset);
416  if (ret == AVERROR_EOF) {
417  c->connection_closed = 1;
418  ret = 0;
419  } else if (ret < 0) {
420  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
421  return ret;
422  }
423 
424  c->enc_buf_offset += ret;
425  }
426 
427  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK && c->dec_buf_offset < len) {
428  /* input buffer */
429  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
430 
431  /* additional buffers for possible output */
432  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
433  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
434  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
435  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
436 
437  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
438  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
439  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
440  /* handle decrypted data */
441  if (inbuf[1].BufferType == SECBUFFER_DATA) {
442  /* grow buffer if needed */
443  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
444  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
445  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
446  c->dec_buf_size = c->dec_buf_offset + size;
447  if (c->dec_buf_size < len)
448  c->dec_buf_size = len;
449  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
450  if (ret < 0) {
451  c->dec_buf_size = c->dec_buf_offset = 0;
452  return ret;
453  }
454  }
455 
456  /* copy decrypted data to buffer */
457  size = inbuf[1].cbBuffer;
458  if (size) {
459  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
460  c->dec_buf_offset += size;
461  }
462  }
463  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
464  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
465  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
466  inbuf[3].cbBuffer);
467  c->enc_buf_offset = inbuf[3].cbBuffer;
468  }
469  } else
470  c->enc_buf_offset = 0;
471 
472  if (sspi_ret == SEC_I_RENEGOTIATE) {
473  if (c->enc_buf_offset) {
474  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
475  ret = AVERROR_UNKNOWN;
476  goto cleanup;
477  }
478 
479  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
480  ret = tls_client_handshake_loop(h, 0);
481  if (ret < 0) {
482  goto cleanup;
483  }
484  sspi_ret = SEC_E_OK;
485  continue;
486  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
487  c->sspi_close_notify = 1;
488  if (!c->connection_closed) {
489  c->connection_closed = 1;
490  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
491  }
492  ret = 0;
493  goto cleanup;
494  }
495  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
496  ret = AVERROR(EAGAIN);
497  goto cleanup;
498  } else {
499  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
500  ret = AVERROR(EIO);
501  goto cleanup;
502  }
503  }
504 
505  ret = 0;
506 
507 cleanup:
508  size = FFMIN(len, c->dec_buf_offset);
509  if (size) {
510  memcpy(buf, c->dec_buf, size);
511  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
512  c->dec_buf_offset -= size;
513 
514  return size;
515  }
516 
517  if (ret == 0 && !c->connection_closed)
518  ret = AVERROR(EAGAIN);
519 
520  return ret < 0 ? ret : AVERROR_EOF;
521 }
522 
523 static int tls_write(URLContext *h, const uint8_t *buf, int len)
524 {
525  TLSContext *c = h->priv_data;
526  TLSShared *s = &c->tls_shared;
527  SECURITY_STATUS sspi_ret;
528  int ret = 0, data_size;
529  uint8_t *data = NULL;
530  SecBuffer outbuf[4];
531  SecBufferDesc outbuf_desc;
532 
533  if (c->sizes.cbMaximumMessage == 0) {
534  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
535  if (sspi_ret != SEC_E_OK)
536  return AVERROR_UNKNOWN;
537  }
538 
539  /* limit how much data we can consume */
540  len = FFMIN(len, c->sizes.cbMaximumMessage);
541 
542  data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
543  data = av_malloc(data_size);
544  if (data == NULL)
545  return AVERROR(ENOMEM);
546 
547  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
548  data, c->sizes.cbHeader);
549  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
550  data + c->sizes.cbHeader, len);
551  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
552  data + c->sizes.cbHeader + len,
553  c->sizes.cbTrailer);
554  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
555  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
556 
557  memcpy(outbuf[1].pvBuffer, buf, len);
558 
559  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
560  if (sspi_ret == SEC_E_OK) {
561  len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
562  ret = ffurl_write(s->tcp, data, len);
563  if (ret < 0 || ret != len) {
564  ret = AVERROR(EIO);
565  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
566  goto done;
567  }
568  } else {
569  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
570  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
571  ret = AVERROR(ENOMEM);
572  else
573  ret = AVERROR(EIO);
574  goto done;
575  }
576 
577 done:
578  av_freep(&data);
579  return ret < 0 ? ret : outbuf[1].cbBuffer;
580 }
581 
583 {
584  TLSContext *c = h->priv_data;
586 }
587 
588 static const AVOption options[] = {
590  { NULL }
591 };
592 
593 static const AVClass tls_class = {
594  .class_name = "tls",
595  .item_name = av_default_item_name,
596  .option = options,
597  .version = LIBAVUTIL_VERSION_INT,
598 };
599 
601  .name = "tls",
602  .url_open2 = tls_open,
603  .url_read = tls_read,
604  .url_write = tls_write,
605  .url_close = tls_close,
606  .url_get_file_handle = tls_get_file_handle,
607  .priv_data_size = sizeof(TLSContext),
609  .priv_data_class = &tls_class,
610 };
#define NULL
Definition: coverity.c:32
ULONG request_flags
Definition: tls_schannel.c:53
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
int verify
Definition: tls.h:31
static const AVClass tls_class
Definition: tls_schannel.c:593
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1787
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:420
const char * desc
Definition: nvenc.c:68
const URLProtocol ff_tls_protocol
Definition: tls_schannel.c:600
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
int connection_closed
Definition: tls_schannel.c:67
GLint GLenum type
Definition: opengl_enc.c:104
int enc_buf_offset
Definition: tls_schannel.c:58
int listen
Definition: tls.h:34
#define SCHANNEL_FREE_BUFFER_SIZE
Definition: tls_schannel.c:36
TimeStamp ctxt_timestamp
Definition: tls_schannel.c:51
CtxtHandle ctxt_handle
Definition: tls_schannel.c:50
uint8_t * dec_buf
Definition: tls_schannel.c:60
static const AVOption options[]
Definition: tls_schannel.c:588
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
uint8_t
#define av_malloc(s)
static int tls_read(URLContext *h, uint8_t *buf, int len)
Definition: tls_schannel.c:385
static int tls_write(URLContext *h, const uint8_t *buf, int len)
Definition: tls_schannel.c:523
miscellaneous OS support macros and functions.
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
int sspi_close_notify
Definition: tls_schannel.c:68
ULONG context_flags
Definition: tls_schannel.c:54
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
Definition: tls_schannel.c:79
Definition: tls.h:29
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int dec_buf_size
Definition: tls_schannel.c:61
ptrdiff_t size
Definition: opengl_enc.c:100
#define av_log(a,...)
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
Definition: tls_schannel.c:71
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define SECBUFFER_ALERT
Definition: tls_schannel.c:40
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_schannel.c:334
#define fail()
Definition: checkasm.h:122
char * host
Definition: tls.h:36
#define FFMIN(a, b)
Definition: common.h:96
static int tls_close(URLContext *h)
Definition: tls_schannel.c:126
SecPkgContext_StreamSizes sizes
Definition: tls_schannel.c:64
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:45
#define s(width, name)
Definition: cbs_vp9.c:257
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:625
uint8_t * enc_buf
Definition: tls_schannel.c:56
TimeStamp cred_timestamp
Definition: tls_schannel.c:48
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
static int tls_shutdown_client(URLContext *h)
Definition: tls_schannel.c:87
CredHandle cred_handle
Definition: tls_schannel.c:47
TLSShared tls_shared
Definition: tls_gnutls.c:50
void * buf
Definition: avisynth_c.h:766
Definition: url.h:38
Describe the class of an AVClass context structure.
Definition: log.h:67
void * priv_data
Definition: url.h:41
#define SCHANNEL_INITIAL_BUFFER_SIZE
Definition: tls_schannel.c:35
uint32_t DWORD
int enc_buf_size
Definition: tls_schannel.c:57
const char * name
Definition: url.h:55
static int tls_client_handshake(URLContext *h)
Definition: tls_schannel.c:294
#define flags(name, subs,...)
Definition: cbs_av1.c:561
int ffurl_close(URLContext *h)
Definition: avio.c:466
Main libavformat public API header.
GLuint * buffers
Definition: opengl_enc.c:98
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition: tls.c:56
uint32_t ULONG
URLContext * tcp
Definition: tls.h:41
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
static int tls_client_handshake_loop(URLContext *h, int initial)
Definition: tls_schannel.c:146
int dec_buf_offset
Definition: tls_schannel.c:62
int len
static int tls_get_file_handle(URLContext *h)
Definition: tls_schannel.c:582
#define av_freep(p)
unbuffered private I/O API
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
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...
Definition: avio.c:406
GLuint buffer
Definition: opengl_enc.c:101
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:127