Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
f24d92ba
Commit
f24d92ba
authored
May 28, 2015
by
Rodger Combs
Committed by
Michael Niedermayer
May 29, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavf/tls: Support Secure Transport
Signed-off-by:
Michael Niedermayer
<
michaelni@gmx.at
>
parent
bedb5d58
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
413 additions
and
7 deletions
+413
-7
Changelog
Changelog
+1
-0
configure
configure
+11
-3
Makefile
libavformat/Makefile
+1
-0
allformats.c
libavformat/allformats.c
+1
-0
avio.c
libavformat/avio.c
+3
-1
tls.h
libavformat/tls.h
+1
-1
tls_securetransport.c
libavformat/tls_securetransport.c
+393
-0
version.h
libavformat/version.h
+2
-2
No files found.
Changelog
View file @
f24d92ba
...
...
@@ -23,6 +23,7 @@ version <next>:
- VP9 high bit-depth and extended colorspaces decoding support
- WebPAnimEncoder API when available for encoding and muxing WebP
- Direct3D11-accelerated decoding
- Support Secure Transport
version 2.6:
...
...
configure
View file @
f24d92ba
...
...
@@ -276,6 +276,8 @@ External library support:
--enable-openssl enable openssl, needed for https support
if gnutls is not used [no]
--disable-sdl disable sdl [autodetect]
--disable-securetransport disable Secure Transport, needed for TLS support
on OSX if openssl and gnutls are not used [autodetect]
--enable-x11grab enable X11 grabbing (legacy) [no]
--disable-xlib disable xlib [autodetect]
--disable-zlib disable zlib [autodetect]
...
...
@@ -1424,6 +1426,7 @@ EXTERNAL_LIBRARY_LIST="
opengl
openssl
sdl
securetransport
x11grab
xlib
zlib
...
...
@@ -2636,9 +2639,10 @@ 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_openssl_protocol_deps
=
"openssl !tls_gnutls_protocol"
tls_protocol_deps_any
=
"tls_gnutls_protocol tls_openssl_protocol"
tls_securetransport_protocol_deps
=
"securetransport"
tls_gnutls_protocol_deps
=
"gnutls !tls_securetransport_protocol"
tls_openssl_protocol_deps
=
"openssl !tls_securetransport_protocol !tls_gnutls_protocol"
tls_protocol_deps_any
=
"tls_securetransport_protocol tls_gnutls_protocol tls_openssl_protocol"
tls_protocol_select
=
"tcp_protocol"
udp_protocol_select
=
"network"
udplite_protocol_select
=
"network"
...
...
@@ -5213,6 +5217,10 @@ if ! disabled sdl; then
fi
enabled sdl
&&
add_cflags
$sdl_cflags
&&
add_extralibs
$sdl_libs
disabled securetransport
||
{
check_func SecIdentityCreate
"-Wl,-framework,CoreFoundation -Wl,-framework,Security"
&&
check_lib2 Security/SecureTransport.h SSLCreateContext
"-Wl,-framework,CoreFoundation -Wl,-framework,Security"
&&
enable
securetransport
;
}
makeinfo
--version
>
/dev/null 2>&1
&&
enable
makeinfo
||
disable makeinfo
enabled makeinfo
&&
(
makeinfo
--version
|
\
grep
-q
'makeinfo (GNU texinfo) 5'
>
/dev/null 2>&1
)
\
...
...
libavformat/Makefile
View file @
f24d92ba
...
...
@@ -523,6 +523,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_SECURETRANSPORT_PROTOCOL)
+=
tls_securetransport.o
tls.o
OBJS-$(CONFIG_UDP_PROTOCOL)
+=
udp.o
OBJS-$(CONFIG_UDPLITE_PROTOCOL)
+=
udp.o
OBJS-$(CONFIG_UNIX_PROTOCOL)
+=
unix.o
...
...
libavformat/allformats.c
View file @
f24d92ba
...
...
@@ -377,6 +377,7 @@ void av_register_all(void)
REGISTER_PROTOCOL
(
SRTP
,
srtp
);
REGISTER_PROTOCOL
(
SUBFILE
,
subfile
);
REGISTER_PROTOCOL
(
TCP
,
tcp
);
REGISTER_PROTOCOL
(
TLS_SECURETRANSPORT
,
tls_securetransport
);
REGISTER_PROTOCOL
(
TLS_GNUTLS
,
tls_gnutls
);
REGISTER_PROTOCOL
(
TLS_OPENSSL
,
tls_openssl
);
REGISTER_PROTOCOL
(
UDP
,
udp
);
...
...
libavformat/avio.c
View file @
f24d92ba
...
...
@@ -263,7 +263,9 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
*
puc
=
NULL
;
if
(
av_strstart
(
filename
,
"https:"
,
NULL
))
av_log
(
NULL
,
AV_LOG_WARNING
,
"https protocol not found, recompile with openssl or gnutls enabled.
\n
"
);
av_log
(
NULL
,
AV_LOG_WARNING
,
"https protocol not found, recompile with "
"openssl, gnutls,
\n
"
"or securetransport enabled.
\n
"
);
return
AVERROR_PROTOCOL_NOT_FOUND
;
}
...
...
libavformat/tls.h
View file @
f24d92ba
...
...
@@ -26,7 +26,7 @@
#include "url.h"
#include "libavutil/opt.h"
#define CONFIG_TLS_PROTOCOL (CONFIG_TLS_GNUTLS_PROTOCOL | CONFIG_TLS_OPENSSL_PROTOCOL)
#define CONFIG_TLS_PROTOCOL (CONFIG_TLS_GNUTLS_PROTOCOL | CONFIG_TLS_OPENSSL_PROTOCOL
| CONFIG_TLS_SECURETRANSPORT_PROTOCOL
)
typedef
struct
TLSShared
{
char
*
ca_file
;
...
...
libavformat/tls_securetransport.c
0 → 100644
View file @
f24d92ba
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpeg; if not, write to the Free Software * Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include "avformat.h"
#include "internal.h"
#include "network.h"
#include "os_support.h"
#include "url.h"
#include "tls.h"
#include "libavcodec/internal.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include <Security/Security.h>
#include <Security/SecureTransport.h>
#include <CoreFoundation/CoreFoundation.h>
// We use a private API call here; it's good enough for WebKit.
SecIdentityRef
SecIdentityCreate
(
CFAllocatorRef
allocator
,
SecCertificateRef
certificate
,
SecKeyRef
privateKey
);
#define ioErr -36
typedef
struct
TLSContext
{
const
AVClass
*
class
;
TLSShared
tls_shared
;
SSLContextRef
ssl_context
;
CFArrayRef
ca_array
;
int
lastErr
;
}
TLSContext
;
static
int
print_tls_error
(
URLContext
*
h
,
int
ret
)
{
TLSContext
*
c
=
h
->
priv_data
;
switch
(
ret
)
{
case
errSSLWouldBlock
:
break
;
case
errSSLXCertChainInvalid
:
av_log
(
h
,
AV_LOG_ERROR
,
"Invalid certificate chain
\n
"
);
return
AVERROR
(
EIO
);
case
ioErr
:
return
c
->
lastErr
;
default:
av_log
(
h
,
AV_LOG_ERROR
,
"IO Error: %i
\n
"
,
ret
);
return
AVERROR
(
EIO
);
}
return
AVERROR
(
EIO
);
}
static
int
import_pem
(
URLContext
*
h
,
char
*
path
,
CFArrayRef
*
array
)
{
AVIOContext
*
s
=
NULL
;
CFDataRef
data
=
NULL
;
int64_t
ret
=
0
;
char
*
buf
=
NULL
;
SecExternalFormat
format
=
kSecFormatPEMSequence
;
SecExternalFormat
type
=
kSecItemTypeAggregate
;
CFStringRef
pathStr
=
CFStringCreateWithCString
(
NULL
,
path
,
0x08000100
);
if
(
!
pathStr
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
if
((
ret
=
avio_open2
(
&
s
,
path
,
AVIO_FLAG_READ
,
&
h
->
interrupt_callback
,
NULL
))
<
0
)
goto
end
;
if
((
ret
=
avio_size
(
s
))
<
0
)
goto
end
;
if
(
ret
==
0
)
{
ret
=
AVERROR_INVALIDDATA
;
goto
end
;
}
if
(
!
(
buf
=
av_malloc
(
ret
)))
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
if
((
ret
=
avio_read
(
s
,
buf
,
ret
))
<
0
)
goto
end
;
data
=
CFDataCreate
(
kCFAllocatorDefault
,
buf
,
ret
);
if
(
SecItemImport
(
data
,
pathStr
,
&
format
,
&
type
,
0
,
NULL
,
NULL
,
array
)
!=
noErr
||
!
array
)
{
ret
=
AVERROR_UNKNOWN
;
goto
end
;
}
if
(
CFArrayGetCount
(
*
array
)
==
0
)
{
ret
=
AVERROR_INVALIDDATA
;
goto
end
;
}
end:
av_free
(
buf
);
if
(
pathStr
)
CFRelease
(
pathStr
);
if
(
data
)
CFRelease
(
data
);
if
(
s
)
avio_close
(
s
);
return
ret
;
}
static
int
load_ca
(
URLContext
*
h
)
{
TLSContext
*
c
=
h
->
priv_data
;
int
ret
=
0
;
CFArrayRef
array
=
NULL
;
if
((
ret
=
import_pem
(
h
,
c
->
tls_shared
.
ca_file
,
&
array
))
<
0
)
goto
end
;
if
(
!
(
c
->
ca_array
=
CFRetain
(
array
)))
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
end:
if
(
array
)
CFRelease
(
array
);
return
ret
;
}
static
int
load_cert
(
URLContext
*
h
)
{
TLSContext
*
c
=
h
->
priv_data
;
int
ret
=
0
;
CFArrayRef
certArray
=
NULL
;
CFArrayRef
keyArray
=
NULL
;
SecIdentityRef
id
=
NULL
;
CFMutableArrayRef
outArray
=
NULL
;
if
((
ret
=
import_pem
(
h
,
c
->
tls_shared
.
cert_file
,
&
certArray
))
<
0
)
goto
end
;
if
((
ret
=
import_pem
(
h
,
c
->
tls_shared
.
key_file
,
&
keyArray
))
<
0
)
goto
end
;
if
(
!
(
id
=
SecIdentityCreate
(
kCFAllocatorDefault
,
(
SecCertificateRef
)
CFArrayGetValueAtIndex
(
certArray
,
0
),
(
SecKeyRef
)
CFArrayGetValueAtIndex
(
keyArray
,
0
))))
{
ret
=
AVERROR_UNKNOWN
;
goto
end
;
}
if
(
!
(
outArray
=
CFArrayCreateMutableCopy
(
kCFAllocatorDefault
,
0
,
certArray
)))
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
CFArraySetValueAtIndex
(
outArray
,
0
,
id
);
SSLSetCertificate
(
c
->
ssl_context
,
outArray
);
end:
if
(
certArray
)
CFRelease
(
certArray
);
if
(
keyArray
)
CFRelease
(
keyArray
);
if
(
outArray
)
CFRelease
(
outArray
);
if
(
id
)
CFRelease
(
id
);
return
ret
;
}
static
OSStatus
tls_read_cb
(
SSLConnectionRef
connection
,
void
*
data
,
size_t
*
dataLength
)
{
URLContext
*
h
=
(
URLContext
*
)
connection
;
TLSContext
*
c
=
h
->
priv_data
;
int
read
=
ffurl_read_complete
(
c
->
tls_shared
.
tcp
,
data
,
*
dataLength
);
if
(
read
<=
0
)
{
*
dataLength
=
0
;
switch
(
AVUNERROR
(
read
))
{
case
ENOENT
:
case
0
:
return
errSSLClosedGraceful
;
case
ECONNRESET
:
return
errSSLClosedAbort
;
case
EAGAIN
:
return
errSSLWouldBlock
;
default:
c
->
lastErr
=
read
;
return
ioErr
;
}
}
else
{
*
dataLength
=
read
;
return
noErr
;
}
}
static
OSStatus
tls_write_cb
(
SSLConnectionRef
connection
,
const
void
*
data
,
size_t
*
dataLength
)
{
URLContext
*
h
=
(
URLContext
*
)
connection
;
TLSContext
*
c
=
h
->
priv_data
;
int
written
=
ffurl_write
(
c
->
tls_shared
.
tcp
,
data
,
*
dataLength
);
if
(
written
<=
0
)
{
*
dataLength
=
0
;
switch
(
AVUNERROR
(
written
))
{
case
EAGAIN
:
return
errSSLWouldBlock
;
default:
c
->
lastErr
=
written
;
return
ioErr
;
}
}
else
{
*
dataLength
=
written
;
return
noErr
;
}
}
static
int
tls_close
(
URLContext
*
h
)
{
TLSContext
*
c
=
h
->
priv_data
;
if
(
c
->
ssl_context
)
{
SSLClose
(
c
->
ssl_context
);
CFRelease
(
c
->
ssl_context
);
}
if
(
c
->
ca_array
)
CFRelease
(
c
->
ca_array
);
if
(
c
->
tls_shared
.
tcp
)
ffurl_close
(
c
->
tls_shared
.
tcp
);
return
0
;
}
#define CHECK_ERROR(func, ...) do { \
OSStatus status = func(__VA_ARGS__); \
if (status != noErr) { \
ret = AVERROR_UNKNOWN; \
av_log(h, AV_LOG_ERROR, #func ": Error %i\n", (int)status); \
goto fail; \
} \
} while (0)
static
int
tls_open
(
URLContext
*
h
,
const
char
*
uri
,
int
flags
,
AVDictionary
**
options
)
{
TLSContext
*
c
=
h
->
priv_data
;
TLSShared
*
s
=
&
c
->
tls_shared
;
int
ret
;
if
((
ret
=
ff_tls_open_underlying
(
s
,
h
,
uri
,
options
))
<
0
)
goto
fail
;
c
->
ssl_context
=
SSLCreateContext
(
NULL
,
s
->
listen
?
kSSLServerSide
:
kSSLClientSide
,
kSSLStreamType
);
if
(
!
c
->
ssl_context
)
{
av_log
(
h
,
AV_LOG_ERROR
,
"Unable to create SSL context
\n
"
);
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
if
(
s
->
ca_file
)
{
if
((
ret
=
load_ca
(
h
))
<
0
)
goto
fail
;
CHECK_ERROR
(
SSLSetSessionOption
,
c
->
ssl_context
,
kSSLSessionOptionBreakOnServerAuth
,
true
);
}
if
(
s
->
cert_file
)
if
((
ret
=
load_cert
(
h
))
<
0
)
goto
fail
;
if
(
s
->
verify
)
CHECK_ERROR
(
SSLSetPeerDomainName
,
c
->
ssl_context
,
s
->
host
,
strlen
(
s
->
host
));
CHECK_ERROR
(
SSLSetIOFuncs
,
c
->
ssl_context
,
tls_read_cb
,
tls_write_cb
);
CHECK_ERROR
(
SSLSetConnection
,
c
->
ssl_context
,
h
);
while
(
1
)
{
OSStatus
status
=
SSLHandshake
(
c
->
ssl_context
);
if
(
status
==
errSSLServerAuthCompleted
)
{
SecTrustRef
peerTrust
;
SecTrustResultType
trustResult
;
if
(
!
s
->
verify
)
continue
;
if
(
SSLCopyPeerTrust
(
c
->
ssl_context
,
&
peerTrust
)
!=
noErr
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
if
(
SecTrustSetAnchorCertificates
(
peerTrust
,
c
->
ca_array
)
!=
noErr
)
{
ret
=
AVERROR_UNKNOWN
;
goto
fail
;
}
if
(
SecTrustEvaluate
(
peerTrust
,
&
trustResult
)
!=
noErr
)
{
ret
=
AVERROR_UNKNOWN
;
goto
fail
;
}
if
(
trustResult
==
kSecTrustResultProceed
||
trustResult
==
kSecTrustResultUnspecified
)
{
// certificate is trusted
status
=
errSSLWouldBlock
;
// so we call SSLHandshake again
}
else
if
(
trustResult
==
kSecTrustResultRecoverableTrustFailure
)
{
// not trusted, for some reason other than being expired
status
=
errSSLXCertChainInvalid
;
}
else
{
// cannot use this certificate (fatal)
status
=
errSSLBadCert
;
}
if
(
peerTrust
)
CFRelease
(
peerTrust
);
}
if
(
status
==
noErr
)
break
;
av_log
(
h
,
AV_LOG_ERROR
,
"Unable to negotiate TLS/SSL session: %i
\n
"
,
(
int
)
status
);
ret
=
AVERROR
(
EIO
);
goto
fail
;
}
return
0
;
fail:
tls_close
(
h
);
return
ret
;
}
static
int
map_ssl_error
(
OSStatus
status
,
size_t
processed
)
{
switch
(
status
)
{
case
noErr
:
return
processed
;
case
errSSLClosedGraceful
:
case
errSSLClosedNoNotify
:
return
0
;
default:
return
(
int
)
status
;
}
}
static
int
tls_read
(
URLContext
*
h
,
uint8_t
*
buf
,
int
size
)
{
TLSContext
*
c
=
h
->
priv_data
;
size_t
processed
;
int
ret
=
map_ssl_error
(
SSLRead
(
c
->
ssl_context
,
buf
,
size
,
&
processed
),
processed
);
if
(
ret
>
0
)
return
ret
;
if
(
ret
==
0
)
return
AVERROR_EOF
;
return
print_tls_error
(
h
,
ret
);
}
static
int
tls_write
(
URLContext
*
h
,
const
uint8_t
*
buf
,
int
size
)
{
TLSContext
*
c
=
h
->
priv_data
;
size_t
processed
;
int
ret
=
map_ssl_error
(
SSLWrite
(
c
->
ssl_context
,
buf
,
size
,
&
processed
),
processed
);
if
(
ret
>
0
)
return
ret
;
if
(
ret
==
0
)
return
AVERROR_EOF
;
return
print_tls_error
(
h
,
ret
);
}
static
const
AVOption
options
[]
=
{
TLS_COMMON_OPTIONS
(
TLSContext
,
tls_shared
),
{
NULL
}
};
static
const
AVClass
tls_class
=
{
.
class_name
=
"tls"
,
.
item_name
=
av_default_item_name
,
.
option
=
options
,
.
version
=
LIBAVUTIL_VERSION_INT
,
};
URLProtocol
ff_tls_securetransport_protocol
=
{
.
name
=
"tls"
,
.
url_open2
=
tls_open
,
.
url_read
=
tls_read
,
.
url_write
=
tls_write
,
.
url_close
=
tls_close
,
.
priv_data_size
=
sizeof
(
TLSContext
),
.
flags
=
URL_PROTOCOL_FLAG_NETWORK
,
.
priv_data_class
=
&
tls_class
,
};
libavformat/version.h
View file @
f24d92ba
...
...
@@ -30,8 +30,8 @@
#include "libavutil/version.h"
#define LIBAVFORMAT_VERSION_MAJOR 56
#define LIBAVFORMAT_VERSION_MINOR 3
3
#define LIBAVFORMAT_VERSION_MICRO 10
1
#define LIBAVFORMAT_VERSION_MINOR 3
4
#define LIBAVFORMAT_VERSION_MICRO 10
0
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment