[FFmpeg-devel] [PATCH] avformat: implement SChannel SSP TLS protocol
This implementation does not support TLS listen sockets and loading CA/Certs from files. The Windows API does not support loading PEM certs, and would either require a manual loader or instead be limited to loading Windows PFX certificates TLS listen sockets would have to be implemented quite separately, as many of the APIs are different for server-mode (as opposed to client mode). --- Because of the limitations in comparison to OpenSSL or GnuTLS, we might make this implementation not active by default, if someone feels like thats a better course of action. configure | 20 +- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/tls.h | 2 +- libavformat/tls_schannel.c | 601 + 5 files changed, 621 insertions(+), 4 deletions(-) create mode 100644 libavformat/tls_schannel.c diff --git a/configure b/configure index 5e7ded1..6b9b99c 100755 --- a/configure +++ b/configure @@ -280,6 +280,8 @@ External library support: --enable-opengl enable OpenGL rendering [no] --enable-openssl enable openssl, needed for https support if gnutls is not used [no] + --disable-schannel disable SChannel SSP, needed for TLS support on + Windows if openssl and gnutls are not used [autodetect] --disable-sdldisable sdl [autodetect] --disable-securetransport disable Secure Transport, needed for TLS support on OSX if openssl and gnutls are not used [autodetect] @@ -1465,6 +1467,7 @@ EXTERNAL_LIBRARY_LIST=" opencl opengl openssl +schannel sdl securetransport x11grab @@ -2754,13 +2757,15 @@ sctp_protocol_deps="struct_sctp_event_subscribe" sctp_protocol_select="network" srtp_protocol_select="rtp_protocol" tcp_protocol_select="network" -tls_gnutls_protocol_deps="gnutls !tls_securetransport_protocol" +tls_gnutls_protocol_deps="gnutls !tls_schannel_protocol !tls_securetransport_protocol" tls_gnutls_protocol_select="tcp_protocol" -tls_openssl_protocol_deps="openssl !tls_securetransport_protocol !tls_gnutls_protocol" +tls_openssl_protocol_deps="openssl !tls_schannel_protocol !tls_securetransport_protocol !tls_gnutls_protocol" tls_openssl_protocol_select="tcp_protocol" +tls_schannel_protocol_deps="schannel" +tls_schannel_protocol_select="tcp_protocol" tls_securetransport_protocol_deps="securetransport" tls_securetransport_protocol_select="tcp_protocol" -tls_protocol_deps_any="tls_securetransport_protocol tls_gnutls_protocol tls_openssl_protocol" +tls_protocol_deps_any="tls_schannel_protocol tls_securetransport_protocol tls_gnutls_protocol tls_openssl_protocol" udp_protocol_select="network" udplite_protocol_select="network" unix_protocol_deps="sys_un_h" @@ -5501,6 +5506,15 @@ disabled securetransport || { check_func SecIdentityCreate "-Wl,-framework,CoreF check_lib2 "Security/SecureTransport.h Security/Security.h" "SSLCreateContext SecItemImport" "-Wl,-framework,CoreFoundation -Wl,-framework,Security" && enable securetransport; } +if ! disabled schannel; then +check_cc < +#include +int main(void) { InitializeSecurityContext(NULL, NULL, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL); return 0; } +EOF +fi + makeinfo --version > /dev/null 2>&1 && enable makeinfo || disable makeinfo enabled makeinfo \ && [ 0$(makeinfo --version | grep "texinfo" | sed 's/.*texinfo[^0-9]*\([0-9]*\)\..*/\1/') -ge 5 ] \ diff --git a/libavformat/Makefile b/libavformat/Makefile index ded2d54..b2d6057 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -535,6 +535,7 @@ OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o OBJS-$(CONFIG_TLS_GNUTLS_PROTOCOL) += tls_gnutls.o tls.o OBJS-$(CONFIG_TLS_OPENSSL_PROTOCOL) += tls_openssl.o tls.o +OBJS-$(CONFIG_TLS_SCHANNEL_PROTOCOL) += tls_schannel.o tls.o OBJS-$(CONFIG_TLS_SECURETRANSPORT_PROTOCOL) += tls_securetransport.o tls.o OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 40fea8e..dad2644 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -387,6 +387,7 @@ void av_register_all(void) REGISTER_PROTOCOL(SRTP, srtp); REGISTER_PROTOCOL(SUBFILE, subfile); REGISTER_PROTOCOL(TCP, tcp); +REGISTER_PROTOCOL(TLS_SCHANNEL, tls_schannel); REGISTER_PROTOCOL(TLS_SECURETRANSPORT, tls_securetransport); REGISTER_PROTOCOL(TLS_GNUTLS, tls_gnutls); REGISTER_PROTOCOL(TLS_OPENSSL, tls_openssl); diff --git a/libavformat/tls.h b/libavformat/tls.h index 2a36f34..0326ef7 100644 --- a/libavformat/tls.h +++ b/libavformat/tls.h @@ -26,7 +26,7 @@ #include "url.h" #include "libavutil/opt.h" -#define CONFIG_TLS_PROTOCOL (CONFIG_TLS_GNUTLS_PROT
Re: [FFmpeg-devel] [PATCH] avformat: implement SChannel SSP TLS protocol
On Wed, Oct 21, 2015 at 1:52 PM, Hendrik Leppkes wrote: > This implementation does not support TLS listen sockets and loading > CA/Certs from files. > > The Windows API does not support loading PEM certs, and would either > require a manual loader or instead be limited to loading Windows PFX > certificates > > TLS listen sockets would have to be implemented quite separately, as many > of the APIs are different for server-mode (as opposed to client mode). > --- > > Because of the limitations in comparison to OpenSSL or GnuTLS, > we might make this implementation not active by default, if someone feels > like thats a better course of action. > > > configure | 20 +- > libavformat/Makefile | 1 + > libavformat/allformats.c | 1 + > libavformat/tls.h | 2 +- > libavformat/tls_schannel.c | 601 > + > 5 files changed, 621 insertions(+), 4 deletions(-) > create mode 100644 libavformat/tls_schannel.c > > diff --git a/configure b/configure > index 5e7ded1..6b9b99c 100755 > --- a/configure > +++ b/configure > @@ -280,6 +280,8 @@ External library support: >--enable-opengl enable OpenGL rendering [no] >--enable-openssl enable openssl, needed for https support > if gnutls is not used [no] > + --disable-schannel disable SChannel SSP, needed for TLS support on > + Windows if openssl and gnutls are not used > [autodetect] >--disable-sdldisable sdl [autodetect] >--disable-securetransport disable Secure Transport, needed for TLS support > on OSX if openssl and gnutls are not used > [autodetect] > @@ -1465,6 +1467,7 @@ EXTERNAL_LIBRARY_LIST=" > opencl > opengl > openssl > +schannel > sdl > securetransport > x11grab > @@ -2754,13 +2757,15 @@ sctp_protocol_deps="struct_sctp_event_subscribe" > sctp_protocol_select="network" > srtp_protocol_select="rtp_protocol" > tcp_protocol_select="network" > -tls_gnutls_protocol_deps="gnutls !tls_securetransport_protocol" > +tls_gnutls_protocol_deps="gnutls !tls_schannel_protocol > !tls_securetransport_protocol" > tls_gnutls_protocol_select="tcp_protocol" > -tls_openssl_protocol_deps="openssl !tls_securetransport_protocol > !tls_gnutls_protocol" > +tls_openssl_protocol_deps="openssl !tls_schannel_protocol > !tls_securetransport_protocol !tls_gnutls_protocol" > tls_openssl_protocol_select="tcp_protocol" > +tls_schannel_protocol_deps="schannel" > +tls_schannel_protocol_select="tcp_protocol" > tls_securetransport_protocol_deps="securetransport" > tls_securetransport_protocol_select="tcp_protocol" > -tls_protocol_deps_any="tls_securetransport_protocol tls_gnutls_protocol > tls_openssl_protocol" > +tls_protocol_deps_any="tls_schannel_protocol tls_securetransport_protocol > tls_gnutls_protocol tls_openssl_protocol" > udp_protocol_select="network" > udplite_protocol_select="network" > unix_protocol_deps="sys_un_h" > @@ -5501,6 +5506,15 @@ disabled securetransport || { check_func > SecIdentityCreate "-Wl,-framework,CoreF > check_lib2 "Security/SecureTransport.h Security/Security.h" > "SSLCreateContext SecItemImport" "-Wl,-framework,CoreFoundation > -Wl,-framework,Security" && > enable securetransport; } > > +if ! disabled schannel; then > +check_cc < +#define SECURITY_WIN32 > +#include > +#include > +int main(void) { InitializeSecurityContext(NULL, NULL, NULL, 0, 0, 0, NULL, > 0, NULL, NULL, NULL, NULL); return 0; } > +EOF > +fi > + > makeinfo --version > /dev/null 2>&1 && enable makeinfo || disable makeinfo > enabled makeinfo \ > && [ 0$(makeinfo --version | grep "texinfo" | sed > 's/.*texinfo[^0-9]*\([0-9]*\)\..*/\1/') -ge 5 ] \ > diff --git a/libavformat/Makefile b/libavformat/Makefile > index ded2d54..b2d6057 100644 > --- a/libavformat/Makefile > +++ b/libavformat/Makefile > @@ -535,6 +535,7 @@ OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o > OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o > OBJS-$(CONFIG_TLS_GNUTLS_PROTOCOL) += tls_gnutls.o tls.o > OBJS-$(CONFIG_TLS_OPENSSL_PROTOCOL) += tls_openssl.o tls.o > +OBJS-$(CONFIG_TLS_SCHANNEL_PROTOCOL) += tls_schannel.o tls.o > OBJS-$(CONFIG_TLS_SECURETRANSPORT_PROTOCOL) += tls_securetransport.o tls.o > OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o > OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o > diff --git a/libavformat/allformats.c b/libavformat/allformats.c > index 40fea8e..dad2644 100644 > --- a/libavformat/allformats.c > +++ b/libavformat/allformats.c > @@ -387,6 +387,7 @@ void av_register_all(void) > REGISTER_PROTOCOL(SRTP, srtp); > REGISTER_PROTOCOL(SUBFILE, subfile); > REGISTER_PROTOCOL(TCP, tcp); > +REGISTER_PROTOCOL(TLS_SCHANNEL, tls_schannel); > REGISTER_PROTOCOL(TLS_SECURETRANSPORT, tls_securetransport); > REGISTER_PROTOCOL(TLS_GNUTLS,
Re: [FFmpeg-devel] [PATCH] avformat: implement SChannel SSP TLS protocol
Enjoy my half-assed / useless review. > +#ifndef SECBUFFER_ALERT > +#define SECBUFFER_ALERT17 > +#endif Why? > +SecPkgContext_StreamSizes Sizes; Accidental capital? > +if (c->enc_buf == NULL) { > +c->enc_buf_offset = 0; > +c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE; > +ret = av_reallocp(&c->enc_buf, c->enc_buf_size); > +if (ret < 0) > +goto fail; I can never remember if _close() is guaranteed to be called. I'll assume yes. > +while (1) > +{ > +if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) > { Can enc_buf_offset ever end up bigger? e.. if data keeps being read, and you keep getting SEC_E_INCOMPLETE_MESSAGE. > +/* input buffers */ > +InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, > av_malloc(c->enc_buf_offset), c->enc_buf_offset); Is this a unchecked malloc, or is it passed into inbuf[0].pvBuffer? > + > +sspi_ret = InitializeSecurityContext(&c->cred_handle, > &c->ctxt_handle, s->host, c->request_flags, > + 0, 0, &inbuf_desc, 0, NULL, > &outbuf_desc, &c->context_flags, > + &c->ctxt_timestamp); > +av_freep(&inbuf[0].pvBuffer); Double checking: is this safe? > +/* SChannel Options */ > +memset(&schannel_cred, 0, sizeof(schannel_cred)); SCHANNEL_CRED schannel_cred = { 0 }; > +cleanup: > +size = len < c->dec_buf_offset ? len : c->dec_buf_offset; > +if (size) { > +memcpy(buf, c->dec_buf, size); > +memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size); > +c->dec_buf_offset -= size; > + > +return size; > +} > + > +if (ret == 0 && !c->connection_closed) > +ret = AVERROR(EAGAIN); > + > +return ret < 0 ? ret : 0; > + > +fail: > +return ret; No cleanup in case of failure? - Derek ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: implement SChannel SSP TLS protocol
On Wed, Oct 28, 2015 at 6:07 PM, Derek Buitenhuis wrote: > Enjoy my half-assed / useless review. > >> +#ifndef SECBUFFER_ALERT >> +#define SECBUFFER_ALERT17 >> +#endif > > Why? I think it was needed on some configuration, I'll verify. > >> +SecPkgContext_StreamSizes Sizes; > > Accidental capital? > >> +if (c->enc_buf == NULL) { >> +c->enc_buf_offset = 0; >> +c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE; >> +ret = av_reallocp(&c->enc_buf, c->enc_buf_size); >> +if (ret < 0) >> +goto fail; > > I can never remember if _close() is guaranteed to be called. I'll assume yes. > >> +while (1) >> +{ >> +if (c->enc_buf_size - c->enc_buf_offset < >> SCHANNEL_FREE_BUFFER_SIZE) { > > Can enc_buf_offset ever end up bigger? e.. if data keeps being read, and you > keep > getting SEC_E_INCOMPLETE_MESSAGE. Bigger than what, buf_size? it should grow that as necessary when data is received. > >> +/* input buffers */ >> +InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, >> av_malloc(c->enc_buf_offset), c->enc_buf_offset); > > Is this a unchecked malloc, or is it passed into inbuf[0].pvBuffer? Yes this ends up in inbuf[0].pvBuffer which is then checked. I could make it explicit before if people like. > >> + >> +sspi_ret = InitializeSecurityContext(&c->cred_handle, >> &c->ctxt_handle, s->host, c->request_flags, >> + 0, 0, &inbuf_desc, 0, NULL, >> &outbuf_desc, &c->context_flags, >> + &c->ctxt_timestamp); >> +av_freep(&inbuf[0].pvBuffer); > > Double checking: is this safe? Since this is the buffer we av_malloc'ed before, yes. > > >> +/* SChannel Options */ >> +memset(&schannel_cred, 0, sizeof(schannel_cred)); > > SCHANNEL_CRED schannel_cred = { 0 }; > >> +cleanup: >> +size = len < c->dec_buf_offset ? len : c->dec_buf_offset; >> +if (size) { >> +memcpy(buf, c->dec_buf, size); >> +memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size); >> +c->dec_buf_offset -= size; >> + >> +return size; >> +} >> + >> +if (ret == 0 && !c->connection_closed) >> +ret = AVERROR(EAGAIN); >> + >> +return ret < 0 ? ret : 0; >> + >> +fail: >> +return ret; > > No cleanup in case of failure? fail is only used for serious unrecoverable failures, like socket read failure or mem allocation failure. It could still call that code, I suppose, just in case some valid data is stuck in the decrypted buffer. > > - Derek > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel