summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2003-04-16 10:20:14 +0000
committerAndrew Bartlett <abartlet@samba.org>2003-04-16 10:20:14 +0000
commit6e6b7b79edae3efd0197651e9a8ce6775c001cf2 (patch)
tree703a6e67574b344a83c9a551a0cc0ec80e5e62be
parentc7dc0b27aca8f7e4653b25dae37ea38d68fc045a (diff)
downloadsamba-6e6b7b79edae3efd0197651e9a8ce6775c001cf2.tar.gz
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
-rw-r--r--source/auth/auth_domain.c10
-rw-r--r--source/include/secrets.h4
-rw-r--r--source/libads/kerberos_verify.c2
-rw-r--r--source/libads/ldap.c8
-rw-r--r--source/libads/util.c8
-rw-r--r--source/libsmb/trusts_util.c65
-rw-r--r--source/nsswitch/winbindd_ads.c2
-rw-r--r--source/nsswitch/winbindd_cm.c8
-rw-r--r--source/nsswitch/winbindd_misc.c7
-rw-r--r--source/nsswitch/winbindd_pam.c19
-rw-r--r--source/passdb/machine_sid.c15
-rw-r--r--source/passdb/secrets.c102
-rw-r--r--source/rpc_client/cli_netlogon.c18
-rw-r--r--source/rpcclient/cmd_netlogon.c10
-rw-r--r--source/rpcclient/rpcclient.c5
-rw-r--r--source/smbd/change_trust_pw.c95
-rw-r--r--source/smbd/process.c6
-rw-r--r--source/utils/net.c32
-rw-r--r--source/utils/net.h2
-rw-r--r--source/utils/net_ads.c17
-rw-r--r--source/utils/net_rpc.c83
-rw-r--r--source/utils/net_rpc_join.c62
-rw-r--r--source/utils/net_rpc_samsync.c11
23 files changed, 368 insertions, 223 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
@@ -222,25 +222,40 @@ BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
}
/************************************************************************
+ 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
the above call.
************************************************************************/
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,26 +24,36 @@
#include "includes.h"
-/*********************************************************
- Change the domain password on the PDC.
-**********************************************************/
+/************************************************************************
+ Change the trust account password for a domain.
+************************************************************************/
-static NTSTATUS modify_trust_password( const char *domain, const char *remote_machine,
- unsigned char orig_trust_passwd_hash[16])
+NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine)
{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct in_addr pdc_ip;
+ fstring dc_name;
struct cli_state *cli;
- DOM_SID domain_sid;
- NTSTATUS nt_status;
- /*
- * Ensure we have the domain SID for this domain.
- */
+ if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
+ /* Use the PDC *only* for this */
+
+ if ( !get_pdc_ip(domain, &pdc_ip) ) {
+ DEBUG(0,("Can't get IP for PDC for domain %s\n", domain));
+ goto failed;
+ }
- if (!secrets_fetch_domain_sid(domain, &domain_sid)) {
- DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) )
+ goto failed;
}
-
+ /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */
+ else {
+ fstrcpy( dc_name, remote_machine );
+ }
+
+ /* if this next call fails, then give up. We can't do
+ password changes on BDC's --jerry */
+
if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine,
NULL, 0,
"IPC$", "IPC",
@@ -51,7 +61,8 @@ static NTSTATUS modify_trust_password( const char *domain, const char *remote_ma
"", 0, NULL)))
{
DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine));
- return NT_STATUS_UNSUCCESSFUL;
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto failed;
}
/*
@@ -65,64 +76,22 @@ static NTSTATUS modify_trust_password( const char *domain, const char *remote_ma
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
- return NT_STATUS_UNSUCCESSFUL;
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto failed;
}
- nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx,
- orig_trust_passwd_hash);
+ 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);
- 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;
- 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;
- }
-
- if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
- /* Use the PDC *only* for this */
-
- if ( !get_pdc_ip(domain, &pdc_ip) ) {
- DEBUG(0,("Can't get IP for PDC for domain %s\n", domain));
- goto failed;
- }
-
- if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) )
- goto failed;
- }
- /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */
- else {
- fstrcpy( dc_name, remote_machine );
- }
-
- /* 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);
-
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 <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},
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");