From 951466000c05cd9824c3a6361be707bf55a23550 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 12 Dec 2007 18:03:20 +0100 Subject: Fix for bug #4801: Correctly implement lsa lookup levels for lookupnames. This is a first patch aimed at fixing bug #4801. It is still incomplete in that winbindd does not walk the the trusted domains to lookup unqualified names here. Apart from that this fix should be pretty much complete. Michael (This used to be commit dd320c0924ce393a89b1cab020fd5cffc5b80380) --- source3/passdb/lookup_sid.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index bb54959e96..54db14fbfe 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -59,16 +59,19 @@ bool lookup_name(TALLOC_CTX *mem_ctx, name = talloc_strdup(tmp_ctx, full_name); } - DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", - full_name, domain, name)); - if ((domain == NULL) || (name == NULL)) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(tmp_ctx); return false; } - if (strequal(domain, get_global_sam_name())) { + DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n", + full_name, domain, name)); + DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags)); + + if ((flags & LOOKUP_NAME_DOMAIN) && + strequal(domain, get_global_sam_name())) + { /* It's our own domain, lookup the name in passdb */ if (lookup_global_sam_name(name, flags, &rid, &type)) { @@ -80,8 +83,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, return false; } - if (strequal(domain, builtin_domain_name())) { - + if ((flags & LOOKUP_NAME_BUILTIN) && + strequal(domain, builtin_domain_name())) + { /* Explicit request for a name in BUILTIN */ if (lookup_builtin_name(name, &rid)) { sid_copy(&sid, &global_sid_Builtin); @@ -97,6 +101,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, * domain yet at this point yet. This comes later. */ if ((domain[0] != '\0') && + (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) && (winbind_lookup_name(domain, name, &sid, &type))) { goto ok; } @@ -131,14 +136,18 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* 1. well-known names */ - if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) { + if ((flags & LOOKUP_NAME_WKN) && + lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) + { type = SID_NAME_WKN_GRP; goto ok; } /* 2. Builtin domain as such */ - if (strequal(name, builtin_domain_name())) { + if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) && + strequal(name, builtin_domain_name())) + { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; sid_copy(&sid, &global_sid_Builtin); @@ -148,7 +157,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* 3. Account domain */ - if (strequal(name, get_global_sam_name())) { + if ((flags & LOOKUP_NAME_DOMAIN) && + strequal(name, get_global_sam_name())) + { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch my SID\n")); TALLOC_FREE(tmp_ctx); @@ -162,7 +173,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* 4. Primary domain */ - if (!IS_DC && strequal(name, lp_workgroup())) { + if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC && + strequal(name, lp_workgroup())) + { if (!secrets_fetch_domain_sid(name, &sid)) { DEBUG(3, ("Could not fetch the domain SID\n")); TALLOC_FREE(tmp_ctx); @@ -177,7 +190,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* 5. Trusted domains as such, to me it looks as if members don't do this, tested an XP workstation in a NT domain -- vl */ - if (IS_DC && (pdb_get_trusteddom_pw(name, NULL, &sid, NULL))) { + if ((flags & LOOKUP_NAME_REMOTE) && IS_DC && + (secrets_fetch_trusted_domain_password(name, NULL, &sid, NULL))) + { /* Swap domain and name */ tmp = name; name = domain; domain = tmp; type = SID_NAME_DOMAIN; @@ -186,7 +201,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* 6. Builtin aliases */ - if (lookup_builtin_name(name, &rid)) { + if ((flags & LOOKUP_NAME_BUILTIN) && + lookup_builtin_name(name, &rid)) + { domain = talloc_strdup(tmp_ctx, builtin_domain_name()); sid_copy(&sid, &global_sid_Builtin); sid_append_rid(&sid, rid); @@ -199,7 +216,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* Both cases are done by looking at our passdb */ - if (lookup_global_sam_name(name, flags, &rid, &type)) { + if ((flags & LOOKUP_NAME_DOMAIN) && + lookup_global_sam_name(name, flags, &rid, &type)) + { domain = talloc_strdup(tmp_ctx, get_global_sam_name()); sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); -- cgit From b99a6b0e8c3ca57666c16a9228337338033df1c1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 10 Dec 2007 23:53:55 +0100 Subject: Remove two unneeded functions. secrets_store_trust_account_password() and trust_password_delete() are the write access functions to the SECRETS/$MACHINE.ACC/domain keys in secrets.tdb, the md4 hashed machine passwords. These are not used any more: Current code always writes the clear text password. Michael (This used to be commit 4788fe392427901f6b1c505e3a743136ac8a91ca) --- source3/passdb/secrets.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index a4cb76602a..3466f24533 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -558,20 +558,6 @@ bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd, return True; } -/************************************************************************ - Routine to set the trust account password for a domain. -************************************************************************/ - -bool secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16]) -{ - struct machine_acct_pass pass; - - pass.mod_time = time(NULL); - memcpy(pass.hash, new_pwd, 16); - - return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass)); -} - /** * Routine to store the password for trusted domain * @@ -721,15 +707,6 @@ char *secrets_fetch_machine_password(const char *domain, return ret; } -/************************************************************************ - Routine to delete the machine trust account password file for a domain. -************************************************************************/ - -bool trust_password_delete(const char *domain) -{ - return secrets_delete(trust_keystr(domain)); -} - /************************************************************************ Routine to delete the password for trusted domain ************************************************************************/ -- cgit From f793c99ca54d62cb8142607e8449f5b5b3a5e79d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 13:05:44 +0100 Subject: Let get_trust_pw() determine the machine_account_name to use. Up to now each caller used its own logic. This eliminates code paths where there was a special treatment of the following situation: the domain given is not our workgroup (i.e. our own domain) and we are not a DC (i.e. it is not a typical trusted domain situation). In situation the given domain name was previously used as the machine account name, resulting in an account name of DOMAIN\\DOMAIN$, which does not seem very reasonable to me. get_trust_pw would not have obtained a password in this situation anyways. I hope I have not missed an important point here! Michael (This used to be commit 6ced4a7f88798dc449a667d63bc29bf6c569291f) --- source3/passdb/passdb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 2a4d4c4a0a..f9b972da9b 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1523,10 +1523,12 @@ bool pdb_increment_bad_password_count(struct samu *sampass) /******************************************************************* - Wrapper around retrieving the trust account password + Wrapper around retrieving the trust account password. + appropriate account name is stored in account_name. *******************************************************************/ -bool get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel) +bool get_trust_pw(const char *domain, uint8 ret_pwd[16], + const char **account_name, uint32 *channel) { DOM_SID sid; char *pwd; @@ -1550,6 +1552,10 @@ bool get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel) E_md4hash(pwd, ret_pwd); SAFE_FREE(pwd); + if (account_name != NULL) { + *account_name = lp_workgroup(); + } + return True; } @@ -1558,7 +1564,13 @@ bool get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel) if (secrets_fetch_trust_account_password(domain, ret_pwd, &last_set_time, channel)) + { + if (account_name != NULL) { + *account_name = global_myname(); + } + return True; + } DEBUG(5, ("get_trust_pw: could not fetch trust account " "password for domain %s\n", domain)); -- cgit From fe969f9a7fdf823b7701d4cc4cfd55dac81ca90e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:02:45 +0100 Subject: Refactor the lagacy part of secrets_fetch_trust_account_password() out into a new function secrets_fetch_trust_account_password_legacy() that does only try to obtain the hashed version of the machine password directly from secrets.tdb. Michael (This used to be commit 91da12b751b3168dc40049f3e90c10d840393efc) --- source3/passdb/secrets.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 3466f24533..fde7fc0968 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -284,27 +284,19 @@ uint32 get_default_sec_channel(void) /************************************************************************ Routine to get the trust account password for a domain. + This only tries to get the legacy hashed version of the password. The user of this function must have locked the trust password file using the above secrets_lock_trust_account_password(). ************************************************************************/ -bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], - time_t *pass_last_set_time, - uint32 *channel) +bool secrets_fetch_trust_account_password_legacy(const char *domain, + uint8 ret_pwd[16], + time_t *pass_last_set_time, + uint32 *channel) { struct machine_acct_pass *pass; - char *plaintext; size_t size = 0; - plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, - channel); - if (plaintext) { - DEBUG(4,("Using cleartext machine password\n")); - E_md4hash(plaintext, ret_pwd); - SAFE_FREE(plaintext); - return True; - } - if (!(pass = (struct machine_acct_pass *)secrets_fetch( trust_keystr(domain), &size))) { DEBUG(5, ("secrets_fetch failed!\n")); @@ -337,6 +329,32 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], return True; } +/************************************************************************ + Routine to get the trust account password for a domain. + The user of this function must have locked the trust password file using + the above secrets_lock_trust_account_password(). +************************************************************************/ + +bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], + time_t *pass_last_set_time, + uint32 *channel) +{ + char *plaintext; + + plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, + channel); + if (plaintext) { + DEBUG(4,("Using cleartext machine password\n")); + E_md4hash(plaintext, ret_pwd); + SAFE_FREE(plaintext); + return True; + } + + return secrets_fetch_trust_account_password_legacy(domain, ret_pwd, + pass_last_set_time, + channel); +} + /** * Pack SID passed by pointer * -- cgit From 1084151442552e63c0b9b310273d8d42711aa55c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 13:59:54 +0100 Subject: Export logic of get_trust_pw() to new function get_trust_pw_clear(). get_trust_pw() just now computes the md4 hash of the result of get_trust_pw_clear() if that was successful. As a last resort, in the non-trusted-domain-situation, get_trust_pw() now tries to directly obtain the hashed version of the password out of secrets.tdb. Michael (This used to be commit 4562342eb84e6fdcec15d8b7ae83aa146aabe2b7) --- source3/passdb/passdb.c | 74 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 16 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index f9b972da9b..488458fc85 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1521,58 +1521,100 @@ bool pdb_increment_bad_password_count(struct samu *sampass) return True; } +bool is_trusted_domain_situation(const char *domain_name) +{ + return IS_DC && + lp_allow_trusted_domains() && + !strequal(domain_name, lp_workgroup()); +} /******************************************************************* - Wrapper around retrieving the trust account password. + Wrapper around retrieving the clear text trust account password. appropriate account name is stored in account_name. + Caller must free password, but not account_name. *******************************************************************/ -bool get_trust_pw(const char *domain, uint8 ret_pwd[16], - const char **account_name, uint32 *channel) +bool get_trust_pw_clear(const char *domain, char **ret_pwd, + const char **account_name, uint32 *channel) { DOM_SID sid; char *pwd; time_t last_set_time; /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ + * for the domain trust */ - if (IS_DC && !strequal(domain, lp_workgroup()) && - lp_allow_trusted_domains()) - { - if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &last_set_time)) + if (is_trusted_domain_situation(domain)) { + if (!pdb_get_trusteddom_pw(domain, ret_pwd, &sid, + &last_set_time)) { DEBUG(0, ("get_trust_pw: could not fetch trust " "account password for trusted domain %s\n", domain)); - return False; + return false; } *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); if (account_name != NULL) { *account_name = lp_workgroup(); } - return True; + return true; } /* Just get the account for the requested domain. In the future this * might also cover to be member of more than one domain. */ - if (secrets_fetch_trust_account_password(domain, ret_pwd, - &last_set_time, channel)) + pwd = secrets_fetch_machine_password(domain, &last_set_time, channel); + + if (pwd != NULL) { + *ret_pwd = pwd; + if (account_name != NULL) { + *account_name = global_myname(); + } + + return true; + } + + DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust " + "account password for domain %s\n", domain)); + return false; +} + +/******************************************************************* + Wrapper around retrieving the trust account password. + appropriate account name is stored in account_name. +*******************************************************************/ + +bool get_trust_pw(const char *domain, uint8 ret_pwd[16], + const char **account_name, uint32 *channel) +{ + char *pwd = NULL; + time_t last_set_time; + + if (get_trust_pw_clear(domain, &pwd, account_name, channel)) { + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + return true; + } else if (is_trusted_domain_situation(domain)) { + return false; + } + + /* as a fallback, try to get the hashed pwd directly from the tdb... */ + + if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd, + &last_set_time, + channel)) { if (account_name != NULL) { *account_name = global_myname(); } - return True; + return true; } - DEBUG(5, ("get_trust_pw: could not fetch trust account " + DEBUG(5, ("get_trust_pw_hash: could not fetch trust account " "password for domain %s\n", domain)); return False; } -- cgit From 31f221ed9316c8dc2f4911d7b8ddcdf8b74367db Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:07:32 +0100 Subject: Rename get_trust_pw() to get_trust_pw_hash(). Michael (This used to be commit 0cde7ac9cb39a0026a38ccf66dbecefc12931074) --- source3/passdb/passdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 488458fc85..11c5b68197 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1587,8 +1587,8 @@ bool get_trust_pw_clear(const char *domain, char **ret_pwd, appropriate account name is stored in account_name. *******************************************************************/ -bool get_trust_pw(const char *domain, uint8 ret_pwd[16], - const char **account_name, uint32 *channel) +bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16], + const char **account_name, uint32 *channel) { char *pwd = NULL; time_t last_set_time; -- cgit From ce76bcff29819056dc7a4aac0c3468022a7485f1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:12:49 +0100 Subject: Pass NULL instead of unneeded &sid: pdb_get_trusteddom_pw() checks. Michael (This used to be commit b2e12365b56f24586a7dfcb845f4de51f0b0e7d5) --- source3/passdb/passdb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 11c5b68197..c4248bb48e 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1537,7 +1537,6 @@ bool is_trusted_domain_situation(const char *domain_name) bool get_trust_pw_clear(const char *domain, char **ret_pwd, const char **account_name, uint32 *channel) { - DOM_SID sid; char *pwd; time_t last_set_time; @@ -1545,7 +1544,7 @@ bool get_trust_pw_clear(const char *domain, char **ret_pwd, * for the domain trust */ if (is_trusted_domain_situation(domain)) { - if (!pdb_get_trusteddom_pw(domain, ret_pwd, &sid, + if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL, &last_set_time)) { DEBUG(0, ("get_trust_pw: could not fetch trust " -- cgit