The branch, master has been updated
       via  6bf1b9885b7 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
zero password
       via  61f216dc896 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
max len password
       via  56297c70890 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
all zero password
       via  b2f4a556715 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
confounder
       via  e790f9d20a1 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
all zero password
       via  f47e3734158 CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 
all zero enc req
       via  07c316346ae CVE-2020-1472(ZeroLogon): torture: Move existing tests
       via  6f59a5fd841 CVE-2020-1472(ZeroLogon): Add zerologon test suite
       via  b9b6abf18b8 CVE-2020-1472(ZeroLogon): rpc_server/netlogon: Fix 
confounder check
       via  c56c5c17fd4 tevent: also use portable __has_attribute macro to 
check for "deprecated" attribute
       via  de748864201 replace: also use portable __has_attribute macro to 
check for "deprecated" attribute
       via  2889baeec4a talloc: also use portable __has_attribute macro to 
check for "deprecated" attribute
       via  2541f67c67e fuzz: add fuzz_cli_credentials_parse_string
       via  e721dfc833a fuzz: add fuzz_dcerpc_parse_binding
      from  2b8b0139fcc vfs_zfsacl: add zfs configuration guidance to manpage

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 6bf1b9885b7ca8f6164e5d9065aceb15a363ea90
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 10:02:16 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 zero password
    
    Ensure that a password of all zeros shorter than the maximum length is
    rejected.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abart...@samba.org>
    Autobuild-Date(master): Fri Oct 16 06:09:06 UTC 2020 on sn-devel-184

commit 61f216dc89669be2641bba678cf6e1c69788364d
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 10:01:34 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 max len password
    
    Ensure that a maximum length password (512) is still accepted
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 56297c70890287d800e30cf057e4702314261d0b
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 10:00:54 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 all zero password
    
    Check that an all zero password is rejected, Note this test user ARC4
    encryption so that it passes the self encryption test.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit b2f4a556715119da526bf67ae4ee7b444ed7c9f5
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 10:00:00 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 confounder
    
    Test that a confounder that encrypts to itself is rejected
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit e790f9d20a123859ed687ae1d5af6159c0fed61a
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 09:54:41 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 all zero password
    
    Check that a password buffer containing all zeros is rejected.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit f47e3734158c108f2ea3e875f87085649dc0704e
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 09:45:28 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: ServerSetPassword2 all zero enc req
    
    Check that a request that encrypts to all zeros, is rejected if the length
    encrypts to itself.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 07c316346ae3e7778d5d6809245480f2b30275bd
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 09:33:35 2020 +1300

    CVE-2020-1472(ZeroLogon): torture: Move existing tests
    
    Move the existing ZeroLogon tests into the ZeroLogon testsuite.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 6f59a5fd8416bd648265b909ca45de6376747548
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Mon Sep 28 09:29:25 2020 +1300

    CVE-2020-1472(ZeroLogon): Add zerologon test suite
    
    Add a ZeroLogon test suite, to allow the ZeroLogon tests to be run against
    the s3 and s4 netlogon servers.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit b9b6abf18b873ee83194405719fe993b8fb2073a
Author: Gary Lockyer <g...@catalyst.net.nz>
Date:   Thu Sep 24 13:35:47 2020 +1200

    CVE-2020-1472(ZeroLogon): rpc_server/netlogon: Fix confounder check
    
    Add check for zero length confounder, to allow setting of passwords 512
    bytes long. This does not need to be backported, as it is extremely
    unlikely that anyone is using 512 byte passwords.
    
    Signed-off-by: Gary Lockyer <g...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit c56c5c17fd4f5764935ee6a4cd90b9c0a2c525b4
Author: Björn Jacke <b...@sernet.de>
Date:   Thu Oct 8 12:21:31 2020 +0200

    tevent: also use portable __has_attribute macro to check for "deprecated" 
attribute
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14526
    
    Signed-off-by: Bjoern Jacke <bja...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit de748864201167ac1b4ecf4f121fbe2b110103e5
Author: Björn Jacke <b...@sernet.de>
Date:   Thu Oct 8 12:10:35 2020 +0200

    replace: also use portable __has_attribute macro to check for "deprecated" 
attribute
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14526
    
    Signed-off-by: Bjoern Jacke <bja...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 2889baeec4a1c66a1ffd78469ed916e3b292f4d0
