1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00

Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test

This commit is contained in:
Alexander Bokovoy 2007-12-13 12:57:24 +03:00
commit 45636efa39
8 changed files with 308 additions and 214 deletions

View File

@ -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_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",
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);

View File

@ -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

View File

@ -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);

View File

@ -1521,46 +1521,99 @@ 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], 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, NULL,
&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);
return True;
if (account_name != NULL) {
*account_name = lp_workgroup();
}
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))
return True;
pwd = secrets_fetch_machine_password(domain, &last_set_time, channel);
DEBUG(5, ("get_trust_pw: could not fetch trust account "
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_hash(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;
}
DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
"password for domain %s\n", domain));
return False;
}

View File

@ -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
*
@ -558,20 +576,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 +725,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
************************************************************************/

View File

@ -2424,49 +2424,29 @@ 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];
fstring machine_account;
netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
if (!netlogon_pipe) {
return NULL;
}
const char *machine_account;
/* Get the machine account credentials from secrets.tdb. */
if (!get_trust_pw(domain, machine_pwd, &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",
domain));
cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
return NULL;
return false;
}
/* 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 */
@ -2477,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) {
@ -2489,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;
}
@ -2560,61 +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];
fstring 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(domain, machine_pwd, &sec_chan_type)) {
DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch "
"trust account password for domain '%s'\n",
domain));
if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
pneg_flags, perr))
{
cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
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 */
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;
}

View File

@ -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) {

View File

@ -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.
@ -646,8 +680,12 @@ 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;
char *ipc_username = NULL;
char *ipc_domain = NULL;
char *ipc_password = NULL;
bool got_mutex;
@ -661,23 +699,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;
}
cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
*retry = True;
got_mutex = secrets_named_mutex(controller,
@ -734,10 +755,20 @@ 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;
result = get_trust_creds(domain, &machine_password,
&machine_account,
&machine_krb5_principal);
if (!NT_STATUS_IS_OK(result)) {
goto done;
}
if (lp_security() == SEC_ADS) {
/* Try a krb5 session */
@ -752,7 +783,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",
@ -762,7 +793,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;
}
}
@ -772,12 +803,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)));
@ -786,15 +817,17 @@ 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;
cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
(strlen(ipc_username) > 0)) {
@ -1935,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)) {
@ -1957,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,
@ -2069,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;
}
@ -2219,10 +2269,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,27 +2280,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 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_hash(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(