summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-03-01 02:56:35 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-03-01 02:56:35 +0000
commit75de5a5dfa4ccd2f46e9f1bddad7ca2d0d2e665e (patch)
tree588e4931fbe645f6717c4d1ecb6da83f37ad9784 /source3/utils
parentcd76214b15246553284ca43441780d49cf2f5819 (diff)
downloadsamba-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.c54
-rw-r--r--source3/utils/net_rpc.c372
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}