1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

Store the type of 'sec channel' that we establish to the DC. If we are a

workstation, we have to use the workstation type, if we have a BDC account,
we must use the BDC type - even if we are pretending to be a workstation
at the moment.

Also actually store and retreive the last change time, so we can do
periodic password changes again (for RPC at least).

And finally, a couple of minor fixes to 'net'.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett 0001-01-01 00:00:00 +00:00
parent c7dc0b27ac
commit 6e6b7b79ed
23 changed files with 372 additions and 227 deletions

View File

@ -352,6 +352,11 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
"Error was %s.\n", user_info->smb_name.str,
user_info->domain.str, cli->srv_name_slash,
nt_errstr(nt_status)));
/* map to something more useful */
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
nt_status = NT_STATUS_NO_LOGON_SERVERS;
}
} else {
nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str,
user_info->smb_name.str, domain, server_info, &info3);
@ -400,6 +405,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
unsigned char trust_passwd[16];
time_t last_change_time;
const char *domain = lp_workgroup();
uint32 sec_channel_type = 0;
if (!user_info || !server_info || !auth_context) {
DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n"));
@ -422,7 +428,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
* No need to become_root() as secrets_init() is done at startup.
*/
if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time))
if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time, &sec_channel_type))
{
DEBUG(0, ("check_ntdomain_security: could not fetch trust account password for domain '%s'\n", domain));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
@ -447,7 +453,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
nt_status = domain_client_validate(mem_ctx, user_info, domain,
(uchar *)auth_context->challenge.data,
server_info,
password_server, global_myname(), SEC_CHAN_WKSTA, trust_passwd, last_change_time);
password_server, global_myname(), sec_channel_type,trust_passwd, last_change_time);
return nt_status;
}

View File

@ -26,7 +26,9 @@
*/
#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC"
#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD"
#define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME"
#define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE"
#define SECRETS_MACHINE_TRUST_ACCOUNT_NAME "SECRETS/SECRETS_MACHINE_TRUST_ACCOUNT_NAME"
/* this one is for storing trusted domain account password */
#define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC"

View File

@ -53,7 +53,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
return NT_STATUS_LOGON_FAILURE;
}
password_s = secrets_fetch_machine_password();
password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
if (!password_s) {
DEBUG(1,("failed to fetch machine password\n"));
return NT_STATUS_LOGON_FAILURE;

View File

@ -1024,6 +1024,7 @@ char *ads_ou_string(const char *org_unit)
add a machine account to the ADS server
*/
static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
uint32 account_type,
const char *org_unit)
{
ADS_STATUS ret, status;
@ -1073,7 +1074,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
if (!(samAccountName = talloc_asprintf(ctx, "%s$", hostname)))
goto done;
acct_control = UF_WORKSTATION_TRUST_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
acct_control = account_type | UF_DONT_EXPIRE_PASSWD;
#ifndef ENCTYPE_ARCFOUR_HMAC
acct_control |= UF_USE_DES_KEY_ONLY;
#endif
@ -1335,7 +1336,8 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
* @param org_unit Organizational unit to place machine in
* @return status of join
**/
ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org_unit)
ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname,
uint32 account_type, const char *org_unit)
{
ADS_STATUS status;
LDAPMessage *res;
@ -1356,7 +1358,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org
}
}
status = ads_add_machine_acct(ads, host, org_unit);
status = ads_add_machine_acct(ads, host, account_type, org_unit);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_add_machine_acct: %s\n", ads_errstr(status)));
return status;

View File

@ -29,21 +29,23 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
char *new_password;
char *service_principal;
ADS_STATUS ret;
if ((password = secrets_fetch_machine_password()) == NULL) {
uint32 sec_channel_type;
if ((password = secrets_fetch_machine_password(lp_workgroup(), NULL, &sec_channel_type)) == NULL) {
DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT);
}
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
if (!ADS_ERR_OK(ret)) goto failed;
if (!secrets_store_machine_password(new_password)) {
if (!secrets_store_machine_password(new_password, lp_workgroup(), sec_channel_type)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES);
}

View File

