r7391: - Added client-support for various lsa_query_trust_dom_info-calls and a
authorGünther Deschner <gd@samba.org>
Wed, 8 Jun 2005 13:59:03 +0000 (13:59 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:57:07 +0000 (10:57 -0500)
  rpcclient-tester for some info-levels.

  Jerry, I tried to adopt to prs_pointer() where possible and to not
  interfere with your work for usrmgr.

- Add "net rpc trustdom vampire"-tool.

  This allows to retrieve Interdomain Trust(ed)-Relationships from
  NT4-Servers including cleartext-passwords (still stored in the local
  secrets.tdb).

  The net-hook was done in cooperation with Lars Mueller
  <lmuelle@suse.de>.

  To vampire trusted domains simply call:

        net rpc trustdom vampire -S nt4dc -Uadmin%pass

Guenther

source/include/rpc_lsa.h
source/libsmb/smbencrypt.c
source/rpc_client/cli_lsarpc.c
source/rpc_parse/parse_lsa.c
source/rpcclient/cmd_lsarpc.c
source/rpcclient/rpcclient.c
source/utils/net_rpc.c

index fe444bfdd109fc5cc992fd1baa346f6c6c802374..053a23b218508dee8cee55290d8ecda6e6996731 100644 (file)
@@ -60,7 +60,7 @@
 #define LSA_GETSYSTEMACCOUNT   0x17
 #define LSA_SETSYSTEMACCOUNT   0x18
 #define LSA_OPENTRUSTDOM       0x19    /* TODO: implement this one  -- jerry */
-#define LSA_QUERYTRUSTDOM      0x1a
+#define LSA_QUERYTRUSTDOMINFO  0x1a
 #define LSA_SETINFOTRUSTDOM    0x1b
 #define LSA_OPENSECRET         0x1c    /* TODO: implement this one  -- jerry */
 #define LSA_SETSECRET          0x1d    /* TODO: implement this one  -- jerry */
@@ -73,7 +73,7 @@
 #define LSA_ENUMACCTRIGHTS     0x24
 #define LSA_ADDACCTRIGHTS      0x25
 #define LSA_REMOVEACCTRIGHTS   0x26
-#define LSA_QUERYTRUSTDOMINFO  0x27
+#define LSA_QUERYTRUSTDOMINFOBYSID  0x27
 #define LSA_SETTRUSTDOMINFO    0x28
 #define LSA_DELETETRUSTDOM     0x29
 #define LSA_STOREPRIVDATA      0x2a
@@ -81,6 +81,8 @@
 #define LSA_OPENPOLICY2        0x2c
 #define LSA_UNK_GET_CONNUSER   0x2d /* LsaGetConnectedCredentials ? */
 #define LSA_QUERYINFO2         0x2e
+#define LSA_QUERYTRUSTDOMINFOBYNAME 0x30
+#define LSA_OPENTRUSTDOMBYNAME 0x37
 
 /* XXXX these are here to get a compile! */
 #define LSA_LOOKUPRIDS      0xFD
@@ -724,16 +726,27 @@ typedef struct lsa_r_removeprivs
 } LSA_R_REMOVEPRIVS;
 
 /*******************************************************/
-
+#if 0 /* jerry, I think this not correct - gd */
 typedef struct {
        POLICY_HND      handle;
        uint32          count;  /* ??? this is what ethereal calls it */
        DOM_SID         sid;
 } LSA_Q_OPEN_TRUSTED_DOMAIN;
+#endif
 
+/* LSA_Q_OPEN_TRUSTED_DOMAIN - LSA Query Open Trusted Domain */
+typedef struct lsa_q_open_trusted_domain
+{
+       POLICY_HND      pol;    /* policy handle */
+       DOM_SID2        sid;    /* domain sid */
+       uint32  access_mask;    /* access mask */
+       
+} LSA_Q_OPEN_TRUSTED_DOMAIN;
+
+/* LSA_R_OPEN_TRUSTED_DOMAIN - response to LSA Query Open Trusted Domain */
 typedef struct {
-       POLICY_HND      handle;
-       NTSTATUS        status;
+       POLICY_HND      handle; /* trustdom policy handle */
+       NTSTATUS        status; /* return code */
 } LSA_R_OPEN_TRUSTED_DOMAIN;
 
 
@@ -810,5 +823,138 @@ typedef struct {
        NTSTATUS        status;
 } LSA_R_SET_SECRET;
 
