diff options
author | Andrew Bartlett <abartlet@samba.org> | 2002-03-01 02:56:35 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2002-03-01 02:56:35 +0000 |
commit | 75de5a5dfa4ccd2f46e9f1bddad7ca2d0d2e665e (patch) | |
tree | 588e4931fbe645f6717c4d1ecb6da83f37ad9784 /source3/utils | |
parent | cd76214b15246553284ca43441780d49cf2f5819 (diff) | |
download | samba-75de5a5dfa4ccd2f46e9f1bddad7ca2d0d2e665e.tar.gz samba-75de5a5dfa4ccd2f46e9f1bddad7ca2d0d2e665e.tar.bz2 samba-75de5a5dfa4ccd2f46e9f1bddad7ca2d0d2e665e.zip |
The beginning of trusted and trusting domain support from
Rafal Szczesniak <mimir@diament.ists.pwr.wroc.pl>
This adds the 'net' tools to manipulate the trusted domains.
Andrew Bartlett
(This used to be commit 770c8a31d9804d3339ffa0de8b5072a5c7eb02df)
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/net.c | 54 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 372 |
2 files changed, 411 insertions, 15 deletions
diff --git a/source3/utils/net.c b/source3/utils/net.c index 3577b922d3..aac5235ac8 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -104,9 +104,9 @@ int net_run_function(int argc, const char **argv, struct functable *table, /**************************************************************************** connect to \\server\ipc$ ****************************************************************************/ -static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *server_name) +NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip, + const char *server_name) { - struct cli_state *c; NTSTATUS nt_status; if (!got_pass) { @@ -116,14 +116,14 @@ static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *s } } - nt_status = cli_full_connection(&c, opt_requester_name, server_name, + nt_status = cli_full_connection(c, opt_requester_name, server_name, server_ip, opt_port, "IPC$", "IPC", opt_user_name, opt_workgroup, opt_password, strlen(opt_password)); if (NT_STATUS_IS_OK(nt_status)) { - return c; + return nt_status; } else { DEBUG(0,("Cannot connect to server. Error was %s\n", get_nt_error_msg(nt_status))); @@ -134,29 +134,29 @@ static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *s NT_STATUS_V(NT_STATUS_LOGON_FAILURE)) d_printf("The username or password was not correct.\n"); - return NULL; + return nt_status; } } /**************************************************************************** connect to \\server\ipc$ anonymously ****************************************************************************/ -static struct cli_state *connect_to_ipc_anonymous(struct in_addr *server_ip, const char *server_name) +NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, + struct in_addr *server_ip, const char *server_name) { - struct cli_state *c; NTSTATUS nt_status; - nt_status = cli_full_connection(&c, opt_requester_name, server_name, + nt_status = cli_full_connection(c, opt_requester_name, server_name, server_ip, opt_port, "IPC$", "IPC", "", "", "", 0); if (NT_STATUS_IS_OK(nt_status)) { - return c; + return nt_status; } else { DEBUG(0,("Cannot connect to server (anonymously). Error was %s\n", get_nt_error_msg(nt_status))); - return NULL; + return nt_status; } } @@ -232,11 +232,39 @@ static BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **se return True; } + +BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, char *domain_name) +{ + struct in_addr *ip_list; + int addr_count; + + if (get_dc_list(True /* PDC only*/, domain_name, &ip_list, &addr_count)) { + fstring dc_name; + if (addr_count < 1) { + return False; + } + + *server_ip = *ip_list; + + if (is_zero_ip(*server_ip)) + return False; + + if (!lookup_dc_name(global_myname, domain_name, server_ip, dc_name)) + return False; + + safe_strcpy(server_name, dc_name, FSTRING_LEN); + return True; + } else + return False; +} + + struct cli_state *net_make_ipc_connection(unsigned flags) { char *server_name = NULL; struct in_addr server_ip; - struct cli_state *cli; + struct cli_state *cli = NULL; + NTSTATUS nt_status; if (!net_find_server(flags, &server_ip, &server_name)) { d_printf("\nUnable to find a suitable server\n"); @@ -244,9 +272,9 @@ struct cli_state *net_make_ipc_connection(unsigned flags) } if (flags & NET_FLAGS_ANONYMOUS) { - cli = connect_to_ipc_anonymous(&server_ip, server_name); + nt_status = connect_to_ipc_anonymous(&cli, &server_ip, server_name); } else { - cli = connect_to_ipc(&server_ip, server_name); + nt_status = connect_to_ipc(&cli, &server_ip, server_name); } SAFE_FREE(server_name); return cli; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index d46644acf5..b19a82f366 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -302,9 +302,9 @@ static int rpc_join(int argc, const char **argv) * All paramaters are provided by the run_rpc_command funcion, except for * argc, argv which are passes through. * - * @param domain_sid The domain sid aquired from the remote server + * @param domain_sid The domain sid acquired from the remote server * @param cli A cli_state connected to the server. - * @param mem_ctx Talloc context, destoyed on compleation of the function. + * @param mem_ctx Talloc context, destoyed on completion of the function. * @param argc Standard main() style argc * @param argc Standard main() style argv. Initial components are already * stripped @@ -554,6 +554,372 @@ static int rpc_shutdown(int argc, const char **argv) argc, argv); } +/*************************************************************************** + NT Domain trusts code (i.e. 'net rpc trustdom' functionality) + + ***************************************************************************/ + +/** + * Add interdomain trust account to the RPC server. + * All parameters (except for argc and argv) are passed by run_rpc_command + * function. + * + * @param domain_sid The domain sid acquired from the server + * @param cli A cli_state connected to the server. + * @param mem_ctx Talloc context, destoyed on completion of the function. + * @param argc Standard main() style argc + * @param argc Standard main() style argv. Initial components are already + * stripped + * + * @return normal NTSTATUS return code + */ + +static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) { + + POLICY_HND connect_pol, domain_pol, user_pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + char *acct_name; + uint16 acb_info; + uint32 unknown, user_rid; + + if (argc != 1) { + d_printf("Usage: net rpc trustdom add <domain_name>\n"); + return NT_STATUS_OK; + } + + /* + * Make valid trusting domain account (ie. uppercased and with '$' appended) + */ + + if (asprintf(&acct_name, "%s$", argv[0]) < 0) { + return NT_STATUS_NO_MEMORY; + } + + strupper(acct_name); + + /* Get sam policy handle */ + + result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + &connect_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Get domain policy handle */ + + result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + MAXIMUM_ALLOWED_ACCESS, + domain_sid, &domain_pol); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + /* Create trusting domain's account */ + + acb_info = ACB_DOMTRUST; + unknown = 0xe005000b; /* No idea what this is - a permission mask? + Is it needed for interdomain account also ? */ + + result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, + acct_name, acb_info, unknown, + &user_pol, &user_rid); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + + done: + SAFE_FREE(acct_name); + return result; +} + +/** + * Create interdomain trust account for a remote domain. + * + * @param argc standard argc + * @param argv standard argv without initial components + * + * @return Integer status (0 means success) + **/ + +static int rpc_trustdom_add(int argc, const char **argv) +{ + return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals, + argc, argv); +} + + +/** + * Delete interdomain trust account for a remote domain. + * + * @param argc standard argc + * @param argv standard argv without initial components + * + * @return Integer status (0 means success) + **/ + +static int rpc_trustdom_del(int argc, const char **argv) +{ + d_printf("Sorry, not yet implemented.\n"); + return -1; +} + + +/** + * Establish trust relationship to a trusting domain. + * Interdomain account must already be created on remote PDC. + * + * @param argc standard argc + * @param argv standard argv without initial components + * + * @return Integer status (0 means success) + **/ + +extern char *opt_user_name; +extern char *opt_password; + +static int rpc_trustdom_establish(int argc, const char **argv) { + + struct cli_state *cli; + struct in_addr server_ip; + POLICY_HND connect_hnd; + TALLOC_CTX *mem_ctx; + NTSTATUS nt_status; + DOM_SID domain_sid; + WKS_INFO_100 wks_info; + + char* domain_name; + char* acct_name; + fstring pdc_name; + + /* + * Connect to \\server\ipc$ as 'our domain' account with password + */ + + domain_name = smb_xstrdup(argv[0]); + strupper(domain_name); + + asprintf(&acct_name, "%s$", lp_workgroup()); + strupper(acct_name); + + opt_user_name = (char*)malloc(strlen(acct_name) + 1); + safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1); + + /* find the domain controller */ + if (!net_find_dc(&server_ip, pdc_name, domain_name)) { + DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name)); + return -1; + } + + /* connect to ipc$ as username/password */ + nt_status = connect_to_ipc(&cli, &server_ip, pdc_name); + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) { + + /* Is it trusting domain account for sure ? */ + DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n", + get_nt_error_msg(nt_status))); + return -1; + } + + /* + * Connect to \\server\ipc$ again (this time anonymously) + */ + + nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name); + + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n", + domain_name, get_nt_error_msg(nt_status))); + } + + /* + * Use NetServerEnum2 to make sure we're talking to a proper server + */ + + if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) { + DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\ + for domain %s\n", domain_name)); + } + + /* + * Call WksQueryInfo to check remote server's capabilities + * FIXME:Is really necessary ? nt serv does this, but from samba's + * point of view it doesn't seem to make the difference + * IDEA: It may be used to get info about type of pdc we're talking to + * (e.g. WinNT or Win2k) + */ + + if (!cli_nt_session_open(cli, PIPE_WKSSVC)) { + DEBUG(0, ("Couldn't not initialise wkssvc pipe\n")); + return -1; + } + + /* TODO: convert this call from rpc_client/cli_wkssvc.c + to cli_wks_query_info() in libsmb/cli_wkssvc.c + UPDATE: already done :) + */ + + if (!(mem_ctx = talloc_init())) { + DEBUG(0, ("talloc_init() failed\n")); + cli_shutdown(cli); + return -1; + } + + nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info); + + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("WksQueryInfo call failed.\n")); + return -1; + } + + if (cli->nt_pipe_fnum) { + cli_nt_session_close(cli); + talloc_destroy(mem_ctx); + } + + + /* + * Call LsaOpenPolicy and LsaQueryInfo + */ + + if (!(mem_ctx = talloc_init())) { + DEBUG(0, ("talloc_init() failed\n")); + cli_shutdown(cli); + return -1; + } + + if (!cli_nt_session_open(cli, PIPE_LSARPC)) { + DEBUG(0, ("Could not initialise lsa pipe\n")); + } + + nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, + &connect_hnd); + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't open policy handle. Error was %s\n", + get_nt_error_msg(nt_status))); + return -1; + } + + /* Querying info level 5 */ + + nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd, + 5 /* info level */, domain_name, &domain_sid); + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("LSA Query Info failed. Returned error was %s\n", + get_nt_error_msg(nt_status))); + return -1; + } + + + /* There should be actually query info level 3 (following nt serv behaviour), + but I still don't know if it's _really_ necessary */ + + /* + * Close the pipes and clean up + */ + + nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd); + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n", + get_nt_error_msg(nt_status))); + return -1; + } + + if (cli->nt_pipe_fnum) + cli_nt_session_close(cli); + + talloc_destroy(mem_ctx); + + + /* + * Store the password in secrets db + */ + + if (!secrets_store_trusted_domain_password(domain_name, opt_password, + domain_sid)) { + DEBUG(0, ("Storing password for trusted domain failed.\n")); + return -1; + } + + DEBUG(0, ("Success!\n")); + return 0; +} + +/** + * Revoke trust relationship to the remote domain + * + * @param argc standard argc + * @param argv standard argv without initial components + * + * @return Integer status (0 means success) + **/ + +static int rpc_trustdom_revoke(int argc, const char **argv) { + + char* domain_name; + + if (argc < 1) return -1; + + /* generate upper cased domain name */ + domain_name = smb_xstrdup(argv[0]); + strupper(domain_name); + + /* delete password of the trust */ + if (!trusted_domain_password_delete(domain_name)) { + DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n", + domain_name)); + return -1; + }; + + return 0; +} + +/** + * Usage for 'net rpc trustdom' command + * + * @param argc standard argc + * @param argv standard argv without inital components + * + * @return Integer status returned to shell + **/ + +static int rpc_trustdom_usage(int argc, const char **argv) { + d_printf(" net rpc trustdom add \t\t add trusting domain's account\n"); + d_printf(" net rpc trustdom del \t\t delete trusting domain's account\n"); + d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n"); + d_printf(" net rpc trustdom revoke \t abandon relationship to trusted domain\n"); + d_printf(" net rpc trustdom list \t show current interdomain trust relationships\n"); + return -1; +} + + +/** + * Entrypoint for 'net rpc trustdom' code + * + * @param argc standard argc + * @param argv standard argv without initial components + * + * @return Integer status (0 means success) + */ + +static int rpc_trustdom(int argc, const char **argv) +{ + struct functable func[] = { + {"add", rpc_trustdom_add}, + {"del", rpc_trustdom_del}, + {"establish", rpc_trustdom_establish}, + {"revoke", rpc_trustdom_revoke}, + {NULL, NULL} + }; + + if (argc == 0) { + rpc_trustdom_usage(argc, argv); + return -1; + } + + return (net_run_function(argc, argv, func, rpc_user_usage)); +} + /****************************************************************************/ @@ -569,6 +935,7 @@ int net_rpc_usage(int argc, const char **argv) d_printf(" net rpc join \tto join a domain \n"); d_printf(" net rpc user \tto add, delete and list users\n"); d_printf(" net rpc changetrustpw \tto change the trust account password\n"); + d_printf(" net rpc trustdom \tto create trusting domain's account or establish trust\n"); d_printf(" net rpc abortshutdown \tto to abort the shutdown of a remote server\n"); d_printf(" net rpc shutdown \tto to shutdown a remote server\n"); d_printf("\n"); @@ -593,6 +960,7 @@ int net_rpc(int argc, const char **argv) {"join", rpc_join}, {"user", rpc_user}, {"changetrustpw", rpc_changetrustpw}, + {"trustdom", rpc_trustdom}, {"abortshutdown", rpc_shutdown_abort}, {"shutdown", rpc_shutdown}, {NULL, NULL} |