@ -31,12 +31,13 @@
**********************************************************/
static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx,
unsigned char orig_trust_passwd_hash[16],
unsigned char new_trust_passwd_hash[16])
unsigned char new_trust_passwd_hash[16],
uint32 sec_channel_type)
{
NTSTATUS result;
uint32 neg_flags = 0x000001ff;
result = cli_nt_setup_creds(cli, get_sec_chan(), orig_trust_passwd_hash, &neg_flags, 2);
result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",
@ -60,7 +61,9 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
**********************************************************/
NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx,
unsigned char orig_trust_passwd_hash[16])
const char *domain,
unsigned char orig_trust_passwd_hash[16],
uint32 sec_channel_type)
{
unsigned char new_trust_passwd_hash[16];
char *new_trust_passwd;
@ -74,7 +77,7 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
E_md4hash(new_trust_passwd, new_trust_passwd_hash);
nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
new_trust_passwd_hash);
new_trust_passwd_hash, sec_channel_type);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
@ -83,7 +86,7 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
* Return the result of trying to write the new password
* back into the trust account file.
*/
if (!secrets_store_machine_password(new_trust_passwd)) {
if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
nt_status = NT_STATUS_UNSUCCESSFUL;
}
}
@ -97,22 +100,26 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
already setup the connection to the NETLOGON pipe
**********************************************************/
NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli,
TALLOC_CTX *mem_ctx,
const char *domain)
{
unsigned char old_trust_passwd_hash[16];
char *up_domain;
uint32 sec_channel_type = 0;
up_domain = talloc_strdup(mem_ctx, domain);
if (!secrets_fetch_trust_account_password(domain,
old_trust_passwd_hash,
NULL)) {
NULL, &sec_channel_type)) {
DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
return NT_STATUS_UNSUCCESSFUL;
}
return trust_pw_change_and_store_it(cli, mem_ctx, old_trust_passwd_hash);
return trust_pw_change_and_store_it(cli, mem_ctx, domain,
old_trust_passwd_hash,
sec_channel_type);
}
@ -127,35 +134,21 @@ NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, TALLOC_CTX *me
BOOL is_trusted_domain(const char* dom_name)
{
int enum_ctx = 0;
const int trustdom_size = 10;
int num_domains, i;
TRUSTDOM **domains;
NTSTATUS result;
fstring trustdom_name;
DOM_SID trustdom_sid;
TALLOC_CTX *mem_ctx;
/*
* Query the secrets db as an ultimate source of information
* about trusted domain names. This is PDC or BDC case.
*/
mem_ctx = talloc_init("is_trusted_domain");
do {
result = secrets_get_trusted_domains(mem_ctx, &enum_ctx, trustdom_size,
&num_domains, &domains);
/* compare each returned entry against incoming connection's domain */
for (i = 0; i < num_domains; i++) {
pull_ucs2_fstring(trustdom_name, domains[i]->name);
if (strequal(trustdom_name, dom_name)) {
talloc_destroy(mem_ctx);
return True;
}
}
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
char *pass = NULL;
time_t lct;
BOOL ret;
talloc_destroy(mem_ctx);
if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
/*
* Query the secrets db as an ultimate source of information
* about trusted domain names. This is PDC or BDC case.
*/
ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
SAFE_FREE(pass);
if (ret)
return ret;
}
/*
* Query the trustdom_cache updated periodically. The only

View File

@ -56,7 +56,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
/* the machine acct password might have change - fetch it every time */
SAFE_FREE(ads->auth.password);
ads->auth.password = secrets_fetch_machine_password();
ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
if (primary_realm) {
SAFE_FREE(ads->auth.realm);

View File

@ -853,7 +853,9 @@ CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
netlogon pipe as no handle is returned. */
NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd,
NTSTATUS cm_get_netlogon_cli(const char *domain,
const unsigned char *trust_passwd,
uint32 sec_channel_type,
struct cli_state **cli)
{
NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
@ -876,7 +878,7 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_pass
DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller));
}
result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
result = cli_nt_setup_creds(conn->cli, sec_channel_type, trust_passwd, &neg_flags, 2);
if (got_mutex)
secrets_named_mutex_release(lock_name);
@ -896,7 +898,7 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_pass
}
/* Try again */
result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
result = cli_nt_setup_creds( conn->cli, sec_channel_type,trust_passwd, &neg_flags, 2);
if (got_mutex)
secrets_named_mutex_release(lock_name);

View File