+/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO - LSA query trusted domain info */
+typedef struct lsa_query_trusted_domain_info
+{
+       POLICY_HND      pol;            /* policy handle */
+       uint16          info_class;     /* info class */
+
+} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO;
+
+/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID - LSA query trusted domain info */
+typedef struct lsa_query_trusted_domain_info_by_sid
+{
+       POLICY_HND      pol;            /* policy handle */
+       DOM_SID2        dom_sid;        /* domain sid */
+       uint16          info_class;     /* info class */
+       
+} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID;
+
+/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME - LSA query trusted domain info */
+typedef struct lsa_query_trusted_domain_info_by_name
+{
+       POLICY_HND      pol;            /* policy handle */
+       LSA_STRING      domain_name;    /* domain name */
+       uint16          info_class;     /* info class */
+       
+} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME;
+
+typedef struct trusted_domain_info_name {
+       LSA_STRING      netbios_name; 
+} TRUSTED_DOMAIN_INFO_NAME;
+
+typedef struct trusted_domain_info_posix_offset {
+       uint32          posix_offset;
+} TRUSTED_DOMAIN_INFO_POSIX_OFFSET;
+
+typedef struct lsa_data_buf {
+       uint32 size;
+       uint32 offset;
+       uint32 length;
+       uint8 *data;
+} LSA_DATA_BUF;
+
+typedef struct lsa_data_buf_hdr {
+       uint32 length;
+       uint32 size;
+       uint32 data_ptr;
+} LSA_DATA_BUF_HDR;
+
+
+typedef struct lsa_data_buf2 {
+       uint32 size;
+       uint8 *data;
+} LSA_DATA_BUF2;
+
+typedef struct trusted_domain_info_password {
+       uint32 ptr_password;
+       uint32 ptr_old_password;
+       LSA_DATA_BUF_HDR password_hdr;
+       LSA_DATA_BUF_HDR old_password_hdr;
+       LSA_DATA_BUF password;
+       LSA_DATA_BUF old_password;
+} TRUSTED_DOMAIN_INFO_PASSWORD;
+
+typedef struct trusted_domain_info_basic {
+       LSA_STRING      netbios_name;
+       DOM_SID2        sid;
+} TRUSTED_DOMAIN_INFO_BASIC;
+
+typedef struct trusted_domain_info_ex {
+       LSA_STRING      domain_name;
+       LSA_STRING      netbios_name;
+       DOM_SID2        sid;
+       uint32          trust_direction;
+       uint32          trust_type;
+       uint32          trust_attributes;
+} TRUSTED_DOMAIN_INFO_EX;
+
+typedef struct trust_domain_info_buffer {
+       NTTIME          last_update_time;
+       uint32          secret_type;
+       LSA_DATA_BUF2   data;
+} LSA_TRUSTED_DOMAIN_INFO_BUFFER;
+
+typedef struct trusted_domain_info_auth_info {
+       uint32 incoming_count;
+       LSA_TRUSTED_DOMAIN_INFO_BUFFER incoming_current_auth_info;
+       LSA_TRUSTED_DOMAIN_INFO_BUFFER incoming_previous_auth_info;
+       uint32 outgoing_count;
+       LSA_TRUSTED_DOMAIN_INFO_BUFFER outgoing_current_auth_info;
+       LSA_TRUSTED_DOMAIN_INFO_BUFFER outgoing_previous_auth_info;
+} TRUSTED_DOMAIN_INFO_AUTH_INFO;
+
+typedef struct trusted_domain_info_full_info {
+       TRUSTED_DOMAIN_INFO_EX          info_ex;
+       TRUSTED_DOMAIN_INFO_POSIX_OFFSET posix_offset;
+       TRUSTED_DOMAIN_INFO_AUTH_INFO   auth_info;
+} TRUSTED_DOMAIN_INFO_FULL_INFO;
+
+typedef struct trusted_domain_info_11 {
+       TRUSTED_DOMAIN_INFO_EX          info_ex;
+       LSA_DATA_BUF2                   data1;
+} TRUSTED_DOMAIN_INFO_11;
+
+typedef struct trusted_domain_info_all {
+       TRUSTED_DOMAIN_INFO_EX          info_ex;
+       LSA_DATA_BUF2                   data1;
+       TRUSTED_DOMAIN_INFO_POSIX_OFFSET posix_offset;
+       TRUSTED_DOMAIN_INFO_AUTH_INFO   auth_info;
+} TRUSTED_DOMAIN_INFO_ALL;
+
+/* LSA_TRUSTED_DOMAIN_INFO */
+typedef union lsa_trusted_domain_info
+{
+       uint16                                  info_class;
+       TRUSTED_DOMAIN_INFO_NAME                name;
+       /* deprecated - gd
+       TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO    controllers; */
+       TRUSTED_DOMAIN_INFO_POSIX_OFFSET        posix_offset;
+       TRUSTED_DOMAIN_INFO_PASSWORD            password;
+       TRUSTED_DOMAIN_INFO_BASIC               basic;
+       TRUSTED_DOMAIN_INFO_EX                  info_ex;
+       TRUSTED_DOMAIN_INFO_AUTH_INFO           auth_info;
+       TRUSTED_DOMAIN_INFO_FULL_INFO           full_info;
+       TRUSTED_DOMAIN_INFO_11                  info11;
+       TRUSTED_DOMAIN_INFO_ALL                 info_all;
+
+} LSA_TRUSTED_DOMAIN_INFO;
+
+/* LSA_R_QUERY_TRUSTED_DOMAIN_INFO - LSA query trusted domain info */
+typedef struct r_lsa_query_trusted_domain_info
+{
+       LSA_TRUSTED_DOMAIN_INFO *info;
+       NTSTATUS status;
+} LSA_R_QUERY_TRUSTED_DOMAIN_INFO;
 
 #endif /* _RPC_LSA_H */