Author: Björn Jacke <b...@sernet.de>
Date:   Thu Oct 8 12:05:41 2020 +0200

    talloc: also use portable __has_attribute macro to check for "deprecated" 
attribute
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14526
    
    Signed-off-by: Bjoern Jacke <bja...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 2541f67c67eda0f772bd3fd3980be20265d6186e
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Oct 8 16:22:44 2020 +1300

    fuzz: add fuzz_cli_credentials_parse_string
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit e721dfc833a84a83158bee1182336b2502a9a57d
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Wed Sep 30 15:34:37 2020 +1300

    fuzz: add fuzz_dcerpc_parse_binding
    
    We parse a binding and do a few tricks with it, including turning it
    into a tower and back.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 ...acket.c => fuzz_cli_credentials_parse_string.c} |  59 +-
 lib/fuzzing/fuzz_dcerpc_parse_binding.c            |  68 +++
 lib/fuzzing/wscript_build                          |  10 +
 lib/replace/replace.h                              |   2 +-
 lib/talloc/talloc.h                                |   2 +-
 lib/tevent/tevent.h                                |   8 +-
 selftest/knownfail.d/rpc-netlogon-zerologon        |   4 +
 source3/rpc_server/netlogon/srv_netlog_nt.c        |   2 +-
 source3/selftest/tests.py                          |   1 +
 source4/rpc_server/netlogon/dcerpc_netlogon.c      |   2 +-
 source4/selftest/tests.py                          |   4 +-
 source4/torture/rpc/netlogon.c                     | 654 ++++++++++++++++++++-
 source4/torture/rpc/rpc.c                          |   1 +
 13 files changed, 765 insertions(+), 52 deletions(-)
 copy lib/fuzzing/{fuzz_nmblib_parse_packet.c => 
fuzz_cli_credentials_parse_string.c} (54%)
 create mode 100644 lib/fuzzing/fuzz_dcerpc_parse_binding.c
 create mode 100644 selftest/knownfail.d/rpc-netlogon-zerologon


Changeset truncated at 500 lines:

diff --git a/lib/fuzzing/fuzz_nmblib_parse_packet.c 
b/lib/fuzzing/fuzz_cli_credentials_parse_string.c
similarity index 54%
copy from lib/fuzzing/fuzz_nmblib_parse_packet.c
copy to lib/fuzzing/fuzz_cli_credentials_parse_string.c
index 7b35abe9f97..3b88109298d 100644
--- a/lib/fuzzing/fuzz_nmblib_parse_packet.c
+++ b/lib/fuzzing/fuzz_cli_credentials_parse_string.c
@@ -15,42 +15,43 @@
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-
-#include "../../source3/include/includes.h"
-#include "libsmb/libsmb.h"
-#include "libsmb/nmblib.h"
+#include "includes.h"
+#include "auth/credentials/credentials.h"
 #include "fuzzing/fuzzing.h"
 
-#define PORT 138
-#define MAX_LENGTH (1024 * 1024)
+#define MAX_LENGTH (1024 * 10)
 char buf[MAX_LENGTH + 1];
 
