1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-03 01:18:10 +03:00

Compare commits

...

21 Commits

Author SHA1 Message Date
Stefan Metzmacher
cb27914403 s4:rpc_server/netlogon: fix dcesrv_netr_LogonSamLogon_base_call() for ServerAuthenticateKerberos()
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Thu Dec 12 15:00:10 UTC 2024 on atb-devel-224
2024-12-12 15:00:10 +00:00
Stefan Metzmacher
5aa79e3263 s4:rpc_server/netlogon: fix dcesrv_netr_ServerPasswordSet[2] for ServerAuthenticateKerberos
Review with: git show --patience

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
ff16cb25c4 librpc/server: call dcesrv_netr_check_schannel() as schannel_check_creds_state() callback
If schannel is not used we need to return ACCESS_DENIED and discard
the effect of netlogon_creds_server_step_check().

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
2cf8a8ea35 libcli/auth: let schannel_check_creds_state() take an access_check callback
This allows the callback to decide if the updated creds should be stored
or not.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
e830da448b selftest: add 'server support krb5 netlogon = yes' for ad_dc
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
f4547f2176 selftest add 'server reject aes schannel:COMPUTER$' rules
These avoid a lot of messages during the tests...

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
1a18706bcd s4:rpc_server/netlogon: implement dcesrv_netr_ServerAuthenticateKerberos
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
4834b9dacc librpc/server: prepare schannel_util.c for netr_ServerAuthenticateKerberos
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
c58137aad9 docs-xml/smbdotconf: add "server support krb5 netlogon" options
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
a5993f0c5c docs-xml/smbdotconf: add "server reject aes schannel[:COMPUTERACCOUNT]" options
This will be useful in order to require netr_ServerAuthenticateKerberos()

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
d002f371ec s4:rpc_server/lsa: allow krb5+privacy instead of schannel
With netr_ServerAuthenticateKerberos() clients also use
krb5 for lsa_LookupSids3 and lsa_LookupNames4.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
87b553084d auth_log: prepare for netr_ServerAuthenticateKerberos
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
ff2e287585 python:tests/krb5: add ServerAuthenticateKerberos related tests to netlogon.py
Works against Windows 2025 preview:

SMB_CONF_PATH=/dev/null \
SERVER=172.31.9.115 DC_SERVER=w2025p-115.w2025p-l8.base \
DOMAIN="W2025P-L8" REALM="W2025P-L8.BASE" \
ADMIN_USERNAME="Administrator" ADMIN_PASSWORD="A1b2C3d4" \
NETLOGON_STRONG_KEY_SUPPORT=1 NETLOGON_AUTH_KRB5_SUPPORT=1 \
STRICT_CHECKING=0 python/samba/tests/krb5/netlogon.py

The code still works against Windows 2022 with the
following options:

SMB_CONF_PATH=/dev/null \
SERVER=172.31.9.118 DC_SERVER=w2022-118.w2022-l7.base \
DOMAIN="W2022-L7" REALM="W2022-L7.BASE" \
ADMIN_USERNAME="Administrator" ADMIN_PASSWORD="A1b2C3d4" \
NETLOGON_STRONG_KEY_SUPPORT=1 NETLOGON_AUTH_KRB5_SUPPORT=0 \
STRICT_CHECKING=0 python/samba/tests/krb5/netlogon.py

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
64d5efa2de pycredentials: add py_netlogon_creds_kerberos_init
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
e296b912b2 python:tests/krb5: let netlogon.py test strong key without arcfour
It shows that there's no encryption on buffers...

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
c7a0efb29e libcli/auth: add infrastructure for netr_ServerAuthenticateKerberos()
This shows that STRONG_KEY without ARCFOUR means no encryption
for ServerPasswordSet2.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Stefan Metzmacher
36b5a75123 libcli/auth: add let netlogon_creds_alloc() use _talloc_keep_secret()
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2024-12-12 13:59:29 +00:00
Andreas Schneider
d091182156 ldb: Add LGPLv3 LICENSE file
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15729

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2024-12-12 13:59:29 +00:00
Andreas Schneider
d1849ba12f tdb: Add LGPLv3 LICENSE file
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15729

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2024-12-12 13:59:29 +00:00
Andreas Schneider
24494f9ff7 tevent: Add LGPLv3 LICENSE file
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15729

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2024-12-12 13:59:29 +00:00
Andreas Schneider
cd0fb59568 talloc: Add LGPLv3 LICENSE file
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15729

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2024-12-12 13:59:29 +00:00
24 changed files with 2189 additions and 70 deletions

View File

