From 6e6b7b79edae3efd0197651e9a8ce6775c001cf2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Apr 2003 10:20:14 +0000 Subject: [PATCH] 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 --- source/auth/auth_domain.c | 10 ++- source/include/secrets.h | 4 +- source/libads/kerberos_verify.c | 2 +- source/libads/ldap.c | 8 ++- source/libads/util.c | 8 ++- source/libsmb/trusts_util.c | 65 +++++++++---------- source/nsswitch/winbindd_ads.c | 2 +- source/nsswitch/winbindd_cm.c | 8 ++- source/nsswitch/winbindd_misc.c | 7 ++- source/nsswitch/winbindd_pam.c | 19 +++--- source/passdb/machine_sid.c | 15 +++-- source/passdb/secrets.c | 102 ++++++++++++++++++++++++++---- source/rpc_client/cli_netlogon.c | 18 ------ source/rpcclient/cmd_netlogon.c | 10 +-- source/rpcclient/rpcclient.c | 5 +- source/smbd/change_trust_pw.c | 103 +++++++++++-------------------- source/smbd/process.c | 6 +- source/utils/net.c | 32 ++++++++-- source/utils/net.h | 2 +- source/utils/net_ads.c | 17 +++-- source/utils/net_rpc.c | 83 ++++++++++++++++++------- source/utils/net_rpc_join.c | 62 +++++++++++++------ source/utils/net_rpc_samsync.c | 11 ++-- 23 files changed, 372 insertions(+), 227 deletions(-) diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c index 7dca5914f0b..db5f7d82b08 100644 --- a/source/auth/auth_domain.c +++ b/source/auth/auth_domain.c @@ -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; } diff --git a/source/include/secrets.h b/source/include/secrets.h index 07faf28d439..dacfef26ead 100644 --- a/source/include/secrets.h +++ b/source/include/secrets.h @@ -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" diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c index 6a50137400f..35d429ca2ab 100644 --- a/source/libads/kerberos_verify.c +++ b/source/libads/kerberos_verify.c @@ -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; diff --git a/source/libads/ldap.c b/source/libads/ldap.c index baedfb28dbb..3ce80975da4 100644 --- a/source/libads/ldap.c +++ b/source/libads/ldap.c @@ -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; diff --git a/source/libads/util.c b/source/libads/util.c index 335cabc9526..9912a7ba831 100644 --- a/source/libads/util.c +++ b/source/libads/util.c @@ -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); } diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c index b8f84ba890a..d5a02bb6259 100644 --- a/source/libsmb/trusts_util.c +++ b/source/libsmb/trusts_util.c @@ -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 diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c index de3757aa44c..beb40af79de 100644 --- a/source/nsswitch/winbindd_ads.c +++ b/source/nsswitch/winbindd_ads.c @@ -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); diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 1b49d8ce013..dbcfdcf88f9 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -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); diff --git a/source/nsswitch/winbindd_misc.c b/source/nsswitch/winbindd_misc.c index 52889e85d42..fb56d0e6574 100644 --- a/source/nsswitch/winbindd_misc.c +++ b/source/nsswitch/winbindd_misc.c @@ -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) { diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index e49a95f4b87..2998372bd21 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -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))); diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c index 071af50877e..a578ecc7113 100644 --- a/source/passdb/machine_sid.c +++ b/source/passdb/machine_sid.c @@ -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; diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 64fedc7284e..138a9231fd3 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -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; /* diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c index 61d4b597231..ce0dd95e94a 100644 --- a/source/rpc_client/cli_netlogon.c +++ b/source/rpc_client/cli_netlogon.c @@ -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, diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c index 7a77d125a6f..32fa9c3699f 100644 --- a/source/rpcclient/cmd_netlogon.c +++ b/source/rpcclient/cmd_netlogon.c @@ -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"); diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c index efc883ff9ff..bf016e94c7c 100644 --- a/source/rpcclient/rpcclient.c +++ b/source/rpcclient/rpcclient.c @@ -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; } diff --git a/source/smbd/change_trust_pw.c b/source/smbd/change_trust_pw.c index a1409787330..8aff96d0d6d 100644 --- a/source/smbd/change_trust_pw.c +++ b/source/smbd/change_trust_pw.c @@ -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; } diff --git a/source/smbd/process.c b/source/smbd/process.c index de1bea493fa..54fd4a90d99 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -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; } diff --git a/source/utils/net.c b/source/utils/net.c index 9d8441e649a..5d526e22dfe 100644 --- a/source/utils/net.c +++ b/source/utils/net.c @@ -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); diff --git a/source/utils/net.h b/source/utils/net.h index c1b49a919b4..f83d0169bfd 100644 --- a/source/utils/net.h +++ b/source/utils/net.h @@ -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; diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c index 5a8265f0b9e..91f82a5dbe0 100644 --- a/source/utils/net_ads.c +++ b/source/utils/net_ads.c @@ -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(); diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index a35cdd0b5bb..9ae50aaf0dd 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -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 [%%password] [options]\n"\ + d_printf("net rpc join -U [%%password] [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 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}, diff --git a/source/utils/net_rpc_join.c b/source/utils/net_rpc_join.c index e2fd9aa4341..35564b1e10c 100644 --- a/source/utils/net_rpc_join.c +++ b/source/utils/net_rpc_join.c @@ -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); diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c index b886119eef9..909ed298cb3 100644 --- a/source/utils/net_rpc_samsync.c +++ b/source/utils/net_rpc_samsync.c @@ -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");