Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
923ac2e5
Commit
923ac2e5
authored
Oct 31, 2012
by
Hiroshi Miura
Committed by
Alexandre Julliard
Nov 01, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wininet: Add a TLS fallback mechanism.
parent
c59efbed
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
127 additions
and
39 deletions
+127
-39
netconnection.c
dlls/wininet/netconnection.c
+127
-39
No files found.
dlls/wininet/netconnection.c
View file @
923ac2e5
...
...
@@ -124,8 +124,10 @@ MAKE_FUNCPTR(SSL_load_error_strings);
MAKE_FUNCPTR
(
SSLv23_method
);
MAKE_FUNCPTR
(
SSL_CTX_free
);
MAKE_FUNCPTR
(
SSL_CTX_new
);
MAKE_FUNCPTR
(
SSL_CTX_ctrl
);
MAKE_FUNCPTR
(
SSL_new
);
MAKE_FUNCPTR
(
SSL_free
);
MAKE_FUNCPTR
(
SSL_ctrl
);
MAKE_FUNCPTR
(
SSL_set_fd
);
MAKE_FUNCPTR
(
SSL_connect
);
MAKE_FUNCPTR
(
SSL_shutdown
);
...
...
@@ -446,7 +448,50 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
return
ret
;
}
static
long
get_tls_option
(
void
)
{
long
tls_option
=
SSL_OP_NO_SSLv2
;
/* disable SSLv2 for security reason, secur32/Schannel(GnuTLS) don't support it */
#ifdef SSL_OP_NO_TLSv1_2
DWORD
type
,
val
,
size
;
HKEY
hkey
,
tls12_client
,
tls11_client
;
LONG
res
;
const
WCHAR
Schannel_Prot
[]
=
{
/* SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCANNEL\\Protocols */
'S'
,
'Y'
,
'S'
,
'T'
,
'E'
,
'M'
,
'\\'
,
'C'
,
'u'
,
'r'
,
'r'
,
'e'
,
'n'
,
't'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'S'
,
'e'
,
't'
,
'\\'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'\\'
,
'S'
,
'e'
,
'c'
,
'u'
,
'r'
,
'i'
,
't'
,
'y'
,
'P'
,
'r'
,
'o'
,
'v'
,
'i'
,
'd'
,
'e'
,
'r'
,
's'
,
'\\'
,
'S'
,
'C'
,
'H'
,
'A'
,
'N'
,
'N'
,
'E'
,
'L'
,
'\\'
,
'P'
,
'r'
,
'o'
,
't'
,
'o'
,
'c'
,
'o'
,
'l'
,
's'
,
0
};
const
WCHAR
TLS12_Client
[]
=
{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'2'
,
'\\'
,
'C'
,
'l'
,
'i'
,
'e'
,
'n'
,
't'
,
0
};
const
WCHAR
TLS11_Client
[]
=
{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'1'
,
'\\'
,
'C'
,
'l'
,
'i'
,
'e'
,
'n'
,
't'
,
0
};
const
WCHAR
DisabledByDefault
[]
=
{
'D'
,
'i'
,
's'
,
'a'
,
'b'
,
'l'
,
'e'
,
'd'
,
'B'
,
'y'
,
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
0
};
res
=
RegOpenKeyExW
(
HKEY_LOCAL_MACHINE
,
Schannel_Prot
,
0
,
KEY_READ
,
&
hkey
);
if
(
res
!=
ERROR_SUCCESS
)
{
/* enabled TLSv1.1/1.2 when no registry entry */
return
tls_option
;
}
if
(
RegOpenKeyExW
(
hkey
,
TLS12_Client
,
0
,
KEY_READ
,
&
tls12_client
)
==
ERROR_SUCCESS
)
{
size
=
sizeof
(
DWORD
);
if
(
RegQueryValueExW
(
tls12_client
,
DisabledByDefault
,
NULL
,
&
type
,
(
LPBYTE
)
&
val
,
&
size
)
==
ERROR_SUCCESS
&&
type
==
REG_DWORD
)
{
tls_option
|=
val
?
SSL_OP_NO_TLSv1_2
:
0
;
}
RegCloseKey
(
tls12_client
);
}
if
(
RegOpenKeyExW
(
hkey
,
TLS11_Client
,
0
,
KEY_READ
,
&
tls11_client
)
==
ERROR_SUCCESS
)
{
size
=
sizeof
(
DWORD
);
if
(
RegQueryValueExW
(
tls11_client
,
DisabledByDefault
,
NULL
,
&
type
,
(
LPBYTE
)
&
val
,
&
size
)
==
ERROR_SUCCESS
&&
type
==
REG_DWORD
)
{
tls_option
|=
val
?
SSL_OP_NO_TLSv1_1
:
0
;
}
RegCloseKey
(
tls11_client
);
}
RegCloseKey
(
hkey
);
#endif
return
tls_option
;
}
#endif
/* SONAME_LIBSSL */
static
CRITICAL_SECTION
init_ssl_cs
;
static
CRITICAL_SECTION_DEBUG
init_ssl_cs_debug
=
...
...
@@ -491,8 +536,10 @@ static DWORD init_openssl(void)
DYNSSL
(
SSLv23_method
);
DYNSSL
(
SSL_CTX_free
);
DYNSSL
(
SSL_CTX_new
);
DYNSSL
(
SSL_CTX_ctrl
);
DYNSSL
(
SSL_new
);
DYNSSL
(
SSL_free
);
DYNSSL
(
SSL_ctrl
);
DYNSSL
(
SSL_set_fd
);
DYNSSL
(
SSL_connect
);
DYNSSL
(
SSL_shutdown
);
...
...
@@ -534,12 +581,18 @@ static DWORD init_openssl(void)
DYNCRYPTO
(
sk_value
);
#undef DYNCRYPTO
#define pSSL_CTX_set_options(ctx,op) \
pSSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
#define pSSL_set_options(ssl,op) \
pSSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
pSSL_library_init
();
pSSL_load_error_strings
();
pBIO_new_fp
(
stderr
,
BIO_NOCLOSE
);
/* FIXME: should use winedebug stuff */
meth
=
pSSLv23_method
();
ctx
=
pSSL_CTX_new
(
meth
);
pSSL_CTX_set_options
(
ctx
,
get_tls_option
());
if
(
!
pSSL_CTX_set_default_verify_paths
(
ctx
))
{
ERR
(
"SSL_CTX_set_default_verify_paths failed: %s
\n
"
,
pERR_error_string
(
pERR_get_error
(),
0
));
...
...
@@ -580,33 +633,10 @@ static DWORD init_openssl(void)
#endif
}
DWORD
create_netconn
(
BOOL
useSSL
,
server_t
*
server
,
DWORD
security_flags
,
BOOL
mask_errors
,
DWORD
timeout
,
netconn_t
**
re
t
)
static
DWORD
create_netconn_socket
(
server_t
*
server
,
netconn_t
*
netconn
,
DWORD
timeou
t
)
{
netconn_t
*
netconn
;
int
result
,
flag
;
if
(
useSSL
)
{
DWORD
res
;
TRACE
(
"using SSL connection
\n
"
);
EnterCriticalSection
(
&
init_ssl_cs
);
res
=
init_openssl
();
LeaveCriticalSection
(
&
init_ssl_cs
);
if
(
res
!=
ERROR_SUCCESS
)
return
res
;
}
netconn
=
heap_alloc_zero
(
sizeof
(
*
netconn
));
if
(
!
netconn
)
return
ERROR_OUTOFMEMORY
;
netconn
->
useSSL
=
useSSL
;
netconn
->
socketFD
=
-
1
;
netconn
->
security_flags
=
security_flags
|
server
->
security_flags
;
netconn
->
mask_errors
=
mask_errors
;
list_init
(
&
netconn
->
pool_entry
);
assert
(
server
->
addr_len
);
result
=
netconn
->
socketFD
=
socket
(
server
->
addr
.
ss_family
,
SOCK_STREAM
,
0
);
if
(
result
!=
-
1
)
{
...
...
@@ -656,11 +686,42 @@ DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL m
WARN
(
"setsockopt(TCP_NODELAY) failed
\n
"
);
#endif
return
ERROR_SUCCESS
;
}
DWORD
create_netconn
(
BOOL
useSSL
,
server_t
*
server
,
DWORD
security_flags
,
BOOL
mask_errors
,
DWORD
timeout
,
netconn_t
**
ret
)
{
netconn_t
*
netconn
;
int
result
;
if
(
useSSL
)
{
DWORD
res
;
TRACE
(
"using SSL connection
\n
"
);
EnterCriticalSection
(
&
init_ssl_cs
);
res
=
init_openssl
();
LeaveCriticalSection
(
&
init_ssl_cs
);
if
(
res
!=
ERROR_SUCCESS
)
return
res
;
}
netconn
=
heap_alloc_zero
(
sizeof
(
*
netconn
));
if
(
!
netconn
)
return
ERROR_OUTOFMEMORY
;
netconn
->
useSSL
=
useSSL
;
netconn
->
socketFD
=
-
1
;
netconn
->
security_flags
=
security_flags
|
server
->
security_flags
;
netconn
->
mask_errors
=
mask_errors
;
list_init
(
&
netconn
->
pool_entry
);
result
=
create_netconn_socket
(
server
,
netconn
,
timeout
);
server_addref
(
server
);
netconn
->
server
=
server
;
*
ret
=
netconn
;
return
ERROR_SUCCESS
;
return
result
;
}
void
free_netconn
(
netconn_t
*
netconn
)
...
...
@@ -772,24 +833,13 @@ int sock_get_error( int err )
return
err
;
}
/******************************************************************************
* NETCON_secure_connect
* Initiates a secure connection over an existing plaintext connection.
*/
DWORD
NETCON_secure_connect
(
netconn_t
*
connection
)
{
DWORD
res
=
ERROR_NOT_SUPPORTED
;
#ifdef SONAME_LIBSSL
static
DWORD
netcon_secure_connect_setup
(
netconn_t
*
connection
,
long
tls_option
)
{
void
*
ssl_s
;
DWORD
res
;
int
bits
;
/* can't connect if we are already connected */
if
(
connection
->
ssl_s
)
{
ERR
(
"already connected
\n
"
);
return
ERROR_INTERNET_CANNOT_CONNECT
;
}
ssl_s
=
pSSL_new
(
ctx
);
if
(
!
ssl_s
)
{
...
...
@@ -798,6 +848,7 @@ DWORD NETCON_secure_connect(netconn_t *connection)
return
ERROR_OUTOFMEMORY
;
}
pSSL_set_options
(
ssl_s
,
tls_option
);
if
(
!
pSSL_set_fd
(
ssl_s
,
connection
->
socketFD
))
{
ERR
(
"SSL_set_fd failed: %s
\n
"
,
...
...
@@ -843,6 +894,43 @@ fail:
pSSL_shutdown
(
ssl_s
);
pSSL_free
(
ssl_s
);
}
return
res
;
}
#endif
/******************************************************************************
* NETCON_secure_connect
* Initiates a secure connection over an existing plaintext connection.
*/
DWORD
NETCON_secure_connect
(
netconn_t
*
connection
)
{
DWORD
res
=
ERROR_NOT_SUPPORTED
;
#ifdef SONAME_LIBSSL
/* can't connect if we are already connected */
if
(
connection
->
ssl_s
)
{
ERR
(
"already connected
\n
"
);
return
ERROR_INTERNET_CANNOT_CONNECT
;
}
/* connect with given TLS options */
res
=
netcon_secure_connect_setup
(
connection
,
get_tls_option
());
if
(
res
==
ERROR_SUCCESS
)
return
res
;
#ifdef SSL_OP_NO_TLSv1_2
/* FIXME: when got version alert and FIN from server */
/* fallback to connect without TLSv1.1/TLSv1.2 */
if
(
res
==
ERROR_INTERNET_SECURITY_CHANNEL_ERROR
)
{
closesocket
(
connection
->
socketFD
);
pSSL_CTX_set_options
(
ctx
,
SSL_OP_NO_TLSv1_1
|
SSL_OP_NO_TLSv1_2
);
res
=
create_netconn_socket
(
connection
->
server
,
connection
,
500
);
if
(
res
!=
ERROR_SUCCESS
)
return
res
;
res
=
netcon_secure_connect_setup
(
connection
,
get_tls_option
()
|
SSL_OP_NO_TLSv1_1
|
SSL_OP_NO_TLSv1_2
);
}
#endif
#endif
return
res
;
}
...
...
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