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 +++++++++++++++++++++++++++++------------ source3/rpc_server/srv_lsa_nt.c | 37 ++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 22 deletions(-) (limited to 'source3') 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); diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 20655082a5..c5f0c7b6ab 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1035,6 +1035,31 @@ NTSTATUS _lsa_lookup_sids3(pipes_struct *p, return r_u->status; } +static int lsa_lookup_level_to_flags(uint16 level) +{ + int flags; + + switch (level) { + case 1: + flags = LOOKUP_NAME_ALL; + break; + case 2: + flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_REMOTE|LOOKUP_NAME_ISOLATED; + break; + case 3: + flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED; + break; + case 4: + case 5: + case 6: + default: + flags = LOOKUP_NAME_NONE; + break; + } + + return flags; +} + /*************************************************************************** lsa_reply_lookup_names ***************************************************************************/ @@ -1054,10 +1079,7 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries)); } - /* Probably the lookup_level is some sort of bitmask. */ - if (q_u->lookup_level == 1) { - flags = LOOKUP_NAME_ALL; - } + flags = lsa_lookup_level_to_flags(q_u->lookup_level); ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); if (!ref) { @@ -1123,11 +1145,8 @@ NTSTATUS _lsa_lookup_names2(pipes_struct *p, LSA_Q_LOOKUP_NAMES2 *q_u, LSA_R_LOO num_entries = MAX_LOOKUP_SIDS; DEBUG(5,("_lsa_lookup_names2: truncating name lookup list to %d\n", num_entries)); } - - /* Probably the lookup_level is some sort of bitmask. */ - if (q_u->lookup_level == 1) { - flags = LOOKUP_NAME_ALL; - } + + flags = lsa_lookup_level_to_flags(q_u->lookup_level); ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF); if (ref == NULL) { -- 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') 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 4884f5d23af41a0b88b98a0485cb3935beb820fe Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 08:52:20 +0100 Subject: In cm_prepare_connection(), only get auth user creds if we need to. Michael (This used to be commit 164bfb25d7b5cfeffeb4d81958b7629a11ca5d5e) --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 3f6544965d..0a96e04052 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -676,8 +676,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -795,6 +793,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, (*cli)->use_kerberos = False; + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && (strlen(ipc_username) > 0)) { -- cgit From 5d9c97703432bbca7d45948708b5b21a3718559a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 12:47:28 +0100 Subject: Streamline logic in cm_connect_netlogon() by retrieving trust password only, when it will be used. Michael (This used to be commit cdc60d8ae8c0ef804206b20b451e9557f97d4439) --- source3/winbindd/winbindd_cm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0a96e04052..d5c8b9955f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2219,10 +2219,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); if (netlogon_pipe == NULL) { @@ -2234,11 +2230,16 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags &= ~NETLOGON_NEG_SCHANNEL; goto no_schannel; } - + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; } + if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { + cli_rpc_pipe_close(netlogon_pipe); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + /* if we are a DC and this is a trusted domain, then we need to use our domain name in the net_req_auth2() request */ -- 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/auth/auth_domain.c | 7 +++++-- source3/passdb/passdb.c | 16 ++++++++++++++-- source3/rpc_client/cli_pipe.c | 38 ++++++-------------------------------- source3/winbindd/winbindd_cm.c | 22 +++------------------- 4 files changed, 28 insertions(+), 55 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 7cddabbbbd..b428723a06 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -127,8 +127,11 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; + const char *account_name; - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + if (!get_trust_pw(domain, machine_pwd, &account_name, + &sec_chan_type)) + { DEBUG(0, ("connect_to_domain_password_server: could not fetch " "trust account password for domain '%s'\n", domain)); @@ -142,7 +145,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); dc_name, /* server name */ domain, /* domain */ global_myname(), /* client name */ - global_myname(), /* machine account name */ + account_name, /* machine account name */ machine_pwd, sec_chan_type, &neg_flags); 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)); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 37558a7ff0..bf019c89a1 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2436,7 +2436,7 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, struct rpc_pipe_client *netlogon_pipe = NULL; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; - fstring machine_account; + const char *machine_account; netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); if (!netlogon_pipe) { @@ -2444,7 +2444,8 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, } /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + if (!get_trust_pw(domain, machine_pwd, &machine_account, &sec_chan_type)) + { DEBUG(0, ("get_schannel_session_key: could not fetch " "trust account password for domain '%s'\n", domain)); @@ -2453,20 +2454,6 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, return NULL; } - /* A DC should use DOMAIN$ as its account name. - A member server can only use it's machine name since it - does not have an account in a trusted domain. - - We don't check the domain against lp_workgroup() here since - 'net ads join' has to continue to work with only the realm - specified in smb.conf. -- jerry */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) { - fstrcpy( machine_account, lp_workgroup() ); - } else { - fstrcpy(machine_account, global_myname()); - } - *perr = rpccli_netlogon_setup_creds(netlogon_pipe, cli->desthost, /* server name */ domain, /* domain */ @@ -2562,7 +2549,7 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ struct rpc_pipe_client *netlogon_pipe = NULL; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; - fstring machine_account; + const char *machine_account; netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr); if (!netlogon_pipe) { @@ -2570,7 +2557,8 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ } /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + if (!get_trust_pw(domain, machine_pwd, &machine_account, &sec_chan_type)) + { DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch " "trust account password for domain '%s'\n", domain)); @@ -2579,20 +2567,6 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ return NULL; } - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) { - fstrcpy( machine_account, lp_workgroup() ); - } else { - /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */ - if (strequal(domain, lp_workgroup())) { - fstrcpy(machine_account, global_myname()); - } else { - fstrcpy(machine_account, domain); - } - } - *perr = rpccli_netlogon_setup_creds(netlogon_pipe, cli->desthost, /* server name */ domain, /* domain */ diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d5c8b9955f..adb9d11edc 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,27 +2235,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC - && !strequal(domain->name, lp_workgroup()) - && lp_allow_trusted_domains() ) + if (!get_trust_pw(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { - account_name = lp_workgroup(); - } else { - account_name = domain->primary ? - global_myname() : domain->name; - } - - if (account_name == NULL) { cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_NO_MEMORY; + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } result = rpccli_netlogon_setup_creds( -- 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') 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') 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/auth/auth_domain.c | 4 ++-- source3/passdb/passdb.c | 4 ++-- source3/rpc_client/cli_pipe.c | 6 ++++-- source3/winbindd/winbindd_cm.c | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index b428723a06..b2c87174fd 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -129,8 +129,8 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); unsigned char machine_pwd[16]; const char *account_name; - if (!get_trust_pw(domain, machine_pwd, &account_name, - &sec_chan_type)) + if (!get_trust_pw_hash(domain, machine_pwd, &account_name, + &sec_chan_type)) { DEBUG(0, ("connect_to_domain_password_server: could not fetch " "trust account password for domain '%s'\n", 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; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index bf019c89a1..9f1d9c6e3e 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2444,7 +2444,8 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, } /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &machine_account, &sec_chan_type)) + if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, + &sec_chan_type)) { DEBUG(0, ("get_schannel_session_key: could not fetch " "trust account password for domain '%s'\n", @@ -2557,7 +2558,8 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ } /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw(domain, machine_pwd, &machine_account, &sec_chan_type)) + if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, + &sec_chan_type)) { DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch " "trust account password for domain '%s'\n", diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index adb9d11edc..d8040d79ac 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,8 +2235,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &account_name, - &sec_chan_type)) + if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; -- 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') 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 From 7cf5c17f12328d100fca7979a292ea22165bf80b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:36:11 +0100 Subject: Refactoring out get_schannel_session_key logic. Refactor the actual retrieval of the session key through the established netlogon pipe out of get_schannel_session_key() and get_schannel_session_key_auth_ntlmssp() into a new function get_schannel_session_key_common(). (To avoid code duplication.) Michael (This used to be commit e77c4022cfbb868e608edcb06b676658b0e201ad) --- source3/rpc_client/cli_pipe.c | 92 ++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 53 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 9f1d9c6e3e..f61ea95d04 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2424,25 +2424,18 @@ struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli, } /**************************************************************************** - Open a netlogon pipe and get the schannel session key. - Now exposed to external callers. + Get a the schannel session key out of an already opened netlogon pipe. ****************************************************************************/ - -struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, - const char *domain, - uint32 *pneg_flags, - NTSTATUS *perr) +static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, + struct cli_state *cli, + const char *domain, + uint32 *pneg_flags, + NTSTATUS *perr) { - struct rpc_pipe_client *netlogon_pipe = NULL; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; const char *machine_account; - netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); - if (!netlogon_pipe) { - return NULL; - } - /* Get the machine account credentials from secrets.tdb. */ if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, &sec_chan_type)) @@ -2450,9 +2443,8 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, DEBUG(0, ("get_schannel_session_key: could not fetch " "trust account password for domain '%s'\n", domain)); - cli_rpc_pipe_close(netlogon_pipe); *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return NULL; + return false; } *perr = rpccli_netlogon_setup_creds(netlogon_pipe, @@ -2465,11 +2457,10 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, pneg_flags); if (!NT_STATUS_IS_OK(*perr)) { - DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds " + DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds " "failed with result %s to server %s, domain %s, machine account %s.\n", nt_errstr(*perr), cli->desthost, domain, machine_account )); - cli_rpc_pipe_close(netlogon_pipe); - return NULL; + return false; } if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { @@ -2477,6 +2468,34 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, cli->desthost)); cli_rpc_pipe_close(netlogon_pipe); *perr = NT_STATUS_INVALID_NETWORK_RESPONSE; + return false; + } + + return true; +} + +/**************************************************************************** + Open a netlogon pipe and get the schannel session key. + Now exposed to external callers. + ****************************************************************************/ + + +struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, + const char *domain, + uint32 *pneg_flags, + NTSTATUS *perr) +{ + struct rpc_pipe_client *netlogon_pipe = NULL; + + netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); + if (!netlogon_pipe) { + return NULL; + } + + if (!get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags, perr)) + { + cli_rpc_pipe_close(netlogon_pipe); return NULL; } @@ -2548,49 +2567,16 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_ NTSTATUS *perr) { struct rpc_pipe_client *netlogon_pipe = NULL; - uint32 sec_chan_type = 0; - unsigned char machine_pwd[16]; - const char *machine_account; netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr); if (!netlogon_pipe) { return NULL; } - /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, - &sec_chan_type)) + if (!get_schannel_session_key_common(netlogon_pipe, cli, domain, + pneg_flags, perr)) { - DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch " - "trust account password for domain '%s'\n", - domain)); - cli_rpc_pipe_close(netlogon_pipe); - *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return NULL; - } - - *perr = rpccli_netlogon_setup_creds(netlogon_pipe, - cli->desthost, /* server name */ - domain, /* domain */ - global_myname(), /* client name */ - machine_account, /* machine account name */ - machine_pwd, - sec_chan_type, - pneg_flags); - - if (!NT_STATUS_IS_OK(*perr)) { - DEBUG(3,("get_schannel_session_key_auth_ntlmssp: rpccli_netlogon_setup_creds " - "failed with result %s\n", - nt_errstr(*perr) )); - cli_rpc_pipe_close(netlogon_pipe); - return NULL; - } - - if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { - DEBUG(3, ("get_schannel_session_key_auth_ntlmssp: Server %s did not offer schannel\n", - cli->desthost)); cli_rpc_pipe_close(netlogon_pipe); - *perr = NT_STATUS_INVALID_NETWORK_RESPONSE; return NULL; } -- cgit From a493c7baac311e9ac0a560e4412d07df150f4407 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 15:39:36 +0100 Subject: Streamline and fix logic of cm_prepare_connection(). Do not attempt to do a session setup when in a trusted domain situation (this gives STATUS_NOLOGON_TRUSTED_DOMAIN_ACCOUNT). Use get_trust_pw_clear to get machine trust account. Only call this when the results is really used. Use the proper domain and account name for session setup. Michael (This used to be commit 18c66a364e0ddc4960769871ca190944f7fe5c44) --- source3/winbindd/winbindd_cm.c | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d8040d79ac..00d9092dc3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -646,8 +646,13 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, bool *retry) { - char *machine_password, *machine_krb5_principal, *machine_account; - char *ipc_username, *ipc_domain, *ipc_password; + char *machine_password = NULL; + char *machine_krb5_principal = NULL; + char *machine_account = NULL; + const char *account_name = NULL; + char *ipc_username = NULL; + char *ipc_domain = NULL; + char *ipc_password = NULL; bool got_mutex; @@ -661,21 +666,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n", controller, domain->name )); - machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, - NULL); - - if (asprintf(&machine_account, "%s$", global_myname()) == -1) { - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), - lp_realm()) == -1) { - SAFE_FREE(machine_account); - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -732,10 +722,32 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = NT_STATUS_UNSUCCESSFUL; goto done; } - - if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { + + if (!is_trusted_domain_situation(domain->name) && + (*cli)->protocol >= PROTOCOL_NT1 && + (*cli)->capabilities & CAP_EXTENDED_SECURITY) + { ADS_STATUS ads_status; + if (!get_trust_pw_clear(domain->name, &machine_password, + &account_name, NULL)) + { + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + + if (asprintf(&machine_account, "%s$", account_name) == -1) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, + lp_realm()) == -1) + { + result = NT_STATUS_NO_MEMORY; + goto done; + } + if (lp_security() == SEC_ADS) { /* Try a krb5 session */ @@ -750,7 +762,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ads_status = cli_session_setup_spnego(*cli, machine_krb5_principal, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4,("failed kerberos session setup with %s\n", @@ -760,7 +772,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } @@ -770,12 +782,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(5, ("connecting to %s from %s with username " "[%s]\\[%s]\n", controller, global_myname(), - lp_workgroup(), machine_account)); + domain->name, machine_account)); ads_status = cli_session_setup_spnego(*cli, machine_account, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4, ("authenticated session setup failed with %s\n", ads_errstr(ads_status))); @@ -784,12 +796,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } - /* Fall back to non-kerberos session setup */ + /* Fall back to non-kerberos session setup with auth_user */ (*cli)->use_kerberos = False; -- cgit From 13e0e4bdf25d00bdf021851d4f5a9e906212c357 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:32:38 +0100 Subject: Refactor out assembling of trust creds (pw, account name, principal). Michael (This used to be commit 481f18b20d6d5ee12c62120a3559bb16cc98e465) --- source3/winbindd/winbindd_cm.c | 55 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 00d9092dc3..cc7a0cc671 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -635,6 +635,40 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, return True; } +/** + * Helper function to assemble trust password and account name + */ +static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, + char **machine_password, + char **machine_account, + char **machine_krb5_principal) +{ + const char *account_name; + + if (!get_trust_pw_clear(domain->name, machine_password, + &account_name, NULL)) + { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + if ((machine_account != NULL) && + (asprintf(machine_account, "%s$", account_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + /* this is at least correct when domain is our domain, + * which is the only case, when this is currently used: */ + if ((machine_krb5_principal != NULL) && + (asprintf(machine_krb5_principal, "%s$@%s", account_name, + domain->alt_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + /************************************************************************ Given a fd with a just-connected TCP connection to a DC, open a connection to the pipe. @@ -649,7 +683,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, char *machine_password = NULL; char *machine_krb5_principal = NULL; char *machine_account = NULL; - const char *account_name = NULL; char *ipc_username = NULL; char *ipc_domain = NULL; char *ipc_password = NULL; @@ -729,22 +762,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, { ADS_STATUS ads_status; - if (!get_trust_pw_clear(domain->name, &machine_password, - &account_name, NULL)) - { - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - if (asprintf(&machine_account, "%s$", account_name) == -1) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, - lp_realm()) == -1) - { - result = NT_STATUS_NO_MEMORY; + result = get_trust_creds(domain, &machine_password, + &machine_account, + &machine_krb5_principal); + if (!NT_STATUS_IS_OK(result)) { goto done; } -- cgit From 9104d2bf79e92ccdca3e6406bda9f0facea89ddb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:34:39 +0100 Subject: Make cm_connect_sam() try harder to connect autheticated. Even if the session setup was anonymous, try and collect trust creds with get_trust_creds() and use these before falling back to schannel. This is the first attempt to fix interdomain trusts. (get password policy and stuff) Michael (This used to be commit e180bbd45452435e981192028a0ad90078c04236) --- source3/winbindd/winbindd_cm.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'source3') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index cc7a0cc671..cb366a293c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1968,6 +1968,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring conn_pwd; struct dcinfo *p_dcinfo; + char *machine_password = NULL; + char *machine_account = NULL; + char *domain_name = NULL; result = init_dc_connection(domain); if (!NT_STATUS_IS_OK(result)) { @@ -1990,34 +1993,46 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, pwd_get_cleartext(&conn->cli->pwd, conn_pwd); if ((conn->cli->user_name[0] == '\0') || (conn->cli->domain[0] == '\0') || - (conn_pwd[0] == '\0')) { - DEBUG(10, ("cm_connect_sam: No no user available for " - "domain %s, trying schannel\n", conn->cli->domain)); + (conn_pwd[0] == '\0')) + { + result = get_trust_creds(domain, &machine_password, + &machine_account, NULL); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("cm_connect_sam: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + domain_name = domain->name; goto schannel; + } else { + machine_password = conn_pwd; + machine_account = conn->cli->user_name; + domain_name = conn->cli->domain; } + /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ conn->samr_pipe = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, - conn->cli->domain, - conn->cli->user_name, - conn_pwd, &result); + domain_name, + machine_account, + machine_password, &result); if (conn->samr_pipe == NULL) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " "pipe for domain %s using NTLMSSP " "authenticated pipe: user %s\\%s. Error was " - "%s\n", domain->name, conn->cli->domain, - conn->cli->user_name, nt_errstr(result))); + "%s\n", domain->name, domain_name, + machine_account, nt_errstr(result))); goto schannel; } DEBUG(10,("cm_connect_sam: connected to SAMR pipe for " "domain %s using NTLMSSP authenticated " "pipe: user %s\\%s\n", domain->name, - conn->cli->domain, conn->cli->user_name )); + domain_name, machine_account)); result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, @@ -2102,6 +2117,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, *cli = conn->samr_pipe; *sam_handle = conn->sam_domain_handle; + SAFE_FREE(machine_password); + SAFE_FREE(machine_account); return result; } -- cgit From 5db4a7f6c423bb5df8403e1b8737a4d80cee85ae Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 28 Nov 2007 02:15:37 +0100 Subject: Add flags for correctly implementing lsa_lookup_name levels. (Prepare fix for Bug #4801.) Michael (This used to be commit 537b12647e25adcb7da3581f18d2e9feca1caf0c) --- source3/include/smb.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/include/smb.h b/source3/include/smb.h index d58c124e6d..a725ae1392 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -242,6 +242,7 @@ typedef uint64_t NTTIME; #define SID_MAX_SIZE ((size_t)(8+(MAXSUBAUTHS*4))) +#define LOOKUP_NAME_NONE 0x00000000 #define LOOKUP_NAME_ISOLATED 0x00000001 /* Look up unqualified names */ #define LOOKUP_NAME_REMOTE 0x00000002 /* Ask others */ #define LOOKUP_NAME_GROUP 0x00000004 /* (unused) This is a NASTY hack for @@ -250,7 +251,14 @@ typedef uint64_t NTTIME; #define LOOKUP_NAME_EXPLICIT 0x00000008 /* Only include explicitly mapped names and not the Unix {User,Group} domain */ -#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE) +#define LOOKUP_NAME_BUILTIN 0x00000010 /* builtin names */ +#define LOOKUP_NAME_WKN 0x00000020 /* well known names */ +#define LOOKUP_NAME_DOMAIN 0x00000040 /* only lookup own domain */ +#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED\ + |LOOKUP_NAME_REMOTE\ + |LOOKUP_NAME_BUILTIN\ + |LOOKUP_NAME_WKN\ + |LOOKUP_NAME_DOMAIN) /** * @brief Security Identifier -- cgit From ceedf1a111598c815ffef9a0fe312689cc4bf136 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 13 Dec 2007 12:55:32 +0300 Subject: Fix pam_smbpass build (This used to be commit fbc510f1717fe82338262c18c252d18987c55b5c) --- source3/pam_smbpass/support.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c index 9d56bd4950..bc9481d9e9 100644 --- a/source3/pam_smbpass/support.c +++ b/source3/pam_smbpass/support.c @@ -61,10 +61,6 @@ void _cleanup(pam_handle_t *, void *, int); char *_pam_delete(register char *); - /* default configuration file location */ - - const char *servicesf = get_dyn_CONFIGFILE(); - /* syslogging function for errors and other information */ void _log_err( int err, const char *format, ... ) @@ -128,7 +124,7 @@ int set_ctrl( int flags, int argc, const char **argv ) { int i = 0; - const char *service_file = get_dyn_CONFIGFILE(); + const char *service_file = NULL; unsigned int ctrl; ctrl = SMB_DEFAULTS; /* the default selection of options */ @@ -139,7 +135,7 @@ int set_ctrl( int flags, int argc, const char **argv ) set( SMB__NONULL, ctrl ); /* initialize service file location */ - service_file=servicesf; + service_file=get_dyn_CONFIGFILE(); if (flags & PAM_SILENT) { set( SMB__QUIET, ctrl ); -- cgit From 733425f312729bf4c26bfcea866f310bc9b6b5be Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Thu, 13 Dec 2007 14:23:04 +0300 Subject: Fix codepagedir to follow predefined libdir when using FHS. Fixes x86_64 build. (This used to be commit b8e582c9941d2466a403e476c52026f4b4201062) --- source3/configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index 84ae6f7e50..7272ae4d9a 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -65,10 +65,10 @@ AC_ARG_WITH(fhs, mandir="\${prefix}/share/man" logfilebase="\${VARDIR}/log/samba" privatedir="\${CONFIGDIR}/private" - libdir="\${prefix}/lib/samba" + test "${libdir}" || libdir="\${prefix}/lib/samba" configdir="\${sysconfdir}/samba" swatdir="\${DATADIR}/samba/swat" - codepagedir="\${prefix}/lib/samba" + codepagedir="\${LIBDIR}" statedir="\${VARDIR}/lib/samba" cachedir="\${VARDIR}/lib/samba" AC_DEFINE(FHS_COMPATIBLE, 1, [Whether to use fully FHS-compatible paths]) -- cgit From 0d8146d5de33b4a8fc4b2833fb7e112f440ae365 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 13 Dec 2007 14:38:05 +0100 Subject: Fix typo in debug statement. Michael (This used to be commit da23684261f40c06dea30ab2df0c878ebb0d0d81) --- source3/auth/token_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c index 63672bcf74..330acde6e4 100644 --- a/source3/auth/token_util.c +++ b/source3/auth/token_util.c @@ -85,7 +85,7 @@ NT_USER_TOKEN *get_root_nt_token( void ) return token; if ( !(pw = sys_getpwnam( "root" )) ) { - DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n")); + DEBUG(0,("get_root_nt_token: getpwnam(\"root\") failed!\n")); return NULL; } -- cgit From 9e733924d9119a3a7a8b755557ffe458dda96d63 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Dec 2007 16:44:24 -0800 Subject: Arg. The fix for CVE-2007-6015 hadn't been merged into 3.2. Do so now.... Jeremy. (This used to be commit 6b1246c29a0241c8e4bb98d659d847d010826b36) --- source3/libsmb/clidgram.c | 6 ++++++ source3/nmbd/nmbd_packets.c | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'source3') diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c index 82f874f383..76630bd504 100644 --- a/source3/libsmb/clidgram.c +++ b/source3/libsmb/clidgram.c @@ -75,6 +75,12 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx, /* Setup the smb part. */ ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ memcpy(tmp,ptr,4); + + if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) { + DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n")); + return False; + } + set_message(ptr,17,strlen(mailslot) + 1 + len,True); memcpy(ptr,tmp,4); diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index b78ab5ba7e..349d36ce70 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -1918,6 +1918,12 @@ bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len, /* Setup the smb part. */ ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ memcpy(tmp,ptr,4); + + if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) { + DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); + return false; + } + set_message(ptr,17,strlen(mailslot) + 1 + len,True); memcpy(ptr,tmp,4); -- cgit From 03ccaab05f929a2ba7bd7727ea0fe055e1f0989f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Dec 2007 17:18:48 -0800 Subject: Add a varient of Steve Langasek patch for bug #4780. Cause user mounts to inherit uid= and gid= from the calling user when called as non-root, except when overridden on the commandline. Jeremy. (This used to be commit 7fad5f38ea86ef76dc8e0853926b3248230616be) --- source3/client/mount.cifs.c | 69 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 10 deletions(-) (limited to 'source3') diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index f141e8e4c7..c89a477ef9 100644 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -354,6 +354,8 @@ static int parse_options(char ** optionsp, int * filesys_flags) int out_len = 0; int word_len; int rc = 0; + char user[32]; + char group[32]; if (!optionsp || !*optionsp) return 1; @@ -364,6 +366,13 @@ static int parse_options(char ** optionsp, int * filesys_flags) /* BB fixme check for separator override BB */ + if (getuid()) { + got_uid = 1; + snprintf(user,sizeof(user),"%u",getuid()); + got_gid = 1; + snprintf(group,sizeof(group),"%u",getgid()); + } + /* while ((data = strsep(&options, ",")) != NULL) { */ while(data != NULL) { /* check if ends with trailing comma */ @@ -526,33 +535,35 @@ static int parse_options(char ** optionsp, int * filesys_flags) got_uid = 1; if (!isdigit(*value)) { struct passwd *pw; - static char temp[32]; if (!(pw = getpwnam(value))) { printf("bad user name \"%s\"\n", value); exit(1); } - snprintf(temp, sizeof(temp), "%u", pw->pw_uid); - value = temp; + snprintf(user, sizeof(user), "%u", pw->pw_uid); endpwent(); + } else { + strlcpy(user,value,sizeof(user)); } } + goto nocopy; } else if (strncmp(data, "gid", 3) == 0) { if (value && *value) { got_gid = 1; if (!isdigit(*value)) { struct group *gr; - static char temp[32]; if (!(gr = getgrnam(value))) { printf("bad group name \"%s\"\n", value); exit(1); } - snprintf(temp, sizeof(temp), "%u", gr->gr_gid); - value = temp; + snprintf(group, sizeof(group), "%u", gr->gr_gid); endpwent(); + } else { + strlcpy(group,value,sizeof(group)); } } + goto nocopy; /* fmask and dmask synonyms for people used to smbfs syntax */ } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) { if (!value || !*value) { @@ -643,17 +654,55 @@ static int parse_options(char ** optionsp, int * filesys_flags) exit(1); } - if (out_len) - out[out_len++] = ','; + if (out_len) { + strlcat(out, ",", out_len + word_len + 2); + out_len++; + } + if (value) - snprintf(out + out_len, word_len + 2, "%s=%s", data, value); + snprintf(out + out_len, word_len + 1, "%s=%s", data, value); else - snprintf(out + out_len, word_len + 2, "%s", data); + snprintf(out + out_len, word_len + 1, "%s", data); out_len = strlen(out); nocopy: data = next_keyword; } + + /* special-case the uid and gid */ + if (got_uid) { + word_len = strlen(user); + + out = (char *)realloc(out, out_len + word_len + 6); + if (out == NULL) { + perror("malloc"); + exit(1); + } + + if (out_len) { + strlcat(out, ",", out_len + word_len + 6); + out_len++; + } + snprintf(out + out_len, word_len + 5, "uid=%s", user); + out_len = strlen(out); + } + if (got_gid) { + word_len = strlen(group); + + out = (char *)realloc(out, out_len + 1 + word_len + 6); + if (out == NULL) { + perror("malloc"); + exit(1); + } + + if (out_len) { + strlcat(out, ",", out_len + word_len + 6); + out_len++; + } + snprintf(out + out_len, word_len + 5, "gid=%s", group); + out_len = strlen(out); + } + free(*optionsp); *optionsp = out; return 0; -- cgit From 138333ed1f571cd6bb76c3be655f70e35cd48a99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Dec 2007 17:25:26 -0800 Subject: We don't need to call endpwent if we never call getpwent. Jeremy. (This used to be commit 27078d1292e8588956ae78e4cddb1bcebbe84478) --- source3/client/mount.cifs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3') diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index c89a477ef9..ec245ed200 100644 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -541,7 +541,6 @@ static int parse_options(char ** optionsp, int * filesys_flags) exit(1); } snprintf(user, sizeof(user), "%u", pw->pw_uid); - endpwent(); } else { strlcpy(user,value,sizeof(user)); } @@ -558,7 +557,6 @@ static int parse_options(char ** optionsp, int * filesys_flags) exit(1); } snprintf(group, sizeof(group), "%u", gr->gr_gid); - endpwent(); } else { strlcpy(group,value,sizeof(group)); } -- cgit