@ -34,13 +34,14 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
uchar trust_passwd[16];
int num_retries = 0;
struct cli_state *cli;
uint32 sec_channel_type;
DEBUG(3, ("[%5d]: check machine account\n", state->pid));
/* Get trust account password */
again:
if (!secrets_fetch_trust_account_password(
lp_workgroup(), trust_passwd, NULL)) {
lp_workgroup(), trust_passwd, NULL, &sec_channel_type)) {
result = NT_STATUS_INTERNAL_ERROR;
goto done;
}
@ -49,7 +50,7 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
the trust account password. */
/* Don't shut this down - it belongs to the connection cache code */
result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli);
result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, sec_channel_type, &cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
@ -234,7 +235,7 @@ enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state)
return WINBINDD_OK;
}
/* What's my name again? */
/* Where can I find the privilaged pipe? */
enum winbindd_result winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
{

View File

@ -61,7 +61,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
fstring name_domain, name_user;
unsigned char trust_passwd[16];
time_t last_change_time;
uint32 smb_uid_low;
uint32 sec_channel_type;
NET_USER_INFO_3 info3;
struct cli_state *cli = NULL;
uchar chal[8];
@ -111,21 +111,20 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
*/
if (!secrets_fetch_trust_account_password(
lp_workgroup(), trust_passwd, &last_change_time)) {
lp_workgroup(), trust_passwd, &last_change_time,
&sec_channel_type)) {
DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
"password for domain %s\n", lp_workgroup()));
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
goto done;
}
/* We really don't care what LUID we give the user. */
generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False);
ZERO_STRUCT(info3);
/* Don't shut this down - it belongs to the connection cache code */
result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli);
result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd,
sec_channel_type,
&cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
@ -169,6 +168,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
NTSTATUS result;
unsigned char trust_passwd[16];
time_t last_change_time;
uint32 sec_channel_type;
NET_USER_INFO_3 info3;
struct cli_state *cli = NULL;
TALLOC_CTX *mem_ctx = NULL;
@ -256,7 +256,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
*/
if (!secrets_fetch_trust_account_password (
contact_domain, trust_passwd, &last_change_time)) {
contact_domain, trust_passwd, &last_change_time,
&sec_channel_type)) {
DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
"password for domain %s\n", contact_domain));
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
@ -266,7 +267,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
ZERO_STRUCT(info3);
/* Don't shut this down - it belongs to the connection cache code */
result = cm_get_netlogon_cli(contact_domain, trust_passwd, &cli);
result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, &cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result)));

View File

