r11706: Implement dsr_getdcname client code. It's handy: It not only gives you the IP
authorVolker Lendecke <vlendec@samba.org>
Sun, 13 Nov 2005 11:38:17 +0000 (11:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:24 +0000 (11:05 -0500)
address but also the fqdn of the remote dc and site info.

Volker
(This used to be commit 62d01ce7e6c14971084c208ab61f379cb172cb22)

source3/include/rpc_netlogon.h
source3/lib/util_unistr.c
source3/rpc_client/cli_netlogon.c
source3/rpc_parse/parse_net.c
source3/rpcclient/cmd_netlogon.c

index c73cd03f103d387fa7521a2752165d79831c04e3..bc4c41cd1f3aaf6a4ef6c53fab76c61330b2c122 100644 (file)
@@ -38,6 +38,7 @@
 #define NET_LOGON_CTRL2                0x0e
 #define NET_SAM_SYNC           0x10
 #define NET_TRUST_DOM_LIST     0x13
+#define NET_DSR_GETDCNAME      0x14
 #define NET_AUTH3              0x1a
 
 /* Secure Channel types.  used in NetrServerAuthenticate negotiation */
@@ -934,4 +935,37 @@ typedef struct net_r_sam_deltas_info {
        NTSTATUS status;
 } NET_R_SAM_DELTAS;
 
+/* NET_Q_DSR_GETDCNAME - Ask a DC for a trusted DC name and its address */
+typedef struct net_q_dsr_getdcname {
+       uint32 ptr_server_unc;
+       UNISTR2 uni_server_unc;
+       uint32 ptr_domain_name;
+       UNISTR2 uni_domain_name;
+       uint32 ptr_domain_guid;
+       struct uuid *domain_guid;
+       uint32 ptr_site_guid;
+       struct uuid *site_guid;
+       uint32_t flags;
+} NET_Q_DSR_GETDCNAME;
+
+/* NET_R_DSR_GETDCNAME - Ask a DC for a trusted DC name and its address */
+typedef struct net_r_dsr_getdcname {
+       uint32 ptr_dc_unc;
+       UNISTR2 uni_dc_unc;
+       uint32 ptr_dc_address;
+       UNISTR2 uni_dc_address;
+       int32 dc_address_type;
+       struct uuid domain_guid;
+       uint32 ptr_domain_name;
+       UNISTR2 uni_domain_name;
+       uint32 ptr_forest_name;
+       UNISTR2 uni_forest_name;
+       uint32 dc_flags;
+       uint32 ptr_dc_site_name;
+       UNISTR2 uni_dc_site_name;
+       uint32 ptr_client_site_name;
+       UNISTR2 uni_client_site_name;
+       WERROR result;
+} NET_R_DSR_GETDCNAME;
+
 #endif /* _RPC_NETLOGON_H */
index d80bb2ce5219b74149db09547e58fb52f0b0bfa4..b979745d36640b2d0280df45fb353acbcbf96498 100644 (file)
@@ -265,6 +265,34 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
                          src->uni_str_len * 2, 0);
 }
 
+/* Helper function to return a talloc'ed string. I have implemented it with a
+ * copy because I don't really know how pull_ucs2 and friends calculate the
+ * target size. If this turns out to be a major bottleneck someone with deeper
+ * multi-byte knowledge needs to revisit this.
+ * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would
+ * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
+ */
+
+size_t rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, char **dest,
+                                 UNISTR2 *src)
+{
+       pstring tmp;
+       size_t result;
+
+       result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp),
+                          src->uni_str_len * 2, 0);
+       if (result < 0) {
+               return result;
+       }
+
+       *dest = talloc_strdup(mem_ctx, tmp);
+       if (*dest == NULL) {
+               return -1;
+       }
+
+       return result;
+}
+
 /* Converts a string from internal samba format to unicode
  */ 
 
index af0062f2b390ab7f16739bc67881e621e5d8340f..f12f7d09fa7094a620efa79ac5cb57bd3a91742e 100644 (file)
@@ -417,6 +417,129 @@ NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
        return result;
 }
 
