trust relationship listing (patch)

mimir at diament.ists.pwr.wroc.pl mimir at diament.ists.pwr.wroc.pl
Thu Jul 25 11:05:01 GMT 2002


Here are another patches adding trust relationship features.
More details:
 1) trusts.diff
    Better error reporting in cli_lsa_enum_trust_dom().
    Implementation of cli_samr_enum_dom_users() which cli_samr.c
    lacked.
    Additional debugging in trusted domain enumeration code in
    secrets.c 
 2) net.diff
    More "consts" -- one of arguments in net_find_dc().
    Modified implementation of run_rpc_command() -- now it
    allows to reuse already opened connection (if it is passed)
    to remote server's IPC$ (e.g. as part of longer exchange
    of rpc calls). I'm sure Andrew will argue ;-)
    More neat version of rpc_trustdom_list() function. 


I'm waiting for _any_ feedback.


-- 
cheers,
+------------------------------------------------------------+
|Rafal 'Mimir' Szczesniak <mimir at diament.ists.pwr.wroc.pl>   |
|*BSD, GNU/Linux and Samba                                  /
|__________________________________________________________/
-------------- next part --------------
Index: libsmb/cli_lsarpc.c
===================================================================
RCS file: /cvsroot/samba/source/libsmb/cli_lsarpc.c,v
retrieving revision 1.46
diff -u -r1.46 cli_lsarpc.c
--- libsmb/cli_lsarpc.c	1 Jun 2002 00:10:08 -0000	1.46
+++ libsmb/cli_lsarpc.c	24 Jul 2002 16:39:56 -0000
@@ -543,7 +543,7 @@
 NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol, uint32 *enum_ctx, 
                                 uint32 *pref_num_domains, uint32 *num_domains,
-				char ***domain_names, DOM_SID **domain_sids)
+                                char ***domain_names, DOM_SID **domain_sids)
 {
 	prs_struct qbuf, rbuf;
 	LSA_Q_ENUM_TRUST_DOM q;
@@ -598,7 +598,7 @@
 
 		if (!*domain_names) {
 			DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
-			result = NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_NO_MEMORY;
 			goto done;
 		}
 
@@ -606,7 +606,7 @@
 						 r.num_domains);
 		if (!domain_sids) {
 			DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n"));
-			result = NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_NO_MEMORY;
 			goto done;
 		}
 
@@ -631,6 +631,7 @@
 
 	return result;
 }
+
 
 /** Enumerate priviledges*/
 
Index: libsmb/cli_samr.c
===================================================================
RCS file: /cvsroot/samba/source/libsmb/cli_samr.c,v
retrieving revision 1.31
diff -u -r1.31 cli_samr.c
--- libsmb/cli_samr.c	21 Jun 2002 17:23:18 -0000	1.31
+++ libsmb/cli_samr.c	24 Jul 2002 16:39:57 -0000
@@ -5,7 +5,8 @@
    Copyright (C) Andrew Tridgell              1992-1997,2000,
    Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
    Copyright (C) Paul Ashton                       1997,2000,
-   Copyright (C) Elrond                                 2000.
+   Copyright (C) Elrond                                 2000,
+   Copyright (C) Rafal Szczesniak                       2002.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -490,6 +491,113 @@
 
 	return result;
 }
+
+/**
+ * Enumerate domain users
+ *
+ * @param cli client state structure
+ * @param mem_ctx talloc context
+ * @param pol opened domain policy handle
+ * @param start_idx starting index of enumeration, returns context for
+                    next enumeration
+ * @param acb_mask account control bit mask (to enumerate some particular
+ *                 kind of accounts)
+ * @param size max acceptable size of response
+ * @param dom_users returned array of domain user names
+ * @param rids returned array of domain user RIDs
+ * @param num_dom_users numer returned entries
+ * 
+ * @return NTSTATUS returned in rpc response
+ **/
+NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                 POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask,
+                                 uint32 size, char ***dom_users, uint32 **rids,
+                                 uint32 *num_dom_users)
+{
+	prs_struct qdata;
+	prs_struct rdata;
+	SAMR_Q_ENUM_DOM_USERS q;
+	SAMR_R_ENUM_DOM_USERS r;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+	int i;
+	
+	ZERO_STRUCT(q);
+	ZERO_STRUCT(r);
+	
+	if (cli == NULL || pol == NULL)
+		return result;
+	
+	/* initialise parse structures */
+	prs_init(&qdata, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rdata, 0, mem_ctx, UNMARSHALL);
+	
+	DEBUG(4, ("SAMR Enum Domain Users. start_idx: %d, acb: %d, size: %d\n",
+			*start_idx, acb_mask, size));
+	
+	/* fill query structure with parameters */
+	init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size);
+	
+	/* prepare query stream */
+	if (!samr_io_q_enum_dom_users("", &q, &qdata, 0)) {
+		prs_mem_free(&qdata);
+		prs_mem_free(&rdata);
+		return result;
+	};
+	
+	/* send rpc call over the pipe */
+	if (!rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &qdata, &rdata)) {
+		prs_mem_free(&qdata);
+		prs_mem_free(&rdata);
+		return result;
+	}
+		
+	/* unpack received stream */
+	if(!samr_io_r_enum_dom_users("", &r, &rdata, 0)) {
+		prs_mem_free(&qdata);
+		prs_mem_free(&rdata);
+		result = r.status;
+		return result;
+	}
+	
+	/* return the data obtained in response */
+	if (!NT_STATUS_IS_OK(r.status) &&
+		(NT_STATUS_EQUAL(r.status, STATUS_MORE_ENTRIES) ||
+		NT_STATUS_EQUAL(r.status, NT_STATUS_NO_MORE_ENTRIES))) {
+		return r.status;
+	};
+	
+	*start_idx = r.next_idx;
+	*num_dom_users = r.num_entries2;
+	result = r.status;
+
+	/* allocate memory needed to return received data */	
+	*rids = (uint32*)talloc(mem_ctx, sizeof(uint32[r.num_entries2]));
+	if (!*rids) {
+		DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
+		return NT_STATUS_NO_MEMORY;
+	};
+		
+	*dom_users = (char**)talloc(mem_ctx, sizeof(char*) * r.num_entries2);
+	if (!*dom_users) {
+		DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
+		return NT_STATUS_NO_MEMORY;
+	};
+
+	/* fill output buffers with rpc response */
+	for (i = 0; i < r.num_entries2; i++) {
+		fstring conv_buf;
+		
+		(*rids)[i] = r.sam[i].rid;
+		unistr2_to_ascii(conv_buf, &(r.uni_acct_name[i]), sizeof(conv_buf) - 1);
+		(*dom_users)[i] = talloc_strdup(mem_ctx, conv_buf);
+	};
+	
+	prs_mem_free(&qdata);
+	prs_mem_free(&rdata);
+	
+	return result;
+};
+
 
 /* Enumerate domain groups */
 
Index: passdb/secrets.c
===================================================================
RCS file: /cvsroot/samba/source/passdb/secrets.c,v
retrieving revision 1.38
diff -u -r1.38 secrets.c
--- passdb/secrets.c	20 Jul 2002 13:02:46 -0000	1.38
+++ passdb/secrets.c	24 Jul 2002 16:40:09 -0000
@@ -388,7 +388,9 @@
 
 
 /**
- * The linked list is allocated on the supplied talloc context, caller gets to destory
+ * Get trusted domains info from secrets.tdb.
+ *
+ * The linked list is allocated on the supplied talloc context, caller gets to destroy
  * when done.
  *
  * @param ctx Allocation context
@@ -409,10 +411,11 @@
 	int start_idx;
 	uint32 idx = 0;
 	size_t size;
+	char dom_name[32];
 	struct trusted_dom_pass *pass;
 	NTSTATUS status;
 
-	secrets_init();
+	if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
 
 	*num_domains = 0;
 	start_idx = *enum_ctx;
@@ -455,6 +458,10 @@
 			SAFE_FREE(pass);
 			continue;
 		}
+		
+		ucs2_to_ascii(dom_name, pass->uni_name, sizeof(dom_name));
+		DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
+			   idx, dom_name, sid_string_static(&pass->domain_sid)));
 
 		SAFE_FREE(secrets_key);
 
@@ -475,6 +482,10 @@
 			dom->name = talloc_strdup_w(ctx, pass->uni_name);
 			
 			(*domains)[idx - start_idx] = dom;
+			
+			DEBUG(18, ("Secret record is in required range.\n
+				   start_idx = %d, max_num_domains = %d. Added to returned array.\n",
+				   start_idx, max_num_domains));
 
 			*enum_ctx = idx + 1;
 			(*num_domains)++;
@@ -487,6 +498,10 @@
 				/* this is the last entry in the whole enumeration */
 				status = NT_STATUS_OK;
 			}
+		} else {
+			DEBUG(18, ("Secret is outside the required range.\n
+				   start_idx = %d, max_num_domains = %d. Not added to returned array\n",
+				   start_idx, max_num_domains));
 		}
 		
 		idx++;
-------------- next part --------------
Index: utils/net.c
===================================================================
RCS file: /cvsroot/samba/source/utils/net.c,v
retrieving revision 1.52
diff -u -r1.52 net.c
--- utils/net.c	14 Jul 2002 03:49:15 -0000	1.52
+++ utils/net.c	24 Jul 2002 16:40:25 -0000
@@ -234,7 +234,7 @@
 }
 
 
-BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, char *domain_name)
+BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, const char *domain_name)
 {
 	struct in_addr *ip_list;
 	int addr_count;
Index: utils/net_rpc.c
===================================================================
RCS file: /cvsroot/samba/source/utils/net_rpc.c,v
retrieving revision 1.24
diff -u -r1.24 net_rpc.c
--- utils/net_rpc.c	20 Jul 2002 11:58:06 -0000	1.24
+++ utils/net_rpc.c	24 Jul 2002 16:40:28 -0000
@@ -117,18 +117,20 @@
  * @return A shell status integer (0 for success)
  */
 
-static int run_rpc_command(const char *pipe_name, int conn_flags,
-			   rpc_command_fn fn,
-			   int argc, const char **argv) 
+static int run_rpc_command(struct cli_state *cli_arg, const char *pipe_name, int conn_flags,
+                           rpc_command_fn fn,
+                           int argc, const char **argv) 
 {
-	struct cli_state *cli = net_make_ipc_connection(conn_flags);
+	struct cli_state *cli = NULL;
 	TALLOC_CTX *mem_ctx;
 	NTSTATUS nt_status;
 	DOM_SID *domain_sid;
 
-	if (!cli) {
-		return -1;
-	}
+	/* make use of cli_state handed over as an argument, if possible */
+	if (!cli_arg)
+		cli = net_make_ipc_connection(conn_flags);
+	else
+		cli = cli_arg;
 
 	domain_sid = net_get_remote_domain_sid(cli);
 
@@ -141,7 +143,7 @@
 	}
 	
 	if (!cli_nt_session_open(cli, pipe_name)) {
-		DEBUG(0, ("Could not initialise samr pipe\n"));
+		DEBUG(0, ("Could not initialise %s pipe\n", pipe_name));
 	}
 	
 	nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
@@ -156,6 +158,10 @@
 	if (cli->nt_pipe_fnum)
 		cli_nt_session_close(cli);
 	
+	/* close the connection only if it was opened here */
+	if (!cli_arg)
+		cli_shutdown(cli);
+	
 	talloc_destroy(mem_ctx);
 
 	return (!NT_STATUS_IS_OK(nt_status));
@@ -199,7 +205,7 @@
 
 static int rpc_changetrustpw(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
+	return run_rpc_command(NULL, PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
 			       argc, argv);
 }
 
@@ -261,7 +267,7 @@
 
 static int net_rpc_join_oldstyle(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
+	return run_rpc_command(NULL, PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
 			       argc, argv);
 }
 
@@ -371,7 +377,7 @@
  **/
 int net_rpc_info(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
+	return run_rpc_command(NULL, PIPE_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
 			       rpc_info_internals,
 			       argc, argv);
 }
@@ -477,7 +483,7 @@
 
 static int rpc_user_add(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
+	return run_rpc_command(NULL, PIPE_SAMR, 0, rpc_user_add_internals,
 			       argc, argv);
 }
 
@@ -578,7 +584,7 @@
 
 static int rpc_user_delete(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_SAMR, 0, rpc_user_del_internals,
+	return run_rpc_command(NULL, PIPE_SAMR, 0, rpc_user_del_internals,
 			       argc, argv);
 }
 
@@ -680,7 +686,7 @@
 
 static int rpc_user_info(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_SAMR, 0, rpc_user_info_internals,
+	return run_rpc_command(NULL, PIPE_SAMR, 0, rpc_user_info_internals,
 			       argc, argv);
 }
 
@@ -775,7 +781,7 @@
 		if (opt_long_list_entries) {
 		} else {
 		}
-			return run_rpc_command(PIPE_SAMR, 0, 
+			return run_rpc_command(NULL,PIPE_SAMR, 0, 
 					       rpc_user_list_internals,
 					       argc, argv);
 	}
@@ -926,7 +932,7 @@
 		if (opt_long_list_entries) {
 		} else {
 		}
-		return run_rpc_command(PIPE_SAMR, 0, 
+		return run_rpc_command(NULL, PIPE_SAMR, 0, 
 				       rpc_group_list_internals,
 				       argc, argv);
 	}
@@ -984,7 +990,7 @@
 		DEBUG(1,("Sharename or path not specified on add\n"));
 		return rpc_share_usage(argc, argv);
 	}
-	return run_rpc_command(PIPE_SRVSVC, 0, 
+	return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 			       rpc_share_add_internals,
 			       argc, argv);
 }
@@ -1030,7 +1036,7 @@
 		DEBUG(1,("Sharename not specified on delete\n"));
 		return rpc_share_usage(argc, argv);
 	}
-	return run_rpc_command(PIPE_SRVSVC, 0, 
+	return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 			       rpc_share_del_internals,
 			       argc, argv);
 }
@@ -1120,7 +1126,7 @@
 	};
 
 	if (argc == 0)
-		return run_rpc_command(PIPE_SRVSVC, 0, 
+		return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 				       rpc_share_list_internals,
 				       argc, argv);
 
@@ -1174,7 +1180,7 @@
 		return(rpc_file_usage(argc, argv));
 	}
 
-	return run_rpc_command(PIPE_SRVSVC, 0, 
+	return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 			       rpc_file_close_internals,
 			       argc, argv);
 }
@@ -1227,7 +1233,7 @@
 
 	/* if argc > 0, must be user command */
 	if (argc > 0)
-		username = argv[0];
+		username = smb_xstrdup(argv[0]);
 		
 	result = cli_srvsvc_net_file_enum(
 		cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
@@ -1265,7 +1271,7 @@
 		return(rpc_file_usage(argc, argv));
 	}
 
-	return run_rpc_command(PIPE_SRVSVC, 0, 
+	return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 			       rpc_file_list_internals,
 			       argc, argv);
 }
@@ -1290,7 +1296,7 @@
 	};
 
 	if (argc == 0)
-		return run_rpc_command(PIPE_SRVSVC, 0, 
+		return run_rpc_command(NULL, PIPE_SRVSVC, 0, 
 				       rpc_file_list_internals,
 				       argc, argv);
 
@@ -1345,7 +1351,7 @@
 
 static int rpc_shutdown_abort(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
+	return run_rpc_command(NULL, PIPE_WINREG, 0, rpc_shutdown_abort_internals,
 			       argc, argv);
 }
 
@@ -1435,7 +1441,7 @@
 
 static int rpc_shutdown(int argc, const char **argv) 
 {
-	return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
+	return run_rpc_command(NULL, PIPE_WINREG, 0, rpc_shutdown_internals,
 				       argc, argv);
 }
 
@@ -1460,7 +1466,7 @@
  */
 
 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-				       int argc, const char **argv) {
+                                           int argc, const char **argv) {
 
 	POLICY_HND connect_pol, domain_pol, user_pol;
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -1483,16 +1489,14 @@
 
 	strupper(acct_name);
 
-	/* Get sam policy handle */
-	
-	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+	/* Get samr 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);
@@ -1501,10 +1505,9 @@
 	}
 
 	/* 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 ? */
+	unknown = 0xe005000b; /* No idea what this is - a permission mask?
+	                         mimir: yes, most probably it is */
 
 	result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
 					  acct_name, acb_info, unknown,
@@ -1529,7 +1532,7 @@
 
 static int rpc_trustdom_add(int argc, const char **argv)
 {
-	return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
+	return run_rpc_command(NULL, PIPE_SAMR, 0, rpc_trustdom_add_internals,
 			       argc, argv);
 }
 
@@ -1562,9 +1565,10 @@
 
 extern char *opt_user_name;
 extern char *opt_password;
+extern char *opt_workgroup;
 
-static int rpc_trustdom_establish(int argc, const char **argv) {
-
+static int rpc_trustdom_establish(int argc, const char **argv)
+{
 	struct cli_state *cli;
 	struct in_addr server_ip;
 	POLICY_HND connect_hnd;
@@ -1582,14 +1586,22 @@
 	 */
 
 	if (argc != 1) {
-		d_printf("Usage: net rpc trustdom add <domain_name>\n");
+		d_printf("Usage: net rpc trustdom establish <domain_name>\n");
 		return -1;
 	}
 
-
 	domain_name = smb_xstrdup(argv[0]);
 	strupper(domain_name);
 	
+	/*
+	 * opt_workgroup will be used by connection functions further,
+	 * hence it should be set to remote domain name instead of ours
+	 */
+	if (opt_workgroup) {
+		SAFE_FREE(opt_workgroup);
+		opt_workgroup = smb_xstrdup(domain_name);
+	};
+	
 	asprintf(&acct_name, "%s$", lp_workgroup());
 	strupper(acct_name);
 	
@@ -1634,10 +1646,7 @@
 	 
 	/*
 	 * 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)
+	 * note: It is now used only to get unicode domain name
 	 */
 	
 	if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
@@ -1645,12 +1654,8 @@
 		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())) {
+	if (!(mem_ctx = talloc_init_named("establishing trust relationship to domain %s",
+	                domain_name))) {
 		DEBUG(0, ("talloc_init() failed\n"));
 		cli_shutdown(cli);
 		return -1;
@@ -1679,10 +1684,12 @@
 
 	if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
 		DEBUG(0, ("Could not initialise lsa pipe\n"));
+		cli_shutdown(cli);
+		return -1;
 	}
 
 	nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
-					&connect_hnd);
+	                                 &connect_hnd);
 	if (NT_STATUS_IS_ERR(nt_status)) {
 		DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
 			nt_errstr(nt_status)));
@@ -1692,7 +1699,8 @@
 	/* Querying info level 5 */
 	
 	nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
-					5 /* info level */, domain_name, &domain_sid);
+	                                      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",
 			nt_errstr(nt_status)));
@@ -1743,8 +1751,8 @@
  * @return Integer status (0 means success)
  **/
 
