From 2f3601e1a1e3c395c1eb0bdfae66c5698ca9e5ce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jan 2017 19:02:21 +0000 Subject: [PATCH 01/13] 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 366329e75d4858e37372e23b0aba90295fe886cf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Feb 2017 21:47:52 +0100 Subject: [PATCH 02/13] 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 38f3409dd86a308e9d9dfe8a209b6285993b223c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 09:30:05 +0200 Subject: [PATCH 03/13] 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 1f265e8..89f0535 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 e8720c21c7a679b5b51d7161a4cde936285fe2cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jan 2017 19:57:30 +0100 Subject: [PATCH 04/13] 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 d18d9b73508806a728e29cd8e32ba08124fc68c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 9 Feb 2017 22:53:52 +0100 Subject: [PATCH 05/13] 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 d33bf1271bdab5f3f4398f8bb0aafc717128cdc0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:12:35 +0200 Subject: [PATCH 06/13] 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 62cd257..c29e266 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -882,6 +882,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 823d4ea121099b801f5f27eeb232727eee1fedea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:12:35 +0200 Subject: [PATCH 07/13] 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 8786d492354c24483cdd391a995c368e01350e24 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 10:38:58 +0200 Subject: [PATCH 08/13] 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 75623dd..dabe262b 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -451,7 +451,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 6236051d8966f3a2826e424f05eab3298e5e21a0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:09:57 +0200 Subject: [PATCH 09/13] 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 bab58f3..7e0afc1 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1128,9 +1128,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; @@ -1223,9 +1225,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 95bbde1875cfcc41a9836b040dfd1789c5125efa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 10:42:30 +0200 Subject: [PATCH 10/13] 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 79b6019ea6336fabf796ea56543c117ab3361c35 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:41:48 +0200 Subject: [PATCH 11/13] 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 7eeef88..a9a4fbe 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -736,12 +736,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 d847b7609e6d017b1f657512c9f7776fac99b79e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Aug 2016 12:41:48 +0200 Subject: [PATCH 12/13] 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 1683b67491215b7355404cf41b67ec8eaa25e30a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Feb 2017 12:15:07 +0100 Subject: [PATCH 13/13] 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 6cfd498..7f0ba4a 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 @@ -165,6 +166,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