From f071020f5e49837154581c97c5af5f84d0e2de89 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Apr 2003 14:09:03 +0000 Subject: Merge from HEAD - save the type of channel used to contact the DC. This allows us to join as a BDC, without appearing on the network as one until we have the database replicated, and the admin changes the configuration. This also change the SID retreval order from secrets.tdb, so we no longer require a 'net rpc getsid' - the sid fetch during the domain join is sufficient. Also minor fixes to 'net'. Andrew Bartlett (This used to be commit 876e00fd112e4aaf7519eec27f382eb99ec7562a) --- source3/utils/net.c | 32 +++++++++++++--- source3/utils/net.h | 2 +- source3/utils/net_ads.c | 17 ++++++--- source3/utils/net_rpc.c | 85 +++++++++++++++++++++++++++++------------ source3/utils/net_rpc_join.c | 62 +++++++++++++++++++++--------- source3/utils/net_rpc_samsync.c | 11 ++++-- 6 files changed, 151 insertions(+), 58 deletions(-) (limited to 'source3/utils') diff --git a/source3/utils/net.c b/source3/utils/net.c index 67d3176b4d..b404bac595 100644 --- a/source3/utils/net.c +++ b/source3/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 @@ -623,11 +644,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()) @@ -636,7 +657,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 */ @@ -645,9 +666,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/source3/utils/net.h b/source3/utils/net.h index c1b49a919b..f83d0169bf 100644 --- a/source3/utils/net.h +++ b/source3/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/source3/utils/net_ads.c b/source3/utils/net_ads.c index 71b7a0802f..3615fd0e94 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -564,7 +564,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; } @@ -596,7 +596,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; @@ -637,6 +637,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]; @@ -645,6 +647,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); @@ -669,7 +676,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; @@ -692,7 +699,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; } @@ -945,7 +952,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/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index fcd8a54118..9ae50aaf0d 100644 --- a/source3/utils/net_rpc.c +++ b/source3/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,21 +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 (opt_user_specified) - return net_rpc_join_newstyle(argc, argv); - 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); } @@ -2181,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"); @@ -2247,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/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index e2fd9aa434..35564b1e10 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/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/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index b886119eef..909ed298cb 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/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"); -- cgit