index ab61f6b419e14f22e0c75b2ac1494c54e6e9eef8..8361c35a8e2bfb3b7392ab8631c0b79a103e2f54 100644 (file)
@@ -583,3 +583,69 @@ void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *sessi
                memcpy(&out->data[i], bout, MIN(8, in->length-i));
         }
 }
+
+/* Decrypts password-blob with session-key
+ * @param pass         password for session-key
+ * @param data_in      DATA_BLOB encrypted password
+ *
+ * Returns cleartext password in CH_UNIX 
+ * Caller must free the returned string
+ */
+
+char *decrypt_trustdom_secret(const char *pass, DATA_BLOB *data_in)
+{
+       DATA_BLOB data_out, sess_key;
+       uchar nt_hash[16];
+       uint32_t length;
+       uint32_t version;
+       fstring cleartextpwd;
+
+       if (!data_in || !pass)
+               return NULL;
+
+       /* generate md4 password-hash derived from the NT UNICODE password */
+       E_md4hash(pass, nt_hash);
+
+       /* hashed twice with md4 */
+       mdfour(nt_hash, nt_hash, 16);
+
+       /* 16-Byte session-key */
+       sess_key = data_blob(nt_hash, 16);
+       if (sess_key.data == NULL)
+               return NULL;
+       
+       data_out = data_blob(NULL, data_in->length);
+       if (data_out.data == NULL)
+               return NULL;
+       
+       /* decrypt with des3 */
+       sess_crypt_blob(&data_out, data_in, &sess_key, 0);
+
+       /* 4 Byte length, 4 Byte version */
+       length  = IVAL(data_out.data, 0);
+       version = IVAL(data_out.data, 4);
+
+       if (length > data_in->length - 8) {
+               DEBUG(0,("decrypt_trustdom_secret: invalid length (%d)\n", length));
+               return NULL;
+       }
+       
+       if (version != 1) {
+               DEBUG(0,("decrypt_trustdom_secret: unknown version number (%d)\n", version));
+               return NULL;
+       }
+       
+       rpcstr_pull(cleartextpwd, data_out.data + 8, sizeof(fstring), length, 0 );
+
+#ifdef DEBUG_PASSWORD
+       DEBUG(100,("decrypt_trustdom_secret: length is: %d, version is: %d, password is: %s\n", 
+                               length, version, cleartextpwd));
+#endif
+
+       data_blob_free(&data_out);
+       data_blob_free(&sess_key);
+       
+       return SMB_STRDUP(cleartextpwd);
+
+}
+
index f404b5144a6b13a37224438abd666aa105db7b6a..47dd0b1ea310ff4dc68322d5b370ab61f6e42ef2 100644 (file)
@@ -1452,4 +1452,199 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
 
 #endif
 
+NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                    POLICY_HND *pol, DOM_SID *dom_sid, uint32 access_mask,
+                                    POLICY_HND *trustdom_pol)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_OPEN_TRUSTED_DOMAIN q;
+       LSA_R_OPEN_TRUSTED_DOMAIN r;
+       NTSTATUS result;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Initialise input parameters */
+
+       init_lsa_q_open_trusted_domain(&q, pol, dom_sid, access_mask);
+
+       /* Marshall data and send request */
+
+       if (!lsa_io_q_open_trusted_domain("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENTRUSTDOM, &qbuf, &rbuf)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!lsa_io_r_open_trusted_domain("", &r, &rbuf, 0)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       /* Return output parameters */
+       
+       if (NT_STATUS_IS_OK(result = r.status)) {
+               *trustdom_pol = r.handle;
+       }
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                          POLICY_HND *pol, 
+                                          uint16 info_class, DOM_SID *dom_sid, 
+                                          LSA_TRUSTED_DOMAIN_INFO **info)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_QUERY_TRUSTED_DOMAIN_INFO q;
+       LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+       init_q_query_trusted_domain_info(&q, pol, info_class); 
+
+       if (!lsa_io_q_query_trusted_domain_info("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFO, &qbuf, &rbuf)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if (!NT_STATUS_IS_OK(result = r.status)) {
+               goto done;
+       }
+
+       *info = r.info;
+               
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+
+NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                                 POLICY_HND *pol, 
+                                                 uint16 info_class, DOM_SID *dom_sid, 
+                                                 LSA_TRUSTED_DOMAIN_INFO **info)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID q;
+       LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+       init_q_query_trusted_domain_info_by_sid(&q, pol, info_class, dom_sid); 
+
+       if (!lsa_io_q_query_trusted_domain_info_by_sid("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID, &qbuf, &rbuf)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if (!NT_STATUS_IS_OK(result = r.status)) {
+               goto done;
+       }
+
+       *info = r.info;
+
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                                  POLICY_HND *pol, 
+                                                  uint16 info_class, const char *domain_name, 
+                                                  LSA_TRUSTED_DOMAIN_INFO **info)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME q;
+       LSA_R_QUERY_TRUSTED_DOMAIN_INFO r;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
+
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Marshall data and send request */
+
+       init_q_query_trusted_domain_info_by_name(&q, pol, info_class, domain_name); 
+
+       if (!lsa_io_q_query_trusted_domain_info_by_name("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME, &qbuf, &rbuf)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       /* Unmarshall response */
+
+       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if (!NT_STATUS_IS_OK(result = r.status)) {
+               goto done;
+       }
+
+       *info = r.info;
+
+done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+       
+       return result;
+}
+
 /** @} **/
+
index 6d0a0bfc51cf049cd42605752ee07d11fa4ecae6..884012c9be76f8c2a6b7c0ca2aad0ba954bf2e2f 100644 (file)
@@ -2503,8 +2503,21 @@ BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *out
 }
 
 /*******************************************************************
+ Inits an LSA_Q_OPEN_TRUSTED_DOMAIN structure.
 ********************************************************************/
 
+void init_lsa_q_open_trusted_domain(LSA_Q_OPEN_TRUSTED_DOMAIN *q, POLICY_HND *hnd, DOM_SID *sid, uint32 desired_access)
+{
+       memcpy(&q->pol, hnd, sizeof(q->pol));
+
+       init_dom_sid2(&q->sid, sid);
+       q->access_mask = desired_access;
+}
+
+/*******************************************************************
+********************************************************************/
+
+#if 0 /* jerry, I think this not correct - gd */
 BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *in, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain");
@@ -2524,8 +2537,34 @@ BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *i
 
        return True;
 }
+#endif
+
+/*******************************************************************
+ Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN structure.
+********************************************************************/
+
+BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *q_o, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_pol_hnd("pol", &q_o->pol, ps, depth))
+               return False;
+
+       if(!smb_io_dom_sid2("sid", &q_o->sid, ps, depth))
+               return False;
+
+       if(!prs_uint32("access", ps, depth, &q_o->access_mask))
+               return False;
+  
+       return True;
+}
 
 /*******************************************************************
+ Reads or writes an LSA_R_OPEN_TRUSTED_DOMAIN structure.
 ********************************************************************/
 
 BOOL lsa_io_r_open_trusted_domain(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN *out, prs_struct *ps, int depth)