+const enum credentials_obtained obtained = CRED_UNINITIALISED;
+
 
 int LLVMFuzzerTestOneInput(uint8_t *input, size_t len)
 {
-       struct packet_struct *p = NULL;
-       struct in_addr ip = {
-               0x0100007f /* 127.0.0.1 */
-       };
-
-       p = parse_packet((char *)input,
-                        len,
-                        NMB_PACKET,
-                        ip,
-                        PORT);
-       /*
-        * We expect NULL (parse failure) most of the time.
-        *
-        * When it is not NULL we want to ensure the parsed packet is
-        * reasonably sound.
-        */
-
-       if (p != NULL) {
-               struct nmb_packet *nmb = &p->packet.nmb;
-               pull_ascii_nstring(buf, MAX_LENGTH,
-                                  nmb->question.question_name.name);
-               build_packet(buf, MAX_LENGTH, p);
-               free_packet(p);
+       TALLOC_CTX *mem_ctx = NULL;
+       struct cli_credentials *credentials = NULL;
+       bool anon;
+       const char *username;
+       const char *domain;
+
+       if (len > MAX_LENGTH) {
+               return 0;
        }
+
+       memcpy(buf, input, len);
+       buf[len] = '\0';
+
+       mem_ctx = talloc_new(NULL);
+       credentials = cli_credentials_init(mem_ctx);
+
+       cli_credentials_parse_string(credentials, buf, obtained);
+
+       anon = cli_credentials_is_anonymous(credentials);
+
+       cli_credentials_get_ntlm_username_domain(credentials,
+                                                mem_ctx,
+                                                &username,
+                                                &domain);
+
+       talloc_free(mem_ctx);
        return 0;
 }
diff --git a/lib/fuzzing/fuzz_dcerpc_parse_binding.c 
b/lib/fuzzing/fuzz_dcerpc_parse_binding.c
new file mode 100644
index 00000000000..5f1c68707ed
--- /dev/null
+++ b/lib/fuzzing/fuzz_dcerpc_parse_binding.c
@@ -0,0 +1,68 @@
+/*
+  Fuzz NMB parse_packet
+  Copyright (C) Catalyst IT 2020
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_epmapper.h"
+#include "librpc/rpc/dcerpc.h"
+#include "fuzzing/fuzzing.h"
+
+#define MAX_LENGTH (1024 * 10)
+char buf[MAX_LENGTH + 1];
+
+
+int LLVMFuzzerTestOneInput(uint8_t *input, size_t len)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+       struct dcerpc_binding *binding = NULL;
+       struct dcerpc_binding *dup = NULL;
+       struct epm_tower tower;
+       NTSTATUS status;
+       struct GUID guid;
+
+       if (len > MAX_LENGTH) {
+               return 0;
+       }
+       memcpy(buf, input, len);
+       buf[len]  = '\0';
+
+       status = dcerpc_parse_binding(mem_ctx, buf, &binding);
+
+       if (! NT_STATUS_IS_OK(status)) {
+               talloc_free(mem_ctx);
+               return 0;
+       }
+
+       /* If the string parses, we try manipulating it a bit */
+
+       dcerpc_binding_string(mem_ctx, binding);
+       dcerpc_binding_get_abstract_syntax(binding);
+       dup = dcerpc_binding_dup(mem_ctx, binding);
+
+       status = dcerpc_binding_build_tower(mem_ctx,
+                                           binding,
+                                           &tower);
+       if (NT_STATUS_IS_OK(status)) {
+               status = dcerpc_binding_from_tower(mem_ctx,
+                                                  &tower,
+                                                  &dup);
+       }
+
+       guid = dcerpc_binding_get_object(binding);
+
+       talloc_free(mem_ctx);
+       return 0;
+}
diff --git a/lib/fuzzing/wscript_build b/lib/fuzzing/wscript_build
index f8b3886d3da..1322d713d0b 100644
--- a/lib/fuzzing/wscript_build
+++ b/lib/fuzzing/wscript_build
@@ -72,6 +72,16 @@ bld.SAMBA_BINARY('fuzz_ldb_parse_tree',
                  deps='fuzzing ldb afl-fuzz-main',
                  fuzzer=True)
 
+bld.SAMBA_BINARY('fuzz_dcerpc_parse_binding',
+                 source='fuzz_dcerpc_parse_binding.c',
+                 deps='fuzzing dcerpc afl-fuzz-main',
+                 fuzzer=True)
+
+bld.SAMBA_BINARY('fuzz_cli_credentials_parse_string',
+                 source='fuzz_cli_credentials_parse_string.c',
+                 deps='fuzzing samba-credentials afl-fuzz-main',
+                 fuzzer=True)
+
 # The fuzz_type and fuzz_function parameters make the built
 # fuzzer take the same input as ndrdump and so the same that
 # could be sent to the client or server as the stub data.
diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index 6c78311f2d3..f7f6b653869 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -465,7 +465,7 @@ int rep_dlclose(void *handle);
 #endif
 
 #ifndef _DEPRECATED_
-#ifdef HAVE___ATTRIBUTE__
+#if __has_attribute(deprecated) || (__GNUC__ >= 3)
 #define _DEPRECATED_ __attribute__ ((deprecated))
 #else
 #define _DEPRECATED_
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
index 0154bf3bbf6..afa0e85d195 100644
--- a/lib/talloc/talloc.h
+++ b/lib/talloc/talloc.h
@@ -107,7 +107,7 @@ typedef void TALLOC_CTX;
 #endif
 
 #ifndef _DEPRECATED_
