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 "libavutil/mem.h"
24 #include "avformat.h"
25 #include "internal.h"
26 #include "network.h"
27 #include "os_support.h"
28 #include "url.h"
29 #include "tls.h"
30 
31 #define SECURITY_WIN32
32 #include <windows.h>
33 #include <security.h>
34 #include <schnlsp.h>
35 
36 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
37 #define SCHANNEL_FREE_BUFFER_SIZE 1024
38 
39 /* mingw does not define this symbol */
40 #ifndef SECBUFFER_ALERT
41 #define SECBUFFER_ALERT 17
42 #endif
43 
44 typedef struct TLSContext {
45  const AVClass *class;
47 
48  CredHandle cred_handle;
49  TimeStamp cred_timestamp;
50 
51  CtxtHandle ctxt_handle;
52  TimeStamp ctxt_timestamp;
53 
56 
57  uint8_t *enc_buf;
60 
61  uint8_t *dec_buf;
64 
65  SecPkgContext_StreamSizes sizes;
66 
67  int connected;
70 } TLSContext;
71 
72 static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
73  void *data, unsigned long size)
74 {
75  buffer->cbBuffer = size;
76  buffer->BufferType = type;
77  buffer->pvBuffer = data;
78 }
79 
80 static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers,
81  unsigned long buffer_count)
82 {
83  desc->ulVersion = SECBUFFER_VERSION;
84  desc->pBuffers = buffers;
85  desc->cBuffers = buffer_count;
86 }
87 
89 {
90  TLSContext *c = h->priv_data;
91  TLSShared *s = &c->tls_shared;
92  int ret;
93 
94  if (c->connected) {
95  SecBufferDesc BuffDesc;
96  SecBuffer Buffer;
97  SECURITY_STATUS sspi_ret;
98  SecBuffer outbuf;
99  SecBufferDesc outbuf_desc;
100 
101  DWORD dwshut = SCHANNEL_SHUTDOWN;
102  init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
103  init_sec_buffer_desc(&BuffDesc, &Buffer, 1);
104 
105  sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
106  if (sspi_ret != SEC_E_OK)
107  av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");
108 
109  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
110  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
111 
112  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
113  c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
114  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
115  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
116  s->tcp->flags &= ~AVIO_FLAG_NONBLOCK;
117  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
118  FreeContextBuffer(outbuf.pvBuffer);
119  if (ret < 0 || ret != outbuf.cbBuffer)
120  av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
121  }
122 
123  c->connected = 0;
124  }
125  return 0;
126 }
127 
128 static int tls_close(URLContext *h)
129 {
130  TLSContext *c = h->priv_data;
131 
133 
134  DeleteSecurityContext(&c->ctxt_handle);
135  FreeCredentialsHandle(&c->cred_handle);
136 
137  av_freep(&c->enc_buf);
138  c->enc_buf_size = c->enc_buf_offset = 0;
139 
140  av_freep(&c->dec_buf);
141  c->dec_buf_size = c->dec_buf_offset = 0;
142 
143  ffurl_closep(&c->tls_shared.tcp);
144  return 0;
145 }
146 
147 static int tls_client_handshake_loop(URLContext *h, int initial)
148 {
149  TLSContext *c = h->priv_data;
150  TLSShared *s = &c->tls_shared;
151  SECURITY_STATUS sspi_ret;
152  SecBuffer outbuf[3] = { 0 };
153  SecBufferDesc outbuf_desc;
154  SecBuffer inbuf[2];
155  SecBufferDesc inbuf_desc;
156  int i, ret = 0, read_data = initial;
157 
158  if (c->enc_buf == NULL) {
159  c->enc_buf_offset = 0;
161  if (ret < 0)
162  goto fail;
163  c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
164  }
165 
166  if (c->dec_buf == NULL) {
167  c->dec_buf_offset = 0;
169  if (ret < 0)
170  goto fail;
171  c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
172  }
173 
174  while (1) {
175  if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
176  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
177  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
178  if (ret < 0) {
179  c->enc_buf_size = c->enc_buf_offset = 0;
180  goto fail;
181  }
182  }
183 
184  if (read_data) {
185  ret = ffurl_read(c->tls_shared.tcp, c->enc_buf + c->enc_buf_offset,
186  c->enc_buf_size - c->enc_buf_offset);
187  if (ret < 0) {
188  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
189  goto fail;
190  }
191  c->enc_buf_offset += ret;
192  }
193 
194  /* input buffers */
195  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
196  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
197  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
198 
199  if (inbuf[0].pvBuffer == NULL) {
200  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
201  ret = AVERROR(ENOMEM);
202  goto fail;
203  }
204 
205  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
206 
207  /* output buffers */
208  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
209  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
210  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
211  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
212 
213  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags,
214  0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &c->context_flags,
215  &c->ctxt_timestamp);
216  av_freep(&inbuf[0].pvBuffer);
217 
218  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
219  av_log(h, AV_LOG_DEBUG, "Received incomplete handshake, need more data\n");
220  read_data = 1;
221  continue;
222  }
223 
224  /* remote requests a client certificate - attempt to continue without one anyway */
225  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
226  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
227  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
228  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
229  read_data = 0;
230  continue;
231  }
232 
233  /* continue handshake */
234  if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
235  for (i = 0; i < 3; i++) {
236  if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
237  ret = ffurl_write(c->tls_shared.tcp, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
238  if (ret < 0 || ret != outbuf[i].cbBuffer) {
239  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
240  ret = AVERROR(EIO);
241  goto fail;
242  }
243  }
244 
245  if (outbuf[i].pvBuffer != NULL) {
246  FreeContextBuffer(outbuf[i].pvBuffer);
247  outbuf[i].pvBuffer = NULL;
248  }
249  }
250  } else {
251  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
252  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
253  else
254  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
256  goto fail;
257  }
258 
259  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
260  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
261  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
262  inbuf[1].cbBuffer);
263  c->enc_buf_offset = inbuf[1].cbBuffer;
264  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
265  read_data = 0;
266  continue;
267  }
268  }
269  } else {
270  c->enc_buf_offset = 0;
271  }
272 
273  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
274  read_data = 1;
275  continue;
276  }
277 
278  break;
279  }
280 
281  return 0;
282 
283 fail:
284  /* free any remaining output data */
285  for (i = 0; i < 3; i++) {
286  if (outbuf[i].pvBuffer != NULL) {
287  FreeContextBuffer(outbuf[i].pvBuffer);
288  outbuf[i].pvBuffer = NULL;
289  }
290  }
291 
292  return ret;
293 }
294 
296 {
297  TLSContext *c = h->priv_data;
298  TLSShared *s = &c->tls_shared;
299  SecBuffer outbuf;
300  SecBufferDesc outbuf_desc;
301  SECURITY_STATUS sspi_ret;
302  int ret;
303 
304  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
305  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
306 
307  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
308  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
309  ISC_REQ_STREAM;
310 
311  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
312  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
313  &c->ctxt_timestamp);
314  if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
315  av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
317  goto fail;
318  }
319 
320  s->tcp->flags &= ~AVIO_FLAG_NONBLOCK;
321  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
322  FreeContextBuffer(outbuf.pvBuffer);
323  if (ret < 0 || ret != outbuf.cbBuffer) {
324  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
325  ret = AVERROR(EIO);
326  goto fail;
327  }
328 
329  return tls_client_handshake_loop(h, 1);
330 
331 fail:
332  DeleteSecurityContext(&c->ctxt_handle);
333  return ret;
334 }
335 
336 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
337 {
338  TLSContext *c = h->priv_data;
339  TLSShared *s = &c->tls_shared;
340  SECURITY_STATUS sspi_ret;
341  SCHANNEL_CRED schannel_cred = { 0 };
342  int ret;
343 
344  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
345  goto fail;
346 
347  if (s->listen) {
348  av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n");
349  ret = AVERROR(EINVAL);
350  goto fail;
351  }
352 
353  /* SChannel Options */
354  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
355 
356  if (s->verify)
357  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
358  SCH_CRED_REVOCATION_CHECK_CHAIN;
359  else
360  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
361  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
362  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
363 
364  /* Get credential handle */
365  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
366  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
367  &c->cred_timestamp);
368  if (sspi_ret != SEC_E_OK) {
369  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
371  goto fail;
372  }
373 
375  if (ret < 0)
376  goto fail;
377 
378  c->connected = 1;
379 
380  return 0;
381 
382 fail:
383  tls_close(h);
384  return ret;
385 }
386 
387 static int tls_read(URLContext *h, uint8_t *buf, int len)
388 {
389  TLSContext *c = h->priv_data;
390  TLSShared *s = &c->tls_shared;
391  SECURITY_STATUS sspi_ret = SEC_E_OK;
392  SecBuffer inbuf[4];
393  SecBufferDesc inbuf_desc;
394  int size, ret = 0;
395  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
396 
397  /* If we have some left-over data from previous network activity,
398  * return it first in case it is enough. It may contain
399  * data that is required to know whether this connection
400  * is still required or not, esp. in case of HTTP keep-alive
401  * connections. */
402  if (c->dec_buf_offset > 0)
403  goto cleanup;
404 
405  if (c->sspi_close_notify)
406  goto cleanup;
407 
408  if (!c->connection_closed) {
409  size = c->enc_buf_size - c->enc_buf_offset;
410  if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
411  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
412  if (c->enc_buf_size < min_enc_buf_size)
413  c->enc_buf_size = min_enc_buf_size;
414  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
415  if (ret < 0) {
416  c->enc_buf_size = c->enc_buf_offset = 0;
417  return ret;
418  }
419  }
420 
421  s->tcp->flags &= ~AVIO_FLAG_NONBLOCK;
422  s->tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK;
423 
424  ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset,
425  c->enc_buf_size - c->enc_buf_offset);
426  if (ret == AVERROR_EOF) {
427  c->connection_closed = 1;
428  ret = 0;
429  } else if (ret == AVERROR(EAGAIN)) {
430  ret = 0;
431  } else if (ret < 0) {
432  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
433  return ret;
434  }
435 
436  c->enc_buf_offset += ret;
437  }
438 
439  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
440  /* input buffer */
441  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
442 
443  /* additional buffers for possible output */
444  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
445  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
446  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
447  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
448 
449  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
450  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
451  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
452  /* handle decrypted data */
453  if (inbuf[1].BufferType == SECBUFFER_DATA) {
454  /* grow buffer if needed */
455  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
456  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
457  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
458  c->dec_buf_size = c->dec_buf_offset + size;
459  if (c->dec_buf_size < len)
460  c->dec_buf_size = len;
461  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
462  if (ret < 0) {
463  c->dec_buf_size = c->dec_buf_offset = 0;
464  return ret;
465  }
466  }
467 
468  /* copy decrypted data to buffer */
469  size = inbuf[1].cbBuffer;
470  if (size) {
471  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
472  c->dec_buf_offset += size;
473  }
474  }
475  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
476  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
477  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
478  inbuf[3].cbBuffer);
479  c->enc_buf_offset = inbuf[3].cbBuffer;
480  }
481  } else
482  c->enc_buf_offset = 0;
483 
484  if (sspi_ret == SEC_I_RENEGOTIATE) {
485  if (c->enc_buf_offset) {
486  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
488  goto cleanup;
489  }
490 
491  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
493  if (ret < 0) {
494  goto cleanup;
495  }
496  sspi_ret = SEC_E_OK;
497  continue;
498  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
499  c->sspi_close_notify = 1;
500  if (!c->connection_closed) {
501  c->connection_closed = 1;
502  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
503  }
504  ret = 0;
505  goto cleanup;
506  }
507  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
508  ret = AVERROR(EAGAIN);
509  goto cleanup;
510  } else {
511  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
512  ret = AVERROR(EIO);
513  goto cleanup;
514  }
515  }
516 
517  ret = 0;
518 
519 cleanup:
520  size = FFMIN(len, c->dec_buf_offset);
521  if (size) {
522  memcpy(buf, c->dec_buf, size);
523  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
524  c->dec_buf_offset -= size;
525 
526  return size;
527  }
528 
529  if (ret == 0 && !c->connection_closed)
530  ret = AVERROR(EAGAIN);
531 
532  return ret < 0 ? ret : AVERROR_EOF;
533 }
534 
535 static int tls_write(URLContext *h, const uint8_t *buf, int len)
536 {
537  TLSContext *c = h->priv_data;
538  TLSShared *s = &c->tls_shared;
539  SECURITY_STATUS sspi_ret;
540  int ret = 0, data_size;
541  uint8_t *data = NULL;
542  SecBuffer outbuf[4];
543  SecBufferDesc outbuf_desc;
544 
545  if (c->sizes.cbMaximumMessage == 0) {
546  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
547  if (sspi_ret != SEC_E_OK)
548  return AVERROR_UNKNOWN;
549  }
550 
551  /* limit how much data we can consume */
552  len = FFMIN(len, c->sizes.cbMaximumMessage);
553 
554  data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
555  data = av_malloc(data_size);
556  if (data == NULL)
557  return AVERROR(ENOMEM);
558 
559  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
560  data, c->sizes.cbHeader);
561  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
562  data + c->sizes.cbHeader, len);
563  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
564  data + c->sizes.cbHeader + len,
565  c->sizes.cbTrailer);
566  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
567  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
568 
569  memcpy(outbuf[1].pvBuffer, buf, len);
570 
571  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
572  if (sspi_ret == SEC_E_OK) {
573  len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
574 
575  s->tcp->flags &= ~AVIO_FLAG_NONBLOCK;
576  s->tcp->flags |= h->flags & AVIO_FLAG_NONBLOCK;
577 
578  ret = ffurl_write(s->tcp, data, len);
579  if (ret == AVERROR(EAGAIN)) {
580  goto done;
581  } else if (ret < 0 || ret != len) {
582  ret = AVERROR(EIO);
583  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
584  goto done;
585  }
586  } else {
587  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
588  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
589  ret = AVERROR(ENOMEM);
590  else
591  ret = AVERROR(EIO);
592  goto done;
593  }
594 
595 done:
596  av_freep(&data);
597  return ret < 0 ? ret : outbuf[1].cbBuffer;
598 }
599 
601 {
602  TLSContext *c = h->priv_data;
603  return ffurl_get_file_handle(c->tls_shared.tcp);
604 }
605 
607 {
608  TLSContext *s = h->priv_data;
609  return ffurl_get_short_seek(s->tls_shared.tcp);
610 }
611 
612 static const AVOption options[] = {
613  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
614  { NULL }
615 };
616 
617 static const AVClass tls_class = {
618  .class_name = "tls",
619  .item_name = av_default_item_name,
620  .option = options,
621  .version = LIBAVUTIL_VERSION_INT,
622 };
623 
625  .name = "tls",
626  .url_open2 = tls_open,
627  .url_read = tls_read,
628  .url_write = tls_write,
629  .url_close = tls_close,
630  .url_get_file_handle = tls_get_file_handle,
631  .url_get_short_seek = tls_get_short_seek,
632  .priv_data_size = sizeof(TLSContext),
634  .priv_data_class = &tls_class,
635 };
TLSContext
Definition: tls_gnutls.c:44
read_data
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1772
AVERROR
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
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
TLSContext::context_flags
ULONG context_flags
Definition: tls_schannel.c:55
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
TLSContext::request_flags
ULONG request_flags
Definition: tls_schannel.c:54
ffurl_write
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: url.h:202
SCHANNEL_FREE_BUFFER_SIZE
#define SCHANNEL_FREE_BUFFER_SIZE
Definition: tls_schannel.c:37
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
ff_tls_protocol
const URLProtocol ff_tls_protocol
Definition: tls_schannel.c:624
AVOption
AVOption.
Definition: opt.h:429
data
const char data[16]
Definition: mxf.c:149
options
static const AVOption options[]
Definition: tls_schannel.c:612
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
AVDictionary
Definition: dict.c:34
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
URLProtocol
Definition: url.h:51
os_support.h
TLSContext::dec_buf
uint8_t * dec_buf
Definition: tls_schannel.c:61
TLSContext::cred_handle
CredHandle cred_handle
Definition: tls_schannel.c:48
tls_class
static const AVClass tls_class
Definition: tls_schannel.c:617
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
tls_write
static int tls_write(URLContext *h, const uint8_t *buf, int len)
Definition: tls_schannel.c:535
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:46
fail
#define fail()
Definition: checkasm.h:188
ffurl_get_short_seek
int ffurl_get_short_seek(void *urlcontext)
Return the current short seek threshold value for this URL.
Definition: avio.c:838
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_schannel.c:336
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
TLSContext::sspi_close_notify
int sspi_close_notify
Definition: tls_schannel.c:69
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
init_sec_buffer_desc
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
Definition: tls_schannel.c:80
s
#define s(width, name)
Definition: cbs_vp9.c:198
TLSContext::dec_buf_offset
int dec_buf_offset
Definition: tls_schannel.c:63
tls_read
static int tls_read(URLContext *h, uint8_t *buf, int len)
Definition: tls_schannel.c:387
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
TLSContext::enc_buf_offset
int enc_buf_offset
Definition: tls_schannel.c:59
internal.h
SECBUFFER_ALERT
#define SECBUFFER_ALERT
Definition: tls_schannel.c:41
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
tls_shutdown_client
static int tls_shutdown_client(URLContext *h)
Definition: tls_schannel.c:88
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
init_sec_buffer
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
Definition: tls_schannel.c:72
c
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
tls_close
static int tls_close(URLContext *h)
Definition: tls_schannel.c:128
size
int size
Definition: twinvq_data.h:10344
av_reallocp
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:188
TLSContext::tls_shared
TLSShared tls_shared
Definition: tls_gnutls.c:46
URLProtocol::name
const char * name
Definition: url.h:52
TLSContext::enc_buf_size
int enc_buf_size
Definition: tls_schannel.c:58
URLContext
Definition: url.h:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
TLSContext::ctxt_timestamp
TimeStamp ctxt_timestamp
Definition: tls_schannel.c:52
TLSContext::connected
int connected
Definition: tls_schannel.c:67
TLSContext::ctxt_handle
CtxtHandle ctxt_handle
Definition: tls_schannel.c:51
tls_client_handshake
static int tls_client_handshake(URLContext *h)
Definition: tls_schannel.c:295
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
TLSContext::cred_timestamp
TimeStamp cred_timestamp
Definition: tls_schannel.c:49
url.h
len
int len
Definition: vorbis_enc_data.h:426
TLSContext::sizes
SecPkgContext_StreamSizes sizes
Definition: tls_schannel.c:65
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:588
ff_tls_open_underlying
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition: tls.c:67
ret
ret
Definition: filter_design.txt:187
SCHANNEL_INITIAL_BUFFER_SIZE
#define SCHANNEL_INITIAL_BUFFER_SIZE
Definition: tls_schannel.c:36
AVClass::class_name
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:80
avformat.h
network.h
TLSContext::enc_buf
uint8_t * enc_buf
Definition: tls_schannel.c:57
tls.h
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
desc
const char * desc
Definition: libsvtav1.c:79
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_schannel.c:600
mem.h
TLSShared
Definition: tls.h:29
AVIO_FLAG_NONBLOCK
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:636
TLSContext::connection_closed
int connection_closed
Definition: tls_schannel.c:68
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
tls_client_handshake_loop
static int tls_client_handshake_loop(URLContext *h, int initial)
Definition: tls_schannel.c:147
TLSContext::dec_buf_size
int dec_buf_size
Definition: tls_schannel.c:62
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:814
tls_get_short_seek
static int tls_get_short_seek(URLContext *h)
Definition: tls_schannel.c:606
ffurl_read
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition: url.h:181