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
f93284df
Commit
f93284df
authored
Mar 10, 2021
by
Hans Leidekker
Committed by
Alexandre Julliard
Mar 10, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
secur32: Add DTLS support.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
37b29862
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
75 additions
and
19 deletions
+75
-19
schannel.c
dlls/secur32/schannel.c
+38
-17
schannel_gnutls.c
dlls/secur32/schannel_gnutls.c
+37
-2
No files found.
dlls/secur32/schannel.c
View file @
f93284df
...
...
@@ -60,6 +60,7 @@ struct schan_context
struct
schan_transport
transport
;
ULONG
req_ctx_attr
;
const
CERT_CONTEXT
*
cert
;
SIZE_T
header_size
;
};
static
struct
schan_handle
*
schan_handle_table
;
...
...
@@ -184,7 +185,9 @@ static void read_config(void)
{{
'S'
,
'S'
,
'L'
,
' '
,
'3'
,
'.'
,
'0'
,
0
},
SP_PROT_SSL3_CLIENT
,
TRUE
,
FALSE
},
{{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'0'
,
0
},
SP_PROT_TLS1_0_CLIENT
,
TRUE
,
FALSE
},
{{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'1'
,
0
},
SP_PROT_TLS1_1_CLIENT
,
TRUE
,
FALSE
/* NOTE: not enabled by default on Windows */
},
{{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'2'
,
0
},
SP_PROT_TLS1_2_CLIENT
,
TRUE
,
FALSE
/* NOTE: not enabled by default on Windows */
}
{{
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'2'
,
0
},
SP_PROT_TLS1_2_CLIENT
,
TRUE
,
FALSE
/* NOTE: not enabled by default on Windows */
},
{{
'D'
,
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'0'
,
0
},
SP_PROT_DTLS1_0_CLIENT
,
TRUE
,
TRUE
},
{{
'D'
,
'T'
,
'L'
,
'S'
,
' '
,
'1'
,
'.'
,
'2'
,
0
},
SP_PROT_DTLS1_2_CLIENT
,
TRUE
,
TRUE
},
};
/* No need for thread safety */
...
...
@@ -399,10 +402,17 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
if
(
schanCred
)
{
const
unsigned
dtls_protocols
=
SP_PROT_DTLS_CLIENT
|
SP_PROT_DTLS1_2_CLIENT
;
const
unsigned
tls_protocols
=
SP_PROT_TLS1_CLIENT
|
SP_PROT_TLS1_0_CLIENT
|
SP_PROT_TLS1_1_CLIENT
|
SP_PROT_TLS1_2_CLIENT
|
SP_PROT_TLS1_3_CLIENT
;
status
=
get_cert
(
schanCred
,
&
cert
);
if
(
status
!=
SEC_E_OK
&&
status
!=
SEC_E_NO_CREDENTIALS
)
return
status
;
if
((
schanCred
->
grbitEnabledProtocols
&
tls_protocols
)
&&
(
schanCred
->
grbitEnabledProtocols
&
dtls_protocols
))
return
SEC_E_ALGORITHM_MISMATCH
;
status
=
SEC_E_OK
;
}
...
...
@@ -773,12 +783,18 @@ static void dump_buffer_desc(SecBufferDesc *desc)
}
#define HEADER_SIZE_TLS 5
#define HEADER_SIZE_DTLS 13
static
inline
SIZE_T
read_record_size
(
const
BYTE
*
buf
,
SIZE_T
header_size
)
{
return
(
buf
[
header_size
-
2
]
<<
8
)
|
buf
[
header_size
-
1
];
}
static
inline
BOOL
is_dtls_context
(
const
struct
schan_context
*
ctx
)
{
return
(
ctx
->
header_size
==
HEADER_SIZE_DTLS
);
}
/***********************************************************************
* InitializeSecurityContextW
*/
...
...
@@ -836,6 +852,11 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
return
SEC_E_INTERNAL_ERROR
;
}
if
(
cred
->
enabled_protocols
&
(
SP_PROT_DTLS1_0_CLIENT
|
SP_PROT_DTLS1_2_CLIENT
))
ctx
->
header_size
=
HEADER_SIZE_DTLS
;
else
ctx
->
header_size
=
HEADER_SIZE_TLS
;
ctx
->
transport
.
ctx
=
ctx
;
schan_imp_set_session_transport
(
ctx
->
session
,
&
ctx
->
transport
);
...
...
@@ -866,9 +887,9 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
SIZE_T
record_size
=
0
;
unsigned
char
*
ptr
;
if
(
!
pInput
)
return
SEC_E_INCOMPLETE_MESSAGE
;
ctx
=
schan_get_object
(
phContext
->
dwLower
,
SCHAN_HANDLE_CTX
);
if
(
pInput
)
{
idx
=
schan_find_sec_buffer_idx
(
pInput
,
0
,
SECBUFFER_TOKEN
);
if
(
idx
==
-
1
)
return
SEC_E_INCOMPLETE_MESSAGE
;
...
...
@@ -877,9 +898,9 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
ptr
=
buffer
->
pvBuffer
;
expected_size
=
0
;
while
(
buffer
->
cbBuffer
>
expected_size
+
HEADER_SIZE_TLS
)
while
(
buffer
->
cbBuffer
>
expected_size
+
ctx
->
header_size
)
{
record_size
=
HEADER_SIZE_TLS
+
read_record_size
(
ptr
,
HEADER_SIZE_TLS
);
record_size
=
ctx
->
header_size
+
read_record_size
(
ptr
,
ctx
->
header_size
);
if
(
buffer
->
cbBuffer
<
expected_size
+
record_size
)
break
;
...
...
@@ -894,10 +915,10 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
max
(
6
,
record_size
),
buffer
->
cbBuffer
);
return
SEC_E_INCOMPLETE_MESSAGE
;
}
}
else
if
(
!
is_dtls_context
(
ctx
))
return
SEC_E_INCOMPLETE_MESSAGE
;
TRACE
(
"Using expected_size %lu.
\n
"
,
expected_size
);
ctx
=
schan_get_object
(
phContext
->
dwLower
,
SCHAN_HANDLE_CTX
);
}
ctx
->
req_ctx_attr
=
fContextReq
;
...
...
@@ -1038,11 +1059,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
unsigned
int
block_size
=
schan_imp_get_session_cipher_block_size
(
ctx
->
session
);
unsigned
int
message_size
=
schan_imp_get_max_message_size
(
ctx
->
session
);
TRACE
(
"Using
%lu mac bytes
, message size %u, block size %u
\n
"
,
mac_size
,
message_size
,
block_size
);
TRACE
(
"Using
header size %lu mac bytes %lu
, message size %u, block size %u
\n
"
,
ctx
->
header_size
,
mac_size
,
message_size
,
block_size
);
/* These are defined by the TLS RFC */
stream_sizes
->
cbHeader
=
HEADER_SIZE_TLS
;
stream_sizes
->
cbHeader
=
ctx
->
header_size
;
stream_sizes
->
cbTrailer
=
mac_size
+
256
;
/* Max 255 bytes padding + 1 for padding size */
stream_sizes
->
cbMaximumMessage
=
message_size
;
stream_sizes
->
cbBuffers
=
4
;
...
...
@@ -1367,7 +1388,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
buffer
=
&
message
->
pBuffers
[
idx
];
buf_ptr
=
buffer
->
pvBuffer
;
expected_size
=
HEADER_SIZE_TLS
+
read_record_size
(
buf_ptr
,
HEADER_SIZE_TLS
);
expected_size
=
ctx
->
header_size
+
read_record_size
(
buf_ptr
,
ctx
->
header_size
);
if
(
buffer
->
cbBuffer
<
expected_size
)
{
TRACE
(
"Expected %u bytes, but buffer only contains %u bytes
\n
"
,
expected_size
,
buffer
->
cbBuffer
);
...
...
@@ -1384,7 +1405,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
return
SEC_E_INCOMPLETE_MESSAGE
;
}
data_size
=
expected_size
-
HEADER_SIZE_TLS
;
data_size
=
expected_size
-
ctx
->
header_size
;
data
=
heap_alloc
(
data_size
);
init_schan_buffers
(
&
ctx
->
transport
.
in
,
message
,
schan_decrypt_message_get_next_buffer
);
...
...
@@ -1419,21 +1440,21 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
TRACE
(
"Received %ld bytes
\n
"
,
received
);
memcpy
(
buf_ptr
+
HEADER_SIZE_TLS
,
data
,
received
);
memcpy
(
buf_ptr
+
ctx
->
header_size
,
data
,
received
);
heap_free
(
data
);
schan_decrypt_fill_buffer
(
message
,
SECBUFFER_DATA
,
buf_ptr
+
HEADER_SIZE_TLS
,
received
);
buf_ptr
+
ctx
->
header_size
,
received
);
schan_decrypt_fill_buffer
(
message
,
SECBUFFER_STREAM_TRAILER
,
buf_ptr
+
HEADER_SIZE_TLS
+
received
,
buffer
->
cbBuffer
-
HEADER_SIZE_TLS
-
received
);
buf_ptr
+
ctx
->
header_size
+
received
,
buffer
->
cbBuffer
-
ctx
->
header_size
-
received
);
if
(
buffer
->
cbBuffer
>
expected_size
)
schan_decrypt_fill_buffer
(
message
,
SECBUFFER_EXTRA
,
buf_ptr
+
expected_size
,
buffer
->
cbBuffer
-
expected_size
);
buffer
->
BufferType
=
SECBUFFER_STREAM_HEADER
;
buffer
->
cbBuffer
=
HEADER_SIZE_TLS
;
buffer
->
cbBuffer
=
ctx
->
header_size
;
return
status
;
}
...
...
dlls/secur32/schannel_gnutls.c
View file @
f93284df
...
...
@@ -50,6 +50,10 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
/* Not present in gnutls version < 2.9.10. */
static
int
(
*
pgnutls_cipher_get_block_size
)(
gnutls_cipher_algorithm_t
);
/* Not present in gnutls version < 3.0. */
static
void
(
*
pgnutls_transport_set_pull_timeout_function
)(
gnutls_session_t
,
int
(
*
)(
gnutls_transport_ptr_t
,
unsigned
int
));
/* Not present in gnutls version < 3.2.0. */
static
int
(
*
pgnutls_alpn_get_selected_protocol
)(
gnutls_session_t
,
gnutls_datum_t
*
);
static
int
(
*
pgnutls_alpn_set_protocols
)(
gnutls_session_t
,
const
gnutls_datum_t
*
,
...
...
@@ -147,6 +151,12 @@ static int compat_cipher_get_block_size(gnutls_cipher_algorithm_t cipher)
}
}
static
void
compat_gnutls_transport_set_pull_timeout_function
(
gnutls_session_t
session
,
int
(
*
func
)(
gnutls_transport_ptr_t
,
unsigned
int
))
{
FIXME
(
"
\n
"
);
}
static
int
compat_gnutls_privkey_export_x509
(
gnutls_privkey_t
privkey
,
gnutls_x509_privkey_t
*
key
)
{
FIXME
(
"
\n
"
);
...
...
@@ -212,6 +222,8 @@ static const struct {
DWORD
enable_flag
;
const
char
*
gnutls_flag
;
}
protocol_priority_flags
[]
=
{
{
SP_PROT_DTLS1_2_CLIENT
,
"VERS-DTLS1.2"
},
{
SP_PROT_DTLS1_0_CLIENT
,
"VERS-DTLS1.0"
},
{
SP_PROT_TLS1_3_CLIENT
,
"VERS-TLS1.3"
},
{
SP_PROT_TLS1_2_CLIENT
,
"VERS-TLS1.2"
},
{
SP_PROT_TLS1_1_CLIENT
,
"VERS-TLS1.1"
},
...
...
@@ -257,14 +269,29 @@ DWORD schan_imp_enabled_protocols(void)
return
supported_protocols
;
}
static
int
schan_pull_timeout
(
gnutls_transport_ptr_t
transport
,
unsigned
int
timeout
)
{
struct
schan_transport
*
t
=
(
struct
schan_transport
*
)
transport
;
SIZE_T
count
=
0
;
if
(
schan_get_buffer
(
t
,
&
t
->
in
,
&
count
))
return
1
;
return
0
;
}
BOOL
schan_imp_create_session
(
schan_imp_session
*
session
,
schan_credentials
*
cred
)
{
gnutls_session_t
*
s
=
(
gnutls_session_t
*
)
session
;
char
priority
[
128
]
=
"NORMAL:%LATEST_RECORD_VERSION"
,
*
p
;
BOOL
using_vers_all
=
FALSE
,
disabled
;
unsigned
i
;
unsigned
int
i
,
flags
=
(
cred
->
credential_use
==
SECPKG_CRED_INBOUND
)
?
GNUTLS_SERVER
:
GNUTLS_CLIENT
;
int
err
;
int
err
=
pgnutls_init
(
s
,
cred
->
credential_use
==
SECPKG_CRED_INBOUND
?
GNUTLS_SERVER
:
GNUTLS_CLIENT
);
if
(
cred
->
enabled_protocols
&
(
SP_PROT_DTLS1_0_CLIENT
|
SP_PROT_DTLS1_2_CLIENT
))
{
flags
|=
GNUTLS_DATAGRAM
|
GNUTLS_NONBLOCK
;
}
err
=
pgnutls_init
(
s
,
flags
);
if
(
err
!=
GNUTLS_E_SUCCESS
)
{
pgnutls_perror
(
err
);
...
...
@@ -315,6 +342,7 @@ BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cre
}
pgnutls_transport_set_pull_function
(
*
s
,
schan_pull_adapter
);
if
(
flags
&
GNUTLS_DATAGRAM
)
pgnutls_transport_set_pull_timeout_function
(
*
s
,
schan_pull_timeout
);
pgnutls_transport_set_push_function
(
*
s
,
schan_push_adapter
);
return
TRUE
;
...
...
@@ -400,6 +428,8 @@ static DWORD schannel_get_protocol(gnutls_protocol_t proto)
case
GNUTLS_TLS1_0
:
return
SP_PROT_TLS1_0_CLIENT
;
case
GNUTLS_TLS1_1
:
return
SP_PROT_TLS1_1_CLIENT
;
case
GNUTLS_TLS1_2
:
return
SP_PROT_TLS1_2_CLIENT
;
case
GNUTLS_DTLS1_0
:
return
SP_PROT_DTLS1_0_CLIENT
;
case
GNUTLS_DTLS1_2
:
return
SP_PROT_DTLS1_2_CLIENT
;
default:
FIXME
(
"unknown protocol %d
\n
"
,
proto
);
return
0
;
...
...
@@ -1085,6 +1115,11 @@ BOOL schan_imp_init(void)
WARN
(
"gnutls_cipher_get_block_size not found
\n
"
);
pgnutls_cipher_get_block_size
=
compat_cipher_get_block_size
;
}
if
(
!
(
pgnutls_transport_set_pull_timeout_function
=
dlsym
(
libgnutls_handle
,
"gnutls_transport_set_pull_timeout_function"
)))
{
WARN
(
"gnutls_transport_set_pull_timeout_function not found
\n
"
);
pgnutls_transport_set_pull_timeout_function
=
compat_gnutls_transport_set_pull_timeout_function
;
}
if
(
!
(
pgnutls_alpn_set_protocols
=
dlsym
(
libgnutls_handle
,
"gnutls_alpn_set_protocols"
)))
{
WARN
(
"gnutls_alpn_set_protocols not found
\n
"
);
...
...
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