summaryrefslogtreecommitdiff
path: root/source4/rpcclient
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-08-13 01:53:07 +0000
committerAndrew Tridgell <tridge@samba.org>2003-08-13 01:53:07 +0000
commitef2e26c91b80556af033d3335e55f5dfa6fff31d (patch)
treefaa21bfd7e7b5247250b47c7891dc1a5ebee6be9 /source4/rpcclient
downloadsamba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.tar.gz
samba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.tar.bz2
samba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.zip
first public release of samba4 code
(This used to be commit b0510b5428b3461aeb9bbe3cc95f62fc73e2b97f)
Diffstat (limited to 'source4/rpcclient')
-rw-r--r--source4/rpcclient/cmd_dfs.c237
-rw-r--r--source4/rpcclient/cmd_ds.c59
-rw-r--r--source4/rpcclient/cmd_lsarpc.c760
-rw-r--r--source4/rpcclient/cmd_netlogon.c342
-rw-r--r--source4/rpcclient/cmd_reg.c1007
-rw-r--r--source4/rpcclient/cmd_samr.c1517
-rw-r--r--source4/rpcclient/cmd_spoolss.c2297
-rw-r--r--source4/rpcclient/cmd_srvsvc.c361
-rw-r--r--source4/rpcclient/cmd_wkssvc.c84
-rw-r--r--source4/rpcclient/display_sec.c144
-rw-r--r--source4/rpcclient/rpcclient.c756
-rw-r--r--source4/rpcclient/rpcclient.h34
12 files changed, 7598 insertions, 0 deletions
diff --git a/source4/rpcclient/cmd_dfs.c b/source4/rpcclient/cmd_dfs.c
new file mode 100644
index 0000000000..715174c824
--- /dev/null
+++ b/source4/rpcclient/cmd_dfs.c
@@ -0,0 +1,237 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/* Check DFS is supported by the remote server */
+
+static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ BOOL dfs_exists;
+ NTSTATUS result;
+
+ if (argc != 1) {
+ printf("Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_dfs_exist(cli, mem_ctx, &dfs_exists);
+
+ if (NT_STATUS_IS_OK(result))
+ printf("dfs is %spresent\n", dfs_exists ? "" : "not ");
+
+ return result;
+}
+
+static NTSTATUS cmd_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ const char *entrypath, *servername, *sharename, *comment;
+ uint32 flags = 0;
+
+ if (argc != 5) {
+ printf("Usage: %s entrypath servername sharename comment\n",
+ argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ entrypath = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+ comment = argv[4];
+
+ result = cli_dfs_add(cli, mem_ctx, entrypath, servername,
+ sharename, comment, flags);
+
+ return result;
+}
+
+static NTSTATUS cmd_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ const char *entrypath, *servername, *sharename;
+
+ if (argc != 4) {
+ printf("Usage: %s entrypath servername sharename\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ entrypath = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+
+ result = cli_dfs_remove(cli, mem_ctx, entrypath, servername,
+ sharename);
+
+ return result;
+}
+
+/* Display a DFS_INFO_1 structure */
+
+static void display_dfs_info_1(DFS_INFO_1 *info1)
+{
+ fstring temp;
+
+ unistr2_to_ascii(temp, &info1->entrypath, sizeof(temp) - 1);
+ printf("entrypath: %s\n", temp);
+}
+
+/* Display a DFS_INFO_2 structure */
+
+static void display_dfs_info_2(DFS_INFO_2 *info2)
+{
+ fstring temp;
+
+ unistr2_to_ascii(temp, &info2->entrypath, sizeof(temp) - 1);
+ printf("entrypath: %s\n", temp);
+
+ unistr2_to_ascii(temp, &info2->comment, sizeof(temp) - 1);
+ printf("\tcomment: %s\n", temp);
+
+ printf("\tstate: %d\n", info2->state);
+ printf("\tnum_storages: %d\n", info2->num_storages);
+}
+
+/* Display a DFS_INFO_3 structure */
+
+static void display_dfs_info_3(DFS_INFO_3 *info3)
+{
+ fstring temp;
+ int i;
+
+ unistr2_to_ascii(temp, &info3->entrypath, sizeof(temp) - 1);
+ printf("entrypath: %s\n", temp);
+
+ unistr2_to_ascii(temp, &info3->comment, sizeof(temp) - 1);
+ printf("\tcomment: %s\n", temp);
+
+ printf("\tstate: %d\n", info3->state);
+ printf("\tnum_storages: %d\n", info3->num_storages);
+
+ for (i = 0; i < info3->num_storages; i++) {
+ DFS_STORAGE_INFO *dsi = &info3->storages[i];
+
+ unistr2_to_ascii(temp, &dsi->servername, sizeof(temp) - 1);
+ printf("\t\tstorage[%d] servername: %s\n", i, temp);
+
+ unistr2_to_ascii(temp, &dsi->sharename, sizeof(temp) - 1);
+ printf("\t\tstorage[%d] sharename: %s\n", i, temp);
+ }
+}
+
+/* Display a DFS_INFO_CTR structure */
+
+static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
+{
+ int i;
+
+ for (i = 0; i < ctr->num_entries; i++) {
+ switch (ctr->switch_value) {
+ case 0x01:
+ display_dfs_info_1(&ctr->dfs.info1[i]);
+ break;
+ case 0x02:
+ display_dfs_info_2(&ctr->dfs.info2[i]);
+ break;
+ case 0x03:
+ display_dfs_info_3(&ctr->dfs.info3[i]);
+ break;
+ default:
+ printf("unsupported info level %d\n",
+ ctr->switch_value);
+ break;
+ }
+ }
+}
+
+/* Enumerate dfs shares */
+
+static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ DFS_INFO_CTR ctr;
+ NTSTATUS result;
+ uint32 info_level = 1;
+
+ if (argc > 2) {
+ printf("Usage: %s [info_level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ result = cli_dfs_enum(cli, mem_ctx, info_level, &ctr);
+
+ if (NT_STATUS_IS_OK(result))
+ display_dfs_info_ctr(&ctr);
+
+ return result;
+}
+
+static NTSTATUS cmd_dfs_getinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ const char *entrypath, *servername, *sharename;
+ uint32 info_level = 1;
+ DFS_INFO_CTR ctr;
+
+ if (argc < 4 || argc > 5) {
+ printf("Usage: %s entrypath servername sharename "
+ "[info_level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ entrypath = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+
+ if (argc == 5)
+ info_level = atoi(argv[4]);
+
+ result = cli_dfs_get_info(cli, mem_ctx, entrypath, servername,
+ sharename, info_level, &ctr);
+
+ if (NT_STATUS_IS_OK(result))
+ display_dfs_info_ctr(&ctr);
+
+ return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set dfs_commands[] = {
+
+ { "DFS" },
+
+ { "dfsexist", cmd_dfs_exist, PI_NETDFS, "Query DFS support", "" },
+ { "dfsadd", cmd_dfs_add, PI_NETDFS, "Add a DFS share", "" },
+ { "dfsremove", cmd_dfs_remove, PI_NETDFS, "Remove a DFS share", "" },
+ { "dfsgetinfo", cmd_dfs_getinfo, PI_NETDFS, "Query DFS share info", "" },
+ { "dfsenum", cmd_dfs_enum, PI_NETDFS, "Enumerate dfs shares", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_ds.c b/source4/rpcclient/cmd_ds.c
new file mode 100644
index 0000000000..9de6d6a9ec
--- /dev/null
+++ b/source4/rpcclient/cmd_ds.c
@@ -0,0 +1,59 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Gerald Carter 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/* Look up domain related information on a remote host */
+
+static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result;
+ DS_DOMINFO_CTR ctr;
+
+ result = cli_ds_getprimarydominfo( cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr );
+ if ( NT_STATUS_IS_OK(result) )
+ {
+ printf ("Machine Role = [%d]\n", ctr.basic->machine_role);
+
+ if ( ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING ) {
+ printf( "Directory Service is running.\n");
+ printf( "Domain is in %s mode.\n", (ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ? "mixed" : "native" );
+ }
+ else
+ printf( "Directory Service not running on server\n");
+ }
+
+ return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set ds_commands[] = {
+
+ { "LSARPC-DS" },
+
+ { "dsroledominfo", cmd_ds_dsrole_getprimarydominfo, PI_LSARPC_DS, "Get Primary Domain Information", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_lsarpc.c b/source4/rpcclient/cmd_lsarpc.c
new file mode 100644
index 0000000000..fab6a89ed5
--- /dev/null
+++ b/source4/rpcclient/cmd_lsarpc.c
@@ -0,0 +1,760 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+
+/* useful function to allow entering a name instead of a SID and
+ * looking it up automatically */
+static NTSTATUS name_to_sid(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ DOM_SID *sid, const char *name)
+{
+ POLICY_HND pol;
+ uint32 *sid_types;
+ NTSTATUS result;
+ DOM_SID *sids;
+
+ /* maybe its a raw SID */
+ if (strncmp(name, "S-", 2) == 0 &&
+ string_to_sid(sid, name)) {
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ cli_lsa_close(cli, mem_ctx, &pol);
+
+ *sid = sids[0];
+
+done:
+ return result;
+}
+
+
+/* Look up domain related information on a remote host */
+
+static NTSTATUS cmd_lsa_query_info_policy(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;
+ GUID dom_guid;
+ fstring sid_str, domain_name="", dns_name="", forest_name="";
+ uint32 info_class = 3;
+
+ if (argc > 2) {
+ printf("Usage: %s [info_class]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_class = atoi(argv[1]);
+
+ /* Lookup info policy */
+ switch (info_class) {
+ case 12:
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+ result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol,
+ info_class, domain_name,
+ dns_name, forest_name,
+ &dom_guid, &dom_sid);
+ break;
+ default:
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+ result = cli_lsa_query_info_policy(cli, mem_ctx, &pol,
+ info_class, domain_name,
+ &dom_sid);
+ }
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ sid_to_string(sid_str, &dom_sid);
+
+ if (domain_name[0])
+ printf("domain %s has sid %s\n", domain_name, sid_str);
+ else
+ printf("could not query info for level %d\n", info_class);
+
+ if (dns_name[0])
+ printf("domain dns name is %s\n", dns_name);
+ if (forest_name[0])
+ printf("forest name is %s\n", forest_name);
+
+ if (info_class == 12) {
+ printf("domain GUID is ");
+ print_guid(&dom_guid);
+ }
+ done:
+ return result;
+}
+
+/* Resolve a list of names to a list of sids */
+
+static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ uint32 *types;
+ int i;
+
+ if (argc == 1) {
+ printf("Usage: %s [name1 [name2 [...]]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1,
+ (const char**)(argv + 1), &sids, &types);
+
+ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
+ NT_STATUS_V(STATUS_SOME_UNMAPPED))
+ goto done;
+
+ result = NT_STATUS_OK;
+
+ /* Print results */
+
+ for (i = 0; i < (argc - 1); i++) {
+ fstring sid_str;
+ sid_to_string(sid_str, &sids[i]);
+ printf("%s %s (%s: %d)\n", argv[i + 1], sid_str,
+ sid_type_lookup(types[i]), types[i]);
+ }
+
+ done:
+ return result;
+}
+
+/* Resolve a list of SIDs to a list of names */
+
+static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ char **domains;
+ char **names;
+ uint32 *types;
+ int i;
+
+ if (argc == 1) {
+ printf("Usage: %s [sid1 [sid2 [...]]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Convert arguments to sids */
+
+ sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * (argc - 1));
+
+ if (!sids) {
+ printf("could not allocate memory for %d sids\n", argc - 1);
+ goto done;
+ }
+
+ for (i = 0; i < argc - 1; i++)
+ if (!string_to_sid(&sids[i], argv[i + 1])) {
+ result = NT_STATUS_INVALID_SID;
+ goto done;
+ }
+
+ /* Lookup the SIDs */
+
+ result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, argc - 1, sids,
+ &domains, &names, &types);
+
+ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
+ NT_STATUS_V(STATUS_SOME_UNMAPPED))
+ goto done;
+
+ result = NT_STATUS_OK;
+
+ /* Print results */
+
+ for (i = 0; i < (argc - 1); i++) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &sids[i]);
+ printf("%s %s\\%s (%d)\n", sid_str,
+ domains[i] ? domains[i] : "*unknown*",
+ names[i] ? names[i] : "*unknown*", types[i]);
+ }
+
+ done:
+ return result;
+}
+
+/* Enumerate list of trusted domains */
+
+static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *domain_sids;
+ char **domain_names;
+
+ /* defaults, but may be changed using params */
+ uint32 enum_ctx = 0;
+ uint32 num_domains = 0;
+ int i;
+
+ if (argc > 2) {
+ printf("Usage: %s [enum context (0)]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2 && argv[1]) {
+ enum_ctx = atoi(argv[2]);
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ POLICY_VIEW_LOCAL_INFORMATION,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Lookup list of trusted domains */
+
+ result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
+ &num_domains,
+ &domain_names, &domain_sids);
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
+ goto done;
+
+ /* Print results: list of names and sids returned in this response. */
+ for (i = 0; i < num_domains; i++) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &domain_sids[i]);
+ printf("%s %s\n", domain_names[i] ? domain_names[i] :
+ "*unknown*", sid_str);
+ }
+
+ done:
+ return result;
+}
+
+/* Enumerates privileges */
+
+static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ uint32 enum_context=0;
+ uint32 pref_max_length=0x1000;
+ uint32 count=0;
+ char **privs_name;
+ uint32 *privs_high;
+ uint32 *privs_low;
+ int i;
+
+ if (argc > 3) {
+ printf("Usage: %s [enum context] [max length]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc>=2)
+ enum_context=atoi(argv[1]);
+
+ if (argc==3)
+ pref_max_length=atoi(argv[2]);
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_enum_privilege(cli, mem_ctx, &pol, &enum_context, pref_max_length,
+ &count, &privs_name, &privs_high, &privs_low);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d privileges\n\n", count);
+
+ for (i = 0; i < count; i++) {
+ printf("%s \t\t%d:%d (0x%x:0x%x)\n", privs_name[i] ? privs_name[i] : "*unknown*",
+ privs_high[i], privs_low[i], privs_high[i], privs_low[i]);
+ }
+
+ done:
+ return result;
+}
+
+/* Get privilege name */
+
+static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ uint16 lang_id=0;
+ uint16 lang_id_sys=0;
+ uint16 lang_id_desc;
+ fstring description;
+
+ if (argc != 2) {
+ printf("Usage: %s privilege name\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_get_dispname(cli, mem_ctx, &pol, argv[1], lang_id, lang_id_sys, description, &lang_id_desc);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("%s -> %s (language: 0x%x)\n", argv[1], description, lang_id_desc);
+
+ done:
+ return result;
+}
+
+/* Enumerate the LSA SIDS */
+
+static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ uint32 enum_context=0;
+ uint32 pref_max_length=0x1000;
+ DOM_SID *sids;
+ uint32 count=0;
+ int i;
+
+ if (argc > 3) {
+ printf("Usage: %s [enum context] [max length]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc>=2)
+ enum_context=atoi(argv[1]);
+
+ if (argc==3)
+ pref_max_length=atoi(argv[2]);
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_enum_sids(cli, mem_ctx, &pol, &enum_context, pref_max_length,
+ &count, &sids);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d SIDs\n\n", count);
+
+ for (i = 0; i < count; i++) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &sids[i]);
+ printf("%s\n", sid_str);
+ }
+
+ done:
+ return result;
+}
+
+/* Enumerate the privileges of an SID */
+
+static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ POLICY_HND user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 access_desired = 0x000f000f;
+
+ DOM_SID sid;
+ uint32 count=0;
+ LUID_ATTR *set;
+ int i;
+
+ if (argc != 2 ) {
+ printf("Usage: %s SID\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = name_to_sid(cli, mem_ctx, &sid, argv[1]);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_open_account(cli, mem_ctx, &dom_pol, &sid, access_desired, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_enum_privsaccount(cli, mem_ctx, &user_pol, &count, &set);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d privileges for SID %s\n\n", count, argv[1]);
+ printf("high\tlow\tattribute\n");
+
+ for (i = 0; i < count; i++) {
+ printf("%u\t%u\t%u\n", set[i].luid.high, set[i].luid.low, set[i].attr);
+ }
+
+ done:
+ return result;
+}
+
+
+/* Enumerate the privileges of an SID via LsaEnumerateAccountRights */
+
+static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DOM_SID sid;
+ uint32 count;
+ char **rights;
+
+ int i;
+
+ if (argc != 2 ) {
+ printf("Usage: %s SID\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = name_to_sid(cli, mem_ctx, &sid, argv[1]);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, sid, &count, &rights);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("found %d privileges for SID %s\n", count, sid_string_static(&sid));
+
+ for (i = 0; i < count; i++) {
+ printf("\t%s\n", rights[i]);
+ }
+
+ done:
+ return result;
+}
+
+
+/* Enumerate the accounts with a specific right */
+
+static NTSTATUS cmd_lsa_enum_acct_with_right(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ uint32 count;
+ const char *right;
+
+ int i;
+
+ if (argc != 2 ) {
+ printf("Usage: %s <RIGHT>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ right = argv[1];
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_enum_account_with_right(cli, mem_ctx, &dom_pol, right, &count, &sids);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("found %d SIDs for '%s'\n", count, right);
+
+ for (i = 0; i < count; i++) {
+ printf("\t%s\n", sid_string_static(&sids[i]));
+ }
+
+ done:
+ return result;
+}
+
+
+/* add some privileges to a SID via LsaAddAccountRights */
+
+static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DOM_SID sid;
+
+ if (argc < 3 ) {
+ printf("Usage: %s SID [rights...]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = name_to_sid(cli, mem_ctx, &sid, argv[1]);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid,
+ argc-2, argv+2);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+
+/* remove some privileges to a SID via LsaRemoveAccountRights */
+
+static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DOM_SID sid;
+
+ if (argc < 3 ) {
+ printf("Usage: %s SID [rights...]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = name_to_sid(cli, mem_ctx, &sid, argv[1]);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid,
+ False, argc-2, argv+2);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+
+/* Get a privilege value given its name */
+
+static NTSTATUS cmd_lsa_lookupprivvalue(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ LUID luid;
+
+ if (argc != 2 ) {
+ printf("Usage: %s name\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_lookupprivvalue(cli, mem_ctx, &pol, argv[1], &luid);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+
+ printf("%u:%u (0x%x:0x%x)\n", luid.high, luid.low, luid.high, luid.low);
+
+ done:
+ return result;
+}
+
+/* Query LSA security object */
+
+static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ SEC_DESC_BUF *sdb;
+ uint32 sec_info = 0x00000004; /* ??? */
+
+ if (argc != 1 ) {
+ printf("Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_query_secobj(cli, mem_ctx, &pol, sec_info, &sdb);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+
+ display_sec_desc(sdb->sec);
+
+ done:
+ return result;
+}
+
+
+/* List of commands exported by this module */
+
+struct cmd_set lsarpc_commands[] = {
+
+ { "LSARPC" },
+
+ { "lsaquery", cmd_lsa_query_info_policy, PI_LSARPC, "Query info policy", "" },
+ { "lookupsids", cmd_lsa_lookup_sids, PI_LSARPC, "Convert SIDs to names", "" },
+ { "lookupnames", cmd_lsa_lookup_names, PI_LSARPC, "Convert names to SIDs", "" },
+ { "enumtrust", cmd_lsa_enum_trust_dom, PI_LSARPC, "Enumerate trusted domains", "Usage: [preferred max number] [enum context (0)]" },
+ { "enumprivs", cmd_lsa_enum_privilege, PI_LSARPC, "Enumerate privileges", "" },
+ { "getdispname", cmd_lsa_get_dispname, PI_LSARPC, "Get the privilege name", "" },
+ { "lsaenumsid", cmd_lsa_enum_sids, PI_LSARPC, "Enumerate the LSA SIDS", "" },
+ { "lsaenumprivsaccount", cmd_lsa_enum_privsaccounts, PI_LSARPC, "Enumerate the privileges of an SID", "" },
+ { "lsaenumacctrights", cmd_lsa_enum_acct_rights, PI_LSARPC, "Enumerate the rights of an SID", "" },
+ { "lsaenumacctwithright",cmd_lsa_enum_acct_with_right,PI_LSARPC,"Enumerate accounts with a right", "" },
+ { "lsaaddacctrights", cmd_lsa_add_acct_rights, PI_LSARPC, "Add rights to an account", "" },
+ { "lsaremoveacctrights", cmd_lsa_remove_acct_rights, PI_LSARPC, "Remove rights from an account", "" },
+ { "lsalookupprivvalue", cmd_lsa_lookupprivvalue, PI_LSARPC, "Get a privilege value given its name", "" },
+ { "lsaquerysecobj", cmd_lsa_query_secobj, PI_LSARPC, "Query LSA security object", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_netlogon.c b/source4/rpcclient/cmd_netlogon.c
new file mode 100644
index 0000000000..407bff3735
--- /dev/null
+++ b/source4/rpcclient/cmd_netlogon.c
@@ -0,0 +1,342 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ uint32 query_level = 1;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (argc > 1) {
+ fprintf(stderr, "Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_netlogon_logon_ctrl2(cli, mem_ctx, query_level);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ done:
+ return result;
+}
+
+static NTSTATUS cmd_netlogon_logon_ctrl(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+#if 0
+ uint32 query_level = 1;
+#endif
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (argc > 1) {
+ fprintf(stderr, "Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+#if 0
+ result = cli_netlogon_logon_ctrl(cli, mem_ctx, query_level);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+#endif
+
+ /* Display results */
+
+ return result;
+}
+
+/* Display sam synchronisation information */
+
+static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas,
+ SAM_DELTA_CTR *deltas)
+{
+ fstring name;
+ uint32 i, j;
+
+ for (i = 0; i < num_deltas; i++) {
+ switch (hdr_deltas[i].type) {
+ case SAM_DELTA_DOMAIN_INFO:
+ unistr2_to_ascii(name,
+ &deltas[i].domain_info.uni_dom_name,
+ sizeof(name) - 1);
+ printf("Domain: %s\n", name);
+ break;
+ case SAM_DELTA_GROUP_INFO:
+ unistr2_to_ascii(name,
+ &deltas[i].group_info.uni_grp_name,
+ sizeof(name) - 1);
+ printf("Group: %s\n", name);
+ break;
+ case SAM_DELTA_ACCOUNT_INFO:
+ unistr2_to_ascii(name,
+ &deltas[i].account_info.uni_acct_name,
+ sizeof(name) - 1);
+ printf("Account: %s\n", name);
+ break;
+ case SAM_DELTA_ALIAS_INFO:
+ unistr2_to_ascii(name,
+ &deltas[i].alias_info.uni_als_name,
+ sizeof(name) - 1);
+ printf("Alias: %s\n", name);
+ break;
+ case SAM_DELTA_ALIAS_MEM: {
+ SAM_ALIAS_MEM_INFO *alias = &deltas[i].als_mem_info;
+
+ for (j = 0; j < alias->num_members; j++) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &alias->sids[j].sid);
+
+ printf("%s\n", sid_str);
+ }
+ break;
+ }
+ case SAM_DELTA_GROUP_MEM: {
+ SAM_GROUP_MEM_INFO *group = &deltas[i].grp_mem_info;
+
+ for (j = 0; j < group->num_members; j++)
+ printf("rid 0x%x, attrib 0x%08x\n",
+ group->rids[j], group->attribs[j]);
+ break;
+ }
+ case SAM_DELTA_MODIFIED_COUNT: {
+ SAM_DELTA_MOD_COUNT *mc = &deltas[i].mod_count;
+
+ printf("sam sequence update: 0x%04x\n", mc->seqnum);
+ break;
+ }
+ default:
+ printf("unknown delta type 0x%02x\n",
+ hdr_deltas[i].type);
+ break;
+ }
+ }
+}
+
+/* Perform sam synchronisation */
+
+static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ unsigned char trust_passwd[16];
+ uint32 database_id = 0, num_deltas;
+ SAM_DELTA_HDR *hdr_deltas;
+ SAM_DELTA_CTR *deltas;
+ DOM_CRED ret_creds;
+ uint32 neg_flags = 0x000001ff;
+
+ if (argc > 2) {
+ fprintf(stderr, "Usage: %s [database_id]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ database_id = atoi(argv[1]);
+
+ if (!secrets_init()) {
+ fprintf(stderr, "Unable to initialise secrets database\n");
+ return result;
+ }
+
+ /* Initialise session credentials */
+
+ if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd,
+ NULL)) {
+ fprintf(stderr, "could not fetch trust account password\n");
+ goto done;
+ }
+
+ result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "Error initialising session creds\n");
+ goto done;
+ }
+
+ /* on first call the returnAuthenticator is empty */
+ memset(&ret_creds, 0, sizeof(ret_creds));
+
+ /* Synchronise sam database */
+
+ result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, database_id,
+ 0, &num_deltas, &hdr_deltas, &deltas);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ display_sam_sync(num_deltas, hdr_deltas, deltas);
+
+ done:
+ return result;
+}
+
+/* Perform sam delta synchronisation */
+
+static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ unsigned char trust_passwd[16];
+ uint32 database_id, num_deltas, tmp;
+ SAM_DELTA_HDR *hdr_deltas;
+ SAM_DELTA_CTR *deltas;
+ UINT64_S seqnum;
+ uint32 neg_flags = 0x000001ff;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ database_id = atoi(argv[1]);
+ tmp = atoi(argv[2]);
+
+ seqnum.low = tmp & 0xffff;
+ seqnum.high = 0;
+
+ if (!secrets_init()) {
+ fprintf(stderr, "Unable to initialise secrets database\n");
+ goto done;
+ }
+
+ /* Initialise session credentials */
+
+ if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd,
+ NULL)) {
+ fprintf(stderr, "could not fetch trust account password\n");
+ goto done;
+ }
+
+ result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "Error initialising session creds\n");
+ goto done;
+ }
+
+ /* Synchronise sam database */
+
+ result = cli_netlogon_sam_deltas(cli, mem_ctx, database_id,
+ seqnum, &num_deltas,
+ &hdr_deltas, &deltas);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ display_sam_sync(num_deltas, hdr_deltas, deltas);
+
+ done:
+ return result;
+}
+
+/* Log on a domain user */
+
+static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ unsigned char trust_passwd[16];
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ int logon_type = NET_LOGON_TYPE;
+ const char *username, *password;
+ uint32 neg_flags = 0x000001ff;
+ int auth_level = 2;
+
+ /* Check arguments */
+
+ if (argc < 3 || argc > 6) {
+ fprintf(stderr, "Usage: samlogon <username> <password> "
+ "[logon_type] [neg flags] [auth level (2 or 3)]\n"
+ "neg flags being 0x000001ff or 0x6007ffff\n");
+ return NT_STATUS_OK;
+ }
+
+ username = argv[1];
+ password = argv[2];
+
+ if (argc == 4)
+ sscanf(argv[3], "%i", &logon_type);
+
+ if (argc == 5)
+ sscanf(argv[4], "%i", &neg_flags);
+
+ if (argc == 6)
+ sscanf(argv[5], "%i", &auth_level);
+
+ /* Authenticate ourselves with the domain controller */
+
+ if (!secrets_init()) {
+ fprintf(stderr, "Unable to initialise secrets database\n");
+ return result;
+ }
+
+ if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL)) {
+ fprintf(stderr, "could not fetch trust account password\n");
+ goto done;
+ }
+
+ result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, auth_level);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "Error initialising session creds\n");
+ goto done;
+ }
+
+ /* Perform the sam logon */
+
+ result = cli_netlogon_sam_logon(cli, mem_ctx, username, password, logon_type);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set netlogon_commands[] = {
+
+ { "NETLOGON" },
+
+ { "logonctrl2", cmd_netlogon_logon_ctrl2, PI_NETLOGON, "Logon Control 2", "" },
+ { "logonctrl", cmd_netlogon_logon_ctrl, PI_NETLOGON, "Logon Control", "" },
+ { "samsync", cmd_netlogon_sam_sync, PI_NETLOGON, "Sam Synchronisation", "" },
+ { "samdeltas", cmd_netlogon_sam_deltas, PI_NETLOGON, "Query Sam Deltas", "" },
+ { "samlogon", cmd_netlogon_sam_logon, PI_NETLOGON, "Sam Logon", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_reg.c b/source4/rpcclient/cmd_reg.c
new file mode 100644
index 0000000000..19c0e7f71f
--- /dev/null
+++ b/source4/rpcclient/cmd_reg.c
@@ -0,0 +1,1007 @@
+/*
+ Unix SMB/CIFS implementation.
+ NT Domain Authentication SMB / MSRPC client
+ Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+ Copyright (C) Simo Sorce 2001
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/*
+ * keys. of the form:
+ * ----
+ *
+ * [HKLM]|[HKU]\[parent_keyname_components]\[subkey]|[value]
+ *
+ * reg_getsubkey() splits this down into:
+ * [HKLM]|[HKU]\[parent_keyname_components] and [subkey]|[value]
+ *
+ * do_reg_connect() splits the left side down further into:
+ * [HKLM]|[HKU] and [parent_keyname_components].
+ *
+ * HKLM is short for HKEY_LOCAL_MACHINE
+ * HKU is short for HKEY_USERS
+ *
+ * oh, and HKEY stands for "Hive Key".
+ *
+ */
+
+#if 0 /* Simo: reg functions need to be updated to the new cmd interface */
+
+/****************************************************************************
+nt registry enum
+****************************************************************************/
+static void cmd_reg_enum(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res1 = True;
+ BOOL res2 = True;
+ int i;
+
+ POLICY_HND key_pol;
+ fstring full_keyname;
+ fstring key_name;
+
+ /*
+ * query key info
+ */
+
+ fstring key_class;
+ uint32 max_class_len = 0;
+ uint32 num_subkeys;
+ uint32 max_subkeylen;
+ uint32 max_subkeysize;
+ uint32 num_values;
+ uint32 max_valnamelen;
+ uint32 max_valbufsize;
+ uint32 sec_desc;
+ NTTIME mod_time;
+
+ /*
+ * unknown 0x1a request
+ */
+
+ uint32 unk_1a_response;
+
+ DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regenum <key_name>\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*key_name) != 0)
+ {
+ /* open an entry */
+ res1 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+ }
+ else
+ {
+ memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+ }
+
+ res1 = res1 ? do_reg_query_key(smb_cli,
+ &key_pol,
+ key_class, &max_class_len,
+ &num_subkeys, &max_subkeylen, &max_subkeysize,
+ &num_values, &max_valnamelen, &max_valbufsize,
+ &sec_desc, &mod_time) : False;
+
+ if (res1 && num_subkeys > 0)
+ {
+ fprintf(out_hnd,"Subkeys\n");
+ fprintf(out_hnd,"-------\n");
+ }
+
+ for (i = 0; i < num_subkeys; i++)
+ {
+ /*
+ * enumerate key
+ */
+
+ fstring enum_name;
+ uint32 enum_unk1;
+ uint32 enum_unk2;
+ time_t key_mod_time;
+
+ /* unknown 1a it */
+ res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+ &unk_1a_response) : False;
+
+ if (res2 && unk_1a_response != 5)
+ {
+ fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
+ }
+
+ /* enum key */
+ res2 = res2 ? do_reg_enum_key(smb_cli, &key_pol,
+ i, enum_name,
+ &enum_unk1, &enum_unk2,
+ &key_mod_time) : False;
+
+ if (res2)
+ {
+ display_reg_key_info(out_hnd, ACTION_HEADER , enum_name, key_mod_time);
+ display_reg_key_info(out_hnd, ACTION_ENUMERATE, enum_name, key_mod_time);
+ display_reg_key_info(out_hnd, ACTION_FOOTER , enum_name, key_mod_time);
+ }
+
+ }
+
+ if (num_values > 0)
+ {
+ fprintf(out_hnd,"Key Values\n");
+ fprintf(out_hnd,"----------\n");
+ }
+
+ for (i = 0; i < num_values; i++)
+ {
+ /*
+ * enumerate key
+ */
+
+ uint32 val_type;
+ BUFFER2 value;
+ fstring val_name;
+
+ /* unknown 1a it */
+ res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+ &unk_1a_response) : False;
+
+ if (res2 && unk_1a_response != 5)
+ {
+ fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
+ }
+
+ /* enum key */
+ res2 = res2 ? do_reg_enum_val(smb_cli, &key_pol,
+ i, max_valnamelen, max_valbufsize,
+ val_name, &val_type, &value) : False;
+
+ if (res2)
+ {
+ display_reg_value_info(out_hnd, ACTION_HEADER , val_name, val_type, &value);
+ display_reg_value_info(out_hnd, ACTION_ENUMERATE, val_name, val_type, &value);
+ display_reg_value_info(out_hnd, ACTION_FOOTER , val_name, val_type, &value);
+ }
+ }
+
+ /* close the handles */
+ if ((*key_name) != 0)
+ {
+ res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
+ }
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res1 && res2)
+ {
+ DEBUG(5,("cmd_reg_enum: query succeeded\n"));
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_enum: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry query key
+****************************************************************************/
+static void cmd_reg_query_key(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res1 = True;
+
+ POLICY_HND key_pol;
+ fstring full_keyname;
+ fstring key_name;
+
+ /*
+ * query key info
+ */
+
+ fstring key_class;
+ uint32 key_class_len = 0;
+ uint32 num_subkeys;
+ uint32 max_subkeylen;
+ uint32 max_subkeysize;
+ uint32 num_values;
+ uint32 max_valnamelen;
+ uint32 max_valbufsize;
+ uint32 sec_desc;
+ NTTIME mod_time;
+
+ DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regquery key_name\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*key_name) != 0)
+ {
+ /* open an entry */
+ res1 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+ }
+ else
+ {
+ memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+ }
+
+ res1 = res1 ? do_reg_query_key(smb_cli,
+ &key_pol,
+ key_class, &key_class_len,
+ &num_subkeys, &max_subkeylen, &max_subkeysize,
+ &num_values, &max_valnamelen, &max_valbufsize,
+ &sec_desc, &mod_time) : False;
+
+ if (res1 && key_class_len != 0)
+ {
+ res1 = res1 ? do_reg_query_key(smb_cli,
+ &key_pol,
+ key_class, &key_class_len,
+ &num_subkeys, &max_subkeylen, &max_subkeysize,
+ &num_values, &max_valnamelen, &max_valbufsize,
+ &sec_desc, &mod_time) : False;
+ }
+
+ if (res1)
+ {
+ fprintf(out_hnd,"Registry Query Info Key\n");
+ fprintf(out_hnd,"key class: %s\n", key_class);
+ fprintf(out_hnd,"subkeys, max_len, max_size: %d %d %d\n", num_subkeys, max_subkeylen, max_subkeysize);
+ fprintf(out_hnd,"vals, max_len, max_size: 0x%x 0x%x 0x%x\n", num_values, max_valnamelen, max_valbufsize);
+ fprintf(out_hnd,"sec desc: 0x%x\n", sec_desc);
+ fprintf(out_hnd,"mod time: %s\n", http_timestring(nt_time_to_unix(&mod_time)));
+ }
+
+ /* close the handles */
+ if ((*key_name) != 0)
+ {
+ res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
+ }
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res1)
+ {
+ DEBUG(5,("cmd_reg_query: query succeeded\n"));
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_query: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry create value
+****************************************************************************/
+static void cmd_reg_create_val(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND parent_pol;
+ fstring full_keyname;
+ fstring keyname;
+ fstring parent_name;
+ fstring val_name;
+ fstring tmp;
+ uint32 val_type;
+ BUFFER3 value;
+
+#if 0
+ uint32 unk_0;
+ uint32 unk_1;
+ /* query it */
+ res1 = res1 ? do_reg_query_info(smb_cli, &val_pol,
+ val_name, *val_type) : False;
+#endif
+
+ DEBUG(5, ("cmd_reg_create_val: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regcreate <val_name> <val_type> <val>\n");
+ return;
+ }
+
+ reg_get_subkey(full_keyname, keyname, val_name);
+
+ if (keyname[0] == 0 || val_name[0] == 0)
+ {
+ fprintf(out_hnd, "invalid key name\n");
+ return;
+ }
+
+ if (!next_token_nr(NULL, tmp, NULL, sizeof(tmp)))
+ {
+ fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
+ return;
+ }
+
+ val_type = atoi(tmp);
+
+ if (val_type != 1 && val_type != 3 && val_type != 4)
+ {
+ fprintf(out_hnd, "val_type 1=UNISTR, 3=BYTES, 4=DWORD supported\n");
+ return;
+ }
+
+ if (!next_token_nr(NULL, tmp, NULL, sizeof(tmp)))
+ {
+ fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
+ return;
+ }
+
+ switch (val_type)
+ {
+ case 0x01: /* UNISTR */
+ {
+ init_buffer3_str(&value, tmp, strlen(tmp)+1);
+ break;
+ }
+ case 0x03: /* BYTES */
+ {
+ init_buffer3_hex(&value, tmp);
+ break;
+ }
+ case 0x04: /* DWORD */
+ {
+ uint32 tmp_val;
+ if (strnequal(tmp, "0x", 2))
+ {
+ tmp_val = strtol(tmp, (char**)NULL, 16);
+ }
+ else
+ {
+ tmp_val = strtol(tmp, (char**)NULL, 10);
+ }
+ init_buffer3_uint32(&value, tmp_val);
+ break;
+ }
+ default:
+ {
+ fprintf(out_hnd, "i told you i only deal with UNISTR, DWORD and BYTES!\n");
+ return;
+ }
+ }
+
+ DEBUG(10,("key data:\n"));
+ dump_data(10, (char *)value.buffer, value.buf_len);
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, keyname, parent_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*val_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ parent_name, 0x02000000, &parent_pol) : False;
+ }
+ else
+ {
+ memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+ }
+
+ /* create an entry */
+ res4 = res3 ? do_reg_create_val(smb_cli, &parent_pol,
+ val_name, val_type, &value) : False;
+
+ /* flush the modified key */
+ res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+ /* close the val handle */
+ if ((*val_name) != 0)
+ {
+ res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+ }
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_create_val: query succeeded\n"));
+ fprintf(out_hnd,"OK\n");
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_create_val: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry delete value
+****************************************************************************/
+static void cmd_reg_delete_val(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND parent_pol;
+ fstring full_keyname;
+ fstring keyname;
+ fstring parent_name;
+ fstring val_name;
+
+ DEBUG(5, ("cmd_reg_delete_val: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regdelete <val_name>\n");
+ return;
+ }
+
+ reg_get_subkey(full_keyname, keyname, val_name);
+
+ if (keyname[0] == 0 || val_name[0] == 0)
+ {
+ fprintf(out_hnd, "invalid key name\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, keyname, parent_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*val_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ parent_name, 0x02000000, &parent_pol) : False;
+ }
+ else
+ {
+ memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+ }
+
+ /* delete an entry */
+ res4 = res3 ? do_reg_delete_val(smb_cli, &parent_pol, val_name) : False;
+
+ /* flush the modified key */
+ res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+ /* close the key handle */
+ res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_delete_val: query succeeded\n"));
+ fprintf(out_hnd,"OK\n");
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_delete_val: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry delete key
+****************************************************************************/
+static void cmd_reg_delete_key(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND parent_pol;
+ fstring full_keyname;
+ fstring parent_name;
+ fstring key_name;
+ fstring subkey_name;
+
+ DEBUG(5, ("cmd_reg_delete_key: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regdeletekey <key_name>\n");
+ return;
+ }
+
+ reg_get_subkey(full_keyname, parent_name, subkey_name);
+
+ if (parent_name[0] == 0 || subkey_name[0] == 0)
+ {
+ fprintf(out_hnd, "invalid key name\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, parent_name, key_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*key_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &parent_pol) : False;
+ }
+ else
+ {
+ memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+ }
+
+ /* create an entry */
+ res4 = res3 ? do_reg_delete_key(smb_cli, &parent_pol, subkey_name) : False;
+
+ /* flush the modified key */
+ res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+ /* close the key handle */
+ if ((*key_name) != 0)
+ {
+ res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+ }
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_delete_key: query succeeded\n"));
+ fprintf(out_hnd,"OK\n");
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_delete_key: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry create key
+****************************************************************************/
+static void cmd_reg_create_key(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND parent_pol;
+ POLICY_HND key_pol;
+ fstring full_keyname;
+ fstring parent_key;
+ fstring parent_name;
+ fstring key_name;
+ fstring key_class;
+ SEC_ACCESS sam_access;
+
+ DEBUG(5, ("cmd_reg_create_key: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "regcreate <key_name> [key_class]\n");
+ return;
+ }
+
+ reg_get_subkey(full_keyname, parent_key, key_name);
+
+ if (parent_key[0] == 0 || key_name[0] == 0)
+ {
+ fprintf(out_hnd, "invalid key name\n");
+ return;
+ }
+
+ if (!next_token_nr(NULL, key_class, NULL, sizeof(key_class)))
+ {
+ memset(key_class, 0, sizeof(key_class));
+ }
+
+ /* set access permissions */
+ sam_access.mask = SEC_RIGHTS_READ;
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, parent_key, parent_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*parent_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ parent_name, 0x02000000, &parent_pol) : False;
+ }
+ else
+ {
+ memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+ }
+
+ /* create an entry */
+ res4 = res3 ? do_reg_create_key(smb_cli, &parent_pol,
+ key_name, key_class, &sam_access, &key_pol) : False;
+
+ /* flush the modified key */
+ res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+ /* close the key handle */
+ res4 = res4 ? do_reg_close(smb_cli, &key_pol) : False;
+
+ /* close the key handle */
+ if ((*parent_name) != 0)
+ {
+ res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+ }
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_create_key: query succeeded\n"));
+ fprintf(out_hnd,"OK\n");
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_create_key: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry security info
+****************************************************************************/
+static void cmd_reg_test_key_sec(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND key_pol;
+ fstring full_keyname;
+ fstring key_name;
+
+ /*
+ * security info
+ */
+
+ uint32 sec_buf_size;
+ SEC_DESC_BUF *psdb;
+
+ DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "reggetsec <key_name>\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*key_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+ }
+ else
+ {
+ memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+ }
+
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+
+ /* query key sec info. first call sets sec_buf_size. */
+
+ sec_buf_size = 0;
+ res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
+ &sec_buf_size, &psdb) : False;
+
+ free_sec_desc_buf(&psdb);
+
+ res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
+ &sec_buf_size, &psdb) : False;
+
+ if (res4 && psdb->len > 0 && psdb->sec != NULL)
+ {
+ display_sec_desc(out_hnd, ACTION_HEADER , psdb->sec);
+ display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+ display_sec_desc(out_hnd, ACTION_FOOTER , psdb->sec);
+
+ res4 = res4 ? do_reg_set_key_sec(smb_cli, &key_pol, psdb) : False;
+ }
+
+ free_sec_desc_buf(&psdb);
+
+ /* close the key handle */
+ if ((*key_name) != 0)
+ {
+ res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
+ }
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_test2: query succeeded\n"));
+ fprintf(out_hnd,"Registry Test2\n");
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_test2: query failed\n"));
+ }
+}
+
+/****************************************************************************
+nt registry security info
+****************************************************************************/
+static void cmd_reg_get_key_sec(struct client_info *info)
+{
+ BOOL res = True;
+ BOOL res3 = True;
+ BOOL res4 = True;
+
+ POLICY_HND key_pol;
+ fstring full_keyname;
+ fstring key_name;
+
+ /*
+ * security info
+ */
+
+ uint32 sec_buf_size;
+ SEC_DESC_BUF *psdb;
+
+ DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
+
+ if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
+ {
+ fprintf(out_hnd, "reggetsec <key_name>\n");
+ return;
+ }
+
+ /* open WINREG session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False;
+
+ /* open registry receive a policy handle */
+ res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+ &info->dom.reg_pol_connect) : False;
+
+ if ((*key_name) != 0)
+ {
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+ }
+ else
+ {
+ memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+ }
+
+ /* open an entry */
+ res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+ key_name, 0x02000000, &key_pol) : False;
+
+ /* Get the size. */
+ sec_buf_size = 0;
+ res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
+ &sec_buf_size, &psdb) : False;
+
+ free_sec_desc_buf(&psdb);
+
+ res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
+ &sec_buf_size, &psdb) : False;
+
+ if (res4 && psdb->len > 0 && psdb->sec != NULL)
+ {
+ display_sec_desc(out_hnd, ACTION_HEADER , psdb->sec);
+ display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+ display_sec_desc(out_hnd, ACTION_FOOTER , psdb->sec);
+ }
+
+ free_sec_desc_buf(&psdb);
+
+ /* close the key handle */
+ if ((*key_name) != 0)
+ {
+ res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
+ }
+
+ /* close the registry handles */
+ res = res ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res && res3 && res4)
+ {
+ DEBUG(5,("cmd_reg_get_key_sec: query succeeded\n"));
+ }
+ else
+ {
+ DEBUG(5,("cmd_reg_get_key_sec: query failed\n"));
+ }
+}
+
+#endif /* 0 */
+
+/****************************************************************************
+nt registry shutdown
+****************************************************************************/
+static NTSTATUS cmd_reg_shutdown(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ fstring msg;
+ uint32 timeout = 20;
+ BOOL force = False;
+ BOOL reboot = False;
+ int opt;
+
+ *msg = 0;
+ optind = 0; /* TODO: test if this hack works on other systems too --simo */
+
+ while ((opt = getopt(argc, argv, "m:t:rf")) != EOF)
+ {
+ /*fprintf (stderr, "[%s]\n", argv[argc-1]);*/
+
+ switch (opt)
+ {
+ case 'm':
+ safe_strcpy(msg, optarg, sizeof(msg)-1);
+ /*fprintf (stderr, "[%s|%s]\n", optarg, msg);*/
+ break;
+
+ case 't':
+ timeout = atoi(optarg);
+ /*fprintf (stderr, "[%s|%d]\n", optarg, timeout);*/
+ break;
+
+ case 'r':
+ reboot = True;
+ break;
+
+ case 'f':
+ force = True;
+ break;
+
+ }
+ }
+
+ /* create an entry */
+ result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, reboot, force);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("cmd_reg_shutdown: query succeeded\n"));
+ else
+ DEBUG(5,("cmd_reg_shutdown: query failed\n"));
+
+ return result;
+}
+
+/****************************************************************************
+abort a shutdown
+****************************************************************************/
+static NTSTATUS cmd_reg_abort_shutdown(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ result = cli_reg_abort_shutdown(cli, mem_ctx);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
+ else
+ DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
+
+ return result;
+}
+
+
+/* List of commands exported by this module */
+struct cmd_set reg_commands[] = {
+
+ { "REG" },
+
+ { "shutdown", cmd_reg_shutdown, PI_WINREG, "Remote Shutdown",
+ "syntax: shutdown [-m message] [-t timeout] [-r] [-h] [-f] (-r == reboot, -h == halt, -f == force)" },
+
+ { "abortshutdown", cmd_reg_abort_shutdown, PI_WINREG, "Abort Shutdown",
+ "syntax: abortshutdown" },
+/*
+ { "regenum", cmd_reg_enum, "Registry Enumeration",
+ "<keyname>" },
+
+ { "regdeletekey", cmd_reg_delete_key, "Registry Key Delete",
+ "<keyname>" },
+
+ { "regcreatekey", cmd_reg_create_key, "Registry Key Create",
+ "<keyname> [keyclass]" },
+
+ { "regqueryval", cmd_reg_query_info, "Registry Value Query",
+ "<valname>" },
+
+ { "regquerykey", cmd_reg_query_key, "Registry Key Query",
+ "<keyname>" },
+
+ { "regdeleteval", cmd_reg_delete_val, "Registry Value Delete",
+ "<valname>" },
+
+ { "regcreateval", cmd_reg_create_val, "Registry Key Create",
+ "<valname> <valtype> <value>" },
+
+ { "reggetsec", cmd_reg_get_key_sec, "Registry Key Security",
+ "<keyname>" },
+
+ { "regtestsec", cmd_reg_test_key_sec, "Test Registry Key Security",
+ "<keyname>" },
+*/
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_samr.c b/source4/rpcclient/cmd_samr.c
new file mode 100644
index 0000000000..cec6b1680b
--- /dev/null
+++ b/source4/rpcclient/cmd_samr.c
@@ -0,0 +1,1517 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Andrew Tridgell 1992-2000,
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
+ Copyright (C) Elrond 2000,
+ Copyright (C) Tim Potter 2000
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+extern DOM_SID domain_sid;
+
+/****************************************************************************
+ display sam_user_info_21 structure
+ ****************************************************************************/
+static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
+{
+ fstring temp;
+
+ unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
+ printf("\tUser Name :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
+ printf("\tFull Name :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
+ printf("\tHome Drive :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
+ printf("\tDir Drive :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
+ printf("\tProfile Path:\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
+ printf("\tLogon Script:\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
+ printf("\tDescription :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
+ printf("\tWorkstations:\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
+ printf("\tUnknown Str :\t%s\n", temp);
+
+ unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
+ printf("\tRemote Dial :\t%s\n", temp);
+
+ printf("\tLogon Time :\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->logon_time)));
+ printf("\tLogoff Time :\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->logoff_time)));
+ printf("\tKickoff Time :\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->kickoff_time)));
+ printf("\tPassword last set Time :\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
+ printf("\tPassword can change Time :\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
+ printf("\tPassword must change Time:\t%s\n",
+ http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
+
+ printf("\tunknown_2[0..31]...\n"); /* user passwords? */
+
+ printf("\tuser_rid :\t0x%x\n" , usr->user_rid ); /* User ID */
+ printf("\tgroup_rid:\t0x%x\n" , usr->group_rid); /* Group ID */
+ printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */
+
+ printf("\tunknown_3:\t0x%08x\n", usr->unknown_3); /* 0x00ff ffff */
+ printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
+ printf("\tunknown_5:\t0x%08x\n", usr->unknown_5); /* 0x0002 0000 */
+
+ printf("\tpadding1[0..7]...\n");
+
+ if (usr->ptr_logon_hrs) {
+ printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
+ }
+}
+
+static const char *display_time(NTTIME nttime)
+{
+ static fstring string;
+
+ float high;
+ float low;
+ int sec;
+ int days, hours, mins, secs;
+
+ if (nttime.high==0 && nttime.low==0)
+ return "Now";
+
+ if (nttime.high==0x80000000 && nttime.low==0)
+ return "Never";
+
+ high = 65536;
+ high = high/10000;
+ high = high*65536;
+ high = high/1000;
+ high = high * (~nttime.high);
+
+ low = ~nttime.low;
+ low = low/(1000*1000*10);
+
+ sec=high+low;
+
+ days=sec/(60*60*24);
+ hours=(sec - (days*60*60*24)) / (60*60);
+ mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
+ secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
+
+ snprintf(string, sizeof(string)-1, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
+ return (string);
+}
+
+static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
+{
+
+ printf("Minimum password length: %d\n", info1->min_length_password);
+ printf("Password uniqueness (remember x passwords): %d\n", info1->password_history);
+ printf("flag: ");
+ if(info1->flag&&2==2) printf("users must open a session to change password ");
+ printf("\n");
+
+ printf("password expire in: %s\n", display_time(info1->expire));
+ printf("Min password age (allow changing in x days): %s\n", display_time(info1->min_passwordage));
+}
+
+static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1);
+ printf("Domain:\t%s\n", name);
+
+ unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1);
+ printf("Server:\t%s\n", name);
+
+ printf("Total Users:\t%d\n", info2->num_domain_usrs);
+ printf("Total Groups:\t%d\n", info2->num_domain_grps);
+ printf("Total Aliases:\t%d\n", info2->num_local_grps);
+
+ printf("Sequence No:\t%d\n", info2->seq_num);
+
+ printf("Unknown 0:\t0x%x\n", info2->unknown_0);
+ printf("Unknown 1:\t0x%x\n", info2->unknown_1);
+ printf("Unknown 2:\t0x%x\n", info2->unknown_2);
+ printf("Unknown 3:\t0x%x\n", info2->unknown_3);
+ printf("Unknown 4:\t0x%x\n", info2->unknown_4);
+ printf("Unknown 5:\t0x%x\n", info2->unknown_5);
+ printf("Unknown 6:\t0x%x\n", info2->unknown_6);
+}
+
+static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
+{
+ fstring tmp;
+
+ printf("index: 0x%x ", e1->user_idx);
+ printf("RID: 0x%x ", e1->rid_user);
+ printf("acb: 0x%x ", e1->acb_info);
+
+ unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1);
+ printf("Account: %s\t", tmp);
+
+ unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1);
+ printf("Name: %s\t", tmp);
+
+ unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1);
+ printf("Desc: %s\n", tmp);
+}
+
+static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
+{
+ fstring tmp;
+
+ printf("index: 0x%x ", e2->user_idx);
+ printf("RID: 0x%x ", e2->rid_user);
+ printf("acb: 0x%x ", e2->acb_info);
+
+ unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1);
+ printf("Account: %s\t", tmp);
+
+ unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1);
+ printf("Name: %s\n", tmp);
+
+}
+
+static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
+{
+ fstring tmp;
+
+ printf("index: 0x%x ", e3->grp_idx);
+ printf("RID: 0x%x ", e3->rid_grp);
+ printf("attr: 0x%x ", e3->attr);
+
+ unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1);
+ printf("Account: %s\t", tmp);
+
+ unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1);
+ printf("Name: %s\n", tmp);
+
+}
+
+static void display_sam_info_4(SAM_ENTRY4 *e4, SAM_STR4 *s4)
+{
+ int i;
+
+ printf("index: %d ", e4->user_idx);
+
+ printf("Account: ");
+ for (i=0; i<s4->acct_name.str_str_len; i++)
+ printf("%c", s4->acct_name.buffer[i]);
+ printf("\n");
+
+}
+
+static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
+{
+ int i;
+
+ printf("index: 0x%x ", e5->grp_idx);
+
+ printf("Account: ");
+ for (i=0; i<s5->grp_name.str_str_len; i++)
+ printf("%c", s5->grp_name.buffer[i]);
+ printf("\n");
+
+}
+
+/****************************************************************************
+ Try samr_connect4 first, then samr_conenct if it fails
+ ****************************************************************************/
+static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 access_mask, POLICY_HND *connect_pol)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ result = cli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ result = cli_samr_connect(cli, mem_ctx, access_mask,
+ connect_pol);
+ }
+ return result;
+}
+
+/**********************************************************************
+ * Query user information
+ */
+static NTSTATUS cmd_samr_query_user(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 info_level = 21;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ SAM_USERINFO_CTR *user_ctr;
+ fstring server;
+ uint32 user_rid;
+
+ if ((argc < 2) || (argc > 4)) {
+ printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &user_rid);
+
+ if (argc > 2)
+ sscanf(argv[2], "%i", &info_level);
+
+ if (argc > 3)
+ sscanf(argv[3], "%x", &access_mask);
+
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ access_mask,
+ user_rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ ZERO_STRUCT(user_ctr);
+
+ result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol,
+ info_level, &user_ctr);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ display_sam_user_info_21(user_ctr->info.id21);
+
+done:
+ return result;
+}
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info1(GROUP_INFO1 *info1)
+{
+ fstring temp;
+
+ unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
+ printf("\tGroup Name:\t%s\n", temp);
+ unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
+ printf("\tDescription:\t%s\n", temp);
+ printf("\tunk1:%d\n", info1->unknown_1);
+ printf("\tNum Members:%d\n", info1->num_members);
+}
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info4(GROUP_INFO4 *info4)
+{
+ fstring desc;
+
+ unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
+ printf("\tGroup Description:%s\n", desc);
+}
+
+/****************************************************************************
+ display sam sync structure
+ ****************************************************************************/
+static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
+{
+ switch (ctr->switch_value1) {
+ case 1: {
+ display_group_info1(&ctr->group.info1);
+ break;
+ }
+ case 4: {
+ display_group_info4(&ctr->group.info4);
+ break;
+ }
+ }
+}
+
+/***********************************************************************
+ * Query group information
+ */
+static NTSTATUS cmd_samr_query_group(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 info_level = 1;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ GROUP_INFO_CTR *group_ctr;
+ fstring server;
+ uint32 group_rid;
+
+ if ((argc < 2) || (argc > 4)) {
+ printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &group_rid);
+
+ if (argc > 2)
+ sscanf(argv[2], "%i", &info_level);
+
+ if (argc > 3)
+ sscanf(argv[3], "%x", &access_mask);
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+ access_mask,
+ group_rid, &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol,
+ info_level, &group_ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ display_group_info_ctr(group_ctr);
+
+done:
+ return result;
+}
+
+/* Query groups a user is a member of */
+
+static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol,
+ domain_pol,
+ user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 num_groups,
+ user_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ DOM_GID *user_gids;
+ int i;
+ fstring server;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s rid [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &user_rid);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ access_mask,
+ user_rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
+ &num_groups, &user_gids);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < num_groups; i++) {
+ printf("\tgroup rid:[0x%x] attr:[0x%x]\n",
+ user_gids[i].g_rid, user_gids[i].attr);
+ }
+
+ done:
+ return result;
+}
+
+/* Query aliases a user is a member of */
+
+static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 user_rid, num_aliases, *alias_rids;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ int i;
+ fstring server;
+ DOM_SID tmp_sid;
+ DOM_SID2 sid;
+ DOM_SID global_sid_Builtin;
+
+ string_to_sid(&global_sid_Builtin, "S-1-5-32");
+
+ if ((argc < 3) || (argc > 4)) {
+ printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[2], "%i", &user_rid);
+
+ if (argc > 3)
+ sscanf(argv[3], "%x", &access_mask);
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (StrCaseCmp(argv[1], "domain")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &global_sid_Builtin, &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ sid_copy(&tmp_sid, &domain_sid);
+ sid_append_rid(&tmp_sid, user_rid);
+ init_dom_sid2(&sid, &tmp_sid);
+
+ result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < num_aliases; i++) {
+ printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
+ }
+
+ done:
+ return result;
+}
+
+/* Query members of a group */
+
+static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 num_members, *group_rids, *group_attrs, group_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ int i;
+ fstring server;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s rid [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &group_rid);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+ access_mask,
+ group_rid, &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
+ &num_members, &group_rids,
+ &group_attrs);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < num_members; i++) {
+ printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
+ group_attrs[i]);
+ }
+
+ done:
+ return result;
+}
+
+/* Enumerate domain users */
+
+static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx, size, num_dom_users, i;
+ char **dom_users;
+ uint32 *dom_rids;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint16 acb_mask = ACB_NORMAL;
+ BOOL got_connect_pol = False, got_domain_pol = False;
+
+ if ((argc < 1) || (argc > 2)) {
+ printf("Usage: %s [access_mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1)
+ sscanf(argv[1], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_connect_pol = True;
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_domain_pol = True;
+
+ /* Enumerate domain users */
+
+ start_idx = 0;
+ size = 0xffff;
+
+ do {
+ result = cli_samr_enum_dom_users(
+ cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
+ size, &dom_users, &dom_rids, &num_dom_users);
+
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
+
+ for (i = 0; i < num_dom_users; i++)
+ printf("group:[%s] rid:[0x%x]\n",
+ dom_users[i], dom_rids[i]);
+ }
+
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ cli_samr_close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ cli_samr_close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Enumerate domain groups */
+
+static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx, size, num_dom_groups, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ struct acct_info *dom_groups;
+ BOOL got_connect_pol = False, got_domain_pol = False;
+
+ if ((argc < 1) || (argc > 2)) {
+ printf("Usage: %s [access_mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1)
+ sscanf(argv[1], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_connect_pol = True;
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_domain_pol = True;
+
+ /* Enumerate domain groups */
+
+ start_idx = 0;
+ size = 0xffff;
+
+ do {
+ result = cli_samr_enum_dom_groups(
+ cli, mem_ctx, &domain_pol, &start_idx, size,
+ &dom_groups, &num_dom_groups);
+
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
+
+ for (i = 0; i < num_dom_groups; i++)
+ printf("group:[%s] rid:[0x%x]\n",
+ dom_groups[i].acct_name,
+ dom_groups[i].rid);
+ }
+
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ cli_samr_close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ cli_samr_close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Enumerate alias groups */
+
+static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx, size, num_als_groups, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ struct acct_info *als_groups;
+ DOM_SID global_sid_Builtin;
+ BOOL got_connect_pol = False, got_domain_pol = False;
+
+ string_to_sid(&global_sid_Builtin, "S-1-5-32");
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_connect_pol = True;
+
+ /* Get domain policy handle */
+
+ if (StrCaseCmp(argv[1], "domain")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ access_mask,
+ &global_sid_Builtin, &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ got_domain_pol = True;
+
+ /* Enumerate alias groups */
+
+ start_idx = 0;
+ size = 0xffff; /* Number of groups to retrieve */
+
+ do {
+ result = cli_samr_enum_als_groups(
+ cli, mem_ctx, &domain_pol, &start_idx, size,
+ &als_groups, &num_als_groups);
+
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
+
+ for (i = 0; i < num_als_groups; i++)
+ printf("group:[%s] rid:[0x%x]\n",
+ als_groups[i].acct_name,
+ als_groups[i].rid);
+ }
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ cli_samr_close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ cli_samr_close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Query alias membership */
+
+static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, alias_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 alias_rid, num_members, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ DOM_SID *alias_sids;
+ DOM_SID global_sid_Builtin;
+
+ string_to_sid(&global_sid_Builtin, "S-1-5-32");
+
+ if ((argc < 3) || (argc > 4)) {
+ printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[2], "%i", &alias_rid);
+
+ if (argc > 3)
+ sscanf(argv[3], "%x", &access_mask);
+
+ /* Open SAMR handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on domain */
+
+ if (StrCaseCmp(argv[1], "domain")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &global_sid_Builtin, &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on alias */
+
+ result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+ access_mask,
+ alias_rid, &alias_pol);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
+ &num_members, &alias_sids);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < num_members; i++) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &alias_sids[i]);
+ printf("\tsid:[%s]\n", sid_str);
+ }
+
+ done:
+ return result;
+}
+
+/* Query display info */
+
+static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32 info_level = 1;
+ SAM_DISPINFO_CTR ctr;
+ SAM_DISPINFO_1 info1;
+ SAM_DISPINFO_2 info2;
+ SAM_DISPINFO_3 info3;
+ SAM_DISPINFO_4 info4;
+ SAM_DISPINFO_5 info5;
+ int loop_count = 0;
+ BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
+
+ if (argc > 5) {
+ printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc >= 2)
+ sscanf(argv[1], "%i", &info_level);
+
+ if (argc >= 3)
+ sscanf(argv[2], "%i", &start_idx);
+
+ if (argc >= 4) {
+ sscanf(argv[3], "%i", &max_entries);
+ got_params = True;
+ }
+
+ if (argc >= 5) {
+ sscanf(argv[4], "%i", &max_size);
+ got_params = True;
+ }
+
+ if (argc >= 6)
+ sscanf(argv[5], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(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,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Query display info */
+
+ ZERO_STRUCT(ctr);
+ ZERO_STRUCT(info1);
+
+ switch (info_level) {
+ case 1:
+ ZERO_STRUCT(info1);
+ ctr.sam.info1 = &info1;
+ break;
+ case 2:
+ ZERO_STRUCT(info2);
+ ctr.sam.info2 = &info2;
+ break;
+ case 3:
+ ZERO_STRUCT(info3);
+ ctr.sam.info3 = &info3;
+ break;
+ case 4:
+ ZERO_STRUCT(info4);
+ ctr.sam.info4 = &info4;
+ break;
+ case 5:
+ ZERO_STRUCT(info5);
+ ctr.sam.info5 = &info5;
+ break;
+ }
+
+
+ while(1) {
+
+ if (!got_params)
+ get_query_dispinfo_params(
+ loop_count, &max_entries, &max_size);
+
+ result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
+ &start_idx, info_level,
+ &num_entries, max_entries,
+ max_size, &ctr);
+
+ loop_count++;
+
+ if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
+ break;
+
+ if (num_entries == 0)
+ break;
+
+ for (i = 0; i < num_entries; i++) {
+ switch (info_level) {
+ case 1:
+ display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
+ break;
+ case 2:
+ display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
+ break;
+ case 3:
+ display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
+ break;
+ case 4:
+ display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
+ break;
+ case 5:
+ display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
+ break;
+ }
+ }
+ }
+
+ done:
+ return result;
+}
+
+/* Query domain info */
+
+static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 switch_level = 2;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ SAM_UNK_CTR ctr;
+
+ if (argc > 2) {
+ printf("Usage: %s [info level] [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1)
+ sscanf(argv[1], "%i", &switch_level);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(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,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Query domain info */
+
+ result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
+ switch_level, &ctr);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display domain info */
+
+ switch (switch_level) {
+ case 1:
+ display_sam_unk_info_1(&ctr.info.inf1);
+ break;
+ case 2:
+ display_sam_unk_info_2(&ctr.info.inf2);
+ break;
+ default:
+ printf("cannot display domain info for switch value %d\n",
+ switch_level);
+ break;
+ }
+
+ done:
+
+ cli_samr_close(cli, mem_ctx, &domain_pol);
+ cli_samr_close(cli, mem_ctx, &connect_pol);
+ return result;
+}
+
+/* Create domain user */
+
+static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *acct_name;
+ uint16 acb_info;
+ uint32 unknown, user_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s username [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ acct_name = argv[1];
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = try_samr_connects(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,
+ access_mask,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Create domain user */
+
+ acb_info = ACB_NORMAL;
+ unknown = 0xe005000b; /* No idea what this is - a permission mask? */
+
+ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+ acct_name, acb_info, unknown,
+ &user_pol, &user_rid);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+/* Lookup sam names */
+
+static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol;
+ uint32 flags = 0x000003e8; /* Unknown */
+ uint32 num_rids, num_names, *name_types, *rids;
+ const char **names;
+ int i;
+ DOM_SID global_sid_Builtin;
+
+ string_to_sid(&global_sid_Builtin, "S-1-5-32");
+
+ if (argc < 3) {
+ printf("Usage: %s domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
+ printf("check on the domain SID: S-1-5-21-x-y-z\n");
+ printf("or check on the builtin SID: S-1-5-32\n");
+ return NT_STATUS_OK;
+ }
+
+ /* Get sam policy and domain handles */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (StrCaseCmp(argv[1], "domain")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &global_sid_Builtin, &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Look up names */
+
+ num_names = argc - 2;
+ names = (const char **)talloc(mem_ctx, sizeof(char *) * num_names);
+
+ for (i = 0; i < argc - 2; i++)
+ names[i] = argv[i + 2];
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+ flags, num_names, names,
+ &num_rids, &rids, &name_types);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ for (i = 0; i < num_names; i++)
+ printf("name %s: 0x%x (%d)\n", names[i], rids[i],
+ name_types[i]);
+
+ done:
+ return result;
+}
+
+/* Lookup sam rids */
+
+static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol;
+ uint32 flags = 0x000003e8; /* Unknown */
+ uint32 num_rids, num_names, *rids, *name_types;
+ char **names;
+ int i;
+
+ if (argc < 2) {
+ printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get sam policy and domain handles */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Look up rids */
+
+ num_rids = argc - 1;
+ rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
+
+ for (i = 0; i < argc - 1; i++)
+ sscanf(argv[i + 1], "%i", &rids[i]);
+
+ result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
+ flags, num_rids, rids,
+ &num_names, &names, &name_types);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ for (i = 0; i < num_names; i++)
+ printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
+
+ done:
+ return result;
+}
+
+/* Delete domain user */
+
+static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s username\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy and domain handles */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get handle on user */
+
+ {
+ uint32 *user_rids, num_rids, *name_types;
+ uint32 flags = 0x000003e8; /* Unknown */
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+ flags, 1, (const char **)&argv[1],
+ &num_rids, &user_rids,
+ &name_types);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ access_mask,
+ user_rids[0], &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+ }
+
+ /* Delete user */
+
+ result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ done:
+ return result;
+}
+
+/**********************************************************************
+ * Query user security object
+ */
+static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, user_pol, *pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 info_level = 4;
+ fstring server;
+ uint32 user_rid = 0;
+ TALLOC_CTX *ctx = NULL;
+ SEC_DESC_BUF *sec_desc_buf=NULL;
+ BOOL domain = False;
+
+ ctx=talloc_init("cmd_samr_query_sec_obj");
+
+ if ((argc < 1) || (argc > 2)) {
+ printf("Usage: %s [rid|-d]\n", argv[0]);
+ printf("\tSpecify rid for security on user, -d for security on domain\n");
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "-d") == 0)
+ domain = True;
+ else
+ sscanf(argv[1], "%i", &user_rid);
+ }
+
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (domain || user_rid)
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (user_rid)
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ user_rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Pick which query pol to use */
+
+ pol = &connect_pol;
+
+ if (domain)
+ pol = &domain_pol;
+
+ if (user_rid)
+ pol = &user_pol;
+
+ /* Query SAM security object */
+
+ result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx,
+ &sec_desc_buf);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ display_sec_desc(sec_desc_buf->sec);
+
+done:
+ talloc_destroy(ctx);
+ return result;
+}
+
+static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint16 unk_0, unk_1, unk_2;
+
+ if (argc != 1) {
+ printf("Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1, &unk_2);
+
+ if (NT_STATUS_IS_OK(result)) {
+ printf("unk_0 = 0x%08x\n", unk_0);
+ printf("unk_1 = 0x%08x\n", unk_1);
+ printf("unk_2 = 0x%08x\n", unk_2);
+ }
+
+ return result;
+}
+
+
+/* List of commands exported by this module */
+
+struct cmd_set samr_commands[] = {
+
+ { "SAMR" },
+
+ { "queryuser", cmd_samr_query_user, PI_SAMR, "Query user info", "" },
+ { "querygroup", cmd_samr_query_group, PI_SAMR, "Query group info", "" },
+ { "queryusergroups", cmd_samr_query_usergroups, PI_SAMR, "Query user groups", "" },
+ { "queryuseraliases", cmd_samr_query_useraliases, PI_SAMR, "Query user aliases", "" },
+ { "querygroupmem", cmd_samr_query_groupmem, PI_SAMR, "Query group membership", "" },
+ { "queryaliasmem", cmd_samr_query_aliasmem, PI_SAMR, "Query alias membership", "" },
+ { "querydispinfo", cmd_samr_query_dispinfo, PI_SAMR, "Query display info", "" },
+ { "querydominfo", cmd_samr_query_dominfo, PI_SAMR, "Query domain info", "" },
+ { "enumdomusers", cmd_samr_enum_dom_users, PI_SAMR, "Enumerate domain users", "" },
+ { "enumdomgroups", cmd_samr_enum_dom_groups, PI_SAMR, "Enumerate domain groups", "" },
+ { "enumalsgroups", cmd_samr_enum_als_groups, PI_SAMR, "Enumerate alias groups", "" },
+
+ { "createdomuser", cmd_samr_create_dom_user, PI_SAMR, "Create domain user", "" },
+ { "samlookupnames", cmd_samr_lookup_names, PI_SAMR, "Look up names", "" },
+ { "samlookuprids", cmd_samr_lookup_rids, PI_SAMR, "Look up names", "" },
+ { "deletedomuser", cmd_samr_delete_dom_user, PI_SAMR, "Delete domain user", "" },
+ { "samquerysecobj", cmd_samr_query_sec_obj, PI_SAMR, "Query SAMR security object", "" },
+ { "getdompwinfo", cmd_samr_get_dom_pwinfo, PI_SAMR, "Retrieve domain password info", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_spoolss.c b/source4/rpcclient/cmd_spoolss.c
new file mode 100644
index 0000000000..9f6f539e19
--- /dev/null
+++ b/source4/rpcclient/cmd_spoolss.c
@@ -0,0 +1,2297 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Gerald Carter 2001
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Andrew Tridgell 1992-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+struct table_node {
+ const char *long_archi;
+ const char *short_archi;
+ int version;
+};
+
+static const struct table_node archi_table[]= {
+
+ {"Windows 4.0", "WIN40", 0 },
+ {"Windows NT x86", "W32X86", 2 },
+ {"Windows NT R4000", "W32MIPS", 2 },
+ {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
+ {"Windows NT PowerPC", "W32PPC", 2 },
+ {NULL, "", -1 }
+};
+
+/**
+ * @file
+ *
+ * rpcclient module for SPOOLSS rpc pipe.
+ *
+ * This generally just parses and checks command lines, and then calls
+ * a cli_spoolss function.
+ **/
+
+/****************************************************************************
+function to do the mapping between the long architecture name and
+the short one.
+****************************************************************************/
+BOOL get_short_archi(char *short_archi, const char *long_archi)
+{
+ int i=-1;
+
+ DEBUG(107,("Getting architecture dependant directory\n"));
+ do {
+ i++;
+ } while ( (archi_table[i].long_archi!=NULL ) &&
+ StrCaseCmp(long_archi, archi_table[i].long_archi) );
+
+ if (archi_table[i].long_archi==NULL) {
+ DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
+ return False;
+ }
+
+ /* this might be client code - but shouldn't this be an fstrcpy etc? */
+
+ StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
+
+ DEBUGADD(108,("index: [%d]\n", i));
+ DEBUGADD(108,("long architecture: [%s]\n", long_archi));
+ DEBUGADD(108,("short architecture: [%s]\n", short_archi));
+
+ return True;
+}
+
+#if 0
+/**********************************************************************
+ * dummy function -- placeholder
+ */
+static NTSTATUS cmd_spoolss_not_implemented(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ printf ("(*) This command is not currently implemented.\n");
+ return NT_STATUS_OK;
+}
+#endif
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_open_printer_ex(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR werror;
+ fstring printername;
+ fstring servername, user;
+ POLICY_HND hnd;
+
+ if (argc != 2) {
+ printf("Usage: %s <printername>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (!cli)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ fstrcpy (user, cli->user_name);
+ fstrcpy (printername, argv[1]);
+
+ /* Open the printer handle */
+
+ werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", PRINTER_ALL_ACCESS,
+ servername, user, &hnd);
+
+ if (W_ERROR_IS_OK(werror)) {
+ printf("Printer %s opened successfully\n", printername);
+ werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ if (!W_ERROR_IS_OK(werror)) {
+ printf("Error closing printer handle! (%s)\n",
+ get_dos_error_msg(werror));
+ }
+ }
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+
+/****************************************************************************
+printer info level 0 display function
+****************************************************************************/
+static void display_print_info_0(PRINTER_INFO_0 *i0)
+{
+ fstring name = "";
+ fstring servername = "";
+
+ if (!i0)
+ return;
+
+ rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
+
+ rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
+
+ printf("\tprintername:[%s]\n", name);
+ printf("\tservername:[%s]\n", servername);
+ printf("\tcjobs:[0x%x]\n", i0->cjobs);
+ printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
+
+ printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
+ i0->day, i0->dayofweek);
+ printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
+ i0->second, i0->milliseconds);
+
+ printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
+ printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
+
+ printf("\tmajorversion:[0x%x]\n", i0->major_version);
+ printf("\tbuildversion:[0x%x]\n", i0->build_version);
+
+ printf("\tunknown7:[0x%x]\n", i0->unknown7);
+ printf("\tunknown8:[0x%x]\n", i0->unknown8);
+ printf("\tunknown9:[0x%x]\n", i0->unknown9);
+ printf("\tsession_counter:[0x%x]\n", i0->session_counter);
+ printf("\tunknown11:[0x%x]\n", i0->unknown11);
+ printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
+ printf("\tunknown13:[0x%x]\n", i0->unknown13);
+ printf("\tunknown14:[0x%x]\n", i0->unknown14);
+ printf("\tunknown15:[0x%x]\n", i0->unknown15);
+ printf("\tunknown16:[0x%x]\n", i0->unknown16);
+ printf("\tchange_id:[0x%x]\n", i0->change_id);
+ printf("\tunknown18:[0x%x]\n", i0->unknown18);
+ printf("\tstatus:[0x%x]\n", i0->status);
+ printf("\tunknown20:[0x%x]\n", i0->unknown20);
+ printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
+ printf("\tunknown22:[0x%x]\n", i0->unknown22);
+ printf("\tunknown23:[0x%x]\n", i0->unknown23);
+ printf("\tunknown24:[0x%x]\n", i0->unknown24);
+ printf("\tunknown25:[0x%x]\n", i0->unknown25);
+ printf("\tunknown26:[0x%x]\n", i0->unknown26);
+ printf("\tunknown27:[0x%x]\n", i0->unknown27);
+ printf("\tunknown28:[0x%x]\n", i0->unknown28);
+ printf("\tunknown29:[0x%x]\n", i0->unknown29);
+
+ printf("\n");
+}
+
+/****************************************************************************
+printer info level 1 display function
+****************************************************************************/
+static void display_print_info_1(PRINTER_INFO_1 *i1)
+{
+ fstring desc = "";
+ fstring name = "";
+ fstring comm = "";
+
+ rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
+ STR_TERMINATE);
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
+
+ printf("\tflags:[0x%x]\n", i1->flags);
+ printf("\tname:[%s]\n", name);
+ printf("\tdescription:[%s]\n", desc);
+ printf("\tcomment:[%s]\n", comm);
+
+ printf("\n");
+}
+
+/****************************************************************************
+printer info level 2 display function
+****************************************************************************/
+static void display_print_info_2(PRINTER_INFO_2 *i2)
+{
+ fstring servername = "";
+ fstring printername = "";
+ fstring sharename = "";
+ fstring portname = "";
+ fstring drivername = "";
+ fstring comment = "";
+ fstring location = "";
+ fstring sepfile = "";
+ fstring printprocessor = "";
+ fstring datatype = "";
+ fstring parameters = "";
+
+ rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
+
+ rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
+
+ rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
+
+ rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
+
+ rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
+
+ rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
+
+ rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
+
+ rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
+
+ rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
+
+ rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
+
+ rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
+
+ printf("\tservername:[%s]\n", servername);
+ printf("\tprintername:[%s]\n", printername);
+ printf("\tsharename:[%s]\n", sharename);
+ printf("\tportname:[%s]\n", portname);
+ printf("\tdrivername:[%s]\n", drivername);
+ printf("\tcomment:[%s]\n", comment);
+ printf("\tlocation:[%s]\n", location);
+ printf("\tsepfile:[%s]\n", sepfile);
+ printf("\tprintprocessor:[%s]\n", printprocessor);
+ printf("\tdatatype:[%s]\n", datatype);
+ printf("\tparameters:[%s]\n", parameters);
+ printf("\tattributes:[0x%x]\n", i2->attributes);
+ printf("\tpriority:[0x%x]\n", i2->priority);
+ printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
+ printf("\tstarttime:[0x%x]\n", i2->starttime);
+ printf("\tuntiltime:[0x%x]\n", i2->untiltime);
+ printf("\tstatus:[0x%x]\n", i2->status);
+ printf("\tcjobs:[0x%x]\n", i2->cjobs);
+ printf("\taverageppm:[0x%x]\n", i2->averageppm);
+
+ if (i2->secdesc)
+ display_sec_desc(i2->secdesc);
+
+ printf("\n");
+}
+
+/****************************************************************************
+printer info level 3 display function
+****************************************************************************/
+static void display_print_info_3(PRINTER_INFO_3 *i3)
+{
+ printf("\tflags:[0x%x]\n", i3->flags);
+
+ display_sec_desc(i3->secdesc);
+
+ printf("\n");
+}
+
+/* Enumerate printers */
+
+static NTSTATUS cmd_spoolss_enum_printers(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ uint32 info_level = 1;
+ PRINTER_INFO_CTR ctr;
+ uint32 i = 0, num_printers, needed;
+ fstring name;
+
+ if (argc > 3)
+ {
+ printf("Usage: %s [level] [name]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ if (argc == 3)
+ fstrcpy(name, argv[2]);
+ else {
+ slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
+ strupper(name);
+ }
+
+ /* Enumerate printers -- Should we enumerate types other
+ than PRINTER_ENUM_LOCAL? Maybe accept as a parameter? --jerry */
+
+ ZERO_STRUCT(ctr);
+
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL,
+ info_level, &num_printers, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL,
+ info_level, &num_printers, &ctr);
+
+ if (W_ERROR_IS_OK(result)) {
+
+ if (!num_printers) {
+ printf ("No printers returned.\n");
+ goto done;
+ }
+
+ for (i = 0; i < num_printers; i++) {
+ switch(info_level) {
+ case 0:
+ display_print_info_0(&ctr.printers_0[i]);
+ break;
+ case 1:
+ display_print_info_1(&ctr.printers_1[i]);
+ break;
+ case 2:
+ display_print_info_2(&ctr.printers_2[i]);
+ break;
+ case 3:
+ display_print_info_3(&ctr.printers_3[i]);
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ goto done;
+ }
+ }
+ }
+ done:
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/****************************************************************************
+port info level 1 display function
+****************************************************************************/
+static void display_port_info_1(PORT_INFO_1 *i1)
+{
+ fstring buffer;
+
+ rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
+ printf("\tPort Name:\t[%s]\n", buffer);
+}
+
+/****************************************************************************
+port info level 2 display function
+****************************************************************************/
+static void display_port_info_2(PORT_INFO_2 *i2)
+{
+ fstring buffer;
+
+ rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
+ printf("\tPort Name:\t[%s]\n", buffer);
+ rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
+
+ printf("\tMonitor Name:\t[%s]\n", buffer);
+ rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
+
+ printf("\tDescription:\t[%s]\n", buffer);
+ printf("\tPort Type:\t[%d]\n", i2->port_type);
+ printf("\tReserved:\t[%d]\n", i2->reserved);
+ printf("\n");
+}
+
+/* Enumerate ports */
+
+static NTSTATUS cmd_spoolss_enum_ports(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 needed, info_level = 1;
+ PORT_INFO_CTR ctr;
+ int returned;
+
+ if (argc > 2) {
+ printf("Usage: %s [level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ /* Enumerate ports */
+
+ ZERO_STRUCT(ctr);
+
+ result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level,
+ &returned, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
+ info_level, &returned, &ctr);
+
+ if (W_ERROR_IS_OK(result)) {
+ int i;
+
+ for (i = 0; i < returned; i++) {
+ switch (info_level) {
+ case 1:
+ display_port_info_1(&ctr.port.info_1[i]);
+ break;
+ case 2:
+ display_port_info_2(&ctr.port.info_2[i]);
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+ }
+ }
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/***********************************************************************
+ * Set printer comment - use a level2 set.
+ */
+static NTSTATUS cmd_spoolss_setprinter(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ uint32 needed;
+ uint32 info_level = 2;
+ BOOL opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ fstring printername,
+ servername,
+ user,
+ comment;
+
+ if (argc == 1 || argc > 3) {
+ printf("Usage: %s printername comment\n", argv[0]);
+
+ return NT_STATUS_OK;
+ }
+
+ /* Open a printer handle */
+ if (argc == 3) {
+ fstrcpy(comment, argv[2]);
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ fstrcpy (printername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* get a printer handle */
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ MAXIMUM_ALLOWED_ACCESS, servername,
+ user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+ result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+
+ /* Modify the comment. */
+ init_unistr(&ctr.printers_2->comment, comment);
+ ctr.printers_2->devmode = NULL;
+ ctr.printers_2->secdesc = NULL;
+
+ result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+ if (W_ERROR_IS_OK(result))
+ printf("Success in setting comment.\n");
+
+ done:
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_getprinter(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ uint32 info_level = 1;
+ BOOL opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ fstring printername,
+ servername,
+ user;
+ uint32 needed;
+
+ if (argc == 1 || argc > 3) {
+ printf("Usage: %s <printername> [level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Open a printer handle */
+ if (argc == 3) {
+ info_level = atoi(argv[2]);
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ slprintf (printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* get a printer handle */
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+
+ result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
+ &pol, info_level, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinter(
+ cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* Display printer info */
+
+ switch (info_level) {
+ case 0:
+ display_print_info_0(ctr.printers_0);
+ break;
+ case 1:
+ display_print_info_1(ctr.printers_1);
+ break;
+ case 2:
+ display_print_info_2(ctr.printers_2);
+ break;
+ case 3:
+ display_print_info_3(ctr.printers_3);
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static void display_reg_value(REGISTRY_VALUE value)
+{
+ pstring text;
+
+ switch(value.type) {
+ case REG_DWORD:
+ printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
+ *((uint32 *) value.data_p));
+ break;
+ case REG_SZ:
+ rpcstr_pull(text, value.data_p, sizeof(text), value.size,
+ STR_TERMINATE);
+ printf("%s: REG_SZ: %s\n", value.valuename, text);
+ break;
+ case REG_BINARY:
+ printf("%s: REG_BINARY: unknown length value not displayed\n",
+ value.valuename);
+ break;
+ case REG_MULTI_SZ: {
+ uint16 *curstr = (uint16 *) value.data_p;
+ uint8 *start = value.data_p;
+ printf("%s: REG_MULTI_SZ:\n", value.valuename);
+ while ((*curstr != 0) &&
+ ((uint8 *) curstr < start + value.size)) {
+ rpcstr_pull(text, curstr, sizeof(text), -1,
+ STR_TERMINATE);
+ printf(" %s\n", text);
+ curstr += strlen(text) + 1;
+ }
+ }
+ break;
+ default:
+ printf("%s: unknown type %d\n", value.valuename, value.type);
+ }
+
+}
+
+/***********************************************************************
+ * Get printer data
+ */
+static NTSTATUS cmd_spoolss_getprinterdata(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ BOOL opened_hnd = False;
+ fstring printername,
+ servername,
+ user;
+ uint32 needed;
+ const char *valuename;
+ REGISTRY_VALUE value;
+
+ if (argc != 3) {
+ printf("Usage: %s <printername> <valuename>\n", argv[0]);
+ printf("<printername> of . queries print server\n");
+ return NT_STATUS_OK;
+ }
+ valuename = argv[2];
+
+ /* Open a printer handle */
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ if (strncmp(argv[1], ".", sizeof(".")) == 0)
+ fstrcpy(printername, servername);
+ else
+ slprintf (printername, sizeof(servername)-1, "%s\\%s",
+ servername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* get a printer handle */
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+
+ result = cli_spoolss_getprinterdata(cli, mem_ctx, 0, &needed,
+ &pol, valuename, &value);
+
+ if (W_ERROR_V(result) == ERRmoredata)
+ result = cli_spoolss_getprinterdata(
+ cli, mem_ctx, needed, NULL, &pol, valuename, &value);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* Display printer data */
+
+ fstrcpy(value.valuename, valuename);
+ display_reg_value(value);
+
+
+ done:
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/***********************************************************************
+ * Get printer data
+ */
+static NTSTATUS cmd_spoolss_getprinterdataex(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ BOOL opened_hnd = False;
+ fstring printername,
+ servername,
+ user;
+ uint32 needed;
+ const char *valuename, *keyname;
+ REGISTRY_VALUE value;
+
+ if (argc != 4) {
+ printf("Usage: %s <printername> <keyname> <valuename>\n",
+ argv[0]);
+ printf("<printername> of . queries print server\n");
+ return NT_STATUS_OK;
+ }
+ valuename = argv[3];
+ keyname = argv[2];
+
+ /* Open a printer handle */
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ if (strncmp(argv[1], ".", sizeof(".")) == 0)
+ fstrcpy(printername, servername);
+ else
+ slprintf (printername, sizeof(printername)-1, "%s\\%s",
+ servername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* get a printer handle */
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+
+ result = cli_spoolss_getprinterdataex(cli, mem_ctx, 0, &needed,
+ &pol, keyname, valuename,
+ &value);
+
+ if (W_ERROR_V(result) == ERRmoredata)
+ result = cli_spoolss_getprinterdataex(cli, mem_ctx, needed,
+ NULL, &pol, keyname,
+ valuename, &value);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* Display printer data */
+
+ fstrcpy(value.valuename, valuename);
+ display_reg_value(value);
+
+
+ done:
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/****************************************************************************
+printer info level 0 display function
+****************************************************************************/
+static void display_print_driver_1(DRIVER_INFO_1 *i1)
+{
+ fstring name;
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+
+ printf ("Printer Driver Info 1:\n");
+ printf ("\tDriver Name: [%s]\n\n", name);
+
+ return;
+}
+
+/****************************************************************************
+printer info level 1 display function
+****************************************************************************/
+static void display_print_driver_2(DRIVER_INFO_2 *i1)
+{
+ fstring name;
+ fstring architecture;
+ fstring driverpath;
+ fstring datafile;
+ fstring configfile;
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+
+ printf ("Printer Driver Info 2:\n");
+ printf ("\tVersion: [%x]\n", i1->version);
+ printf ("\tDriver Name: [%s]\n", name);
+ printf ("\tArchitecture: [%s]\n", architecture);
+ printf ("\tDriver Path: [%s]\n", driverpath);
+ printf ("\tDatafile: [%s]\n", datafile);
+ printf ("\tConfigfile: [%s]\n\n", configfile);
+
+ return;
+}
+
+/****************************************************************************
+printer info level 2 display function
+****************************************************************************/
+static void display_print_driver_3(DRIVER_INFO_3 *i1)
+{
+ fstring name = "";
+ fstring architecture = "";
+ fstring driverpath = "";
+ fstring datafile = "";
+ fstring configfile = "";
+ fstring helpfile = "";
+ fstring dependentfiles = "";
+ fstring monitorname = "";
+ fstring defaultdatatype = "";
+
+ int length=0;
+ BOOL valid = True;
+
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+ rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
+ rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
+ rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
+
+ printf ("Printer Driver Info 3:\n");
+ printf ("\tVersion: [%x]\n", i1->version);
+ printf ("\tDriver Name: [%s]\n",name);
+ printf ("\tArchitecture: [%s]\n", architecture);
+ printf ("\tDriver Path: [%s]\n", driverpath);
+ printf ("\tDatafile: [%s]\n", datafile);
+ printf ("\tConfigfile: [%s]\n", configfile);
+ printf ("\tHelpfile: [%s]\n\n", helpfile);
+
+ while (valid)
+ {
+ rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+
+ length+=strlen(dependentfiles)+1;
+
+ if (strlen(dependentfiles) > 0)
+ {
+ printf ("\tDependentfiles: [%s]\n", dependentfiles);
+ }
+ else
+ {
+ valid = False;
+ }
+ }
+
+ printf ("\n");
+
+ printf ("\tMonitorname: [%s]\n", monitorname);
+ printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+
+ return;
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_getdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR werror;
+ NTSTATUS result;
+ uint32 info_level = 3;
+ BOOL opened_hnd = False;
+ PRINTER_DRIVER_CTR ctr;
+ fstring printername,
+ servername,
+ user;
+ uint32 i;
+
+ if ((argc == 1) || (argc > 3))
+ {
+ printf("Usage: %s <printername> [level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* get the arguments need to open the printer handle */
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ fstrcpy (user, cli->user_name);
+ fstrcpy (printername, argv[1]);
+ if (argc == 3)
+ info_level = atoi(argv[2]);
+
+ /* Open a printer handle */
+
+ werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ACCESS_USE,
+ servername, user, &pol);
+
+ result = W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ printf("Error opening printer handle for %s!\n", printername);
+ return result;
+ }
+
+ opened_hnd = True;
+
+ /* loop through and print driver info level for each architecture */
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+ uint32 needed;
+
+ werror = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, 0, &needed, &pol, info_level,
+ archi_table[i].long_archi, &ctr);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, needed, NULL, &pol, info_level,
+ archi_table[i].long_archi, &ctr);
+
+ if (!W_ERROR_IS_OK(werror))
+ continue;
+
+ printf ("\n[%s]\n", archi_table[i].long_archi);
+
+ switch (info_level) {
+ case 1:
+ display_print_driver_1 (ctr.info1);
+ break;
+ case 2:
+ display_print_driver_2 (ctr.info2);
+ break;
+ case 3:
+ display_print_driver_3 (ctr.info3);
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+ }
+
+ /* Cleanup */
+
+ if (opened_hnd)
+ cli_spoolss_close_printer (cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_enum_drivers(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR werror;
+ uint32 info_level = 1;
+ PRINTER_DRIVER_CTR ctr;
+ uint32 i, j,
+ returned;
+
+ if (argc > 2)
+ {
+ printf("Usage: enumdrivers [level]\n");
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+
+ /* loop through and print driver info level for each architecture */
+ for (i=0; archi_table[i].long_archi!=NULL; i++)
+ {
+ uint32 needed;
+
+ werror = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, 0, &needed, info_level,
+ archi_table[i].long_archi, &returned, &ctr);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, needed, NULL, info_level,
+ archi_table[i].long_archi, &returned, &ctr);
+
+ if (returned == 0)
+ continue;
+
+ if (!W_ERROR_IS_OK(werror)) {
+ printf ("Error getting driver for environment [%s] - %d\n",
+ archi_table[i].long_archi, W_ERROR_V(werror));
+ continue;
+ }
+
+ printf ("\n[%s]\n", archi_table[i].long_archi);
+ switch (info_level)
+ {
+
+ case 1:
+ for (j=0; j < returned; j++) {
+ display_print_driver_1 (&(ctr.info1[j]));
+ }
+ break;
+ case 2:
+ for (j=0; j < returned; j++) {
+ display_print_driver_2 (&(ctr.info2[j]));
+ }
+ break;
+ case 3:
+ for (j=0; j < returned; j++) {
+ display_print_driver_3 (&(ctr.info3[j]));
+ }
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+ }
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/****************************************************************************
+printer info level 1 display function
+****************************************************************************/
+static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
+{
+ fstring name;
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+
+ printf ("\tDirectory Name:[%s]\n", name);
+}
+
+/***********************************************************************
+ * Get printer driver directory information
+ */
+static NTSTATUS cmd_spoolss_getdriverdir(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ fstring env;
+ DRIVER_DIRECTORY_CTR ctr;
+ uint32 needed;
+
+ if (argc > 2) {
+ printf("Usage: %s [environment]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get the arguments need to open the printer handle */
+
+ if (argc == 2)
+ fstrcpy (env, argv[1]);
+ else
+ fstrcpy (env, "Windows NT x86");
+
+ /* Get the directory. Only use Info level 1 */
+
+ result = cli_spoolss_getprinterdriverdir(
+ cli, mem_ctx, 0, &needed, 1, env, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinterdriverdir(
+ cli, mem_ctx, needed, NULL, 1, env, &ctr);
+
+ if (W_ERROR_IS_OK(result))
+ display_printdriverdir_1(ctr.info1);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/*******************************************************************************
+ set the version and environment fields of a DRIVER_INFO_3 struct
+ ******************************************************************************/
+void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
+{
+
+ int i;
+
+ for (i=0; archi_table[i].long_archi != NULL; i++)
+ {
+ if (strcmp(arch, archi_table[i].short_archi) == 0)
+ {
+ info->version = archi_table[i].version;
+ init_unistr (&info->architecture, archi_table[i].long_archi);
+ break;
+ }
+ }
+
+ if (archi_table[i].long_archi == NULL)
+ {
+ DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
+ }
+
+ return;
+}
+
+
+/**************************************************************************
+ wrapper for strtok to get the next parameter from a delimited list.
+ Needed to handle the empty parameter string denoted by "NULL"
+ *************************************************************************/
+static char* get_driver_3_param (const char* str, const char* delim, UNISTR* dest)
+{
+ char *ptr;
+
+ /* get the next token */
+ ptr = strtok(str, delim);
+
+ /* a string of 'NULL' is used to represent an empty
+ parameter because two consecutive delimiters
+ will not return an empty string. See man strtok(3)
+ for details */
+ if (StrCaseCmp(ptr, "NULL") == 0)
+ ptr = NULL;
+
+ if (dest != NULL)
+ init_unistr(dest, ptr);
+
+ return ptr;
+}
+
+/********************************************************************************
+ fill in the members of a DRIVER_INFO_3 struct using a character
+ string in the form of
+ <Long Printer Name>:<Driver File Name>:<Data File Name>:\
+ <Config File Name>:<Help File Name>:<Language Monitor Name>:\
+ <Default Data Type>:<Comma Separated list of Files>
+ *******************************************************************************/
+static BOOL init_drv_info_3_members (
+ TALLOC_CTX *mem_ctx,
+ DRIVER_INFO_3 *info,
+ const char *args
+)
+{
+ char *str, *str2;
+ uint32 len, i;
+
+ /* fill in the UNISTR fields */
+ str = get_driver_3_param (args, ":", &info->name);
+ str = get_driver_3_param (NULL, ":", &info->driverpath);
+ str = get_driver_3_param (NULL, ":", &info->datafile);
+ str = get_driver_3_param (NULL, ":", &info->configfile);
+ str = get_driver_3_param (NULL, ":", &info->helpfile);
+ str = get_driver_3_param (NULL, ":", &info->monitorname);
+ str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
+
+ /* <Comma Separated List of Dependent Files> */
+ str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
+ str = str2;
+
+ /* begin to strip out each filename */
+ str = strtok(str, ",");
+ len = 0;
+ while (str != NULL)
+ {
+ /* keep a cumlative count of the str lengths */
+ len += strlen(str)+1;
+ str = strtok(NULL, ",");
+ }
+
+ /* allocate the space; add one extra slot for a terminating NULL.
+ Each filename is NULL terminated and the end contains a double
+ NULL */
+ if ((info->dependentfiles=(uint16*)talloc(mem_ctx, (len+1)*sizeof(uint16))) == NULL)
+ {
+ DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
+ return False;
+ }
+ for (i=0; i<len; i++)
+ {
+ info->dependentfiles[i] = SSVAL(&info->dependentfiles[i], 0, str2[i]);
+ }
+ info->dependentfiles[len] = '\0';
+
+ return True;
+}
+
+
+static NTSTATUS cmd_spoolss_addprinterdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ uint32 level = 3;
+ PRINTER_DRIVER_CTR ctr;
+ DRIVER_INFO_3 info3;
+ fstring arch;
+ fstring driver_name;
+
+ /* parse the command arguements */
+ if (argc != 3)
+ {
+ printf ("Usage: %s <Environment>\\\n", argv[0]);
+ printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
+ printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
+ printf ("\t<Default Data Type>:<Comma Separated list of Files>\n");
+
+ return NT_STATUS_OK;
+ }
+
+ /* Fill in the DRIVER_INFO_3 struct */
+ ZERO_STRUCT(info3);
+ if (!get_short_archi(arch, argv[1]))
+ {
+ printf ("Error Unknown architechture [%s]\n", argv[1]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ else
+ set_drv_info_3_env(&info3, arch);
+
+ if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
+ {
+ printf ("Error Invalid parameter list - %s.\n", argv[2]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+
+ ctr.info3 = &info3;
+ result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+
+ if (W_ERROR_IS_OK(result)) {
+ rpcstr_pull(driver_name, info3.name.buffer,
+ sizeof(driver_name), -1, STR_TERMINATE);
+ printf ("Printer Driver %s successfully installed.\n",
+ driver_name);
+ }
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS cmd_spoolss_addprinterex(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ uint32 level = 2;
+ PRINTER_INFO_CTR ctr;
+ PRINTER_INFO_2 info2;
+ fstring servername;
+
+ /* parse the command arguements */
+ if (argc != 5)
+ {
+ printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+
+ /* Fill in the DRIVER_INFO_3 struct */
+ ZERO_STRUCT(info2);
+#if 0 /* JERRY */
+ init_unistr( &info2.servername, servername);
+#endif
+ init_unistr( &info2.printername, argv[1]);
+ init_unistr( &info2.sharename, argv[2]);
+ init_unistr( &info2.drivername, argv[3]);
+ init_unistr( &info2.portname, argv[4]);
+ init_unistr( &info2.comment, "Created by rpcclient");
+ init_unistr( &info2.printprocessor, "winprint");
+ init_unistr( &info2.datatype, "RAW");
+ info2.devmode = NULL;
+ info2.secdesc = NULL;
+ info2.attributes = PRINTER_ATTRIBUTE_SHARED;
+ info2.priority = 0;
+ info2.defaultpriority = 0;
+ info2.starttime = 0;
+ info2.untiltime = 0;
+
+ /* These three fields must not be used by AddPrinter()
+ as defined in the MS Platform SDK documentation..
+ --jerry
+ info2.status = 0;
+ info2.cjobs = 0;
+ info2.averageppm = 0;
+ */
+
+ ctr.printers_2 = &info2;
+ result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+
+ if (W_ERROR_IS_OK(result))
+ printf ("Printer %s successfully installed.\n", argv[1]);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_spoolss_setdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ uint32 level = 2;
+ BOOL opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ PRINTER_INFO_2 info2;
+ fstring servername,
+ printername,
+ user;
+ uint32 needed;
+
+ /* parse the command arguements */
+ if (argc != 3)
+ {
+ printf ("Usage: %s <printer> <driver>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ slprintf (printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* Get a printer handle */
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+
+ ZERO_STRUCT (info2);
+ ctr.printers_2 = &info2;
+
+ result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
+ &pol, level, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinter(
+ cli, mem_ctx, needed, NULL, &pol, level, &ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf ("Unable to retrieve printer information!\n");
+ goto done;
+ }
+
+ /* Set the printer driver */
+
+ init_unistr(&ctr.printers_2->drivername, argv[2]);
+
+ result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("SetPrinter call failed!\n");
+ goto done;;
+ }
+
+ printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
+
+done:
+ /* Cleanup */
+
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS cmd_spoolss_deletedriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ fstring servername;
+ int i;
+
+ /* parse the command arguements */
+ if (argc != 2)
+ {
+ printf ("Usage: %s <driver>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+
+ /* delete the driver for all architectures */
+ for (i=0; archi_table[i].long_archi; i++)
+ {
+ /* make the call to remove the driver */
+ result = cli_spoolss_deleteprinterdriver(
+ cli, mem_ctx, archi_table[i].long_archi, argv[1]);
+
+ if ( !W_ERROR_IS_OK(result) ) {
+ if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
+ printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
+ argv[1], archi_table[i].long_archi,
+ W_ERROR_V(result));
+ }
+ }
+ else
+ {
+ printf ("Driver %s removed for arch [%s].\n", argv[1],
+ archi_table[i].long_archi);
+ }
+ }
+
+ return W_ERROR_IS_OK(result) || W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_spoolss_getprintprocdir(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ char *servername = NULL, *environment = NULL;
+ fstring procdir;
+ uint32 needed;
+
+ /* parse the command arguements */
+ if (argc > 2) {
+ printf ("Usage: %s [environment]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
+ return NT_STATUS_NO_MEMORY;
+ strupper(servername);
+
+ if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
+ PRINTER_DRIVER_ARCHITECTURE) < 0) {
+ SAFE_FREE(servername);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result = cli_spoolss_getprintprocessordirectory(
+ cli, mem_ctx, 0, &needed, servername, environment, procdir);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprintprocessordirectory(
+ cli, mem_ctx, needed, NULL, servername, environment,
+ procdir);
+
+ if (W_ERROR_IS_OK(result))
+ printf("%s\n", procdir);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(environment);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Add a form */
+
+static NTSTATUS cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ FORM form;
+ BOOL got_handle = False;
+
+ /* Parse the command arguements */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Dummy up some values for the form data */
+
+ form.flags = FORM_USER;
+ form.size_x = form.size_y = 100;
+ form.left = 0;
+ form.top = 10;
+ form.right = 20;
+ form.bottom = 30;
+
+ init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1);
+
+ /* Add the form */
+
+
+ werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Set a form */
+
+static NTSTATUS cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ FORM form;
+ BOOL got_handle = False;
+
+ /* Parse the command arguements */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Dummy up some values for the form data */
+
+ form.flags = FORM_PRINTER;
+ form.size_x = form.size_y = 100;
+ form.left = 0;
+ form.top = 1000;
+ form.right = 2000;
+ form.bottom = 3000;
+
+ init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1);
+
+ /* Set the form */
+
+ werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Get a form */
+
+static NTSTATUS cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ FORM_1 form;
+ BOOL got_handle = False;
+ uint32 needed;
+
+ /* Parse the command arguements */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Set the form */
+
+ werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
+ &handle, argv[2], 1, &form);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
+ &handle, argv[2], 1, &form);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ printf("width: %d\n", form.width);
+ printf("length: %d\n", form.length);
+ printf("left: %d\n", form.left);
+ printf("top: %d\n", form.top);
+ printf("right: %d\n", form.right);
+ printf("bottom: %d\n", form.bottom);
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Delete a form */
+
+static NTSTATUS cmd_spoolss_deleteform(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ BOOL got_handle = False;
+
+ /* Parse the command arguements */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Delete the form */
+
+ werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Enumerate forms */
+
+static NTSTATUS cmd_spoolss_enum_forms(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ BOOL got_handle = False;
+ uint32 needed, num_forms, level = 1, i;
+ FORM_1 *forms;
+
+ /* Parse the command arguements */
+
+ if (argc != 2) {
+ printf ("Usage: %s <printer>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Enumerate forms */
+
+ werror = cli_spoolss_enumforms(
+ cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_enumforms(
+ cli, mem_ctx, needed, NULL, &handle, level,
+ &num_forms, &forms);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ /* Display output */
+
+ for (i = 0; i < num_forms; i++) {
+ fstring form_name;
+
+ if (forms[i].name.buffer)
+ rpcstr_pull(form_name, forms[i].name.buffer,
+ sizeof(form_name), -1, STR_TERMINATE);
+
+ printf("%s\n", form_name);
+ }
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_spoolss_setprinterdata(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ uint32 needed;
+ fstring servername, printername, user;
+ POLICY_HND pol;
+ BOOL opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ PRINTER_INFO_0 info;
+ REGISTRY_VALUE value;
+
+ /* parse the command arguements */
+ if (argc != 4) {
+ printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper (servername);
+ slprintf (printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy (user, cli->user_name);
+
+ /* get a printer handle */
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ MAXIMUM_ALLOWED_ACCESS, servername,
+ user, &pol);
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ ctr.printers_0 = &info;
+
+ result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
+ &pol, 0, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ printf("%s\n", timestring(True));
+ printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
+
+ /* Set the printer data */
+
+ fstrcpy(value.valuename, argv[2]);
+ value.type = REG_SZ;
+ value.size = strlen(argv[3]) + 1;
+ value.data_p = talloc_memdup(mem_ctx, argv[3], value.size);
+
+ result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
+ goto done;
+ }
+ printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
+
+ result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ printf("%s\n", timestring(True));
+ printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
+
+done:
+ /* cleanup */
+ if (opened_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static void display_job_info_1(JOB_INFO_1 *job)
+{
+ fstring username = "", document = "", text_status = "";
+
+ rpcstr_pull(username, job->username.buffer,
+ sizeof(username), -1, STR_TERMINATE);
+
+ rpcstr_pull(document, job->document.buffer,
+ sizeof(document), -1, STR_TERMINATE);
+
+ rpcstr_pull(text_status, job->text_status.buffer,
+ sizeof(text_status), -1, STR_TERMINATE);
+
+ printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
+ username, document, text_status, job->pagesprinted,
+ job->totalpages);
+}
+
+static void display_job_info_2(JOB_INFO_2 *job)
+{
+ fstring username = "", document = "", text_status = "";
+
+ rpcstr_pull(username, job->username.buffer,
+ sizeof(username), -1, STR_TERMINATE);
+
+ rpcstr_pull(document, job->document.buffer,
+ sizeof(document), -1, STR_TERMINATE);
+
+ rpcstr_pull(text_status, job->text_status.buffer,
+ sizeof(text_status), -1, STR_TERMINATE);
+
+ printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
+ username, document, text_status, job->pagesprinted,
+ job->totalpages, job->size);
+}
+
+/* Enumerate jobs */
+
+static NTSTATUS cmd_spoolss_enum_jobs(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 needed, level = 1, num_jobs, i;
+ BOOL got_hnd = False;
+ pstring printername;
+ fstring servername, user;
+ POLICY_HND hnd;
+ JOB_INFO_CTR ctr;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s printername [level]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 3)
+ level = atoi(argv[2]);
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper(servername);
+ fstrcpy(user, cli->user_name);
+ slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
+ strupper(printername);
+ pstrcat(printername, argv[1]);
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ got_hnd = True;
+
+ /* Enumerate ports */
+
+ result = cli_spoolss_enumjobs(
+ cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
+ &num_jobs, &ctr);
+
+ if (W_ERROR_V(result) == ERRinsufficientbuffer)
+ result = cli_spoolss_enumjobs(
+ cli, mem_ctx, needed, NULL, &hnd, level, 0,
+ 1000, &num_jobs, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < num_jobs; i++) {
+ switch(level) {
+ case 1:
+ display_job_info_1(&ctr.job.job_info_1[i]);
+ break;
+ case 2:
+ display_job_info_2(&ctr.job.job_info_2[i]);
+ break;
+ default:
+ d_printf("unknown info level %d\n", level);
+ break;
+ }
+ }
+
+done:
+ if (got_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* enumerate data */
+
+static NTSTATUS cmd_spoolss_enum_data( struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 i=0, val_needed, data_needed;
+ BOOL got_hnd = False;
+ pstring printername;
+ fstring servername, user;
+ POLICY_HND hnd;
+
+ if (argc != 2) {
+ printf("Usage: %s printername\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper(servername);
+ fstrcpy(user, cli->user_name);
+ slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+ strupper(printername);
+ pstrcat(printername, argv[1]);
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ got_hnd = True;
+
+ /* Enumerate data */
+
+ result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
+ &val_needed, &data_needed,
+ NULL);
+ while (W_ERROR_IS_OK(result)) {
+ REGISTRY_VALUE value;
+ result = cli_spoolss_enumprinterdata(
+ cli, mem_ctx, &hnd, i++, val_needed,
+ data_needed, 0, 0, &value);
+ if (W_ERROR_IS_OK(result))
+ display_reg_value(value);
+ }
+ if (W_ERROR_V(result) == ERRnomoreitems)
+ result = W_ERROR(ERRsuccess);
+
+done:
+ if (got_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* enumerate data for a given key */
+
+static NTSTATUS cmd_spoolss_enum_data_ex( struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 needed, i;
+ BOOL got_hnd = False;
+ pstring printername;
+ fstring servername, user;
+ const char *keyname = NULL;
+ POLICY_HND hnd;
+ REGVAL_CTR ctr;
+
+ if (argc != 3) {
+ printf("Usage: %s printername <keyname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ keyname = argv[2];
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper(servername);
+ fstrcpy(user, cli->user_name);
+ slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+ strupper(printername);
+ pstrcat(printername, argv[1]);
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ got_hnd = True;
+
+ /* Enumerate subkeys */
+
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
+
+ if (W_ERROR_V(result) == ERRmoredata)
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ for (i=0; i < ctr.num_values; i++) {
+ display_reg_value(*(ctr.values[i]));
+ }
+
+ regval_ctr_destroy(&ctr);
+
+done:
+ if (got_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* enumerate subkeys */
+
+static NTSTATUS cmd_spoolss_enum_printerkey( struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 needed, returned;
+ BOOL got_hnd = False;
+ pstring printername;
+ fstring servername, user;
+ const char *keyname = NULL;
+ POLICY_HND hnd;
+ uint16 *keylist = NULL, *curkey;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s printername [keyname]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 3)
+ keyname = argv[2];
+ else
+ keyname = "";
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper(servername);
+ fstrcpy(user, cli->user_name);
+ slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+ strupper(printername);
+ pstrcat(printername, argv[1]);
+
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", MAXIMUM_ALLOWED_ACCESS,
+ servername, user, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ got_hnd = True;
+
+ /* Enumerate subkeys */
+
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
+
+ if (W_ERROR_V(result) == ERRmoredata)
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
+ &returned);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ curkey = keylist;
+ while (*curkey != 0) {
+ pstring subkey;
+ rpcstr_pull(subkey, curkey, sizeof(subkey), -1,
+ STR_TERMINATE);
+ printf("%s\n", subkey);
+ curkey += strlen(subkey) + 1;
+ }
+
+ safe_free(keylist);
+
+done:
+ if (got_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_spoolss_rffpcnex(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ fstring servername, printername;
+ POLICY_HND hnd;
+ BOOL got_hnd = False;
+ WERROR result;
+ SPOOL_NOTIFY_OPTION option;
+
+ if (argc != 2) {
+ printf("Usage: %s printername\n", argv[0]);
+ result = WERR_OK;
+ goto done;
+ }
+
+ /* Open printer */
+
+ slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
+ strupper(servername);
+
+ slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
+ argv[1]);
+ strupper(printername);
+
+ result = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &hnd);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("Error opening %s\n", argv[1]);
+ goto done;
+ }
+
+ got_hnd = True;
+
+ /* Create spool options */
+
+ ZERO_STRUCT(option);
+
+ option.version = 2;
+ option.option_type_ptr = 1;
+ option.count = option.ctr.count = 2;
+
+ option.ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)talloc(
+ mem_ctx, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * 2);
+
+ ZERO_STRUCT(option.ctr.type[0]);
+ option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
+ option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
+ option.ctr.type[0].fields_ptr = 1;
+ option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
+
+ ZERO_STRUCT(option.ctr.type[1]);
+ option.ctr.type[1].type = JOB_NOTIFY_TYPE;
+ option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
+ option.ctr.type[1].fields_ptr = 1;
+ option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
+
+ /* Send rffpcnex */
+
+ slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
+ strupper(servername);
+
+ result = cli_spoolss_rffpcnex(
+ cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("Error rffpcnex %s\n", argv[1]);
+ goto done;
+ }
+
+done:
+ if (got_hnd)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* List of commands exported by this module */
+struct cmd_set spoolss_commands[] = {
+
+ { "SPOOLSS" },
+
+ { "adddriver", cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" },
+ { "addprinter", cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" },
+ { "deldriver", cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" },
+ { "enumdata", cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" },
+ { "enumdataex", cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" },
+ { "enumkey", cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" },
+ { "enumjobs", cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" },
+ { "enumports", cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" },
+ { "enumdrivers", cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" },
+ { "enumprinters", cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" },
+ { "getdata", cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" },
+ { "getdataex", cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""},
+ { "getdriver", cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" },
+ { "getdriverdir", cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" },
+ { "getprinter", cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" },
+ { "getprintprocdir", cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
+ { "openprinter", cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" },
+ { "setdriver", cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" },
+ { "getprintprocdir", cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" },
+ { "addform", cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" },
+ { "setform", cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" },
+ { "getform", cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" },
+ { "deleteform", cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" },
+ { "enumforms", cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" },
+ { "setprinter", cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" },
+ { "setprinterdata", cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" },
+ { "rffpcnex", cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_srvsvc.c b/source4/rpcclient/cmd_srvsvc.c
new file mode 100644
index 0000000000..8597c7bc2e
--- /dev/null
+++ b/source4/rpcclient/cmd_srvsvc.c
@@ -0,0 +1,361 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Andrew Tridgell 1992-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996 - 1999
+ Copyright (C) Tim Potter 2000,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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/* Display server query info */
+
+static char *get_server_type_str(uint32 type)
+{
+ static fstring typestr;
+ int i;
+
+ if (type == SV_TYPE_ALL) {
+ fstrcpy(typestr, "All");
+ return typestr;
+ }
+
+ typestr[0] = 0;
+
+ for (i = 0; i < 32; i++) {
+ if (type & (1 << i)) {
+ switch (1 << i) {
+ case SV_TYPE_WORKSTATION:
+ fstrcat(typestr, "Wk ");
+ break;
+ case SV_TYPE_SERVER:
+ fstrcat(typestr, "Sv ");
+ break;
+ case SV_TYPE_SQLSERVER:
+ fstrcat(typestr, "Sql ");
+ break;
+ case SV_TYPE_DOMAIN_CTRL:
+ fstrcat(typestr, "PDC ");
+ break;
+ case SV_TYPE_DOMAIN_BAKCTRL:
+ fstrcat(typestr, "BDC ");
+ break;
+ case SV_TYPE_TIME_SOURCE:
+ fstrcat(typestr, "Tim ");
+ break;
+ case SV_TYPE_AFP:
+ fstrcat(typestr, "AFP ");
+ break;
+ case SV_TYPE_NOVELL:
+ fstrcat(typestr, "Nov ");
+ break;
+ case SV_TYPE_DOMAIN_MEMBER:
+ fstrcat(typestr, "Dom ");
+ break;
+ case SV_TYPE_PRINTQ_SERVER:
+ fstrcat(typestr, "PrQ ");
+ break;
+ case SV_TYPE_DIALIN_SERVER:
+ fstrcat(typestr, "Din ");
+ break;
+ case SV_TYPE_SERVER_UNIX:
+ fstrcat(typestr, "Unx ");
+ break;
+ case SV_TYPE_NT:
+ fstrcat(typestr, "NT ");
+ break;
+ case SV_TYPE_WFW:
+ fstrcat(typestr, "Wfw ");
+ break;
+ case SV_TYPE_SERVER_MFPN:
+ fstrcat(typestr, "Mfp ");
+ break;
+ case SV_TYPE_SERVER_NT:
+ fstrcat(typestr, "SNT ");
+ break;
+ case SV_TYPE_POTENTIAL_BROWSER:
+ fstrcat(typestr, "PtB ");
+ break;
+ case SV_TYPE_BACKUP_BROWSER:
+ fstrcat(typestr, "BMB ");
+ break;
+ case SV_TYPE_MASTER_BROWSER:
+ fstrcat(typestr, "LMB ");
+ break;
+ case SV_TYPE_DOMAIN_MASTER:
+ fstrcat(typestr, "DMB ");
+ break;
+ case SV_TYPE_SERVER_OSF:
+ fstrcat(typestr, "OSF ");
+ break;
+ case SV_TYPE_SERVER_VMS:
+ fstrcat(typestr, "VMS ");
+ break;
+ case SV_TYPE_WIN95_PLUS:
+ fstrcat(typestr, "W95 ");
+ break;
+ case SV_TYPE_ALTERNATE_XPORT:
+ fstrcat(typestr, "Xpt ");
+ break;
+ case SV_TYPE_LOCAL_LIST_ONLY:
+ fstrcat(typestr, "Dom ");
+ break;
+ case SV_TYPE_DOMAIN_ENUM:
+ fstrcat(typestr, "Loc ");
+ break;
+ }
+ }
+ }
+
+ i = strlen(typestr) - 1;
+
+ if (typestr[i] == ' ')
+ typestr[i] = 0;
+
+ return typestr;
+}
+
+static void display_server(char *sname, uint32 type, const char *comment)
+{
+ printf("\t%-15.15s%-20s %s\n", sname, get_server_type_str(type),
+ comment);
+}
+
+static void display_srv_info_101(SRV_INFO_101 *sv101)
+{
+ fstring name;
+ fstring comment;
+
+ unistr2_to_ascii(name, &sv101->uni_name, sizeof(name) - 1);
+ unistr2_to_ascii(comment, &sv101->uni_comment, sizeof(comment) - 1);
+
+ display_server(name, sv101->srv_type, comment);
+
+ printf("\tplatform_id :\t%d\n", sv101->platform_id);
+ printf("\tos version :\t%d.%d\n", sv101->ver_major,
+ sv101->ver_minor);
+
+ printf("\tserver type :\t0x%x\n", sv101->srv_type);
+}
+
+static void display_srv_info_102(SRV_INFO_102 *sv102)
+{
+ fstring name;
+ fstring comment;
+ fstring usr_path;
+
+ unistr2_to_ascii(name, &sv102->uni_name, sizeof(name) - 1);
+ unistr2_to_ascii(comment, &sv102->uni_comment, sizeof(comment) - 1);
+ unistr2_to_ascii(usr_path, &sv102->uni_usr_path, sizeof(usr_path) - 1);
+
+ display_server(name, sv102->srv_type, comment);
+
+ printf("\tplatform_id :\t%d\n", sv102->platform_id);
+ printf("\tos version :\t%d.%d\n", sv102->ver_major,
+ sv102->ver_minor);
+
+ printf("\tusers :\t%x\n", sv102->users);
+ printf("\tdisc, hidden :\t%x, %x\n", sv102->disc, sv102->hidden);
+ printf("\tannounce, delta :\t%d, %d\n", sv102->announce,
+ sv102->ann_delta);
+ printf("\tlicenses :\t%d\n", sv102->licenses);
+ printf("\tuser path :\t%s\n", usr_path);
+}
+
+/* Server query info */
+static NTSTATUS cmd_srvsvc_srv_query_info(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 101;
+ SRV_INFO_CTR ctr;
+ WERROR result;
+
+ if (argc > 2) {
+ printf("Usage: %s [infolevel]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ result = cli_srvsvc_net_srv_get_info(cli, mem_ctx, info_level,
+ &ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ switch (info_level) {
+ case 101:
+ display_srv_info_101(&ctr.srv.sv101);
+ break;
+ case 102:
+ display_srv_info_102(&ctr.srv.sv102);
+ break;
+ default:
+ printf("unsupported info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
+{
+ fstring netname = "", remark = "";
+
+ rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
+
+ printf("netname: %s\n", netname);
+ printf("\tremark:\t%s\n", remark);
+}
+
+static void display_share_info_2(SRV_SHARE_INFO_2 *info2)
+{
+ fstring netname = "", remark = "", path = "", passwd = "";
+
+ rpcstr_pull_unistr2_fstring(netname, &info2->info_2_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(remark, &info2->info_2_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(path, &info2->info_2_str.uni_path);
+ rpcstr_pull_unistr2_fstring(passwd, &info2->info_2_str.uni_passwd);
+
+ printf("netname: %s\n", netname);
+ printf("\tremark:\t%s\n", remark);
+ printf("\tpath:\t%s\n", path);
+ printf("\tpassword:\t%s\n", passwd);
+}
+
+static NTSTATUS cmd_srvsvc_net_share_enum(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 2;
+ SRV_SHARE_INFO_CTR ctr;
+ WERROR result;
+ ENUM_HND hnd;
+ uint32 preferred_len = 0xffffffff, i;
+
+ if (argc > 2) {
+ printf("Usage: %s [infolevel]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(
+ cli, mem_ctx, info_level, &ctr, preferred_len, &hnd);
+
+ if (!W_ERROR_IS_OK(result) || !ctr.num_entries)
+ goto done;
+
+ /* Display results */
+
+ switch (info_level) {
+ case 1:
+ for (i = 0; i < ctr.num_entries; i++)
+ display_share_info_1(&ctr.share.info1[i]);
+ break;
+ case 2:
+ for (i = 0; i < ctr.num_entries; i++)
+ display_share_info_2(&ctr.share.info2[i]);
+ break;
+ default:
+ printf("unsupported info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_srvsvc_net_remote_tod(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ TIME_OF_DAY_INFO tod;
+ WERROR result;
+
+ if (argc > 1) {
+ printf("Usage: %s\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_srvsvc_net_remote_tod(
+ cli, mem_ctx, cli->srv_name_slash, &tod);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS cmd_srvsvc_net_file_enum(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 3;
+ SRV_FILE_INFO_CTR ctr;
+ WERROR result;
+ ENUM_HND hnd;
+ uint32 preferred_len = 0;
+
+ if (argc > 2) {
+ printf("Usage: %s [infolevel]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ init_enum_hnd(&hnd, 0);
+
+ ZERO_STRUCT(ctr);
+
+ result = cli_srvsvc_net_file_enum(
+ cli, mem_ctx, info_level, NULL, &ctr, preferred_len, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set srvsvc_commands[] = {
+
+ { "SRVSVC" },
+
+ { "srvinfo", cmd_srvsvc_srv_query_info, PI_SRVSVC, "Server query info", "" },
+ { "netshareenum", cmd_srvsvc_net_share_enum, PI_SRVSVC, "Enumerate shares", "" },
+ { "netfileenum", cmd_srvsvc_net_file_enum, PI_SRVSVC, "Enumerate open files", "" },
+ { "netremotetod", cmd_srvsvc_net_remote_tod, PI_SRVSVC, "Fetch remote time of day", "" },
+
+ { NULL }
+};
diff --git a/source4/rpcclient/cmd_wkssvc.c b/source4/rpcclient/cmd_wkssvc.c
new file mode 100644
index 0000000000..bb118234c0
--- /dev/null
+++ b/source4/rpcclient/cmd_wkssvc.c
@@ -0,0 +1,84 @@
+/*
+ Unix SMB/CIFS implementation.
+ NT Domain Authentication SMB / MSRPC client
+ Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+workstation get info query
+****************************************************************************/
+void cmd_wks_query_info(struct client_info *info)
+{
+ fstring dest_wks;
+ fstring tmp;
+ WKS_INFO_100 ctr;
+ uint32 info_level = 100;
+
+ BOOL res = True;
+
+ memset((char *)&ctr, '\0', sizeof(ctr));
+
+ fstrcpy(dest_wks, "\\\\");
+ fstrcat(dest_wks, info->dest_host);
+ strupper(dest_wks);
+
+ if (next_token_nr(NULL, tmp, NULL, sizeof(tmp)))
+ {
+ info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+ }
+
+ DEBUG(4,("cmd_wks_query_info: server:%s info level: %d\n",
+ dest_wks, info_level));
+
+ DEBUG(5, ("cmd_wks_query_info: smb_cli->fd:%d\n", smb_cli->fd));
+
+ /* open LSARPC session. */
+ res = res ? cli_nt_session_open(smb_cli, PI_WKSSVC) : False;
+
+ /* send info level: receive requested info. hopefully. */
+ res = res ? do_wks_query_info(smb_cli,
+ dest_wks, info_level, &ctr) : False;
+
+ /* close the session */
+ cli_nt_session_close(smb_cli);
+
+ if (res)
+ {
+ DEBUG(5,("cmd_wks_query_info: query succeeded\n"));
+
+#if 0
+ display_wks_info_100(out_hnd, ACTION_HEADER , &ctr);
+ display_wks_info_100(out_hnd, ACTION_ENUMERATE, &ctr);
+ display_wks_info_100(out_hnd, ACTION_FOOTER , &ctr);
+#endif
+
+ }
+ else
+ {
+ DEBUG(5,("cmd_wks_query_info: query failed\n"));
+ }
+}
diff --git a/source4/rpcclient/display_sec.c b/source4/rpcclient/display_sec.c
new file mode 100644
index 0000000000..2a93c915f1
--- /dev/null
+++ b/source4/rpcclient/display_sec.c
@@ -0,0 +1,144 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Andrew Tridgell 1992-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996 - 1999
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/****************************************************************************
+convert a security permissions into a string
+****************************************************************************/
+char *get_sec_mask_str(uint32 type)
+{
+ static fstring typestr="";
+
+ typestr[0] = 0;
+
+ if (type & GENERIC_ALL_ACCESS)
+ fstrcat(typestr, "Generic all access ");
+ if (type & GENERIC_EXECUTE_ACCESS)
+ fstrcat(typestr, "Generic execute access ");
+ if (type & GENERIC_WRITE_ACCESS)
+ fstrcat(typestr, "Generic write access ");
+ if (type & GENERIC_READ_ACCESS)
+ fstrcat(typestr, "Generic read access ");
+ if (type & MAXIMUM_ALLOWED_ACCESS)
+ fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
+ if (type & SYSTEM_SECURITY_ACCESS)
+ fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
+ if (type & SYNCHRONIZE_ACCESS)
+ fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
+ if (type & WRITE_OWNER_ACCESS)
+ fstrcat(typestr, "WRITE_OWNER_ACCESS ");
+ if (type & WRITE_DAC_ACCESS)
+ fstrcat(typestr, "WRITE_DAC_ACCESS ");
+ if (type & READ_CONTROL_ACCESS)
+ fstrcat(typestr, "READ_CONTROL_ACCESS ");
+ if (type & DELETE_ACCESS)
+ fstrcat(typestr, "DELETE_ACCESS ");
+
+ printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
+
+ return typestr;
+}
+
+/****************************************************************************
+ display sec_access structure
+ ****************************************************************************/
+void display_sec_access(SEC_ACCESS *info)
+{
+ printf("\t\tPermissions: 0x%x: %s\n", info->mask, get_sec_mask_str(info->mask));
+}
+
+/****************************************************************************
+ display sec_ace structure
+ ****************************************************************************/
+void display_sec_ace(SEC_ACE *ace)
+{
+ fstring sid_str;
+
+ printf("\tACE\n\t\ttype: ");
+ switch (ace->type) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED:
+ printf("ACCESS ALLOWED");
+ break;
+ case SEC_ACE_TYPE_ACCESS_DENIED:
+ printf("ACCESS DENIED");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_AUDIT:
+ printf("SYSTEM AUDIT");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_ALARM:
+ printf("SYSTEM ALARM");
+ break;
+ default:
+ printf("????");
+ break;
+ }
+ printf(" (%d) flags: %d\n", ace->type, ace->flags);
+ display_sec_access(&ace->info);
+ sid_to_string(sid_str, &ace->trustee);
+ printf("\t\tSID: %s\n\n", sid_str);
+}
+
+/****************************************************************************
+ display sec_acl structure
+ ****************************************************************************/
+void display_sec_acl(SEC_ACL *sec_acl)
+{
+ int i;
+
+ printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
+ sec_acl->num_aces, sec_acl->revision);
+ printf("\t---\n");
+
+ if (sec_acl->size != 0 && sec_acl->num_aces != 0)
+ for (i = 0; i < sec_acl->num_aces; i++)
+ display_sec_ace(&sec_acl->ace[i]);
+
+}
+
+/****************************************************************************
+ display sec_desc structure
+ ****************************************************************************/
+void display_sec_desc(SEC_DESC *sec)
+{
+ fstring sid_str;
+
+ if (sec->sacl) {
+ printf("SACL\n");
+ display_sec_acl(sec->sacl);
+ }
+
+ if (sec->dacl) {
+ printf("DACL\n");
+ display_sec_acl(sec->dacl);
+ }
+
+ if (sec->owner_sid) {
+ sid_to_string(sid_str, sec->owner_sid);
+ printf("\tOwner SID:\t%s\n", sid_str);
+ }
+
+ if (sec->grp_sid) {
+ sid_to_string(sid_str, sec->grp_sid);
+ printf("\tParent SID:\t%s\n", sid_str);
+ }
+}
diff --git a/source4/rpcclient/rpcclient.c b/source4/rpcclient/rpcclient.c
new file mode 100644
index 0000000000..c9d8cd96f3
--- /dev/null
+++ b/source4/rpcclient/rpcclient.c
@@ -0,0 +1,756 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000-2001
+ Copyright (C) Martin Pool 2003
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+DOM_SID domain_sid;
+
+
+/* List to hold groups of commands.
+ *
+ * Commands are defined in a list of arrays: arrays are easy to
+ * statically declare, and lists are easier to dynamically extend.
+ */
+
+static struct cmd_list {
+ struct cmd_list *prev, *next;
+ struct cmd_set *cmd_set;
+} *cmd_list;
+
+/****************************************************************************
+handle completion of commands for readline
+****************************************************************************/
+static char **completion_fn(char *text, int start, int end)
+{
+#define MAX_COMPLETIONS 100
+ char **matches;
+ int i, count=0;
+ struct cmd_list *commands = cmd_list;
+
+#if 0 /* JERRY */
+ /* FIXME!!! -- what to do when completing argument? */
+ /* for words not at the start of the line fallback
+ to filename completion */
+ if (start)
+ return NULL;
+#endif
+
+ /* make sure we have a list of valid commands */
+ if (!commands)
+ return NULL;
+
+ matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+ if (!matches) return NULL;
+
+ matches[count++] = strdup(text);
+ if (!matches[0]) return NULL;
+
+ while (commands && count < MAX_COMPLETIONS-1)
+ {
+ if (!commands->cmd_set)
+ break;
+
+ for (i=0; commands->cmd_set[i].name; i++)
+ {
+ if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
+ commands->cmd_set[i].fn)
+ {
+ matches[count] = strdup(commands->cmd_set[i].name);
+ if (!matches[count])
+ return NULL;
+ count++;
+ }
+ }
+
+ commands = commands->next;
+
+ }
+
+ if (count == 2) {
+ SAFE_FREE(matches[0]);
+ matches[0] = strdup(matches[1]);
+ }
+ matches[count] = NULL;
+ return matches;
+}
+
+/***********************************************************************
+ * read in username/password credentials from a file
+ */
+static void read_authfile (
+ char *filename,
+ char* username,
+ char* password,
+ char* domain
+)
+{
+ FILE *auth;
+ fstring buf;
+ uint16 len = 0;
+ char *ptr, *val, *param;
+
+ if ((auth=sys_fopen(filename, "r")) == NULL)
+ {
+ printf ("ERROR: Unable to open credentials file!\n");
+ return;
+ }
+
+ while (!feof(auth))
+ {
+ /* get a line from the file */
+ if (!fgets (buf, sizeof(buf), auth))
+ continue;
+
+ len = strlen(buf);
+
+ /* skip empty lines */
+ if ((len) && (buf[len-1]=='\n'))
+ {
+ buf[len-1] = '\0';
+ len--;
+ }
+ if (len == 0)
+ continue;
+
+ /* break up the line into parameter & value.
+ will need to eat a little whitespace possibly */
+ param = buf;
+ if (!(ptr = strchr_m(buf, '=')))
+ continue;
+ val = ptr+1;
+ *ptr = '\0';
+
+ /* eat leading white space */
+ while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
+ val++;
+
+ if (strwicmp("password", param) == 0)
+ fstrcpy (password, val);
+ else if (strwicmp("username", param) == 0)
+ fstrcpy (username, val);
+ else if (strwicmp("domain", param) == 0)
+ fstrcpy (domain, val);
+
+ memset(buf, 0, sizeof(buf));
+ }
+ fclose(auth);
+
+ return;
+}
+
+static char* next_command (char** cmdstr)
+{
+ static pstring command;
+ char *p;
+
+ if (!cmdstr || !(*cmdstr))
+ return NULL;
+
+ p = strchr_m(*cmdstr, ';');
+ if (p)
+ *p = '\0';
+ pstrcpy(command, *cmdstr);
+ if (p)
+ *cmdstr = p + 1;
+ else
+ *cmdstr = NULL;
+
+ return command;
+}
+
+
+/**
+ * Find default username from environment variables.
+ *
+ * @param username fstring to receive username; not touched if none is
+ * known.
+ **/
+static void get_username (char *username)
+{
+ if (getenv("USER"))
+ fstrcpy(username,getenv("USER"));
+
+ if (*username == 0 && getenv("LOGNAME"))
+ fstrcpy(username,getenv("LOGNAME"));
+
+ if (*username == 0) {
+ fstrcpy(username,"GUEST");
+ }
+
+ return;
+}
+
+/* Fetch the SID for this computer */
+
+static void fetch_machine_sid(struct cli_state *cli)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_OK;
+ uint32 info_class = 5;
+ fstring domain_name;
+ static BOOL got_domain_sid;
+ TALLOC_CTX *mem_ctx;
+
+ if (got_domain_sid) return;
+
+ if (!(mem_ctx=talloc_init("fetch_machine_sid")))
+ {
+ DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
+ goto error;
+ }
+
+
+ if (!cli_nt_session_open (cli, PI_LSARPC)) {
+ fprintf(stderr, "could not initialise lsa pipe\n");
+ goto error;
+ }
+
+ result = cli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
+ domain_name, &domain_sid);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ got_domain_sid = True;
+
+ cli_lsa_close(cli, mem_ctx, &pol);
+ cli_nt_session_close(cli);
+ talloc_destroy(mem_ctx);
+
+ return;
+
+ error:
+ fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "error: %s\n", nt_errstr(result));
+ }
+
+ exit(1);
+}
+
+/* List the available commands on a given pipe */
+
+static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct cmd_list *tmp;
+ struct cmd_set *tmp_set;
+ int i;
+
+ /* Usage */
+
+ if (argc != 2) {
+ printf("Usage: %s <pipe>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Help on one command */
+
+ for (tmp = cmd_list; tmp; tmp = tmp->next)
+ {
+ tmp_set = tmp->cmd_set;
+
+ if (!StrCaseCmp(argv[1], tmp_set->name))
+ {
+ printf("Available commands on the %s pipe:\n\n", tmp_set->name);
+
+ i = 0;
+ tmp_set++;
+ while(tmp_set->name) {
+ printf("%20s", tmp_set->name);
+ tmp_set++;
+ i++;
+ if (i%4 == 0)
+ printf("\n");
+ }
+
+ /* drop out of the loop */
+ break;
+ }
+ }
+ printf("\n\n");
+
+ return NT_STATUS_OK;
+}
+
+/* Display help on commands */
+
+static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct cmd_list *tmp;
+ struct cmd_set *tmp_set;
+
+ /* Usage */
+
+ if (argc > 2) {
+ printf("Usage: %s [command]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Help on one command */
+
+ if (argc == 2) {
+ for (tmp = cmd_list; tmp; tmp = tmp->next) {
+
+ tmp_set = tmp->cmd_set;
+
+ while(tmp_set->name) {
+ if (strequal(argv[1], tmp_set->name)) {
+ if (tmp_set->usage &&
+ tmp_set->usage[0])
+ printf("%s\n", tmp_set->usage);
+ else
+ printf("No help for %s\n", tmp_set->name);
+
+ return NT_STATUS_OK;
+ }
+
+ tmp_set++;
+ }
+ }
+
+ printf("No such command: %s\n", argv[1]);
+ return NT_STATUS_OK;
+ }
+
+ /* List all commands */
+
+ for (tmp = cmd_list; tmp; tmp = tmp->next) {
+
+ tmp_set = tmp->cmd_set;
+
+ while(tmp_set->name) {
+
+ printf("%15s\t\t%s\n", tmp_set->name,
+ tmp_set->description ? tmp_set->description:
+ "");
+
+ tmp_set++;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/* Change the debug level */
+
+static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ if (argc > 2) {
+ printf("Usage: %s [debuglevel]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2) {
+ DEBUGLEVEL = atoi(argv[1]);
+ }
+
+ printf("debuglevel is %d\n", DEBUGLEVEL);
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ exit(0);
+ return NT_STATUS_OK; /* NOTREACHED */
+}
+
+/* Built in rpcclient commands */
+
+static struct cmd_set rpcclient_commands[] = {
+
+ { "GENERAL OPTIONS" },
+
+ { "help", cmd_help, -1, "Get help on commands", "[command]" },
+ { "?", cmd_help, -1, "Get help on commands", "[command]" },
+ { "debuglevel", cmd_debuglevel, -1, "Set debug level", "level" },
+ { "list", cmd_listcommands, -1, "List available commands on <pipe>", "pipe" },
+ { "exit", cmd_quit, -1, "Exit program", "" },
+ { "quit", cmd_quit, -1, "Exit program", "" },
+
+ { NULL }
+};
+
+static struct cmd_set separator_command[] = {
+ { "---------------", NULL, -1, "----------------------" },
+ { NULL }
+};
+
+
+/* Various pipe commands */
+
+extern struct cmd_set lsarpc_commands[];
+extern struct cmd_set samr_commands[];
+extern struct cmd_set spoolss_commands[];
+extern struct cmd_set netlogon_commands[];
+extern struct cmd_set srvsvc_commands[];
+extern struct cmd_set dfs_commands[];
+extern struct cmd_set reg_commands[];
+extern struct cmd_set ds_commands[];
+
+static struct cmd_set *rpcclient_command_list[] = {
+ rpcclient_commands,
+ lsarpc_commands,
+ ds_commands,
+ samr_commands,
+ spoolss_commands,
+ netlogon_commands,
+ srvsvc_commands,
+ dfs_commands,
+ reg_commands,
+ NULL
+};
+
+static void add_command_set(struct cmd_set *cmd_set)
+{
+ struct cmd_list *entry;
+
+ if (!(entry = (struct cmd_list *)malloc(sizeof(struct cmd_list)))) {
+ DEBUG(0, ("out of memory\n"));
+ return;
+ }
+
+ ZERO_STRUCTP(entry);
+
+ entry->cmd_set = cmd_set;
+ DLIST_ADD(cmd_list, entry);
+}
+
+
+/**
+ * Call an rpcclient function, passing an argv array.
+ *
+ * @param cmd Command to run, as a single string.
+ **/
+static NTSTATUS do_cmd(struct cli_state *cli,
+ struct cmd_set *cmd_entry,
+ int argc, char **argv)
+{
+ NTSTATUS result;
+
+ TALLOC_CTX *mem_ctx;
+
+ /* Create mem_ctx */
+
+ if (!(mem_ctx = talloc_init("do_cmd"))) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Open pipe */
+
+ if (cmd_entry->pipe_idx != -1)
+ if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
+ DEBUG(0, ("Could not initialize pipe\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Run command */
+
+ result = cmd_entry->fn(cli, mem_ctx, argc, (const char **) argv);
+
+ /* Cleanup */
+
+ if (cmd_entry->pipe_idx != -1)
+ cli_nt_session_close(cli);
+
+ talloc_destroy(mem_ctx);
+
+ return result;
+}
+
+
+/**
+ * Process a command entered at the prompt or as part of -c
+ *
+ * @returns The NTSTATUS from running the command.
+ **/
+static NTSTATUS process_cmd(struct cli_state *cli, char *cmd)
+{
+ struct cmd_list *temp_list;
+ NTSTATUS result = NT_STATUS_OK;
+ int ret;
+ int argc;
+ char **argv = NULL;
+
+ if ((ret = poptParseArgvString(cmd, &argc, (const char ***) &argv)) != 0) {
+ fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+
+ /* Walk through a dlist of arrays of commands. */
+ for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
+ struct cmd_set *temp_set = temp_list->cmd_set;
+
+ while (temp_set->name) {
+ if (strequal(argv[0], temp_set->name)) {
+ if (!temp_set->fn) {
+ fprintf (stderr, "Invalid command\n");
+ goto out_free;
+ }
+
+ result = do_cmd(cli, temp_set, argc, argv);
+
+ goto out_free;
+ }
+ temp_set++;
+ }
+ }
+
+ if (argv[0]) {
+ printf("command not found: %s\n", argv[0]);
+ }
+
+out_free:
+ if (!NT_STATUS_IS_OK(result)) {
+ printf("result was %s\n", nt_errstr(result));
+ }
+
+ if (argv) {
+ /* NOTE: popt allocates the whole argv, including the
+ * strings, as a single block. So a single free is
+ * enough to release it -- we don't free the
+ * individual strings. rtfm. */
+ free(argv);
+ }
+
+ return result;
+}
+
+
+/* Main function */
+
+ int main(int argc, char *argv[])
+{
+ static int got_pass = 0;
+ BOOL interactive = True;
+ int opt;
+ static char *cmdstr = "";
+ const char *server;
+ struct cli_state *cli;
+ fstring password="",
+ username="",
+ domain="";
+ static char *opt_authfile=NULL,
+ *opt_username=NULL,
+ *opt_domain=NULL,
+ *opt_logfile=NULL,
+ *opt_ipaddr=NULL;
+ pstring logfile;
+ struct cmd_set **cmd_set;
+ struct in_addr server_ip;
+ NTSTATUS nt_status;
+
+ /* make sure the vars that get altered (4th field) are in
+ a fixed location or certain compilers complain */
+ poptContext pc;
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"authfile", 'A', POPT_ARG_STRING, &opt_authfile, 'A', "File containing user credentials", "AUTHFILE"},
+ {"nopass", 'N', POPT_ARG_NONE, &got_pass, 'N', "Don't ask for a password"},
+ {"user", 'U', POPT_ARG_STRING, &opt_username, 'U', "Set the network username", "USER"},
+ {"workgroup", 'W', POPT_ARG_STRING, &opt_domain, 'W', "Set the domain name for user account", "DOMAIN"},
+ {"command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
+ {"logfile", 'l', POPT_ARG_STRING, &opt_logfile, 'l', "Logfile to use instead of stdout", "LOGFILE" },
+ {"dest-ip", 'I', POPT_ARG_STRING, &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
+ { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
+ { NULL }
+ };
+
+ setlinebuf(stdout);
+
+ /* Parse options */
+
+ pc = poptGetContext("rpcclient", argc, (const char **) argv,
+ long_options, 0);
+
+ if (argc == 1) {
+ poptPrintHelp(pc, stderr, 0);
+ return 0;
+ }
+
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'A':
+ /* only get the username, password, and domain from the file */
+ read_authfile (opt_authfile, username, password, domain);
+ if (strlen (password))
+ got_pass = 1;
+ break;
+
+ case 'l':
+ slprintf(logfile, sizeof(logfile) - 1, "%s.client",
+ opt_logfile);
+ lp_set_logfile(logfile);
+ interactive = False;
+ break;
+
+ case 'U': {
+ char *lp;
+
+ fstrcpy(username,opt_username);
+
+ if ((lp=strchr_m(username,'%'))) {
+ *lp = 0;
+ fstrcpy(password,lp+1);
+ got_pass = 1;
+ memset(strchr_m(opt_username,'%') + 1, 'X',
+ strlen(password));
+ }
+ break;
+ }
+ case 'I':
+ if ( (server_ip.s_addr=inet_addr(opt_ipaddr)) == INADDR_NONE ) {
+ fprintf(stderr, "%s not a valid IP address\n",
+ opt_ipaddr);
+ return 1;
+ }
+ case 'W':
+ fstrcpy(domain, opt_domain);
+ break;
+ }
+ }
+
+ /* Get server as remaining unparsed argument. Print usage if more
+ than one unparsed argument is present. */
+
+ server = poptGetArg(pc);
+
+ if (!server || poptGetArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ return 1;
+ }
+
+ poptFreeContext(pc);
+
+ /* the following functions are part of the Samba debugging
+ facilities. See lib/debug.c */
+ setup_logging("rpcclient", interactive);
+ if (!interactive)
+ reopen_logs();
+
+ /* Load smb.conf file */
+
+ if (!lp_load(dyn_CONFIGFILE,True,False,False))
+ fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
+
+ load_interfaces();
+
+ if (!init_names())
+ return 1;
+
+ /* Resolve the IP address */
+
+ if (!opt_ipaddr && !resolve_name(server, &server_ip, 0x20)) {
+ fprintf(stderr, "Unable to resolve %s\n", server);
+ return 1;
+ }
+
+ /*
+ * Get password
+ * from stdin if necessary
+ */
+
+ if (!got_pass) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ fstrcpy(password, pass);
+ }
+ }
+
+ if (!strlen(username) && !got_pass)
+ get_username(username);
+
+ nt_status = cli_full_connection(&cli, lp_netbios_name(), server,
+ &server_ip, 0,
+ "IPC$", "IPC",
+ username, domain,
+ password, 0, NULL);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("Cannot connect to server. Error was %s\n", nt_errstr(nt_status)));
+ return 1;
+ }
+
+ memset(password,'X',sizeof(password));
+
+ /* Load command lists */
+
+ cmd_set = rpcclient_command_list;
+
+ while(*cmd_set) {
+ add_command_set(*cmd_set);
+ add_command_set(separator_command);
+ cmd_set++;
+ }
+
+ fetch_machine_sid(cli);
+
+ /* Do anything specified with -c */
+ if (cmdstr[0]) {
+ char *cmd;
+ char *p = cmdstr;
+
+ while((cmd=next_command(&p)) != NULL) {
+ process_cmd(cli, cmd);
+ }
+
+ cli_shutdown(cli);
+ return 0;
+ }
+
+ /* Loop around accepting commands */
+
+ while(1) {
+ pstring prompt;
+ char *line;
+
+ slprintf(prompt, sizeof(prompt) - 1, "rpcclient $> ");
+
+ line = smb_readline(prompt, NULL, completion_fn);
+
+ if (line == NULL)
+ break;
+
+ if (line[0] != '\n')
+ process_cmd(cli, line);
+ }
+
+ cli_shutdown(cli);
+ return 0;
+}
diff --git a/source4/rpcclient/rpcclient.h b/source4/rpcclient/rpcclient.h
new file mode 100644
index 0000000000..1bd3c1a641
--- /dev/null
+++ b/source4/rpcclient/rpcclient.h
@@ -0,0 +1,34 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef RPCCLIENT_H
+#define RPCCLIENT_H
+
+struct cmd_set {
+ const char *name;
+ NTSTATUS (*fn)(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc,
+ const char **argv);
+ int pipe_idx;
+ const char *description;
+ const char *usage;
+};
+
+#endif /* RPCCLIENT_H */