-#ifdef HAVE___ATTRIBUTE__
+#if __has_attribute(deprecated) || (__GNUC__ >= 3)
 #define _DEPRECATED_ __attribute__ ((deprecated))
 #else
 #define _DEPRECATED_
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index dc68a1d3f69..b8e46feec46 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -33,6 +33,12 @@
 #include <sys/time.h>
 #include <stdbool.h>
 
+/* for old gcc releases that don't have the feature test macro __has_attribute 
*/
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+
 struct tevent_context;
 struct tevent_ops;
 struct tevent_fd;
@@ -2076,7 +2082,7 @@ void _tevent_threaded_schedule_immediate(struct 
tevent_threaded_context *tctx,
 
 #ifdef TEVENT_DEPRECATED
 #ifndef _DEPRECATED_
-#ifdef HAVE___ATTRIBUTE__
+#if __has_attribute(deprecated) || (__GNUC__ >= 3)
 #define _DEPRECATED_ __attribute__ ((deprecated))
 #else
 #define _DEPRECATED_
diff --git a/selftest/knownfail.d/rpc-netlogon-zerologon 
b/selftest/knownfail.d/rpc-netlogon-zerologon
new file mode 100644
index 00000000000..29d2e6ee393
--- /dev/null
+++ b/selftest/knownfail.d/rpc-netlogon-zerologon
@@ -0,0 +1,4 @@
+#
+# Due to differences in the way UTF-16 strings are handled by the source4 and
+# source3 rpc servers, this test fails on the source3 rpc server
+^samba3.rpc.netlogon.zerologon.netlogon.test_SetPassword2_maximum_length_password\(nt4_dc\)
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c 
b/source3/rpc_server/netlogon/srv_netlog_nt.c
index c217fee9c43..3a80d4f56b0 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1524,7 +1524,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
        confounder_len = 512 - new_password.length;
        enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
        dec_blob = data_blob_const(password_buf.data, confounder_len);
-       if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+       if (confounder_len > 0 && data_blob_cmp(&dec_blob, &enc_blob) == 0) {
                DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
                            confounder_len);
                TALLOC_FREE(creds);
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index be0efd3217e..002f6d4a4b0 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -626,6 +626,7 @@ rpc = ["rpc.authcontext", "rpc.samba3.bind", 
"rpc.samba3.srvsvc", "rpc.samba3.sh
        "rpc.samr.passwords.pwdlastset", "rpc.samr.passwords.lockout", 
"rpc.samr.passwords.badpwdcount", "rpc.samr.large-dc", "rpc.samr.machine.auth",
        "rpc.samr.priv", "rpc.samr.passwords.validate", "rpc.samr.handletype",
        "rpc.netlogon.admin",
+       "rpc.netlogon.zerologon",
        "rpc.schannel", "rpc.schannel2", "rpc.bench-schannel1", 
"rpc.schannel_anon_setpw", "rpc.join", "rpc.bind",
        "rpc.initshutdown", "rpc.wkssvc", "rpc.srvsvc"]
 
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c 
b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 0c5ed1f0665..ac8f2eab657 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -909,7 +909,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct 
dcesrv_call_state *dce_cal
        confounder_len = 512 - new_password.length;
        enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
        dec_blob = data_blob_const(password_buf.data, confounder_len);
-       if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+       if (confounder_len > 0 && data_blob_cmp(&dec_blob, &enc_blob) == 0) {
                DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
                            confounder_len);
                return NT_STATUS_WRONG_PASSWORD;
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index ccd895fcd54..71c87229852 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -186,9 +186,9 @@ 
plantestsuite_loadlist("samba4.tests.attr_from_server.python(ad_dc_ntvfs)",
 # add tests to this list as they start passing, so we test
 # that they stay passing
 ncacn_np_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", 
"rpc.altercontext", "rpc.netlogon", "rpc.netlogon.admin", "rpc.handles", 
"rpc.samsync", "rpc.samba3-sessionkey", "rpc.samba3-getusername", 
"rpc.samba3-lsa", "rpc.samba3-bind", "rpc.samba3-netlogon", "rpc.asyncbind", 
"rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext"]
-ncalrpc_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", 
"rpc.altercontext", "rpc.netlogon", "rpc.netlogon.admin", "rpc.asyncbind", 
"rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", "rpc.authcontext"]
+ncalrpc_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", 
"rpc.altercontext", "rpc.netlogon", "rpc.netlogon.admin", 
"rpc.netlogon.zerologon", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", 
"rpc.schannel2", "rpc.authcontext"]
 drs_rpc_tests = smbtorture4_testsuites("drs.rpc")