+/* Dsr_GetDCName */
+
+WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    const char *server_name,
+                                    const char *domain_name,
+                                    struct uuid *domain_guid,
+                                    struct uuid *site_guid,
+                                    uint32_t flags,
+                                    char **dc_unc, char **dc_address,
+                                    int32 *dc_address_type,
+                                    struct uuid *domain_guid_out,
+                                    char **domain_name_out,
+                                    char **forest_name,
+                                    uint32 *dc_flags,
+                                    char **dc_site_name,
+                                    char **client_site_name)
+{
+       prs_struct qbuf, rbuf;
+       NET_Q_DSR_GETDCNAME q;
+       NET_R_DSR_GETDCNAME r;
+       char *tmp_str;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialize input parameters */
+
+       tmp_str = talloc_asprintf(mem_ctx, "\\\\%s", server_name);
+       if (tmp_str == NULL) {
+               return WERR_NOMEM;
+       }
+
+       init_net_q_dsr_getdcname(&q, tmp_str, domain_name, domain_guid,
+                                site_guid, flags);
+
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_NETLOGON, NET_DSR_GETDCNAME,
+                       q, r,
+                       qbuf, rbuf,
+                       net_io_q_dsr_getdcname,
+                       net_io_r_dsr_getdcname,
+                       WERR_GENERAL_FAILURE);
+
+       if (!W_ERROR_IS_OK(r.result)) {
+               return r.result;
+       }
+
+       if (dc_unc != NULL) {
+               char *tmp;
+               if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
+                                              &r.uni_dc_unc) < 0) {
+                       return WERR_GENERAL_FAILURE;
+               }
+               if (*tmp == '\\') tmp += 1;
+               if (*tmp == '\\') tmp += 1;
+
+               /* We have to talloc_strdup, otherwise a talloc_steal would
+                  fail */
+               *dc_unc = talloc_strdup(mem_ctx, tmp);
+               if (*dc_unc == NULL) {
+                       return WERR_NOMEM;
+               }
+       }
+
+       if (dc_address != NULL) {
+               char *tmp;
+               if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
+                                              &r.uni_dc_address) < 0) {
+                       return WERR_GENERAL_FAILURE;
+               }
+               if (*tmp == '\\') tmp += 1;
+               if (*tmp == '\\') tmp += 1;
+
+               /* We have to talloc_strdup, otherwise a talloc_steal would
+                  fail */
+               *dc_address = talloc_strdup(mem_ctx, tmp);
+               if (*dc_address == NULL) {
+                       return WERR_NOMEM;
+               }
+       }
+
+       if (dc_address_type != NULL) {
+               *dc_address_type = r.dc_address_type;
+       }
+
+       if (domain_guid_out != NULL) {
+               *domain_guid_out = r.domain_guid;
+       }
+
+       if ((domain_name_out != NULL) &&
+           (rpcstr_pull_unistr2_talloc(mem_ctx, domain_name_out,
+                                       &r.uni_domain_name) < 1)) {
+               return WERR_GENERAL_FAILURE;
+       }
+
+       if ((forest_name != NULL) &&
+           (rpcstr_pull_unistr2_talloc(mem_ctx, forest_name,
+                                       &r.uni_forest_name) < 1)) {
+               return WERR_GENERAL_FAILURE;
+       }
+
+       if (dc_flags != NULL) {
+               *dc_flags = r.dc_flags;
+       }
+
+       if ((dc_site_name != NULL) &&
+           (rpcstr_pull_unistr2_talloc(mem_ctx, dc_site_name,
+                                       &r.uni_dc_site_name) < 1)) {
+               return WERR_GENERAL_FAILURE;
+       }
+
+       if ((client_site_name != NULL) &&
+           (rpcstr_pull_unistr2_talloc(mem_ctx, client_site_name,
+                                       &r.uni_client_site_name) < 1)) {
+               return WERR_GENERAL_FAILURE;
+       }
+
+       return WERR_OK;
+}
+
+
 /* Sam synchronisation */
 
 NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
index a32edd4384154bbd1a286c8660ac8b1895551b20..3732ab3a725950b78a4f4747bec184eb93c0da60 100644 (file)
@@ -3153,3 +3153,239 @@ BOOL net_io_r_sam_deltas(const char *desc,
 
        return True;
 }
