The Samba-Bugzilla – Attachment 13329 Details for
Bug 12782
winbindd changes the local password and gets NT_STATUS_WRONG_PASSWORD for the remote change
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patches for v4-6-test
tmp46.diff.txt (text/plain), 196.47 KB, created by
Stefan Metzmacher
on 2017-06-29 13:54:44 UTC
(
hide
)
Description:
Patches for v4-6-test
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2017-06-29 13:54:44 UTC
Size:
196.47 KB
patch
obsolete
>From 3bb31eeaaf2c23de887473a87b5d3c472ad6e4b9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 12 Jun 2017 18:58:49 +0200 >Subject: [PATCH 01/56] pidl:NDR/Parser: add missing {start,end}_flags() to > ParseElementPrint() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 81bbfb010599b65308aca89cc50532372ca4cb00) >--- > pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 4 ++++ > 1 file changed, 4 insertions(+) > >diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm >index 94f4855..044e1d1 100644 >--- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm >+++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm >@@ -839,8 +839,10 @@ sub ParseElementPrint($$$$$) > my $cur_depth = 0; > my $ignore_depth = 0xFFFF; > >+ $self->start_flags($e, $ndr); > if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { > $self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}($ndr, \"$e->{NAME}\", $var_name);"); >+ $self->end_flags($e, $ndr); > return; > } > >@@ -935,6 +937,8 @@ sub ParseElementPrint($$$$$) > $self->pidl("$ndr->depth--;"); > } > } >+ >+ $self->end_flags($e, $ndr); > } > > ##################################################################### >-- >1.9.1 > > >From 6aa850b05a7c6af20c0694aadff268cea9ecf15a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 12 Jun 2017 15:22:42 +0200 >Subject: [PATCH 02/56] librpc/ndr: align the definition of LIBNDR_STRING_FLAGS > with currently defined flags > >The range included the unused (1<<14) before. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 91d8272e8604b5d87bcc0ce365b553bc760c8ed3) >--- > librpc/ndr/libndr.h | 14 +++++++++++++- > 1 file changed, 13 insertions(+), 1 deletion(-) > >diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h >index 0c3c55a..db13c05 100644 >--- a/librpc/ndr/libndr.h >+++ b/librpc/ndr/libndr.h >@@ -124,7 +124,19 @@ struct ndr_print { > #define LIBNDR_FLAG_STR_CHARLEN (1<<11) > #define LIBNDR_FLAG_STR_UTF8 (1<<12) > #define LIBNDR_FLAG_STR_RAW8 (1<<13) >-#define LIBNDR_STRING_FLAGS (0x7FFC) >+#define LIBNDR_STRING_FLAGS (0 | \ >+ LIBNDR_FLAG_STR_ASCII | \ >+ LIBNDR_FLAG_STR_LEN4 | \ >+ LIBNDR_FLAG_STR_SIZE4 | \ >+ LIBNDR_FLAG_STR_NOTERM | \ >+ LIBNDR_FLAG_STR_NULLTERM | \ >+ LIBNDR_FLAG_STR_SIZE2 | \ >+ LIBNDR_FLAG_STR_BYTESIZE | \ >+ LIBNDR_FLAG_STR_CONFORMANT | \ >+ LIBNDR_FLAG_STR_CHARLEN | \ >+ LIBNDR_FLAG_STR_UTF8 | \ >+ LIBNDR_FLAG_STR_RAW8 | \ >+ 0) > > /* Disable string token compression */ > #define LIBNDR_FLAG_NO_COMPRESSION (1<<15) >-- >1.9.1 > > >From 04e12ede26abc6b9a738ddedc72878e11b06024f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 12 Jun 2017 17:58:20 +0200 >Subject: [PATCH 03/56] librpc/ndr: add LIBNDR_FLAG_IS_SECRET handling > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 32aa3a199dfd61eb5982e158008964b4747599b8) >--- > librpc/ndr/libndr.h | 10 ++++++++++ > librpc/ndr/ndr.c | 23 +++++++++++++++++++++++ > librpc/ndr/ndr_basic.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 77 insertions(+) > >diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h >index db13c05..38e4313 100644 >--- a/librpc/ndr/libndr.h >+++ b/librpc/ndr/libndr.h >@@ -108,6 +108,7 @@ struct ndr_print { > void (*print)(struct ndr_print *, const char *, ...) PRINTF_ATTRIBUTE(2,3); > void *private_data; > bool no_newline; >+ bool print_secrets; > }; > > #define LIBNDR_FLAG_BIGENDIAN (1<<0) >@@ -138,6 +139,12 @@ struct ndr_print { > LIBNDR_FLAG_STR_RAW8 | \ > 0) > >+/* >+ * Mark an element as SECRET, it won't be printed by >+ * via ndr_print* unless NDR_PRINT_SECRETS is specified. >+ */ >+#define LIBNDR_FLAG_IS_SECRET (1<<14) >+ > /* Disable string token compression */ > #define LIBNDR_FLAG_NO_COMPRESSION (1<<15) > >@@ -209,6 +216,9 @@ struct ndr_print { > #define NDR_PRINT_OUT_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_OUT, p) > #define NDR_PRINT_IN_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_IN | NDR_SET_VALUES, p) > >+#define NDR_HIDE_SECRET(ndr) \ >+ (unlikely(((ndr)->flags & LIBNDR_FLAG_IS_SECRET) && !(ndr)->print_secrets)) >+ > #define NDR_BE(ndr) (unlikely(((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)) > > enum ndr_err_code { >diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c >index 22c4d76..17e4def 100644 >--- a/librpc/ndr/ndr.c >+++ b/librpc/ndr/ndr.c >@@ -399,6 +399,12 @@ _PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *na > ndr->print = ndr_print_debugc_helper; > ndr->depth = 1; > ndr->flags = 0; >+#ifdef DEBUG_PASSWORD >+ if (CHECK_DEBUGLVL(100)) { >+ ndr->print_secrets = true; >+ } >+#endif >+ > fn(ndr, name, ptr); > talloc_free(ndr); > } >@@ -417,6 +423,12 @@ _PUBLIC_ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr) > ndr->print = ndr_print_debug_helper; > ndr->depth = 1; > ndr->flags = 0; >+#ifdef DEBUG_PASSWORD >+ if (CHECK_DEBUGLVL(100)) { >+ ndr->print_secrets = true; >+ } >+#endif >+ > fn(ndr, name, ptr); > talloc_free(ndr); > } >@@ -435,6 +447,12 @@ _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_ > ndr->print = ndr_print_debug_helper; > ndr->depth = 1; > ndr->flags = 0; >+#ifdef DEBUG_PASSWORD >+ if (CHECK_DEBUGLVL(100)) { >+ ndr->print_secrets = true; >+ } >+#endif >+ > ndr_print_set_switch_value(ndr, ptr, level); > fn(ndr, name, ptr); > talloc_free(ndr); >@@ -454,6 +472,11 @@ _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name > ndr->print = ndr_print_debug_helper; > ndr->depth = 1; > ndr->flags = 0; >+#ifdef DEBUG_PASSWORD >+ if (CHECK_DEBUGLVL(100)) { >+ ndr->print_secrets = true; >+ } >+#endif > > fn(ndr, name, flags, ptr); > talloc_free(ndr); >diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c >index b532cc5..c874f34 100644 >--- a/librpc/ndr/ndr_basic.c >+++ b/librpc/ndr/ndr_basic.c >@@ -1064,41 +1064,73 @@ _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const ch > > _PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: %d", name, v); > } > > _PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v); > } > > _PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: %d", name, v); > } > > _PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v); > } > > _PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: %d", name, v); > } > > _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v); > } > > _PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: %d", name, v); > } > > _PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v); > } > >@@ -1114,6 +1146,10 @@ _PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_ > > _PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name); >+ return; >+ } > ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v); > } > >@@ -1203,6 +1239,11 @@ _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, > return; > } > >+ if (NDR_HIDE_SECRET(ndr)) { >+ ndr->print(ndr, "%s: ARRAY(%d): <REDACTED SECRET VALUES>", name, count); >+ return; >+ } >+ > if (count <= _ONELINE_LIMIT && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) { > char s[(_ONELINE_LIMIT + 1) * 2]; > for (i=0;i<count;i++) { >@@ -1243,6 +1284,9 @@ static void ndr_print_dump_data_cb(const char *buf, void *private_data) > */ > static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len) > { >+ if (NDR_HIDE_SECRET(ndr)) { >+ return; >+ } > ndr->no_newline = true; > dump_data_cb(buf, len, true, ndr_print_dump_data_cb, ndr); > ndr->no_newline = false; >-- >1.9.1 > > >From 394b0e55f934fab673005c77a95266d8698d5f7f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 12 Jun 2017 17:58:46 +0200 >Subject: [PATCH 04/56] idl_types.h: add NDR_SECRET shortcut > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 969ab12c56cd12dcc0e63e9b662397c1604a0cc0) >--- > librpc/idl/idl_types.h | 6 ++++++ > 1 file changed, 6 insertions(+) > >diff --git a/librpc/idl/idl_types.h b/librpc/idl/idl_types.h >index 72a5d85..2d063de 100644 >--- a/librpc/idl/idl_types.h >+++ b/librpc/idl/idl_types.h >@@ -52,6 +52,12 @@ > */ > #define NDR_PAHEX LIBNDR_PRINT_ARRAY_HEX > >+/* >+ * Mark an element as SECRET, it won't be printed by >+ * via ndr_print* unless NDR_PRINT_SECRETS is specified. >+ */ >+#define NDR_SECRET LIBNDR_FLAG_IS_SECRET >+ > #define NDR_RELATIVE_REVERSE LIBNDR_FLAG_RELATIVE_REVERSE > #define NDR_NO_RELATIVE_REVERSE LIBNDR_FLAG_NO_RELATIVE_REVERSE > >-- >1.9.1 > > >From ecaa4c41acf7fba0436cf2dacee7672d1330ee6d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 15:05:51 +0200 >Subject: [PATCH 05/56] s3:librpc: let NDR_SECRETS depend on NDR_SECURITY > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 4260b52a399667bcdbaa375a20952237ff68449c) >--- > source3/librpc/wscript_build | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/librpc/wscript_build b/source3/librpc/wscript_build >index 2445859..1d8c17b 100644 >--- a/source3/librpc/wscript_build >+++ b/source3/librpc/wscript_build >@@ -27,7 +27,7 @@ bld.SAMBA3_SUBSYSTEM('NDR_LEASES_DB', > > bld.SAMBA3_SUBSYSTEM('NDR_SECRETS', > source='gen_ndr/ndr_secrets.c', >- public_deps='ndr' >+ public_deps='ndr NDR_SECURITY' > ) > > bld.SAMBA3_SUBSYSTEM('NDR_PERFCOUNT', >-- >1.9.1 > > >From 30f247badd7f6eaef0f3f092d58932a5561686f4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 16:13:37 +0200 >Subject: [PATCH 06/56] s3:libads: remove unused > kerberos_secrets_store_salting_principal() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit c56043a94a10c76a220ce3c7eb7cb8cf2e992cab) >--- > source3/libads/kerberos.c | 72 ----------------------------------------- > source3/libads/kerberos_proto.h | 3 -- > 2 files changed, 75 deletions(-) > >diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c >index 13c48ca..b4bd768 100644 >--- a/source3/libads/kerberos.c >+++ b/source3/libads/kerberos.c >@@ -434,78 +434,6 @@ int create_kerberos_key_from_string(krb5_context context, > } > > /************************************************************************ >- Routine to set the salting principal for this service. Active >- Directory may use a non-obvious principal name to generate the salt >- when it determines the key to use for encrypting tickets for a service, >- and hopefully we detected that when we joined the domain. >- Setting principal to NULL deletes this entry. >- ************************************************************************/ >- >-bool kerberos_secrets_store_salting_principal(const char *service, >- int enctype, >- const char *principal) >-{ >- char *key = NULL; >- bool ret = False; >- krb5_context context = NULL; >- krb5_principal princ = NULL; >- char *princ_s = NULL; >- char *unparsed_name = NULL; >- krb5_error_code code; >- >- if (((code = krb5_init_context(&context)) != 0) || (context == NULL)) { >- DEBUG(5, ("kerberos_secrets_store_salting_pricipal: kdb5_init_context failed: %s\n", >- error_message(code))); >- return False; >- } >- if (strchr_m(service, '@')) { >- if (asprintf(&princ_s, "%s", service) == -1) { >- goto out; >- } >- } else { >- if (asprintf(&princ_s, "%s@%s", service, lp_realm()) == -1) { >- goto out; >- } >- } >- >- if (smb_krb5_parse_name(context, princ_s, &princ) != 0) { >- goto out; >- } >- if (smb_krb5_unparse_name(talloc_tos(), context, princ, &unparsed_name) != 0) { >- goto out; >- } >- >- if (asprintf(&key, "%s/%s/enctype=%d", >- SECRETS_SALTING_PRINCIPAL, unparsed_name, enctype) >- == -1) { >- goto out; >- } >- >- if ((principal != NULL) && (strlen(principal) > 0)) { >- ret = secrets_store(key, principal, strlen(principal) + 1); >- } else { >- ret = secrets_delete(key); >- } >- >- out: >- >- SAFE_FREE(key); >- SAFE_FREE(princ_s); >- TALLOC_FREE(unparsed_name); >- >- if (princ) { >- krb5_free_principal(context, princ); >- } >- >- if (context) { >- krb5_free_context(context); >- } >- >- return ret; >-} >- >- >-/************************************************************************ > ************************************************************************/ > > int kerberos_kinit_password(const char *principal, >diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h >index 7c56672..8917d63 100644 >--- a/source3/libads/kerberos_proto.h >+++ b/source3/libads/kerberos_proto.h >@@ -62,9 +62,6 @@ char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, > const char *host_princ_s, > int enctype); > >-bool kerberos_secrets_store_salting_principal(const char *service, >- int enctype, >- const char *principal); > int kerberos_kinit_password(const char *principal, > const char *password, > int time_offset, >-- >1.9.1 > > >From 1d0a01070c0eb0570477b64c3a5f9b1343560c2b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 17:13:02 +0200 >Subject: [PATCH 07/56] krb5_wrap: add smb_krb5_salt_principal() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5df46700cfb0a15fec2d366e12728cd497188741) >--- > lib/krb5_wrap/krb5_samba.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ > lib/krb5_wrap/krb5_samba.h | 6 +++ > 2 files changed, 126 insertions(+) > >diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c >index 4fbc2e0..248195e 100644 >--- a/lib/krb5_wrap/krb5_samba.c >+++ b/lib/krb5_wrap/krb5_samba.c >@@ -422,6 +422,126 @@ int smb_krb5_get_pw_salt(krb5_context context, > #error UNKNOWN_SALT_FUNCTIONS > #endif > >+/** >+ * @brief This constructs the salt principal used by active directory >+ * >+ * Most Kerberos encryption types require a salt in order to >+ * calculate the long term private key for user/computer object >+ * based on a password. >+ * >+ * The returned _salt_principal is a string in forms like this: >+ * - host/somehost.example.com@EXAMPLE.COM >+ * - SomeAccount@EXAMPLE.COM >+ * - SomePrincipal@EXAMPLE.COM >+ * >+ * This is not the form that's used as salt, it's just >+ * the human readable form. >+ * >+ * @param[in] realm The realm the user/computer is added too. >+ * >+ * @param[in] sAMAccountName The sAMAccountName attribute of the object. >+ * >+ * @param[in] userPrincipalName The userPrincipalName attribute of the object >+ * or NULL is not available. >+ * >+ * @param[in] is_computer The indication of the object includes >+ * objectClass=computer. >+ * >+ * @param[in] mem_ctx The TALLOC_CTX to allocate _salt_principal. >+ * >+ * @param[out] _salt_principal The resulting principal as string. >+ * >+ * @retval 0 Success; otherwise - Kerberos error codes >+ */ >+int smb_krb5_salt_principal(const char *realm, >+ const char *sAMAccountName, >+ const char *userPrincipalName, >+ bool is_computer, >+ TALLOC_CTX *mem_ctx, >+ char **_salt_principal) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ char *upper_realm = NULL; >+ const char *principal = NULL; >+ int principal_len = 0; >+ >+ *_salt_principal = NULL; >+ >+ if (sAMAccountName == NULL) { >+ TALLOC_FREE(frame); >+ return EINVAL; >+ } >+ >+ if (realm == NULL) { >+ TALLOC_FREE(frame); >+ return EINVAL; >+ } >+ >+ upper_realm = strupper_talloc(frame, realm); >+ if (upper_realm == NULL) { >+ TALLOC_FREE(frame); >+ return ENOMEM; >+ } >+ >+ /* Many, many thanks to lukeh@padl.com for this >+ * algorithm, described in his Nov 10 2004 mail to >+ * samba-technical@lists.samba.org */ >+ >+ /* >+ * Determine a salting principal >+ */ >+ if (is_computer) { >+ int computer_len = 0; >+ char *tmp = NULL; >+ >+ computer_len = strlen(sAMAccountName); >+ if (sAMAccountName[computer_len-1] == '$') { >+ computer_len -= 1; >+ } >+ >+ tmp = talloc_asprintf(frame, "host/%*.*s.%s", >+ computer_len, computer_len, >+ sAMAccountName, realm); >+ if (tmp == NULL) { >+ TALLOC_FREE(frame); >+ return ENOMEM; >+ } >+ >+ principal = strlower_talloc(frame, tmp); >+ TALLOC_FREE(tmp); >+ if (principal == NULL) { >+ TALLOC_FREE(frame); >+ return ENOMEM; >+ } >+ principal_len = strlen(principal); >+ >+ } else if (userPrincipalName != NULL) { >+ char *p; >+ >+ principal = userPrincipalName; >+ p = strchr(principal, '@'); >+ if (p != NULL) { >+ principal_len = PTR_DIFF(p, principal); >+ } else { >+ principal_len = strlen(principal); >+ } >+ } else { >+ principal = sAMAccountName; >+ principal_len = strlen(principal); >+ } >+ >+ *_salt_principal = talloc_asprintf(mem_ctx, "%*.*s@%s", >+ principal_len, principal_len, >+ principal, upper_realm); >+ if (*_salt_principal == NULL) { >+ TALLOC_FREE(frame); >+ return ENOMEM; >+ } >+ >+ TALLOC_FREE(frame); >+ return 0; >+} >+ > #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES) > /** > * @brief Get a list of encryption types allowed for session keys >diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h >index c921538..cdd3dc4 100644 >--- a/lib/krb5_wrap/krb5_samba.h >+++ b/lib/krb5_wrap/krb5_samba.h >@@ -352,6 +352,12 @@ krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx, > int smb_krb5_get_pw_salt(krb5_context context, > krb5_const_principal host_princ, > krb5_data *psalt); >+int smb_krb5_salt_principal(const char *realm, >+ const char *sAMAccountName, >+ const char *userPrincipalName, >+ bool is_computer, >+ TALLOC_CTX *mem_ctx, >+ char **_salt_principal); > > int smb_krb5_create_key_from_string(krb5_context context, > krb5_const_principal host_princ, >-- >1.9.1 > > >From e3ad4badd54e1229c4bb7352d52ff0b5446b50e8 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 11:32:46 +0200 >Subject: [PATCH 08/56] krb5_wrap: add smb_krb5_salt_principal2data() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit ec2da944d304852d76137e8f9d234462bc807c6b) >--- > lib/krb5_wrap/krb5_samba.c | 69 +++++++++++++++++++++++++++++++++++++++++++++- > lib/krb5_wrap/krb5_samba.h | 4 +++ > 2 files changed, 72 insertions(+), 1 deletion(-) > >diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c >index 248195e..6a863bd 100644 >--- a/lib/krb5_wrap/krb5_samba.c >+++ b/lib/krb5_wrap/krb5_samba.c >@@ -435,7 +435,8 @@ int smb_krb5_get_pw_salt(krb5_context context, > * - SomePrincipal@EXAMPLE.COM > * > * This is not the form that's used as salt, it's just >- * the human readable form. >+ * the human readable form. It needs to be converted by >+ * smb_krb5_salt_principal2data(). > * > * @param[in] realm The realm the user/computer is added too. > * >@@ -452,6 +453,8 @@ int smb_krb5_get_pw_salt(krb5_context context, > * @param[out] _salt_principal The resulting principal as string. > * > * @retval 0 Success; otherwise - Kerberos error codes >+ * >+ * @see smb_krb5_salt_principal2data > */ > int smb_krb5_salt_principal(const char *realm, > const char *sAMAccountName, >@@ -542,6 +545,70 @@ int smb_krb5_salt_principal(const char *realm, > return 0; > } > >+/** >+ * @brief Converts the salt principal string into the salt data blob >+ * >+ * This function takes a salt_principal as string in forms like this: >+ * - host/somehost.example.com@EXAMPLE.COM >+ * - SomeAccount@EXAMPLE.COM >+ * - SomePrincipal@EXAMPLE.COM >+ * >+ * It generates values like: >+ * - EXAMPLE.COMhost/somehost.example.com >+ * - EXAMPLE.COMSomeAccount >+ * - EXAMPLE.COMSomePrincipal >+ * >+ * @param[in] realm The realm the user/computer is added too. >+ * >+ * @param[in] sAMAccountName The sAMAccountName attribute of the object. >+ * >+ * @param[in] userPrincipalName The userPrincipalName attribute of the object >+ * or NULL is not available. >+ * >+ * @param[in] is_computer The indication of the object includes >+ * objectClass=computer. >+ * >+ * @param[in] mem_ctx The TALLOC_CTX to allocate _salt_principal. >+ * >+ * @param[out] _salt_principal The resulting principal as string. >+ * >+ * @retval 0 Success; otherwise - Kerberos error codes >+ * >+ * @see smb_krb5_salt_principal >+ */ >+int smb_krb5_salt_principal2data(krb5_context context, >+ const char *salt_principal, >+ TALLOC_CTX *mem_ctx, >+ char **_salt_data) >+{ >+ krb5_error_code ret; >+ krb5_principal salt_princ = NULL; >+ krb5_data salt; >+ >+ *_salt_data = NULL; >+ >+ ret = krb5_parse_name(context, salt_principal, &salt_princ); >+ if (ret != 0) { >+ return ret; >+ } >+ >+ ret = smb_krb5_get_pw_salt(context, salt_princ, &salt); >+ krb5_free_principal(context, salt_princ); >+ if (ret != 0) { >+ return ret; >+ } >+ >+ *_salt_data = talloc_strndup(mem_ctx, >+ (char *)salt.data, >+ salt.length); >+ smb_krb5_free_data_contents(context, &salt); >+ if (*_salt_data == NULL) { >+ return ENOMEM; >+ } >+ >+ return 0; >+} >+ > #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES) > /** > * @brief Get a list of encryption types allowed for session keys >diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h >index cdd3dc4..5834629 100644 >--- a/lib/krb5_wrap/krb5_samba.h >+++ b/lib/krb5_wrap/krb5_samba.h >@@ -358,6 +358,10 @@ int smb_krb5_salt_principal(const char *realm, > bool is_computer, > TALLOC_CTX *mem_ctx, > char **_salt_principal); >+int smb_krb5_salt_principal2data(krb5_context context, >+ const char *salt_principal, >+ TALLOC_CTX *mem_ctx, >+ char **_salt_data); > > int smb_krb5_create_key_from_string(krb5_context context, > krb5_const_principal host_princ, >-- >1.9.1 > > >From 3fc47c39b6bc511172590d88ab62b94a86d21315 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 12:42:04 +0200 >Subject: [PATCH 09/56] s3:libnet_join: remove dead code from > libnet_join_connect_ads() > >username[strlen(username)] is *always* '\0'! > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5958c6790fbceb39065353c07fe25f74ddf09ef0) >--- > source3/libnet/libnet_join.c | 9 ++------- > 1 file changed, 2 insertions(+), 7 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 4d00ef6..e33c383 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -195,16 +195,11 @@ static ADS_STATUS libnet_join_connect_ads(TALLOC_CTX *mem_ctx, > r->in.machine_password == NULL) { > return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); > } >- username = talloc_strdup(mem_ctx, r->in.machine_name); >+ username = talloc_asprintf(mem_ctx, "%s$", >+ r->in.machine_name); > if (username == NULL) { > return ADS_ERROR(LDAP_NO_MEMORY); > } >- if (username[strlen(username)] != '$') { >- username = talloc_asprintf(username, "%s$", username); >- if (username == NULL) { >- return ADS_ERROR(LDAP_NO_MEMORY); >- } >- } > password = r->in.machine_password; > ccname = "MEMORY:libnet_join_machine_creds"; > } else { >-- >1.9.1 > > >From fbf17af91e78bf5948772d6060dc1ad11ced4f34 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 13:53:19 +0200 >Subject: [PATCH 10/56] s3:libnet_join: calculate r->out.account_name in > libnet_join_pre_processing() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 826223cc8d36871c2bcb37fe23241f1dbe99a0db) >--- > source3/libnet/libnet_join.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index e33c383..1e290d7 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -1122,7 +1122,6 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, > struct rpc_pipe_client *netlogon_pipe = NULL; > struct netlogon_creds_cli_context *netlogon_creds = NULL; > struct samr_Password current_nt_hash; >- const char *account_name = NULL; > NTSTATUS status; > > status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, >@@ -1147,16 +1146,9 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, > /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */ > E_md4hash(r->in.admin_password, current_nt_hash.hash); > >- account_name = talloc_asprintf(frame, "%s$", >- r->in.machine_name); >- if (account_name == NULL) { >- TALLOC_FREE(frame); >- return NT_STATUS_NO_MEMORY; >- } >- > status = rpccli_create_netlogon_creds(netlogon_pipe->desthost, > r->in.domain_name, >- account_name, >+ r->out.account_name, > r->in.secure_channel_type, > r->in.msg_ctx, > frame, >@@ -2111,6 +2103,14 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, > return WERR_INVALID_PARAMETER; > } > >+ r->out.account_name = talloc_asprintf(mem_ctx, "%s$", >+ r->in.machine_name); >+ if (r->out.account_name == NULL) { >+ libnet_join_set_error_string(mem_ctx, r, >+ "Unable to construct r->out.account_name"); >+ return WERR_NOT_ENOUGH_MEMORY; >+ } >+ > if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name, > &r->in.domain_name, > &r->in.dc_name)) { >-- >1.9.1 > > >From 01a2e4f8bfb2a7fdc7be6937a204b3e9ef2994b6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 15:45:22 +0200 >Subject: [PATCH 11/56] s3:libnet_join.idl: return the domain_guid in > libnet_JoinCtx > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 03e455f5a815ce2134e216dc28929646a964384f) >--- > source3/librpc/idl/libnet_join.idl | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl >index 63ea1df..fc7b66c 100644 >--- a/source3/librpc/idl/libnet_join.idl >+++ b/source3/librpc/idl/libnet_join.idl >@@ -49,6 +49,7 @@ interface libnetjoin > [out] string dns_domain_name, > [out] string forest_name, > [out] string dn, >+ [out] GUID domain_guid, > [out] dom_sid *domain_sid, > [out] boolean8 modified_config, > [out] string error_string, >-- >1.9.1 > > >From aac1fee1a290a4cafde46d51be15c2e62ee6f4d2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 15:45:22 +0200 >Subject: [PATCH 12/56] s3:libnet_join: remember the domain_guid for AD domains > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit fc2bad0cf34fca5e65fba7e036acf1d8c61f05c0) >--- > source3/libnet/libnet_join.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 1e290d7..37645a7 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -1080,6 +1080,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, > r->out.netbios_domain_name = info->dns.name.string; > r->out.dns_domain_name = info->dns.dns_domain.string; > r->out.forest_name = info->dns.dns_forest.string; >+ r->out.domain_guid = info->dns.domain_guid; > r->out.domain_sid = dom_sid_dup(mem_ctx, info->dns.sid); > NT_STATUS_HAVE_NO_MEMORY(r->out.domain_sid); > } >-- >1.9.1 > > >From b38f07eafe19b3f6f24be921bb29eac9952918f9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:38:26 +0200 >Subject: [PATCH 13/56] s3:libnet_join.idl: add krb5_salt to libnet_JoinCtx > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 3b13e4d2d0f73c6374ffdae57528cd1a7f333792) >--- > source3/librpc/idl/libnet_join.idl | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl >index fc7b66c..e45034d 100644 >--- a/source3/librpc/idl/libnet_join.idl >+++ b/source3/librpc/idl/libnet_join.idl >@@ -54,7 +54,8 @@ interface libnetjoin > [out] boolean8 modified_config, > [out] string error_string, > [out] boolean8 domain_is_ad, >- [out] uint32 set_encryption_types >+ [out] uint32 set_encryption_types, >+ [out] string krb5_salt > ); > > [nopush,nopull,noopnum] WERROR libnet_UnjoinCtx( >-- >1.9.1 > > >From 18c678f58287f5d798cae47da090ca40efc34541 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:40:25 +0200 >Subject: [PATCH 14/56] s3:libnet_join: remember r->out.krb5_salt in > libnet_join_derive_salting_principal() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 549c9d9a07d3002442cbbb7a90d0a7fef4a92bff) >--- > source3/libnet/libnet_join.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 37645a7..a5e863a 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -864,6 +864,7 @@ static bool libnet_join_derive_salting_principal(TALLOC_CTX *mem_ctx, > } > } > >+ r->out.krb5_salt = salt; > return kerberos_secrets_store_des_salt(salt); > } > >-- >1.9.1 > > >From 08a33963ae7f643b541f14ff8df08f91a343cc0e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:48:49 +0200 >Subject: [PATCH 15/56] s3:libnet_join: move kerberos_secrets_store_des_salt() > out of libnet_join_derive_salting_principal() > >We should separate the calculation and the storing steps. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 0c65d5f41023076fd201c3a179df77dd615cdb01) >--- > source3/libnet/libnet_join.c | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index a5e863a..780c26c 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -865,7 +865,7 @@ static bool libnet_join_derive_salting_principal(TALLOC_CTX *mem_ctx, > } > > r->out.krb5_salt = salt; >- return kerberos_secrets_store_des_salt(salt); >+ return true; > } > > /**************************************************************** >@@ -964,6 +964,17 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, > return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); > } > >+ if (r->out.krb5_salt != NULL) { >+ bool ok; >+ >+ ok = kerberos_secrets_store_des_salt(r->out.krb5_salt); >+ if (!ok) { >+ libnet_join_set_error_string(mem_ctx, r, >+ "failed to store krb5_salt"); >+ return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); >+ } >+ } >+ > if (!libnet_join_create_keytab(mem_ctx, r)) { > libnet_join_set_error_string(mem_ctx, r, > "failed to create kerberos keytab"); >-- >1.9.1 > > >From 47aa094b64593043e1030ccc58a1028fdbb66f2d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:50:49 +0200 >Subject: [PATCH 16/56] s3:libnet_join: split libnet_join_post_processing_ads() > into modify/sync > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 0ab7944a2b00df4aa155a239c86f97e4e731b864) >--- > source3/libnet/libnet_join.c | 24 +++++++++++++++++++++--- > 1 file changed, 21 insertions(+), 3 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 780c26c..7493ac8 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -871,8 +871,8 @@ static bool libnet_join_derive_salting_principal(TALLOC_CTX *mem_ctx, > /**************************************************************** > ****************************************************************/ > >-static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, >- struct libnet_JoinCtx *r) >+static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx, >+ struct libnet_JoinCtx *r) > { > ADS_STATUS status; > bool need_etype_update = false; >@@ -964,6 +964,12 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, > return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); > } > >+ return ADS_SUCCESS; >+} >+ >+static ADS_STATUS libnet_join_post_processing_ads_sync(TALLOC_CTX *mem_ctx, >+ struct libnet_JoinCtx *r) >+{ > if (r->out.krb5_salt != NULL) { > bool ok; > >@@ -2214,6 +2220,18 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, > return WERR_OK; > } > >+#ifdef HAVE_ADS >+ if (r->out.domain_is_ad && >+ !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) { >+ ADS_STATUS ads_status; >+ >+ ads_status = libnet_join_post_processing_ads_modify(mem_ctx, r); >+ if (!ADS_ERR_OK(ads_status)) { >+ return WERR_GEN_FAILURE; >+ } >+ } >+#endif /* HAVE_ADS */ >+ > saf_join_store(r->out.netbios_domain_name, r->in.dc_name); > if (r->out.dns_domain_name) { > saf_join_store(r->out.dns_domain_name, r->in.dc_name); >@@ -2224,7 +2242,7 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, > !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) { > ADS_STATUS ads_status; > >- ads_status = libnet_join_post_processing_ads(mem_ctx, r); >+ ads_status = libnet_join_post_processing_ads_sync(mem_ctx, r); > if (!ADS_ERR_OK(ads_status)) { > return WERR_GEN_FAILURE; > } >-- >1.9.1 > > >From a733fdfb58cd4837e61eb534b3c0500696441d6c Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:52:59 +0200 >Subject: [PATCH 17/56] s3:libnet_join: call do_JoinConfig() after we did > remote changes on the server > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 559de1e7236fd4a38f2a1f9980216db95d0430ce) >--- > source3/libnet/libnet_join.c | 15 ++++++++++----- > 1 file changed, 10 insertions(+), 5 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 7493ac8..5e4a0d3 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -2211,12 +2211,12 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, > return r->out.result; > } > >- werr = do_JoinConfig(r); >- if (!W_ERROR_IS_OK(werr)) { >- return werr; >- } >- > if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) { >+ werr = do_JoinConfig(r); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ > return WERR_OK; > } > >@@ -2237,6 +2237,11 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, > saf_join_store(r->out.dns_domain_name, r->in.dc_name); > } > >+ werr = do_JoinConfig(r); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ > #ifdef HAVE_ADS > if (r->out.domain_is_ad && > !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) { >-- >1.9.1 > > >From 37c13c960b2a0d1c15b28ecc7824dfe72670c11c Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 15:59:00 +0200 >Subject: [PATCH 18/56] s3:libnet_join: move > libnet_join_joindomain_store_secrets() to libnet_join_post_processing() > >We should not store the secrets before we did all remote changes >(except the optional dns updates). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit a922e01baeccedc3ffc8a893f1d6072bb203220f) >--- > source3/libnet/libnet_join.c | 9 ++++----- > 1 file changed, 4 insertions(+), 5 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 5e4a0d3..56bddf5 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -2237,6 +2237,10 @@ static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx, > saf_join_store(r->out.dns_domain_name, r->in.dc_name); > } > >+ if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) { >+ return WERR_NERR_SETUPNOTJOINED; >+ } >+ > werr = do_JoinConfig(r); > if (!W_ERROR_IS_OK(werr)) { > return werr; >@@ -2628,11 +2632,6 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx, > goto done; > } > >- if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) { >- werr = WERR_NERR_SETUPNOTJOINED; >- goto done; >- } >- > werr = WERR_OK; > > done: >-- >1.9.1 > > >From 7c523616bf951fe4f6eb2050619825e0acd42bab Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 18 May 2017 16:02:44 +0200 >Subject: [PATCH 19/56] s3:libnet_join: move kerberos_secrets_store_des_salt() > to libnet_join_joindomain_store_secrets() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 7d2eea39112fd69d2b710181b23301562efea387) >--- > source3/libnet/libnet_join.c | 21 ++++++++++----------- > 1 file changed, 10 insertions(+), 11 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 56bddf5..7669c2e 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -970,17 +970,6 @@ static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx, > static ADS_STATUS libnet_join_post_processing_ads_sync(TALLOC_CTX *mem_ctx, > struct libnet_JoinCtx *r) > { >- if (r->out.krb5_salt != NULL) { >- bool ok; >- >- ok = kerberos_secrets_store_des_salt(r->out.krb5_salt); >- if (!ok) { >- libnet_join_set_error_string(mem_ctx, r, >- "failed to store krb5_salt"); >- return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); >- } >- } >- > if (!libnet_join_create_keytab(mem_ctx, r)) { > libnet_join_set_error_string(mem_ctx, r, > "failed to create kerberos keytab"); >@@ -1013,6 +1002,16 @@ static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx, > return false; > } > >+ if (r->out.krb5_salt != NULL) { >+ bool ok; >+ >+ ok = kerberos_secrets_store_des_salt(r->out.krb5_salt); >+ if (!ok) { >+ DEBUG(1,("Failed to save krb5 salt\n")); >+ return false; >+ } >+ } >+ > return true; > } > >-- >1.9.1 > > >From a9e2b143921844fb53636a896070857858688b47 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 16:01:55 +0200 >Subject: [PATCH 20/56] s3:libads: remove > kerberos_secrets_fetch_salting_principal() fallback > >The handling for per encryption type salts was removed in >Samba 3.0.23a (Jul 21, 2006). It's very unlikely that someone >has such an installation that got constantly upgraded over 10 years >with an automatic password change nor rejoin. It also means >that the KDC only has salt-less arcfour-hmac-md5 key together >with the salted des keys. So there would only be a problem >if the client whould try to use a des key to contact the smb server. > >Having this legacy code adds quite some complexity for no >good reason. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 487b4717b58a6f1ba913708ce8419145b7f4fac8) >--- > source3/libads/kerberos.c | 37 ++++--------------------------------- > 1 file changed, 4 insertions(+), 33 deletions(-) > >diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c >index b4bd768..ba2311b 100644 >--- a/source3/libads/kerberos.c >+++ b/source3/libads/kerberos.c >@@ -273,27 +273,6 @@ int ads_kdestroy(const char *cc_name) > } > > /************************************************************************ >- Routine to fetch the salting principal for a service. Active >- Directory may use a non-obvious principal name to generate the salt >- when it determines the key to use for encrypting tickets for a service, >- and hopefully we detected that when we joined the domain. >- ************************************************************************/ >- >-static char *kerberos_secrets_fetch_salting_principal(const char *service, int enctype) >-{ >- char *key = NULL; >- char *ret = NULL; >- >- if (asprintf(&key, "%s/%s/enctype=%d", >- SECRETS_SALTING_PRINCIPAL, service, enctype) == -1) { >- return NULL; >- } >- ret = (char *)secrets_fetch(key, NULL); >- SAFE_FREE(key); >- return ret; >-} >- >-/************************************************************************ > Return the standard DES salt key > ************************************************************************/ > >@@ -372,10 +351,8 @@ char* kerberos_secrets_fetch_des_salt( void ) > } > > /************************************************************************ >- Routine to get the salting principal for this service. This is >- maintained for backwards compatibilty with releases prior to 3.0.24. >- Since we store the salting principal string only at join, we may have >- to look for the older tdb keys. Caller must free if return is not null. >+ Routine to get the salting principal for this service. >+ Caller must free if return is not null. > ************************************************************************/ > > char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, >@@ -387,14 +364,8 @@ char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, > > salt_princ_s = kerberos_secrets_fetch_des_salt(); > if (salt_princ_s == NULL) { >- >- /* look under the old key. If this fails, just use the standard key */ >- salt_princ_s = kerberos_secrets_fetch_salting_principal(host_princ_s, >- enctype); >- if (salt_princ_s == NULL) { >- /* fall back to host/machine.realm@REALM */ >- salt_princ_s = kerberos_standard_des_salt(); >- } >+ /* fall back to host/machine.realm@REALM */ >+ salt_princ_s = kerberos_standard_des_salt(); > } > > return salt_princ_s; >-- >1.9.1 > > >From a33ca7f2433e8b9d1f8ccdf69e7b54f842c4b9ba Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 16:15:34 +0200 >Subject: [PATCH 21/56] s3:libads: provide a simpler > kerberos_fetch_salt_princ() function > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5fe939e32cdaf7bb5b6dac67e7b0118ce65846be) >--- > source3/libads/kerberos.c | 11 ++++++++--- > source3/libads/kerberos_proto.h | 1 + > 2 files changed, 9 insertions(+), 3 deletions(-) > >diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c >index ba2311b..a307286 100644 >--- a/source3/libads/kerberos.c >+++ b/source3/libads/kerberos.c >@@ -355,9 +355,7 @@ char* kerberos_secrets_fetch_des_salt( void ) > Caller must free if return is not null. > ************************************************************************/ > >-char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, >- const char *host_princ_s, >- int enctype) >+char *kerberos_secrets_fetch_salt_princ(void) > { > char *salt_princ_s; > /* lookup new key first */ >@@ -371,6 +369,13 @@ char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, > return salt_princ_s; > } > >+char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, >+ const char *host_princ_s, >+ int enctype) >+{ >+ return kerberos_secrets_fetch_salt_princ(); >+} >+ > int create_kerberos_key_from_string(krb5_context context, > krb5_principal host_princ, > krb5_principal salt_princ, >diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h >index 8917d63..6a6e269 100644 >--- a/source3/libads/kerberos_proto.h >+++ b/source3/libads/kerberos_proto.h >@@ -61,6 +61,7 @@ bool kerberos_secrets_store_des_salt( const char* salt ); > char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, > const char *host_princ_s, > int enctype); >+char *kerberos_secrets_fetch_salt_princ(void); > > int kerberos_kinit_password(const char *principal, > const char *password, >-- >1.9.1 > > >From 32dfedd9713860801d94b75b9415b46f5fcc54df Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 16:28:42 +0200 >Subject: [PATCH 22/56] s3:gse_krb5: simplify fill_keytab_from_password() by > using kerberos_fetch_salt_princ() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 1d1cf9792f9227e65857c85ff66a961331e3c16e) >--- > source3/librpc/crypto/gse_krb5.c | 40 ++++++++++++++-------------------------- > 1 file changed, 14 insertions(+), 26 deletions(-) > >diff --git a/source3/librpc/crypto/gse_krb5.c b/source3/librpc/crypto/gse_krb5.c >index 4dd39ea..2c9fc03 100644 >--- a/source3/librpc/crypto/gse_krb5.c >+++ b/source3/librpc/crypto/gse_krb5.c >@@ -122,6 +122,8 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx, > krb5_enctype *enctypes; > krb5_keytab_entry kt_entry; > unsigned int i; >+ krb5_principal salt_princ = NULL; >+ char *salt_princ_s = NULL; > > ret = smb_krb5_get_allowed_etypes(krbctx, &enctypes); > if (ret) { >@@ -130,11 +132,19 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx, > return ret; > } > >+ salt_princ_s = kerberos_secrets_fetch_salt_princ(); >+ if (salt_princ_s == NULL) { >+ ret = ENOMEM; >+ goto out; >+ } >+ ret = krb5_parse_name(krbctx, salt_princ_s, &salt_princ); >+ SAFE_FREE(salt_princ_s); >+ if (ret != 0) { >+ goto out; >+ } >+ > for (i = 0; enctypes[i]; i++) { > krb5_keyblock *key = NULL; >- krb5_principal salt_princ = NULL; >- char *salt_princ_s; >- char *princ_s; > int rc; > > if (!(key = SMB_MALLOC_P(krb5_keyblock))) { >@@ -142,28 +152,6 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx, > goto out; > } > >- ret = krb5_unparse_name(krbctx, princ, &princ_s); >- if (ret != 0) { >- SAFE_FREE(key); >- continue; >- } >- >- salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(krbctx, >- princ_s, >- enctypes[i]); >- SAFE_FREE(princ_s); >- if (salt_princ_s == NULL) { >- SAFE_FREE(key); >- continue; >- } >- >- ret = krb5_parse_name(krbctx, salt_princ_s, &salt_princ); >- SAFE_FREE(salt_princ_s); >- if (ret != 0) { >- SAFE_FREE(key); >- continue; >- } >- > rc = create_kerberos_key_from_string(krbctx, > princ, > salt_princ, >@@ -171,7 +159,6 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx, > key, > enctypes[i], > false); >- krb5_free_principal(krbctx, salt_princ); > if (rc != 0) { > DEBUG(10, ("Failed to create key for enctype %d " > "(error: %s)\n", >@@ -199,6 +186,7 @@ static krb5_error_code fill_keytab_from_password(krb5_context krbctx, > ret = 0; > > out: >+ krb5_free_principal(krbctx, salt_princ); > SAFE_FREE(enctypes); > return ret; > } >-- >1.9.1 > > >From c8add71e81dd1ce06c3c9c88751ec6ad9b2bb896 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 17:04:36 +0200 >Subject: [PATCH 23/56] s3:libnet: make use of > kerberos_secrets_fetch_salt_princ() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 51ae7b42d4d52016b39b79447a3e28d473e676cb) >--- > source3/libnet/libnet_keytab.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > >diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c >index 9aefac1..1b5ac67 100644 >--- a/source3/libnet/libnet_keytab.c >+++ b/source3/libnet/libnet_keytab.c >@@ -241,9 +241,7 @@ static krb5_error_code libnet_keytab_add_entry(krb5_context context, > > keyp = KRB5_KT_KEY(&kt_entry); > >- salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(context, >- princ_s, >- enctype); >+ salt_princ_s = kerberos_secrets_fetch_salt_princ(); > if (salt_princ_s == NULL) { > ret = KRB5KRB_ERR_GENERIC; > goto done; >-- >1.9.1 > > >From e63338206189cea1930258eaa4db0c263fbad138 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 17:08:24 +0200 >Subject: [PATCH 24/56] s3:libads: make use of > kerberos_secrets_fetch_salt_princ() in ads_keytab_add_entry() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit b0928a2687a9ffe92ebdce7b5252781d62e7e02d) >--- > source3/libads/kerberos_keytab.c | 14 ++++++++------ > 1 file changed, 8 insertions(+), 6 deletions(-) > >diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c >index 96df10f..ff12ec0 100644 >--- a/source3/libads/kerberos_keytab.c >+++ b/source3/libads/kerberos_keytab.c >@@ -237,10 +237,14 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc) > goto out; > } > >+ salt_princ_s = kerberos_secrets_fetch_salt_princ(); >+ if (salt_princ_s == NULL) { >+ DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n"); >+ ret = -1; >+ goto out; >+ } >+ > for (i = 0; enctypes[i]; i++) { >- salt_princ_s = kerberos_fetch_salt_princ_for_host_princ(context, >- princ_s, >- enctypes[i]); > > /* add the fqdn principal to the keytab */ > ret = smb_krb5_kt_add_entry(context, >@@ -254,7 +258,6 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc) > false); > if (ret) { > DEBUG(1, (__location__ ": Failed to add entry to keytab\n")); >- SAFE_FREE(salt_princ_s); > goto out; > } > >@@ -272,14 +275,13 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc) > if (ret) { > DEBUG(1, (__location__ > ": Failed to add short entry to keytab\n")); >- SAFE_FREE(salt_princ_s); > goto out; > } > } >- SAFE_FREE(salt_princ_s); > } > > out: >+ SAFE_FREE(salt_princ_s); > TALLOC_FREE(tmpctx); > > if (keytab) { >-- >1.9.1 > > >From e481c5897e8e14fe5ff4d8fa3dd4a139db41de8f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 17:09:20 +0200 >Subject: [PATCH 25/56] s3:libads: remove unused > kerberos_fetch_salt_princ_for_host_princ() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 1a26805ad9f19f02a52d9eaa4f2f11ff20ee76ac) >--- > source3/libads/kerberos.c | 7 ------- > source3/libads/kerberos_proto.h | 3 --- > 2 files changed, 10 deletions(-) > >diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c >index a307286..6cfbca6 100644 >--- a/source3/libads/kerberos.c >+++ b/source3/libads/kerberos.c >@@ -369,13 +369,6 @@ char *kerberos_secrets_fetch_salt_princ(void) > return salt_princ_s; > } > >-char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, >- const char *host_princ_s, >- int enctype) >-{ >- return kerberos_secrets_fetch_salt_princ(); >-} >- > int create_kerberos_key_from_string(krb5_context context, > krb5_principal host_princ, > krb5_principal salt_princ, >diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h >index 6a6e269..e481d1d 100644 >--- a/source3/libads/kerberos_proto.h >+++ b/source3/libads/kerberos_proto.h >@@ -58,9 +58,6 @@ int kerberos_kinit_password_ext(const char *principal, > int ads_kdestroy(const char *cc_name); > char* kerberos_standard_des_salt( void ); > bool kerberos_secrets_store_des_salt( const char* salt ); >-char *kerberos_fetch_salt_princ_for_host_princ(krb5_context context, >- const char *host_princ_s, >- int enctype); > char *kerberos_secrets_fetch_salt_princ(void); > > int kerberos_kinit_password(const char *principal, >-- >1.9.1 > > >From ab49425ace50dea520b3a66c7014378ce36bc7c9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 17:17:00 +0200 >Subject: [PATCH 26/56] s3:secrets: move kerberos_secrets_*salt related > functions to machine_account_secrets.c > >These don't use any krb5_context related functions and they just >work on secrets.tdb, so they really belong to machine_account_secrets.c. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 504b446d8dc7410ad63eba9d214e9cf271cf3b2f) >--- > source3/include/secrets.h | 4 ++ > source3/libads/kerberos.c | 97 -------------------------------- > source3/libads/kerberos_proto.h | 3 - > source3/libnet/libnet_keytab.c | 1 + > source3/passdb/machine_account_secrets.c | 96 +++++++++++++++++++++++++++++++ > 5 files changed, 101 insertions(+), 100 deletions(-) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index f397129..c40a951 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -133,6 +133,10 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > uint32_t secure_channel, > bool delete_join); > >+char* kerberos_standard_des_salt( void ); >+bool kerberos_secrets_store_des_salt( const char* salt ); >+char *kerberos_secrets_fetch_salt_princ(void); >+ > /* The following definitions come from passdb/secrets_lsa.c */ > NTSTATUS lsa_secret_get(TALLOC_CTX *mem_ctx, > const char *secret_name, >diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c >index 6cfbca6..cfb09a7 100644 >--- a/source3/libads/kerberos.c >+++ b/source3/libads/kerberos.c >@@ -272,103 +272,6 @@ int ads_kdestroy(const char *cc_name) > return code; > } > >-/************************************************************************ >- Return the standard DES salt key >-************************************************************************/ >- >-char* kerberos_standard_des_salt( void ) >-{ >- fstring salt; >- >- fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() ); >- (void)strlower_m( salt ); >- fstrcat( salt, lp_realm() ); >- >- return SMB_STRDUP( salt ); >-} >- >-/************************************************************************ >-************************************************************************/ >- >-static char* des_salt_key( void ) >-{ >- char *key; >- >- if (asprintf(&key, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, >- lp_realm()) == -1) { >- return NULL; >- } >- >- return key; >-} >- >-/************************************************************************ >-************************************************************************/ >- >-bool kerberos_secrets_store_des_salt( const char* salt ) >-{ >- char* key; >- bool ret; >- >- if ( (key = des_salt_key()) == NULL ) { >- DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n")); >- return False; >- } >- >- if ( !salt ) { >- DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n")); >- secrets_delete( key ); >- return True; >- } >- >- DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt)); >- >- ret = secrets_store( key, salt, strlen(salt)+1 ); >- >- SAFE_FREE( key ); >- >- return ret; >-} >- >-/************************************************************************ >-************************************************************************/ >- >-static >-char* kerberos_secrets_fetch_des_salt( void ) >-{ >- char *salt, *key; >- >- if ( (key = des_salt_key()) == NULL ) { >- DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n")); >- return NULL; >- } >- >- salt = (char*)secrets_fetch( key, NULL ); >- >- SAFE_FREE( key ); >- >- return salt; >-} >- >-/************************************************************************ >- Routine to get the salting principal for this service. >- Caller must free if return is not null. >- ************************************************************************/ >- >-char *kerberos_secrets_fetch_salt_princ(void) >-{ >- char *salt_princ_s; >- /* lookup new key first */ >- >- salt_princ_s = kerberos_secrets_fetch_des_salt(); >- if (salt_princ_s == NULL) { >- /* fall back to host/machine.realm@REALM */ >- salt_princ_s = kerberos_standard_des_salt(); >- } >- >- return salt_princ_s; >-} >- > int create_kerberos_key_from_string(krb5_context context, > krb5_principal host_princ, > krb5_principal salt_princ, >diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h >index e481d1d..f92cabd 100644 >--- a/source3/libads/kerberos_proto.h >+++ b/source3/libads/kerberos_proto.h >@@ -56,9 +56,6 @@ int kerberos_kinit_password_ext(const char *principal, > time_t renewable_time, > NTSTATUS *ntstatus); > int ads_kdestroy(const char *cc_name); >-char* kerberos_standard_des_salt( void ); >-bool kerberos_secrets_store_des_salt( const char* salt ); >-char *kerberos_secrets_fetch_salt_princ(void); > > int kerberos_kinit_password(const char *principal, > const char *password, >diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c >index 1b5ac67..c76e7b2 100644 >--- a/source3/libnet/libnet_keytab.c >+++ b/source3/libnet/libnet_keytab.c >@@ -22,6 +22,7 @@ > #include "includes.h" > #include "smb_krb5.h" > #include "ads.h" >+#include "secrets.h" > #include "libnet/libnet_keytab.h" > > #ifdef HAVE_KRB5 >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 3f097ab..3f6d6b6 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -553,6 +553,102 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > return ret; > } > >+/************************************************************************ >+ Return the standard DES salt key >+************************************************************************/ >+ >+char* kerberos_standard_des_salt( void ) >+{ >+ fstring salt; >+ >+ fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() ); >+ (void)strlower_m( salt ); >+ fstrcat( salt, lp_realm() ); >+ >+ return SMB_STRDUP( salt ); >+} >+ >+/************************************************************************ >+************************************************************************/ >+ >+static char* des_salt_key( void ) >+{ >+ char *key; >+ >+ if (asprintf(&key, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, >+ lp_realm()) == -1) { >+ return NULL; >+ } >+ >+ return key; >+} >+ >+/************************************************************************ >+************************************************************************/ >+ >+bool kerberos_secrets_store_des_salt( const char* salt ) >+{ >+ char* key; >+ bool ret; >+ >+ if ( (key = des_salt_key()) == NULL ) { >+ DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n")); >+ return False; >+ } >+ >+ if ( !salt ) { >+ DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n")); >+ secrets_delete( key ); >+ return True; >+ } >+ >+ DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt)); >+ >+ ret = secrets_store( key, salt, strlen(salt)+1 ); >+ >+ SAFE_FREE( key ); >+ >+ return ret; >+} >+ >+/************************************************************************ >+************************************************************************/ >+ >+static >+char* kerberos_secrets_fetch_des_salt( void ) >+{ >+ char *salt, *key; >+ >+ if ( (key = des_salt_key()) == NULL ) { >+ DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n")); >+ return NULL; >+ } >+ >+ salt = (char*)secrets_fetch( key, NULL ); >+ >+ SAFE_FREE( key ); >+ >+ return salt; >+} >+ >+/************************************************************************ >+ Routine to get the salting principal for this service. >+ Caller must free if return is not null. >+ ************************************************************************/ >+ >+char *kerberos_secrets_fetch_salt_princ(void) >+{ >+ char *salt_princ_s; >+ /* lookup new key first */ >+ >+ salt_princ_s = kerberos_secrets_fetch_des_salt(); >+ if (salt_princ_s == NULL) { >+ /* fall back to host/machine.realm@REALM */ >+ salt_princ_s = kerberos_standard_des_salt(); >+ } >+ >+ return salt_princ_s; >+} > > /************************************************************************ > Routine to fetch the previous plaintext machine account password for a realm >-- >1.9.1 > > >From 65922e4be76c79866e42dd474c0325cdcd7a96e6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 11:38:12 +0200 >Subject: [PATCH 27/56] s3:secrets: rework des_salt_key() to take the realm as > argument > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 072dd87e639d7dbfc583ede5ddf6559d9d433b8b) >--- > source3/passdb/machine_account_secrets.c | 25 +++++++++++++------------ > 1 file changed, 13 insertions(+), 12 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 3f6d6b6..114bed6 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -571,16 +571,15 @@ char* kerberos_standard_des_salt( void ) > /************************************************************************ > ************************************************************************/ > >-static char* des_salt_key( void ) >+static char *des_salt_key(const char *realm) > { >- char *key; >- >- if (asprintf(&key, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, >- lp_realm()) == -1) { >- return NULL; >- } >+ char *keystr; > >- return key; >+ keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s", >+ SECRETS_SALTING_PRINCIPAL, >+ realm); >+ SMB_ASSERT(keystr != NULL); >+ return keystr; > } > > /************************************************************************ >@@ -591,7 +590,8 @@ bool kerberos_secrets_store_des_salt( const char* salt ) > char* key; > bool ret; > >- if ( (key = des_salt_key()) == NULL ) { >+ key = des_salt_key(lp_realm()); >+ if (key == NULL) { > DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n")); > return False; > } >@@ -606,7 +606,7 @@ bool kerberos_secrets_store_des_salt( const char* salt ) > > ret = secrets_store( key, salt, strlen(salt)+1 ); > >- SAFE_FREE( key ); >+ TALLOC_FREE(key); > > return ret; > } >@@ -619,14 +619,15 @@ char* kerberos_secrets_fetch_des_salt( void ) > { > char *salt, *key; > >- if ( (key = des_salt_key()) == NULL ) { >+ key = des_salt_key(lp_realm()); >+ if (key == NULL) { > DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n")); > return NULL; > } > > salt = (char*)secrets_fetch( key, NULL ); > >- SAFE_FREE( key ); >+ TALLOC_FREE(key); > > return salt; > } >-- >1.9.1 > > >From 44b82a98a67141610c51cd07da693be57dc27f36 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:10:45 +0200 >Subject: [PATCH 28/56] s3:secrets: split out a domain_guid_keystr() function > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit d37e30cef7906b7b2b14351ad81d0d884811557b) >--- > source3/passdb/machine_account_secrets.c | 24 ++++++++++++++---------- > 1 file changed, 14 insertions(+), 10 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 114bed6..060babf 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -51,6 +51,16 @@ static const char *domain_sid_keystr(const char *domain) > return keystr; > } > >+static const char *domain_guid_keystr(const char *domain) >+{ >+ char *keystr; >+ >+ keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s", >+ SECRETS_DOMAIN_GUID, domain); >+ SMB_ASSERT(keystr != NULL); >+ return keystr; >+} >+ > static const char *protect_ids_keystr(const char *domain) > { > char *keystr; >@@ -139,7 +149,7 @@ bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid) > bool secrets_store_domain_guid(const char *domain, struct GUID *guid) > { > char *protect_ids; >- fstring key; >+ const char *key; > > protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL); > if (protect_ids) { >@@ -152,24 +162,18 @@ bool secrets_store_domain_guid(const char *domain, struct GUID *guid) > } > SAFE_FREE(protect_ids); > >- slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); >- if (!strupper_m(key)) { >- return false; >- } >+ key = domain_guid_keystr(domain); > return secrets_store(key, guid, sizeof(struct GUID)); > } > > bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) > { > struct GUID *dyn_guid; >- fstring key; >+ const char *key; > size_t size = 0; > struct GUID new_guid; > >- slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); >- if (!strupper_m(key)) { >- return false; >- } >+ key = domain_guid_keystr(domain); > dyn_guid = (struct GUID *)secrets_fetch(key, &size); > > if (!dyn_guid) { >-- >1.9.1 > > >From cb1bf4eeb59d2ceb04e31542b23e81e2c139cffa Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 21 Jun 2017 19:38:15 +0200 >Subject: [PATCH 29/56] s3:secrets: add some const to > secrets_store_domain_guid() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 99013685a1114829579e420df3625ed79eb7ee94) >--- > source3/include/secrets.h | 2 +- > source3/passdb/machine_account_secrets.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index c40a951..6f74494 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -95,7 +95,7 @@ bool secrets_mark_domain_protected(const char *domain); > bool secrets_clear_domain_protection(const char *domain); > bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid); > bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid); >-bool secrets_store_domain_guid(const char *domain, struct GUID *guid); >+bool secrets_store_domain_guid(const char *domain, const struct GUID *guid); > bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid); > enum netr_SchannelType get_default_sec_channel(void); > bool secrets_fetch_trust_account_password_legacy(const char *domain, >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 060babf..7d31734 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -146,7 +146,7 @@ bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid) > return True; > } > >-bool secrets_store_domain_guid(const char *domain, struct GUID *guid) >+bool secrets_store_domain_guid(const char *domain, const struct GUID *guid) > { > char *protect_ids; > const char *key; >-- >1.9.1 > > >From e82bfd09b229199f1e1f5b22160a660e60ef5e24 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:18:33 +0200 >Subject: [PATCH 30/56] s3:secrets: make use of des_salt_key() in > secrets_store_machine_pw_sync() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 4e37d7805b345d80ca6e8a598e39fc81f72a27ce) >--- > source3/passdb/machine_account_secrets.c | 8 +++----- > 1 file changed, 3 insertions(+), 5 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 7d31734..369f774 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -34,6 +34,8 @@ > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_PASSDB > >+static char *des_salt_key(const char *realm); >+ > /** > * Form a key for fetching the domain sid > * >@@ -545,11 +547,7 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > } > > if (realm && salting_principal) { >- char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm); >- if (!key) { >- TALLOC_FREE(frame); >- return false; >- } >+ char *key = des_salt_key(realm); > ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 ); > } > >-- >1.9.1 > > >From b1f40aa37b007f67cf024082217f855af644a783 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 20 Jun 2017 13:07:15 +0200 >Subject: [PATCH 31/56] s3:secrets: rename secrets_delete() to > secrets_delete_entry() > >secrets_delete_entry() fails if the key doesn't exist. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit cd1e888773c4fd3db63ce38a496fc3d54eb8e021) >--- > source3/include/secrets.h | 2 +- > source3/passdb/machine_account_secrets.c | 16 ++++++++-------- > source3/passdb/secrets.c | 6 +++--- > source3/passdb/secrets_lsa.c | 2 +- > source3/utils/net.c | 6 +++--- > 5 files changed, 16 insertions(+), 16 deletions(-) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index 6f74494..e7f87a9 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -88,7 +88,7 @@ struct db_context *secrets_db_ctx(void); > void secrets_shutdown(void); > void *secrets_fetch(const char *key, size_t *size); > bool secrets_store(const char *key, const void *data, size_t size); >-bool secrets_delete(const char *key); >+bool secrets_delete_entry(const char *key); > > /* The following definitions come from passdb/machine_account_secrets.c */ > bool secrets_mark_domain_protected(const char *domain); >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 369f774..7f19c65 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -92,7 +92,7 @@ bool secrets_clear_domain_protection(const char *domain) > > if (protection) { > SAFE_FREE(protection); >- ret = secrets_delete(protect_ids_keystr(domain)); >+ ret = secrets_delete_entry(protect_ids_keystr(domain)); > if (!ret) { > DEBUG(0, ("Failed to remove Domain IDs protection\n")); > } >@@ -381,7 +381,7 @@ static bool secrets_delete_prev_machine_password(const char *domain) > return true; > } > SAFE_FREE(oldpass); >- return secrets_delete(machine_prev_password_keystr(domain)); >+ return secrets_delete_entry(machine_prev_password_keystr(domain)); > } > > /************************************************************************ >@@ -394,13 +394,13 @@ bool secrets_delete_machine_password_ex(const char *domain) > if (!secrets_delete_prev_machine_password(domain)) { > return false; > } >- if (!secrets_delete(machine_password_keystr(domain))) { >+ if (!secrets_delete_entry(machine_password_keystr(domain))) { > return false; > } >- if (!secrets_delete(machine_sec_channel_type_keystr(domain))) { >+ if (!secrets_delete_entry(machine_sec_channel_type_keystr(domain))) { > return false; > } >- return secrets_delete(machine_last_change_time_keystr(domain)); >+ return secrets_delete_entry(machine_last_change_time_keystr(domain)); > } > > /************************************************************************ >@@ -409,7 +409,7 @@ bool secrets_delete_machine_password_ex(const char *domain) > > bool secrets_delete_domain_sid(const char *domain) > { >- return secrets_delete(domain_sid_keystr(domain)); >+ return secrets_delete_entry(domain_sid_keystr(domain)); > } > > /************************************************************************ >@@ -514,7 +514,7 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL); > if (value) { > SAFE_FREE(value); >- ret = secrets_delete(machine_sec_channel_type_keystr(domain)); >+ ret = secrets_delete_entry(machine_sec_channel_type_keystr(domain)); > if (!ret) { > TALLOC_FREE(frame); > return ret; >@@ -600,7 +600,7 @@ bool kerberos_secrets_store_des_salt( const char* salt ) > > if ( !salt ) { > DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n")); >- secrets_delete( key ); >+ secrets_delete_entry( key ); > return True; > } > >diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c >index 4372c63..ae00936 100644 >--- a/source3/passdb/secrets.c >+++ b/source3/passdb/secrets.c >@@ -146,7 +146,7 @@ bool secrets_store(const char *key, const void *data, size_t size) > > /* delete a secets database entry > */ >-bool secrets_delete(const char *key) >+bool secrets_delete_entry(const char *key) > { > NTSTATUS status; > if (!secrets_init()) { >@@ -277,7 +277,7 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd, > > bool trusted_domain_password_delete(const char *domain) > { >- return secrets_delete(trustdom_keystr(domain)); >+ return secrets_delete_entry(trustdom_keystr(domain)); > } > > bool secrets_store_ldap_pw(const char* dn, char* pw) >@@ -352,7 +352,7 @@ bool fetch_ldap_pw(char **dn, char** pw) > SAFE_FREE(*dn); > return False; > } >- if (!secrets_delete(old_style_key)) { >+ if (!secrets_delete_entry(old_style_key)) { > DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); > } > >diff --git a/source3/passdb/secrets_lsa.c b/source3/passdb/secrets_lsa.c >index a40942c..3ebaac4 100644 >--- a/source3/passdb/secrets_lsa.c >+++ b/source3/passdb/secrets_lsa.c >@@ -223,7 +223,7 @@ NTSTATUS lsa_secret_delete(const char *secret_name) > return status; > } > >- if (!secrets_delete(key)) { >+ if (!secrets_delete_entry(key)) { > talloc_free(key); > return NT_STATUS_ACCESS_DENIED; > } >diff --git a/source3/utils/net.c b/source3/utils/net.c >index beb8760..6f7a7a4 100644 >--- a/source3/utils/net.c >+++ b/source3/utils/net.c >@@ -156,9 +156,9 @@ static int net_setauthuser(struct net_context *c, int argc, const char **argv) > " Delete the auth user setting.\n")); > return 1; > } >- secrets_delete(SECRETS_AUTH_USER); >- secrets_delete(SECRETS_AUTH_DOMAIN); >- secrets_delete(SECRETS_AUTH_PASSWORD); >+ secrets_delete_entry(SECRETS_AUTH_USER); >+ secrets_delete_entry(SECRETS_AUTH_DOMAIN); >+ secrets_delete_entry(SECRETS_AUTH_PASSWORD); > return 0; > } > >-- >1.9.1 > > >From 9fb825847dbd5726d884c13a33b0e61ff1c186ea Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:21:37 +0200 >Subject: [PATCH 32/56] s3:secrets: re-add secrets_delete() helper to simplify > deleting optional keys > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit fde4af1c329655d7ef3f55727632b3f026a3ea73) >--- > source3/include/secrets.h | 1 + > source3/passdb/secrets.c | 19 +++++++++++++++++++ > 2 files changed, 20 insertions(+) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index e7f87a9..548003f 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -89,6 +89,7 @@ void secrets_shutdown(void); > void *secrets_fetch(const char *key, size_t *size); > bool secrets_store(const char *key, const void *data, size_t size); > bool secrets_delete_entry(const char *key); >+bool secrets_delete(const char *key); > > /* The following definitions come from passdb/machine_account_secrets.c */ > bool secrets_mark_domain_protected(const char *domain); >diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c >index ae00936..d843b60 100644 >--- a/source3/passdb/secrets.c >+++ b/source3/passdb/secrets.c >@@ -158,6 +158,25 @@ bool secrets_delete_entry(const char *key) > return NT_STATUS_IS_OK(status); > } > >+/* >+ * Deletes the key if it exists. >+ */ >+bool secrets_delete(const char *key) >+{ >+ bool exists; >+ >+ if (!secrets_init()) { >+ return false; >+ } >+ >+ exists = dbwrap_exists(db_ctx, string_tdb_data(key)); >+ if (!exists) { >+ return true; >+ } >+ >+ return secrets_delete_entry(key); >+} >+ > /** > * Form a key for fetching a trusted domain password > * >-- >1.9.1 > > >From 6878c63107514a195be92311568708413a99045e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:21:37 +0200 >Subject: [PATCH 33/56] s3:secrets: make use of secrets_delete() in > secrets_store_machine_pw_sync() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit c5ded1123797b2bd152b0989e24eba7cae6a5792) >--- > source3/passdb/machine_account_secrets.c | 19 +++++-------------- > 1 file changed, 5 insertions(+), 14 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 7f19c65..6b89e25 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -478,7 +478,6 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > uint8_t last_change_time_store[4]; > TALLOC_CTX *frame = talloc_stackframe(); > uint8_t sec_channel_bytes[4]; >- void *value; > > if (delete_join) { > secrets_delete_machine_password_ex(domain); >@@ -496,11 +495,7 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > if (oldpass) { > ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1); > } else { >- value = secrets_fetch_prev_machine_password(domain); >- if (value) { >- SAFE_FREE(value); >- ret = secrets_delete_prev_machine_password(domain); >- } >+ ret = secrets_delete(machine_prev_password_keystr(domain)); > } > if (!ret) { > TALLOC_FREE(frame); >@@ -511,14 +506,10 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > /* We delete this and instead have the read code fall back to > * a default based on server role, as our caller can't specify > * this with any more certainty */ >- value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL); >- if (value) { >- SAFE_FREE(value); >- ret = secrets_delete_entry(machine_sec_channel_type_keystr(domain)); >- if (!ret) { >- TALLOC_FREE(frame); >- return ret; >- } >+ ret = secrets_delete(machine_sec_channel_type_keystr(domain)); >+ if (!ret) { >+ TALLOC_FREE(frame); >+ return ret; > } > } else { > SIVAL(&sec_channel_bytes, 0, secure_channel_type); >-- >1.9.1 > > >From ee9309a529e3344426ee34d20c1c70eb2520fa24 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:27:45 +0200 >Subject: [PATCH 34/56] s3:secrets: let secrets_store_machine_pw_sync() delete > the des_salt_key when there's no value > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 45eea321a6faa6db1c9c706a27527cc0766dc831) >--- > source3/passdb/machine_account_secrets.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 6b89e25..c3a760b 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -537,9 +537,16 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > return ret; > } > >- if (realm && salting_principal) { >+ if (realm != NULL) { > char *key = des_salt_key(realm); >- ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 ); >+ >+ if (salting_principal != NULL) { >+ ret = secrets_store(key, >+ salting_principal, >+ strlen(salting_principal)+1); >+ } else { >+ ret = secrets_delete(key); >+ } > } > > TALLOC_FREE(frame); >-- >1.9.1 > > >From d128724e95d4eb56c84656f8b73e13cfcff70f8c Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 24 May 2017 06:44:32 +0200 >Subject: [PATCH 35/56] s3:secrets: replace > secrets_delete_prev_machine_password() by secrets_delete() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5b95cb74e7b2838d228f9773c0e20982b81d1e7d) >--- > source3/passdb/machine_account_secrets.c | 16 +--------------- > 1 file changed, 1 insertion(+), 15 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index c3a760b..2457ac7 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -371,27 +371,13 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16 > } > > /************************************************************************ >- Routine to delete the old plaintext machine account password if any >-************************************************************************/ >- >-static bool secrets_delete_prev_machine_password(const char *domain) >-{ >- char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL); >- if (oldpass == NULL) { >- return true; >- } >- SAFE_FREE(oldpass); >- return secrets_delete_entry(machine_prev_password_keystr(domain)); >-} >- >-/************************************************************************ > Routine to delete the plaintext machine account password, old password, > sec channel type and last change time from secrets database > ************************************************************************/ > > bool secrets_delete_machine_password_ex(const char *domain) > { >- if (!secrets_delete_prev_machine_password(domain)) { >+ if (!secrets_delete(machine_prev_password_keystr(domain))) { > return false; > } > if (!secrets_delete_entry(machine_password_keystr(domain))) { >-- >1.9.1 > > >From 2cb97de6fb989d1c68f224c41ad469f9889b0c45 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:31:01 +0200 >Subject: [PATCH 36/56] s3:secrets: rewrite > secrets_delete_machine_password_ex() using helper variables > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5bc2764fe517748c03a57b61f2f7ef889c92825d) >--- > source3/passdb/machine_account_secrets.c | 26 ++++++++++++++++++++++---- > 1 file changed, 22 insertions(+), 4 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 2457ac7..56a9442 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -377,16 +377,34 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16 > > bool secrets_delete_machine_password_ex(const char *domain) > { >- if (!secrets_delete(machine_prev_password_keystr(domain))) { >+ const char *tmpkey = NULL; >+ bool ok; >+ >+ tmpkey = machine_prev_password_keystr(domain); >+ ok = secrets_delete(tmpkey); >+ if (!ok) { >+ return false; >+ } >+ >+ tmpkey = machine_password_keystr(domain); >+ ok = secrets_delete_entry(tmpkey); >+ if (!ok) { > return false; > } >- if (!secrets_delete_entry(machine_password_keystr(domain))) { >+ >+ tmpkey = machine_sec_channel_type_keystr(domain); >+ ok = secrets_delete_entry(tmpkey); >+ if (!ok) { > return false; > } >- if (!secrets_delete_entry(machine_sec_channel_type_keystr(domain))) { >+ >+ tmpkey = machine_last_change_time_keystr(domain); >+ ok = secrets_delete_entry(tmpkey); >+ if (!ok) { > return false; > } >- return secrets_delete_entry(machine_last_change_time_keystr(domain)); >+ >+ return true; > } > > /************************************************************************ >-- >1.9.1 > > >From 2fa642cad54dbea8b7c62327b47d48110785a544 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:40:05 +0200 >Subject: [PATCH 37/56] s3:secrets: let secrets_delete_machine_password_ex() > remove SID and GUID too > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit cf8a4646fe71a974b6a5ee13ae7d7751a5a0adc9) >--- > source3/libnet/libnet_join.c | 4 ---- > source3/passdb/machine_account_secrets.c | 16 +++++++++++++--- > 2 files changed, 13 insertions(+), 7 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 7669c2e..9a2f227 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -1705,10 +1705,6 @@ static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX *mem_ctx, > return false; > } > >- if (!secrets_delete_domain_sid(lp_workgroup())) { >- return false; >- } >- > return true; > } > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 56a9442..06e42f2 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -371,8 +371,7 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16 > } > > /************************************************************************ >- Routine to delete the plaintext machine account password, old password, >- sec channel type and last change time from secrets database >+ Routine to delete all information related to the domain joined machine. > ************************************************************************/ > > bool secrets_delete_machine_password_ex(const char *domain) >@@ -380,6 +379,12 @@ bool secrets_delete_machine_password_ex(const char *domain) > const char *tmpkey = NULL; > bool ok; > >+ tmpkey = domain_guid_keystr(domain); >+ ok = secrets_delete(tmpkey); >+ if (!ok) { >+ return false; >+ } >+ > tmpkey = machine_prev_password_keystr(domain); > ok = secrets_delete(tmpkey); > if (!ok) { >@@ -404,6 +409,12 @@ bool secrets_delete_machine_password_ex(const char *domain) > return false; > } > >+ tmpkey = domain_sid_keystr(domain); >+ ok = secrets_delete_entry(tmpkey); >+ if (!ok) { >+ return false; >+ } >+ > return true; > } > >@@ -485,7 +496,6 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > > if (delete_join) { > secrets_delete_machine_password_ex(domain); >- secrets_delete_domain_sid(domain); > TALLOC_FREE(frame); > return true; > } >-- >1.9.1 > > >From 7ba39037e81d64498450b4a6f4dbb6d668ff2f27 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 12:44:31 +0200 >Subject: [PATCH 38/56] s3:secrets: let secrets_delete_machine_password_ex() > also remove the des_salt key > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit dfaadc81925e313901c9b30cd98a4b4fd2404f9d) >--- > source3/include/secrets.h | 2 +- > source3/libnet/libnet_join.c | 9 ++++----- > source3/passdb/machine_account_secrets.c | 12 ++++++++++-- > 3 files changed, 15 insertions(+), 8 deletions(-) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index 548003f..fc8e118 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -110,7 +110,7 @@ bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd, > struct dom_sid *sid, time_t *pass_last_set_time); > bool secrets_store_trusted_domain_password(const char* domain, const char* pwd, > const struct dom_sid *sid); >-bool secrets_delete_machine_password_ex(const char *domain); >+bool secrets_delete_machine_password_ex(const char *domain, const char *realm); > bool secrets_delete_domain_sid(const char *domain); > bool secrets_store_machine_password(const char *pass, const char *domain, enum netr_SchannelType sec_channel); > char *secrets_fetch_prev_machine_password(const char *domain); >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 9a2f227..ecae4c5 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -1701,11 +1701,10 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx, > static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX *mem_ctx, > struct libnet_UnjoinCtx *r) > { >- if (!secrets_delete_machine_password_ex(lp_workgroup())) { >- return false; >- } >- >- return true; >+ /* >+ * TODO: use values from 'struct libnet_UnjoinCtx' ? >+ */ >+ return secrets_delete_machine_password_ex(lp_workgroup(), lp_realm()); > } > > /**************************************************************** >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 06e42f2..70a8277 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -374,11 +374,19 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16 > Routine to delete all information related to the domain joined machine. > ************************************************************************/ > >-bool secrets_delete_machine_password_ex(const char *domain) >+bool secrets_delete_machine_password_ex(const char *domain, const char *realm) > { > const char *tmpkey = NULL; > bool ok; > >+ if (realm != NULL) { >+ tmpkey = des_salt_key(domain); >+ ok = secrets_delete(tmpkey); >+ if (!ok) { >+ return false; >+ } >+ } >+ > tmpkey = domain_guid_keystr(domain); > ok = secrets_delete(tmpkey); > if (!ok) { >@@ -495,7 +503,7 @@ bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const > uint8_t sec_channel_bytes[4]; > > if (delete_join) { >- secrets_delete_machine_password_ex(domain); >+ secrets_delete_machine_password_ex(domain, realm); > TALLOC_FREE(frame); > return true; > } >-- >1.9.1 > > >From 92c7374a72d80c1f413baf9223c1d67fc797f453 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 24 May 2017 05:56:32 +0200 >Subject: [PATCH 39/56] s3:secrets: use secrets_delete for all keys in > secrets_delete_machine_password_ex() > >We just want all values to be removed at the end, it doesn't matter >if they didn't existed before. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit bfe35abc1fb15e70a99fa74d064051a1ad541ed0) >--- > source3/passdb/machine_account_secrets.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 70a8277..9a96a3f 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -400,25 +400,25 @@ bool secrets_delete_machine_password_ex(const char *domain, const char *realm) > } > > tmpkey = machine_password_keystr(domain); >- ok = secrets_delete_entry(tmpkey); >+ ok = secrets_delete(tmpkey); > if (!ok) { > return false; > } > > tmpkey = machine_sec_channel_type_keystr(domain); >- ok = secrets_delete_entry(tmpkey); >+ ok = secrets_delete(tmpkey); > if (!ok) { > return false; > } > > tmpkey = machine_last_change_time_keystr(domain); >- ok = secrets_delete_entry(tmpkey); >+ ok = secrets_delete(tmpkey); > if (!ok) { > return false; > } > > tmpkey = domain_sid_keystr(domain); >- ok = secrets_delete_entry(tmpkey); >+ ok = secrets_delete(tmpkey); > if (!ok) { > return false; > } >-- >1.9.1 > > >From fd4011fb0198f25159b7bb193af41c207a83a7e4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 15:36:29 +0200 >Subject: [PATCH 40/56] s3:trusts_util: pass dcname to trust_pw_change() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 1421abfc733247a6b71eefd819dfeae7151a6d78) >--- > source3/include/proto.h | 1 + > source3/libsmb/trusts_util.c | 1 + > source3/rpcclient/cmd_netlogon.c | 2 ++ > source3/utils/net_rpc.c | 8 ++++++++ > source3/winbindd/winbindd_dual.c | 1 + > source3/winbindd/winbindd_dual_srv.c | 2 ++ > 6 files changed, 15 insertions(+) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index c18e88f..baa5799 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -869,6 +869,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > struct messaging_context *msg_ctx, > struct dcerpc_binding_handle *b, > const char *domain, >+ const char *dcname, > bool force); > > /* The following definitions come from param/loadparm.c */ >diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c >index 2cc6264..47b79b7 100644 >--- a/source3/libsmb/trusts_util.c >+++ b/source3/libsmb/trusts_util.c >@@ -107,6 +107,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > struct messaging_context *msg_ctx, > struct dcerpc_binding_handle *b, > const char *domain, >+ const char *dcname, > bool force) > { > TALLOC_CTX *frame = talloc_stackframe(); >diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c >index f657172..7d12f17 100644 >--- a/source3/rpcclient/cmd_netlogon.c >+++ b/source3/rpcclient/cmd_netlogon.c >@@ -831,6 +831,7 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, > const char **argv) > { > NTSTATUS result = NT_STATUS_UNSUCCESSFUL; >+ const char *dcname = cli->desthost; > > /* Check arguments */ > >@@ -843,6 +844,7 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, > rpcclient_msg_ctx, > cli->binding_handle, > lp_workgroup(), >+ dcname, > true); /* force */ > if (!NT_STATUS_IS_OK(result)) > goto done; >diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c >index 17b3e4d..c179cc2 100644 >--- a/source3/utils/net_rpc.c >+++ b/source3/utils/net_rpc.c >@@ -279,11 +279,19 @@ static NTSTATUS rpc_changetrustpw_internals(struct net_context *c, > const char **argv) > { > NTSTATUS status; >+ const char *dcname = NULL; >+ >+ if (cli == NULL) { >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ dcname = smbXcli_conn_remote_name(cli->conn); > > status = trust_pw_change(c->netlogon_creds, > c->msg_ctx, > pipe_hnd->binding_handle, > c->opt_target_workgroup, >+ dcname, > true); /* force */ > if (!NT_STATUS_IS_OK(status)) { > d_fprintf(stderr, _("Failed to change machine account password: %s\n"), >diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c >index c389e00..8636ccd 100644 >--- a/source3/winbindd/winbindd_dual.c >+++ b/source3/winbindd/winbindd_dual.c >@@ -1095,6 +1095,7 @@ static void machine_password_change_handler(struct tevent_context *ctx, > msg_ctx, > netlogon_pipe->binding_handle, > child->domain->name, >+ child->domain->dcname, > false); /* force */ > > DEBUG(10, ("machine_password_change_handler: " >diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c >index 52e8629..0a2a5e2 100644 >--- a/source3/winbindd/winbindd_dual_srv.c >+++ b/source3/winbindd/winbindd_dual_srv.c >@@ -730,6 +730,7 @@ NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p, > msg_ctx, > netlogon_pipe->binding_handle, > domain->name, >+ domain->dcname, > true); /* force */ > > /* Pass back result code - zero for success, other values for >@@ -1406,6 +1407,7 @@ reconnect: > > status = trust_pw_change(domain->conn.netlogon_creds, > msg_ctx, b, domain->name, >+ domain->dcname, > true); /* force */ > if (!NT_STATUS_IS_OK(status)) { > if (!retry && dcerpc_binding_handle_is_connected(b)) { >-- >1.9.1 > > >From 697b967427991d4d31f6562dbc7d286cf5ac0eb3 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 20:44:40 +0200 >Subject: [PATCH 41/56] libcli/auth: pass an array of nt_hashes to > netlogon_creds_cli_auth*() > >This way the caller can pass more than 2 hashes and can only >know which hash was used for a successful connection. > >We allow up to 4 hashes (next, current, old, older). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit ddd7ac68ccae8b4df6c6a65b3dad20e21924f538) >--- > libcli/auth/netlogon_creds_cli.c | 58 +++++++++++++++++++++++++-------------- > libcli/auth/netlogon_creds_cli.h | 12 ++++---- > source3/libsmb/trusts_util.c | 19 +++++++++---- > source3/rpc_client/cli_netlogon.c | 15 ++++++++-- > 4 files changed, 71 insertions(+), 33 deletions(-) > >diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c >index d55142e..ba8e063 100644 >--- a/libcli/auth/netlogon_creds_cli.c >+++ b/libcli/auth/netlogon_creds_cli.c >@@ -942,9 +942,10 @@ struct netlogon_creds_cli_auth_state { > struct tevent_context *ev; > struct netlogon_creds_cli_context *context; > struct dcerpc_binding_handle *binding_handle; >- struct samr_Password current_nt_hash; >- struct samr_Password previous_nt_hash; >- struct samr_Password used_nt_hash; >+ uint8_t num_nt_hashes; >+ uint8_t idx_nt_hashes; >+ const struct samr_Password * const *nt_hashes; >+ const struct samr_Password *used_nt_hash; > char *srv_name_slash; > uint32_t current_flags; > struct netr_Credential client_challenge; >@@ -956,7 +957,6 @@ struct netlogon_creds_cli_auth_state { > bool try_auth3; > bool try_auth2; > bool require_auth2; >- bool try_previous_nt_hash; > struct netlogon_creds_cli_locked_state *locked_state; > }; > >@@ -967,8 +967,8 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- struct samr_Password current_nt_hash, >- const struct samr_Password *previous_nt_hash) >+ uint8_t num_nt_hashes, >+ const struct samr_Password * const *nt_hashes) > { > struct tevent_req *req; > struct netlogon_creds_cli_auth_state *state; >@@ -984,12 +984,19 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, > state->ev = ev; > state->context = context; > state->binding_handle = b; >- state->current_nt_hash = current_nt_hash; >- if (previous_nt_hash != NULL) { >- state->previous_nt_hash = *previous_nt_hash; >- state->try_previous_nt_hash = true; >+ if (num_nt_hashes < 1) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); >+ return tevent_req_post(req, ev); >+ } >+ if (num_nt_hashes > 4) { >+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); >+ return tevent_req_post(req, ev); > } > >+ state->num_nt_hashes = num_nt_hashes; >+ state->idx_nt_hashes = 0; >+ state->nt_hashes = nt_hashes; >+ > if (context->db.locked_state != NULL) { > tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED); > return tevent_req_post(req, ev); >@@ -1019,7 +1026,7 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, > state->require_auth2 = true; > } > >- state->used_nt_hash = state->current_nt_hash; >+ state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes]; > state->current_flags = context->client.proposed_flags; > > if (context->db.g_ctx != NULL) { >@@ -1141,7 +1148,7 @@ static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) > state->context->client.type, > &state->client_challenge, > &state->server_challenge, >- &state->used_nt_hash, >+ state->used_nt_hash, > &state->client_credential, > state->current_flags); > if (tevent_req_nomem(state->creds, req)) { >@@ -1283,7 +1290,8 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) > return; > } > >- if (!state->try_previous_nt_hash) { >+ state->idx_nt_hashes += 1; >+ if (state->idx_nt_hashes >= state->num_nt_hashes) { > /* > * we already retried, giving up... > */ >@@ -1294,8 +1302,7 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) > /* > * lets retry with the old nt hash. > */ >- state->try_previous_nt_hash = false; >- state->used_nt_hash = state->previous_nt_hash; >+ state->used_nt_hash = state->nt_hashes[state->idx_nt_hashes]; > state->current_flags = state->context->client.proposed_flags; > netlogon_creds_cli_auth_challenge_start(req); > return; >@@ -1330,43 +1337,52 @@ static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) > tevent_req_done(req); > } > >-NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req) >+NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req, >+ uint8_t *idx_nt_hashes) > { >+ struct netlogon_creds_cli_auth_state *state = >+ tevent_req_data(req, >+ struct netlogon_creds_cli_auth_state); > NTSTATUS status; > >+ *idx_nt_hashes = 0; >+ > if (tevent_req_is_nterror(req, &status)) { > tevent_req_received(req); > return status; > } > >+ *idx_nt_hashes = state->idx_nt_hashes; > tevent_req_received(req); > return NT_STATUS_OK; > } > > NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- struct samr_Password current_nt_hash, >- const struct samr_Password *previous_nt_hash) >+ uint8_t num_nt_hashes, >+ const struct samr_Password * const *nt_hashes, >+ uint8_t *idx_nt_hashes) > { > TALLOC_CTX *frame = talloc_stackframe(); > struct tevent_context *ev; > struct tevent_req *req; > NTSTATUS status = NT_STATUS_NO_MEMORY; > >+ *idx_nt_hashes = 0; >+ > ev = samba_tevent_context_init(frame); > if (ev == NULL) { > goto fail; > } > req = netlogon_creds_cli_auth_send(frame, ev, context, b, >- current_nt_hash, >- previous_nt_hash); >+ num_nt_hashes, nt_hashes); > if (req == NULL) { > goto fail; > } > if (!tevent_req_poll_ntstatus(req, ev, &status)) { > goto fail; > } >- status = netlogon_creds_cli_auth_recv(req); >+ status = netlogon_creds_cli_auth_recv(req, idx_nt_hashes); > fail: > TALLOC_FREE(frame); > return status; >diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h >index 949e03b..4cedb3b 100644 >--- a/libcli/auth/netlogon_creds_cli.h >+++ b/libcli/auth/netlogon_creds_cli.h >@@ -84,13 +84,15 @@ struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- struct samr_Password current_nt_hash, >- const struct samr_Password *previous_nt_hash); >-NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req); >+ uint8_t num_nt_hashes, >+ const struct samr_Password * const *nt_hashes); >+NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req, >+ uint8_t *idx_nt_hashes); > NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- struct samr_Password current_nt_hash, >- const struct samr_Password *previous_nt_hash); >+ uint8_t num_nt_hashes, >+ const struct samr_Password * const *nt_hashes, >+ uint8_t *idx_nt_hashes); > > struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c >index 47b79b7..128beb7 100644 >--- a/source3/libsmb/trusts_util.c >+++ b/source3/libsmb/trusts_util.c >@@ -115,7 +115,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > struct trust_pw_change_state *state; > struct cli_credentials *creds = NULL; > const struct samr_Password *current_nt_hash = NULL; >- const struct samr_Password *previous_nt_hash = NULL; >+ uint8_t num_nt_hashes = 0; >+ const struct samr_Password *nt_hashes[1] = { NULL, }; >+ uint8_t idx_nt_hashes = 0; > enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; > time_t pass_last_set_time; > uint32_t old_version = 0; >@@ -245,6 +247,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > return NT_STATUS_NO_MEMORY; > } > >+ nt_hashes[0] = current_nt_hash; >+ num_nt_hashes = 1; >+ > /* > * We could use cli_credentials_get_old_nt_hash(creds, frame) to > * set previous_nt_hash. >@@ -259,8 +264,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > * local secrets before doing the change. > */ > status = netlogon_creds_cli_auth(context, b, >- *current_nt_hash, >- previous_nt_hash); >+ num_nt_hashes, >+ nt_hashes, >+ &idx_nt_hashes); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old password - %s!\n", > context_name, nt_errstr(status))); >@@ -349,9 +355,12 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > /* > * Now we verify the new password. > */ >+ nt_hashes[0] = current_nt_hash; >+ num_nt_hashes = 1; > status = netlogon_creds_cli_auth(context, b, >- *current_nt_hash, >- NULL); /* previous_nt_hash */ >+ num_nt_hashes, >+ nt_hashes, >+ &idx_nt_hashes); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for new password - %s!\n", > context_name, nt_errstr(status))); >diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c >index 166f318..7c39f46 100644 >--- a/source3/rpc_client/cli_netlogon.c >+++ b/source3/rpc_client/cli_netlogon.c >@@ -160,6 +160,9 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, > TALLOC_CTX *frame = talloc_stackframe(); > struct rpc_pipe_client *netlogon_pipe = NULL; > struct netlogon_creds_CredentialState *creds = NULL; >+ uint8_t num_nt_hashes = 0; >+ const struct samr_Password *nt_hashes[2] = { NULL, NULL }; >+ uint8_t idx_nt_hashes = 0; > NTSTATUS status; > > status = netlogon_creds_cli_get(netlogon_creds, >@@ -196,10 +199,18 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, > } > talloc_steal(frame, netlogon_pipe); > >+ nt_hashes[0] = ¤t_nt_hash; >+ num_nt_hashes = 1; >+ if (previous_nt_hash != NULL) { >+ nt_hashes[1] = previous_nt_hash; >+ num_nt_hashes = 2; >+ } >+ > status = netlogon_creds_cli_auth(netlogon_creds, > netlogon_pipe->binding_handle, >- current_nt_hash, >- previous_nt_hash); >+ num_nt_hashes, >+ nt_hashes, >+ &idx_nt_hashes); > if (!NT_STATUS_IS_OK(status)) { > TALLOC_FREE(frame); > return status; >-- >1.9.1 > > >From 9539a78e33a19c950f244ca210da823c697f5d2e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Jun 2017 11:17:03 +0200 >Subject: [PATCH 42/56] libcli/auth: add const to set_pw_in_buffer() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 1b48c8515ed8fd29204c82cc47f958f4636cd494) >--- > libcli/auth/proto.h | 2 +- > libcli/auth/smbencrypt.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > >diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h >index cc9ae33..a03f45e 100644 >--- a/libcli/auth/proto.h >+++ b/libcli/auth/proto.h >@@ -187,7 +187,7 @@ void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_B > encode a password buffer with an already unicode password. The > rest of the buffer is filled with random data to make it harder to attack. > ************************************************************/ >-bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password); >+bool set_pw_in_buffer(uint8_t buffer[516], const DATA_BLOB *password); > > /*********************************************************** > decode a password buffer >diff --git a/libcli/auth/smbencrypt.c b/libcli/auth/smbencrypt.c >index ebf6812..afd9286 100644 >--- a/libcli/auth/smbencrypt.c >+++ b/libcli/auth/smbencrypt.c >@@ -804,7 +804,7 @@ void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_B > encode a password buffer with an already unicode password. The > rest of the buffer is filled with random data to make it harder to attack. > ************************************************************/ >-bool set_pw_in_buffer(uint8_t buffer[516], DATA_BLOB *password) >+bool set_pw_in_buffer(uint8_t buffer[516], const DATA_BLOB *password) > { > if (password->length > 512) { > return false; >-- >1.9.1 > > >From e8a233ba3479bad43dce82629c0dca7868d5a591 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 13 Jun 2017 11:18:37 +0200 >Subject: [PATCH 43/56] libcli/auth: pass the cleartext blob to > netlogon_creds_cli_ServerPasswordSet*() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 0f5945a06df4bef501ca5085c621294057007225) >--- > libcli/auth/netlogon_creds_cli.c | 20 +++++++++++--------- > libcli/auth/netlogon_creds_cli.h | 4 ++-- > source3/libnet/libnet_join.c | 19 ++++++++++++++++++- > source3/libsmb/trusts_util.c | 39 ++++++++++++++++++++++++++++++++------- > 4 files changed, 63 insertions(+), 19 deletions(-) > >diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c >index ba8e063..29baae4 100644 >--- a/libcli/auth/netlogon_creds_cli.c >+++ b/libcli/auth/netlogon_creds_cli.c >@@ -36,6 +36,7 @@ > #include "source3/include/messages.h" > #include "source3/include/g_lock.h" > #include "libds/common/roles.h" >+#include "lib/crypto/crypto.h" > > struct netlogon_creds_cli_locked_state; > >@@ -1750,7 +1751,7 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx > struct tevent_context *ev, > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- const char *new_password, >+ const DATA_BLOB *new_password, > const uint32_t *new_version) > { > struct tevent_req *req; >@@ -1768,20 +1769,21 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx > state->context = context; > state->binding_handle = b; > >- /* >- * netr_ServerPasswordSet >- */ >- ok = E_md4hash(new_password, state->samr_password.hash); >- if (!ok) { >+ if (new_password->length < 14) { > tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); > return tevent_req_post(req, ev); > } > > /* >+ * netr_ServerPasswordSet >+ */ >+ mdfour(state->samr_password.hash, new_password->data, new_password->length); >+ >+ /* > * netr_ServerPasswordSet2 > */ >- ok = encode_pw_buffer(state->samr_crypt_password.data, >- new_password, STR_UNICODE); >+ ok = set_pw_in_buffer(state->samr_crypt_password.data, >+ new_password); > if (!ok) { > tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); > return tevent_req_post(req, ev); >@@ -2051,7 +2053,7 @@ NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req) > NTSTATUS netlogon_creds_cli_ServerPasswordSet( > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- const char *new_password, >+ const DATA_BLOB *new_password, > const uint32_t *new_version) > { > TALLOC_CTX *frame = talloc_stackframe(); >diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h >index 4cedb3b..a7fd48c 100644 >--- a/libcli/auth/netlogon_creds_cli.h >+++ b/libcli/auth/netlogon_creds_cli.h >@@ -106,13 +106,13 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx > struct tevent_context *ev, > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- const char *new_password, >+ const DATA_BLOB *new_password, > const uint32_t *new_version); > NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req); > NTSTATUS netlogon_creds_cli_ServerPasswordSet( > struct netlogon_creds_cli_context *context, > struct dcerpc_binding_handle *b, >- const char *new_password, >+ const DATA_BLOB *new_password, > const uint32_t *new_version); > > struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index ecae4c5..99bba2a 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -1140,6 +1140,9 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, > struct rpc_pipe_client *netlogon_pipe = NULL; > struct netlogon_creds_cli_context *netlogon_creds = NULL; > struct samr_Password current_nt_hash; >+ size_t len = 0; >+ bool ok; >+ DATA_BLOB new_trust_blob = data_blob_null; > NTSTATUS status; > > status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, >@@ -1186,9 +1189,23 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, > return status; > } > >+ len = strlen(r->in.machine_password); >+ ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16, >+ r->in.machine_password, len, >+ (void **)&new_trust_blob.data, >+ &new_trust_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ TALLOC_FREE(frame); >+ return status; >+ } >+ > status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds, > netlogon_pipe->binding_handle, >- r->in.machine_password, >+ &new_trust_blob, > NULL); /* new_version */ > if (!NT_STATUS_IS_OK(status)) { > TALLOC_FREE(frame); >diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c >index 128beb7..5bc8005 100644 >--- a/source3/libsmb/trusts_util.c >+++ b/source3/libsmb/trusts_util.c >@@ -125,7 +125,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > struct timeval g_timeout = { 0, }; > int timeout = 0; > struct timeval tv = { 0, }; >- char *new_trust_passwd = NULL; >+ char *new_trust_pw_str = NULL; >+ size_t len = 0; >+ DATA_BLOB new_trust_pw_blob = data_blob_null; > uint32_t new_version = 0; > uint32_t *new_trust_version = NULL; > NTSTATUS status; >@@ -239,14 +241,31 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > * We create a random buffer and convert that to utf8. > * This is similar to what windows is doing. > */ >- new_trust_passwd = trust_pw_new_value(frame, sec_channel_type, >+ new_trust_pw_str = trust_pw_new_value(frame, sec_channel_type, > lp_security()); >- if (new_trust_passwd == NULL) { >+ if (new_trust_pw_str == NULL) { > DEBUG(0, ("trust_pw_new_value() failed\n")); > TALLOC_FREE(frame); > return NT_STATUS_NO_MEMORY; > } > >+ len = strlen(new_trust_pw_str); >+ ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16, >+ new_trust_pw_str, len, >+ (void **)&new_trust_pw_blob.data, >+ &new_trust_pw_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " >+ "failed for of %s - %s\n", >+ domain, nt_errstr(status)); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ > nt_hashes[0] = current_nt_hash; > num_nt_hashes = 1; > >@@ -287,13 +306,16 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > > case SEC_CHAN_WKSTA: > case SEC_CHAN_BDC: >- ok = secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type); >+ ok = secrets_store_machine_password(new_trust_pw_str, >+ domain, >+ sec_channel_type); > if (!ok) { > DEBUG(0, ("secrets_store_machine_password failed for domain %s!\n", > domain)); > TALLOC_FREE(frame); > return NT_STATUS_INTERNAL_DB_CORRUPTION; > } >+ TALLOC_FREE(new_trust_pw_str); > break; > > case SEC_CHAN_DNS_DOMAIN: >@@ -302,7 +324,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > * we need to get the sid first for the > * pdb_set_trusteddom_pw call > */ >- ok = pdb_set_trusteddom_pw(domain, new_trust_passwd, >+ ok = pdb_set_trusteddom_pw(domain, new_trust_pw_str, > &td->security_identifier); > if (!ok) { > DEBUG(0, ("pdb_set_trusteddom_pw() failed for domain %s!\n", >@@ -310,6 +332,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > TALLOC_FREE(frame); > return NT_STATUS_INTERNAL_DB_CORRUPTION; > } >+ TALLOC_FREE(new_trust_pw_str); > break; > > default: >@@ -321,7 +344,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > current_timestring(talloc_tos(), false), __func__, domain)); > > status = netlogon_creds_cli_ServerPasswordSet(context, b, >- new_trust_passwd, >+ &new_trust_pw_blob, > new_trust_version); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(0,("%s : %s(%s) remote password change set with %s failed - %s\n", >@@ -336,7 +359,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > current_timestring(talloc_tos(), false), > __func__, domain, context_name)); > >- ok = cli_credentials_set_password(creds, new_trust_passwd, CRED_SPECIFIED); >+ ok = cli_credentials_set_utf16_password(creds, >+ &new_trust_pw_blob, >+ CRED_SPECIFIED); > if (!ok) { > DEBUG(0, ("cli_credentials_set_password failed for domain %s!\n", > domain)); >-- >1.9.1 > > >From ee0b7f15d085ab086443479019005bf55d07a982 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 21 Jun 2017 21:30:39 +0200 >Subject: [PATCH 44/56] s3:trusts_util: also pass the previous_nt_hash to > netlogon_creds_cli_auth() > >Even in the case where only the password is known to the server, we should >try to leave a valid authentication behind. > >We have better ways to indentify which password worked than only using >the current one. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit d60404b032eca5384d889352f52b9b129861b4af) >--- > source3/libsmb/trusts_util.c | 43 +++++++++++++++++++++++++++++++------------ > 1 file changed, 31 insertions(+), 12 deletions(-) > >diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c >index 5bc8005..ff7f256 100644 >--- a/source3/libsmb/trusts_util.c >+++ b/source3/libsmb/trusts_util.c >@@ -115,9 +115,12 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > struct trust_pw_change_state *state; > struct cli_credentials *creds = NULL; > const struct samr_Password *current_nt_hash = NULL; >+ const struct samr_Password *previous_nt_hash = NULL; > uint8_t num_nt_hashes = 0; >- const struct samr_Password *nt_hashes[1] = { NULL, }; >+ uint8_t idx = 0; >+ const struct samr_Password *nt_hashes[1+1] = { NULL, }; > uint8_t idx_nt_hashes = 0; >+ uint8_t idx_current = UINT8_MAX; > enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; > time_t pass_last_set_time; > uint32_t old_version = 0; >@@ -181,6 +184,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > TALLOC_FREE(frame); > return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; > } >+ previous_nt_hash = cli_credentials_get_old_nt_hash(creds, frame); > > old_version = cli_credentials_get_kvno(creds); > pass_last_set_time = cli_credentials_get_password_last_changed_time(creds); >@@ -266,15 +270,19 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > return status; > } > >- nt_hashes[0] = current_nt_hash; >- num_nt_hashes = 1; >+ idx_current = idx; >+ nt_hashes[idx++] = current_nt_hash; >+ if (previous_nt_hash != NULL) { >+ nt_hashes[idx++] = previous_nt_hash; >+ } >+ num_nt_hashes = idx; >+ >+ DEBUG(0,("%s : %s(%s): Verifying passwords remotely %s.\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain, context_name)); > > /* >- * We could use cli_credentials_get_old_nt_hash(creds, frame) to >- * set previous_nt_hash. >- * >- * But we want to check if the dc has our current password and only do >- * a change if that's the case. So we keep previous_nt_hash = NULL. >+ * Check which password the dc knows about. > * > * TODO: > * If the previous password is the only password in common with the dc, >@@ -287,12 +295,21 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > nt_hashes, > &idx_nt_hashes); > if (!NT_STATUS_IS_OK(status)) { >- DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old password - %s!\n", >- context_name, nt_errstr(status))); >+ DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old passwords (%u) - %s!\n", >+ context_name, num_nt_hashes, nt_errstr(status))); > TALLOC_FREE(frame); > return status; > } > >+ if (idx_nt_hashes != idx_current) { >+ DEBUG(0,("%s : %s(%s): Verified older password remotely " >+ "skip changing %s\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain, context_name)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; >+ } >+ > DEBUG(0,("%s : %s(%s): Verified old password remotely using %s\n", > current_timestring(talloc_tos(), false), > __func__, domain, context_name)); >@@ -380,8 +397,10 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > /* > * Now we verify the new password. > */ >- nt_hashes[0] = current_nt_hash; >- num_nt_hashes = 1; >+ idx = 0; >+ idx_current = idx; >+ nt_hashes[idx++] = current_nt_hash; >+ num_nt_hashes = idx; > status = netlogon_creds_cli_auth(context, b, > num_nt_hashes, > nt_hashes, >-- >1.9.1 > > >From 988cd50434b2ca7b65752424441b066fdb590e68 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 11:35:20 +0200 >Subject: [PATCH 45/56] lsa.idl: make lsa_DnsDomainInfo [public] > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit ea0798881a7aaf5897a3a3806149536d3d54fc3b) >--- > librpc/idl/lsa.idl | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/librpc/idl/lsa.idl b/librpc/idl/lsa.idl >index 66a07e5..6dda7dc 100644 >--- a/librpc/idl/lsa.idl >+++ b/librpc/idl/lsa.idl >@@ -367,7 +367,7 @@ import "misc.idl", "security.idl"; > uint8 log_is_full; > } lsa_AuditFullQueryInfo; > >- typedef struct { >+ typedef [public] struct { > /* it's important that we use the lsa_StringLarge here, > * because otherwise windows clients result with such dns hostnames > * e.g. w2k3-client.samba4.samba.orgsamba4.samba.org >-- >1.9.1 > > >From 9d80eaf76e4003bb957c8859727a106f74ade983 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 11:35:37 +0200 >Subject: [PATCH 46/56] netlogon.idl: make netr_TrustFlags [public] > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 60274475332dafdfb829a7c086ea09cd9ed00540) >--- > librpc/idl/netlogon.idl | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl >index 621d537..50ce15c 100644 >--- a/librpc/idl/netlogon.idl >+++ b/librpc/idl/netlogon.idl >@@ -1261,7 +1261,7 @@ interface netlogon > > /****************/ > /* Function 0x1d */ >- typedef [bitmap32bit] bitmap { >+ typedef [public,bitmap32bit] bitmap { > NETR_TRUST_FLAG_IN_FOREST = 0x00000001, > NETR_TRUST_FLAG_OUTBOUND = 0x00000002, > NETR_TRUST_FLAG_TREEROOT = 0x00000004, >-- >1.9.1 > > >From 9ee7f623aac1e2970b872f98e07a28e494a63f76 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 10:09:01 +0200 >Subject: [PATCH 47/56] netlogon.idl: use lsa_TrustType and lsa_TrustAttributes > in netr_trust_extension > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 28ac10503476de3c000b3deee2c1f67e0b305578) >--- > librpc/idl/netlogon.idl | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl >index 50ce15c..b56c825 100644 >--- a/librpc/idl/netlogon.idl >+++ b/librpc/idl/netlogon.idl >@@ -1369,8 +1369,8 @@ interface netlogon > [value(8)] uint32 size; > netr_TrustFlags flags; > uint32 parent_index; >- uint32 trust_type; >- uint32 trust_attributes; >+ lsa_TrustType trust_type; >+ lsa_TrustAttributes trust_attributes; > } netr_trust_extension; > > typedef struct { >-- >1.9.1 > > >From 4791ee44f5d5f7149da5f340cf5f33e442ee359b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 10:11:18 +0200 >Subject: [PATCH 48/56] secrets.idl: add secrets_domain_info that will be used > in secrets.tdb for machine account trusts > >This blob will be store in secrets.tdb. It makes it possible to store much >more useful details about the workstation trust. > >The key feature that that triggered this change is the ability >to store details for the next password change before doing >the remote change. This will allow us to recover from failures. > >While being there I also thought about possible new features, >which we may implement in the near future. > >We also store the raw UTF16 like cleartext buffer as well as derived >keys like the NTHASH (arcfour-hmac-md5 key) and other kerberos keys. >This will allow us to avoid recalculating the keys for an in memory >keytab in future. > >I also added pointer to an optional lsa_ForestTrustInformation structure, >which might be useful to implement multi-tenancy in future. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit a59c9cba31a801d90db06b767cfd44776f4ede77) >--- > source3/librpc/idl/secrets.idl | 92 +++++++++++++++++++++++++++++++++++++++++- > source3/librpc/wscript_build | 2 +- > 2 files changed, 92 insertions(+), 2 deletions(-) > >diff --git a/source3/librpc/idl/secrets.idl b/source3/librpc/idl/secrets.idl >index 1d0ba19..2c06fa6 100644 >--- a/source3/librpc/idl/secrets.idl >+++ b/source3/librpc/idl/secrets.idl >@@ -1,6 +1,6 @@ > #include "idl_types.h" > >-import "security.idl"; >+import "misc.idl", "samr.idl", "lsa.idl", "netlogon.idl", "security.idl"; > > /* > IDL structures for secrets code >@@ -37,5 +37,95 @@ import "security.idl"; > security_descriptor *sd; > } lsa_secret; > >+ /* >+ * This is the on-disc format the workstation trust. >+ * >+ * DO NOT CHANGE >+ * without changing secrets_domain_info_version >+ * and adding glue code. Discuss on samba-technical >+ * first! >+ */ >+ typedef struct { >+ uint32 keytype; >+ uint32 iteration_count; >+ [flag(NDR_SECRET)] DATA_BLOB value; >+ } secrets_domain_info1_kerberos_key; >+ >+ typedef struct { >+ NTTIME change_time; >+ [string,charset(UTF16)] uint16 change_server[]; >+ >+ [flag(NDR_SECRET)] DATA_BLOB cleartext_blob; >+ [flag(NDR_SECRET)] samr_Password nt_hash; >+ >+ [string,charset(UTF16)] uint16 *salt_data; >+ uint32 default_iteration_count; >+ uint16 num_keys; >+ secrets_domain_info1_kerberos_key keys[num_keys]; >+ } secrets_domain_info1_password; >+ >+ typedef struct { >+ NTSTATUS local_status; >+ NTSTATUS remote_status; >+ NTTIME change_time; >+ [string,charset(UTF16)] uint16 change_server[]; >+ [ref] secrets_domain_info1_password *password; >+ } secrets_domain_info1_change; >+ >+ typedef [public] struct { >+ [value(0)] hyper reserved_flags; >+ >+ NTTIME join_time; >+ >+ [string,charset(UTF16)] uint16 computer_name[]; >+ [string,charset(UTF16)] uint16 account_name[]; >+ netr_SchannelType secure_channel_type; >+ >+ lsa_DnsDomainInfo domain_info; >+ netr_TrustFlags trust_flags; >+ lsa_TrustType trust_type; >+ lsa_TrustAttributes trust_attributes; >+ >+ /* >+ * This is unused currently, it might >+ * be useful to implement multi-tenancy (joining multiple domains) >+ * in future. >+ * >+ * Or we could use it to do other filtering of domains. >+ */ >+ [value(NULL)] lsa_ForestTrustInformation *reserved_routing; >+ >+ kerb_EncTypes supported_enc_types; >+ [string,charset(UTF16)] uint16 *salt_principal; >+ >+ NTTIME password_last_change; >+ hyper password_changes; >+ secrets_domain_info1_change *next_change; >+ >+ [ref] secrets_domain_info1_password *password; >+ secrets_domain_info1_password *old_password; >+ secrets_domain_info1_password *older_password; >+ } secrets_domain_info1; >+ >+ typedef [v1_enum] enum { >+ SECRETS_DOMAIN_INFO_VERSION_1 = 0x00000001 >+ } secrets_domain_info_version; >+ >+ /* >+ * If we ever need to change this we need to >+ * change secrets_domain_info into >+ * secrets_domain_info_v1 >+ */ >+ typedef union { >+ [case(SECRETS_DOMAIN_INFO_VERSION_1)] >+ secrets_domain_info1 *info1; >+ [default]; >+ } secrets_domain_infoU; >+ >+ typedef [public] struct { >+ secrets_domain_info_version version; >+ [value(0)] uint32 reserved; >+ [switch_is(version)] secrets_domain_infoU info; >+ } secrets_domain_infoB; > } > >diff --git a/source3/librpc/wscript_build b/source3/librpc/wscript_build >index 1d8c17b..9260350 100644 >--- a/source3/librpc/wscript_build >+++ b/source3/librpc/wscript_build >@@ -27,7 +27,7 @@ bld.SAMBA3_SUBSYSTEM('NDR_LEASES_DB', > > bld.SAMBA3_SUBSYSTEM('NDR_SECRETS', > source='gen_ndr/ndr_secrets.c', >- public_deps='ndr NDR_SECURITY' >+ public_deps='ndr NDR_SAMR NDR_LSA NDR_NETLOGON NDR_SECURITY' > ) > > bld.SAMBA3_SUBSYSTEM('NDR_PERFCOUNT', >-- >1.9.1 > > >From fba8f124c95f800c207f944f421f4484fb76f1d5 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 May 2017 16:28:17 +0200 >Subject: [PATCH 49/56] s3:secrets: add infrastructure to use > secrets_domain_infoB to store credentials > >We now store various hashed keys at change time and maintain a lot of details >that will help debugging failed password changes. > >We keep storing the legacy values: > SECRETS/SID/ > SECRETS/DOMGUID/ > SECRETS/MACHINE_LAST_CHANGE_TIME/ > SECRETS/MACHINE_PASSWORD/ > SECRETS/MACHINE_PASSWORD.PREV/ > SECRETS/SALTING_PRINCIPAL/DES/ > >This allows downgrades to older Samba versions. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 5f0038fba612afd7fc15b7ab321df979891170d8) >--- > source3/include/secrets.h | 28 + > source3/passdb/machine_account_secrets.c | 1391 ++++++++++++++++++++++++++++++ > 2 files changed, 1419 insertions(+) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index fc8e118..0363b6b 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -29,6 +29,7 @@ > #define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME" > #define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE" > #define SECRETS_MACHINE_TRUST_ACCOUNT_NAME "SECRETS/SECRETS_MACHINE_TRUST_ACCOUNT_NAME" >+#define SECRETS_MACHINE_DOMAIN_INFO "SECRETS/MACHINE_DOMAIN_INFO" > /* this one is for storing trusted domain account password */ > #define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC" > >@@ -110,6 +111,33 @@ bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd, > struct dom_sid *sid, time_t *pass_last_set_time); > bool secrets_store_trusted_domain_password(const char* domain, const char* pwd, > const struct dom_sid *sid); >+struct libnet_JoinCtx; >+NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r); >+struct secrets_domain_info1; >+struct secrets_domain_info1_change; >+void secrets_debug_domain_info(int lvl, const struct secrets_domain_info1 *info, >+ const char *name); >+char *secrets_domain_info_string(TALLOC_CTX *mem_ctx, const struct secrets_domain_info1 *info1, >+ const char *name, bool include_secrets); >+NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pinfo); >+NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, >+ const char *cleartext_unix, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pinfo, >+ struct secrets_domain_info1_change **pprev); >+NTSTATUS secrets_failed_password_change(const char *change_server, >+ NTSTATUS local_status, >+ NTSTATUS remote_status, >+ const struct secrets_domain_info1 *info); >+NTSTATUS secrets_defer_password_change(const char *change_server, >+ NTSTATUS local_status, >+ NTSTATUS remote_status, >+ const struct secrets_domain_info1 *info); >+NTSTATUS secrets_finish_password_change(const char *change_server, >+ NTTIME change_time, >+ const struct secrets_domain_info1 *info); > bool secrets_delete_machine_password_ex(const char *domain, const char *realm); > bool secrets_delete_domain_sid(const char *domain); > bool secrets_store_machine_password(const char *pass, const char *domain, enum netr_SchannelType sec_channel); >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index 9a96a3f..b88fbe9 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -31,9 +31,17 @@ > #include "util_tdb.h" > #include "libcli/security/security.h" > >+#include "librpc/gen_ndr/libnet_join.h" >+#include "librpc/gen_ndr/ndr_secrets.h" >+#include "lib/crypto/crypto.h" >+#include "lib/krb5_wrap/krb5_samba.h" >+#include "lib/util/time_basic.h" >+ > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_PASSDB > >+static char *domain_info_keystr(const char *domain); >+ > static char *des_salt_key(const char *realm); > > /** >@@ -379,6 +387,12 @@ bool secrets_delete_machine_password_ex(const char *domain, const char *realm) > const char *tmpkey = NULL; > bool ok; > >+ tmpkey = domain_info_keystr(domain); >+ ok = secrets_delete(tmpkey); >+ if (!ok) { >+ return false; >+ } >+ > if (realm != NULL) { > tmpkey = des_salt_key(domain); > ok = secrets_delete(tmpkey); >@@ -735,3 +749,1380 @@ char *secrets_fetch_machine_password(const char *domain, > > return ret; > } >+ >+static char *domain_info_keystr(const char *domain) >+{ >+ char *keystr; >+ >+ keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s", >+ SECRETS_MACHINE_DOMAIN_INFO, >+ domain); >+ SMB_ASSERT(keystr != NULL); >+ return keystr; >+} >+ >+/************************************************************************ >+ Routine to get account password to trusted domain >+************************************************************************/ >+ >+static NTSTATUS secrets_fetch_domain_info1_by_key(const char *key, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **_info1) >+{ >+ struct secrets_domain_infoB sdib = { .version = 0, }; >+ enum ndr_err_code ndr_err; >+ /* unpacking structures */ >+ DATA_BLOB blob; >+ >+ /* fetching trusted domain password structure */ >+ blob.data = (uint8_t *)secrets_fetch(key, &blob.length); >+ if (blob.data == NULL) { >+ DBG_NOTICE("secrets_fetch failed!\n"); >+ return NT_STATUS_OBJECT_NAME_NOT_FOUND; >+ } >+ >+ /* unpack trusted domain password */ >+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sdib, >+ (ndr_pull_flags_fn_t)ndr_pull_secrets_domain_infoB); >+ SAFE_FREE(blob.data); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ DBG_ERR("ndr_pull_struct_blob failed - %s!\n", >+ ndr_errstr(ndr_err)); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ >+ if (sdib.version != SECRETS_DOMAIN_INFO_VERSION_1) { >+ DBG_ERR("sdib.version = %u\n", (unsigned)sdib.version); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ >+ *_info1 = sdib.info.info1; >+ return NT_STATUS_OK;; >+} >+ >+static NTSTATUS secrets_fetch_domain_info(const char *domain, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pinfo) >+{ >+ char *key = domain_info_keystr(domain); >+ return secrets_fetch_domain_info1_by_key(key, mem_ctx, pinfo); >+} >+ >+void secrets_debug_domain_info(int lvl, const struct secrets_domain_info1 *info1, >+ const char *name) >+{ >+ struct secrets_domain_infoB sdib = { >+ .version = SECRETS_DOMAIN_INFO_VERSION_1, >+ }; >+ >+ sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1); >+ >+ ndr_print_debug((ndr_print_fn_t)ndr_print_secrets_domain_infoB, >+ name, &sdib); >+} >+ >+char *secrets_domain_info_string(TALLOC_CTX *mem_ctx, const struct secrets_domain_info1 *info1, >+ const char *name, bool include_secrets) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct secrets_domain_infoB sdib = { >+ .version = SECRETS_DOMAIN_INFO_VERSION_1, >+ }; >+ struct ndr_print *ndr = NULL; >+ char *ret = NULL; >+ >+ sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1); >+ >+ ndr = talloc_zero(frame, struct ndr_print); >+ if (ndr == NULL) { >+ TALLOC_FREE(frame); >+ return NULL; >+ } >+ ndr->private_data = talloc_strdup(ndr, ""); >+ if (ndr->private_data == NULL) { >+ TALLOC_FREE(frame); >+ return NULL; >+ } >+ ndr->print = ndr_print_string_helper; >+ ndr->depth = 1; >+ ndr->print_secrets = include_secrets; >+ >+ ndr_print_secrets_domain_infoB(ndr, name, &sdib); >+ ret = talloc_steal(mem_ctx, (char *)ndr->private_data); >+ TALLOC_FREE(frame); >+ return ret; >+} >+ >+static NTSTATUS secrets_store_domain_info1_by_key(const char *key, >+ const struct secrets_domain_info1 *info1) >+{ >+ struct secrets_domain_infoB sdib = { >+ .version = SECRETS_DOMAIN_INFO_VERSION_1, >+ }; >+ /* packing structures */ >+ DATA_BLOB blob; >+ enum ndr_err_code ndr_err; >+ bool ok; >+ >+ sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1); >+ >+ ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &sdib, >+ (ndr_push_flags_fn_t)ndr_push_secrets_domain_infoB); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ return ndr_map_error2ntstatus(ndr_err); >+ } >+ >+ ok = secrets_store(key, blob.data, blob.length); >+ data_blob_clear_free(&blob); >+ if (!ok) { >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS secrets_store_domain_info(const struct secrets_domain_info1 *info) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ const char *domain = info->domain_info.name.string; >+ const char *realm = info->domain_info.dns_domain.string; >+ char *key = domain_info_keystr(domain); >+ struct db_context *db = NULL; >+ struct timeval last_change_tv; >+ const DATA_BLOB *cleartext_blob = NULL; >+ DATA_BLOB pw_blob = data_blob_null; >+ DATA_BLOB old_pw_blob = data_blob_null; >+ const char *pw = NULL; >+ const char *old_pw = NULL; >+ bool ok; >+ NTSTATUS status; >+ int ret; >+ int role = lp_server_role(); >+ >+ switch (info->secure_channel_type) { >+ case SEC_CHAN_WKSTA: >+ case SEC_CHAN_BDC: >+ if (role >= ROLE_ACTIVE_DIRECTORY_DC) { >+ DBG_ERR("AD_DC not supported for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ break; >+ default: >+ DBG_ERR("SEC_CHAN_* not supported for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ ok = secrets_clear_domain_protection(domain); >+ if (!ok) { >+ DBG_ERR("secrets_clear_domain_protection(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ >+ ok = secrets_delete_machine_password_ex(domain, realm); >+ if (!ok) { >+ DBG_ERR("secrets_delete_machine_password_ex(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ >+ status = secrets_store_domain_info1_by_key(key, info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info1_by_key() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * We use info->password_last_change instead >+ * of info->password.change_time because >+ * we may want to defer the next change approach >+ * if the server rejected the change the last time, >+ * e.g. due to RefusePasswordChange=1. >+ */ >+ nttime_to_timeval(&last_change_tv, info->password_last_change); >+ >+ cleartext_blob = &info->password->cleartext_blob; >+ ok = convert_string_talloc(frame, CH_UTF16MUNGED, CH_UNIX, >+ cleartext_blob->data, >+ cleartext_blob->length, >+ (void **)&pw_blob.data, >+ &pw_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " >+ "failed for pw of %s - %s\n", >+ domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ pw = (const char *)pw_blob.data; >+ if (info->old_password != NULL) { >+ cleartext_blob = &info->old_password->cleartext_blob; >+ ok = convert_string_talloc(frame, CH_UTF16MUNGED, CH_UNIX, >+ cleartext_blob->data, >+ cleartext_blob->length, >+ (void **)&old_pw_blob.data, >+ &old_pw_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " >+ "failed for old_pw of %s - %s\n", >+ domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ data_blob_clear_free(&pw_blob); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ old_pw = (const char *)old_pw_blob.data; >+ } >+ >+ ok = secrets_store_machine_pw_sync(pw, old_pw, >+ domain, realm, >+ info->salt_principal, >+ info->supported_enc_types, >+ info->domain_info.sid, >+ last_change_tv.tv_sec, >+ info->secure_channel_type, >+ false); /* delete_join */ >+ data_blob_clear_free(&pw_blob); >+ data_blob_clear_free(&old_pw_blob); >+ if (!ok) { >+ DBG_ERR("secrets_store_machine_pw_sync(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ >+ if (!GUID_all_zero(&info->domain_info.domain_guid)) { >+ ok = secrets_store_domain_guid(domain, >+ &info->domain_info.domain_guid); >+ if (!ok) { >+ DBG_ERR("secrets_store_domain_guid(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ } >+ >+ ok = secrets_mark_domain_protected(domain); >+ if (!ok) { >+ DBG_ERR("secrets_mark_domain_protected(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >+ >+static int secrets_domain_info_kerberos_keys(struct secrets_domain_info1_password *p, >+ const char *salt_principal) >+{ >+#ifdef HAVE_ADS >+ krb5_error_code krb5_ret; >+ krb5_context krb5_ctx = NULL; >+ DATA_BLOB cleartext_utf8_b = data_blob_null; >+ krb5_data cleartext_utf8; >+ krb5_data salt; >+ krb5_keyblock key; >+ DATA_BLOB aes_256_b = data_blob_null; >+ DATA_BLOB aes_128_b = data_blob_null; >+ DATA_BLOB des_md5_b = data_blob_null; >+ bool ok; >+#endif /* HAVE_ADS */ >+ DATA_BLOB arc4_b = data_blob_null; >+ const uint16_t max_keys = 4; >+ struct secrets_domain_info1_kerberos_key *keys = NULL; >+ uint16_t idx = 0; >+ char *salt_data = NULL; >+ >+ /* >+ * We calculate: >+ * ENCTYPE_AES256_CTS_HMAC_SHA1_96 >+ * ENCTYPE_AES128_CTS_HMAC_SHA1_96 >+ * ENCTYPE_ARCFOUR_HMAC >+ * ENCTYPE_DES_CBC_MD5 >+ * >+ * We don't include ENCTYPE_DES_CBC_CRC >+ * as W2008R2 also doesn't store it anymore. >+ * >+ * Note we store all enctypes we support, >+ * including the weak encryption types, >+ * but that's no problem as we also >+ * store the cleartext password anyway. >+ * >+ * Which values are then used to construct >+ * a keytab is configured at runtime and the >+ * configuration of msDS-SupportedEncryptionTypes. >+ * >+ * If we don't have kerberos support or no >+ * salt, we only generate an entry for arcfour-hmac-md5. >+ */ >+ keys = talloc_zero_array(p, >+ struct secrets_domain_info1_kerberos_key, >+ max_keys); >+ if (keys == NULL) { >+ return ENOMEM; >+ } >+ >+ arc4_b = data_blob_talloc(keys, >+ p->nt_hash.hash, >+ sizeof(p->nt_hash.hash)); >+ if (arc4_b.data == NULL) { >+ DBG_ERR("data_blob_talloc failed for arcfour-hmac-md5.\n"); >+ TALLOC_FREE(keys); >+ return ENOMEM; >+ } >+ >+#ifdef HAVE_ADS >+ if (salt_principal == NULL) { >+ goto no_kerberos; >+ } >+ >+ initialize_krb5_error_table(); >+ krb5_ret = krb5_init_context(&krb5_ctx); >+ if (krb5_ret != 0) { >+ TALLOC_FREE(keys); >+ return krb5_ret; >+ } >+ >+ krb5_ret = smb_krb5_salt_principal2data(krb5_ctx, salt_principal, >+ p, &salt_data); >+ if (krb5_ret != 0) { >+ DBG_ERR("smb_krb5_salt_principal2data(%s) failed: %s\n", >+ salt_principal, >+ smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys)); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ return krb5_ret; >+ } >+ >+ salt.data = discard_const(salt_data); >+ salt.length = strlen(salt_data); >+ >+ ok = convert_string_talloc(keys, CH_UTF16MUNGED, CH_UTF8, >+ p->cleartext_blob.data, >+ p->cleartext_blob.length, >+ (void **)&cleartext_utf8_b.data, >+ &cleartext_utf8_b.length); >+ if (!ok) { >+ if (errno != 0) { >+ krb5_ret = errno; >+ } else { >+ krb5_ret = EINVAL; >+ } >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ return krb5_ret; >+ } >+ cleartext_utf8.data = (void *)cleartext_utf8_b.data; >+ cleartext_utf8.length = cleartext_utf8_b.length; >+ >+ krb5_ret = smb_krb5_create_key_from_string(krb5_ctx, >+ NULL, >+ &salt, >+ &cleartext_utf8, >+ ENCTYPE_AES256_CTS_HMAC_SHA1_96, >+ &key); >+ if (krb5_ret != 0) { >+ DBG_ERR("generation of a aes256-cts-hmac-sha1-96 key failed: %s\n", >+ smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys)); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return krb5_ret; >+ } >+ aes_256_b = data_blob_talloc(keys, >+ KRB5_KEY_DATA(&key), >+ KRB5_KEY_LENGTH(&key)); >+ krb5_free_keyblock_contents(krb5_ctx, &key); >+ if (aes_256_b.data == NULL) { >+ DBG_ERR("data_blob_talloc failed for aes-256.\n"); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return ENOMEM; >+ } >+ >+ krb5_ret = smb_krb5_create_key_from_string(krb5_ctx, >+ NULL, >+ &salt, >+ &cleartext_utf8, >+ ENCTYPE_AES128_CTS_HMAC_SHA1_96, >+ &key); >+ if (krb5_ret != 0) { >+ DBG_ERR("generation of a aes128-cts-hmac-sha1-96 key failed: %s\n", >+ smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys)); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return krb5_ret; >+ } >+ aes_128_b = data_blob_talloc(keys, >+ KRB5_KEY_DATA(&key), >+ KRB5_KEY_LENGTH(&key)); >+ krb5_free_keyblock_contents(krb5_ctx, &key); >+ if (aes_128_b.data == NULL) { >+ DBG_ERR("data_blob_talloc failed for aes-128.\n"); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return ENOMEM; >+ } >+ >+ krb5_ret = smb_krb5_create_key_from_string(krb5_ctx, >+ NULL, >+ &salt, >+ &cleartext_utf8, >+ ENCTYPE_DES_CBC_MD5, >+ &key); >+ if (krb5_ret != 0) { >+ DBG_ERR("generation of a des-cbc-md5 key failed: %s\n", >+ smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys)); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return krb5_ret; >+ } >+ des_md5_b = data_blob_talloc(keys, >+ KRB5_KEY_DATA(&key), >+ KRB5_KEY_LENGTH(&key)); >+ krb5_free_keyblock_contents(krb5_ctx, &key); >+ if (des_md5_b.data == NULL) { >+ DBG_ERR("data_blob_talloc failed for des-cbc-md5.\n"); >+ krb5_free_context(krb5_ctx); >+ TALLOC_FREE(keys); >+ TALLOC_FREE(salt_data); >+ return ENOMEM; >+ } >+ >+ krb5_free_context(krb5_ctx); >+no_kerberos: >+ >+ if (aes_256_b.length != 0) { >+ keys[idx].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; >+ keys[idx].iteration_count = 4096; >+ keys[idx].value = aes_256_b; >+ idx += 1; >+ } >+ >+ if (aes_128_b.length != 0) { >+ keys[idx].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; >+ keys[idx].iteration_count = 4096; >+ keys[idx].value = aes_128_b; >+ idx += 1; >+ } >+ >+#endif /* HAVE_ADS */ >+ >+ keys[idx].keytype = ENCTYPE_ARCFOUR_HMAC; >+ keys[idx].iteration_count = 4096; >+ keys[idx].value = arc4_b; >+ idx += 1; >+ >+#ifdef HAVE_ADS >+ if (des_md5_b.length != 0) { >+ keys[idx].keytype = ENCTYPE_DES_CBC_MD5; >+ keys[idx].iteration_count = 4096; >+ keys[idx].value = des_md5_b; >+ idx += 1; >+ } >+#endif /* HAVE_ADS */ >+ >+ p->salt_data = salt_data; >+ p->default_iteration_count = 4096; >+ p->num_keys = idx; >+ p->keys = keys; >+ return 0; >+} >+ >+static NTSTATUS secrets_domain_info_password_create(TALLOC_CTX *mem_ctx, >+ const char *cleartext_unix, >+ const char *salt_principal, >+ NTTIME change_time, >+ const char *change_server, >+ struct secrets_domain_info1_password **_p) >+{ >+ struct secrets_domain_info1_password *p = NULL; >+ bool ok; >+ size_t len; >+ int ret; >+ >+ if (change_server == NULL) { >+ return NT_STATUS_INVALID_PARAMETER_MIX; >+ } >+ >+ p = talloc_zero(mem_ctx, struct secrets_domain_info1_password); >+ if (p == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ p->change_time = change_time; >+ p->change_server = talloc_strdup(p, change_server); >+ if (p->change_server == NULL) { >+ TALLOC_FREE(p); >+ return NT_STATUS_NO_MEMORY; >+ } >+ len = strlen(cleartext_unix); >+ ok = convert_string_talloc(p, CH_UNIX, CH_UTF16, >+ cleartext_unix, len, >+ (void **)&p->cleartext_blob.data, >+ &p->cleartext_blob.length); >+ if (!ok) { >+ NTSTATUS status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ TALLOC_FREE(p); >+ return status; >+ } >+ mdfour(p->nt_hash.hash, >+ p->cleartext_blob.data, >+ p->cleartext_blob.length); >+ >+ ret = secrets_domain_info_kerberos_keys(p, salt_principal); >+ if (ret != 0) { >+ NTSTATUS status = krb5_to_nt_status(ret); >+ TALLOC_FREE(p); >+ return status; >+ } >+ >+ *_p = p; >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pinfo) >+{ >+ TALLOC_CTX *frame = NULL; >+ struct secrets_domain_info1 *old = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ const char *dns_domain = NULL; >+ const char *server = NULL; >+ struct db_context *db = NULL; >+ time_t last_set_time; >+ NTTIME last_set_nt; >+ enum netr_SchannelType channel; >+ char *pw = NULL; >+ char *old_pw = NULL; >+ struct dom_sid domain_sid; >+ struct GUID domain_guid; >+ bool ok; >+ NTSTATUS status; >+ int ret; >+ >+ ok = strequal(domain, lp_workgroup()); >+ if (ok) { >+ dns_domain = lp_dnsdomain(); >+ >+ if (dns_domain != NULL && dns_domain[0] == '\0') { >+ dns_domain = NULL; >+ } >+ } >+ >+ last_set_time = secrets_fetch_pass_last_set_time(domain); >+ if (last_set_time == 0) { >+ return NT_STATUS_OK; >+ } >+ unix_to_nt_time(&last_set_nt, last_set_time); >+ >+ frame = talloc_stackframe(); >+ >+ status = secrets_fetch_domain_info(domain, frame, &old); >+ if (NT_STATUS_IS_OK(status)) { >+ if (old->password_last_change >= last_set_nt) { >+ *pinfo = talloc_move(mem_ctx, &old); >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+ } >+ TALLOC_FREE(old); >+ } >+ >+ info = talloc_zero(frame, struct secrets_domain_info1); >+ if (info == NULL) { >+ DBG_ERR("talloc_zero failed\n"); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ pw = secrets_fetch_machine_password(domain, >+ &last_set_time, >+ &channel); >+ if (pw == NULL) { >+ DBG_ERR("secrets_fetch_machine_password(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ unix_to_nt_time(&last_set_nt, last_set_time); >+ >+ old_pw = secrets_fetch_prev_machine_password(domain); >+ >+ ok = secrets_fetch_domain_sid(domain, &domain_sid); >+ if (!ok) { >+ DBG_ERR("secrets_fetch_domain_sid(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; >+ } >+ >+ ok = secrets_fetch_domain_guid(domain, &domain_guid); >+ if (!ok) { >+ domain_guid = GUID_zero(); >+ } >+ >+ info->computer_name = lp_netbios_name(); >+ info->account_name = talloc_asprintf(frame, "%s$", info->computer_name); >+ if (info->account_name == NULL) { >+ DBG_ERR("talloc_asprintf(%s$) failed\n", info->computer_name); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ info->secure_channel_type = channel; >+ >+ info->domain_info.name.string = domain; >+ info->domain_info.dns_domain.string = dns_domain; >+ info->domain_info.dns_forest.string = dns_domain; >+ info->domain_info.domain_guid = domain_guid; >+ info->domain_info.sid = &domain_sid; >+ >+ info->trust_flags = NETR_TRUST_FLAG_PRIMARY; >+ info->trust_flags |= NETR_TRUST_FLAG_OUTBOUND; >+ >+ if (dns_domain != NULL) { >+ /* >+ * We just assume all AD domains are >+ * NETR_TRUST_FLAG_NATIVE these days. >+ * >+ * This isn't used anyway for now. >+ */ >+ info->trust_flags |= NETR_TRUST_FLAG_NATIVE; >+ >+ info->trust_type = LSA_TRUST_TYPE_UPLEVEL; >+ >+ server = info->domain_info.dns_domain.string; >+ } else { >+ info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL; >+ >+ server = talloc_asprintf(info, >+ "%s#%02X", >+ domain, >+ NBT_NAME_PDC); >+ if (server == NULL) { >+ DBG_ERR("talloc_asprintf(%s#%02X) failed\n", >+ domain, NBT_NAME_PDC); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ } >+ info->trust_attributes = LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL; >+ >+ info->join_time = 0; >+ >+ /* >+ * We don't have enough information about the configured >+ * enctypes. >+ */ >+ info->supported_enc_types = 0; >+ info->salt_principal = NULL; >+ if (info->trust_type == LSA_TRUST_TYPE_UPLEVEL) { >+ char *p = NULL; >+ >+ p = kerberos_secrets_fetch_salt_princ(); >+ if (p == NULL) { >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ info->salt_principal = talloc_strdup(info, p); >+ SAFE_FREE(p); >+ if (info->salt_principal == NULL) { >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ } >+ >+ info->password_last_change = last_set_nt; >+ info->password_changes = 1; >+ info->next_change = NULL; >+ >+ status = secrets_domain_info_password_create(info, >+ pw, >+ info->salt_principal, >+ last_set_nt, server, >+ &info->password); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_domain_info_password_create(pw) failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * After a join we don't have old passwords. >+ */ >+ if (old_pw != NULL) { >+ status = secrets_domain_info_password_create(info, >+ old_pw, >+ info->salt_principal, >+ 0, server, >+ &info->old_password); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_domain_info_password_create(old) failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ info->password_changes += 1; >+ } else { >+ info->old_password = NULL; >+ } >+ info->older_password = NULL; >+ >+ secrets_debug_domain_info(DBGLVL_INFO, info, "upgrade"); >+ >+ status = secrets_store_domain_info(info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * We now reparse it. >+ */ >+ status = secrets_fetch_domain_info(domain, frame, &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_fetch_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ *pinfo = talloc_move(mem_ctx, &info); >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct secrets_domain_info1 *old = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ struct db_context *db = NULL; >+ struct timeval tv = timeval_current(); >+ NTTIME now = timeval_to_nttime(&tv); >+ const char *domain = r->out.netbios_domain_name; >+ NTSTATUS status; >+ int ret; >+ >+ info = talloc_zero(frame, struct secrets_domain_info1); >+ if (info == NULL) { >+ DBG_ERR("talloc_zero failed\n"); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ info->computer_name = r->in.machine_name; >+ info->account_name = r->out.account_name; >+ info->secure_channel_type = r->in.secure_channel_type; >+ >+ info->domain_info.name.string = >+ r->out.netbios_domain_name; >+ info->domain_info.dns_domain.string = >+ r->out.dns_domain_name; >+ info->domain_info.dns_forest.string = >+ r->out.forest_name; >+ info->domain_info.domain_guid = r->out.domain_guid; >+ info->domain_info.sid = r->out.domain_sid; >+ >+ info->trust_flags = NETR_TRUST_FLAG_PRIMARY; >+ info->trust_flags |= NETR_TRUST_FLAG_OUTBOUND; >+ if (r->out.domain_is_ad) { >+ /* >+ * We just assume all AD domains are >+ * NETR_TRUST_FLAG_NATIVE these days. >+ * >+ * This isn't used anyway for now. >+ */ >+ info->trust_flags |= NETR_TRUST_FLAG_NATIVE; >+ >+ info->trust_type = LSA_TRUST_TYPE_UPLEVEL; >+ } else { >+ info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL; >+ } >+ info->trust_attributes = LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL; >+ >+ info->join_time = now; >+ >+ info->supported_enc_types = r->out.set_encryption_types; >+ info->salt_principal = r->out.krb5_salt; >+ >+ if (info->salt_principal == NULL && r->out.domain_is_ad) { >+ char *p = NULL; >+ >+ ret = smb_krb5_salt_principal(info->domain_info.dns_domain.string, >+ info->account_name, >+ NULL /* userPrincipalName */, >+ true /* is_computer */, >+ info, &p); >+ if (ret != 0) { >+ status = krb5_to_nt_status(ret); >+ DBG_ERR("smb_krb5_salt_principal() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ info->salt_principal = p; >+ } >+ >+ info->password_last_change = now; >+ info->password_changes = 1; >+ info->next_change = NULL; >+ >+ status = secrets_domain_info_password_create(info, >+ r->in.machine_password, >+ info->salt_principal, >+ now, r->in.dc_name, >+ &info->password); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_domain_info_password_create(pw) failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ status = secrets_fetch_or_upgrade_domain_info(domain, frame, &old); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) { >+ DBG_DEBUG("no old join for domain(%s) available\n", >+ domain); >+ old = NULL; >+ } else if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_fetch_or_upgrade_domain_info(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * We reuse values from an old join, so that >+ * we still accept already granted kerberos tickets. >+ */ >+ if (old != NULL) { >+ info->old_password = old->password; >+ info->older_password = old->old_password; >+ } >+ >+ secrets_debug_domain_info(DBGLVL_INFO, info, "join"); >+ >+ status = secrets_store_domain_info(info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, >+ const char *cleartext_unix, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pinfo, >+ struct secrets_domain_info1_change **pprev) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct db_context *db = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ struct secrets_domain_info1_change *prev = NULL; >+ struct secrets_domain_info1_change *next = NULL; >+ struct timeval tv = timeval_current(); >+ NTTIME now = timeval_to_nttime(&tv); >+ NTSTATUS status; >+ int ret; >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ status = secrets_fetch_or_upgrade_domain_info(domain, frame, &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_fetch_or_upgrade_domain_info(%s) failed\n", >+ domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ prev = info->next_change; >+ info->next_change = NULL; >+ >+ next = talloc_zero(frame, struct secrets_domain_info1_change); >+ if (next == NULL) { >+ DBG_ERR("talloc_zero failed\n"); >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ if (prev != NULL) { >+ *next = *prev; >+ } else { >+ status = secrets_domain_info_password_create(next, >+ cleartext_unix, >+ info->salt_principal, >+ now, dcname, >+ &next->password); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_domain_info_password_create(next) failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ } >+ >+ next->local_status = NT_STATUS_OK; >+ next->remote_status = NT_STATUS_NOT_COMMITTED; >+ next->change_time = now; >+ next->change_server = dcname; >+ >+ info->next_change = next; >+ >+ secrets_debug_domain_info(DBGLVL_INFO, info, "prepare_change"); >+ >+ status = secrets_store_domain_info(info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * We now reparse it. >+ */ >+ status = secrets_fetch_domain_info(domain, frame, &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_fetch_domain_info(%s) failed\n", domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ *pinfo = talloc_move(mem_ctx, &info); >+ if (prev != NULL) { >+ *pprev = talloc_move(mem_ctx, &prev); >+ } else { >+ *pprev = NULL; >+ } >+ >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS secrets_check_password_change(const struct secrets_domain_info1 *cookie, >+ TALLOC_CTX *mem_ctx, >+ struct secrets_domain_info1 **pstored) >+{ >+ const char *domain = cookie->domain_info.name.string; >+ struct secrets_domain_info1 *stored = NULL; >+ struct secrets_domain_info1_change *sn = NULL; >+ struct secrets_domain_info1_change *cn = NULL; >+ NTSTATUS status; >+ int cmp; >+ >+ if (cookie->next_change == NULL) { >+ DBG_ERR("cookie->next_change == NULL for %s.\n", domain); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ if (cookie->next_change->password == NULL) { >+ DBG_ERR("cookie->next_change->password == NULL for %s.\n", domain); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ if (cookie->password == NULL) { >+ DBG_ERR("cookie->password == NULL for %s.\n", domain); >+ return NT_STATUS_INTERNAL_ERROR; >+ } >+ >+ /* >+ * Here we check that the given strucure still contains the >+ * same secrets_domain_info1_change as currently stored. >+ * >+ * There's always a gap between secrets_prepare_password_change() >+ * and the callers of secrets_check_password_change(). >+ */ >+ >+ status = secrets_fetch_domain_info(domain, mem_ctx, &stored); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_fetch_domain_info(%s) failed\n", domain); >+ return status; >+ } >+ >+ if (stored->next_change == NULL) { >+ /* >+ * We hit a race..., the administrator >+ * rejoined or something similar happened. >+ */ >+ DBG_ERR("stored->next_change == NULL for %s.\n", domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ if (stored->password_last_change != cookie->password_last_change) { >+ struct timeval store_tv; >+ struct timeval_buf store_buf; >+ struct timeval cookie_tv; >+ struct timeval_buf cookie_buf; >+ >+ nttime_to_timeval(&store_tv, stored->password_last_change); >+ nttime_to_timeval(&cookie_tv, cookie->password_last_change); >+ >+ DBG_ERR("password_last_change differs %s != %s for %s.\n", >+ timeval_str_buf(&store_tv, false, false, &store_buf), >+ timeval_str_buf(&cookie_tv, false, false, &cookie_buf), >+ domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ sn = stored->next_change; >+ cn = cookie->next_change; >+ >+ if (sn->change_time != cn->change_time) { >+ struct timeval store_tv; >+ struct timeval_buf store_buf; >+ struct timeval cookie_tv; >+ struct timeval_buf cookie_buf; >+ >+ nttime_to_timeval(&store_tv, sn->change_time); >+ nttime_to_timeval(&cookie_tv, cn->change_time); >+ >+ DBG_ERR("next change_time differs %s != %s for %s.\n", >+ timeval_str_buf(&store_tv, false, false, &store_buf), >+ timeval_str_buf(&cookie_tv, false, false, &cookie_buf), >+ domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ if (sn->password->change_time != cn->password->change_time) { >+ struct timeval store_tv; >+ struct timeval_buf store_buf; >+ struct timeval cookie_tv; >+ struct timeval_buf cookie_buf; >+ >+ nttime_to_timeval(&store_tv, sn->password->change_time); >+ nttime_to_timeval(&cookie_tv, cn->password->change_time); >+ >+ DBG_ERR("next password.change_time differs %s != %s for %s.\n", >+ timeval_str_buf(&store_tv, false, false, &store_buf), >+ timeval_str_buf(&cookie_tv, false, false, &cookie_buf), >+ domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ cmp = memcmp(sn->password->nt_hash.hash, >+ cn->password->nt_hash.hash, >+ 16); >+ if (cmp != 0) { >+ DBG_ERR("next password.nt_hash differs for %s.\n", >+ domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ cmp = memcmp(stored->password->nt_hash.hash, >+ cookie->password->nt_hash.hash, >+ 16); >+ if (cmp != 0) { >+ DBG_ERR("password.nt_hash differs for %s.\n", >+ domain); >+ TALLOC_FREE(stored); >+ return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; >+ } >+ >+ *pstored = stored; >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS secrets_abort_password_change(const char *change_server, >+ NTSTATUS local_status, >+ NTSTATUS remote_status, >+ const struct secrets_domain_info1 *cookie, >+ bool defer) >+{ >+ const char *domain = cookie->domain_info.name.string; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct db_context *db = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ const char *reason = defer ? "defer_change" : "failed_change"; >+ struct timeval tv = timeval_current(); >+ NTTIME now = timeval_to_nttime(&tv); >+ NTSTATUS status; >+ int ret; >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ /* >+ * secrets_check_password_change() >+ * checks that cookie->next_change >+ * is valid and the same as store >+ * in the database. >+ */ >+ status = secrets_check_password_change(cookie, frame, &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_check_password_change(%s) failed\n", domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ /* >+ * Remember the last server and error. >+ */ >+ info->next_change->change_server = change_server; >+ info->next_change->change_time = now; >+ info->next_change->local_status = local_status; >+ info->next_change->remote_status = remote_status; >+ >+ /* >+ * Make sure the next automatic change is deferred. >+ */ >+ if (defer) { >+ info->password_last_change = now; >+ } >+ >+ secrets_debug_domain_info(DBGLVL_WARNING, info, reason); >+ >+ status = secrets_store_domain_info(info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >+ >+NTSTATUS secrets_failed_password_change(const char *change_server, >+ NTSTATUS local_status, >+ NTSTATUS remote_status, >+ const struct secrets_domain_info1 *cookie) >+{ >+ static const bool defer = false; >+ return secrets_abort_password_change(change_server, >+ local_status, >+ remote_status, >+ cookie, defer); >+} >+ >+NTSTATUS secrets_defer_password_change(const char *change_server, >+ NTSTATUS local_status, >+ NTSTATUS remote_status, >+ const struct secrets_domain_info1 *cookie) >+{ >+ static const bool defer = true; >+ return secrets_abort_password_change(change_server, >+ local_status, >+ remote_status, >+ cookie, defer); >+} >+ >+NTSTATUS secrets_finish_password_change(const char *change_server, >+ NTTIME change_time, >+ const struct secrets_domain_info1 *cookie) >+{ >+ const char *domain = cookie->domain_info.name.string; >+ TALLOC_CTX *frame = talloc_stackframe(); >+ struct db_context *db = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ struct secrets_domain_info1_change *nc = NULL; >+ NTSTATUS status; >+ int ret; >+ >+ db = secrets_db_ctx(); >+ >+ ret = dbwrap_transaction_start(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_start() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ /* >+ * secrets_check_password_change() checks that cookie->next_change is >+ * valid and the same as store in the database. >+ */ >+ status = secrets_check_password_change(cookie, frame, &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_check_password_change(%s) failed\n", domain); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ nc = info->next_change; >+ >+ nc->password->change_server = change_server; >+ nc->password->change_time = change_time; >+ >+ info->password_last_change = change_time; >+ info->password_changes += 1; >+ info->next_change = NULL; >+ >+ info->older_password = info->old_password; >+ info->old_password = info->password; >+ info->password = nc->password; >+ >+ secrets_debug_domain_info(DBGLVL_WARNING, info, "finish_change"); >+ >+ status = secrets_store_domain_info(info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_domain_info() failed " >+ "for %s - %s\n", domain, nt_errstr(status)); >+ dbwrap_transaction_cancel(db); >+ TALLOC_FREE(frame); >+ return status; >+ } >+ >+ ret = dbwrap_transaction_commit(db); >+ if (ret != 0) { >+ DBG_ERR("dbwrap_transaction_commit() failed for %s\n", >+ domain); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+} >-- >1.9.1 > > >From aa7d492b93004c89d752ab3ffd39038279eca0b0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 24 May 2017 18:05:40 +0200 >Subject: [PATCH 50/56] net: add "net primarytrust dumpinfo" command that dumps > the details of the workstation trust > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit c7c17d9f503d6037aa8ed0bd7ab7cf52f5f28382) >--- > source3/utils/net.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 85 insertions(+) > >diff --git a/source3/utils/net.c b/source3/utils/net.c >index 6f7a7a4..f7f0bf6 100644 >--- a/source3/utils/net.c >+++ b/source3/utils/net.c >@@ -91,6 +91,83 @@ static void set_line_buffering(FILE *f) > setvbuf(f, NULL, _IOLBF, 0); > } > >+static int net_primarytrust_dumpinfo(struct net_context *c, int argc, >+ const char **argv) >+{ >+ int role = lp_server_role(); >+ const char *domain = lp_workgroup(); >+ struct secrets_domain_info1 *info = NULL; >+ bool include_secrets = c->opt_force; >+ char *str = NULL; >+ NTSTATUS status; >+ >+ if (role >= ROLE_ACTIVE_DIRECTORY_DC) { >+ d_printf(_("net primarytrust dumpinfo is only supported " >+ "on a DOMAIN_MEMBER for now.\n")); >+ return 1; >+ } >+ >+ if (c->opt_stdin) { >+ set_line_buffering(stdin); >+ set_line_buffering(stdout); >+ set_line_buffering(stderr); >+ } >+ >+ status = secrets_fetch_or_upgrade_domain_info(domain, >+ talloc_tos(), >+ &info); >+ if (!NT_STATUS_IS_OK(status)) { >+ d_fprintf(stderr, >+ _("Unable to fetch the information for domain[%s] " >+ "in the secrets database.\n"), >+ domain); >+ return 1; >+ } >+ >+ str = secrets_domain_info_string(info, info, domain, include_secrets); >+ if (str == NULL) { >+ d_fprintf(stderr, "secrets_domain_info_string() failed.\n"); >+ return 1; >+ } >+ >+ d_printf("%s", str); >+ if (!c->opt_force) { >+ d_printf(_("The password values are only included using " >+ "-f flag.\n")); >+ } >+ >+ TALLOC_FREE(info); >+ return 0; >+} >+ >+/** >+ * Entrypoint for 'net primarytrust' code. >+ * >+ * @param argc Standard argc. >+ * @param argv Standard argv without initial components. >+ * >+ * @return Integer status (0 means success). >+ */ >+ >+static int net_primarytrust(struct net_context *c, int argc, const char **argv) >+{ >+ struct functable func[] = { >+ { >+ "dumpinfo", >+ net_primarytrust_dumpinfo, >+ NET_TRANSPORT_LOCAL, >+ N_("Dump the details of the workstation trust"), >+ N_(" net [options] primarytrust dumpinfo'\n" >+ " Dump the details of the workstation trust " >+ "in secrets.tdb.\n" >+ " Requires the -f flag to include the password values.") >+ }, >+ {NULL, NULL, 0, NULL, NULL} >+ }; >+ >+ return net_run_function(c, argc, argv, "net primarytrust", func); >+} >+ > static int net_changesecretpw(struct net_context *c, int argc, > const char **argv) > { >@@ -570,6 +647,14 @@ static struct functable net_func[] = { > N_(" Use 'net help password' to get more information about " > "'net password' commands.") > }, >+ { >+ "primarytrust", >+ net_primarytrust, >+ NET_TRANSPORT_RPC, >+ N_("Run functions related to the primary workstation trust."), >+ N_(" Use 'net help primarytrust' to get more extensive information " >+ "about 'net primarytrust' commands.") >+ }, > { "changetrustpw", > net_changetrustpw, > NET_TRANSPORT_ADS | NET_TRANSPORT_RPC, >-- >1.9.1 > > >From 1a3babe13e4f4e1890765942429c52709cae92c4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 17 May 2017 10:29:59 +0200 >Subject: [PATCH 51/56] s3:libnet: make use of secrets_store_JoinCtx() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit c3ad8be5d5192070c599350d6ab28c064206b6cf) >--- > source3/libnet/libnet_join.c | 26 +++++--------------------- > 1 file changed, 5 insertions(+), 21 deletions(-) > >diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c >index 99bba2a..591c177 100644 >--- a/source3/libnet/libnet_join.c >+++ b/source3/libnet/libnet_join.c >@@ -987,31 +987,15 @@ static ADS_STATUS libnet_join_post_processing_ads_sync(TALLOC_CTX *mem_ctx, > static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx, > struct libnet_JoinCtx *r) > { >- if (!secrets_store_domain_sid(r->out.netbios_domain_name, >- r->out.domain_sid)) >- { >- DEBUG(1,("Failed to save domain sid\n")); >- return false; >- } >+ NTSTATUS status; > >- if (!secrets_store_machine_password(r->in.machine_password, >- r->out.netbios_domain_name, >- r->in.secure_channel_type)) >- { >- DEBUG(1,("Failed to save machine password\n")); >+ status = secrets_store_JoinCtx(r); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("secrets_store_JoinCtx() failed %s\n", >+ nt_errstr(status)); > return false; > } > >- if (r->out.krb5_salt != NULL) { >- bool ok; >- >- ok = kerberos_secrets_store_des_salt(r->out.krb5_salt); >- if (!ok) { >- DEBUG(1,("Failed to save krb5 salt\n")); >- return false; >- } >- } >- > return true; > } > >-- >1.9.1 > > >From 11e2cc93abca0f6dc14069c46ee96b6c787f2a64 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 May 2017 20:47:17 +0200 >Subject: [PATCH 52/56] s3:trusts_util: make use the workstation password > change more robust > >We use secrets_{prepare,failed,defer,finish}_password_change() to make >the process more robust. > >Even if we just just verified the current password with the DC >it can still happen that the remote password change will fail. > >If a server has the RefusePasswordChange=1 under >HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters, >it will reject NetrServerPasswordSet2() with NT_STATUS_WRONG_PASSWORD. > >This results in a successful local change, but a failing remote change, >which means the domain membership is broken (as we don't fallback to >the previous password for ntlmssp nor kerberos yet). > >An (at least Samba) RODC will also reject a password change, >see https://bugzilla.samba.org/show_bug.cgi?id=12773. > >Even with this change we still have open problems, e.g. if the password was >changed, but we didn't get the servers response. In order to fix that we need >to use only netlogon and lsa over unprotected transports, just using schannel >authentication (which supports the fallback to the old password). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 40c42af11fda062fef9df96a9b5ae3e02709f07c) >--- > source3/libsmb/trusts_util.c | 204 +++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 187 insertions(+), 17 deletions(-) > >diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c >index ff7f256..57cd542 100644 >--- a/source3/libsmb/trusts_util.c >+++ b/source3/libsmb/trusts_util.c >@@ -24,6 +24,7 @@ > #include "rpc_client/cli_netlogon.h" > #include "rpc_client/cli_pipe.h" > #include "../librpc/gen_ndr/ndr_netlogon.h" >+#include "librpc/gen_ndr/secrets.h" > #include "secrets.h" > #include "passdb.h" > #include "libsmb/libsmb.h" >@@ -114,11 +115,13 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > const char *context_name = NULL; > struct trust_pw_change_state *state; > struct cli_credentials *creds = NULL; >+ struct secrets_domain_info1 *info = NULL; >+ struct secrets_domain_info1_change *prev = NULL; > const struct samr_Password *current_nt_hash = NULL; > const struct samr_Password *previous_nt_hash = NULL; > uint8_t num_nt_hashes = 0; > uint8_t idx = 0; >- const struct samr_Password *nt_hashes[1+1] = { NULL, }; >+ const struct samr_Password *nt_hashes[1+3] = { NULL, }; > uint8_t idx_nt_hashes = 0; > uint8_t idx_current = UINT8_MAX; > enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; >@@ -270,10 +273,75 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > return status; > } > >- idx_current = idx; >- nt_hashes[idx++] = current_nt_hash; >- if (previous_nt_hash != NULL) { >- nt_hashes[idx++] = previous_nt_hash; >+ switch (sec_channel_type) { >+ >+ case SEC_CHAN_WKSTA: >+ case SEC_CHAN_BDC: >+ status = secrets_prepare_password_change(domain, dcname, >+ new_trust_pw_str, >+ frame, &info, &prev); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", >+ domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ TALLOC_FREE(new_trust_pw_str); >+ >+ if (prev != NULL) { >+ /* >+ * We had a failure before we changed the password. >+ */ >+ nt_hashes[idx++] = &prev->password->nt_hash; >+ >+ DEBUG(0,("%s : %s(%s): A password change was already " >+ "started against '%s' at %s. Trying to " >+ "recover...\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain, >+ prev->password->change_server, >+ nt_time_string(talloc_tos(), >+ prev->password->change_time))); >+ DEBUG(0,("%s : %s(%s): Last failure local[%s] remote[%s] " >+ "against '%s' at %s.\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain, >+ nt_errstr(prev->local_status), >+ nt_errstr(prev->remote_status), >+ prev->change_server, >+ nt_time_string(talloc_tos(), >+ prev->change_time))); >+ } >+ >+ idx_current = idx; >+ nt_hashes[idx++] = &info->password->nt_hash; >+ if (info->old_password != NULL) { >+ nt_hashes[idx++] = &info->old_password->nt_hash; >+ } >+ if (info->older_password != NULL) { >+ nt_hashes[idx++] = &info->older_password->nt_hash; >+ } >+ >+ /* >+ * We use the password that's already persitent in >+ * our database in order to handle failures. >+ */ >+ data_blob_clear_free(&new_trust_pw_blob); >+ new_trust_pw_blob = info->next_change->password->cleartext_blob; >+ break; >+ >+ case SEC_CHAN_DNS_DOMAIN: >+ case SEC_CHAN_DOMAIN: >+ idx_current = idx; >+ nt_hashes[idx++] = current_nt_hash; >+ if (previous_nt_hash != NULL) { >+ nt_hashes[idx++] = previous_nt_hash; >+ } >+ break; >+ >+ default: >+ smb_panic("Unsupported secure channel type"); >+ break; > } > num_nt_hashes = idx; > >@@ -301,11 +369,50 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > return status; > } > >+ if (prev != NULL && idx_nt_hashes == 0) { >+ DEBUG(0,("%s : %s(%s): Verified new password remotely " >+ "without changing %s\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain, context_name)); >+ >+ status = secrets_finish_password_change(prev->password->change_server, >+ prev->password->change_time, >+ info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", >+ domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ >+ DEBUG(0,("%s : %s(%s): Recovered previous password change.\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_OK; >+ } >+ > if (idx_nt_hashes != idx_current) { > DEBUG(0,("%s : %s(%s): Verified older password remotely " > "skip changing %s\n", > current_timestring(talloc_tos(), false), > __func__, domain, context_name)); >+ >+ if (info == NULL) { >+ TALLOC_FREE(frame); >+ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; >+ } >+ >+ status = secrets_defer_password_change(dcname, >+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE, >+ NT_STATUS_NOT_COMMITTED, >+ info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0, ("secrets_defer_password_change() failed for domain %s!\n", >+ domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } > TALLOC_FREE(frame); > return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; > } >@@ -323,16 +430,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > > case SEC_CHAN_WKSTA: > case SEC_CHAN_BDC: >- ok = secrets_store_machine_password(new_trust_pw_str, >- domain, >- sec_channel_type); >- if (!ok) { >- DEBUG(0, ("secrets_store_machine_password failed for domain %s!\n", >- domain)); >- TALLOC_FREE(frame); >- return NT_STATUS_INTERNAL_DB_CORRUPTION; >- } >- TALLOC_FREE(new_trust_pw_str); >+ /* >+ * we called secrets_prepare_password_change() above. >+ */ > break; > > case SEC_CHAN_DNS_DOMAIN: >@@ -364,10 +464,48 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > &new_trust_pw_blob, > new_trust_version); > if (!NT_STATUS_IS_OK(status)) { >- DEBUG(0,("%s : %s(%s) remote password change set with %s failed - %s\n", >+ NTSTATUS status2; >+ const char *fn = NULL; >+ >+ ok = dcerpc_binding_handle_is_connected(b); >+ >+ DEBUG(0,("%s : %s(%s) remote password change with %s failed " >+ "- %s (%s)\n", > current_timestring(talloc_tos(), false), > __func__, domain, context_name, >- nt_errstr(status))); >+ nt_errstr(status), >+ ok ? "connected": "disconnected")); >+ >+ if (!ok) { >+ /* >+ * The connection is broken, we don't >+ * know if the password was changed, >+ * we hope to have more luck next time. >+ */ >+ status2 = secrets_failed_password_change(dcname, >+ NT_STATUS_NOT_COMMITTED, >+ status, >+ info); >+ fn = "secrets_failed_password_change"; >+ } else { >+ /* >+ * The server rejected the change, we don't >+ * retry and defer the change to the next >+ * "machine password timeout" interval. >+ */ >+ status2 = secrets_defer_password_change(dcname, >+ NT_STATUS_NOT_COMMITTED, >+ status, >+ info); >+ fn = "secrets_defer_password_change"; >+ } >+ if (!NT_STATUS_IS_OK(status2)) { >+ DEBUG(0, ("%s() failed for domain %s!\n", >+ fn, domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ > TALLOC_FREE(frame); > return status; > } >@@ -376,6 +514,38 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, > current_timestring(talloc_tos(), false), > __func__, domain, context_name)); > >+ switch (sec_channel_type) { >+ >+ case SEC_CHAN_WKSTA: >+ case SEC_CHAN_BDC: >+ status = secrets_finish_password_change( >+ info->next_change->change_server, >+ info->next_change->change_time, >+ info); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n", >+ domain)); >+ TALLOC_FREE(frame); >+ return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ } >+ >+ DEBUG(0,("%s : %s(%s): Finished password change.\n", >+ current_timestring(talloc_tos(), false), >+ __func__, domain)); >+ break; >+ >+ case SEC_CHAN_DNS_DOMAIN: >+ case SEC_CHAN_DOMAIN: >+ /* >+ * we used pdb_set_trusteddom_pw(). >+ */ >+ break; >+ >+ default: >+ smb_panic("Unsupported secure channel type"); >+ break; >+ } >+ > ok = cli_credentials_set_utf16_password(creds, > &new_trust_pw_blob, > CRED_SPECIFIED); >-- >1.9.1 > > >From 35882f139a7c36c55a60785241fe189d3c97350e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 23 May 2017 17:29:31 +0200 >Subject: [PATCH 53/56] net: make use of secrets_*_password_change() for "net > changesecretpw" > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 4ae6a3ffb233c9b9576a3b5bb15a51ee56e4dbc3) >--- > source3/utils/net.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 44 insertions(+), 7 deletions(-) > >diff --git a/source3/utils/net.c b/source3/utils/net.c >index f7f0bf6..7aa7405 100644 >--- a/source3/utils/net.c >+++ b/source3/utils/net.c >@@ -172,9 +172,23 @@ static int net_changesecretpw(struct net_context *c, int argc, > const char **argv) > { > char *trust_pw; >- enum netr_SchannelType sec_channel_type = SEC_CHAN_WKSTA; >+ int role = lp_server_role(); >+ >+ if (role != ROLE_DOMAIN_MEMBER) { >+ d_printf(_("Machine account password change only supported on a DOMAIN_MEMBER.\n" >+ "Do NOT use this function unless you know what it does!\n" >+ "This function will change the ADS Domain member " >+ "machine account password in the secrets.tdb file!\n")); >+ return 1; >+ } > > if(c->opt_force) { >+ struct secrets_domain_info1 *info = NULL; >+ struct secrets_domain_info1_change *prev = NULL; >+ NTSTATUS status; >+ struct timeval tv = timeval_current(); >+ NTTIME now = timeval_to_nttime(&tv); >+ > if (c->opt_stdin) { > set_line_buffering(stdin); > set_line_buffering(stdout); >@@ -188,14 +202,37 @@ static int net_changesecretpw(struct net_context *c, int argc, > return 1; > } > >- if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) { >- d_fprintf(stderr, >- _("Unable to write the machine account password in the secrets database")); >- return 1; >+ status = secrets_prepare_password_change(lp_workgroup(), >+ "localhost", >+ trust_pw, >+ talloc_tos(), >+ &info, &prev); >+ if (!NT_STATUS_IS_OK(status)) { >+ d_fprintf(stderr, >+ _("Unable to write the machine account password in the secrets database")); >+ return 1; > } >- else { >- d_printf(_("Modified trust account password in secrets database\n")); >+ if (prev != NULL) { >+ d_fprintf(stderr, >+ _("Pending machine account password change found - aborting.")); >+ status = secrets_failed_password_change("localhost", >+ NT_STATUS_REQUEST_NOT_ACCEPTED, >+ NT_STATUS_NOT_COMMITTED, >+ info); >+ if (!NT_STATUS_IS_OK(status)) { >+ d_fprintf(stderr, >+ _("Failed to abort machine account password change")); >+ } >+ return 1; > } >+ status = secrets_finish_password_change("localhost", now, info); >+ if (!NT_STATUS_IS_OK(status)) { >+ d_fprintf(stderr, >+ _("Unable to write the machine account password in the secrets database")); >+ return 1; >+ } >+ >+ d_printf(_("Modified trust account password in secrets database\n")); > } > else { > d_printf(_("Machine account password change requires the -f flag.\n" >-- >1.9.1 > > >From 75c61e5e46cc7465ad01def1b0a03fc27fb4552a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 23 May 2017 17:41:34 +0200 >Subject: [PATCH 54/56] s3:libads: make use of secrets_*_password_change() in > ads_change_trust_account_password() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit b874dc90c91dd41c35e99bf7c4fe04220465edca) >--- > source3/libads/util.c | 106 ++++++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 90 insertions(+), 16 deletions(-) > >diff --git a/source3/libads/util.c b/source3/libads/util.c >index b0754be..14dbf86 100644 >--- a/source3/libads/util.c >+++ b/source3/libads/util.c >@@ -20,42 +20,116 @@ > #include "includes.h" > #include "ads.h" > #include "secrets.h" >+#include "librpc/gen_ndr/ndr_secrets.h" > > #ifdef HAVE_KRB5 >- > ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal) > { >- char *password; >- char *new_password; >+ const char *password = NULL; >+ const char *new_password = NULL; > ADS_STATUS ret; >- enum netr_SchannelType sec_channel_type; >- >- if ((password = secrets_fetch_machine_password(lp_workgroup(), NULL, &sec_channel_type)) == NULL) { >- DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal)); >- return ADS_ERROR_SYSTEM(ENOENT); >+ const char *domain = lp_workgroup(); >+ struct secrets_domain_info1 *info = NULL; >+ struct secrets_domain_info1_change *prev = NULL; >+ const DATA_BLOB *cleartext_blob = NULL; >+ DATA_BLOB pw_blob = data_blob_null; >+ DATA_BLOB new_pw_blob = data_blob_null; >+ NTSTATUS status; >+ struct timeval tv = timeval_current(); >+ NTTIME now = timeval_to_nttime(&tv); >+ int role = lp_server_role(); >+ bool ok; >+ >+ if (role != ROLE_DOMAIN_MEMBER) { >+ DBG_ERR("Machine account password change only supported on a DOMAIN_MEMBER.\n"); >+ return ADS_ERROR_NT(NT_STATUS_INVALID_SERVER_STATE); > } > > new_password = trust_pw_new_value(talloc_tos(), SEC_CHAN_WKSTA, SEC_ADS); > if (new_password == NULL) { > ret = ADS_ERROR_SYSTEM(errno); > DEBUG(1,("Failed to generate machine password\n")); >- goto failed; >+ return ret; >+ } >+ >+ status = secrets_prepare_password_change(domain, >+ ads->auth.kdc_server, >+ new_password, >+ talloc_tos(), >+ &info, &prev); >+ if (!NT_STATUS_IS_OK(status)) { >+ return ADS_ERROR_NT(status); >+ } >+ if (prev != NULL) { >+ status = NT_STATUS_REQUEST_NOT_ACCEPTED; >+ secrets_failed_password_change("localhost", >+ status, >+ NT_STATUS_NOT_COMMITTED, >+ info); >+ return ADS_ERROR_NT(status); >+ } >+ >+ cleartext_blob = &info->password->cleartext_blob; >+ ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX, >+ cleartext_blob->data, >+ cleartext_blob->length, >+ (void **)&pw_blob.data, >+ &pw_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " >+ "failed for password of %s - %s\n", >+ domain, nt_errstr(status)); >+ return ADS_ERROR_NT(status); >+ } >+ password = (const char *)pw_blob.data; >+ >+ cleartext_blob = &info->next_change->password->cleartext_blob; >+ ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX, >+ cleartext_blob->data, >+ cleartext_blob->length, >+ (void **)&new_pw_blob.data, >+ &new_pw_blob.length); >+ if (!ok) { >+ status = NT_STATUS_UNMAPPABLE_CHARACTER; >+ if (errno == ENOMEM) { >+ status = NT_STATUS_NO_MEMORY; >+ } >+ DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " >+ "failed for new_password of %s - %s\n", >+ domain, nt_errstr(status)); >+ secrets_failed_password_change("localhost", >+ status, >+ NT_STATUS_NOT_COMMITTED, >+ info); >+ return ADS_ERROR_NT(status); > } >+ new_password = (const char *)new_pw_blob.data; > > ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset); > > if (!ADS_ERR_OK(ret)) { >- goto failed; >+ status = ads_ntstatus(ret); >+ DBG_ERR("kerberos_set_password(%s, %s) " >+ "failed for new_password of %s - %s\n", >+ ads->auth.kdc_server, host_principal, >+ domain, nt_errstr(status)); >+ secrets_failed_password_change(ads->auth.kdc_server, >+ NT_STATUS_NOT_COMMITTED, >+ status, >+ info); >+ return ret; > } > >- if (!secrets_store_machine_password(new_password, lp_workgroup(), sec_channel_type)) { >+ status = secrets_finish_password_change(ads->auth.kdc_server, now, info); >+ if (!NT_STATUS_IS_OK(status)) { > DEBUG(1,("Failed to save machine password\n")); >- ret = ADS_ERROR_SYSTEM(EACCES); >- goto failed; >+ return ADS_ERROR_NT(status); > } > >-failed: >- SAFE_FREE(password); >- return ret; >+ return ADS_SUCCESS; > } > #endif >-- >1.9.1 > > >From 88b7c3fbe86db3b3a93cf141c92e3860e0e37479 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 23 May 2017 17:42:09 +0200 >Subject: [PATCH 55/56] s3:secrets: remove unused > secrets_store_[prev_]machine_password() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit f513c20ee04fe896900c99ae804753d445414d7d) >--- > source3/include/secrets.h | 1 - > source3/passdb/machine_account_secrets.c | 49 -------------------------------- > 2 files changed, 50 deletions(-) > >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index 0363b6b..24ae5bd 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -140,7 +140,6 @@ NTSTATUS secrets_finish_password_change(const char *change_server, > const struct secrets_domain_info1 *info); > bool secrets_delete_machine_password_ex(const char *domain, const char *realm); > bool secrets_delete_domain_sid(const char *domain); >-bool secrets_store_machine_password(const char *pass, const char *domain, enum netr_SchannelType sec_channel); > char *secrets_fetch_prev_machine_password(const char *domain); > time_t secrets_fetch_pass_last_set_time(const char *domain); > char *secrets_fetch_machine_password(const char *domain, >diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c >index b88fbe9..3d1cb5b 100644 >--- a/source3/passdb/machine_account_secrets.c >+++ b/source3/passdb/machine_account_secrets.c >@@ -450,55 +450,6 @@ bool secrets_delete_domain_sid(const char *domain) > } > > /************************************************************************ >- Routine to store the previous machine password (by storing the current password >- as the old) >-************************************************************************/ >- >-static bool secrets_store_prev_machine_password(const char *domain) >-{ >- char *oldpass; >- bool ret; >- >- oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL); >- if (oldpass == NULL) { >- return true; >- } >- ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1); >- SAFE_FREE(oldpass); >- return ret; >-} >- >-/************************************************************************ >- Routine to set the plaintext machine account password for a realm >- the password is assumed to be a null terminated ascii string. >- Before storing >-************************************************************************/ >- >-bool secrets_store_machine_password(const char *pass, const char *domain, >- enum netr_SchannelType sec_channel) >-{ >- bool ret; >- uint32_t last_change_time; >- uint32_t sec_channel_type; >- >- if (!secrets_store_prev_machine_password(domain)) { >- return false; >- } >- >- ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1); >- if (!ret) >- return ret; >- >- SIVAL(&last_change_time, 0, time(NULL)); >- ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time)); >- >- SIVAL(&sec_channel_type, 0, sec_channel); >- ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type)); >- >- return ret; >-} >- >-/************************************************************************ > Set the machine trust account password, the old pw and last change > time, domain SID and salting principals based on values passed in > (added to supprt the secrets_tdb_sync module on secrets.ldb) >-- >1.9.1 > > >From 6bca3be71ac04dba2de06e0b14c92cb55cb8ebae Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 22 Jun 2017 15:30:56 +0200 >Subject: [PATCH 56/56] selftest:Samba3: call "net primarytrust dumpinfo" > setup_nt4_member() after the join > >Here we check that we get 'REDACTED SECRET VALUES' printed, in order >to avoid regression on the non '-f' behavior. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andreas Schneider <asn@samba.org> >(cherry picked from commit 9530284383f252efd64bfdf138579964c6500eba) >--- > selftest/target/Samba3.pm | 10 ++++++++++ > 1 file changed, 10 insertions(+) > >diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm >index a7699f8..f4871aa 100755 >--- a/selftest/target/Samba3.pm >+++ b/selftest/target/Samba3.pm >@@ -352,6 +352,16 @@ sub setup_nt4_member($$$) > return undef; > } > >+ my $cmd = ""; >+ $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; >+ $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" "; >+ $cmd .= "$net $ret->{CONFIGURATION} primarytrust dumpinfo | grep -q 'REDACTED SECRET VALUES'"; >+ >+ if (system($cmd) != 0) { >+ warn("check failed\n$cmd"); >+ return undef; >+ } >+ > if (not $self->check_or_start($ret, "yes", "yes", "yes")) { > return undef; > } >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review?
(
slow
)
asn
:
review+
Actions:
View
Attachments on
bug 12782
:
13289
| 13329 |
13330