@ -78,6 +78,7 @@ static void generate_random_sid(DOM_SID *sid)
static BOOL pdb_generate_sam_sid(void)
{
DOM_SID domain_sid;
char *fname = NULL;
BOOL is_dc = False;
@ -97,8 +98,14 @@ static BOOL pdb_generate_sam_sid(void)
break;
}
if (is_dc) {
if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
sid_copy(global_sam_sid, &domain_sid);
return True;
}
}
if (secrets_fetch_domain_sid(global_myname(), global_sam_sid)) {
DOM_SID domain_sid;
/* We got our sid. If not a pdc/bdc, we're done. */
if (!is_dc)
@ -117,11 +124,11 @@ static BOOL pdb_generate_sam_sid(void)
if (!sid_equal(&domain_sid, global_sam_sid)) {
/* Domain name sid doesn't match global sam sid. Re-store global sam sid as domain sid. */
/* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */
DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID as a pdc/bdc.\n"));
if (!secrets_store_domain_sid(global_myname(), &domain_sid)) {
DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
return False;
}
return True;

View File

@ -221,6 +221,20 @@ BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
return True;
}
/************************************************************************
Routine to get the default secure channel type for trust accounts
************************************************************************/
uint32 get_default_sec_channel(void)
{
if (lp_server_role() == ROLE_DOMAIN_BDC ||
lp_server_role() == ROLE_DOMAIN_PDC) {
return SEC_CHAN_BDC;
} else {
return SEC_CHAN_WKSTA;
}
}
/************************************************************************
Routine to get the trust account password for a domain.
The user of this function must have locked the trust password file using
@ -228,19 +242,20 @@ BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
************************************************************************/
BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
time_t *pass_last_set_time)
time_t *pass_last_set_time,
uint32 *channel)
{
struct machine_acct_pass *pass;
char *plaintext;
size_t size;
plaintext = secrets_fetch_machine_password();
plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
channel);
if (plaintext) {
/* we have an ADS password - use that */
DEBUG(4,("Using ADS machine password\n"));
E_md4hash(plaintext, ret_pwd);
SAFE_FREE(plaintext);
pass_last_set_time = 0;
return True;
}
@ -257,6 +272,10 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
memcpy(ret_pwd, pass->hash, 16);
SAFE_FREE(pass);
if (channel)
*channel = get_default_sec_channel();
return True;
}
@ -369,14 +388,42 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
the password is assumed to be a null terminated ascii string
************************************************************************/
BOOL secrets_store_machine_password(const char *pass)
BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
{
char *key;
char *key = NULL;
BOOL ret;
asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, lp_workgroup());
uint32 last_change_time;
uint32 sec_channel_type;
asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
if (!key)
return False;
strupper(key);
ret = secrets_store(key, pass, strlen(pass)+1);
free(key);
SAFE_FREE(key);
if (!ret)
return ret;
asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
if (!key)
return False;
strupper(key);
SIVAL(&last_change_time, 0, time(NULL));
ret = secrets_store(key, &last_change_time, sizeof(last_change_time));
SAFE_FREE(key);
asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
if (!key)
return False;
strupper(key);
SIVAL(&sec_channel_type, 0, sec_channel);
ret = secrets_store(key, &sec_channel_type, sizeof(sec_channel_type));
SAFE_FREE(key);
return ret;
}
@ -385,14 +432,45 @@ BOOL secrets_store_machine_password(const char *pass)
Routine to fetch the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
************************************************************************/
char *secrets_fetch_machine_password(void)
char *secrets_fetch_machine_password(const char *domain,
time_t *pass_last_set_time,
uint32 *channel)
{
char *key;
char *key = NULL;
char *ret;
asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, lp_workgroup());
asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
strupper(key);
ret = (char *)secrets_fetch(key, NULL);
free(key);
SAFE_FREE(key);
if (pass_last_set_time) {
size_t size;
uint32 *last_set_time;
asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
strupper(key);
last_set_time = secrets_fetch(key, &size);
if (last_set_time) {
*pass_last_set_time = IVAL(last_set_time,0);
} else {
*pass_last_set_time = 0;
}
SAFE_FREE(key);
}
if (channel) {
size_t size;
uint32 *channel_type;
asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
strupper(key);
channel_type = secrets_fetch(key, &size);
if (channel_type) {
*channel = IVAL(channel_type,0);
} else {
*channel = get_default_sec_channel();
}
SAFE_FREE(key);
}
return ret;
}
@ -637,7 +715,7 @@ BOOL must_use_pdc( const char *domain )
time_t last_change_time;
unsigned char passwd[16];
if ( !secrets_fetch_trust_account_password(domain, passwd, &last_change_time) )
if ( !secrets_fetch_trust_account_password(domain, passwd, &last_change_time, NULL) )
return False;
/*

View File

@ -227,24 +227,6 @@ password ?).\n", cli->desthost ));
return result;
}
/* Return the secure channel type depending on the server role. */
uint16 get_sec_chan(void)
{
uint16 sec_chan = SEC_CHAN_WKSTA;
switch (lp_server_role()) {
case ROLE_DOMAIN_PDC:
sec_chan = SEC_CHAN_DOMAIN;
break;
case ROLE_DOMAIN_BDC:
sec_chan = SEC_CHAN_BDC;
break;
}
return sec_chan;
}
/* Initialize domain session credentials */
NTSTATUS cli_nt_setup_creds(struct cli_state *cli,

View File

@ -152,6 +152,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
SAM_DELTA_CTR *deltas;
DOM_CRED ret_creds;
uint32 neg_flags = 0x000001ff;
uint32 sec_channel_type = 0;
if (argc > 2) {
fprintf(stderr, "Usage: %s [database_id]\n", argv[0]);
@ -169,12 +170,12 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
/* Initialise session credentials */
if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd,
NULL)) {
NULL, &sec_channel_type)) {
fprintf(stderr, "could not fetch trust account password\n");
goto done;
}
result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
result = cli_nt_setup_creds(cli, sec_channel_type, trust_passwd, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
fprintf(stderr, "Error initialising session creds\n");
@ -213,6 +214,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
SAM_DELTA_CTR *deltas;
UINT64_S seqnum;
uint32 neg_flags = 0x000001ff;
uint32 sec_channel_type = 0;
if (argc != 3) {
fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]);
@ -233,12 +235,12 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
/* Initialise session credentials */
if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd,
NULL)) {
NULL, &sec_channel_type)) {
fprintf(stderr, "could not fetch trust account password\n");
goto done;
}
result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
result = cli_nt_setup_creds(cli, sec_channel_type, trust_passwd, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
fprintf(stderr, "Error initialising session creds\n");

View File

@ -393,15 +393,16 @@ static NTSTATUS do_cmd(struct cli_state *cli,
if (cmd_entry->pipe_idx == PI_NETLOGON) {
uchar trust_password[16];
uint32 sec_channel_type;
if (!secrets_fetch_trust_account_password(lp_workgroup(),
trust_password,
NULL)) {
NULL, &sec_channel_type)) {
return NT_STATUS_UNSUCCESSFUL;
}
if (!cli_nt_open_netlogon(cli, trust_password,
SEC_CHAN_WKSTA)) {
sec_channel_type)) {
DEBUG(0, ("Could not initialise NETLOGON pipe\n"));
return NT_STATUS_UNSUCCESSFUL;
}

View File

@ -24,78 +24,16 @@
#include "includes.h"
/*********************************************************
Change the domain password on the PDC.
**********************************************************/
static NTSTATUS modify_trust_password( const char *domain, const char *remote_machine,
unsigned char orig_trust_passwd_hash[16])
{
struct cli_state *cli;
DOM_SID domain_sid;
NTSTATUS nt_status;
/*
* Ensure we have the domain SID for this domain.
*/
if (!secrets_fetch_domain_sid(domain, &domain_sid)) {
DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n"));
return NT_STATUS_UNSUCCESSFUL;
}
if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine,
NULL, 0,
"IPC$", "IPC",
"", "",
"", 0, NULL)))
{
DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine));
return NT_STATUS_UNSUCCESSFUL;
}
/*
* Ok - we have an anonymous connection to the IPC$ share.
* Now start the NT Domain stuff :-).
*/
if(cli_nt_session_open(cli, PI_NETLOGON) == False) {
DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n",
remote_machine, cli_errstr(cli)));
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return NT_STATUS_UNSUCCESSFUL;
}
nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx,
orig_trust_passwd_hash);
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return nt_status;
}
/************************************************************************
Change the trust account password for a domain.
************************************************************************/
NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine)
{
unsigned char old_trust_passwd_hash[16];
time_t lct;
NTSTATUS res = NT_STATUS_UNSUCCESSFUL;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct in_addr pdc_ip;
fstring dc_name;
if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) {
DEBUG(0,("change_trust_account_password: unable to read the machine account password for domain %s.\n",
domain));
return NT_STATUS_UNSUCCESSFUL;
}
struct cli_state *cli;
if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
/* Use the PDC *only* for this */
@ -116,13 +54,44 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
/* if this next call fails, then give up. We can't do
password changes on BDC's --jerry */
res = modify_trust_password(domain, dc_name, old_trust_passwd_hash);
if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine,
NULL, 0,
"IPC$", "IPC",
"", "",
"", 0, NULL)))
{
DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine));
nt_status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
/*
* Ok - we have an anonymous connection to the IPC$ share.
* Now start the NT Domain stuff :-).
*/
if(cli_nt_session_open(cli, PI_NETLOGON) == False) {
DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n",
remote_machine, cli_errstr(cli)));
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
nt_status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx,
domain);
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
failed:
if (!NT_STATUS_IS_OK(res)) {
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n",
timestring(False), domain));
}
return res;
return nt_status;
}

