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
11afc2da
Commit
11afc2da
authored
Jun 20, 2023
by
Hans Leidekker
Committed by
Alexandre Julliard
Jun 22, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
secur32: Add support for sending TLS alerts.
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=55086
parent
aaf051ff
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
165 additions
and
29 deletions
+165
-29
schannel.c
dlls/secur32/schannel.c
+34
-10
schannel_gnutls.c
dlls/secur32/schannel_gnutls.c
+76
-17
secur32_priv.h
dlls/secur32/secur32_priv.h
+5
-2
schannel.c
dlls/secur32/tests/schannel.c
+13
-0
schannel.h
include/schannel.h
+37
-0
No files found.
dlls/secur32/schannel.c
View file @
11afc2da
...
...
@@ -63,7 +63,9 @@ struct schan_context
ULONG
req_ctx_attr
;
const
CERT_CONTEXT
*
cert
;
SIZE_T
header_size
;
BOOL
shutdown_requested
;
enum
control_token
control_token
;
unsigned
int
alert_type
;
unsigned
int
alert_number
;
};
static
struct
schan_handle
*
schan_handle_table
;
...
...
@@ -865,9 +867,9 @@ static SECURITY_STATUS establish_context(
unsigned
char
*
ptr
;
if
(
phContext
&&
!
(
ctx
=
schan_get_object
(
phContext
->
dwLower
,
SCHAN_HANDLE_CTX
)))
return
SEC_E_INVALID_HANDLE
;
if
(
!
pInput
&&
!
ctx
->
shutdown_requested
&&
!
is_dtls_context
(
ctx
))
return
SEC_E_INCOMPLETE_MESSAGE
;
if
(
!
pInput
&&
!
ctx
->
control_token
&&
!
is_dtls_context
(
ctx
))
return
SEC_E_INCOMPLETE_MESSAGE
;
if
(
!
ctx
->
shutdown_requested
&&
pInput
)
if
(
!
ctx
->
control_token
&&
pInput
)
{
if
(
!
validate_input_buffers
(
pInput
))
return
SEC_E_INVALID_TOKEN
;
if
((
idx
=
schan_find_sec_buffer_idx
(
pInput
,
0
,
SECBUFFER_TOKEN
))
==
-
1
)
return
SEC_E_INCOMPLETE_MESSAGE
;
...
...
@@ -940,8 +942,10 @@ static SECURITY_STATUS establish_context(
params
.
input_offset
=
&
input_offset
;
params
.
output_buffer_idx
=
&
output_buffer_idx
;
params
.
output_offset
=
&
output_offset
;
params
.
control_token
=
ctx
->
shutdown_requested
?
control_token_shutdown
:
control_token_none
;
ctx
->
shutdown_requested
=
FALSE
;
params
.
control_token
=
ctx
->
control_token
;
params
.
alert_type
=
ctx
->
alert_type
;
params
.
alert_number
=
ctx
->
alert_number
;
ctx
->
control_token
=
CONTROL_TOKEN_NONE
;
ret
=
GNUTLS_CALL
(
handshake
,
&
params
);
if
(
output_buffer_idx
!=
-
1
)
...
...
@@ -1588,23 +1592,43 @@ static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context
static
SECURITY_STATUS
SEC_ENTRY
schan_ApplyControlToken
(
PCtxtHandle
context_handle
,
PSecBufferDesc
input
)
{
struct
schan_context
*
ctx
;
DWORD
type
;
TRACE
(
"%p %p
\n
"
,
context_handle
,
input
);
dump_buffer_desc
(
input
);
if
(
!
context_handle
)
return
SEC_E_INVALID_HANDLE
;
if
(
!
context_handle
||
!
(
ctx
=
schan_get_object
(
context_handle
->
dwLower
,
SCHAN_HANDLE_CTX
)))
return
SEC_E_INVALID_HANDLE
;
if
(
!
input
)
return
SEC_E_INTERNAL_ERROR
;
if
(
input
->
cBuffers
!=
1
)
return
SEC_E_INVALID_TOKEN
;
if
(
input
->
pBuffers
[
0
].
BufferType
!=
SECBUFFER_TOKEN
)
return
SEC_E_INVALID_TOKEN
;
if
(
input
->
pBuffers
[
0
].
cbBuffer
<
sizeof
(
DWORD
))
return
SEC_E_UNSUPPORTED_FUNCTION
;
if
(
*
(
DWORD
*
)
input
->
pBuffers
[
0
].
pvBuffer
!=
SCHANNEL_SHUTDOWN
)
return
SEC_E_UNSUPPORTED_FUNCTION
;
if
(
input
->
pBuffers
[
0
].
cbBuffer
<
sizeof
(
type
))
return
SEC_E_UNSUPPORTED_FUNCTION
;
type
=
*
(
DWORD
*
)
input
->
pBuffers
[
0
].
pvBuffer
;
ctx
=
schan_get_object
(
context_handle
->
dwLower
,
SCHAN_HANDLE_CTX
);
ctx
->
shutdown_requested
=
TRUE
;
switch
(
type
)
{
case
SCHANNEL_SHUTDOWN
:
ctx
->
control_token
=
CONTROL_TOKEN_SHUTDOWN
;
ctx
->
alert_type
=
TLS1_ALERT_WARNING
;
ctx
->
alert_number
=
TLS1_ALERT_CLOSE_NOTIFY
;
return
SEC_E_OK
;
case
SCHANNEL_ALERT
:
{
SCHANNEL_ALERT_TOKEN
*
alert
=
input
->
pBuffers
[
0
].
pvBuffer
;
if
(
input
->
pBuffers
[
0
].
cbBuffer
<
sizeof
(
*
alert
))
return
SEC_E_INVALID_TOKEN
;
ctx
->
control_token
=
CONTROL_TOKEN_ALERT
;
ctx
->
alert_type
=
alert
->
dwAlertType
;
ctx
->
alert_number
=
alert
->
dwAlertNumber
;
return
SEC_E_OK
;
}
default:
FIXME
(
"token type %lu not supported
\n
"
,
type
);
return
SEC_E_UNSUPPORTED_FUNCTION
;
}
}
static
const
SecurityFunctionTableA
schanTableA
=
{
...
...
dlls/secur32/schannel_gnutls.c
View file @
11afc2da
...
...
@@ -84,6 +84,7 @@ static void *libgnutls_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR
(
gnutls_alert_get
);
MAKE_FUNCPTR
(
gnutls_alert_get_name
);
MAKE_FUNCPTR
(
gnutls_alert_send
);
MAKE_FUNCPTR
(
gnutls_certificate_allocate_credentials
);
MAKE_FUNCPTR
(
gnutls_certificate_free_credentials
);
MAKE_FUNCPTR
(
gnutls_certificate_get_peers
);
...
...
@@ -121,7 +122,6 @@ MAKE_FUNCPTR(gnutls_x509_crt_deinit);
MAKE_FUNCPTR
(
gnutls_x509_crt_import
);
MAKE_FUNCPTR
(
gnutls_x509_crt_init
);
MAKE_FUNCPTR
(
gnutls_x509_privkey_deinit
);
MAKE_FUNCPTR
(
gnutls_alert_send
);
#undef MAKE_FUNCPTR
#if GNUTLS_VERSION_MAJOR < 3
...
...
@@ -566,6 +566,74 @@ static NTSTATUS schan_set_session_target( void *args )
return
STATUS_SUCCESS
;
}
static
gnutls_alert_level_t
map_alert_type
(
unsigned
int
type
)
{
switch
(
type
)
{
case
TLS1_ALERT_WARNING
:
return
GNUTLS_AL_WARNING
;
case
TLS1_ALERT_FATAL
:
return
GNUTLS_AL_FATAL
;
default:
FIXME
(
"unknown type %u
\n
"
,
type
);
return
-
1
;
}
}
static
gnutls_alert_description_t
map_alert_number
(
unsigned
int
number
)
{
switch
(
number
)
{
case
TLS1_ALERT_CLOSE_NOTIFY
:
return
GNUTLS_A_CLOSE_NOTIFY
;
case
TLS1_ALERT_UNEXPECTED_MESSAGE
:
return
GNUTLS_A_UNEXPECTED_MESSAGE
;
case
TLS1_ALERT_BAD_RECORD_MAC
:
return
GNUTLS_A_BAD_RECORD_MAC
;
case
TLS1_ALERT_DECRYPTION_FAILED
:
return
GNUTLS_A_DECRYPTION_FAILED
;
case
TLS1_ALERT_RECORD_OVERFLOW
:
return
GNUTLS_A_RECORD_OVERFLOW
;
case
TLS1_ALERT_DECOMPRESSION_FAIL
:
return
GNUTLS_A_DECOMPRESSION_FAILURE
;
case
TLS1_ALERT_HANDSHAKE_FAILURE
:
return
GNUTLS_A_HANDSHAKE_FAILURE
;
case
TLS1_ALERT_BAD_CERTIFICATE
:
return
GNUTLS_A_BAD_CERTIFICATE
;
case
TLS1_ALERT_UNSUPPORTED_CERT
:
return
GNUTLS_A_UNSUPPORTED_CERTIFICATE
;
case
TLS1_ALERT_CERTIFICATE_REVOKED
:
return
GNUTLS_A_CERTIFICATE_REVOKED
;
case
TLS1_ALERT_CERTIFICATE_EXPIRED
:
return
GNUTLS_A_CERTIFICATE_EXPIRED
;
case
TLS1_ALERT_CERTIFICATE_UNKNOWN
:
return
GNUTLS_A_CERTIFICATE_UNKNOWN
;
case
TLS1_ALERT_ILLEGAL_PARAMETER
:
return
GNUTLS_A_ILLEGAL_PARAMETER
;
case
TLS1_ALERT_UNKNOWN_CA
:
return
GNUTLS_A_UNKNOWN_CA
;
case
TLS1_ALERT_ACCESS_DENIED
:
return
GNUTLS_A_ACCESS_DENIED
;
case
TLS1_ALERT_DECODE_ERROR
:
return
GNUTLS_A_DECODE_ERROR
;
case
TLS1_ALERT_DECRYPT_ERROR
:
return
GNUTLS_A_DECRYPT_ERROR
;
case
TLS1_ALERT_EXPORT_RESTRICTION
:
return
GNUTLS_A_EXPORT_RESTRICTION
;
case
TLS1_ALERT_PROTOCOL_VERSION
:
return
GNUTLS_A_PROTOCOL_VERSION
;
case
TLS1_ALERT_INSUFFIENT_SECURITY
:
return
GNUTLS_A_INSUFFICIENT_SECURITY
;
case
TLS1_ALERT_INTERNAL_ERROR
:
return
GNUTLS_A_INTERNAL_ERROR
;
case
TLS1_ALERT_USER_CANCELED
:
return
GNUTLS_A_USER_CANCELED
;
case
TLS1_ALERT_NO_RENEGOTIATION
:
return
GNUTLS_A_NO_RENEGOTIATION
;
case
TLS1_ALERT_UNSUPPORTED_EXT
:
return
GNUTLS_A_UNSUPPORTED_EXTENSION
;
case
TLS1_ALERT_UNKNOWN_PSK_IDENTITY
:
return
GNUTLS_A_UNKNOWN_PSK_IDENTITY
;
case
TLS1_ALERT_NO_APP_PROTOCOL
:
return
GNUTLS_A_NO_APPLICATION_PROTOCOL
;
default:
FIXME
(
"unhandled alert %u
\n
"
,
number
);
return
-
1
;
}
}
static
NTSTATUS
send_alert
(
gnutls_session_t
session
,
unsigned
int
type
,
unsigned
int
number
)
{
gnutls_alert_level_t
level
=
map_alert_type
(
type
);
gnutls_alert_description_t
desc
=
map_alert_number
(
number
);
int
ret
;
do
{
ret
=
pgnutls_alert_send
(
session
,
level
,
desc
);
}
while
(
ret
==
GNUTLS_E_INTERRUPTED
||
ret
==
GNUTLS_E_AGAIN
);
if
(
ret
<
0
)
{
pgnutls_perror
(
ret
);
return
SEC_E_INTERNAL_ERROR
;
}
return
SEC_E_OK
;
}
static
NTSTATUS
schan_handshake
(
void
*
args
)
{
const
struct
handshake_params
*
params
=
args
;
...
...
@@ -578,22 +646,9 @@ static NTSTATUS schan_handshake( void *args )
t
->
in
.
limit
=
params
->
input_size
;
init_schan_buffers
(
&
t
->
out
,
params
->
output
);
if
(
params
->
control_token
==
control_token_shutdown
)
{
err
=
pgnutls_alert_send
(
s
,
GNUTLS_AL_WARNING
,
GNUTLS_A_CLOSE_NOTIFY
);
if
(
err
==
GNUTLS_E_SUCCESS
)
{
status
=
SEC_E_OK
;
}
else
if
(
err
==
GNUTLS_E_AGAIN
)
{
status
=
SEC_E_INVALID_TOKEN
;
}
else
if
(
params
->
control_token
)
{
pgnutls_perror
(
err
);
status
=
SEC_E_INTERNAL_ERROR
;
}
status
=
send_alert
(
s
,
params
->
alert_type
,
params
->
alert_number
);
goto
done
;
}
...
...
@@ -1431,6 +1486,7 @@ static NTSTATUS process_attach( void *args )
LOAD_FUNCPTR
(
gnutls_alert_get
)
LOAD_FUNCPTR
(
gnutls_alert_get_name
)
LOAD_FUNCPTR
(
gnutls_alert_send
)
LOAD_FUNCPTR
(
gnutls_certificate_allocate_credentials
)
LOAD_FUNCPTR
(
gnutls_certificate_free_credentials
)
LOAD_FUNCPTR
(
gnutls_certificate_get_peers
)
...
...
@@ -1468,7 +1524,6 @@ static NTSTATUS process_attach( void *args )
LOAD_FUNCPTR
(
gnutls_x509_crt_import
)
LOAD_FUNCPTR
(
gnutls_x509_crt_init
)
LOAD_FUNCPTR
(
gnutls_x509_privkey_deinit
)
LOAD_FUNCPTR
(
gnutls_alert_send
)
#undef LOAD_FUNCPTR
if
(
!
(
pgnutls_cipher_get_block_size
=
dlsym
(
libgnutls_handle
,
"gnutls_cipher_get_block_size"
)))
...
...
@@ -1751,6 +1806,8 @@ static NTSTATUS wow64_schan_handshake( void *args )
PTR32
output_buffer_idx
;
PTR32
output_offset
;
enum
control_token
control_token
;
unsigned
int
alert_type
;
unsigned
int
alert_number
;
}
const
*
params32
=
args
;
struct
handshake_params
params
=
{
...
...
@@ -1762,6 +1819,8 @@ static NTSTATUS wow64_schan_handshake( void *args )
ULongToPtr
(
params32
->
output_buffer_idx
),
ULongToPtr
(
params32
->
output_offset
),
params32
->
control_token
,
params32
->
alert_type
,
params32
->
alert_number
,
};
if
(
params32
->
input
)
{
...
...
dlls/secur32/secur32_priv.h
View file @
11afc2da
...
...
@@ -147,8 +147,9 @@ struct get_unique_channel_binding_params
enum
control_token
{
control_token_none
,
control_token_shutdown
,
CONTROL_TOKEN_NONE
,
CONTROL_TOKEN_SHUTDOWN
,
CONTROL_TOKEN_ALERT
,
};
struct
handshake_params
...
...
@@ -161,6 +162,8 @@ struct handshake_params
int
*
output_buffer_idx
;
ULONG
*
output_offset
;
enum
control_token
control_token
;
unsigned
int
alert_type
;
unsigned
int
alert_number
;
};
struct
recv_params
...
...
dlls/secur32/tests/schannel.c
View file @
11afc2da
...
...
@@ -1963,6 +1963,7 @@ static void test_connection_shutdown(void)
CredHandle
cred_handle
;
SCHANNEL_CRED
cred
;
SecBuffer
*
buf
;
SCHANNEL_ALERT_TOKEN
alert
;
ULONG
attrs
;
void
*
tmp
;
...
...
@@ -2075,6 +2076,18 @@ static void test_connection_shutdown(void)
ok
(
buf
->
cbBuffer
==
sizeof
(
message
),
"got cbBuffer %#lx.
\n
"
,
buf
->
cbBuffer
);
ok
(
!
memcmp
(
buf
->
pvBuffer
,
message
,
sizeof
(
message
)
),
"message data mismatch.
\n
"
);
alert
.
dwTokenType
=
SCHANNEL_ALERT
;
alert
.
dwAlertType
=
TLS1_ALERT_FATAL
;
alert
.
dwAlertNumber
=
TLS1_ALERT_BAD_CERTIFICATE
;
memcpy
(
buf
->
pvBuffer
,
&
alert
,
sizeof
(
alert
));
buf
->
cbBuffer
=
sizeof
(
alert
);
status
=
ApplyControlToken
(
&
context
,
buffers
);
ok
(
status
==
SEC_E_OK
,
"got %08lx.
\n
"
,
status
);
status
=
InitializeSecurityContextA
(
&
cred_handle
,
&
context
,
NULL
,
0
,
0
,
0
,
NULL
,
0
,
NULL
,
&
buffers
[
1
],
&
attrs
,
NULL
);
ok
(
status
==
SEC_E_OK
,
"got %08lx.
\n
"
,
status
);
free_buffers
(
&
buffers
[
0
]
);
free_buffers
(
&
buffers
[
1
]
);
DeleteSecurityContext
(
&
context
);
...
...
include/schannel.h
View file @
11afc2da
...
...
@@ -88,6 +88,43 @@ static const WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l',0 };
#define SCHANNEL_ALERT 2
#define SCHANNEL_SESSION 3
typedef
struct
_SCHANNEL_ALERT_TOKEN
{
DWORD
dwTokenType
;
DWORD
dwAlertType
;
DWORD
dwAlertNumber
;
}
SCHANNEL_ALERT_TOKEN
;
#define TLS1_ALERT_WARNING 1
#define TLS1_ALERT_FATAL 2
#define TLS1_ALERT_CLOSE_NOTIFY 0
#define TLS1_ALERT_UNEXPECTED_MESSAGE 10
#define TLS1_ALERT_BAD_RECORD_MAC 20
#define TLS1_ALERT_DECRYPTION_FAILED 21
#define TLS1_ALERT_RECORD_OVERFLOW 22
#define TLS1_ALERT_DECOMPRESSION_FAIL 30
#define TLS1_ALERT_HANDSHAKE_FAILURE 40
#define TLS1_ALERT_BAD_CERTIFICATE 42
#define TLS1_ALERT_UNSUPPORTED_CERT 43
#define TLS1_ALERT_CERTIFICATE_REVOKED 44
#define TLS1_ALERT_CERTIFICATE_EXPIRED 45
#define TLS1_ALERT_CERTIFICATE_UNKNOWN 46
#define TLS1_ALERT_ILLEGAL_PARAMETER 47
#define TLS1_ALERT_UNKNOWN_CA 48
#define TLS1_ALERT_ACCESS_DENIED 49
#define TLS1_ALERT_DECODE_ERROR 50
#define TLS1_ALERT_DECRYPT_ERROR 51
#define TLS1_ALERT_EXPORT_RESTRICTION 60
#define TLS1_ALERT_PROTOCOL_VERSION 70
#define TLS1_ALERT_INSUFFIENT_SECURITY 71
#define TLS1_ALERT_INTERNAL_ERROR 80
#define TLS1_ALERT_USER_CANCELED 90
#define TLS1_ALERT_NO_RENEGOTIATION 100
#define TLS1_ALERT_UNSUPPORTED_EXT 110
#define TLS1_ALERT_UNKNOWN_PSK_IDENTITY 115
#define TLS1_ALERT_NO_APP_PROTOCOL 120
#define SP_PROT_ALL 0xffffffff
#define SP_PROT_UNI_CLIENT 0x80000000
#define SP_PROT_UNI_SERVER 0x40000000
...
...
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