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:
commit
45636efa39
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
************************************************************************/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user