View File

@ -1179,9 +1179,11 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
return True;
}
if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct)) {
if(!secrets_fetch_trust_account_password(lp_workgroup(),
trust_passwd_hash,
&lct, NULL)) {
DEBUG(0,("process: unable to read the machine account password for \
machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
machine %s in domain %s.\n", global_myname(), lp_workgroup()));
secrets_lock_trust_account_password(lp_workgroup(), False);
return True;
}

View File

@ -68,7 +68,7 @@ int opt_force = 0;
int opt_port = 0;
int opt_maxusers = -1;
const char *opt_comment = "";
char *opt_container = "cn=Users";
const char *opt_container = "cn=Users";
int opt_flags = -1;
int opt_timeout = 0;
const char *opt_target_workgroup = NULL;
@ -77,6 +77,27 @@ static int opt_machine_pass = 0;
BOOL opt_have_ip = False;
struct in_addr opt_dest_ip;
uint32 get_sec_channel_type(const char *param)
{
if (param && *param) {
return get_default_sec_channel();
} else {
if (strcasecmp(param, "PDC")==0) {
return SEC_CHAN_BDC;
} else if (strcasecmp(param, "BDC")==0) {
return SEC_CHAN_BDC;
} else if (strcasecmp(param, "MEMBER")==0) {
return SEC_CHAN_WKSTA;
#if 0
} else if (strcasecmp(param, "DOMAIN")==0) {
return SEC_CHAN_DOMAIN;
#endif
} else {
return get_default_sec_channel();
}
}
}
/*
run a function from a function table. If not found then
call the specified usage function
@ -602,11 +623,11 @@ static struct functable net_func[] = {
}
if (!opt_workgroup) {
opt_workgroup = lp_workgroup();
opt_workgroup = smb_xstrdup(lp_workgroup());
}
if (!opt_target_workgroup) {
opt_target_workgroup = strdup(lp_workgroup());
opt_target_workgroup = smb_xstrdup(lp_workgroup());
}
if (!init_names())
@ -615,7 +636,7 @@ static struct functable net_func[] = {
load_interfaces();
if (opt_machine_pass) {
char *user;
char *user = NULL;
/* it is very useful to be able to make ads queries as the
machine account for testing purposes and for domain leave */
@ -624,9 +645,10 @@ static struct functable net_func[] = {
exit(1);
}
opt_password = secrets_fetch_machine_password(opt_workgroup, NULL, NULL);
asprintf(&user,"%s$", global_myname());
opt_user_name = user;
opt_password = secrets_fetch_machine_password();
if (!opt_password) {
d_printf("ERROR: Unable to fetch machine password\n");
exit(1);

View File

@ -38,7 +38,7 @@
extern int opt_maxusers;
extern const char *opt_comment;
extern char *opt_container;
extern const char *opt_container;
extern int opt_flags;
extern const char *opt_comment;

View File

@ -575,7 +575,7 @@ static int net_ads_leave(int argc, const char **argv)
if (!opt_password) {
char *user_name;
asprintf(&user_name, "%s$", global_myname());
opt_password = secrets_fetch_machine_password();
opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
opt_user_name = user_name;
}
@ -607,7 +607,7 @@ static int net_ads_join_ok(void)
asprintf(&user_name, "%s$", global_myname());
opt_user_name = user_name;
opt_password = secrets_fetch_machine_password();
opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
if (!(ads = ads_startup())) {
return -1;
@ -648,6 +648,8 @@ int net_ads_join(int argc, const char **argv)
void *res;
DOM_SID dom_sid;
char *ou_str;
uint32 sec_channel_type;
uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
if (argc > 0) org_unit = argv[0];
@ -656,6 +658,11 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
/* check what type of join
TODO: make this variable like RPC
*/
account_type = UF_WORKSTATION_TRUST_ACCOUNT;
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
password = strdup(tmp_password);
@ -680,7 +687,7 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
rc = ads_join_realm(ads, global_myname(), org_unit);
rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
if (!ADS_ERR_OK(rc)) {
d_printf("ads_join_realm: %s\n", ads_errstr(rc));
return -1;
@ -703,7 +710,7 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
if (!secrets_store_machine_password(password)) {
if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
DEBUG(1,("Failed to save machine password\n"));
return -1;
}
@ -956,7 +963,7 @@ int net_ads_changetrustpw(int argc, const char **argv)
asprintf(&user_name, "%s$", global_myname());
opt_user_name = user_name;
opt_password = secrets_fetch_machine_password();
opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
use_in_memory_ccache();

View File

@ -235,8 +235,9 @@ int net_rpc_changetrustpw(int argc, const char **argv)
* @return Normal NTSTATUS return.
**/
static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
int argc, const char **argv) {
static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli,
TALLOC_CTX *mem_ctx,
int argc, const char **argv) {
fstring trust_passwd;
unsigned char orig_trust_passwd_hash[16];
@ -254,10 +255,22 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl
E_md4hash(trust_passwd, orig_trust_passwd_hash);
result = trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup,
orig_trust_passwd_hash,
SEC_CHAN_WKSTA);
/* SEC_CHAN_WKSTA specified specifically, as you cannot use this
to join a BDC to the domain (MS won't allow it, and is *really*
insecure) */
if (NT_STATUS_IS_OK(result))
printf("Joined domain %s.\n",lp_workgroup());
printf("Joined domain %s.\n",opt_target_workgroup);
if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
result = NT_STATUS_UNSUCCESSFUL;
}
return result;
}
@ -274,7 +287,38 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl
static int net_rpc_join_oldstyle(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
uint32 sec_channel_type;
/* check what type of join */
if (argc >= 0) {
sec_channel_type = get_sec_channel_type(argv[0]);
} else {
sec_channel_type = get_sec_channel_type(NULL);
}
if (sec_channel_type != SEC_CHAN_WKSTA)
return 1;
return run_rpc_command(NULL, PI_NETLOGON,
NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
rpc_join_oldstyle_internals,
argc, argv);
}
/**
* Join a domain, the old way.
*
* @param argc Standard main() style argc
* @param argc Standard main() style argv. Initial components are already
* stripped
*
* @return A shell status integer (0 for success)
**/
static int net_rpc_oldjoin(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_NETLOGON,
NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
rpc_join_oldstyle_internals,
argc, argv);
}
@ -287,11 +331,13 @@ static int net_rpc_join_oldstyle(int argc, const char **argv)
static int rpc_join_usage(int argc, const char **argv)
{
d_printf("net rpc join -U <username>[%%password] [options]\n"\
d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
"\t to join a domain with admin username & password\n"\
"\t\t password will be prompted if none is specified\n");
d_printf("net rpc join [options except -U]\n"\
"\t to join a domain created in server manager\n\n\n");
"\t\t password will be prompted if needed and none is specified\n"\
"\t <type> can be (default MEMBER)\n"\
"\t\t BDC - Join as a BDC\n"\
"\t\t PDC - Join as a PDC\n"\
"\t\t MEMBER - Join as a MEMBER server\n");
net_common_flags_usage(argc, argv);
return -1;
@ -311,19 +357,10 @@ static int rpc_join_usage(int argc, const char **argv)
int net_rpc_join(int argc, const char **argv)
{
struct functable func[] = {
{"oldstyle", net_rpc_join_oldstyle},
{NULL, NULL}
};
if (argc == 0) {
if ((net_rpc_join_oldstyle(argc, argv) == 0))
return 0;
return net_rpc_join_newstyle(argc, argv);
}
return net_run_function(argc, argv, func, rpc_join_usage);
if ((net_rpc_join_oldstyle(argc, argv) == 0))
return 0;
return net_rpc_join_newstyle(argc, argv);
}
@ -2179,6 +2216,7 @@ int net_rpc_usage(int argc, const char **argv)
{
d_printf(" net rpc info \t\t\tshow basic info about a domain \n");
d_printf(" net rpc join \t\t\tto join a domain \n");
d_printf(" net rpc oldjoin \t\t\tto join a domain created in server manager\n\n\n");
d_printf(" net rpc testjoin \t\ttests that a join is valid\n");
d_printf(" net rpc user \t\t\tto add, delete and list users\n");
d_printf(" net rpc group \t\tto list groups\n");
@ -2245,6 +2283,7 @@ int net_rpc(int argc, const char **argv)
struct functable func[] = {
{"info", net_rpc_info},
{"join", net_rpc_join},
{"oldjoin", net_rpc_oldjoin},
{"testjoin", net_rpc_testjoin},
{"user", net_rpc_user},
{"group", net_rpc_group},

View File

@ -62,18 +62,12 @@ int net_rpc_join_ok(const char *domain)
}
if (!secrets_fetch_trust_account_password(domain,
stored_md4_trust_password, NULL)) {
stored_md4_trust_password,
NULL, &channel)) {
DEBUG(0,("Could not retreive domain trust secret"));
goto done;
}
if (lp_server_role() == ROLE_DOMAIN_BDC ||
lp_server_role() == ROLE_DOMAIN_PDC) {
channel = SEC_CHAN_BDC;
} else {
channel = SEC_CHAN_WKSTA;
}
CHECK_RPC_ERR(cli_nt_setup_creds(cli,
channel,
stored_md4_trust_password, &neg_flags, 2),
@ -108,7 +102,8 @@ int net_rpc_join_newstyle(int argc, const char **argv)
struct cli_state *cli;
TALLOC_CTX *mem_ctx;
uint32 acb_info;
uint32 acb_info = ACB_WSTRUST;
uint32 sec_channel_type;
/* rpc variables */
@ -121,10 +116,11 @@ int net_rpc_join_newstyle(int argc, const char **argv)
char *clear_trust_password = NULL;
fstring ucs2_trust_password;
int ucs2_pw_len;
uchar pwbuf[516], sess_key[16];
uchar pwbuf[516];
SAM_USERINFO_CTR ctr;
SAM_USER_INFO_24 p24;
SAM_USER_INFO_10 p10;
uchar md4_trust_password[16];
/* Misc */
@ -135,6 +131,25 @@ int net_rpc_join_newstyle(int argc, const char **argv)
uint32 flags = 0x3e8;
char *acct_name;
const char *const_acct_name;
uint32 neg_flags = 0x000001ff;
/* check what type of join */
if (argc >= 0) {
sec_channel_type = get_sec_channel_type(argv[0]);
} else {
sec_channel_type = get_sec_channel_type(NULL);
}
switch (sec_channel_type) {
case SEC_CHAN_WKSTA:
acb_info = ACB_WSTRUST;
case SEC_CHAN_BDC:
acb_info = ACB_SVRTRUST;
#if 0
case SEC_CHAN_DOMAIN:
acb_info = ACB_DOMTRUST;
#endif
}
/* Connect to remote machine */
@ -189,8 +204,6 @@ int net_rpc_join_newstyle(int argc, const char **argv)
strlower(acct_name);
const_acct_name = acct_name;
acb_info = ((lp_server_role() == ROLE_DOMAIN_BDC) || lp_server_role() == ROLE_DOMAIN_PDC) ? ACB_SVRTRUST : ACB_WSTRUST;
result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
acct_name, acb_info,
0xe005000b, &user_pol,
@ -245,6 +258,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
char *str;
str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
clear_trust_password = strdup(str);
E_md4hash(clear_trust_password, md4_trust_password);
}
ucs2_pw_len = push_ucs2(NULL, ucs2_trust_password,
@ -287,8 +301,22 @@ int net_rpc_join_newstyle(int argc, const char **argv)
as a normal user with "Add workstation to domain" privilege. */
result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10,
sess_key, &ctr);
cli->user_session_key, &ctr);
/* Now check the whole process from top-to-bottom */
cli_samr_close(cli, mem_ctx, &user_pol);
cli_nt_session_close(cli); /* Done with this pipe */
if (!cli_nt_session_open(cli, PI_NETLOGON)) {
DEBUG(0,("Error connecting to NETLOGON pipe\n"));
goto done;
}
CHECK_RPC_ERR(cli_nt_setup_creds(cli,
sec_channel_type,
md4_trust_password, &neg_flags, 2),
"error in domain join verification");
/* Now store the secret in the secrets database */
strupper(domain);
@ -298,14 +326,11 @@ int net_rpc_join_newstyle(int argc, const char **argv)
goto done;
}
if (!secrets_store_machine_password(clear_trust_password)) {
if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) {
DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain));
}
/* Now check the whole process from top-to-bottom */
cli_samr_close(cli, mem_ctx, &user_pol);
cli_nt_session_close(cli); /* Done with this pipe */
/* double-check, connection from scratch */
retval = net_rpc_join_ok(domain);
done:
@ -317,7 +342,6 @@ done:
/* Display success or failure */
if (retval != 0) {
trust_password_delete(domain);
fprintf(stderr,"Unable to join domain %s.\n",domain);
} else {
printf("Joined domain %s.\n",domain);

View File

@ -198,6 +198,7 @@ int rpc_samdump(int argc, const char **argv)
struct cli_state *cli = NULL;
uchar trust_password[16];
DOM_CRED ret_creds;
uint32 sec_channel;
ZERO_STRUCT(ret_creds);
@ -210,12 +211,12 @@ int rpc_samdump(int argc, const char **argv)
if (!secrets_fetch_trust_account_password(lp_workgroup(),
trust_password,
NULL)) {
NULL, &sec_channel)) {
DEBUG(0,("Could not fetch trust account password\n"));
goto fail;
}
if (!cli_nt_open_netlogon(cli, trust_password, SEC_CHAN_BDC)) {
if (!cli_nt_open_netlogon(cli, trust_password, sec_channel)) {
DEBUG(0,("Error connecting to NETLOGON pipe\n"));
goto fail;
}
@ -810,6 +811,7 @@ int rpc_vampire(int argc, const char **argv)
DOM_CRED ret_creds;
uint32 neg_flags = 0x000001ff;
DOM_SID dom_sid;
uint32 sec_channel;
ZERO_STRUCT(ret_creds);
@ -825,12 +827,13 @@ int rpc_vampire(int argc, const char **argv)
}
if (!secrets_fetch_trust_account_password(lp_workgroup(),
trust_password, NULL)) {
trust_password, NULL,
&sec_channel)) {
d_printf("Could not retrieve domain trust secret\n");
goto fail;
}
result = cli_nt_setup_creds(cli, SEC_CHAN_BDC, trust_password,
result = cli_nt_setup_creds(cli, sec_channel, trust_password,
&neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
d_printf("Failed to setup BDC creds\n");