@@ -2536,7 +2575,7 @@ BOOL lsa_io_r_open_trusted_domain(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN *o
        if(!prs_align(ps))
                return False;
 
-       if (!smb_io_pol_hnd("", &out->handle, ps, depth))
+       if (!smb_io_pol_hnd("handle", &out->handle, ps, depth))
                return False;
 
        if(!prs_ntstatus("status", ps, depth, &out->status))
@@ -2726,3 +2765,308 @@ BOOL lsa_io_r_delete_object(const char *desc, LSA_R_DELETE_OBJECT *out, prs_stru
 
        return True;
 }
+
+/*******************************************************************
+ Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO structure.
+********************************************************************/
+
+void init_q_query_trusted_domain_info(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO *q, 
+                                     POLICY_HND *hnd, uint16 info_class) 
+{
+       DEBUG(5, ("init_q_query_trusted_domain_info\n"));
+       
+       q->pol = *hnd;
+       q->info_class = info_class;
+}
+
+/*******************************************************************
+ Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME structure.
+********************************************************************/
+
+void init_q_query_trusted_domain_info_by_name(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME *q, 
+                                             POLICY_HND *hnd, uint16 info_class, 
+                                             const char *dom_name)
+{
+       DEBUG(5, ("init_q_query_trusted_domain_info_by_name\n"));
+       
+       q->pol = *hnd;
+       init_lsa_string(&q->domain_name, dom_name );
+       q->info_class = info_class;
+}
+
+/*******************************************************************
+ Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID structure.
+********************************************************************/
+
+void init_q_query_trusted_domain_info_by_sid(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID *q, 
+                                            POLICY_HND *hnd, uint16 info_class, 
+                                            DOM_SID *dom_sid)
+{
+       DEBUG(5, ("init_q_query_trusted_domain_info_by_sid\n"));
+       
+       q->pol = *hnd;
+       init_dom_sid2(&q->dom_sid, dom_sid);
+       q->info_class = info_class;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_trusted_domain_info(const char *desc, 
+                                       LSA_Q_QUERY_TRUSTED_DOMAIN_INFO *q_q,
+                                       prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth))
+               return False;
+
+       if(!prs_uint16("info_class", ps, depth, &q_q->info_class))
+               return False;
+
+       return True;
+}
+
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_trusted_domain_info_by_sid(const char *desc, 
+                                              LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID *q_q,
+                                              prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info_by_sid");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_dom_sid2("dom_sid", &q_q->dom_sid, ps, depth))
+               return False;
+
+       if(!prs_uint16("info_class", ps, depth, &q_q->info_class))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_trusted_domain_info_by_name(const char *desc, 
+                                               LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME *q_q,
+                                               prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info_by_name");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_lsa_string("domain_name", &q_q->domain_name, ps, depth))
+               return False;
+
+       if(!prs_uint16("info_class", ps, depth, &q_q->info_class))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL smb_io_lsa_data_buf_hdr(const char *desc, LSA_DATA_BUF_HDR *buf_hdr, 
+                                   prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "smb_io_lsa_data_buf_hdr");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("length", ps, depth, &buf_hdr->length))
+               return False;
+       
+       if(!prs_uint32("size", ps, depth, &buf_hdr->size))
+               return False;
+
+       if (!prs_uint32("data_ptr", ps, depth, &buf_hdr->data_ptr))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL smb_io_lsa_data_buf(const char *desc, LSA_DATA_BUF *buf, 
+                               prs_struct *ps, int depth, int length, int size)
+{
+       prs_debug(ps, depth, desc, "smb_io_lsa_data_buf");
+       depth++;
+
+       if ( UNMARSHALLING(ps) ) {
+               if ( !(buf->data = PRS_ALLOC_MEM( ps, uint8, length )) )
+                       return False;
+       }
+
+       if (!prs_uint32("size", ps, depth, &buf->size))
+               return False;
+
+       if (!prs_uint32("offset", ps, depth, &buf->offset))
+               return False;
+
+       if (!prs_uint32("length", ps, depth, &buf->length))
+               return False;
+
+       if(!prs_uint8s(False, "data", ps, depth, buf->data, size))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL lsa_io_trustdom_query_1(const char *desc, TRUSTED_DOMAIN_INFO_NAME *name, 
+                                   prs_struct *ps, int depth)
+{
+       if (!smb_io_lsa_string("netbios_name", &name->netbios_name, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL lsa_io_trustdom_query_3(const char *desc, TRUSTED_DOMAIN_INFO_POSIX_OFFSET *posix, 
+                                   prs_struct *ps, int depth)
+{
+       if(!prs_uint32("posix_offset", ps, depth, &posix->posix_offset))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL lsa_io_trustdom_query_4(const char *desc, TRUSTED_DOMAIN_INFO_PASSWORD *password, 
+                                   prs_struct *ps, int depth)
+{
+       if(!prs_align(ps))
+               return False;
+       
+       if(!prs_uint32("ptr_password", ps, depth, &password->ptr_password))
+               return False;
+
+       if(!prs_uint32("ptr_old_password", ps, depth, &password->ptr_old_password))
+               return False;
+
+       if (&password->ptr_password) {
+       
+               if (!smb_io_lsa_data_buf_hdr("password_hdr", &password->password_hdr, ps, depth))
+                       return False;
+
+               if (!smb_io_lsa_data_buf("password", &password->password, ps, depth, 
+                                       password->password_hdr.length, password->password_hdr.size))
+                       return False;
+       }
+
+       if (&password->ptr_old_password) {
+
+               if (!smb_io_lsa_data_buf_hdr("old_password_hdr", &password->old_password_hdr, ps, depth))
+                       return False;
+
+               if (!smb_io_lsa_data_buf("old_password", &password->old_password, ps, depth, 
+                                       password->old_password_hdr.length, password->old_password_hdr.size))
+                       return False;
+       }
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL lsa_io_trustdom_query(const char *desc, prs_struct *ps, int depth, LSA_TRUSTED_DOMAIN_INFO *info)
+{
+       prs_debug(ps, depth, desc, "lsa_io_trustdom_query");
+       depth++;
+
+       if(!prs_uint16("info_class", ps, depth, &info->info_class))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       switch (info->info_class) {
+       case 1:
+               if(!lsa_io_trustdom_query_1("name", &info->name, ps, depth))
+                       return False;
+               break;
+       case 3:
+               if(!lsa_io_trustdom_query_3("posix_offset", &info->posix_offset, ps, depth))
+                       return False;
+               break;
+       case 4:
+               if(!lsa_io_trustdom_query_4("password", &info->password, ps, depth))
+                       return False;
+               break;
+       default:
+               DEBUG(0,("unsupported info-level: %d\n", info->info_class));
+               return False;
+               break;
+       }
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_QUERY_TRUSTED_DOMAIN_INFO structure.
+********************************************************************/
+
+BOOL lsa_io_r_query_trusted_domain_info(const char *desc, 
+                                       LSA_R_QUERY_TRUSTED_DOMAIN_INFO *r_q, 
+                                       prs_struct *ps, int depth)
+{
+       if (r_q == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "lsa_io_r_query_trusted_domain_info");
+       depth++;
+
+       if (!prs_pointer("trustdom", ps, depth, (void**)&r_q->info, 
+                        sizeof(LSA_TRUSTED_DOMAIN_INFO), 
+                        (PRS_POINTER_CAST)lsa_io_trustdom_query) )
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_ntstatus("status", ps, depth, &r_q->status))
+               return False;
+
+       return True;
+}
+
index f6ecd8c706dc2061036ea36732832f6aaff8b656..cccf9679e3de953f2c7c27e18da32a4dcb72802e 100644 (file)
@@ -746,6 +746,191 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli,
        return result;
 }
 
+static void display_trust_dom_info_1(TRUSTED_DOMAIN_INFO_NAME *n)
+{
+       printf("NetBIOS Name:\t%s\n", unistr2_static(&n->netbios_name.unistring));
+}
+
+static void display_trust_dom_info_3(TRUSTED_DOMAIN_INFO_POSIX_OFFSET *p)
+{
+       printf("Posix Offset:\t%d\n", p->posix_offset);
+}
+
+static void display_trust_dom_info_4(TRUSTED_DOMAIN_INFO_PASSWORD *p, const char *password)
+{
+       char *pwd, *pwd_old;
+       
+       DATA_BLOB data     = data_blob(NULL, p->password.length);
+       DATA_BLOB data_old = data_blob(NULL, p->old_password.length);
+
+       memcpy(data.data, p->password.data, p->password.length);
+       data.length     = p->password.length;
+                               
+       memcpy(data_old.data, p->old_password.data, p->old_password.length);
+       data_old.length = p->old_password.length;
+       
+       pwd     = decrypt_trustdom_secret(password, &data);
+       pwd_old = decrypt_trustdom_secret(password, &data_old);
+       
+       printf("Password:\t%s\n", pwd);
+       printf("Old Password:\t%s\n", pwd_old);
+
+       SAFE_FREE(pwd);
+       SAFE_FREE(pwd_old);
+       
+       data_blob_free(&data);
+       data_blob_free(&data_old);
+}
+
+static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_class, const char *pass)
+{
+       switch (info_class) {
+       case 1:
+               display_trust_dom_info_1(&info->name);
+               break;
+       case 3:
+               display_trust_dom_info_3(&info->posix_offset);
+               break;
+       case 4:
+               display_trust_dom_info_4(&info->password, pass);
+               break;
+       default:
+               printf("unsupported info-class: %d\n", info_class);
+               break;
+       }
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli,
+                                               TALLOC_CTX *mem_ctx, int argc, 
+                                               const char **argv) 
+{
+       POLICY_HND pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       DOM_SID dom_sid;
+       uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       LSA_TRUSTED_DOMAIN_INFO *info;
+
+       uint32 info_class = 1; 
+
+       if (argc > 3 || argc < 2) {
+               printf("Usage: %s [sid] [info_class]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (!string_to_sid(&dom_sid, argv[1]))
+               return NT_STATUS_NO_MEMORY;
+
+       if (argc == 3)
+               info_class = atoi(argv[2]);
+
+       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol,
+                                                         info_class, &dom_sid, &info);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       display_trust_dom_info(info, info_class, cli->pwd.password);
+
+ done:
+       if (&pol)
+               cli_lsa_close(cli, mem_ctx, &pol);
+
+       return result;
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli,
+                                                TALLOC_CTX *mem_ctx, int argc,
+                                                const char **argv) 
+{
+       POLICY_HND pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       LSA_TRUSTED_DOMAIN_INFO *info;
+       uint32 info_class = 1; 
+
+       if (argc > 3 || argc < 2) {
+               printf("Usage: %s [name] [info_class]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 3)
+               info_class = atoi(argv[2]);
+
+       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = cli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, 
+                                                          info_class, argv[1], &info);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       display_trust_dom_info(info, info_class, cli->pwd.password);
+
+ done:
+       if (&pol)
+               cli_lsa_close(cli, mem_ctx, &pol);
+
+       return result;
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli,
+                                          TALLOC_CTX *mem_ctx, int argc,
+                                          const char **argv) 
+{
+       POLICY_HND pol, trustdom_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       LSA_TRUSTED_DOMAIN_INFO *info;
+       DOM_SID dom_sid;
+       uint32 info_class = 1; 
+
+       if (argc > 3 || argc < 2) {
+               printf("Usage: %s [sid] [info_class]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (!string_to_sid(&dom_sid, argv[1]))
+               return NT_STATUS_NO_MEMORY;
+
+
+       if (argc == 3)
+               info_class = atoi(argv[2]);
+
+       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+       
+       result = cli_lsa_open_trusted_domain(cli, mem_ctx, &pol,
+                                            &dom_sid, access_mask, &trustdom_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = cli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, 
+                                                  info_class, &dom_sid, &info);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       display_trust_dom_info(info, info_class, cli->pwd.password);
+
+ done:
+       if (&pol)
+               cli_lsa_close(cli, mem_ctx, &pol);
+
+       return result;
+}
+
+
 
 /* List of commands exported by this module */
 
@@ -771,6 +956,9 @@ struct cmd_set lsarpc_commands[] = {
        { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account",   "" },
        { "lsalookupprivvalue",  RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value,  NULL, PI_LSARPC, "Get a privilege value given its name", "" },
        { "lsaquerysecobj",      RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj,       NULL, PI_LSARPC, "Query LSA security object", "" },
+       { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" },
+       { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" },
+       { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" },
 
        { NULL }
 };
index c02a279db9ebd8fe7f909965fcce3bf48fec2699..14004327ad43eeab4a1f13a1110f9c80fa60d350 100644 (file)
@@ -204,10 +204,10 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                        i = 0;
                        tmp_set++;
                        while(tmp_set->name) {
-                               printf("%20s", tmp_set->name);
+                               printf("%30s", tmp_set->name);
                                 tmp_set++;
                                i++;
-                               if (i%4 == 0)
+                               if (i%3 == 0)
                                        printf("\n");
                        }
                        
index 3956756489e8abb9ec461021af773e3e026243fb..9793932b5137039f7a78401a9764b645a853b595 100644 (file)
@@ -4795,6 +4795,7 @@ static int rpc_trustdom_usage(int argc, const char **argv)
        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");
+       d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
        return -1;
 }
 
@@ -4810,6 +4811,201 @@ static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid,
        return NT_STATUS_OK;
 }
 
+static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
+{
+       fstring ascii_sid, padding;
+       int pad_len, col_len = 20;
+
+       /* convert sid into ascii string */
+       sid_to_string(ascii_sid, dom_sid);
+
+       /* calculate padding space for d_printf to look nicer */
+       pad_len = col_len - strlen(trusted_dom_name);
+       padding[pad_len] = 0;
+       do padding[--pad_len] = ' '; while (pad_len);
+                       
+       d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
+}
+
+static NTSTATUS vampire_trusted_domain(struct cli_state *cli, 
+                                     TALLOC_CTX *mem_ctx, 
+                                     POLICY_HND *pol, 
+                                     DOM_SID dom_sid, 
+                                     const char *trusted_dom_name)
+{
+       NTSTATUS nt_status;
+       LSA_TRUSTED_DOMAIN_INFO *info;
+       char *cleartextpwd;
+       DATA_BLOB data;
+       smb_ucs2_t *uni_dom_name;
+
+       nt_status = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, pol, 4, &dom_sid, &info);
+       
+       if (NT_STATUS_IS_ERR(nt_status)) {
+               DEBUG(0,("Could not query trusted domain info. Error was %s\n",
+               nt_errstr(nt_status)));
+               goto done;
+       }
+
+       data = data_blob(NULL, info->password.password.length);
+
+       memcpy(data.data, info->password.password.data, info->password.password.length);
+       data.length     = info->password.password.length;
+                               
+       cleartextpwd = decrypt_trustdom_secret(cli->pwd.password, &data);
+
+       if (cleartextpwd == NULL) {
+               DEBUG(0,("retrieved NULL password\n"));
+               nt_status = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+       
+       if (push_ucs2_talloc(mem_ctx, &uni_dom_name, trusted_dom_name) < 0) {
+               DEBUG(0, ("Could not convert domain name %s to unicode\n",
+                         trusted_dom_name));
+               nt_status = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if (!secrets_store_trusted_domain_password(trusted_dom_name,
+                                                  uni_dom_name,
+                                                  strlen_w(uni_dom_name)+1,
+                                                  cleartextpwd,
+                                                  dom_sid)) {
+               DEBUG(0, ("Storing password for trusted domain failed.\n"));
+               nt_status = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",  
+               trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
+
+done:
+       SAFE_FREE(cleartextpwd);
+       data_blob_free(&data);
+
+       return nt_status;
+}
+
+static int rpc_trustdom_vampire(int argc, const char **argv)
+{
+       /* common variables */
+       TALLOC_CTX* mem_ctx;
+       struct cli_state *cli;
+       NTSTATUS nt_status;
+       const char *domain_name = NULL;
+       DOM_SID *queried_dom_sid;
+       POLICY_HND connect_hnd;
+
+       /* trusted domains listing variables */
+       unsigned int num_domains, enum_ctx = 0;
+       int i;
+       DOM_SID *domain_sids;
+       char **trusted_dom_names;
+       fstring pdc_name;
+       char *dummy;
+
+       /*
+        * Listing trusted domains (stored in secrets.tdb, if local)
+        */
+
+       mem_ctx = talloc_init("trust relationships vampire");
+
+       /*
+        * set domain and pdc name to local samba server (default)
+        * or to remote one given in command line
+        */
+
+       if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
+               domain_name = opt_workgroup;
+               opt_target_workgroup = opt_workgroup;
+       } else {
+               fstrcpy(pdc_name, global_myname());
+               domain_name = talloc_strdup(mem_ctx, lp_workgroup());
+               opt_target_workgroup = domain_name;
+       };
+
+       /* 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, PI_LSARPC)) {
+               DEBUG(0, ("Could not initialise lsa pipe\n"));
+               return -1;
+       };
+
+       nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, 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 */, 
+               &dummy, &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("Vampire trusted domains:\n\n");
+
+       do {
+               nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
+                                                  &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++) {
+
+                       print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
+
+                       nt_status = vampire_trusted_domain(cli, mem_ctx, &connect_hnd, 
+                                                          domain_sids[i], trusted_dom_names[i]);
+                       if (!NT_STATUS_IS_OK(nt_status))
+                               return -1;
+               };
+
+               /*
+                * in case of no trusted domains say something rather
+                * than just display blank line
+                */
+               if (!num_domains) d_printf("none\n");
+
+       } 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;
+       };
+
+       /* close lsarpc pipe and connection to IPC$ */
+       cli_nt_session_close(cli);
+       cli_shutdown(cli);
+
+       talloc_destroy(mem_ctx);         
+       return 0;
+}
 
 static int rpc_trustdom_list(int argc, const char **argv)
 {
@@ -4819,7 +5015,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        NTSTATUS nt_status;
        const char *domain_name = NULL;
        DOM_SID *queried_dom_sid;
-       fstring ascii_sid, padding;
+       fstring padding;
        int ascii_dom_name_len;
        POLICY_HND connect_hnd;
        
@@ -4905,15 +5101,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
                };
                
                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);
+                       print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
                };
                
                /*
@@ -5065,6 +5253,7 @@ static int rpc_trustdom(int argc, const char **argv)
                {"revoke", rpc_trustdom_revoke},
                {"help", rpc_trustdom_usage},
                {"list", rpc_trustdom_list},
+               {"vampire", rpc_trustdom_vampire},
                {NULL, NULL}
        };