-ncacn_ip_tcp_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", 
"rpc.drsuapi", "rpc.drsuapi_w2k8", "rpc.netlogon", "rpc.netlogon.admin", 
"rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", "rpc.schannel2", 
"rpc.authcontext", "rpc.samr.passwords.validate"] + drs_rpc_tests
+ncacn_ip_tcp_tests = ["rpc.schannel", "rpc.join", "rpc.lsa", "rpc.dssetup", 
"rpc.drsuapi", "rpc.drsuapi_w2k8", "rpc.netlogon", "rpc.netlogon.admin", 
"rpc.netlogon.zerologon", "rpc.asyncbind", "rpc.lsalookup", "rpc.lsa-getuser", 
"rpc.schannel2", "rpc.authcontext", "rpc.samr.passwords.validate"] + 
drs_rpc_tests
 slow_ncacn_np_tests = ["rpc.samlogon", "rpc.samr", "rpc.samr.users", 
"rpc.samr.large-dc", "rpc.samr.users.privileges", "rpc.samr.passwords", 
"rpc.samr.passwords.pwdlastset", "rpc.samr.passwords.lockout", 
"rpc.samr.passwords.badpwdcount"]
 slow_ncacn_ip_tcp_tests = ["rpc.cracknames"]
 
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 3fdcfcf9c22..7899b987724 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -807,6 +807,108 @@ static bool test_ServerReqChallenge_4_repeats(
        return true;
 }
 
+/*
+ * Establish a NetLogon session, using a session key that encrypts the
+ * target character to zero
+ */
+static bool test_ServerAuthenticate2_encrypts_to_zero(
+       struct torture_context *tctx,
+       struct dcerpc_pipe *p,
+       struct cli_credentials *machine_credentials,
+       const char target,
+       struct netlogon_creds_CredentialState **creds_out)
+{
+       const char *computer_name =
+               cli_credentials_get_workstation(machine_credentials);
+       struct netr_ServerReqChallenge r;
+       struct netr_ServerAuthenticate2 a;
+       struct netr_Credential credentials1, credentials2, credentials3;
+       struct netlogon_creds_CredentialState *creds  = NULL;
+       const struct samr_Password *mach_password;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       const char *account_name = cli_credentials_get_username(
+               machine_credentials);
+       uint32_t flags =
+               NETLOGON_NEG_AUTH2_ADS_FLAGS |
+               NETLOGON_NEG_SUPPORTS_AES;
+       enum netr_SchannelType sec_chan_type =
+               cli_credentials_get_secure_channel_type(machine_credentials);
+       /*
+        * Limit the number of attempts to generate a suitable session key.
+        */
+       const unsigned MAX_ITER = 4096;
+       unsigned i = 0;
+
+       mach_password = cli_credentials_get_nt_hash(machine_credentials, tctx);
+
+       r.in.server_name = NULL;
+       r.in.computer_name = computer_name;
+       r.in.credentials = &credentials1;
+       r.out.return_credentials = &credentials2;
+
+       netlogon_creds_random_challenge(&credentials1);
+       credentials1.data[0] = target;
+       i = 0;
+       torture_comment(tctx, "Generating candidate session keys\n");
+       do {
+               TALLOC_FREE(creds);
+               i++;
+
+               torture_assert_ntstatus_ok(
+                       tctx,
+                       dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+                       "ServerReqChallenge failed");
+               torture_assert_ntstatus_ok(
+                       tctx,
+                       r.out.result,
+                       "ServerReqChallenge failed");
+
+               a.in.server_name = NULL;
+               a.in.account_name = account_name;
+               a.in.secure_channel_type = sec_chan_type;
+               a.in.computer_name = computer_name;
+               a.in.negotiate_flags = &flags;
+               a.out.negotiate_flags = &flags;
+               a.in.credentials = &credentials3;
+               a.out.return_credentials = &credentials3;
+
+               creds = netlogon_creds_client_init(
+                       tctx,
+                       a.in.account_name,
+                       a.in.computer_name,
+                       a.in.secure_channel_type,
+                       &credentials1,
+                       &credentials2,
+                       mach_password,
+                       &credentials3,
+                       flags);
+
+               torture_assert(tctx, creds != NULL, "memory allocation");
+       } while (credentials3.data[0] != 0 && i < MAX_ITER);
+
+       if (i >= MAX_ITER) {
+               torture_comment(
+                       tctx,
+                       "Unable to obtain a suitable session key, "
+                       "after [%u] attempts\n",
+                       i);
+               torture_fail(tctx, "Unable obtain suitable session key");
+       }
+
+       torture_assert_ntstatus_ok(
+               tctx,
+               dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a),
+               "ServerAuthenticate2 failed");
+       torture_assert_ntstatus_equal(
+               tctx,
+               a.out.result,
+               NT_STATUS_OK,
+               "ServerAuthenticate2 unexpected result code");
+
+       *creds_out = creds;
+       return true;
+}
+
 /*
   try a change password for our machine account
 */
