[Patches] Fixes for machine password problems [bug #12262]
Stefan Metzmacher
metze at samba.org
Mon Feb 20 19:08:36 UTC 2017
Hi,
here's some patches to fix problem with the random passwords
winbindd sets every week (by default).
https://bugzilla.samba.org/show_bug.cgi?id=12262
In Samba 4.2 we only used ascii passwords, but with 4.3
we're using random unicode passwords. This causes
a lot of trouble if someone uses "unix charset != utf8".
But also with unix charset = utf8 it can sometimes happen
that kerberos authentication start to fail if
the password uses code points > 0xffff.
Please review and push:-)
Thanks!
metze
PS: As future improvement we could calculate the
ENCTYPE_ARCFOUR_HMAC in smb_krb5_create_key_from_string()
ourself using E_md4hash(). In the long run we may also
store the precalculated hashes when we change the password
and then use them for the servers in memory keytab
and as a client use this in memory keytab for kinit,
then we could use true random utf16 buffers like microsoft.
-------------- next part --------------
From 4ddb6ade9153c8389b55f828c4b66d268e43405f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jan 2017 19:02:21 +0000
Subject: [PATCH 01/21] libcli/auth: check E_md4hash() result in
netlogon_creds_cli_ServerPasswordSet_send()
We need to make sure we can convert the given string to an nthash.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
libcli/auth/netlogon_creds_cli.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index b97d60e..93ec1bf 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -1747,7 +1747,11 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx
/*
* netr_ServerPasswordSet
*/
- E_md4hash(new_password, state->samr_password.hash);
+ ok = E_md4hash(new_password, state->samr_password.hash);
+ if (!ok) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
/*
* netr_ServerPasswordSet2
--
1.9.1
From bc82fc95172ba177cc954af87acd776fa90d2d55 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 9 Feb 2017 21:47:52 +0100
Subject: [PATCH 02/21] libcli/auth: add netlogon_creds_cli_debug_string()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
libcli/auth/netlogon_creds_cli.c | 8 ++++++++
libcli/auth/netlogon_creds_cli.h | 4 ++++
2 files changed, 12 insertions(+)
diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index 93ec1bf..d55142e 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -484,6 +484,14 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer,
return NT_STATUS_OK;
}
+char *netlogon_creds_cli_debug_string(
+ const struct netlogon_creds_cli_context *context,
+ TALLOC_CTX *mem_ctx)
+{
+ return talloc_asprintf(mem_ctx, "netlogon_creds_cli:%s",
+ context->db.key_name);
+}
+
enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
struct netlogon_creds_cli_context *context)
{
diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h
index 006367a..949e03b 100644
--- a/libcli/auth/netlogon_creds_cli.h
+++ b/libcli/auth/netlogon_creds_cli.h
@@ -52,6 +52,10 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer,
TALLOC_CTX *mem_ctx,
struct netlogon_creds_cli_context **_context);
+char *netlogon_creds_cli_debug_string(
+ const struct netlogon_creds_cli_context *context,
+ TALLOC_CTX *mem_ctx);
+
enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
struct netlogon_creds_cli_context *context);
--
1.9.1
From 3bf0fe2dcd1a5f5bf60951e29a084aa03d36c946 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 09:30:05 +0200
Subject: [PATCH 03/21] lib/util: add generate_random_machine_password()
function
It generates more random password for the use as machine password,
restricted to codepoints <= 0xFFFF in order to be compatible
with MIT krb5 and Heimdal.
Note: the fallback to ascii if 'unix charset' is not 'utf8'.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
lib/util/genrand_util.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++-
lib/util/samba_util.h | 32 ++++++++-
2 files changed, 198 insertions(+), 2 deletions(-)
diff --git a/lib/util/genrand_util.c b/lib/util/genrand_util.c
index fbd9998..76b7cd9 100644
--- a/lib/util/genrand_util.c
+++ b/lib/util/genrand_util.c
@@ -210,7 +210,7 @@ again:
}
/**
- * Generate a random text password.
+ * Generate a random text password (based on printable ascii characters).
*/
_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max)
@@ -258,6 +258,172 @@ again:
}
/**
+ * Generate a random machine password (based on random utf16 characters,
+ * converted to utf8). min must be at least 14, max must be at most 255.
+ *
+ * If 'unix charset' is not utf8, the password consist of random ascii
+ * values!
+ */
+
+_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max)
+{
+ TALLOC_CTX *frame = NULL;
+ struct generate_random_machine_password_state {
+ uint8_t password_buffer[256 * 2];
+ uint8_t tmp;
+ } *state;
+ char *new_pw = NULL;
+ size_t len = max;
+ char *utf8_pw = NULL;
+ size_t utf8_len = 0;
+ char *unix_pw = NULL;
+ size_t unix_len = 0;
+ size_t diff;
+ size_t i;
+ bool ok;
+ int cmp;
+
+ if (max > 255) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (min < 14) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (min > max) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ frame = talloc_stackframe_pool(2048);
+ state = talloc_zero(frame, struct generate_random_machine_password_state);
+
+ diff = max - min;
+
+ if (diff > 0) {
+ size_t tmp;
+
+ generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
+
+ tmp %= diff;
+
+ len = min + tmp;
+ }
+
+ /*
+ * Create a random machine account password
+ * We create a random buffer and convert that to utf8.
+ * This is similar to what windows is doing.
+ *
+ * In future we may store the raw random buffer,
+ * but for now we need to pass the password as
+ * char pointer through some layers.
+ *
+ * As most kerberos keys are derived from the
+ * utf8 password we need to fallback to
+ * ASCII passwords if "unix charset" is not utf8.
+ */
+ generate_secret_buffer(state->password_buffer, len * 2);
+ for (i = 0; i < len; i++) {
+ size_t idx = i*2;
+ uint16_t c;
+
+ /*
+ * both MIT krb5 and HEIMDAL only
+ * handle codepoints up to 0xffff.
+ *
+ * It means we need to avoid
+ * 0xD800 - 0xDBFF (high surrogate)
+ * and
+ * 0xDC00 - 0xDFFF (low surrogate)
+ * in the random utf16 data.
+ *
+ * 55296 0xD800 0154000 0b1101100000000000
+ * 57343 0xDFFF 0157777 0b1101111111111111
+ * 8192 0x2000 020000 0b10000000000000
+ *
+ * The above values show that we can check
+ * for 0xD800 and just add 0x2000 to avoid
+ * the surrogate ranges.
+ *
+ * The rest will be handled by CH_UTF16MUNGED
+ * see utf16_munged_pull().
+ */
+ c = SVAL(state->password_buffer, idx);
+ if (c & 0xD800) {
+ c |= 0x2000;
+ }
+ SSVAL(state->password_buffer, idx, c);
+ }
+ ok = convert_string_talloc(frame,
+ CH_UTF16MUNGED, CH_UTF8,
+ state->password_buffer, len * 2,
+ (void *)&utf8_pw, &utf8_len);
+ if (!ok) {
+ DEBUG(0, ("%s: convert_string_talloc() failed\n",
+ __func__));
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+
+ ok = convert_string_talloc(frame,
+ CH_UTF16MUNGED, CH_UNIX,
+ state->password_buffer, len * 2,
+ (void *)&unix_pw, &unix_len);
+ if (!ok) {
+ goto ascii_fallback;
+ }
+
+ if (utf8_len != unix_len) {
+ goto ascii_fallback;
+ }
+
+ cmp = memcmp((const uint8_t *)utf8_pw,
+ (const uint8_t *)unix_pw,
+ utf8_len);
+ if (cmp != 0) {
+ goto ascii_fallback;
+ }
+
+ new_pw = talloc_strdup(mem_ctx, utf8_pw);
+ if (new_pw == NULL) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+ talloc_set_name_const(new_pw, __func__);
+ TALLOC_FREE(frame);
+ return new_pw;
+
+ascii_fallback:
+ for (i = 0; i < len; i++) {
+ /*
+ * truncate to ascii
+ */
+ state->tmp = state->password_buffer[i] & 0x7f;
+ if (state->tmp == 0) {
+ state->tmp = state->password_buffer[i] >> 1;
+ }
+ if (state->tmp == 0) {
+ state->tmp = 0x01;
+ }
+ state->password_buffer[i] = state->tmp;
+ }
+ state->password_buffer[i] = '\0';
+
+ new_pw = talloc_strdup(mem_ctx, (const char *)state->password_buffer);
+ if (new_pw == NULL) {
+ TALLOC_FREE(frame);
+ return NULL;
+ }
+ talloc_set_name_const(new_pw, __func__);
+ TALLOC_FREE(frame);
+ return new_pw;
+}
+
+/**
* Generate an array of unique text strings all of the same length.
* The returned string will be allocated.
* Returns NULL if the number of unique combinations cannot be created.
diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index 8aa8eba..7a74617 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -97,11 +97,41 @@ _PUBLIC_ uint32_t generate_random(void);
_PUBLIC_ bool check_password_quality(const char *s);
/**
- * Generate a random text password.
+ * Generate a random text password (based on printable ascii characters).
+ * This function is designed to provide a password that
+ * meats the complexity requirements of UF_NORMAL_ACCOUNT objects
+ * and they should be human readable and writeable on any keyboard layout.
+ *
+ * Characters used are:
+ * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~
*/
_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max);
/**
+ * Generate a random machine password
+ *
+ * min and max are the number of utf16 characters used
+ * to generate on utf8 compatible password.
+ *
+ * Note: if 'unix charset' is not 'utf8' (the default)
+ * then each utf16 character is only filled with
+ * values from 0x01 to 0x7f (ascii values without 0x00).
+ * This is important as the password neets to be
+ * a valid value as utf8 string and at the same time
+ * a valid value in the 'unix charset'.
+ *
+ * If 'unix charset' is 'utf8' (the default) then
+ * each utf16 character is a random value from 0x0000
+ * 0xFFFF (exluding the surrogate ranges from 0xD800-0xDFFF)
+ * while the translation from CH_UTF16MUNGED
+ * to CH_UTF8 replaces invalid values (see utf16_munged_pull()).
+ *
+ * Note: these passwords may not pass the complexity requirements
+ * for UF_NORMAL_ACCOUNT objects (except krbtgt accounts).
+ */
+_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max);
+
+/**
Use the random number generator to generate a random string.
**/
_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list);
--
1.9.1
From 4a209ebbccf4b8f19a41855dbae1ab9147c18e83 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 18 Jan 2017 19:57:30 +0100
Subject: [PATCH 04/21] s3:libsmb: let trust_pw_change() debug more verbose
information
Password changes caused much trouble in the past, so we better debug
them at log level 0 and may see them also in the syslog.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libsmb/trusts_util.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index c56949e..a3cabd4 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -54,6 +54,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
bool force)
{
TALLOC_CTX *frame = talloc_stackframe();
+ const char *context_name = NULL;
struct trust_pw_change_state *state;
struct cli_credentials *creds = NULL;
const struct samr_Password *current_nt_hash = NULL;
@@ -181,6 +182,12 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
return NT_STATUS_OK;
}
+ context_name = netlogon_creds_cli_debug_string(context, talloc_tos());
+ if (context_name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
/*
* Create a random machine account password
* We create a random buffer and convert that to utf8.
@@ -215,12 +222,16 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
*current_nt_hash,
previous_nt_hash);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("netlogon_creds_cli_auth for domain %s - %s!\n",
- domain, nt_errstr(status)));
+ DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old password - %s!\n",
+ context_name, nt_errstr(status)));
TALLOC_FREE(frame);
return status;
}
+ DEBUG(0,("%s : %s(%s): Verified old password remotely using %s\n",
+ current_timestring(talloc_tos(), false),
+ __func__, domain, context_name));
+
/*
* Return the result of trying to write the new password
* back into the trust account file.
@@ -260,22 +271,24 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
break;
}
- DEBUG(1,("%s : %s(%s): Changed password locally\n",
+ DEBUG(0,("%s : %s(%s): Changed password locally\n",
current_timestring(talloc_tos(), false), __func__, domain));
status = netlogon_creds_cli_ServerPasswordSet(context, b,
new_trust_passwd,
new_trust_version);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("%s : %s(%s) remote password change set failed - %s\n",
- current_timestring(talloc_tos(), false), __func__,
- domain, nt_errstr(status)));
+ DEBUG(0,("%s : %s(%s) remote password change set with %s failed - %s\n",
+ current_timestring(talloc_tos(), false),
+ __func__, domain, context_name,
+ nt_errstr(status)));
TALLOC_FREE(frame);
return status;
}
- DEBUG(1,("%s : %s(%s): Changed password remotely.\n",
- current_timestring(talloc_tos(), false), __func__, domain));
+ DEBUG(0,("%s : %s(%s): Changed password remotely using %s\n",
+ current_timestring(talloc_tos(), false),
+ __func__, domain, context_name));
TALLOC_FREE(frame);
return NT_STATUS_OK;
--
1.9.1
From 58fde532382978a9dcddbc4adbb4f4b158394d6c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 9 Feb 2017 22:53:52 +0100
Subject: [PATCH 05/21] s3:libsmb: let trust_pw_change() verify the new
password at the end.
We should notice problems as early as possible, it makes no
sense to keep things working for a while and later find out
the we lost our trust relationship with our domain.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libsmb/trusts_util.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index a3cabd4..4b784c1 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -290,6 +290,39 @@ 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);
+ if (!ok) {
+ DEBUG(0, ("cli_credentials_set_password failed for domain %s!\n",
+ domain));
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ current_nt_hash = cli_credentials_get_nt_hash(creds, frame);
+ if (current_nt_hash == NULL) {
+ DEBUG(0, ("cli_credentials_get_nt_hash failed for domain %s!\n",
+ domain));
+ TALLOC_FREE(frame);
+ return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
+ }
+
+ /*
+ * Now we verify the new password.
+ */
+ status = netlogon_creds_cli_auth(context, b,
+ *current_nt_hash,
+ NULL); /* previous_nt_hash */
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for new password - %s!\n",
+ context_name, nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ DEBUG(0,("%s : %s(%s): Verified new password remotely using %s\n",
+ current_timestring(talloc_tos(), false),
+ __func__, domain, context_name));
+
TALLOC_FREE(frame);
return NT_STATUS_OK;
}
--
1.9.1
From d223d3cb64b5c799364e5d4bb7f03c48c250fd49 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:12:35 +0200
Subject: [PATCH 06/21] s3:libsmb: add trust_pw_new_value() helper function
This generates a new trust password based on the secure channel type
and lp_security().
NT4 really has a limit of 28 UTF16 bytes.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/include/proto.h | 3 +++
source3/libsmb/trusts_util.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index b3d3ca0..e6d4284 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -862,6 +862,9 @@ void update_trustdom_cache( void );
struct netlogon_creds_cli_context;
struct messaging_context;
struct dcerpc_binding_handle;
+char *trust_pw_new_value(TALLOC_CTX *mem_ctx,
+ enum netr_SchannelType sec_channel_type,
+ int security);
NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
struct messaging_context *msg_ctx,
struct dcerpc_binding_handle *b,
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 4b784c1..efe8098 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -47,6 +47,62 @@ static int trust_pw_change_state_destructor(struct trust_pw_change_state *state)
return 0;
}
+char *trust_pw_new_value(TALLOC_CTX *mem_ctx,
+ enum netr_SchannelType sec_channel_type,
+ int security)
+{
+ /*
+ * use secure defaults.
+ */
+ size_t min = 128;
+ size_t max = 255;
+
+ switch (sec_channel_type) {
+ case SEC_CHAN_WKSTA:
+ case SEC_CHAN_BDC:
+ if (security == SEC_DOMAIN) {
+ /*
+ * The maximum length of a trust account password.
+ * Used when we randomly create it, 15 char passwords
+ * exceed NT4's max password length.
+ */
+ min = 14;
+ max = 14;
+ }
+ break;
+ case SEC_CHAN_DNS_DOMAIN:
+ /*
+ * new_len * 2 = 498 bytes is the largest possible length
+ * NL_PASSWORD_VERSION consumes the rest of the possible 512 bytes
+ * and a confounder with at least 2 bytes is required.
+ *
+ * Windows uses new_len = 120 => 240 bytes (utf16)
+ */
+ min = 120;
+ max = 120;
+ break;
+ /* fall through */
+ case SEC_CHAN_DOMAIN:
+ /*
+ * The maximum length of a trust account password.
+ * Used when we randomly create it, 15 char passwords
+ * exceed NT4's max password length.
+ */
+ min = 14;
+ max = 14;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Create a random machine account password
+ * We create a random buffer and convert that to utf8.
+ * This is similar to what windows is doing.
+ */
+ return generate_random_machine_password(mem_ctx, min, max);
+}
+
NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
struct messaging_context *msg_ctx,
struct dcerpc_binding_handle *b,
--
1.9.1
From eff60f69b697336188c472a3bf9d16cfa639fa27 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:12:35 +0200
Subject: [PATCH 07/21] s3:libsmb: use trust_pw_new_value() in
trust_pw_change()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libsmb/trusts_util.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index efe8098..2cc6264 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -122,10 +122,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
struct timeval g_timeout = { 0, };
int timeout = 0;
struct timeval tv = { 0, };
- size_t new_len = DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH;
- uint8_t new_password_buffer[256 * 2] = { 0, };
char *new_trust_passwd = NULL;
- size_t len = 0;
uint32_t new_version = 0;
uint32_t *new_trust_version = NULL;
NTSTATUS status;
@@ -191,16 +188,6 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
case SEC_CHAN_BDC:
break;
case SEC_CHAN_DNS_DOMAIN:
- /*
- * new_len * 2 = 498 bytes is the largest possible length
- * NL_PASSWORD_VERSION consumes the rest of the possible 512 bytes
- * and a confounder with at least 2 bytes is required.
- *
- * Windows uses new_len = 120 => 240 bytes.
- */
- new_len = 120;
-
- /* fall through */
case SEC_CHAN_DOMAIN:
status = pdb_get_trusted_domain(frame, domain, &td);
if (!NT_STATUS_IS_OK(status)) {
@@ -249,14 +236,10 @@ 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.
*/
- generate_secret_buffer(new_password_buffer, new_len * 2);
- ok = convert_string_talloc(frame,
- CH_UTF16MUNGED, CH_UTF8,
- new_password_buffer, new_len * 2,
- (void *)&new_trust_passwd, &len);
- ZERO_STRUCT(new_password_buffer);
- if (!ok) {
- DEBUG(0, ("convert_string_talloc failed\n"));
+ new_trust_passwd = trust_pw_new_value(frame, sec_channel_type,
+ lp_security());
+ if (new_trust_passwd == NULL) {
+ DEBUG(0, ("trust_pw_new_value() failed\n"));
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
--
1.9.1
From 7a03f4531752d1d43a08d75fdc8203dda25c243f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 10:38:58 +0200
Subject: [PATCH 08/21] s3:libads: use trust_pw_new_value() for krb5 machine
passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libads/util.c | 9 ++++++---
source3/wscript_build | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/source3/libads/util.c b/source3/libads/util.c
index 2e22bca..b0754be 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -35,9 +35,12 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
return ADS_ERROR_SYSTEM(ENOENT);
}
- new_password = generate_random_password(talloc_tos(),
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ 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;
+ }
ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
diff --git a/source3/wscript_build b/source3/wscript_build
index 8c9a15b..9903624 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -553,6 +553,7 @@ bld.SAMBA3_LIBRARY('ads',
libsmb
DCUTIL
smbldap
+ trusts_util
''',
private_library=True)
--
1.9.1
From 774511e0b294376cb2ccd8882e3ff5697b231b4a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:09:57 +0200
Subject: [PATCH 09/21] s3:libnet_join: make use of trust_pw_new_value()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libnet/libnet_join.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 8275a7c..4d00ef6 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1138,9 +1138,11 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx,
}
if (!r->in.machine_password) {
- r->in.machine_password = generate_random_password(mem_ctx,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
+
+ r->in.machine_password = trust_pw_new_value(mem_ctx,
+ r->in.secure_channel_type,
+ security);
if (r->in.machine_password == NULL) {
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
@@ -1233,9 +1235,11 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
}
if (!r->in.machine_password) {
- r->in.machine_password = generate_random_password(mem_ctx,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
+
+ r->in.machine_password = trust_pw_new_value(mem_ctx,
+ r->in.secure_channel_type,
+ security);
NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
}
--
1.9.1
From bc0bb39df49fbf5ad99acc4dd45fca4c9e8fdc9c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 10:42:30 +0200
Subject: [PATCH 10/21] s3:net_rpc_trust: make use of trust_pw_new_value()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/utils/net_rpc_trust.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/source3/utils/net_rpc_trust.c b/source3/utils/net_rpc_trust.c
index 5e58103..5c13e06 100644
--- a/source3/utils/net_rpc_trust.c
+++ b/source3/utils/net_rpc_trust.c
@@ -518,9 +518,9 @@ static int rpc_trust_common(struct net_context *net_ctx, int argc,
}
DEBUG(0, ("Using random trust password.\n"));
- trust_pw = generate_random_password(mem_ctx,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
- DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ trust_pw = trust_pw_new_value(mem_ctx,
+ SEC_CHAN_DOMAIN,
+ SEC_DOMAIN);
if (trust_pw == NULL) {
DEBUG(0, ("generate_random_password failed.\n"));
goto done;
--
1.9.1
From 99897b5217d49afbdc3f508f77a44fec64915f96 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:41:48 +0200
Subject: [PATCH 11/21] s3:include: remove unused
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/include/smb.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 7de47c8..24a73e57 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -732,12 +732,6 @@ struct node_status_extra {
#define SAFE_NETBIOS_CHARS ". -_"
-/* The maximum length of a trust account password.
- Used when we randomly create it, 15 char passwords
- exceed NT4's max password length */
-
-#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
-
#define PORT_NONE 0
#ifndef LDAP_PORT
#define LDAP_PORT 389
--
1.9.1
From 9a7168e7493a29991655734f8f2b416925b831bd Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:41:48 +0200
Subject: [PATCH 12/21] s4:libcli/raw: remove unused
DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libcli/raw/smb.h | 7 -------
1 file changed, 7 deletions(-)
diff --git a/source4/libcli/raw/smb.h b/source4/libcli/raw/smb.h
index 5bde657..d770fa5 100644
--- a/source4/libcli/raw/smb.h
+++ b/source4/libcli/raw/smb.h
@@ -297,13 +297,6 @@
#define UID_FIELD_INVALID 0
-/* The maximum length of a trust account password.
- Used when we randomly create it, 15 char passwords
- exceed NT4's max password length */
-
-#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
-
-
/*
filesystem attribute bits
*/
--
1.9.1
From 19b9aa4d5fb9dfbe9a3c02106f10964c3453d440 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Feb 2017 19:35:54 +0100
Subject: [PATCH 13/21] s4:libnet: make use of
generate_random_machine_password()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libnet/libnet_vampire.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index 91d951f..f74f9bb 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -160,7 +160,7 @@ NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
settings.realm = s->realm;
settings.domain = s->domain_name;
settings.server_dn_str = p->dest_dsa->server_dn_str;
- settings.machine_password = generate_random_password(s, 16, 255);
+ settings.machine_password = generate_random_machine_password(s, 128, 255);
settings.targetdir = s->targetdir;
settings.use_ntvfs = true;
status = provision_bare(s, s->lp_ctx, &settings, &result);
--
1.9.1
From 60d1f21ef6e99998ae7fb61d06d22781f850fd78 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Feb 2017 19:01:21 +0100
Subject: [PATCH 14/21] s4:dsdb: autogenerate a random utf16 buffer for krbtgt
password resets.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/dsdb/samdb/ldb_modules/password_hash.c | 84 ++++++++++++++++++++++++++
source4/dsdb/samdb/ldb_modules/samldb.c | 25 +++-----
2 files changed, 94 insertions(+), 15 deletions(-)
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 9b772a8..bd29377 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -35,6 +35,7 @@
#include "includes.h"
#include "ldb_module.h"
#include "libcli/auth/libcli_auth.h"
+#include "libcli/security/dom_sid.h"
#include "system/kerberos.h"
#include "auth/kerberos/kerberos.h"
#include "dsdb/samdb/samdb.h"
@@ -125,6 +126,7 @@ struct setup_password_fields_io {
const char *sAMAccountName;
const char *user_principal_name;
bool is_computer;
+ bool is_krbtgt;
uint32_t restrictions;
} u;
@@ -2793,6 +2795,8 @@ static int setup_io(struct ph_context *ac,
ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
int ret;
const struct ldb_message *info_msg = NULL;
+ struct dom_sid *account_sid = NULL;
+ int rodc_krbtgt = 0;
ZERO_STRUCTP(io);
@@ -2837,6 +2841,26 @@ static int setup_io(struct ph_context *ac,
"userPrincipalName", NULL);
io->u.is_computer = ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
+ /* Ensure it has an objectSID too */
+ account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
+ if (account_sid != NULL) {
+ NTSTATUS status;
+ uint32_t rid = 0;
+
+ status = dom_sid_split_rid(account_sid, account_sid, NULL, &rid);
+ if (NT_STATUS_IS_OK(status)) {
+ if (rid == DOMAIN_RID_KRBTGT) {
+ io->u.is_krbtgt = true;
+ }
+ }
+ }
+
+ rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
+ "msDS-SecondaryKrbTgtNumber", 0);
+ if (rodc_krbtgt != 0) {
+ io->u.is_krbtgt = true;
+ }
+
if (io->u.sAMAccountName == NULL) {
ldb_asprintf_errstring(ldb,
"setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
@@ -2867,6 +2891,12 @@ static int setup_io(struct ph_context *ac,
& (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
| UF_SERVER_TRUST_ACCOUNT));
+ if (io->u.is_krbtgt) {
+ io->u.restrictions = 0;
+ io->ac->status->domain_data.pwdHistoryLength =
+ MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
+ }
+
if (ac->userPassword) {
ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
ac->req->operation,
@@ -3172,6 +3202,59 @@ static int setup_io(struct ph_context *ac,
return ldb_operr(ldb);
}
+ if (io->u.is_krbtgt) {
+ size_t min = 196;
+ size_t max = 255;
+ size_t diff = max - min;
+ size_t len = max;
+ struct ldb_val *krbtgt_utf16 = NULL;
+
+ if (!ac->pwd_reset) {
+ return dsdb_module_werror(ac->module,
+ LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
+ WERR_DS_ATT_ALREADY_EXISTS,
+ "Password change on krbtgt not permitted!");
+ }
+
+ if (io->n.cleartext_utf16 == NULL) {
+ return dsdb_module_werror(ac->module,
+ LDB_ERR_UNWILLING_TO_PERFORM,
+ WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
+ "Password reset on krbtgt requires UTF16!");
+ }
+
+ /*
+ * Instead of taking the callers value,
+ * we just generate a new random value here.
+ *
+ * Include null termination in the array.
+ */
+ if (diff > 0) {
+ size_t tmp;
+
+ generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
+
+ tmp %= diff;
+
+ len = min + tmp;
+ }
+
+ krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
+ if (krbtgt_utf16 == NULL) {
+ return ldb_oom(ldb);
+ }
+
+ *krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
+ (len+1)*2);
+ if (krbtgt_utf16->data == NULL) {
+ return ldb_oom(ldb);
+ }
+ krbtgt_utf16->length = len * 2;
+ generate_secret_buffer(krbtgt_utf16->data,
+ krbtgt_utf16->length);
+ io->n.cleartext_utf16 = krbtgt_utf16;
+ }
+
if (existing_msg != NULL) {
NTSTATUS status;
@@ -4055,6 +4138,7 @@ static int password_hash_mod_search_self(struct ph_context *ac)
"badPasswordTime",
"badPwdCount",
"lockoutTime",
+ "msDS-SecondaryKrbTgtNumber",
NULL };
struct ldb_request *search_req;
int ret;
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index ea43ccc..2c47ff1 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -664,7 +664,6 @@ static int samldb_rodc_add(struct samldb_ctx *ac)
struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
uint32_t krbtgt_number, i_start, i;
int ret;
- char *newpass;
struct ldb_val newpass_utf16;
/* find a unused msDC-SecondaryKrbTgtNumber */
@@ -710,21 +709,17 @@ found:
return ldb_operr(ldb);
}
- newpass = generate_random_password(ac->msg, 128, 255);
- if (newpass == NULL) {
- return ldb_operr(ldb);
- }
-
- if (!convert_string_talloc(ac,
- CH_UNIX, CH_UTF16,
- newpass, strlen(newpass),
- (void *)&newpass_utf16.data,
- &newpass_utf16.length)) {
- ldb_asprintf_errstring(ldb,
- "samldb_rodc_add: "
- "failed to generate UTF16 password from random password");
- return LDB_ERR_OPERATIONS_ERROR;
+ newpass_utf16 = data_blob_talloc_zero(ac->module, 256);
+ if (newpass_utf16.data == NULL) {
+ return ldb_oom(ldb);
}
+ /*
+ * Note that the password_hash module will ignore
+ * this value and use it's own generate_secret_buffer()
+ * that's why we can just use generate_random_buffer()
+ * here.
+ */
+ generate_random_buffer(newpass_utf16.data, newpass_utf16.length);
ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
if (ret != LDB_SUCCESS) {
return ldb_operr(ldb);
--
1.9.1
From a9db138d1a0b0db44cae6d8538dadd58309aa574 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 17 Feb 2017 00:10:12 +0100
Subject: [PATCH 15/21] python/samba: provision_dns_add_samba.ldif expects
utf-16-le passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/join.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index 058fa08..6485468 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -708,7 +708,7 @@ class dc_join(object):
{"DNSDOMAIN": ctx.dnsdomain,
"DOMAINDN": ctx.base_dn,
"HOSTNAME" : ctx.myname,
- "DNSPASS_B64": b64encode(ctx.dnspass),
+ "DNSPASS_B64": b64encode(ctx.dnspass.encode('utf-16-le')),
"DNSNAME" : ctx.dnshostname}))
for changetype, msg in recs:
assert changetype == ldb.CHANGETYPE_NONE
--
1.9.1
From fe880743d811a109d701d0f1649c8501cccb5546 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Feb 2017 22:34:06 +0100
Subject: [PATCH 16/21] python/samba: use an explicit .encode('utf-8') where we
expect utf8 passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/join.py | 2 +-
python/samba/netcmd/user.py | 2 +-
python/samba/provision/__init__.py | 2 +-
python/samba/provision/sambadns.py | 2 +-
python/samba/samdb.py | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index 6485468..01c2260 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -880,7 +880,7 @@ class dc_join(object):
repl_creds.guess(ctx.lp)
repl_creds.set_kerberos_state(DONT_USE_KERBEROS)
repl_creds.set_username(ctx.samname)
- repl_creds.set_password(ctx.acct_pass)
+ repl_creds.set_password(ctx.acct_pass.encode('utf-8'))
else:
repl_creds = ctx.creds
diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py
index 4358170..f007ee5 100644
--- a/python/samba/netcmd/user.py
+++ b/python/samba/netcmd/user.py
@@ -683,7 +683,7 @@ class cmd_user_password(Command):
self.outf.write("Sorry, passwords do not match.\n")
try:
- net.change_password(password)
+ net.change_password(password.encode('utf-8'))
except Exception, msg:
# FIXME: catch more specific exception
raise CommandError("Failed to change password : %s" % msg)
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index 3187b65..ad269aa 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -877,7 +877,7 @@ def secretsdb_self_join(secretsdb, domain,
msg["msDS-KeyVersionNumber"] = [str(key_version_number)]
msg["privateKeytab"] = ["secrets.keytab"]
- msg["secret"] = [machinepass]
+ msg["secret"] = [machinepass.encode('utf-8')]
msg["samAccountName"] = ["%s$" % netbiosname]
msg["secureChannelType"] = [str(secure_channel_type)]
if domainsid is not None:
diff --git a/python/samba/provision/sambadns.py b/python/samba/provision/sambadns.py
index df4673b..2c69dd4 100644
--- a/python/samba/provision/sambadns.py
+++ b/python/samba/provision/sambadns.py
@@ -661,7 +661,7 @@ def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
"REALM": realm,
"DNSDOMAIN": dnsdomain,
"DNS_KEYTAB": dns_keytab_path,
- "DNSPASS_B64": b64encode(dnspass),
+ "DNSPASS_B64": b64encode(dnspass.encode('utf-8')),
"KEY_VERSION_NUMBER": str(key_version_number),
"HOSTNAME": names.hostname,
"DNSNAME" : '%s.%s' % (
diff --git a/python/samba/samdb.py b/python/samba/samdb.py
index eabe363..19dd8e9 100644
--- a/python/samba/samdb.py
+++ b/python/samba/samdb.py
@@ -503,7 +503,7 @@ member: %s
if len(res) > 1:
raise Exception('Matched %u multiple users with filter "%s"' % (len(res), search_filter))
user_dn = res[0].dn
- pw = unicode('"' + password + '"', 'utf-8').encode('utf-16-le')
+ pw = unicode('"' + password.encode('utf-8') + '"', 'utf-8').encode('utf-16-le')
setpw = """
dn: %s
changetype: modify
--
1.9.1
From 2d41b65ced3522b0ecc8cb7afda828811af7b661 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 09:35:50 +0200
Subject: [PATCH 17/21] pyglue: add generate_random_machine_password() wrapper
We use PyUnicode_FromString() (which is available from 2.6)
because we really have non-ascii strings.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/pyglue.c | 26 +++++++++++++++++++++++++-
python/samba/__init__.py | 1 +
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/python/pyglue.c b/python/pyglue.c
index dbe7eb4..0e80ba6 100644
--- a/python/pyglue.c
+++ b/python/pyglue.c
@@ -60,6 +60,23 @@ static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
return ret;
}
+static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *args)
+{
+ int min, max;
+ PyObject *ret;
+ char *retstr;
+ if (!PyArg_ParseTuple(args, "ii", &min, &max))
+ return NULL;
+
+ retstr = generate_random_machine_password(NULL, min, max);
+ if (retstr == NULL) {
+ return NULL;
+ }
+ ret = PyUnicode_FromString(retstr);
+ talloc_free(retstr);
+ return ret;
+}
+
static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
{
time_t t;
@@ -261,7 +278,14 @@ static PyMethodDef py_misc_methods[] = {
"Generate random string with specified length." },
{ "generate_random_password", (PyCFunction)py_generate_random_password,
METH_VARARGS, "generate_random_password(min, max) -> string\n"
- "Generate random password with a length >= min and <= max." },
+ "Generate random password (based on printable ascii characters) "
+ "with a length >= min and <= max." },
+ { "generate_random_machine_password", (PyCFunction)py_generate_random_machine_password,
+ METH_VARARGS, "generate_random_machine_password(min, max) -> string\n"
+ "Generate random password "
+ "(based on random utf16 characters converted to utf8 or "
+ "random ascii characters if 'unix charset' is not 'utf8')"
+ "with a length >= min (at least 14) and <= max (at most 255)." },
{ "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
"unix2nttime(timestamp) -> nttime" },
{ "nttime2unix", (PyCFunction)py_nttime2unix, METH_VARARGS,
diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 5f91531..19d5e38 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -396,6 +396,7 @@ nttime2string = _glue.nttime2string
nttime2unix = _glue.nttime2unix
unix2nttime = _glue.unix2nttime
generate_random_password = _glue.generate_random_password
+generate_random_machine_password = _glue.generate_random_machine_password
strcasecmp_m = _glue.strcasecmp_m
strstr_m = _glue.strstr_m
is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built
--
1.9.1
From 865916a11713d1dc78e63cedc46ade03248b1898 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:27:19 +0200
Subject: [PATCH 18/21] samba-tool:domain: use
generate_random_machine_password() for trusted domains
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/join.py | 3 ++-
python/samba/netcmd/domain.py | 29 +++++------------------------
2 files changed, 7 insertions(+), 25 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index 01c2260..b998997 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -1330,7 +1330,8 @@ def join_subdomain(logger=None, server=None, creds=None, lp=None, site=None,
ctx.domsid = security.random_sid()
ctx.acct_dn = None
ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain)
- ctx.trustdom_pass = samba.generate_random_password(128, 128)
+ # Windows uses 240 bytes as UTF16 so we do
+ ctx.trustdom_pass = samba.generate_random_machine_password(120, 120)
ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index 24bf4fc..de8d537 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -2265,33 +2265,14 @@ class cmd_domain_trust_create(DomainTrustCommand):
# needs to pass the NL_PASSWORD_VERSION structure within the
# 512 bytes and a 2 bytes confounder is required.
#
- def random_trust_secret(length, use_aes_keys=True):
- secret = [0] * length
-
- pw1 = samba.generate_random_password(length/2, length/2)
- if not use_aes_keys:
- # With arcfour-hmac-md5 we have to use valid utf16
- # in order to generate the correct pre-auth key
- # based on a utf8 password.
- #
- # We can remove this once our client libraries
- # support using the correct NTHASH.
- return string_to_byte_array(pw1.encode('utf-16-le'))
-
- # We mix characters from generate_random_password
- # with random numbers from random.randint()
- for i in range(len(secret)):
- if len(pw1) > i:
- secret[i] = ord(pw1[i])
- else:
- secret[i] = random.randint(0, 255)
-
- return secret
+ def random_trust_secret(length):
+ pw = samba.generate_random_machine_password(length/2, length/2)
+ return string_to_byte_array(pw.encode('utf-16-le'))
if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_INBOUND:
- incoming_secret = random_trust_secret(240, use_aes_keys=use_aes_keys)
+ incoming_secret = random_trust_secret(240)
if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
- outgoing_secret = random_trust_secret(240, use_aes_keys=use_aes_keys)
+ outgoing_secret = random_trust_secret(240)
remote_policy_access |= lsa.LSA_POLICY_TRUST_ADMIN
remote_policy_access |= lsa.LSA_POLICY_CREATE_SECRET
--
1.9.1
From 91bcdf41a3ca7131ebb885e09c65171591276603 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:37:37 +0200
Subject: [PATCH 19/21] samba-tool:domain: use
generate_random_machine_password() for machine passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/join.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index b998997..9b211ac 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -105,7 +105,7 @@ class dc_join(object):
if machinepass is not None:
ctx.acct_pass = machinepass
else:
- ctx.acct_pass = samba.generate_random_password(32, 40)
+ ctx.acct_pass = samba.generate_random_machine_password(128, 255)
ctx.dnsdomain = ctx.samdb.domain_dns_name()
if clone_only:
@@ -684,7 +684,7 @@ class dc_join(object):
pass
ctx.net.set_password(account_name=ctx.samname,
domain_name=ctx.domain_name,
- newpassword=ctx.acct_pass)
+ newpassword=ctx.acct_pass.encode('utf-8'))
res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE,
attrs=["msDS-KeyVersionNumber"])
--
1.9.1
From 0941141f39dac83a4ce1de876cab99088b64db73 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 23 Aug 2016 12:40:24 +0200
Subject: [PATCH 20/21] samba-tool:provision: use
generate_random_machine_password() for machine passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
python/samba/provision/__init__.py | 4 ++--
python/samba/upgradehelpers.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index ad269aa..81bbb0c 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -1768,9 +1768,9 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
invocationid = str(uuid.uuid4())
if krbtgtpass is None:
- krbtgtpass = samba.generate_random_password(128, 255)
+ krbtgtpass = samba.generate_random_machine_password(128, 255)
if machinepass is None:
- machinepass = samba.generate_random_password(128, 255)
+ machinepass = samba.generate_random_machine_password(128, 255)
if dnspass is None:
dnspass = samba.generate_random_password(128, 255)
diff --git a/python/samba/upgradehelpers.py b/python/samba/upgradehelpers.py
index 9b2c1c2..99ffe28 100644
--- a/python/samba/upgradehelpers.py
+++ b/python/samba/upgradehelpers.py
@@ -573,7 +573,7 @@ def update_machine_account_password(samdb, secrets_ldb, names):
assert(len(res) == 1)
msg = ldb.Message(res[0].dn)
- machinepass = samba.generate_random_password(128, 255)
+ machinepass = samba.generate_random_machine_password(128, 255)
mputf16 = machinepass.encode('utf-16-le')
msg["clearTextPassword"] = ldb.MessageElement(mputf16,
ldb.FLAG_MOD_REPLACE,
@@ -648,7 +648,7 @@ def update_krbtgt_account_password(samdb, names):
assert(len(res) == 1)
msg = ldb.Message(res[0].dn)
- machinepass = samba.generate_random_password(128, 255)
+ machinepass = samba.generate_random_machine_password(128, 255)
mputf16 = machinepass.encode('utf-16-le')
msg["clearTextPassword"] = ldb.MessageElement(mputf16,
ldb.FLAG_MOD_REPLACE,
--
1.9.1
From 5ab85408d28a7f52c950b07188cb392a825550f4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Feb 2017 19:37:09 +0100
Subject: [PATCH 21/21] s4:scripting: use generate_random_machine_password()
for machine passwords
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/scripting/bin/renamedc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/scripting/bin/renamedc b/source4/scripting/bin/renamedc
index 4494401..f14a837 100755
--- a/source4/scripting/bin/renamedc
+++ b/source4/scripting/bin/renamedc
@@ -95,7 +95,7 @@ if __name__ == '__main__':
# Then change password and samaccountname and dnshostname
msg = ldb.Message(newdn)
- machinepass = samba.generate_random_password(128, 255)
+ machinepass = samba.generate_random_machine_password(128, 255)
mputf16 = machinepass.encode('utf-16-le')
account = "%s$" % opts.newname.upper()
--
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170220/eeee7562/signature.sig>
More information about the samba-technical
mailing list