@ -754,8 +754,10 @@ static const char* get_password_type(const struct auth_usersupplied_info *ui)
} else if (ui->auth_description != NULL &&
strncmp("ServerAuthenticate", ui->auth_description, 18) == 0)
{
if (ui->netlogon_trust_account.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES) {
if (ui->netlogon_trust_account.authenticate_kerberos) {
password_type = "Kerberos";
} else if (ui->netlogon_trust_account.negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES) {
password_type = "HMAC-SHA256";
} else if (ui->netlogon_trust_account.negotiate_flags
& NETLOGON_NEG_STRONG_KEYS) {

View File

@ -79,6 +79,7 @@ struct auth_usersupplied_info
struct {
uint32_t negotiate_flags;
bool authenticate_kerberos;
enum netr_SchannelType secure_channel_type;
const char *computer_name; /* [charset(UTF8)] */
const char *account_name; /* [charset(UTF8)] */

View File

@ -1902,6 +1902,62 @@ PyTypeObject PyCredentialCacheContainer = {
.tp_methods = py_ccache_container_methods,
};
static PyObject *py_netlogon_creds_kerberos_init(PyObject *module,
PyObject *args,
PyObject *kwargs)
{
const char * const kwnames[] = {
"client_account",
"client_computer_name",
"secure_channel_type",
"client_requested_flags",
"negotiate_flags",
NULL,
};
const char *client_account = NULL;
const char *client_computer_name = NULL;
unsigned short secure_channel_type = 0;
unsigned int client_requested_flags = 0;
unsigned int negotiate_flags = 0;
struct netlogon_creds_CredentialState *ncreds = NULL;
PyObject *py_ncreds = Py_None;
bool ok;
ok = PyArg_ParseTupleAndKeywords(args, kwargs, "ssHII",
discard_const_p(char *, kwnames),
&client_account,
&client_computer_name,
&secure_channel_type,
&client_requested_flags,
&negotiate_flags);
if (!ok) {
return NULL;
}
ncreds = netlogon_creds_kerberos_init(NULL,
client_account,
client_computer_name,
secure_channel_type,
client_requested_flags,
NULL, /* client_sid */
negotiate_flags);
if (ncreds == NULL) {
PyErr_NoMemory();
return NULL;
}
py_ncreds = py_return_ndr_struct("samba.dcerpc.schannel",
"netlogon_creds_CredentialState",
ncreds,
ncreds);
if (py_ncreds == NULL) {
TALLOC_FREE(ncreds);
return NULL;
}
return py_ncreds;
}
static PyObject *py_netlogon_creds_random_challenge(PyObject *module,
PyObject *unused)
{
@ -2896,6 +2952,18 @@ static PyObject *py_netlogon_creds_encrypt_SendToSam(PyObject *module,
}
static PyMethodDef py_module_methods[] = {
{
.ml_name = "netlogon_creds_kerberos_init",
.ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction,
py_netlogon_creds_kerberos_init),
.ml_flags = METH_VARARGS | METH_KEYWORDS,
.ml_doc = "credentials.netlogon_creds_kerberos_init("
"client_account, client_computer_name,"
"secure_channel_type, "
"client_requested_flags, negotiate_flags)"
"-> netlogon_creds_CredentialState\n"
"Create a new state for netr_ServerAuthenticateKerberos()",
},
{
.ml_name = "netlogon_creds_random_challenge",
.ml_meth = py_netlogon_creds_random_challenge,

View File

@ -145,6 +145,13 @@ static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
uint32_t checksum_length,
uint8_t seq_num[8])
{
if (state->creds->authenticate_kerberos) {
DBG_WARNING("Called with authenticate_kerberos from %s %s\n",
state->creds->account_name,
state->creds->computer_name);
return NT_STATUS_ACCESS_DENIED;
}
if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
gnutls_cipher_hd_t cipher_hnd = NULL;
gnutls_datum_t key = {
@ -243,6 +250,13 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state,
uint8_t *data, uint32_t length,
bool forward)
{
if (state->creds->authenticate_kerberos) {
DBG_WARNING("Called with authenticate_kerberos from %s %s\n",
state->creds->account_name,
state->creds->computer_name);
return NT_STATUS_ACCESS_DENIED;
}
if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
gnutls_cipher_hd_t cipher_hnd = NULL;
uint8_t sess_kf0[16] = {0};
@ -423,6 +437,13 @@ static NTSTATUS netsec_do_sign(struct schannel_state *state,
uint8_t header[8],
uint8_t *checksum)
{
if (state->creds->authenticate_kerberos) {
DBG_WARNING("Called with authenticate_kerberos from %s %s\n",
state->creds->account_name,
state->creds->computer_name);
return NT_STATUS_ACCESS_DENIED;
}
if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
gnutls_hmac_hd_t hmac_hnd = NULL;
int rc;
@ -833,6 +854,16 @@ static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security
return NT_STATUS_INVALID_PARAMETER_MIX;
}
if (creds->authenticate_kerberos) {
DBG_ERR("attempted schannel connection with "
"authenticate_kerberos from %s %s\n",
creds->account_name,
creds->computer_name);
NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
log_stack_trace();
return NT_STATUS_INVALID_PARAMETER_MIX;
}
state = netsec_create_state(gensec_security,
creds, true /* initiator */);
if (state == NULL) {

View File

@ -46,8 +46,10 @@
'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>' options.</para>
<para>This option is over-ridden by the effective value of 'yes' from
the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>'
and/or '<smbconfoption name="reject md5 clients"/>' options.</para>
the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>',
'<smbconfoption name="reject md5 clients"/>',
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT"/>',
and/or '<smbconfoption name="server reject aes schannel"/>' options.</para>
</description>
<value type="default">no</value>
@ -88,18 +90,24 @@
<para>This option overrides the <smbconfoption name="allow nt4 crypto"/> option.</para>
<para>This option is over-ridden by the effective value of 'yes' from
the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>'
and/or '<smbconfoption name="reject md5 clients"/>' options.</para>
the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>',
'<smbconfoption name="reject md5 clients"/>',
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT"/>'
and/or '<smbconfoption name="server reject aes schannel"/>' options.</para>
<para>Which means '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>'
is only useful in combination with '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'</para>
is only useful in combination with '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'
and '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>'.</para>
<programlisting>
allow nt4 crypto:LEGACYCOMPUTER1$ = yes
server reject md5 schannel:LEGACYCOMPUTER1$ = no
server reject aes schannel:LEGACYCOMPUTER1$ = no
allow nt4 crypto:NASBOX$ = yes
server reject md5 schannel:NASBOX$ = no
server reject aes schannel:NASBOX$ = no
allow nt4 crypto:LEGACYCOMPUTER2$ = yes
server reject md5 schannel:LEGACYCOMPUTER2$ = no
server reject aes schannel:LEGACYCOMPUTER2$ = no
</programlisting>
</description>

View File

@ -54,6 +54,10 @@
'<smbconfoption name="allow nt4 crypto"/>' options and implies
'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">no</smbconfoption>'.
</para>
<para>This option is over-ridden by the effective value of 'yes' from
the '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT"/>'
and/or '<smbconfoption name="server reject aes schannel"/>' options.</para>
</description>
<value type="default">yes</value>
@ -100,10 +104,19 @@
'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">no</smbconfoption>'.
</para>
<para>This option is over-ridden by the effective value of 'yes' from
the '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT"/>'
and/or '<smbconfoption name="server reject aes schannel"/>' options.</para>
<para>Which means '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'
is only useful in combination with '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>'.</para>
<programlisting>
server reject md5 schannel:LEGACYCOMPUTER1$ = no
server reject aes schannel:LEGACYCOMPUTER1$ = no
server reject md5 schannel:NASBOX$ = no
server reject aes schannel:NASBOX$ = no
server reject md5 schannel:LEGACYCOMPUTER2$ = no
server reject aes schannel:LEGACYCOMPUTER2$ = no
</programlisting>
</description>

View File

@ -0,0 +1,118 @@
<samba:parameter name="server reject aes schannel"
context="G"
type="boolean"
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
<description>
<para><emphasis>This option is experimental for now!</emphasis>
</para>
<para>This option controls whether the netlogon server (currently
only in 'active directory domain controller' mode), will
reject clients which do not support ServerAuthenticateKerberos.</para>
<para>Support for ServerAuthenticateKerberos was added in Windows
starting with Server 2025, it's available in Samba starting with 4.22 with the
'<smbconfoption name="server support krb5 netlogon">yes</smbconfoption>' and
'<smbconfoption name="client use krb5 netlogon">yes</smbconfoption>' options,
which are disabled by default.
</para>
<para>Note this options is not really related to security problems
behind CVE_2022_38023, but it still uses the debug level related
logic and options.</para>
<para>
Samba will log an error in the log files at log level 0
if legacy a client is rejected without an explicit,
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>' option
for the client. The message will indicate
the explicit '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>'
line to be added, if the client software requires it. (The log level can be adjusted with
'<smbconfoption name="CVE_2022_38023:error_debug_level">1</smbconfoption>'
in order to complain only at a higher log level).
</para>
<para>
Samba will log a message in the log files at log level 5
if a client is allowed without an explicit,
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>' option
for the client. The message will indicate
the explicit '<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no</smbconfoption>'
line to be added, if the client software requires it. (The log level can be adjusted with
'<smbconfoption name="NETLOGON_AES:usage_debug_level">0</smbconfoption>'
in order to complain only at a lower or higher log level).
This can we used to prepare the configuration before changing to
'<smbconfoption name="server reject aes schannel">yes</smbconfoption>'
</para>
<para>Admins can use
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">no/yes</smbconfoption>' options in
order to have more control</para>
<para>When set to 'yes' this option overrides the
'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>' and
'<smbconfoption name="reject md5 clients"/>' options and implies
'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'.
</para>
<para>This option interacts with the '<smbconfoption name="server support krb5 netlogon"/>' option.
</para>
<para>For now '<smbconfoption name="server reject aes schannel"/>'
is EXPERIMENTAL and should not be configured explicitly.</para>
</description>
<value type="default">no</value>
<value type="example">yes</value>
</samba:parameter>
<samba:parameter name="server reject aes schannel:COMPUTERACCOUNT"
context="G"
type="string"
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
<description>
<para>If the time has come and most domain members or trusted domains
support ServerAuthenticateKerberos, admins may want to use "server reject aes schannel = yes".
It is possible to specify an explicit exception per computer account
by setting 'server reject aes schannel:COMPUTERACCOUNT = no'.
Note that COMPUTERACCOUNT has to be the sAMAccountName value of
the computer account (including the trailing '$' sign).
</para>
<para>Note this options is not really related to security problems
behind CVE_2022_38023, but it still uses the debug level related
logic and options.
</para>
<para>
Samba will log a complaint in the log files at log level 0
about the security problem if the option is set to "no",
but the related computer does not require it.
(The log level can be adjusted with
'<smbconfoption name="CVE_2022_38023:warn_about_unused_debug_level">1</smbconfoption>'
in order to complain only at a higher log level).
</para>
<para>
Samba will log a warning in the log files at log level 5
if a setting is still needed for the specified computer account.
</para>
<para>This option overrides the <smbconfoption name="server reject aes schannel"/> option.</para>
<para>When set to 'yes' this option overrides the
'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>' and
'<smbconfoption name="reject md5 clients"/>' options and implies
'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'.
</para>
<programlisting>
server reject aes schannel:LEGACYCOMPUTER1$ = no
server reject aes schannel:NASBOX$ = no
server reject aes schannel:LEGACYCOMPUTER2$ = no
server reject aes schannel:HIGHPRIVACYSRV$ = yes
</programlisting>
</description>
</samba:parameter>

View File

@ -0,0 +1,28 @@
<samba:parameter name="server support krb5 netlogon"
context="G"
type="boolean"
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
<description>
<para><emphasis>This option is experimental for now!</emphasis>
</para>
<para>This option controls whether the netlogon server (currently
only in 'active directory domain controller' mode), will
provide support for ServerAuthenticateKerberos.</para>
<para>Support for ServerAuthenticateKerberos was added in Windows
starting with Server 2025, it's available in Samba starting with 4.22 with the
'<smbconfoption name="server support krb5 netlogon">yes</smbconfoption>' and
'<smbconfoption name="client use krb5 netlogon">yes</smbconfoption>' options,
which are disabled by default.
</para>
<para>This option interacts with the
'<smbconfoption name="server reject aes schannel:COMPUTERACCOUNT">yes</smbconfoption>' and
'<smbconfoption name="server reject aes schannel">yes</smbconfoption>' options.
</para>
</description>
<value type="default">no</value>
<value type="example">yes</value>
</samba:parameter>

165
lib/ldb/LICENSE Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

165
lib/talloc/LICENSE Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

165
lib/tdb/LICENSE Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

165
lib/tevent/LICENSE Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -56,6 +56,78 @@ bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge)
return true;
}
static NTSTATUS netlogon_creds_no_step_check(struct netlogon_creds_CredentialState *creds,
enum dcerpc_AuthType auth_type,
enum dcerpc_AuthLevel auth_level,
bool *skip)
{
*skip = false;
if (creds == NULL) {
return NT_STATUS_ACCESS_DENIED;
}
/*
* Only if ServerAuthenticateKerberos() was
* used the content of the netr_Authenticator
* values are not checked.
*
* It is independent from the
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH flag.
*/
if (creds->authenticate_kerberos) {
if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
return NT_STATUS_ACCESS_DENIED;
}
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_ACCESS_DENIED;
}
*skip = true;
}
return NT_STATUS_OK;
}
static NTSTATUS netlogon_creds_no_buffer_crypt(struct netlogon_creds_CredentialState *creds,
enum dcerpc_AuthType auth_type,
enum dcerpc_AuthLevel auth_level,
bool *skip)
{
*skip = false;
if (creds == NULL) {
return NT_STATUS_ACCESS_DENIED;
}
if (creds->authenticate_kerberos) {
if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
return NT_STATUS_ACCESS_DENIED;
}
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_ACCESS_DENIED;
}
}
/*
* Even if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH is
* negotiated within ServerAuthenticate3()
* encryption on application buffers is skipped.
*
* Also ServerAuthenticateKerberos() without
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH uses
* encryption with a random session key.
*/
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_ACCESS_DENIED;
}
*skip = true;
}
return NT_STATUS_OK;
}
void netlogon_creds_random_challenge(struct netr_Credential *challenge)
{
ZERO_STRUCTP(challenge);
@ -71,6 +143,13 @@ static NTSTATUS netlogon_creds_step_crypt(struct netlogon_creds_CredentialState
NTSTATUS status;
int rc;
if (creds->authenticate_kerberos) {
/*
* The caller should have checked this already...
*/
return NT_STATUS_INVALID_PARAMETER_MIX;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
memcpy(out->data, in->data, sizeof(out->data));
@ -257,6 +336,17 @@ static NTSTATUS netlogon_creds_step(struct netlogon_creds_CredentialState *creds
struct netr_Credential time_cred;
NTSTATUS status;
if (creds->authenticate_kerberos) {
/* This is only called on the client side */
generate_nonce_buffer(creds->seed.data,
ARRAY_SIZE(creds->seed.data));
generate_nonce_buffer(creds->client.data,
ARRAY_SIZE(creds->client.data));
generate_nonce_buffer(creds->server.data,
ARRAY_SIZE(creds->server.data));
return NT_STATUS_OK;
}
DEBUG(5,("\tseed %08x:%08x\n",
IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
@ -492,6 +582,7 @@ netlogon_creds_alloc(TALLOC_CTX *mem_ctx,
struct netlogon_creds_CredentialState *creds = NULL;
struct timeval tv = timeval_current();
NTTIME now = timeval_to_nttime(&tv);
const char *name = NULL;
creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
if (creds == NULL) {
@ -523,6 +614,66 @@ netlogon_creds_alloc(TALLOC_CTX *mem_ctx,
creds->client_sid = global_sid_NULL;
}
name = talloc_get_name(creds);
_talloc_keep_secret(creds, name);
return creds;
}
struct netlogon_creds_CredentialState *netlogon_creds_kerberos_init(TALLOC_CTX *mem_ctx,
const char *client_account,
const char *client_computer_name,
uint16_t secure_channel_type,
uint32_t client_requested_flags,
const struct dom_sid *client_sid,
uint32_t negotiate_flags)
{
struct netlogon_creds_CredentialState *creds = NULL;
creds = netlogon_creds_alloc(mem_ctx,
client_account,
client_computer_name,
secure_channel_type,
client_requested_flags,
client_sid,
negotiate_flags);
if (creds == NULL) {
return NULL;
}
/*
* Some Windows versions used
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* as a dummy flag in ServerAuthenticate3,
* so we should not use
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* for any logic decisions.
*
* So we use a dedicated bool that
* is only set if ServerAuthenticateKerberos
* was really used. And for that we assert
* that NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* is set too.
*/
creds->authenticate_kerberos = true;
/*
* This should not be required, but we better
* make sure we would not use a zero session key...
*
* It seems that's what Windows is also doing...
* as the values in netr_ServerPasswordGet() are
* encrypted in random ways if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* is missing in netr_ServerAuthenticateKerberos().
*/
generate_nonce_buffer(creds->session_key,
ARRAY_SIZE(creds->session_key));
generate_nonce_buffer(creds->seed.data,
ARRAY_SIZE(creds->seed.data));
generate_nonce_buffer(creds->client.data,
ARRAY_SIZE(creds->client.data));
generate_nonce_buffer(creds->server.data,
ARRAY_SIZE(creds->server.data));
return creds;
}
@ -663,6 +814,21 @@ NTSTATUS netlogon_creds_client_verify(struct netlogon_creds_CredentialState *cre
enum dcerpc_AuthType auth_type,
enum dcerpc_AuthLevel auth_level)
{
NTSTATUS status;
bool skip_crypto = false;
status = netlogon_creds_no_step_check(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (skip_crypto) {
return NT_STATUS_OK;
}
if (!received_credentials ||
!mem_equal_const_time(received_credentials->data, creds->server.data, 8)) {
DEBUG(2,("credentials check failed\n"));
@ -824,13 +990,23 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState
enum dcerpc_AuthLevel auth_level)
{
NTSTATUS status;
bool skip_crypto = false;
if (!received_authenticator || !return_authenticator) {
return NT_STATUS_INVALID_PARAMETER;
}
if (!creds) {
return NT_STATUS_ACCESS_DENIED;
status = netlogon_creds_no_step_check(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
ZERO_STRUCTP(return_authenticator);
return status;
}
if (skip_crypto) {
ZERO_STRUCTP(return_authenticator);
return NT_STATUS_OK;
}
creds->sequence = received_authenticator->timestamp;
@ -859,6 +1035,7 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
{
struct netr_SamBaseInfo *base = NULL;
NTSTATUS status;
bool skip_crypto = false;
if (validation == NULL) {
return NT_STATUS_INVALID_PARAMETER;
@ -919,12 +1096,27 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
return NT_STATUS_INVALID_INFO_CLASS;
}
status = netlogon_creds_no_buffer_crypt(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* find and decrypt the session keys, return in parameters above */
if (validation_level == 6) {
if (skip_crypto || validation_level == 6) {
/* they aren't encrypted! */
} else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
if (!all_zero(base->key.key, sizeof(base->key.key))) {
/*
* Don't crypt an all-zero key, it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don't care
* as we use a random key
*/
if (creds->authenticate_kerberos ||
!all_zero(base->key.key, sizeof(base->key.key))) {
if (do_encrypt) {
status = netlogon_creds_aes_encrypt(
creds,
@ -941,7 +1133,8 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
}
}
if (!all_zero(base->LMSessKey.key,
if (creds->authenticate_kerberos ||
!all_zero(base->LMSessKey.key,
sizeof(base->LMSessKey.key))) {
if (do_encrypt) {
status = netlogon_creds_aes_encrypt(
@ -959,8 +1152,15 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
}
}
} else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
if (!all_zero(base->key.key, sizeof(base->key.key))) {
/*
* Don't crypt an all-zero key, it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don't care
* as we use a random key
*/
if (creds->authenticate_kerberos ||
!all_zero(base->key.key, sizeof(base->key.key))) {
status = netlogon_creds_arcfour_crypt(creds,
base->key.key,
sizeof(base->key.key));
@ -969,7 +1169,8 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
}
}
if (!all_zero(base->LMSessKey.key,
if (creds->authenticate_kerberos ||
!all_zero(base->LMSessKey.key,
sizeof(base->LMSessKey.key))) {
status = netlogon_creds_arcfour_crypt(creds,
base->LMSessKey.key,
@ -979,8 +1180,15 @@ static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_C
}
}
} else {
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
if (!all_zero(base->LMSessKey.key,
/*
* Don't crypt an all-zero key, it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don't care
* as we use a random key
*/
if (creds->authenticate_kerberos ||
!all_zero(base->LMSessKey.key,
sizeof(base->LMSessKey.key))) {
if (do_encrypt) {
status = netlogon_creds_des_encrypt_LMKey(creds,
@ -1034,6 +1242,15 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden
bool do_encrypt)
{
NTSTATUS status;
bool skip_crypto = false;
status = netlogon_creds_no_buffer_crypt(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (logon == NULL) {
return NT_STATUS_INVALID_PARAMETER;
@ -1048,6 +1265,10 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden
return NT_STATUS_INVALID_PARAMETER;
}
if (skip_crypto) {
break;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
uint8_t *h;
@ -1143,6 +1364,10 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden
return NT_STATUS_INVALID_PARAMETER;
}
if (skip_crypto) {
break;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
if (do_encrypt) {
status = netlogon_creds_aes_encrypt(
@ -1165,8 +1390,11 @@ static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_Creden
if (!NT_STATUS_IS_OK(status)) {
return status;
}
} else {
/* Using DES to verify kerberos tickets makes no sense */
} else if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
/*
* Using DES to verify kerberos tickets makes no sense,
* but if the connection is encrypted we don't care...
*/
return NT_STATUS_INVALID_PARAMETER;
}
break;
@ -1213,6 +1441,21 @@ static NTSTATUS netlogon_creds_crypt_samr_Password(
enum dcerpc_AuthLevel auth_level,
bool do_encrypt)
{
NTSTATUS status;
bool skip_crypto = false;
status = netlogon_creds_no_buffer_crypt(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (skip_crypto) {
return NT_STATUS_OK;
}
if (all_zero(pass->hash, ARRAY_SIZE(pass->hash))) {
return NT_STATUS_OK;
}
@ -1260,6 +1503,21 @@ static NTSTATUS netlogon_creds_crypt_samr_CryptPassword(
enum dcerpc_AuthLevel auth_level,
bool do_encrypt)
{
NTSTATUS status;
bool skip_crypto = false;
status = netlogon_creds_no_buffer_crypt(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (skip_crypto) {
return NT_STATUS_OK;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
if (do_encrypt) {
return netlogon_creds_aes_encrypt(creds,
@ -1272,9 +1530,21 @@ static NTSTATUS netlogon_creds_crypt_samr_CryptPassword(
ARRAY_SIZE(pass->data));
}
return netlogon_creds_arcfour_crypt(creds,
pass->data,
ARRAY_SIZE(pass->data));
if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
return netlogon_creds_arcfour_crypt(creds,
pass->data,
ARRAY_SIZE(pass->data));
}
/*
* Using DES to verify to encrypt the password makes no sense,
* but if the connection is encrypted we don't care...
*/
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_INVALID_PARAMETER;
}
return NT_STATUS_OK;
}
NTSTATUS netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds,
@ -1309,6 +1579,21 @@ static NTSTATUS netlogon_creds_crypt_SendToSam(
enum dcerpc_AuthLevel auth_level,
bool do_encrypt)
{
NTSTATUS status;
bool skip_crypto = false;
status = netlogon_creds_no_buffer_crypt(creds,
auth_type,
auth_level,
&skip_crypto);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (skip_crypto) {
return NT_STATUS_OK;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
if (do_encrypt) {
return netlogon_creds_aes_encrypt(creds,
@ -1321,9 +1606,21 @@ static NTSTATUS netlogon_creds_crypt_SendToSam(
opaque_length);
}
return netlogon_creds_arcfour_crypt(creds,
opaque_data,
opaque_length);
if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
return netlogon_creds_arcfour_crypt(creds,
opaque_data,
opaque_length);
}
/*
* Using DES to verify to encrypt the data makes no sense,
* but if the connection is encrypted we don't care...
*/
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_INVALID_PARAMETER;
}
return NT_STATUS_OK;
}
NTSTATUS netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState *creds,

View File

@ -37,6 +37,14 @@ NTSTATUS netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds
#define netlogon_creds_aes_encrypt __DO_NOT_USE_netlogon_creds_aes_encrypt
#define netlogon_creds_aes_decrypt __DO_NOT_USE_netlogon_creds_aes_decrypt
struct netlogon_creds_CredentialState *netlogon_creds_kerberos_init(TALLOC_CTX *mem_ctx,
const char *client_account,
const char *client_computer_name,
uint16_t secure_channel_type,
uint32_t client_requested_flags,
const struct dom_sid *client_sid,
uint32_t negotiate_flags);
/*****************************************************************
The above functions are common to the client and server interface
next comes the client specific functions

View File

@ -39,6 +39,11 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
struct netr_Authenticator *return_authenticator,
enum dcerpc_AuthType auth_type,
enum dcerpc_AuthLevel auth_level,
NTSTATUS (*access_check_cb)(struct netlogon_creds_CredentialState *creds,
NTSTATUS step_status,
bool *store,
void *access_check_private),
void *access_check_private,
struct netlogon_creds_CredentialState **creds_out);
NTSTATUS schannel_get_challenge(struct loadparm_context *lp_ctx,

View File

@ -562,6 +562,11 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
struct netr_Authenticator *return_authenticator,
enum dcerpc_AuthType auth_type,
enum dcerpc_AuthLevel auth_level,
NTSTATUS (*access_check_cb)(struct netlogon_creds_CredentialState *creds,
NTSTATUS step_status,
bool *store,
void *access_check_private),
void *access_check_private,
struct netlogon_creds_CredentialState **creds_out)
{
TALLOC_CTX *tmpctx;
@ -572,6 +577,7 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
char *keystr = NULL;
struct db_record *record;
TDB_DATA key;
bool store = true;
if (creds_out != NULL) {
*creds_out = NULL;
@ -624,13 +630,22 @@ NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
return_authenticator,
auth_type,
auth_level);
if (access_check_cb != NULL) {
NTSTATUS step_status = status;
status = access_check_cb(creds,
step_status,
&store,
access_check_private);
}
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
if (!NT_STATUS_IS_OK(status)) {
goto done;
if (store) {
status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
}
if (creds_out) {

View File

@ -58,7 +58,22 @@ interface schannel
NTTIME auth_time;
[value(0xFFFFFFFF)] uint32 magic3;
dom_sid28 client_sid;
[value(0)] boolean8 reserved1;
/*
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH is not
* enough to implement the logic
* for netr_ServerAuthenticateKerberos()
* as NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* was also used as dummy flag in
* some Windows versions.
*
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* also indicates no encryption for
* application buffers, even if it's
* used via netr_ServerAuthenticate3()
* and aes, arcfour or des are
* otherwise in use.
*/
boolean8 authenticate_kerberos;
/* here's some padding ... */
[value(0)] hyper reserved2;
[value(NULL)] netlogon_creds_CredentialState_extra_info *ex;

View File

@ -22,6 +22,7 @@
*/
#include "includes.h"
#include "auth/auth.h"
#include "schannel_util.h"
#include "param/param.h"
#include "libcli/security/dom_sid.h"
@ -35,6 +36,8 @@ struct dcesrv_netr_check_schannel_state {
enum dcerpc_AuthType auth_type;
enum dcerpc_AuthLevel auth_level;
bool kerberos_required;
bool schannel_global_required;
bool schannel_required;
bool schannel_explicitly_set;
@ -66,6 +69,25 @@ static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *d
*_s = NULL;
if (creds->authenticate_kerberos) {
struct auth_session_info *session_info =
dcesrv_call_session_info(dce_call);
const struct dom_sid *auth_sid =
&session_info->security_token->sids[0];
if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
return NT_STATUS_ACCESS_DENIED;
}
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
return NT_STATUS_ACCESS_DENIED;
}
if (!dom_sid_equal(auth_sid, &creds->client_sid)) {
return NT_STATUS_ACCESS_DENIED;
}
}
s = dcesrv_iface_state_find_conn(dce_call,
DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
struct dcesrv_netr_check_schannel_state);
@ -131,6 +153,11 @@ new_state:
s->seal_required = require_seal;
s->seal_explicitly_set = explicit_seal_opt != NULL;
if (creds->authenticate_kerberos) {
s->kerberos_required = true;
s->seal_required = true;
}
status = dcesrv_iface_state_store_conn(dce_call,
DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
s);
@ -165,7 +192,22 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
opname = ndr_table_netlogon.calls[opnum].name;
}
if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
if (s->auth_type == DCERPC_AUTH_TYPE_KRB5) {
if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
reason = "KRB5 WITH SEALED";
} else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
reason = "KRB5 ONLY WITH SIGNED";
dbg_lvl = DBGLVL_ERR;
s->result = NT_STATUS_ACCESS_DENIED;
} else {
reason = "KRB5 WITH INVALID";
dbg_lvl = DBGLVL_ERR;
s->result = NT_STATUS_ACCESS_DENIED;
}
} else if (s->kerberos_required) {
s->result = NT_STATUS_ACCESS_DENIED;
reason = "WITHOUT KRB5";
} else if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
reason = "WITH SEALED";
} else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
@ -196,6 +238,14 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
return s->result;
}
if (s->auth_type == DCERPC_AUTH_TYPE_KRB5 &&
s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
{
s->result = NT_STATUS_OK;
TALLOC_FREE(frame);
return s->result;
}
if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL &&
s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
{
@ -529,6 +579,52 @@ NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
return NT_STATUS_OK;
}
struct dcesrv_netr_step_access_state {
struct dcesrv_call_state *dce_call;
enum dcerpc_AuthType auth_type;
enum dcerpc_AuthLevel auth_level;
uint16_t opnum;
NTSTATUS status;
};
static NTSTATUS dcesrv_netr_step_access_cb(
struct netlogon_creds_CredentialState *creds,
NTSTATUS step_status,
bool *store,
void *access_check_private)
{
struct dcesrv_netr_step_access_state *s =
(struct dcesrv_netr_step_access_state *)access_check_private;
struct dcesrv_call_state *dce_call =
talloc_get_type_abort(s->dce_call,
struct dcesrv_call_state);
if (NT_STATUS_EQUAL(step_status, NT_STATUS_ACCESS_DENIED)) {
s->status = step_status;
*store = true;
return NT_STATUS_OK;
}
if (!NT_STATUS_IS_OK(step_status)) {
*store = false;
return step_status;
}
s->status = dcesrv_netr_check_schannel(dce_call,
creds,
s->auth_type,
s->auth_level,
s->opnum);
if (!NT_STATUS_IS_OK(s->status)) {
*store = false;
} else {
*store = true;
}
return NT_STATUS_OK;
}
NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
const char *computer_name,
@ -538,29 +634,32 @@ NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
{
NTSTATUS nt_status;
struct netlogon_creds_CredentialState *creds = NULL;
enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
struct dcesrv_netr_step_access_state state = {
.dce_call = dce_call,
.auth_type = DCERPC_AUTH_TYPE_NONE,
.auth_level = DCERPC_AUTH_LEVEL_NONE,
.opnum = dce_call->pkt.u.request.opnum,
.status = NT_STATUS_INTERNAL_ERROR,
};
dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
dcesrv_call_auth_info(dce_call, &state.auth_type, &state.auth_level);
nt_status = schannel_check_creds_state(mem_ctx,
dce_call->conn->dce_ctx->lp_ctx,
computer_name,
received_authenticator,
return_authenticator,
auth_type,
auth_level,
state.auth_type,
state.auth_level,
dcesrv_netr_step_access_cb,
&state,
&creds);
if (!NT_STATUS_IS_OK(nt_status)) {
ZERO_STRUCTP(return_authenticator);
return nt_status;
}
nt_status = dcesrv_netr_check_schannel(dce_call,
creds,
auth_type,
auth_level,
dce_call->pkt.u.request.opnum);
nt_status = state.status;
if (!NT_STATUS_IS_OK(nt_status)) {
TALLOC_FREE(creds);
ZERO_STRUCTP(return_authenticator);

View File

@ -32,7 +32,7 @@ from samba import (
from samba.dcerpc import netlogon, samr, misc, ntlmssp, krb5pac
from samba.ndr import ndr_deepcopy, ndr_print, ndr_pack
from samba.crypto import md4_hash_blob
from samba.tests import DynamicTestCase
from samba.tests import DynamicTestCase, env_get_var_value
from samba.tests.krb5.kdc_base_test import KDCBaseTest
import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
from samba.tests.krb5.rfc4120_constants import KU_NON_KERB_CKSUM_SALT
@ -64,10 +64,16 @@ class NetlogonSchannel(KDCBaseTest):
for test in tests:
for trust in ["wks", "bdc"]:
for auth3_flags in [0x603fffff, 0x613fffff]:
for auth3_flags in [0x603fffff, 0x613fffff, 0xe13fffff]:
setup_test(test, trust, "auth3", auth3_flags)
for auth3_flags in [0x00004004, 0x01000000]:
for auth3_flags in [0x00004004, 0x00004000, 0x01000000]:
setup_test(test, trust, "auth3", auth3_flags)
for authK_flags in [0xe13fffff, 0x80000000, 0x00000000, 0x603fbffb]:
setup_test(test, trust, "authK", authK_flags)
for authK_flags in [0x01004004, 0x01000000, 0x00004000, 0x00000004]:
setup_test(test, trust, "authK", authK_flags)
for authK_flags in [0x613fffff, 0x413fffff, 0x400001ff]:
setup_test(test, trust, "authK", authK_flags)
def setUp(self):
super().setUp()
@ -77,6 +83,20 @@ class NetlogonSchannel(KDCBaseTest):
self.empty_pwd_nt4_hash = self.get_samr_Password(md4_hash_blob(b''))
strong_key_support = env_get_var_value(
'NETLOGON_STRONG_KEY_SUPPORT',
allow_missing=True)
if strong_key_support is None:
strong_key_support = '1'
self.strong_key_support = bool(int(strong_key_support))
auth_krb5_support = env_get_var_value(
'NETLOGON_AUTH_KRB5_SUPPORT',
allow_missing=True)
if auth_krb5_support is None:
auth_krb5_support = '1'
self.auth_krb5_support = bool(int(auth_krb5_support))
self.user_creds = self.get_cached_creds(
account_type=self.AccountType.USER,
opts={'name_prefix': 'u_',
@ -116,6 +136,13 @@ class NetlogonSchannel(KDCBaseTest):
trust_creds.set_netlogon_creds(None)
return conn
def get_krb5_conn(self, trust_creds):
dc_server = self.dc_server
conn = netlogon.netlogon(f'ncacn_ip_tcp:{dc_server}[krb5,seal]',
self.get_lp(),
trust_creds)
return conn
def get_samr_Password(self, nt_hash):
v = samr.Password()
v.hash = list(nt_hash)
@ -204,6 +231,46 @@ class NetlogonSchannel(KDCBaseTest):
return ncreds
def do_AuthenticateKerberos(self, conn, trust_creds,
negotiate_flags, required_flags,
expect_error=None):
(auth_type, auth_level) = conn.auth_info()
trust_account_name = trust_creds.get_username()
trust_computer_name = trust_creds.get_workstation()
ncreds = \
credentials.netlogon_creds_kerberos_init(
client_account=trust_account_name,
client_computer_name=trust_computer_name,
secure_channel_type=trust_creds.get_secure_channel_type(),
client_requested_flags=negotiate_flags,
negotiate_flags=negotiate_flags)
try:
(negotiated_flags, client_rid) = \
conn.netr_ServerAuthenticateKerberos(self.dc_server,
ncreds.account_name,
ncreds.secure_channel_type,
ncreds.computer_name,
ncreds.client_requested_flags)
except NTSTATUSError as err:
status, _ = err.args
self.assertIsNotNone(expect_error,
f'unexpectedly failed with {status:08X}')
self.assertEqual(expect_error, status, 'got wrong status code')
return
self.assertIsNone(expect_error, 'expected error')
self.assertEqual((negotiated_flags & required_flags), required_flags)
self.assertEqual((negotiated_flags & negotiate_flags), negotiated_flags)
credentials.netlogon_creds_client_update(ncreds,
negotiated_flags,
client_rid)
return ncreds
def do_CheckCapabilities(self, ncreds, conn,
expect_error1=None,
expect_error2=None):
@ -899,14 +966,49 @@ class NetlogonSchannel(KDCBaseTest):
creds = self.get_bdc1_creds()
self.assertIsNotNone(creds)
proposed_flags = flags
required_flags = flags
if authX == "auth3":
anon_conn = self.get_anon_conn()
ncreds = self.do_Authenticate3(anon_conn, creds, flags, flags)
expect_error = None
if flags & 0x80000000 and not self.auth_krb5_support:
required_flags &= ~0x80000000
if not (flags & 0x01000000) and not self.strong_key_support:
expect_error = ntstatus.NT_STATUS_DOWNGRADE_DETECTED
ncreds = self.do_Authenticate3(anon_conn, creds,
proposed_flags,
required_flags,
expect_error=expect_error)
if expect_error is not None:
self.skipTest('Requires NETLOGON_STRONG_KEY_SUPPORT')
return (None, None, None, None)
if proposed_flags != required_flags:
self.assertEqual(ncreds.negotiate_flags, required_flags)
self.skipTest('Requires NETLOGON_AUTH_KRB5_SUPPORT')
return (None, None, None, None)
conn = self.get_schannel_conn(creds, ncreds)
elif authX == "authK":
conn = self.get_krb5_conn(creds)
expect_error = None
if not self.auth_krb5_support:
expect_error = ntstatus.NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
ncreds = self.do_AuthenticateKerberos(conn, creds,
proposed_flags,
required_flags,
expect_error=expect_error)
if expect_error is not None:
self.skipTest('Requires NETLOGON_AUTH_KRB5_SUPPORT')
return (None, None, None, None)
self.assertIsNotNone(ncreds)
self.assertIsNotNone(conn)
expect_encrypted = True
if ncreds.authenticate_kerberos:
expect_encrypted = False
elif flags & 0x80000000:
expect_encrypted = False
else:
expect_encrypted = True
return (creds, ncreds, conn, expect_encrypted)
@ -926,6 +1028,26 @@ class NetlogonSchannel(KDCBaseTest):
expect_broken_crypto = False
expect_broken_set2_crypto = False
if ncreds.authenticate_kerberos:
self.assertEqual(expect_encrypted, False)
if ncreds.negotiate_flags & 0x80000000:
# This is the expected case of a sane client
pass
elif ncreds.negotiate_flags & 0x01000004:
# This fails as there is aes or arfour
# encryption with a random key
expect_broken_crypto = True
expect_broken_set2_crypto = True
else:
# This fails as there is des
# encryption with a random key
# This applies to things using
# the NT-HASH (samr_Password)
#
# But for {samr,netr}_CryptPassword
# there's no encryption for
# ServerPasswordSet2
expect_broken_crypto = True
if expect_broken_crypto:
expect_encrypted = True
@ -939,6 +1061,10 @@ class NetlogonSchannel(KDCBaseTest):
expect_set2_encrypted = expect_encrypted
encryption_set2_ncreds = ncreds
if not (ncreds.negotiate_flags & 0x01000004):
# Without aes or arcfour this uses no encryption
expect_set2_encrypted = False
if ncreds.secure_channel_type == misc.SEC_CHAN_WKSTA:
expect_get_error = ntstatus.NT_STATUS_ACCESS_DENIED
else:
@ -982,6 +1108,66 @@ class NetlogonSchannel(KDCBaseTest):
new_set_password,
encryption_ncreds=encryption_set_ncreds,
expect_error=expect_set_error)
if expect_broken_crypto and expect_set_error is None:
#
# This is tricky!
#
# As the encryption works with a random key,
# ServerPasswordSet and ServerGetTrustInfo
# both use the same key to decrypt
# -> store -> retrieve -> encrypt
# As a result we get back the same value we passed
# to ServerPasswordSet.
#
#
self.do_ServerGetTrustInfo(ncreds, conn,
False, # expect_encrypted
new_set_password, # expect_new_password
None, # expect_old_password
decryption_ncreds=False)
# For the old password we're not able to
# decrypt it...
self.do_ServerGetTrustInfo(ncreds, conn,
expect_encrypted,
None, #expect_new_password,
expect_old_password,
expect_broken_crypto=expect_broken_crypto)
self.do_CheckCapabilities(ncreds, conn)
# We re-negotiate the flags with
# NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH, so that
# we can get the value the server stored.
orig_flags = ncreds.negotiate_flags
krb5_flags = orig_flags | 0x80000000
ncreds = self.do_AuthenticateKerberos(conn, trust_creds, krb5_flags, krb5_flags)
self.do_CheckCapabilities(ncreds, conn)
# The value store should not be the one
# we passed to ServerPasswordSet...
self.do_ServerGetTrustInfo(ncreds, conn,
True, # expect_encrypted
new_set_password, # expect_new_password
None, # expect_old_password
expect_broken_crypto=expect_broken_crypto)
# We get the old one fixed self.empty_pwd_nt4_hash now
self.do_ServerGetTrustInfo(ncreds, conn,
False, # expect_encrypted
None, # expect_new_password,
expect_old_password)
# Now we reset the password using ServerPasswordSet2
# in order to do useful testing below...
fix_set2_password = self.get_netr_CryptPassword(new_utf8)
self.do_ServerPasswordSet2(ncreds, conn,
False, # expect__encrypted
fix_set2_password)
self.do_ServerGetTrustInfo(ncreds, conn,
False, # expect_encrypted
new_set_password, # expect_new_password
expect_old_password)
self.do_CheckCapabilities(ncreds, conn)
#
# Now we test with the original flags again
krb5_flags = orig_flags
ncreds = self.do_AuthenticateKerberos(conn, trust_creds, krb5_flags, krb5_flags)
self.do_CheckCapabilities(ncreds, conn)
if old_utf8:
trust_creds.set_old_password(old_utf8)
@ -1045,6 +1231,32 @@ class NetlogonSchannel(KDCBaseTest):
expect_old_password,
expect_broken_crypto=expect_broken_crypto)
if expect_broken_crypto and not expect_broken_set2_crypto:
#
# This is tricky!
#
# ServerPasswordSet2 isn't affected by
# broken crypto, so we can get
# back the nthashes related to
# the unencrypted plaintext password
# set passed to ServerPasswordSet2
orig_flags = ncreds.negotiate_flags
krb5_flags = orig_flags | 0x80000000
ncreds = self.do_AuthenticateKerberos(conn, trust_creds, krb5_flags, krb5_flags)
self.do_CheckCapabilities(ncreds, conn)
self.do_ServerPasswordGet(ncreds, conn,
False, # expect_encrypted
expect_new_password,
expect_error=expect_get_error)
self.do_ServerTrustPasswordsGet(ncreds, conn,
False, # expect_encrypted
expect_new_password,
expect_old_password)
self.do_ServerGetTrustInfo(ncreds, conn,
False, # expect_encrypted
expect_new_password,
expect_old_password)
self.do_CheckCapabilities(ncreds, conn)
return
@ -1052,6 +1264,9 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_check_passwords(creds,
ncreds,
conn,
@ -1062,6 +1277,23 @@ class NetlogonSchannel(KDCBaseTest):
self.do_CheckCapabilities(ncreds, conn)
expect_broken_crypto = False
if ncreds.authenticate_kerberos:
self.assertEqual(expect_encrypted, False)
if ncreds.negotiate_flags & 0x80000000:
# This is the expected case of a sane client
pass
elif ncreds.negotiate_flags & 0x01000004:
# This fails as there is aes or arfour
# encryption with a random key
expect_broken_crypto = True
expect_encrypted = True
else:
# There's no encryption with des
pass
if not (ncreds.negotiate_flags & 0x01000004):
# Without aes or arcfour this uses no encryption
expect_encrypted = False
opaque_buffer = b'invalid_opaque_buffer'
if ncreds.secure_channel_type == misc.SEC_CHAN_WKSTA:
@ -1113,6 +1345,9 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_send_to_sam(creds,
ncreds,
conn,
@ -1124,6 +1359,23 @@ class NetlogonSchannel(KDCBaseTest):
expect_broken_nt_crypto = False
expect_broken_lm_crypto = False
if ncreds.authenticate_kerberos:
self.assertEqual(expect_encrypted, False)
if ncreds.negotiate_flags & 0x80000000:
# This is the expected case of a sane client
pass
elif ncreds.negotiate_flags & 0x01000004:
# This fails as there is aes or arfour
# encryption with a random key
expect_broken_nt_crypto = True
expect_broken_lm_crypto = True
expect_encrypted = True
else:
# This fails as there is des
# encryption with a random key
# but it only encrypts the LMSessKey
expect_encrypted = True
expect_broken_lm_crypto = True
validation_level6 = netlogon.NetlogonValidationSamInfo4
validation_level3 = netlogon.NetlogonValidationSamInfo2
@ -1239,6 +1491,9 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_network_samlogon(creds,
ncreds,
conn,
@ -1258,6 +1513,16 @@ class NetlogonSchannel(KDCBaseTest):
self.user_creds)
expect_broken_crypto = False
if ncreds.authenticate_kerberos:
self.assertEqual(expect_encrypted, False)
if ncreds.negotiate_flags & 0x80000000:
# This is the expected case of a sane client
pass
else:
# This fails as there is aes, arcfour or des
# encryption with a random key
expect_broken_crypto = True
expect_encrypted = True
if expect_broken_crypto:
expect_error = ntstatus.NT_STATUS_WRONG_PASSWORD
@ -1343,6 +1608,9 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_interactive_samlogon(creds,
ncreds,
conn,
@ -1353,12 +1621,29 @@ class NetlogonSchannel(KDCBaseTest):
self.do_CheckCapabilities(ncreds, conn)
expect_broken_crypto = False
if ncreds.authenticate_kerberos:
self.assertEqual(expect_encrypted, False)
if ncreds.negotiate_flags & 0x80000000:
# This is the expected case of a sane client
pass
elif ncreds.negotiate_flags & 0x01000004:
# This fails as there is aes or arfour
# encryption with a random key
expect_broken_crypto = True
expect_encrypted = True
else:
# There's no aes nor arcfour, so no encryption
pass
if expect_broken_crypto:
expect_error = ntstatus.NT_STATUS_INVALID_PARAMETER
else:
expect_error = None
if not (ncreds.negotiate_flags & 0x01000004):
# Without aes or arcfour this uses no encryption
expect_encrypted = False
krbtgt_creds = self.get_krbtgt_creds()
krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
@ -1410,6 +1695,9 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_generic_samlogon(creds,
ncreds,
conn,
@ -1469,11 +1757,199 @@ class NetlogonSchannel(KDCBaseTest):
(creds, ncreds, conn, expect_encrypted) = \
self._prepare_ncreds_conn_with_args(trust, authX, flags)
if conn is None:
return
return self._test_ticket_samlogon(creds,
ncreds,
conn,
expect_encrypted)
def test_wks1_authenticate_flags(self):
wks1_creds = self.get_wks1_creds()
anon_conn = self.get_anon_conn()
des_flags = 0
self.do_Authenticate3(anon_conn, wks1_creds,
des_flags, des_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
strong_flags = 0x00004000
if self.strong_key_support:
strong_ncreds = self.do_Authenticate3(anon_conn, wks1_creds,
strong_flags, strong_flags)
strong_conn = self.get_schannel_conn(wks1_creds, strong_ncreds)
tmp_ncreds = ndr_deepcopy(strong_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(strong_ncreds, strong_conn)
else:
self.do_Authenticate3(anon_conn, wks1_creds,
strong_flags, strong_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
strong_conn = None
aes_flags = 0x01000000
aes_ncreds = self.do_Authenticate3(anon_conn, wks1_creds,
aes_flags, aes_flags)
aes_conn = self.get_schannel_conn(wks1_creds, aes_ncreds)
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(aes_ncreds, aes_conn)
if strong_conn:
self.do_CheckCapabilities(aes_ncreds, strong_conn)
krb5_flags = 0x80000000
krb5_ncreds = self.do_Authenticate3(anon_conn, wks1_creds,
krb5_flags, krb5_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
if strong_conn:
aes_ncreds = self.do_Authenticate3(strong_conn, wks1_creds,
aes_flags, aes_flags)
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(aes_ncreds, aes_conn)
self.do_CheckCapabilities(strong_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(aes_ncreds, strong_conn)
aes_ncreds = self.do_Authenticate3(aes_conn, wks1_creds,
aes_flags, aes_flags)
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(aes_ncreds, aes_conn)
if strong_conn:
self.do_CheckCapabilities(aes_ncreds, strong_conn)
krb5_conn = self.get_krb5_conn(wks1_creds)
des_flags = 0
self.do_Authenticate3(krb5_conn, wks1_creds,
des_flags, des_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
strong_flags = 0x00004000
if self.strong_key_support:
strong_ncreds = self.do_Authenticate3(krb5_conn, wks1_creds,
strong_flags, strong_flags)
tmp_ncreds = ndr_deepcopy(strong_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
if self.auth_krb5_support:
self.do_CheckCapabilities(strong_ncreds, krb5_conn)
else:
tmp_ncreds = ndr_deepcopy(strong_ncreds)
self.do_CheckCapabilities(tmp_ncreds, krb5_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(strong_ncreds, strong_conn)
self.do_CheckCapabilities(strong_ncreds, aes_conn)
self.do_CheckCapabilities(aes_ncreds, strong_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(strong_ncreds, aes_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
else:
self.do_Authenticate3(krb5_conn, wks1_creds,
strong_flags, strong_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
aes_flags = 0x01000000
aes_ncreds = self.do_Authenticate3(krb5_conn, wks1_creds,
aes_flags, aes_flags)
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
if self.auth_krb5_support:
self.do_CheckCapabilities(aes_ncreds, krb5_conn)
else:
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, krb5_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
if strong_conn:
self.do_CheckCapabilities(aes_ncreds, strong_conn)
self.do_CheckCapabilities(aes_ncreds, aes_conn)
krb5_flags = 0x80000000
self.do_Authenticate3(krb5_conn, wks1_creds,
krb5_flags, krb5_flags,
expect_error=ntstatus.NT_STATUS_DOWNGRADE_DETECTED)
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
if self.auth_krb5_support:
self.do_CheckCapabilities(aes_ncreds, krb5_conn)
else:
tmp_ncreds = ndr_deepcopy(aes_ncreds)
self.do_CheckCapabilities(tmp_ncreds, krb5_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
if strong_conn:
self.do_CheckCapabilities(aes_ncreds, strong_conn)
self.do_CheckCapabilities(aes_ncreds, aes_conn)
self.do_CheckCapabilities(tmp_ncreds, aes_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(aes_ncreds, aes_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
krb5_flags = 0
if not self.auth_krb5_support:
self.do_AuthenticateKerberos(krb5_conn, wks1_creds,
krb5_flags, krb5_flags,
expect_error=ntstatus.NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)
return
krb5_ncreds = self.do_AuthenticateKerberos(krb5_conn, wks1_creds,
krb5_flags, krb5_flags)
self.do_CheckCapabilities(krb5_ncreds, anon_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(krb5_ncreds, krb5_conn)
if strong_conn:
self.do_CheckCapabilities(krb5_ncreds, strong_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(krb5_ncreds, aes_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(krb5_ncreds, krb5_conn)
return
def test_wks1_vs_bdc1_authK(self):
if not self.auth_krb5_support:
self.skipTest('Required NETLOGON_AUTH_KRB5_SUPPORT')
wks1_creds = self.get_wks1_creds()
bdc1_creds = self.get_bdc1_creds()
wks1_conn = self.get_krb5_conn(wks1_creds)
bdc1_conn = self.get_krb5_conn(bdc1_creds)
krb5_flags = 0xe13fffff
wks1_ncreds = self.do_AuthenticateKerberos(wks1_conn, wks1_creds,
krb5_flags, krb5_flags)
self.do_CheckCapabilities(wks1_ncreds, wks1_conn)
bdc1_ncreds = self.do_AuthenticateKerberos(bdc1_conn, bdc1_creds,
krb5_flags, krb5_flags)
self.do_CheckCapabilities(bdc1_ncreds, bdc1_conn)
self.do_CheckCapabilities(wks1_ncreds, bdc1_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(bdc1_ncreds, wks1_conn,
expect_error1=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(wks1_ncreds, wks1_conn)
self.do_CheckCapabilities(bdc1_ncreds, bdc1_conn)
self.do_AuthenticateKerberos(wks1_conn, bdc1_creds,
krb5_flags, krb5_flags,
expect_error=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_AuthenticateKerberos(bdc1_conn, wks1_creds,
krb5_flags, krb5_flags,
expect_error=ntstatus.NT_STATUS_ACCESS_DENIED)
self.do_CheckCapabilities(wks1_ncreds, wks1_conn)
self.do_CheckCapabilities(bdc1_ncreds, bdc1_conn)
return
if __name__ == "__main__":
global_asn1_print = True

View File

@ -1,5 +1,2 @@
# Without AES we currently get DOWNGRADE_DETECTED
^samba.tests.krb5.netlogon.*.NetlogonSchannel.test_.*_auth3_00004004
^samba.tests.krb5.netlogon.*.NetlogonSchannel.test_.*_auth3_603fffff
# This is not implemented yet
^samba.tests.krb5.netlogon.*.NetlogonSchannel.test_ticket_samlogon

View File

@ -1650,6 +1650,16 @@ sub provision_ad_dc_ntvfs($$$)
server reject md5 schannel:tests4u2selfwk\$ = no
server reject md5 schannel:torturepacbdc\$ = no
server reject md5 schannel:torturepacwksta\$ = no
server reject aes schannel:schannel2\$ = no
server reject aes schannel:schannel3\$ = no
server reject aes schannel:schannel8\$ = no
server reject aes schannel:schannel9\$ = no
server reject aes schannel:torturetest\$ = no
server reject aes schannel:tests4u2proxywk\$ = no
server reject aes schannel:tests4u2selfbdc\$ = no
server reject aes schannel:tests4u2selfwk\$ = no
server reject aes schannel:torturepacbdc\$ = no
server reject aes schannel:torturepacwksta\$ = no
server require schannel:schannel0\$ = no
server require schannel:schannel1\$ = no
server require schannel:schannel2\$ = no
@ -1727,6 +1737,11 @@ sub provision_fl2000dc($$)
server reject md5 schannel:tests4u2selfwk\$ = no
server reject md5 schannel:torturepacbdc\$ = no
server reject md5 schannel:torturepacwksta\$ = no
server reject aes schannel:tests4u2proxywk\$ = no
server reject aes schannel:tests4u2selfbdc\$ = no
server reject aes schannel:tests4u2selfwk\$ = no
server reject aes schannel:torturepacbdc\$ = no
server reject aes schannel:torturepacwksta\$ = no
";
my $extra_provision_options = ["--base-schema=2008_R2"];
# This environment uses plain text secrets
@ -1782,6 +1797,11 @@ sub provision_fl2003dc($$$)
server reject md5 schannel:tests4u2selfwk\$ = no
server reject md5 schannel:torturepacbdc\$ = no
server reject md5 schannel:torturepacwksta\$ = no
server reject aes schannel:tests4u2proxywk\$ = no
server reject aes schannel:tests4u2selfbdc\$ = no
server reject aes schannel:tests4u2selfwk\$ = no
server reject aes schannel:torturepacbdc\$ = no
server reject aes schannel:torturepacwksta\$ = no
";
my $extra_provision_options = ["--base-schema=2008_R2"];
@ -1845,6 +1865,11 @@ sub provision_fl2008r2dc($$$)
server reject md5 schannel:tests4u2selfwk\$ = no
server reject md5 schannel:torturepacbdc\$ = no
server reject md5 schannel:torturepacwksta\$ = no
server reject aes schannel:tests4u2proxywk\$ = no
server reject aes schannel:tests4u2selfbdc\$ = no
server reject aes schannel:tests4u2selfwk\$ = no
server reject aes schannel:torturepacbdc\$ = no
server reject aes schannel:torturepacwksta\$ = no
";
my $extra_provision_options = ["--base-schema=2008_R2"];
my $ret = $self->provision($prefix,
@ -2071,6 +2096,7 @@ sub provision_ad_dc()
lpq cache time = 0
print notify backchannel = yes
server support krb5 netlogon = yes
CVE_2020_1472:warn_about_unused_debug_level = 3
CVE_2022_38023:warn_about_unused_debug_level = 3
CVE_2022_38023:error_debug_level = 2
@ -2085,6 +2111,17 @@ sub provision_ad_dc()
server reject md5 schannel:torturepacbdc\$ = no
server reject md5 schannel:torturepacwksta\$ = no
server reject md5 schannel:samlogontest\$ = no
server reject aes schannel:schannel2\$ = no
server reject aes schannel:schannel3\$ = no
server reject aes schannel:schannel8\$ = no
server reject aes schannel:schannel9\$ = no
server reject aes schannel:torturetest\$ = no
server reject aes schannel:tests4u2proxywk\$ = no
server reject aes schannel:tests4u2selfbdc\$ = no
server reject aes schannel:tests4u2selfwk\$ = no
server reject aes schannel:torturepacbdc\$ = no
server reject aes schannel:torturepacwksta\$ = no
server reject aes schannel:samlogontest\$ = no
server require schannel:schannel0\$ = no
server require schannel:schannel1\$ = no
server require schannel:schannel2\$ = no

View File

@ -674,6 +674,8 @@ static NTSTATUS schannel_call_setup(struct dcesrv_call_state *dce_call,
enum dcerpc_transport_t transport =
dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
if (transport != NCACN_IP_TCP) {
/* We can't call DCESRV_FAULT() in the sub-function */
dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
@ -687,8 +689,14 @@ static NTSTATUS schannel_call_setup(struct dcesrv_call_state *dce_call,
* NB. gensec requires schannel connections to
* have at least DCERPC_AUTH_LEVEL_INTEGRITY.
*/
dcesrv_call_auth_info(dce_call, &auth_type, NULL);
if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
if (auth_type == DCERPC_AUTH_TYPE_KRB5 &&
auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
{
/* ok */
} else if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
/* ok - implies at least DCERPC_AUTH_LEVEL_INTEGRITY. */
} else {
/* We can't call DCESRV_FAULT() in the sub-function */
dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
return NT_STATUS_ACCESS_DENIED;

View File

@ -178,15 +178,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
bool account_reject_md5_client = global_reject_md5_client;
const char *explicit_md5_opt = NULL;
bool global_reject_aes_client = lpcfg_server_reject_aes_schannel(lp_ctx);
bool account_reject_aes_client = global_reject_aes_client;
const char *explicit_aes_opt = NULL;
bool reject_des_client;
bool allow_nt4_crypto;
bool reject_md5_client;
bool reject_aes_client;
bool need_des = true;
bool need_md5 = true;
bool need_aes = true;
int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
"CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
"CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
int NETLOGON_AES_usage_level = lpcfg_parm_int(lp_ctx, NULL,
"NETLOGON_AES", "usage_debug_level", DBGLVL_INFO);
/*
* We don't use lpcfg_parm_bool(), as we
@ -215,6 +222,17 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
}
reject_md5_client = account_reject_md5_client;
if (trust_account_in_db != NULL) {
explicit_aes_opt = lpcfg_get_parametric(lp_ctx,
NULL,
"server reject aes schannel",
trust_account_in_db);
}
if (explicit_aes_opt != NULL) {
account_reject_aes_client = lp_bool(explicit_aes_opt);
}
reject_aes_client = account_reject_aes_client;
reject_des_client = !allow_nt4_crypto;
/*
@ -238,10 +256,19 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
reject_md5_client = false;
}
if (reject_des_client || reject_md5_client) {
if (dce_call->pkt.u.request.opnum == NDR_NETR_SERVERAUTHENTICATEKERBEROS) {
need_des = false;
need_md5 = false;
need_aes = false;
reject_des_client = false;
reject_md5_client = false;
reject_aes_client = false;
}
if (reject_des_client || reject_md5_client || reject_aes_client) {
TALLOC_CTX *frame = talloc_stackframe();
if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
if (need_aes && lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
CVE_2022_38023_error_level = DBGLVL_NOTICE;
}
@ -270,7 +297,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
"client_negotiate_flags[0x%x] "
"%s%s%s "
"NT_STATUS_DOWNGRADE_DETECTED "
"reject_des[%u] reject_md5[%u]\n",
"reject_des[%u] reject_md5[%u] "
"reject_aes[%u]\n",
log_escape(frame, r->in.account_name),
log_escape(frame, r->in.computer_name),
r->in.secure_channel_type,
@ -279,11 +307,19 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
trust_account_in_db ? trust_account_in_db : "",
trust_account_in_db ? "]" : "",
reject_des_client,
reject_md5_client));
reject_md5_client,
reject_aes_client));
if (trust_account_in_db == NULL) {
goto return_downgrade;
}
if (reject_aes_client && explicit_aes_opt == NULL) {
DEBUG(CVE_2022_38023_error_level, (
"CVE-2022-38023: Check if option "
"'server reject aes schannel:%s = no' "
"might be needed for a legacy client.\n",
trust_account_in_db));
}
if (reject_md5_client && explicit_md5_opt == NULL) {
DEBUG(CVE_2022_38023_error_level, (
"CVE-2022-38023: Check if option "
@ -341,6 +377,28 @@ return_downgrade:
return orig_status;
}
if (global_reject_aes_client && account_reject_aes_client && explicit_aes_opt) {
D_INFO("NETLOGON-AES: Check if option "
"'server reject aes schannel:%s = yes' not needed!?\n",
trust_account_in_db);
} else if (need_aes && !account_reject_aes_client && explicit_aes_opt) {
D_INFO("NETLOGON-AES: Check if option "
"'server reject aes schannel:%s = no' "
"still needed for a client.\n",
trust_account_in_db);
} else if (need_aes && explicit_aes_opt == NULL) {
DEBUG(NETLOGON_AES_usage_level, (
"NETLOGON-AES: Check if option "
"'server reject aes schannel:%s = no' "
"might be needed for a client.\n",
trust_account_in_db));
} else if (!account_reject_aes_client && explicit_aes_opt) {
DEBUG(CVE_2022_38023_warn_level, (
"CVE-2022-38023: Check if option "
"'server reject aes schannel:%s = no' not needed!?\n",
trust_account_in_db));
}
if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
D_INFO("CVE-2022-38023: Check if option "
"'server reject md5 schannel:%s = yes' not needed!?\n",
@ -432,6 +490,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticateGeneric(
uint32_t server_flags = 0;
uint32_t client_flags = 0;
uint32_t negotiate_flags = 0;
struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
bool server_support_krb5_netlogon = lpcfg_server_support_krb5_netlogon(lp_ctx);
ZERO_STRUCTP(r->out.return_credentials);
*r->out.negotiate_flags = 0;
@ -510,6 +570,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticateGeneric(
NETLOGON_NEG_SUPPORTS_AES |
NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
NETLOGON_NEG_AUTHENTICATED_RPC;
if (server_support_krb5_netlogon) {
server_flags |= NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH;
}
/*
* With SAMBA_WEAK_CRYPTO_DISALLOWED
@ -1038,6 +1101,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
return NT_STATUS_NOT_SUPPORTED;
}
nt_status = netlogon_creds_decrypt_samr_Password(creds,
r->in.new_password,
auth_type,
@ -1127,9 +1194,40 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_ACCESS_DENIED;
}
/*
* We don't allow empty passwords for machine accounts.
*/
if (new_password.length < 2) {
DBG_WARNING("Empty password Length[%zu]\n",
new_password.length);
return NT_STATUS_WRONG_PASSWORD;
}
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
/*
* netlogon_creds_decrypt_samr_CryptPassword
* already checked for DCERPC_AUTH_LEVEL_PRIVACY
*/
goto checked_encryption;
} else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
/*
* check it's encrypted
*/
} else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
/*
* check it's encrypted
*/
} else {
/*
* netlogon_creds_decrypt_samr_CryptPassword
* already checked for DCERPC_AUTH_LEVEL_PRIVACY
*/
goto checked_encryption;
}
/*
* Make sure the length field was encrypted,
* otherwise we are under attack.
@ -1140,15 +1238,6 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
return NT_STATUS_WRONG_PASSWORD;
}
/*
* We don't allow empty passwords for machine accounts.
*/
if (new_password.length < 2) {
DBG_WARNING("Empty password Length[%zu]\n",
new_password.length);
return NT_STATUS_WRONG_PASSWORD;
}
/*
* Make sure the confounder part of CryptPassword
* buffer was encrypted, otherwise we are under attack.
@ -1176,6 +1265,8 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
return NT_STATUS_WRONG_PASSWORD;
}
checked_encryption:
/*
* don't allow zero buffers
*/
@ -1354,10 +1445,6 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL
break;
case NDR_NETR_LOGONSAMLOGONEX:
default:
if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
return NT_STATUS_ACCESS_DENIED;
}
nt_status = dcesrv_netr_check_schannel(dce_call,
creds,
auth_type,
@ -1366,6 +1453,13 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
if (!creds->authenticate_kerberos &&
auth_type != DCERPC_AUTH_TYPE_SCHANNEL)
{
return NT_STATUS_ACCESS_DENIED;
}
break;
}
@ -1507,7 +1601,9 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL
case NetlogonGenericInformation:
{
if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
if (creds->authenticate_kerberos) {
/* OK */
} else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
/* OK */
} else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
/* OK */
@ -4888,6 +4984,72 @@ DCESRV_NOT_USED_ON_WIRE(netr_Opnum56NotUsedOnWire)
DCESRV_NOT_USED_ON_WIRE(netr_Opnum57NotUsedOnWire)
DCESRV_NOT_USED_ON_WIRE(netr_Opnum58NotUsedOnWire)
static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos_cb(
struct dcesrv_call_state *dce_call,
const struct netlogon_server_pipe_state *challenge,
const struct netr_ServerAuthenticate3 *r,
uint32_t client_flags,
const struct dom_sid *client_sid,
uint32_t negotiate_flags,
const struct ldb_message *sam_msg,
const struct ldb_message *tdo_msg,
TALLOC_CTX *mem_ctx,
struct netlogon_creds_CredentialState **_creds)
{
TALLOC_CTX *frame = talloc_stackframe();
struct netlogon_creds_CredentialState *creds = NULL;
enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
struct auth_session_info *session_info =
dcesrv_call_session_info(dce_call);
const struct dom_sid *auth_sid =
&session_info->security_token->sids[0];
dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
/*
* The client needs to come via a
* connection encrypted with kerberos.
*
* And the SID from the PAC needs to
* match the sid for the requested
* account name
*/
if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
TALLOC_FREE(frame);
return NT_STATUS_ACCESS_DENIED;
}
if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
TALLOC_FREE(frame);
return NT_STATUS_ACCESS_DENIED;
}
if (!dom_sid_equal(client_sid, auth_sid)) {
TALLOC_FREE(frame);
return NT_STATUS_ACCESS_DENIED;
}
SMB_ASSERT(r->in.credentials == NULL);
SMB_ASSERT(r->out.return_credentials == NULL);
creds = netlogon_creds_kerberos_init(mem_ctx,
r->in.account_name,
r->in.computer_name,
r->in.secure_channel_type,
client_flags,
client_sid,
negotiate_flags);
if (creds == NULL) {
TALLOC_FREE(frame);
return NT_STATUS_ACCESS_DENIED;
}
*_creds = creds;
TALLOC_FREE(frame);
return NT_STATUS_OK;
}
/*
netr_ServerAuthenticateKerberos
*/
@ -4895,7 +5057,76 @@ static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos(struct dcesrv_call_state
TALLOC_CTX *mem_ctx,
struct netr_ServerAuthenticateKerberos *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
NTSTATUS status;
struct dom_sid *sid = NULL;
const char *trust_account_for_search = NULL;
const char *trust_account_in_db = NULL;
struct imessaging_context *imsg_ctx =
dcesrv_imessaging_context(dce_call->conn);
struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
bool server_support_krb5_netlogon = lpcfg_server_support_krb5_netlogon(lp_ctx);
struct auth_usersupplied_info ui = {
.local_host = dce_call->conn->local_address,
.remote_host = dce_call->conn->remote_address,
.client = {
.account_name = r->in.account_name,
.domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
},
.service_description = "NETLOGON",
.auth_description = "ServerAuthenticate",
.netlogon_trust_account = {
.computer_name = r->in.computer_name,
.negotiate_flags = *r->in.negotiate_flags,
.authenticate_kerberos = true,
.secure_channel_type = r->in.account_type,
},
};
struct netr_ServerAuthenticate3 r3 = {
.in = {
.server_name = r->in.server_name,
.account_name = r->in.account_name,
.secure_channel_type = r->in.account_type,
.computer_name = r->in.computer_name,
.credentials = NULL,
.negotiate_flags = r->in.negotiate_flags,
},
.out = {
.return_credentials = NULL,
.rid = r->out.rid,
.negotiate_flags = r->out.negotiate_flags,
.result = NT_STATUS_INTERNAL_ERROR,
},
};
dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn =
dcesrv_netr_ServerAuthenticateKerberos_cb;
if (!server_support_krb5_netlogon) {
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
status = dcesrv_netr_ServerAuthenticateGeneric(dce_call,
mem_ctx,
&r3,
auth_fn,
&trust_account_for_search,
&trust_account_in_db,
&sid);
ui.netlogon_trust_account.sid = sid;
ui.netlogon_trust_account.account_name = trust_account_in_db;
ui.mapped.account_name = trust_account_for_search;
log_authentication_event(
imsg_ctx,
dce_call->conn->dce_ctx->lp_ctx,
NULL,
&ui,
status,
lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
trust_account_in_db,
sid,
NULL /* client_audit_info */,
NULL /* server_audit_info */);
return status;
}
/* include the generated boilerplate */

View File

@ -1995,6 +1995,8 @@ for env in ["ad_dc"]:
environ={
**krb5_environ,
'FAST_SUPPORT': fast_support,
'NETLOGON_STRONG_KEY_SUPPORT': '0',
'NETLOGON_AUTH_KRB5_SUPPORT': '1',
})
planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests',