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 <[EMAIL PROTECTED]>   |
|*BSD, GNU/Linux and Samba                                  /
|__________________________________________________________/
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++;
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}
        };
 

Reply via email to