From 50dc246836014da29c1b6273a03c673e3f38bd58 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jan 2017 19:02:21 +0000 Subject: [PATCH 01/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 8a209e5a0ca810d8cf0e5ebc1902fae8c5cb241e) --- 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 1590ca3729b37416f7792cef34a1fed6dfba255e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Feb 2017 21:47:52 +0100 Subject: [PATCH 02/22] libcli/auth: add netlogon_creds_cli_debug_string() BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme (cherry picked from commit abe427775ee8ed1d278d5094ca127f85289ca5a3) --- 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 628dd6277dd5e48bb94421d81f2e61d7c56d3ad6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 09:30:05 +0200 Subject: [PATCH 03/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit ad12cfae42cc592166d6a1c1ee323f1aae82f235) --- 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 c339161..9ef9ef9 100644 --- a/lib/util/samba_util.h +++ b/lib/util/samba_util.h @@ -103,11 +103,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 08d0d0b0ee91229e724813e855a4b2778478e0cc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jan 2017 19:57:30 +0100 Subject: [PATCH 04/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 4185689dbf0085fcb3840ad8b520df21a33e5d2a) --- 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 1c0315ed17cc676829028f021ccf067a51321c5e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Feb 2017 22:53:52 +0100 Subject: [PATCH 05/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit a2877541681e07f09aee7d7c21adbe50346755e3) --- 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 bc236a1ec0052143fd6c63d2efee7fd07f55d9c9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:12:35 +0200 Subject: [PATCH 06/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 9e26ad86fbd7e6f39f98fb9d037ac86f3146cb11) --- 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 0aa1009..25f43f5 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -880,6 +880,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 000242d525a61a1a12233254e71f95d175bd1e14 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:12:35 +0200 Subject: [PATCH 07/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit c21e9981d04fa016ef708941ea82051d0438b7a7) --- 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 b404a1ed19b646512ae2e586bacf6bdedb1e3661 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 10:38:58 +0200 Subject: [PATCH 08/22] 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 Reviewed-by: Ralph Boehme (similar to commit 00136940757ea6947f97c9c92b25207d9413727b) --- source3/libads/util.c | 9 ++++++--- source3/wscript_build | 2 +- 2 files changed, 7 insertions(+), 4 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 d19b583..2918975 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -455,7 +455,7 @@ bld.SAMBA3_LIBRARY('ads', libads/ldap_schema.c libads/util.c libads/ndr.c''', - deps='cli-ldap-common krb5samba ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap', + deps='cli-ldap-common krb5samba ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap trusts_util', private_library=True) bld.SAMBA3_SUBSYSTEM('LIBADS_SERVER', -- 1.9.1 From 53063ee8eed75dd3dd50b918a66bba1a354a0762 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:09:57 +0200 Subject: [PATCH 09/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 77edef9555acd6e0c843582637bc367fa0d2a203) --- 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 3d66eaf..8f8baff 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 5bd4263147cc64e21a5a9a9cd4ac405dcbad9bc3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 10:42:30 +0200 Subject: [PATCH 10/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 13fd543929c72fa5af1ae6e21ca8dda9a57a0f55) --- 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 3038f2e60a0e5df75fe82c4ad3797b6252985e68 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:41:48 +0200 Subject: [PATCH 11/22] s3:include: remove unused DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme (cherry picked from commit 21cbf8e4db6928a8a3fb712b3750bb50c1201948) --- source3/include/smb.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source3/include/smb.h b/source3/include/smb.h index 0af3b61..cc00e87 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -733,12 +733,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 53ada558aab656973d3b01a6f73f38114158e0d4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:41:48 +0200 Subject: [PATCH 12/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit e9c184088cbbb47e48d9e96fc753a56c544301dc) --- 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 db92fc7b185fdd0746b65b3eb2b5533d63ee8898 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Feb 2017 19:35:54 +0100 Subject: [PATCH 13/22] s4:libnet: make use of generate_random_machine_password() BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262 Signed-off-by: Stefan Metzmacher (cherry picked from commit 26515dca99ba3fa393207df905137021a2177de1) --- 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 da77f88f9c861002abdc7fc77ed98dd6c7283d86 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Feb 2017 19:01:21 +0100 Subject: [PATCH 14/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 0ed258bfe48995db6b345cc14e1747c4af9d076d) --- 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 bb8679c..e5bee6f 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 b33cf24..8459210 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -386,7 +386,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 */ @@ -432,21 +431,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 23f00d89df9e23950a91aefac05ce605bce67e3b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Feb 2017 00:10:12 +0100 Subject: [PATCH 15/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 99b8d6beccf4d3d24f9d87a4d8e5eadfe0e0dd33) --- 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 a50a409..c77cff8 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -691,7 +691,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 04b2d67b7ab5bd688a191b189cc488eb6e8d019d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Feb 2017 22:34:06 +0100 Subject: [PATCH 16/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit b86c29b1e6fb2fb4cf203aa38c7764084d855730) --- 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 c77cff8..13680ee 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -863,7 +863,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 5adc287..2cceea8 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -670,7 +670,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 344766e..19fab25 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 ed338f0746076aee703cb3a5f25f7c4efded76ed Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 09:35:50 +0200 Subject: [PATCH 17/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit d7840e77961cdc4ccc4f5549494d458b6b2c2cf4) --- 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 dcc0795838ff58686325fdda6d2eadb0da8a4064 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:27:19 +0200 Subject: [PATCH 18/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit b2fac99ac63739398aa716c26d8e187a25bb8400) --- 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 13680ee..1a34a02 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -1314,7 +1314,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 cfdd9a4..97d81c4 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -2254,33 +2254,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 3ab413d941bad1e7806640d048de91906150fa61 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:37:37 +0200 Subject: [PATCH 19/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit f04e09e1968c40483b8dc2f92b9c15bce0b0b55a) --- 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 1a34a02..98c9fa7 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -104,7 +104,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: @@ -667,7 +667,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 251ede419c9c10d9af275ebd2ba4ca80c3349331 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:40:24 +0200 Subject: [PATCH 20/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit ea57a204a1f6b4999e5347c1edb5753bed933fba) --- 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 19fab25..d981c66 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 45820f19d7c331cc0c2e68cc7b80c0fd74913f8a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 13 Feb 2017 19:37:09 +0100 Subject: [PATCH 21/22] 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 Reviewed-by: Ralph Boehme (cherry picked from commit 383432d2cd3046c2c3768c1ae452211c7e583604) --- 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 From 2b8854114cb562e98f1ae7f957085433397a1dd6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Feb 2017 12:15:07 +0100 Subject: [PATCH 22/22] krb5_wrap: use our own code to calculate the ENCTYPE_ARCFOUR_HMAC key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our own convert_string_talloc() function handles a wider range of unicode code points than the MIT krb5 or heimdal code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Tue Feb 21 20:08:16 CET 2017 on sn-devel-144 (similar to commit 10e1b92c288ae27f775debb16c3e122b6063fa21) --- lib/krb5_wrap/krb5_samba.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index 2943b33..76e8795 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -24,6 +24,7 @@ #include "system/filesys.h" #include "krb5_samba.h" #include "lib/util/asn1.h" +#include "lib/crypto/crypto.h" #ifdef HAVE_COM_ERR_H #include @@ -202,6 +203,42 @@ int smb_krb5_create_key_from_string(krb5_context context, return -1; } + if ((int)enctype == (int)ENCTYPE_ARCFOUR_HMAC) { + TALLOC_CTX *frame = talloc_stackframe(); + uint8_t *utf16 = NULL; + size_t utf16_size = 0; + uint8_t nt_hash[16]; + bool ok; + + ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16LE, + password->data, password->length, + (void **)&utf16, &utf16_size); + if (!ok) { + if (errno == 0) { + errno = EINVAL; + } + ret = errno; + TALLOC_FREE(frame); + return ret; + } + + mdfour(nt_hash, utf16, utf16_size); + memset(utf16, 0, utf16_size); + ret = smb_krb5_keyblock_init_contents(context, + ENCTYPE_ARCFOUR_HMAC, + nt_hash, + sizeof(nt_hash), + key); + ZERO_STRUCT(nt_hash); + if (ret != 0) { + TALLOC_FREE(frame); + return ret; + } + + TALLOC_FREE(frame); + return 0; + } + #if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_C_STRING_TO_KEY) {/* MIT */ krb5_data _salt; -- 1.9.1