@@ -1168,6 +1270,484 @@ static bool test_SetPassword2_with_flags(struct 
torture_context *tctx,
        return true;
 }
 
+/*
+  try to change the password of our machine account using a buffer of all 
zeros,
+  and a session key that encrypts that to all zeros.
+
+Note: The test does use sign and seal, it's purpose is to exercise
+      the detection code in dcesrv_netr_ServerPasswordSet2
+*/
+static bool test_SetPassword2_encrypted_to_all_zeros(
+       struct torture_context *tctx,
+       struct dcerpc_pipe *p1,
+       struct cli_credentials *machine_credentials)
+{
+       struct netr_ServerPasswordSet2 r;
+       struct netlogon_creds_CredentialState *creds;
+       struct samr_CryptPassword password_buf;
+       struct netr_Authenticator credential, return_authenticator;
+       struct netr_CryptPassword new_password;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+
+       if (!test_ServerAuthenticate2_encrypts_to_zero(
+               tctx,
+               p1,
+               machine_credentials,
+               '\0',
+               &creds)) {
+
+               return false;
+       }
+
+       if (!test_SetupCredentialsPipe(
+               p1,
+               tctx,
+               machine_credentials,
+               creds,
+               DCERPC_SIGN | DCERPC_SEAL,
+               &p))
+       {
+               return false;
+       }
+       b = p->binding_handle;
+
+       r.in.server_name = talloc_asprintf(
+               tctx,
+               "\\\\%s", dcerpc_server_name(p));
+       r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
+       r.in.secure_channel_type =
+               cli_credentials_get_secure_channel_type(machine_credentials);
+       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.credential = &credential;
+       r.in.new_password = &new_password;
+       r.out.return_authenticator = &return_authenticator;
+
+       ZERO_STRUCT(password_buf);
+
+       if (!(creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) {
+               torture_fail(tctx, "NETLOGON_NEG_SUPPORTS_AES not set");
+       }
+       netlogon_creds_aes_encrypt(creds, password_buf.data, 516);
+       if(!all_zero(password_buf.data, 516)) {
+               torture_fail(tctx, "Password did not encrypt to all zeros\n");
+       }
+
+       memcpy(new_password.data, password_buf.data, 512);
+       new_password.length = IVAL(password_buf.data, 512);
+       torture_assert_int_equal(
+               tctx,
+               new_password.length,
+               0,
+               "Length should have encrypted to 0");
+
+       netlogon_creds_client_authenticator(creds, &credential);
+
+       torture_assert_ntstatus_ok(
+               tctx,
+               dcerpc_netr_ServerPasswordSet2_r(b, tctx, &r),
+               "ServerPasswordSet2 zero length check failed");
+       torture_assert_ntstatus_equal(
+               tctx, r.out.result, NT_STATUS_WRONG_PASSWORD, "");
+
+       return true;
+}
+
+/*
+ * Choose a session key that encrypts a password of all zeros to all zeros.
+ * Then try to set the password, using a zeroed buffer, with a non zero
+ * length.
+ *
+ * This exercises the password self encryption check.
+ *
+ * Note: The test does use sign and seal, it's purpose is to exercise
+ *     the detection code in dcesrv_netr_ServerPasswordSet2


-- 
Samba Shared Repository

Reply via email to