+
+/*******************************************************************
+ Inits a NET_Q_DSR_GETDCNAME structure.
+********************************************************************/
+
+void init_net_q_dsr_getdcname(NET_Q_DSR_GETDCNAME *r_t, const char *server_unc,
+                             const char *domain_name,
+                             struct uuid *domain_guid,
+                             struct uuid *site_guid,
+                             uint32_t flags)
+{
+       DEBUG(5, ("init_net_q_dsr_getdcname\n"));
+
+       r_t->ptr_server_unc = (server_unc != NULL);
+       init_unistr2(&r_t->uni_server_unc, server_unc, UNI_STR_TERMINATE);
+
+       r_t->ptr_domain_name = (domain_name != NULL);
+       init_unistr2(&r_t->uni_domain_name, domain_name, UNI_STR_TERMINATE);
+
+       r_t->ptr_domain_guid = (domain_guid != NULL);
+       r_t->domain_guid = domain_guid;
+
+       r_t->ptr_site_guid = (site_guid != NULL);
+       r_t->site_guid = site_guid;
+
+       r_t->flags = flags;
+}
+
+/*******************************************************************
+ Reads or writes an NET_Q_DSR_GETDCNAME structure.
+********************************************************************/
+
+BOOL net_io_q_dsr_getdcname(const char *desc, NET_Q_DSR_GETDCNAME *r_t,
+                           prs_struct *ps, int depth)
+{
+       if (r_t == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "net_io_q_dsr_getdcname");
+       depth++;
+
+       if (!prs_uint32("ptr_server_unc", ps, depth, &r_t->ptr_server_unc))
+               return False;
+
+       if (!smb_io_unistr2("server_unc", &r_t->uni_server_unc,
+                           r_t->ptr_server_unc, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("ptr_domain_name", ps, depth, &r_t->ptr_domain_name))
+               return False;
+
+       if (!smb_io_unistr2("domain_name", &r_t->uni_domain_name,
+                           r_t->ptr_domain_name, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("ptr_domain_guid", ps, depth, &r_t->ptr_domain_guid))
+               return False;
+
+       if (UNMARSHALLING(ps) && (r_t->ptr_domain_guid)) {
+               r_t->domain_guid = PRS_ALLOC_MEM(ps, struct uuid, 1);
+               if (r_t->domain_guid == NULL)
+                       return False;
+       }
+
+       if ((r_t->ptr_domain_guid) &&
+           (!smb_io_uuid("domain_guid", r_t->domain_guid, ps, depth)))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("ptr_site_guid", ps, depth, &r_t->ptr_site_guid))
+               return False;
+
+       if (UNMARSHALLING(ps) && (r_t->ptr_site_guid)) {
+               r_t->site_guid = PRS_ALLOC_MEM(ps, struct uuid, 1);
+               if (r_t->site_guid == NULL)
+                       return False;
+       }
+
+       if ((r_t->ptr_site_guid) &&
+           (!smb_io_uuid("site_guid", r_t->site_guid, ps, depth)))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("flags", ps, depth, &r_t->flags))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Inits a NET_R_DSR_GETDCNAME structure.
+********************************************************************/
+void init_net_r_dsr_getdcname(NET_R_DSR_GETDCNAME *r_t, const char *dc_unc,
+                             const char *dc_address, int32 dc_address_type,
+                             struct uuid domain_guid, const char *domain_name,
+                             const char *forest_name, uint32 dc_flags,
+                             const char *dc_site_name,
+                             const char *client_site_name)
+{
+       DEBUG(5, ("init_net_q_dsr_getdcname\n"));
+
+       r_t->ptr_dc_unc = (dc_unc != NULL);
+       init_unistr2(&r_t->uni_dc_unc, dc_unc, UNI_STR_TERMINATE);
+
+       r_t->ptr_dc_address = (dc_address != NULL);
+       init_unistr2(&r_t->uni_dc_address, dc_address, UNI_STR_TERMINATE);
+
+       r_t->dc_address_type = dc_address_type;
+       r_t->domain_guid = domain_guid;
+
+       r_t->ptr_domain_name = (domain_name != NULL);
+       init_unistr2(&r_t->uni_domain_name, domain_name, UNI_STR_TERMINATE);
+
+       r_t->ptr_forest_name = (forest_name != NULL);
+       init_unistr2(&r_t->uni_forest_name, forest_name, UNI_STR_TERMINATE);
+
+       r_t->dc_flags = dc_flags;
+
+       r_t->ptr_dc_site_name = (dc_site_name != NULL);
+       init_unistr2(&r_t->uni_dc_site_name, dc_site_name, UNI_STR_TERMINATE);
+
+       r_t->ptr_client_site_name = (client_site_name != NULL);
+       init_unistr2(&r_t->uni_client_site_name, client_site_name,
+                    UNI_STR_TERMINATE);
+}
+
+/*******************************************************************
+ Reads or writes an NET_R_DSR_GETDCNAME structure.
+********************************************************************/
+
+BOOL net_io_r_dsr_getdcname(const char *desc, NET_R_DSR_GETDCNAME *r_t,
+                           prs_struct *ps, int depth)
+{
+       uint32 info_ptr = 1;
+
+       if (r_t == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "net_io_r_dsr_getdcname");
+       depth++;
+
+       /* The reply contains *just* an info struct, this is the ptr to it */
+       if (!prs_uint32("info_ptr", ps, depth, &info_ptr))
+               return False;
+
+       if (info_ptr == 0)
+               return False;
+
+       if (!prs_uint32("ptr_dc_unc", ps, depth, &r_t->ptr_dc_unc))
+               return False;
+
+       if (!prs_uint32("ptr_dc_address", ps, depth, &r_t->ptr_dc_address))
+               return False;
+
+       if (!prs_uint32("dc_address_type", ps, depth, &r_t->dc_address_type))
+               return False;
+
+       if (!smb_io_uuid("domain_guid", &r_t->domain_guid, ps, depth))
+               return False;
+
+       if (!prs_uint32("ptr_domain_name", ps, depth, &r_t->ptr_domain_name))
+               return False;
+
+       if (!prs_uint32("ptr_forest_name", ps, depth, &r_t->ptr_forest_name))
+               return False;
+
+       if (!prs_uint32("dc_flags", ps, depth, &r_t->dc_flags))
+               return False;
+
+       if (!prs_uint32("ptr_dc_site_name", ps, depth, &r_t->ptr_dc_site_name))
+               return False;
+
+       if (!prs_uint32("ptr_client_site_name", ps, depth,
+                       &r_t->ptr_client_site_name))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("dc_unc", &r_t->uni_dc_unc,
+                           r_t->ptr_dc_unc, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("dc_address", &r_t->uni_dc_address,
+                           r_t->ptr_dc_address, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("domain_name", &r_t->uni_domain_name,
+                           r_t->ptr_domain_name, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("forest_name", &r_t->uni_forest_name,
+                           r_t->ptr_forest_name, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("dc_site_name", &r_t->uni_dc_site_name,
+                           r_t->ptr_dc_site_name, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!smb_io_unistr2("client_site_name", &r_t->uni_client_site_name,
+                           r_t->ptr_client_site_name, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_werror("result", ps, depth, &r_t->result))
+               return False;
+
+       return True;
+}
index d8f5a75b54e21972e0e700afcdbcf63ee6c93a28..20f11bc3c93b859a3459ea457797fa739cfdb24e 100644 (file)
@@ -70,6 +70,35 @@ static NTSTATUS cmd_netlogon_getdcname(struct rpc_pipe_client *cli,
        return result;
 }
 
+static WERROR cmd_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
+                                        TALLOC_CTX *mem_ctx, int argc,
+                                        const char **argv)
+{
+       WERROR result;
+       char *dcname, *dcaddress;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: %s domainname\n", argv[0]);
+               return WERR_OK;
+       }
+
+       result = rpccli_netlogon_dsr_getdcname(
+               cli, mem_ctx, cli->cli->desthost, argv[1], NULL, NULL,
+               0x40000000, &dcname, &dcaddress, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL);
+
+       if (W_ERROR_IS_OK(result)) {
+               printf("Domain %s's DC is called %s at IP %s\n",
+                      argv[1], dcname, dcaddress);
+               return WERR_OK;
+       }
+
+       printf("rpccli_netlogon_dsr_getdcname returned %s\n",
+              nt_errstr(werror_to_ntstatus(result)));
+
+       return result;
+}
+
 static NTSTATUS cmd_netlogon_logon_ctrl(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx, int argc, 
                                         const char **argv)
@@ -317,6 +346,7 @@ struct cmd_set netlogon_commands[] = {
 
        { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, NULL, "Logon Control 2",     "" },
        { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, NULL, "Get trusted DC name",     "" },
+       { "dsr_getdcname", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getdcname, PI_NETLOGON, NULL, "Get trusted DC name",     "" },
        { "logonctrl",  RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl,  NULL, PI_NETLOGON, NULL, "Logon Control",       "" },
        { "samsync",    RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync,    NULL, PI_NETLOGON, NULL, "Sam Synchronisation", "" },
        { "samdeltas",  RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas,  NULL, PI_NETLOGON, NULL, "Query Sam Deltas",    "" },