-static int rpc_trustdom_revoke(int argc, const char **argv) {
-
+static int rpc_trustdom_revoke(int argc, const char **argv)
+{
 	char* domain_name;
 
 	if (argc < 1) return -1;
@@ -1772,7 +1780,8 @@
  * @return Integer status returned to shell
  **/
  
-static int rpc_trustdom_usage(int argc, const char **argv) {
+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");
@@ -1782,6 +1791,255 @@
 }
 
 
+static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                              int argc, const char **argv)
+{
+	fstring str_sid;
+	sid_to_string(str_sid, domain_sid);
+	d_printf("%s\n", str_sid);
+	return NT_STATUS_OK;
+};
+
+
+extern char* opt_workgroup;
+extern char* opt_target_worgroup;
+extern char* opt_host;
+extern char* opt_password;
+
+static int rpc_trustdom_list(int argc, const char **argv)
+{
+	/* common variables */
+	TALLOC_CTX* mem_ctx;
+	struct cli_state *cli, *remote_cli;
+	NTSTATUS nt_status;
+	char *domain_name = NULL;
+	DOM_SID queried_dom_sid;
+	fstring ascii_sid, padding;
+	int ascii_dom_name_len;
+	POLICY_HND connect_hnd;
+	
+	/* trusted domains listing variables */
+	int enum_ctx = 0, pref_num_domains = 5;
+	int num_domains, i, pad_len, col_len = 20;
+	DOM_SID *domain_sids;
+	char **trusted_dom_names;
+	fstring pdc_name;
+	
+	/* trusting domains listing variables */
+	POLICY_HND domain_hnd;
+	char **trusting_dom_names;
+	uint32 *trusting_dom_rids;
+	
+	/*
+	 * Listing trusted domains (stored in secrets.tdb, if local)
+	 */
+
+	mem_ctx = talloc_init_named("trust relationships listing");
+
+	/*
+	 * set domain and pdc name to local samba server (default)
+	 * or to remote one given in command line
+	 */
+	strupper(opt_workgroup);
+	if (strcmp(opt_workgroup, lp_workgroup())) {
+		domain_name = opt_workgroup;
+		if (opt_target_workgroup) SAFE_FREE(opt_target_workgroup);
+		opt_target_workgroup = opt_workgroup;
+	} else {
+		safe_strcpy(pdc_name, global_myname, FSTRING_LEN);
+		domain_name = talloc_strdup(mem_ctx, lp_workgroup());
+		if (opt_target_workgroup) SAFE_FREE(opt_target_workgroup);
+		opt_target_workgroup = domain_name;
+	};
+
+	/* anonymous access is denied */
+	if (!opt_password) {
+		char *pass = getpass("Password:");
+		if (pass) opt_password = strdup(pass);
+	};
+
+	/* open \PIPE\lsarpc and open policy handle */
+	if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
+		DEBUG(0, ("Couldn't connect to domain controller\n"));
+		return -1;
+	};
+
+	if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
+		DEBUG(0, ("Could not initialise lsa pipe\n"));
+		return -1;
+	};
+
+	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",
+ 			nt_errstr(nt_status)));
+		return -1;
+	};
+	
+	/* query info level 5 to obtain sid of a domain being queried */
+	nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
+					5 /* info level */, domain_name, &queried_dom_sid);
+	if (NT_STATUS_IS_ERR(nt_status)) {
+		DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
+			nt_errstr(nt_status)));
+		return -1;
+	}
+		
+	/*
+	 * Keep calling LsaEnumTrustdom over opened pipe until
+	 * the end of enumeration is reached
+	 */
+	 
+	d_printf("Trusted domains list:\n\n");
+
+	do {
+		nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
+											&pref_num_domains, &num_domains,
+											&trusted_dom_names, &domain_sids);
+		
+		if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
+				nt_errstr(nt_status)));
+			return -1;
+		};
+		
+		for (i = 0; i < num_domains; i++) {
+			/* convert sid into ascii string */
+			sid_to_string(ascii_sid, &(domain_sids[i]));
+		
+			/* calculate padding space for d_printf to look nicer */
+			pad_len = col_len - strlen(trusted_dom_names[i]);
+			padding[pad_len] = 0;
+			do padding[--pad_len] = ' '; while (pad_len);
+			
+			d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid);
+		};
+
+	} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+
+	/* close this connection before doing next one */
+	nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+	if (NT_STATUS_IS_ERR(nt_status)) {
+		DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
+			nt_errstr(nt_status)));
+		return -1;
+	};
+	
+	cli_nt_session_close(cli);
+
+	/*
+	 * Listing trusting domains (stored in passdb backend, if local)
+	 */
+	
+	d_printf("\nTrusting domains list:\n\n");
+
+	/*
+	 * Open \PIPE\samr and get needed policy handles
+	 */
+	if (!cli_nt_session_open(cli, PIPE_SAMR)) {
+		DEBUG(0, ("Could not initialise samr pipe\n"));
+		return -1;
+	};
+	
+	/* SamrConnect */
+	nt_status = cli_samr_connect(cli, mem_ctx, SAMR_ACCESS_OPEN_DOMAIN,
+								 &connect_hnd);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
+			nt_errstr(nt_status)));
+		return -1;
+	};
+	
+	/* SamrOpenDomain - we have to open domain policy handle in order to be
+	   able to enumerate accounts*/
+	nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
+									 DOMAIN_ACCESS_ENUM_ACCOUNTS,
+									 &queried_dom_sid, &domain_hnd);									 
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		DEBUG(0, ("Couldn't open domain object. Error was %s\n",
+			nt_errstr(nt_status)));
+		return -1;
+	};
+	
+	/*
+	 * perform actual enumeration
+	 */
+	 
+	enum_ctx = 0;	/* reset enumeration context from last enumeration */
+	do {
+			
+		nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
+		                                    &enum_ctx, ACB_DOMTRUST, 0xffff,
+		                                    &trusting_dom_names, &trusting_dom_rids,
+		                                    &num_domains);
+		if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
+				nt_errstr(nt_status)));
+			return -1;
+		};
+		
+		for (i = 0; i < num_domains; i++) {
+
+			/*
+			 * get each single domain's sid (do we _really_ need this ?):
+			 *  1) connect to domain's pdc
+			 *  2) query the pdc for domain's sid
+			 */
+
+			/* get rid of '$' tail */
+			ascii_dom_name_len = strlen(trusting_dom_names[i]);
+			if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
+				trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
+			
+			/* calculate padding space for d_printf to look nicer */
+			pad_len = col_len - strlen(trusting_dom_names[i]);
+			padding[pad_len] = 0;
+			do padding[--pad_len] = ' '; while (pad_len);
+
+			/* set opt_* variables to remote domain */
+			strupper(trusting_dom_names[i]);
+			opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
+			if (opt_target_workgroup) SAFE_FREE(opt_target_workgroup);
+			opt_target_workgroup = opt_workgroup;
+			
+			d_printf("%s%s", trusting_dom_names[i], padding);
+			
+			/* connect to remote domain controller */
+			remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
+			if (remote_cli) {			
+				/* query for domain's sid */
+				if (run_rpc_command(remote_cli, PIPE_LSARPC, 0, rpc_query_domain_sid, argc, argv))
+					d_printf("couldn't get domain's sid\n");
+
+				cli_shutdown(remote_cli);
+			
+			} else {
+				d_printf("domain controller is not responding\n");
+			};
+		};
+		
+	} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+
+	/* close opened samr and domain policy handles */
+	nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
+	};
+	
+	nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
+	};
+	
+	/* close samr pipe and connection to IPC$ */
+	cli_nt_session_close(cli);
+	cli_shutdown(cli);
+
+	talloc_destroy(mem_ctx);	 
+	return 0;
+}
+
 /**
  * Entrypoint for 'net rpc trustdom' code
  *
@@ -1799,6 +2057,7 @@
 		{"establish", rpc_trustdom_establish},
 		{"revoke", rpc_trustdom_revoke},
 		{"help", rpc_trustdom_usage},
+		{"list", rpc_trustdom_list},
 		{NULL, NULL}
 	};
 


More information about the samba-technical mailing list