summaryrefslogtreecommitdiff
path: root/source3/rpcclient
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpcclient')
-rw-r--r--source3/rpcclient/cmd_dfs.c329
-rw-r--r--source3/rpcclient/cmd_drsuapi.c566
-rw-r--r--source3/rpcclient/cmd_dssetup.c69
-rw-r--r--source3/rpcclient/cmd_echo.c184
-rw-r--r--source3/rpcclient/cmd_lsarpc.c1395
-rw-r--r--source3/rpcclient/cmd_netlogon.c1034
-rw-r--r--source3/rpcclient/cmd_ntsvcs.c229
-rw-r--r--source3/rpcclient/cmd_samr.c2763
-rw-r--r--source3/rpcclient/cmd_shutdown.c117
-rw-r--r--source3/rpcclient/cmd_spoolss.c2782
-rw-r--r--source3/rpcclient/cmd_srvsvc.c891
-rw-r--r--source3/rpcclient/cmd_test.c75
-rw-r--r--source3/rpcclient/cmd_wkssvc.c170
-rw-r--r--source3/rpcclient/rpcclient.c959
-rw-r--r--source3/rpcclient/rpcclient.h42
15 files changed, 11605 insertions, 0 deletions
diff --git a/source3/rpcclient/cmd_dfs.c b/source3/rpcclient/cmd_dfs.c
new file mode 100644
index 0000000000..d55261bea3
--- /dev/null
+++ b/source3/rpcclient/cmd_dfs.c
@@ -0,0 +1,329 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jelmer Vernooij 2005.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/* Check DFS is supported by the remote server */
+
+static WERROR cmd_dfs_version(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ enum dfs_ManagerVersion version;
+ NTSTATUS result;
+
+ if (argc != 1) {
+ printf("Usage: %s\n", argv[0]);
+ return WERR_OK;
+ }
+
+ result = rpccli_dfs_GetManagerVersion(cli, mem_ctx, &version);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ return ntstatus_to_werror(result);
+ }
+
+ if (version > 0) {
+ printf("dfs is present (%d)\n", version);
+ } else {
+ printf("dfs is not present\n");
+ }
+
+ return WERR_OK;
+}
+
+static WERROR cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ WERROR werr;
+ const char *path, *servername, *sharename, *comment;
+ uint32 flags = 0;
+
+ if (argc != 5) {
+ printf("Usage: %s path servername sharename comment\n",
+ argv[0]);
+ return WERR_OK;
+ }
+
+ path = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+ comment = argv[4];
+
+ result = rpccli_dfs_Add(cli, mem_ctx, path, servername,
+ sharename, comment, flags, &werr);
+ if (!NT_STATUS_IS_OK(result)) {
+ return ntstatus_to_werror(result);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ WERROR werr;
+ const char *path, *servername, *sharename;
+
+ if (argc != 4) {
+ printf("Usage: %s path servername sharename\n", argv[0]);
+ return WERR_OK;
+ }
+
+ path = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+
+ result = rpccli_dfs_Remove(cli, mem_ctx, path, servername,
+ sharename, &werr);
+ if (!NT_STATUS_IS_OK(result)) {
+ return ntstatus_to_werror(result);
+ }
+
+ return werr;
+}
+
+/* Display a DFS_INFO_1 structure */
+
+static void display_dfs_info_1(struct dfs_Info1 *info1)
+{
+ printf("path: %s\n", info1->path);
+}
+
+/* Display a DFS_INFO_2 structure */
+
+static void display_dfs_info_2(struct dfs_Info2 *info2)
+{
+ printf("path: %s\n", info2->path);
+ printf("\tcomment: %s\n", info2->comment);
+
+ printf("\tstate: %d\n", info2->state);
+ printf("\tnum_stores: %d\n", info2->num_stores);
+}
+
+/* Display a DFS_INFO_3 structure */
+
+static void display_dfs_info_3(struct dfs_Info3 *info3)
+{
+ int i;
+
+ printf("path: %s\n", info3->path);
+
+ printf("\tcomment: %s\n", info3->comment);
+
+ printf("\tstate: %d\n", info3->state);
+ printf("\tnum_stores: %d\n", info3->num_stores);
+
+ for (i = 0; i < info3->num_stores; i++) {
+ struct dfs_StorageInfo *dsi = &info3->stores[i];
+
+ printf("\t\tstorage[%d] server: %s\n", i, dsi->server);
+
+ printf("\t\tstorage[%d] share: %s\n", i, dsi->share);
+ }
+}
+
+
+/* Display a DFS_INFO_CTR structure */
+static void display_dfs_info(uint32 level, union dfs_Info *ctr)
+{
+ switch (level) {
+ case 0x01:
+ display_dfs_info_1(ctr->info1);
+ break;
+ case 0x02:
+ display_dfs_info_2(ctr->info2);
+ break;
+ case 0x03:
+ display_dfs_info_3(ctr->info3);
+ break;
+ default:
+ printf("unsupported info level %d\n",
+ level);
+ break;
+ }
+}
+
+static void display_dfs_enumstruct(struct dfs_EnumStruct *ctr)
+{
+ int i;
+
+ /* count is always the first element, so we can just use info1 here */
+ for (i = 0; i < ctr->e.info1->count; i++) {
+ switch (ctr->level) {
+ case 1: display_dfs_info_1(&ctr->e.info1->s[i]); break;
+ case 2: display_dfs_info_2(&ctr->e.info2->s[i]); break;
+ case 3: display_dfs_info_3(&ctr->e.info3->s[i]); break;
+ default:
+ printf("unsupported info level %d\n",
+ ctr->level);
+ return;
+ }
+ }
+}
+
+/* Enumerate dfs shares */
+
+static WERROR cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct dfs_EnumStruct str;
+ struct dfs_EnumArray1 info1;
+ struct dfs_EnumArray2 info2;
+ struct dfs_EnumArray3 info3;
+ struct dfs_EnumArray4 info4;
+ struct dfs_EnumArray200 info200;
+ struct dfs_EnumArray300 info300;
+
+ NTSTATUS result;
+ WERROR werr;
+ uint32 total = 0;
+
+ if (argc > 2) {
+ printf("Usage: %s [info_level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ str.level = 1;
+ if (argc == 2)
+ str.level = atoi(argv[1]);
+
+ switch (str.level) {
+ case 1: str.e.info1 = &info1; ZERO_STRUCT(info1); break;
+ case 2: str.e.info2 = &info2; ZERO_STRUCT(info2); break;
+ case 3: str.e.info3 = &info3; ZERO_STRUCT(info3); break;
+ case 4: str.e.info4 = &info4; ZERO_STRUCT(info4); break;
+ case 200: str.e.info200 = &info200; ZERO_STRUCT(info200); break;
+ case 300: str.e.info300 = &info300; ZERO_STRUCT(info300); break;
+ default:
+ printf("Unknown info level %d\n", str.level);
+ break;
+ }
+
+ result = rpccli_dfs_Enum(cli, mem_ctx, str.level, 0xFFFFFFFF, &str,
+ &total, &werr);
+
+ if (NT_STATUS_IS_OK(result)) {
+ display_dfs_enumstruct(&str);
+ }
+
+ return werr;
+}
+
+/* Enumerate dfs shares */
+
+static WERROR cmd_dfs_enumex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct dfs_EnumStruct str;
+ struct dfs_EnumArray1 info1;
+ struct dfs_EnumArray2 info2;
+ struct dfs_EnumArray3 info3;
+ struct dfs_EnumArray4 info4;
+ struct dfs_EnumArray200 info200;
+ struct dfs_EnumArray300 info300;
+
+ NTSTATUS result;
+ WERROR werr;
+ uint32 total = 0;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s dfs_name [info_level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ str.level = 1;
+
+ if (argc == 3)
+ str.level = atoi(argv[2]);
+
+ switch (str.level) {
+ case 1: str.e.info1 = &info1; ZERO_STRUCT(info1); break;
+ case 2: str.e.info2 = &info2; ZERO_STRUCT(info2); break;
+ case 3: str.e.info3 = &info3; ZERO_STRUCT(info3); break;
+ case 4: str.e.info4 = &info4; ZERO_STRUCT(info4); break;
+ case 200: str.e.info200 = &info200; ZERO_STRUCT(info200); break;
+ case 300: str.e.info300 = &info300; ZERO_STRUCT(info300); break;
+ default:
+ printf("Unknown info level %d\n", str.level);
+ break;
+ }
+
+ result = rpccli_dfs_EnumEx(cli, mem_ctx, argv[1], str.level,
+ 0xFFFFFFFF, &str, &total, &werr);
+
+ if (NT_STATUS_IS_OK(result)) {
+ display_dfs_enumstruct(&str);
+ }
+
+ return werr;
+}
+
+
+static WERROR cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ WERROR werr;
+ const char *path, *servername, *sharename;
+ uint32 info_level = 1;
+ union dfs_Info ctr;
+
+ if (argc < 4 || argc > 5) {
+ printf("Usage: %s path servername sharename "
+ "[info_level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ path = argv[1];
+ servername = argv[2];
+ sharename = argv[3];
+
+ if (argc == 5)
+ info_level = atoi(argv[4]);
+
+ result = rpccli_dfs_GetInfo(cli, mem_ctx, path, servername,
+ sharename, info_level, &ctr, &werr);
+
+ if (NT_STATUS_IS_OK(result)) {
+ display_dfs_info(info_level, &ctr);
+ }
+
+ return werr;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set dfs_commands[] = {
+
+ { "DFS" },
+
+ { "dfsversion", RPC_RTYPE_WERROR, NULL, cmd_dfs_version, &ndr_table_netdfs.syntax_id, NULL, "Query DFS support", "" },
+ { "dfsadd", RPC_RTYPE_WERROR, NULL, cmd_dfs_add, &ndr_table_netdfs.syntax_id, NULL, "Add a DFS share", "" },
+ { "dfsremove", RPC_RTYPE_WERROR, NULL, cmd_dfs_remove, &ndr_table_netdfs.syntax_id, NULL, "Remove a DFS share", "" },
+ { "dfsgetinfo", RPC_RTYPE_WERROR, NULL, cmd_dfs_getinfo, &ndr_table_netdfs.syntax_id, NULL, "Query DFS share info", "" },
+ { "dfsenum", RPC_RTYPE_WERROR, NULL, cmd_dfs_enum, &ndr_table_netdfs.syntax_id, NULL, "Enumerate dfs shares", "" },
+ { "dfsenumex", RPC_RTYPE_WERROR, NULL, cmd_dfs_enumex, &ndr_table_netdfs.syntax_id, NULL, "Enumerate dfs shares", "" },
+
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_drsuapi.c b/source3/rpcclient/cmd_drsuapi.c
new file mode 100644
index 0000000000..71757f5ea3
--- /dev/null
+++ b/source3/rpcclient/cmd_drsuapi.c
@@ -0,0 +1,566 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Guenther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static WERROR cracknames(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ struct policy_handle *bind_handle,
+ enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
+ int argc,
+ const char **argv,
+ union drsuapi_DsNameCtr *ctr)
+{
+ NTSTATUS status;
+ WERROR werr;
+ int i;
+ int32_t level = 1;
+ union drsuapi_DsNameRequest req;
+ int32_t level_out;
+ struct drsuapi_DsNameString *names;
+
+ names = TALLOC_ZERO_ARRAY(mem_ctx, struct drsuapi_DsNameString, argc);
+ W_ERROR_HAVE_NO_MEMORY(names);
+
+ for (i=0; i<argc; i++) {
+ names[i].str = argv[i];
+ }
+
+ req.req1.codepage = 1252; /* german */
+ req.req1.language = 0x00000407; /* german */
+ req.req1.count = argc;
+ req.req1.names = names;
+ req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
+ req.req1.format_offered = format_offered;
+ req.req1.format_desired = format_desired;
+
+ status = rpccli_drsuapi_DsCrackNames(cli, mem_ctx,
+ bind_handle,
+ level,
+ &req,
+ &level_out,
+ ctr,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ return WERR_OK;
+}
+
+static WERROR cmd_drsuapi_cracknames(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ int i;
+
+ struct GUID bind_guid;
+ struct policy_handle bind_handle;
+
+ union drsuapi_DsNameCtr ctr;
+
+ if (argc < 2) {
+ printf("usage: %s name\n", argv[0]);
+ return WERR_OK;
+ }
+
+ GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
+
+ status = rpccli_drsuapi_DsBind(cli, mem_ctx,
+ &bind_guid,
+ NULL,
+ &bind_handle,
+ &werr);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ werr = cracknames(cli, mem_ctx,
+ &bind_handle,
+ DRSUAPI_DS_NAME_FORMAT_UKNOWN,
+ DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+ 1,
+ argv+1,
+ &ctr);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto out;
+ }
+
+ for (i=0; i < ctr.ctr1->count; i++) {
+ printf("status: %d\n",
+ ctr.ctr1->array[i].status);
+ printf("dns_domain_name: %s\n",
+ ctr.ctr1->array[i].dns_domain_name);
+ printf("result_name: %s\n",
+ ctr.ctr1->array[i].result_name);
+ }
+
+ out:
+ if (is_valid_policy_hnd(&bind_handle)) {
+ rpccli_drsuapi_DsUnbind(cli, mem_ctx, &bind_handle, &werr);
+ }
+
+ return werr;
+}
+
+static void display_domain_controller_info_01(struct drsuapi_DsGetDCConnection01 *r)
+{
+ printf("client_ip_address:\t%s\n", r->client_ip_address);
+ printf("unknown2:\t%d\n", r->unknown2);
+ printf("connection_time:\t%d\n", r->connection_time);
+ printf("unknown4:\t%d\n", r->unknown4);
+ printf("unknown5:\t%d\n", r->unknown5);
+ printf("unknown6:\t%d\n", r->unknown6);
+ printf("client_account:\t%s\n", r->client_account);
+}
+
+static void display_domain_controller_info_1(struct drsuapi_DsGetDCInfo1 *r)
+{
+ printf("netbios_name:\t%s\n", r->netbios_name);
+ printf("dns_name:\t%s\n", r->dns_name);
+ printf("site_name:\t%s\n", r->site_name);
+ printf("computer_dn:\t%s\n", r->computer_dn);
+ printf("server_dn:\t%s\n", r->server_dn);
+ printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
+ printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
+}
+
+static void display_domain_controller_info_2(struct drsuapi_DsGetDCInfo2 *r)
+{
+ printf("netbios_name:\t%s\n", r->netbios_name);
+ printf("dns_name:\t%s\n", r->dns_name);
+ printf("site_name:\t%s\n", r->site_name);
+ printf("site_dn:\t%s\n", r->site_dn);
+ printf("computer_dn:\t%s\n", r->computer_dn);
+ printf("server_dn:\t%s\n", r->server_dn);
+ printf("ntds_dn:\t%s\n", r->ntds_dn);
+ printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
+ printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
+ printf("is_gc:\t\t%s\n", r->is_gc ? "true" : "false");
+ printf("site_guid:\t%s\n", GUID_string(talloc_tos(), &r->site_guid));
+ printf("computer_guid:\t%s\n", GUID_string(talloc_tos(), &r->computer_guid));
+ printf("server_guid:\t%s\n", GUID_string(talloc_tos(), &r->server_guid));
+ printf("ntds_guid:\t%s\n", GUID_string(talloc_tos(), &r->ntds_guid));
+}
+
+static void display_domain_controller_info_3(struct drsuapi_DsGetDCInfo3 *r)
+{
+ printf("netbios_name:\t%s\n", r->netbios_name);
+ printf("dns_name:\t%s\n", r->dns_name);
+ printf("site_name:\t%s\n", r->site_name);
+ printf("site_dn:\t%s\n", r->site_dn);
+ printf("computer_dn:\t%s\n", r->computer_dn);
+ printf("server_dn:\t%s\n", r->server_dn);
+ printf("ntds_dn:\t%s\n", r->ntds_dn);
+ printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
+ printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
+ printf("is_gc:\t\t%s\n", r->is_gc ? "true" : "false");
+ printf("is_rodc:\t%s\n", r->is_rodc ? "true" : "false");
+ printf("site_guid:\t%s\n", GUID_string(talloc_tos(), &r->site_guid));
+ printf("computer_guid:\t%s\n", GUID_string(talloc_tos(), &r->computer_guid));
+ printf("server_guid:\t%s\n", GUID_string(talloc_tos(), &r->server_guid));
+ printf("ntds_guid:\t%s\n", GUID_string(talloc_tos(), &r->ntds_guid));
+}
+
+static void display_domain_controller_info(int32_t level,
+ union drsuapi_DsGetDCInfoCtr *ctr)
+{
+ int i;
+
+ switch (level) {
+ case DRSUAPI_DC_CONNECTION_CTR_01:
+ for (i=0; i<ctr->ctr01.count; i++) {
+ printf("----------\n");
+ display_domain_controller_info_01(&ctr->ctr01.array[i]);
+ }
+ break;
+ case DRSUAPI_DC_INFO_CTR_1:
+ for (i=0; i<ctr->ctr1.count; i++) {
+ printf("----------\n");
+ display_domain_controller_info_1(&ctr->ctr1.array[i]);
+ }
+ break;
+ case DRSUAPI_DC_INFO_CTR_2:
+ for (i=0; i<ctr->ctr2.count; i++) {
+ printf("----------\n");
+ display_domain_controller_info_2(&ctr->ctr2.array[i]);
+ }
+ break;
+ case DRSUAPI_DC_INFO_CTR_3:
+ for (i=0; i<ctr->ctr3.count; i++) {
+ printf("----------\n");
+ display_domain_controller_info_3(&ctr->ctr3.array[i]);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static WERROR cmd_drsuapi_getdcinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+
+ struct GUID bind_guid;
+ struct policy_handle bind_handle;
+
+ const char *domain = NULL;
+ int32_t level = 1;
+ int32_t level_out;
+ union drsuapi_DsGetDCInfoRequest req;
+ union drsuapi_DsGetDCInfoCtr ctr;
+
+ if (argc < 2) {
+ printf("usage: %s domain [level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ domain = argv[1];
+ if (argc >= 3) {
+ level = atoi(argv[2]);
+ }
+
+ GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
+
+ status = rpccli_drsuapi_DsBind(cli, mem_ctx,
+ &bind_guid,
+ NULL,
+ &bind_handle,
+ &werr);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ req.req1.domain_name = domain;
+ req.req1.level = level;
+
+ status = rpccli_drsuapi_DsGetDomainControllerInfo(cli, mem_ctx,
+ &bind_handle,
+ 1,
+ &req,
+ &level_out,
+ &ctr,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto out;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto out;
+ }
+
+ display_domain_controller_info(level_out, &ctr);
+ out:
+ if (is_valid_policy_hnd(&bind_handle)) {
+ rpccli_drsuapi_DsUnbind(cli, mem_ctx, &bind_handle, &werr);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle bind_handle;
+
+ struct GUID bind_guid;
+ struct drsuapi_DsBindInfoCtr bind_info;
+ struct drsuapi_DsBindInfo28 info28;
+
+ const char *nc_dn = NULL;
+
+ DATA_BLOB session_key;
+
+ int32_t level = 8;
+ bool single = false;
+ int32_t level_out = 0;
+ union drsuapi_DsGetNCChangesRequest req;
+ union drsuapi_DsGetNCChangesCtr ctr;
+ struct drsuapi_DsReplicaObjectIdentifier nc;
+ struct dom_sid null_sid;
+
+ struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
+ struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
+ int32_t out_level = 0;
+ int y;
+
+ uint32_t supported_extensions = 0;
+ uint32_t replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE |
+ DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP |
+ DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS |
+ DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS |
+ DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED;
+
+ if (argc > 3) {
+ printf("usage: %s [naming_context_or_object_dn [single]]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ nc_dn = argv[1];
+ }
+
+ if (argc == 3) {
+ if (strequal(argv[2], "single")) {
+ single = true;
+ } else {
+ printf("warning: ignoring unknown argument '%s'\n",
+ argv[2]);
+ }
+ }
+
+ ZERO_STRUCT(info28);
+
+ ZERO_STRUCT(null_sid);
+ ZERO_STRUCT(req);
+
+ GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
+
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
+ info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
+ info28.site_guid = GUID_zero();
+ info28.pid = 0;
+ info28.repl_epoch = 0;
+
+ bind_info.length = 28;
+ bind_info.info.info28 = info28;
+
+ status = rpccli_drsuapi_DsBind(cli, mem_ctx,
+ &bind_guid,
+ &bind_info,
+ &bind_handle,
+ &werr);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ if (bind_info.length == 24) {
+ supported_extensions = bind_info.info.info24.supported_extensions;
+ } else if (bind_info.length == 28) {
+ supported_extensions = bind_info.info.info28.supported_extensions;
+ } else if (bind_info.length == 48) {
+ supported_extensions = bind_info.info.info48.supported_extensions;
+ }
+
+ if (!nc_dn) {
+
+ union drsuapi_DsNameCtr crack_ctr;
+ const char *name;
+
+ name = talloc_asprintf(mem_ctx, "%s\\", lp_workgroup());
+ W_ERROR_HAVE_NO_MEMORY(name);
+
+ werr = cracknames(cli, mem_ctx,
+ &bind_handle,
+ DRSUAPI_DS_NAME_FORMAT_UKNOWN,
+ DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+ 1,
+ &name,
+ &crack_ctr);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ if (crack_ctr.ctr1->count != 1) {
+ return WERR_NO_SUCH_DOMAIN;
+ }
+
+ if (crack_ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
+ return WERR_NO_SUCH_DOMAIN;
+ }
+
+ nc_dn = talloc_strdup(mem_ctx, crack_ctr.ctr1->array[0].result_name);
+ W_ERROR_HAVE_NO_MEMORY(nc_dn);
+
+ printf("using: %s\n", nc_dn);
+ }
+
+ nc.dn = nc_dn;
+ nc.guid = GUID_zero();
+ nc.sid = null_sid;
+
+ if (supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
+ level = 8;
+ req.req8.naming_context = &nc;
+ req.req8.replica_flags = replica_flags;
+ req.req8.max_object_count = 402;
+ req.req8.max_ndr_size = 402116;
+ if (single) {
+ req.req8.extended_op = DRSUAPI_EXOP_REPL_OBJ;
+ }
+ } else {
+ level = 5;
+ req.req5.naming_context = &nc;
+ req.req5.replica_flags = replica_flags;
+ req.req5.max_object_count = 402;
+ req.req5.max_ndr_size = 402116;
+ if (single) {
+ req.req5.extended_op = DRSUAPI_EXOP_REPL_OBJ;
+ }
+ }
+
+ for (y=0; ;y++) {
+
+ if (level == 8) {
+ DEBUG(1,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y,
+ (long long)req.req8.highwatermark.tmp_highest_usn,
+ (long long)req.req8.highwatermark.highest_usn));
+ }
+
+ status = rpccli_drsuapi_DsGetNCChanges(cli, mem_ctx,
+ &bind_handle,
+ level,
+ &req,
+ &level_out,
+ &ctr,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to get NC Changes: %s",
+ get_friendly_werror_msg(werr));
+ goto out;
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ status = werror_to_ntstatus(werr);
+ goto out;
+ }
+
+ if (level_out == 1) {
+ out_level = 1;
+ ctr1 = &ctr.ctr1;
+ } else if (level_out == 2) {
+ out_level = 1;
+ ctr1 = ctr.ctr2.ctr.mszip1.ctr1;
+ }
+
+ status = cli_get_session_key(mem_ctx, cli, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to get Session Key: %s",
+ nt_errstr(status));
+ return ntstatus_to_werror(status);
+ }
+
+ if (out_level == 1) {
+ DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
+ (long long)ctr1->new_highwatermark.tmp_highest_usn,
+ (long long)ctr1->new_highwatermark.highest_usn));
+#if 0
+ libnet_dssync_decrypt_attributes(mem_ctx,
+ &session_key,
+ ctr1->first_object);
+#endif
+ if (ctr1->more_data) {
+ req.req5.highwatermark = ctr1->new_highwatermark;
+ continue;
+ }
+ }
+
+ if (level_out == 6) {
+ out_level = 6;
+ ctr6 = &ctr.ctr6;
+ } else if (level_out == 7
+ && ctr.ctr7.level == 6
+ && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP) {
+ out_level = 6;
+ ctr6 = ctr.ctr7.ctr.mszip6.ctr6;
+ }
+
+ if (out_level == 6) {
+ DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
+ (long long)ctr6->new_highwatermark.tmp_highest_usn,
+ (long long)ctr6->new_highwatermark.highest_usn));
+#if 0
+ libnet_dssync_decrypt_attributes(mem_ctx,
+ &session_key,
+ ctr6->first_object);
+#endif
+ if (ctr6->more_data) {
+ req.req8.highwatermark = ctr6->new_highwatermark;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ out:
+ return werr;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set drsuapi_commands[] = {
+
+ { "DRSUAPI" },
+ { "dscracknames", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_cracknames, &ndr_table_drsuapi.syntax_id, NULL, "Crack Name", "" },
+ { "dsgetdcinfo", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getdcinfo, &ndr_table_drsuapi.syntax_id, NULL, "Get Domain Controller Info", "" },
+ { "dsgetncchanges", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getncchanges, &ndr_table_drsuapi.syntax_id, NULL, "Get NC Changes", "" },
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_dssetup.c b/source3/rpcclient/cmd_dssetup.c
new file mode 100644
index 0000000000..f2fd124967
--- /dev/null
+++ b/source3/rpcclient/cmd_dssetup.c
@@ -0,0 +1,69 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Gerald Carter 2002
+ Copyright (C) Guenther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+/* Look up domain related information on a remote host */
+
+static WERROR cmd_ds_dsrole_getprimarydominfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ union dssetup_DsRoleInfo info;
+
+ status = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
+ DS_ROLE_BASIC_INFORMATION,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ printf ("Machine Role = [%d]\n", info.basic.role);
+
+ if (info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) {
+ printf("Directory Service is running.\n");
+ printf("Domain is in %s mode.\n",
+ (info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE) ? "mixed" : "native" );
+ } else {
+ printf("Directory Service not running on server\n");
+ }
+
+ return werr;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set ds_commands[] = {
+
+ { "LSARPC-DS" },
+
+ { "dsroledominfo", RPC_RTYPE_WERROR, NULL, cmd_ds_dsrole_getprimarydominfo, &ndr_table_dssetup.syntax_id, NULL, "Get Primary Domain Information", "" },
+
+{ NULL }
+};
diff --git a/source3/rpcclient/cmd_echo.c b/source3/rpcclient/cmd_echo.c
new file mode 100644
index 0000000000..d90ef3499f
--- /dev/null
+++ b/source3/rpcclient/cmd_echo.c
@@ -0,0 +1,184 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_echo_add_one(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 request = 1, response;
+ NTSTATUS result;
+
+ if (argc > 2) {
+ printf("Usage: %s [num]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2)
+ request = atoi(argv[1]);
+
+ result = rpccli_echo_AddOne(cli, mem_ctx, request, &response);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("%d + 1 = %d\n", request, response);
+
+done:
+ return result;
+}
+
+static NTSTATUS cmd_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ uint8_t *in_data = NULL, *out_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+ if ( (in_data = (uint8_t*)SMB_MALLOC(size)) == NULL ) {
+ printf("Failure to allocate buff of %d bytes\n",
+ size);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ if ( (out_data = (uint8_t*)SMB_MALLOC(size)) == NULL ) {
+ printf("Failure to allocate buff of %d bytes\n",
+ size);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < size; i++)
+ in_data[i] = i & 0xff;
+
+ result = rpccli_echo_EchoData(cli, mem_ctx, size, in_data, out_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < size; i++) {
+ if (in_data[i] != out_data[i]) {
+ printf("mismatch at offset %d, %d != %d\n",
+ i, in_data[i], out_data[i]);
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+done:
+ SAFE_FREE(in_data);
+ SAFE_FREE(out_data);
+
+ return result;
+}
+
+static NTSTATUS cmd_echo_source_data(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ uint8_t *out_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+ if ( (out_data = (uint8_t*)SMB_MALLOC(size)) == NULL ) {
+ printf("Failure to allocate buff of %d bytes\n",
+ size);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+
+ result = rpccli_echo_SourceData(cli, mem_ctx, size, out_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < size; i++) {
+ if (out_data && out_data[i] != (i & 0xff)) {
+ printf("mismatch at offset %d, %d != %d\n",
+ i, out_data[i], i & 0xff);
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+done:
+
+ SAFE_FREE(out_data);
+ return result;
+}
+
+static NTSTATUS cmd_echo_sink_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 size, i;
+ NTSTATUS result;
+ uint8_t *in_data = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s num\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ size = atoi(argv[1]);
+ if ( (in_data = (uint8_t*)SMB_MALLOC(size)) == NULL ) {
+ printf("Failure to allocate buff of %d bytes\n",
+ size);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < size; i++)
+ in_data[i] = i & 0xff;
+
+ result = rpccli_echo_SinkData(cli, mem_ctx, size, in_data);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+done:
+ SAFE_FREE(in_data);
+
+ return result;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set echo_commands[] = {
+
+ { "ECHO" },
+
+ { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one, NULL, &ndr_table_rpcecho.syntax_id, NULL, "Add one to a number", "" },
+ { "echodata", RPC_RTYPE_NTSTATUS, cmd_echo_data, NULL, &ndr_table_rpcecho.syntax_id, NULL, "Echo data", "" },
+ { "sinkdata", RPC_RTYPE_NTSTATUS, cmd_echo_sink_data, NULL, &ndr_table_rpcecho.syntax_id, NULL, "Sink data", "" },
+ { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, &ndr_table_rpcecho.syntax_id, NULL, "Source data", "" },
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
new file mode 100644
index 0000000000..5b5b4ff78c
--- /dev/null
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -0,0 +1,1395 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Rafal Szczesniak 2002
+ Copyright (C) Guenther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#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 rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ DOM_SID *sid, const char *name)
+{
+ POLICY_HND pol;
+ enum lsa_SidType *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 = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, NULL, 1, &sids, &sid_types);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ *sid = sids[0];
+
+done:
+ return result;
+}
+
+static void display_query_info_1(struct lsa_AuditLogInfo *r)
+{
+ d_printf("percent_full:\t%d\n", r->percent_full);
+ d_printf("log_size:\t%d\n", r->log_size);
+ d_printf("retention_time:\t%lld\n", (long long)r->retention_time);
+ d_printf("shutdown_in_progress:\t%d\n", r->shutdown_in_progress);
+ d_printf("time_to_shutdown:\t%lld\n", (long long)r->time_to_shutdown);
+ d_printf("next_audit_record:\t%d\n", r->next_audit_record);
+ d_printf("unknown:\t%d\n", r->unknown);
+}
+
+static void display_query_info_2(struct lsa_AuditEventsInfo *r)
+{
+ int i;
+ d_printf("Auditing enabled:\t%d\n", r->auditing_mode);
+ d_printf("Auditing categories:\t%d\n", r->count);
+ d_printf("Auditsettings:\n");
+ for (i=0; i<r->count; i++) {
+ const char *val = audit_policy_str(talloc_tos(), r->settings[i]);
+ const char *policy = audit_description_str(i);
+ d_printf("%s:\t%s\n", policy, val);
+ }
+}
+
+static void display_query_info_3(struct lsa_DomainInfo *r)
+{
+ d_printf("Domain Name: %s\n", r->name.string);
+ d_printf("Domain Sid: %s\n", sid_string_tos(r->sid));
+}
+
+static void display_query_info_5(struct lsa_DomainInfo *r)
+{
+ d_printf("Domain Name: %s\n", r->name.string);
+ d_printf("Domain Sid: %s\n", sid_string_tos(r->sid));
+}
+
+static void display_query_info_10(struct lsa_AuditFullSetInfo *r)
+{
+ d_printf("Shutdown on full: %d\n", r->shutdown_on_full);
+}
+
+static void display_query_info_11(struct lsa_AuditFullQueryInfo *r)
+{
+ d_printf("Shutdown on full: %d\n", r->shutdown_on_full);
+ d_printf("Log is full: %d\n", r->log_is_full);
+ d_printf("Unknown: %d\n", r->unknown);
+}
+
+static void display_query_info_12(struct lsa_DnsDomainInfo *r)
+{
+ d_printf("Domain NetBios Name: %s\n", r->name.string);
+ d_printf("Domain DNS Name: %s\n", r->dns_domain.string);
+ d_printf("Domain Forest Name: %s\n", r->dns_forest.string);
+ d_printf("Domain Sid: %s\n", sid_string_tos(r->sid));
+ d_printf("Domain GUID: %s\n", smb_uuid_string(talloc_tos(),
+ r->domain_guid));
+}
+
+static void display_lsa_query_info(union lsa_PolicyInformation *info,
+ enum lsa_PolicyInfo level)
+{
+ switch (level) {
+ case 1:
+ display_query_info_1(&info->audit_log);
+ break;
+ case 2:
+ display_query_info_2(&info->audit_events);
+ break;
+ case 3:
+ display_query_info_3(&info->domain);
+ break;
+ case 5:
+ display_query_info_5(&info->account_domain);
+ break;
+ case 10:
+ display_query_info_10(&info->auditfullset);
+ break;
+ case 11:
+ display_query_info_11(&info->auditfullquery);
+ break;
+ case 12:
+ display_query_info_12(&info->dns);
+ break;
+ default:
+ printf("can't display info level: %d\n", level);
+ break;
+ }
+}
+
+static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ union lsa_PolicyInformation *info = NULL;
+
+ 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]);
+
+ switch (info_class) {
+ case 12:
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_QueryInfoPolicy2(cli, mem_ctx,
+ &pol,
+ info_class,
+ &info);
+ break;
+ default:
+ result = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_QueryInfoPolicy(cli, mem_ctx,
+ &pol,
+ info_class,
+ &info);
+ }
+
+ if (NT_STATUS_IS_OK(result)) {
+ display_lsa_query_info(info, info_class);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ done:
+ return result;
+}
+
+/* Resolve a list of names to a list of sids */
+
+static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ enum lsa_SidType *types;
+ int i;
+
+ if (argc == 1) {
+ printf("Usage: %s [name1 [name2 [...]]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1,
+ (const char**)(argv + 1), NULL, 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_fstring(sid_str, &sids[i]);
+ printf("%s %s (%s: %d)\n", argv[i + 1], sid_str,
+ sid_type_lookup(types[i]), types[i]);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ done:
+ return result;
+}
+
+/* Resolve a list of names to a list of sids */
+
+static NTSTATUS cmd_lsa_lookup_names_level(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ enum lsa_SidType *types;
+ int i, level;
+
+ if (argc < 3) {
+ printf("Usage: %s [level] [name1 [name2 [...]]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ level = atoi(argv[1]);
+
+ result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 2,
+ (const char**)(argv + 2), NULL, level, &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 - 2); i++) {
+ fstring sid_str;
+ sid_to_fstring(sid_str, &sids[i]);
+ printf("%s %s (%s: %d)\n", argv[i + 2], sid_str,
+ sid_type_lookup(types[i]), types[i]);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ done:
+ return result;
+}
+
+
+/* Resolve a list of SIDs to a list of names */
+
+static NTSTATUS cmd_lsa_lookup_sids(struct rpc_pipe_client *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;
+ enum lsa_SidType *types;
+ int i;
+
+ if (argc == 1) {
+ printf("Usage: %s [sid1 [sid2 [...]]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_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 = TALLOC_ARRAY(mem_ctx, 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 = rpccli_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_fstring(sid_str, &sids[i]);
+ printf("%s %s\\%s (%d)\n", sid_str,
+ domains[i] ? domains[i] : "*unknown*",
+ names[i] ? names[i] : "*unknown*", types[i]);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ done:
+ return result;
+}
+
+/* Enumerate list of trusted domains */
+
+static NTSTATUS cmd_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_DomainList domain_list;
+
+ /* defaults, but may be changed using params */
+ uint32 enum_ctx = 0;
+ int i;
+ uint32_t max_size = (uint32_t)-1;
+
+ 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 = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ LSA_POLICY_VIEW_LOCAL_INFORMATION,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = STATUS_MORE_ENTRIES;
+
+ while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
+
+ /* Lookup list of trusted domains */
+
+ result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
+ &pol,
+ &enum_ctx,
+ &domain_list,
+ max_size);
+ 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 < domain_list.count; i++) {
+ fstring sid_str;
+
+ sid_to_fstring(sid_str, domain_list.domains[i].sid);
+ printf("%s %s\n",
+ domain_list.domains[i].name.string ?
+ domain_list.domains[i].name.string : "*unknown*",
+ sid_str);
+ }
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+/* Enumerates privileges */
+
+static NTSTATUS cmd_lsa_enum_privilege(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_PrivArray priv_array;
+
+ uint32 enum_context=0;
+ uint32 pref_max_length=0x1000;
+ 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 = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_EnumPrivs(cli, mem_ctx,
+ &pol,
+ &enum_context,
+ &priv_array,
+ pref_max_length);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d privileges\n\n", priv_array.count);
+
+ for (i = 0; i < priv_array.count; i++) {
+ printf("%s \t\t%d:%d (0x%x:0x%x)\n",
+ priv_array.privs[i].name.string ? priv_array.privs[i].name.string : "*unknown*",
+ priv_array.privs[i].luid.high,
+ priv_array.privs[i].luid.low,
+ priv_array.privs[i].luid.high,
+ priv_array.privs[i].luid.low);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+/* Get privilege name */
+
+static NTSTATUS cmd_lsa_get_dispname(struct rpc_pipe_client *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;
+ struct lsa_String lsa_name;
+ struct lsa_StringLarge *description = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s privilege name\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ init_lsa_String(&lsa_name, argv[1]);
+
+ result = rpccli_lsa_LookupPrivDisplayName(cli, mem_ctx,
+ &pol,
+ &lsa_name,
+ 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->string, lang_id_desc);
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+/* Enumerate the LSA SIDS */
+
+static NTSTATUS cmd_lsa_enum_sids(struct rpc_pipe_client *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;
+ struct lsa_SidArray sid_array;
+ 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 = rpccli_lsa_open_policy(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_EnumAccounts(cli, mem_ctx,
+ &pol,
+ &enum_context,
+ &sid_array,
+ pref_max_length);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d SIDs\n\n", sid_array.num_sids);
+
+ for (i = 0; i < sid_array.num_sids; i++) {
+ fstring sid_str;
+
+ sid_to_fstring(sid_str, sid_array.sids[i].sid);
+ printf("%s\n", sid_str);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+/* Create a new account */
+
+static NTSTATUS cmd_lsa_create_account(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ POLICY_HND user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 des_access = 0x000f000f;
+
+ DOM_SID sid;
+
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_CreateAccount(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ des_access,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("Account for SID %s successfully created\n\n", argv[1]);
+ result = NT_STATUS_OK;
+
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+
+/* Enumerate the privileges of an SID */
+
+static NTSTATUS cmd_lsa_enum_privsaccounts(struct rpc_pipe_client *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;
+ struct lsa_PrivilegeSet *privs = NULL;
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_OpenAccount(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ access_desired,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_EnumPrivsAccount(cli, mem_ctx,
+ &user_pol,
+ &privs);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+ printf("found %d privileges for SID %s\n\n", privs->count, argv[1]);
+ printf("high\tlow\tattribute\n");
+
+ for (i = 0; i < privs->count; i++) {
+ printf("%u\t%u\t%u\n",
+ privs->set[i].luid.high,
+ privs->set[i].luid.low,
+ privs->set[i].attribute);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+
+/* Enumerate the privileges of an SID via LsaEnumerateAccountRights */
+
+static NTSTATUS cmd_lsa_enum_acct_rights(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID sid;
+ struct lsa_RightSet 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_EnumAccountRights(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ &rights);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ printf("found %d privileges for SID %s\n", rights.count,
+ sid_string_tos(&sid));
+
+ for (i = 0; i < rights.count; i++) {
+ printf("\t%s\n", rights.names[i].string);
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+
+/* add some privileges to a SID via LsaAddAccountRights */
+
+static NTSTATUS cmd_lsa_add_acct_rights(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_RightSet rights;
+ DOM_SID sid;
+ int i;
+
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rights.count = argc-2;
+ rights.names = TALLOC_ARRAY(mem_ctx, struct lsa_StringLarge,
+ rights.count);
+ if (!rights.names) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<argc-1; i++) {
+ init_lsa_StringLarge(&rights.names[i], argv[i+2]);
+ }
+
+ result = rpccli_lsa_AddAccountRights(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ &rights);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+
+/* remove some privileges to a SID via LsaRemoveAccountRights */
+
+static NTSTATUS cmd_lsa_remove_acct_rights(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_RightSet rights;
+ DOM_SID sid;
+ int i;
+
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rights.count = argc-2;
+ rights.names = TALLOC_ARRAY(mem_ctx, struct lsa_StringLarge,
+ rights.count);
+ if (!rights.names) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<argc-2; i++) {
+ init_lsa_StringLarge(&rights.names[i], argv[i+2]);
+ }
+
+ result = rpccli_lsa_RemoveAccountRights(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ false,
+ &rights);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+
+ done:
+ return result;
+}
+
+
+/* Get a privilege value given its name */
+
+static NTSTATUS cmd_lsa_lookup_priv_value(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_LUID luid;
+ struct lsa_String name;
+
+ if (argc != 2 ) {
+ printf("Usage: %s name\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ init_lsa_String(&name, argv[1]);
+
+ result = rpccli_lsa_LookupPrivValue(cli, mem_ctx,
+ &pol,
+ &name,
+ &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);
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+/* Query LSA security object */
+
+static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *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 = DACL_SECURITY_INFORMATION;
+
+ if (argc < 1 || argc > 2) {
+ printf("Usage: %s [sec_info]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (argc == 2)
+ sscanf(argv[1], "%x", &sec_info);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_QuerySecurity(cli, mem_ctx,
+ &pol,
+ sec_info,
+ &sdb);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Print results */
+
+ display_sec_desc(sdb->sd);
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+static void display_trust_dom_info_4(struct lsa_TrustDomainInfoPassword *p,
+ uint8_t nt_hash[16])
+{
+ char *pwd, *pwd_old;
+
+ DATA_BLOB data = data_blob(NULL, p->password->length);
+ DATA_BLOB data_old = data_blob(NULL, p->old_password->length);
+
+ memcpy(data.data, p->password->data, p->password->length);
+ memcpy(data_old.data, p->old_password->data, p->old_password->length);
+
+ pwd = decrypt_trustdom_secret(nt_hash, &data);
+ pwd_old = decrypt_trustdom_secret(nt_hash, &data_old);
+
+ d_printf("Password:\t%s\n", pwd);
+ d_printf("Old Password:\t%s\n", pwd_old);
+
+ SAFE_FREE(pwd);
+ SAFE_FREE(pwd_old);
+
+ data_blob_free(&data);
+ data_blob_free(&data_old);
+}
+
+static void display_trust_dom_info(TALLOC_CTX *mem_ctx,
+ union lsa_TrustedDomainInfo *info,
+ enum lsa_TrustDomInfoEnum info_class,
+ uint8_t nt_hash[16])
+{
+ switch (info_class) {
+ case LSA_TRUSTED_DOMAIN_INFO_PASSWORD:
+ display_trust_dom_info_4(&info->password, nt_hash);
+ break;
+ default: {
+ const char *str = NULL;
+ str = NDR_PRINT_UNION_STRING(mem_ctx,
+ lsa_TrustedDomainInfo,
+ info_class, info);
+ if (str) {
+ d_printf("%s\n", str);
+ }
+ break;
+ }
+ }
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfobysid(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID dom_sid;
+ uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ union lsa_TrustedDomainInfo *info = NULL;
+ enum lsa_TrustDomInfoEnum info_class = 1;
+ uint8_t nt_hash[16];
+
+ if (argc > 3 || argc < 2) {
+ printf("Usage: %s [sid] [info_class]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (!string_to_sid(&dom_sid, argv[1]))
+ return NT_STATUS_NO_MEMORY;
+
+ if (argc == 3)
+ info_class = atoi(argv[2]);
+
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_QueryTrustedDomainInfoBySid(cli, mem_ctx,
+ &pol,
+ &dom_sid,
+ info_class,
+ &info);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (!rpccli_get_pwd_hash(cli, nt_hash)) {
+ d_fprintf(stderr, "Could not get pwd hash\n");
+ goto done;
+ }
+
+ display_trust_dom_info(mem_ctx, info, info_class, nt_hash);
+
+ done:
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfobyname(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ union lsa_TrustedDomainInfo *info = NULL;
+ enum lsa_TrustDomInfoEnum info_class = 1;
+ struct lsa_String trusted_domain;
+ uint8_t nt_hash[16];
+
+ if (argc > 3 || argc < 2) {
+ printf("Usage: %s [name] [info_class]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 3)
+ info_class = atoi(argv[2]);
+
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ init_lsa_String(&trusted_domain, argv[1]);
+
+ result = rpccli_lsa_QueryTrustedDomainInfoByName(cli, mem_ctx,
+ &pol,
+ &trusted_domain,
+ info_class,
+ &info);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (!rpccli_get_pwd_hash(cli, nt_hash)) {
+ d_fprintf(stderr, "Could not get pwd hash\n");
+ goto done;
+ }
+
+ display_trust_dom_info(mem_ctx, info, info_class, nt_hash);
+
+ done:
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+static NTSTATUS cmd_lsa_query_trustdominfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol, trustdom_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ union lsa_TrustedDomainInfo *info = NULL;
+ DOM_SID dom_sid;
+ enum lsa_TrustDomInfoEnum info_class = 1;
+ uint8_t nt_hash[16];
+
+ if (argc > 3 || argc < 2) {
+ printf("Usage: %s [sid] [info_class]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (!string_to_sid(&dom_sid, argv[1]))
+ return NT_STATUS_NO_MEMORY;
+
+
+ if (argc == 3)
+ info_class = atoi(argv[2]);
+
+ result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_OpenTrustedDomain(cli, mem_ctx,
+ &pol,
+ &dom_sid,
+ access_mask,
+ &trustdom_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_lsa_QueryTrustedDomainInfo(cli, mem_ctx,
+ &trustdom_pol,
+ info_class,
+ &info);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (!rpccli_get_pwd_hash(cli, nt_hash)) {
+ d_fprintf(stderr, "Could not get pwd hash\n");
+ goto done;
+ }
+
+ display_trust_dom_info(mem_ctx, info, info_class, nt_hash);
+
+ done:
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+static NTSTATUS cmd_lsa_get_username(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *servername = cli->desthost;
+ struct lsa_String *account_name = NULL;
+ struct lsa_String *authority_name = NULL;
+
+ if (argc > 2) {
+ printf("Usage: %s servername\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = rpccli_lsa_open_policy(cli, mem_ctx, true,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_GetUserName(cli, mem_ctx,
+ servername,
+ &account_name,
+ &authority_name);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Print results */
+
+ printf("Account Name: %s, Authority Name: %s\n",
+ account_name->string, authority_name->string);
+
+ rpccli_lsa_Close(cli, mem_ctx, &pol);
+ done:
+ return result;
+}
+
+static NTSTATUS cmd_lsa_add_priv(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_PrivilegeSet privs;
+ struct lsa_LUIDAttribute *set = NULL;
+ DOM_SID sid;
+ int i;
+
+ ZERO_STRUCT(privs);
+
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_OpenAccount(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ for (i=2; i<argc; i++) {
+
+ struct lsa_String priv_name;
+ struct lsa_LUID luid;
+
+ init_lsa_String(&priv_name, argv[i]);
+
+ result = rpccli_lsa_LookupPrivValue(cli, mem_ctx,
+ &dom_pol,
+ &priv_name,
+ &luid);
+ if (!NT_STATUS_IS_OK(result)) {
+ continue;
+ }
+
+ privs.count++;
+ set = TALLOC_REALLOC_ARRAY(mem_ctx, set,
+ struct lsa_LUIDAttribute,
+ privs.count);
+ if (!set) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ set[privs.count-1].luid = luid;
+ set[privs.count-1].attribute = 0;
+ }
+
+ privs.set = set;
+
+ result = rpccli_lsa_AddPrivilegesToAccount(cli, mem_ctx,
+ &user_pol,
+ &privs);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &user_pol);
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+static NTSTATUS cmd_lsa_del_priv(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ POLICY_HND dom_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_PrivilegeSet privs;
+ struct lsa_LUIDAttribute *set = NULL;
+ DOM_SID sid;
+ int i;
+
+ ZERO_STRUCT(privs);
+
+ 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 = rpccli_lsa_open_policy2(cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &dom_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_OpenAccount(cli, mem_ctx,
+ &dom_pol,
+ &sid,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ for (i=2; i<argc; i++) {
+
+ struct lsa_String priv_name;
+ struct lsa_LUID luid;
+
+ init_lsa_String(&priv_name, argv[i]);
+
+ result = rpccli_lsa_LookupPrivValue(cli, mem_ctx,
+ &dom_pol,
+ &priv_name,
+ &luid);
+ if (!NT_STATUS_IS_OK(result)) {
+ continue;
+ }
+
+ privs.count++;
+ set = TALLOC_REALLOC_ARRAY(mem_ctx, set,
+ struct lsa_LUIDAttribute,
+ privs.count);
+ if (!set) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ set[privs.count-1].luid = luid;
+ set[privs.count-1].attribute = 0;
+ }
+
+ privs.set = set;
+
+
+ result = rpccli_lsa_RemovePrivilegesFromAccount(cli, mem_ctx,
+ &user_pol,
+ false,
+ &privs);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ rpccli_lsa_Close(cli, mem_ctx, &user_pol);
+ rpccli_lsa_Close(cli, mem_ctx, &dom_pol);
+ done:
+ return result;
+}
+
+
+/* List of commands exported by this module */
+
+struct cmd_set lsarpc_commands[] = {
+
+ { "LSARPC" },
+
+ { "lsaquery", RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query info policy", "" },
+ { "lookupsids", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Convert SIDs to names", "" },
+ { "lookupnames", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Convert names to SIDs", "" },
+ { "lookupnames_level", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names_level, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Convert names to SIDs", "" },
+ { "enumtrust", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_trust_dom, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Enumerate trusted domains", "Usage: [preferred max number] [enum context (0)]" },
+ { "enumprivs", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Enumerate privileges", "" },
+ { "getdispname", RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Get the privilege name", "" },
+ { "lsaenumsid", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Enumerate the LSA SIDS", "" },
+ { "lsacreateaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_create_account, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Create a new lsa account", "" },
+ { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Enumerate the privileges of an SID", "" },
+ { "lsaenumacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Enumerate the rights of an SID", "" },
+ { "lsaaddpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_add_priv, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Assign a privilege to a SID", "" },
+ { "lsadelpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_del_priv, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Revoke a privilege from a SID", "" },
+ { "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Add rights to an account", "" },
+ { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Remove rights from an account", "" },
+ { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Get a privilege value given its name", "" },
+ { "lsaquerysecobj", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA security object", "" },
+ { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA trusted domains info (given a SID)", "" },
+ { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" },
+ { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA trusted domains info (given a SID)", "" },
+ { "getusername", RPC_RTYPE_NTSTATUS, cmd_lsa_get_username, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Get username", "" },
+
+ { NULL }
+};
+
diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c
new file mode 100644
index 0000000000..87ba65c14b
--- /dev/null
+++ b/source3/rpcclient/cmd_netlogon.c
@@ -0,0 +1,1034 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Guenther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static WERROR cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr;
+ const char *logon_server = cli->desthost;
+ enum netr_LogonControlCode function_code = NETLOGON_CONTROL_REDISCOVER;
+ uint32_t level = 1;
+ union netr_CONTROL_DATA_INFORMATION data;
+ union netr_CONTROL_QUERY_INFORMATION query;
+ const char *domain = lp_workgroup();
+
+ if (argc > 5) {
+ fprintf(stderr, "Usage: %s <logon_server> <function_code> "
+ "<level> <domain>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ logon_server = argv[1];
+ }
+
+ if (argc >= 3) {
+ function_code = atoi(argv[2]);
+ }
+
+ if (argc >= 4) {
+ level = atoi(argv[3]);
+ }
+
+ if (argc >= 5) {
+ domain = argv[4];
+ }
+
+ switch (function_code) {
+ case NETLOGON_CONTROL_REDISCOVER:
+ case NETLOGON_CONTROL_TC_QUERY:
+ data.domain = domain;
+ break;
+ default:
+ break;
+ }
+
+ status = rpccli_netr_LogonControl2(cli, mem_ctx,
+ logon_server,
+ function_code,
+ level,
+ &data,
+ &query,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ /* Display results */
+
+ return werr;
+}
+
+static WERROR cmd_netlogon_getanydcname(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ const char *dcname = NULL;
+ WERROR werr;
+ NTSTATUS status;
+ int old_timeout;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s domainname\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Make sure to wait for our DC's reply */
+ old_timeout = rpccli_set_timeout(cli, 30000); /* 30 seconds. */
+ rpccli_set_timeout(cli, MAX(old_timeout, 30000)); /* At least 30 sec */
+
+ status = rpccli_netr_GetAnyDCName(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ &dcname,
+ &werr);
+ rpccli_set_timeout(cli, old_timeout);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ /* Display results */
+
+ printf("%s\n", dcname);
+
+ return werr;
+}
+
+static WERROR cmd_netlogon_getdcname(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ const char *dcname = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ int old_timeout;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s domainname\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Make sure to wait for our DC's reply */
+ old_timeout = rpccli_set_timeout(cli, 30000); /* 30 seconds. */
+ rpccli_set_timeout(cli, MAX(30000, old_timeout)); /* At least 30 sec */
+
+ status = rpccli_netr_GetDcName(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ &dcname,
+ &werr);
+ rpccli_set_timeout(cli, old_timeout);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ /* Display results */
+
+ printf("%s\n", dcname);
+
+ return werr;
+}
+
+static WERROR cmd_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result;
+ WERROR werr = WERR_OK;
+ uint32 flags = DS_RETURN_DNS_NAME;
+ const char *server_name = cli->desthost;
+ const char *domain_name;
+ struct GUID domain_guid = GUID_zero();
+ struct GUID site_guid = GUID_zero();
+ struct netr_DsRGetDCNameInfo *info = NULL;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [domain_name] [domain_guid] "
+ "[site_guid] [flags]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2)
+ domain_name = argv[1];
+
+ if (argc >= 3) {
+ if (!NT_STATUS_IS_OK(GUID_from_string(argv[2], &domain_guid))) {
+ return WERR_NOMEM;
+ }
+ }
+
+ if (argc >= 4) {
+ if (!NT_STATUS_IS_OK(GUID_from_string(argv[3], &site_guid))) {
+ return WERR_NOMEM;
+ }
+ }
+
+ if (argc >= 5)
+ sscanf(argv[4], "%x", &flags);
+
+ debug_dsdcinfo_flags(1,flags);
+
+ result = rpccli_netr_DsRGetDCName(cli, mem_ctx,
+ server_name,
+ domain_name,
+ &domain_guid,
+ &site_guid,
+ flags,
+ &info,
+ &werr);
+
+ if (W_ERROR_IS_OK(werr)) {
+ d_printf("DsGetDcName gave: %s\n",
+ NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info));
+ return WERR_OK;
+ }
+
+ printf("rpccli_netlogon_dsr_getdcname returned %s\n",
+ dos_errstr(werr));
+
+ return werr;
+}
+
+static WERROR cmd_netlogon_dsr_getdcnameex(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+ uint32_t flags = DS_RETURN_DNS_NAME;
+ const char *server_name = cli->desthost;
+ const char *domain_name;
+ const char *site_name = NULL;
+ struct GUID domain_guid = GUID_zero();
+ struct netr_DsRGetDCNameInfo *info = NULL;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [domain_name] [domain_guid] "
+ "[site_name] [flags]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ domain_name = argv[1];
+
+ if (argc >= 3) {
+ if (!NT_STATUS_IS_OK(GUID_from_string(argv[2], &domain_guid))) {
+ return WERR_NOMEM;
+ }
+ }
+
+ if (argc >= 4) {
+ site_name = argv[3];
+ }
+
+ if (argc >= 5) {
+ sscanf(argv[4], "%x", &flags);
+ }
+
+ debug_dsdcinfo_flags(1,flags);
+
+ status = rpccli_netr_DsRGetDCNameEx(cli, mem_ctx,
+ server_name,
+ domain_name,
+ &domain_guid,
+ site_name,
+ flags,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ return result;
+ }
+
+ d_printf("DsRGetDCNameEx gave %s\n",
+ NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info));
+
+ return result;
+}
+
+static WERROR cmd_netlogon_dsr_getdcnameex2(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+ uint32_t flags = DS_RETURN_DNS_NAME;
+ const char *server_name = cli->desthost;
+ const char *domain_name = NULL;
+ const char *client_account = NULL;
+ uint32_t mask = 0;
+ const char *site_name = NULL;
+ struct GUID domain_guid = GUID_zero();
+ struct netr_DsRGetDCNameInfo *info = NULL;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [client_account] [acb_mask] "
+ "[domain_name] [domain_guid] [site_name] "
+ "[flags]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ client_account = argv[1];
+ }
+
+ if (argc >= 3) {
+ mask = atoi(argv[2]);
+ }
+
+ if (argc >= 4) {
+ domain_name = argv[3];
+ }
+
+ if (argc >= 5) {
+ if (!NT_STATUS_IS_OK(GUID_from_string(argv[4], &domain_guid))) {
+ return WERR_NOMEM;
+ }
+ }
+
+ if (argc >= 6) {
+ site_name = argv[5];
+ }
+
+ if (argc >= 7) {
+ sscanf(argv[6], "%x", &flags);
+ }
+
+ debug_dsdcinfo_flags(1,flags);
+
+ status = rpccli_netr_DsRGetDCNameEx2(cli, mem_ctx,
+ server_name,
+ client_account,
+ mask,
+ domain_name,
+ &domain_guid,
+ site_name,
+ flags,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ return result;
+ }
+
+ d_printf("DsRGetDCNameEx2 gave %s\n",
+ NDR_PRINT_STRUCT_STRING(mem_ctx, netr_DsRGetDCNameInfo, info));
+
+ return result;
+}
+
+
+static WERROR cmd_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR werr;
+ NTSTATUS status;
+ const char *sitename = NULL;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s computername\n", argv[0]);
+ return WERR_OK;
+ }
+
+ status = rpccli_netr_DsRGetSiteName(cli, mem_ctx,
+ argv[1],
+ &sitename,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ printf("rpccli_netlogon_dsr_gesitename returned %s\n",
+ nt_errstr(werror_to_ntstatus(werr)));
+ return werr;
+ }
+
+ printf("Computer %s is on Site: %s\n", argv[1], sitename);
+
+ return WERR_OK;
+}
+
+static WERROR cmd_netlogon_logon_ctrl(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr;
+ const char *logon_server = cli->desthost;
+ enum netr_LogonControlCode function_code = 1;
+ uint32_t level = 1;
+ union netr_CONTROL_QUERY_INFORMATION info;
+
+ if (argc > 4) {
+ fprintf(stderr, "Usage: %s <logon_server> <function_code> "
+ "<level>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ logon_server = argv[1];
+ }
+
+ if (argc >= 3) {
+ function_code = atoi(argv[2]);
+ }
+
+ if (argc >= 4) {
+ level = atoi(argv[3]);
+ }
+
+ status = rpccli_netr_LogonControl(cli, mem_ctx,
+ logon_server,
+ function_code,
+ level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ /* Display results */
+
+ return werr;
+}
+
+/* Display sam synchronisation information */
+
+static void display_sam_sync(struct netr_DELTA_ENUM_ARRAY *r)
+{
+ uint32_t i, j;
+
+ for (i=0; i < r->num_deltas; i++) {
+
+ union netr_DELTA_UNION u = r->delta_enum[i].delta_union;
+ union netr_DELTA_ID_UNION id = r->delta_enum[i].delta_id_union;
+
+ switch (r->delta_enum[i].delta_type) {
+ case NETR_DELTA_DOMAIN:
+ printf("Domain: %s\n",
+ u.domain->domain_name.string);
+ break;
+ case NETR_DELTA_GROUP:
+ printf("Group: %s\n",
+ u.group->group_name.string);
+ break;
+ case NETR_DELTA_DELETE_GROUP:
+ printf("Delete Group: %d\n",
+ u.delete_account.unknown);
+ break;
+ case NETR_DELTA_RENAME_GROUP:
+ printf("Rename Group: %s -> %s\n",
+ u.rename_group->OldName.string,
+ u.rename_group->NewName.string);
+ break;
+ case NETR_DELTA_USER:
+ printf("Account: %s\n",
+ u.user->account_name.string);
+ break;
+ case NETR_DELTA_DELETE_USER:
+ printf("Delete User: %d\n",
+ id.rid);
+ break;
+ case NETR_DELTA_RENAME_USER:
+ printf("Rename user: %s -> %s\n",
+ u.rename_user->OldName.string,
+ u.rename_user->NewName.string);
+ break;
+ case NETR_DELTA_GROUP_MEMBER:
+ for (j=0; j < u.group_member->num_rids; j++) {
+ printf("rid 0x%x, attrib 0x%08x\n",
+ u.group_member->rids[j],
+ u.group_member->attribs[j]);
+ }
+ break;
+ case NETR_DELTA_ALIAS:
+ printf("Alias: %s\n",
+ u.alias->alias_name.string);
+ break;
+ case NETR_DELTA_DELETE_ALIAS:
+ printf("Delete Alias: %d\n",
+ r->delta_enum[i].delta_id_union.rid);
+ break;
+ case NETR_DELTA_RENAME_ALIAS:
+ printf("Rename alias: %s -> %s\n",
+ u.rename_alias->OldName.string,
+ u.rename_alias->NewName.string);
+ break;
+ case NETR_DELTA_ALIAS_MEMBER:
+ for (j=0; j < u.alias_member->sids.num_sids; j++) {
+ fstring sid_str;
+ sid_to_fstring(sid_str,
+ u.alias_member->sids.sids[j].sid);
+ printf("%s\n", sid_str);
+ }
+ break;
+ case NETR_DELTA_POLICY:
+ printf("Policy\n");
+ break;
+ case NETR_DELTA_TRUSTED_DOMAIN:
+ printf("Trusted Domain: %s\n",
+ u.trusted_domain->domain_name.string);
+ break;
+ case NETR_DELTA_DELETE_TRUST:
+ printf("Delete Trust: %d\n",
+ u.delete_trust.unknown);
+ break;
+ case NETR_DELTA_ACCOUNT:
+ printf("Account\n");
+ break;
+ case NETR_DELTA_DELETE_ACCOUNT:
+ printf("Delete Account: %d\n",
+ u.delete_account.unknown);
+ break;
+ case NETR_DELTA_SECRET:
+ printf("Secret\n");
+ break;
+ case NETR_DELTA_DELETE_SECRET:
+ printf("Delete Secret: %d\n",
+ u.delete_secret.unknown);
+ break;
+ case NETR_DELTA_DELETE_GROUP2:
+ printf("Delete Group2: %s\n",
+ u.delete_group->account_name);
+ break;
+ case NETR_DELTA_DELETE_USER2:
+ printf("Delete User2: %s\n",
+ u.delete_user->account_name);
+ break;
+ case NETR_DELTA_MODIFY_COUNT:
+ printf("sam sequence update: 0x%016llx\n",
+ (unsigned long long) *u.modified_count);
+ break;
+ default:
+ printf("unknown delta type 0x%02x\n",
+ r->delta_enum[i].delta_type);
+ break;
+ }
+ }
+}
+
+/* Perform sam synchronisation */
+
+static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *logon_server = cli->desthost;
+ const char *computername = global_myname();
+ struct netr_Authenticator credential;
+ struct netr_Authenticator return_authenticator;
+ enum netr_SamDatabaseID database_id = SAM_DATABASE_DOMAIN;
+ uint16_t restart_state = 0;
+ uint32_t sync_context = 0;
+
+ if (argc > 2) {
+ fprintf(stderr, "Usage: %s [database_id]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2) {
+ database_id = atoi(argv[1]);
+ }
+
+ /* Synchronise sam database */
+
+ do {
+ struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+
+ netlogon_creds_client_step(cli->dc, &credential);
+
+ result = rpccli_netr_DatabaseSync2(cli, mem_ctx,
+ logon_server,
+ computername,
+ &credential,
+ &return_authenticator,
+ database_id,
+ restart_state,
+ &sync_context,
+ &delta_enum_array,
+ 0xffff);
+
+ /* Check returned credentials. */
+ if (!netlogon_creds_client_check(cli->dc,
+ &return_authenticator.cred)) {
+ DEBUG(0,("credentials chain check failed\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (NT_STATUS_IS_ERR(result)) {
+ break;
+ }
+
+ /* Display results */
+
+ display_sam_sync(delta_enum_array);
+
+ TALLOC_FREE(delta_enum_array);
+
+ } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
+
+ return result;
+}
+
+/* Perform sam delta synchronisation */
+
+static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32_t tmp;
+ const char *logon_server = cli->desthost;
+ const char *computername = global_myname();
+ struct netr_Authenticator credential;
+ struct netr_Authenticator return_authenticator;
+ enum netr_SamDatabaseID database_id = SAM_DATABASE_DOMAIN;
+ uint64_t sequence_num;
+
+ 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]);
+
+ sequence_num = tmp & 0xffff;
+
+ do {
+ struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+
+ netlogon_creds_client_step(cli->dc, &credential);
+
+ result = rpccli_netr_DatabaseDeltas(cli, mem_ctx,
+ logon_server,
+ computername,
+ &credential,
+ &return_authenticator,
+ database_id,
+ &sequence_num,
+ &delta_enum_array,
+ 0xffff);
+
+ /* Check returned credentials. */
+ if (!netlogon_creds_client_check(cli->dc,
+ &return_authenticator.cred)) {
+ DEBUG(0,("credentials chain check failed\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (NT_STATUS_IS_ERR(result)) {
+ break;
+ }
+
+ /* Display results */
+
+ display_sam_sync(delta_enum_array);
+
+ TALLOC_FREE(delta_enum_array);
+
+ } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
+
+ return result;
+}
+
+/* Log on a domain user */
+
+static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ int logon_type = NET_LOGON_TYPE;
+ const char *username, *password;
+ int auth_level = 2;
+ uint32 logon_param = 0;
+ const char *workstation = NULL;
+
+ /* Check arguments */
+
+ if (argc < 3 || argc > 7) {
+ fprintf(stderr, "Usage: samlogon <username> <password> [workstation]"
+ "[logon_type (1 or 2)] [auth level (2 or 3)] [logon_parameter]\n");
+ return NT_STATUS_OK;
+ }
+
+ username = argv[1];
+ password = argv[2];
+
+ if (argc >= 4)
+ workstation = argv[3];
+
+ if (argc >= 5)
+ sscanf(argv[4], "%i", &logon_type);
+
+ if (argc >= 6)
+ sscanf(argv[5], "%i", &auth_level);
+
+ if (argc == 7)
+ sscanf(argv[6], "%x", &logon_param);
+
+ /* Perform the sam logon */
+
+ result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, logon_type);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+/* Change the trust account password */
+
+static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ /* Check arguments */
+
+ if (argc > 1) {
+ fprintf(stderr, "Usage: change_trust_pw");
+ return NT_STATUS_OK;
+ }
+
+ /* Perform the sam logon */
+
+ result = trust_pw_find_change_and_store_it(cli, mem_ctx,
+ lp_workgroup());
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+static WERROR cmd_netlogon_gettrustrid(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ const char *domain_name = lp_workgroup();
+ uint32_t rid = 0;
+
+ if (argc < 1 || argc > 3) {
+ fprintf(stderr, "Usage: %s <server_name> <domain_name>\n",
+ argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ if (argc >= 3) {
+ domain_name = argv[2];
+ }
+
+ status = rpccli_netr_LogonGetTrustRid(cli, mem_ctx,
+ server_name,
+ domain_name,
+ &rid,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("Rid: %d\n", rid);
+ }
+ done:
+ return werr;
+}
+
+static WERROR cmd_netlogon_dsr_enumtrustdom(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ uint32_t trust_flags = NETR_TRUST_FLAG_IN_FOREST;
+ struct netr_DomainTrustList trusts;
+
+ if (argc < 1 || argc > 3) {
+ fprintf(stderr, "Usage: %s <server_name> <trust_flags>\n",
+ argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ if (argc >= 3) {
+ sscanf(argv[2], "%x", &trust_flags);
+ }
+
+ status = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ server_name,
+ trust_flags,
+ &trusts,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ int i;
+
+ printf("%d domains returned\n", trusts.count);
+
+ for (i=0; i<trusts.count; i++ ) {
+ printf("%s (%s)\n",
+ trusts.array[i].dns_name,
+ trusts.array[i].netbios_name);
+ }
+ }
+ done:
+ return werr;
+}
+
+static WERROR cmd_netlogon_deregisterdnsrecords(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ const char *domain = lp_workgroup();
+ const char *dns_host = NULL;
+
+ if (argc < 1 || argc > 4) {
+ fprintf(stderr, "Usage: %s <server_name> <domain_name> "
+ "<dns_host>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ if (argc >= 3) {
+ domain = argv[2];
+ }
+
+ if (argc >= 4) {
+ dns_host = argv[3];
+ }
+
+ status = rpccli_netr_DsrDeregisterDNSHostRecords(cli, mem_ctx,
+ server_name,
+ domain,
+ NULL,
+ NULL,
+ dns_host,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("success\n");
+ }
+ done:
+ return werr;
+}
+
+static WERROR cmd_netlogon_dsr_getforesttrustinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ const char *trusted_domain_name = NULL;
+ struct lsa_ForestTrustInformation *info = NULL;
+ uint32_t flags = 0;
+
+ if (argc < 1 || argc > 4) {
+ fprintf(stderr, "Usage: %s <server_name> <trusted_domain_name> "
+ "<flags>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ if (argc >= 3) {
+ trusted_domain_name = argv[2];
+ }
+
+ if (argc >= 4) {
+ sscanf(argv[3], "%x", &flags);
+ }
+
+ status = rpccli_netr_DsRGetForestTrustInformation(cli, mem_ctx,
+ server_name,
+ trusted_domain_name,
+ flags,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("success\n");
+ }
+ done:
+ return werr;
+}
+
+static WERROR cmd_netlogon_enumtrusteddomains(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ struct netr_Blob blob;
+
+
+ if (argc < 1 || argc > 3) {
+ fprintf(stderr, "Usage: %s <server_name>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ status = rpccli_netr_NetrEnumerateTrustedDomains(cli, mem_ctx,
+ server_name,
+ &blob,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("success\n");
+ dump_data(1, blob.data, blob.length);
+ }
+ done:
+ return werr;
+}
+
+static WERROR cmd_netlogon_enumtrusteddomainsex(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ WERROR werr = WERR_GENERAL_FAILURE;
+ const char *server_name = cli->desthost;
+ struct netr_DomainTrustList list;
+
+ if (argc < 1 || argc > 3) {
+ fprintf(stderr, "Usage: %s <server_name>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ server_name = argv[1];
+ }
+
+ status = rpccli_netr_NetrEnumerateTrustedDomainsEx(cli, mem_ctx,
+ server_name,
+ &list,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("success\n");
+ }
+ done:
+ return werr;
+}
+
+
+/* List of commands exported by this module */
+
+struct cmd_set netlogon_commands[] = {
+
+ { "NETLOGON" },
+
+ { "logonctrl2", RPC_RTYPE_WERROR, NULL, cmd_netlogon_logon_ctrl2, &ndr_table_netlogon.syntax_id, NULL, "Logon Control 2", "" },
+ { "getanydcname", RPC_RTYPE_WERROR, NULL, cmd_netlogon_getanydcname, &ndr_table_netlogon.syntax_id, NULL, "Get trusted DC name", "" },
+ { "getdcname", RPC_RTYPE_WERROR, NULL, cmd_netlogon_getdcname, &ndr_table_netlogon.syntax_id, NULL, "Get trusted PDC name", "" },
+ { "dsr_getdcname", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getdcname, &ndr_table_netlogon.syntax_id, NULL, "Get trusted DC name", "" },
+ { "dsr_getdcnameex", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getdcnameex, &ndr_table_netlogon.syntax_id, NULL, "Get trusted DC name", "" },
+ { "dsr_getdcnameex2", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getdcnameex2, &ndr_table_netlogon.syntax_id, NULL, "Get trusted DC name", "" },
+ { "dsr_getsitename", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getsitename, &ndr_table_netlogon.syntax_id, NULL, "Get sitename", "" },
+ { "dsr_getforesttrustinfo", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_getforesttrustinfo, &ndr_table_netlogon.syntax_id, NULL, "Get Forest Trust Info", "" },
+ { "logonctrl", RPC_RTYPE_WERROR, NULL, cmd_netlogon_logon_ctrl, &ndr_table_netlogon.syntax_id, NULL, "Logon Control", "" },
+ { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, &ndr_table_netlogon.syntax_id, NULL, "Sam Synchronisation", "" },
+ { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, &ndr_table_netlogon.syntax_id, NULL, "Query Sam Deltas", "" },
+ { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, &ndr_table_netlogon.syntax_id, NULL, "Sam Logon", "" },
+ { "change_trust_pw", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, &ndr_table_netlogon.syntax_id, NULL, "Change Trust Account Password", "" },
+ { "gettrustrid", RPC_RTYPE_WERROR, NULL, cmd_netlogon_gettrustrid, &ndr_table_netlogon.syntax_id, NULL, "Get trust rid", "" },
+ { "dsr_enumtrustdom", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_enumtrustdom, &ndr_table_netlogon.syntax_id, NULL, "Enumerate trusted domains", "" },
+ { "dsenumdomtrusts", RPC_RTYPE_WERROR, NULL, cmd_netlogon_dsr_enumtrustdom, &ndr_table_netlogon.syntax_id, NULL, "Enumerate all trusted domains in an AD forest", "" },
+ { "deregisterdnsrecords", RPC_RTYPE_WERROR, NULL, cmd_netlogon_deregisterdnsrecords, &ndr_table_netlogon.syntax_id, NULL, "Deregister DNS records", "" },
+ { "netrenumtrusteddomains", RPC_RTYPE_WERROR, NULL, cmd_netlogon_enumtrusteddomains, &ndr_table_netlogon.syntax_id, NULL, "Enumerate trusted domains", "" },
+ { "netrenumtrusteddomainsex", RPC_RTYPE_WERROR, NULL, cmd_netlogon_enumtrusteddomainsex, &ndr_table_netlogon.syntax_id, NULL, "Enumerate trusted domains", "" },
+
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_ntsvcs.c b/source3/rpcclient/cmd_ntsvcs.c
new file mode 100644
index 0000000000..377a8a2a00
--- /dev/null
+++ b/source3/rpcclient/cmd_ntsvcs.c
@@ -0,0 +1,229 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Günther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static WERROR cmd_ntsvcs_get_version(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ uint16_t version;
+
+ status = rpccli_PNP_GetVersion(cli, mem_ctx,
+ &version, &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("version: %d\n", version);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_ntsvcs_validate_dev_inst(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ const char *devicepath = NULL;
+ uint32_t flags = 0;
+
+ if (argc < 2 || argc > 3) {
+ printf("usage: %s [devicepath] <flags>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ devicepath = argv[1];
+
+ if (argc >= 3) {
+ flags = atoi(argv[2]);
+ }
+
+ status = rpccli_PNP_ValidateDeviceInstance(cli, mem_ctx,
+ devicepath,
+ flags,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_ntsvcs_get_device_list_size(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ const char *devicename = NULL;
+ uint32_t flags = 0;
+ uint32_t size = 0;
+
+ if (argc < 2 || argc > 4) {
+ printf("usage: %s [devicename] <flags>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ devicename = argv[1];
+
+ if (argc >= 3) {
+ flags = atoi(argv[2]);
+ }
+
+ status = rpccli_PNP_GetDeviceListSize(cli, mem_ctx,
+ devicename,
+ &size,
+ flags,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("size: %d\n", size);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_ntsvcs_hw_prof_flags(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ const char *devicepath = NULL;
+ uint32_t unk3 = 0;
+ uint16_t unk4 = 0;
+ const char *unk5 = NULL;
+ const char *unk5a = NULL;
+
+ if (argc < 2) {
+ printf("usage: %s [devicepath]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ devicepath = argv[1];
+
+ status = rpccli_PNP_HwProfFlags(cli, mem_ctx,
+ 0,
+ devicepath,
+ 0,
+ &unk3,
+ &unk4,
+ unk5,
+ &unk5a,
+ 0,
+ 0,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_ntsvcs_get_hw_prof_info(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ uint32_t idx = 0;
+ struct PNP_HwProfInfo info;
+ uint32_t unknown1 = 0, unknown2 = 0;
+
+ ZERO_STRUCT(info);
+
+ status = rpccli_PNP_GetHwProfInfo(cli, mem_ctx,
+ idx,
+ &info,
+ unknown1,
+ unknown2,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_ntsvcs_get_dev_reg_prop(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ const char *devicepath = NULL;
+ uint32_t property = DEV_REGPROP_DESC;
+ uint32_t unknown1 = 0;
+ uint8_t buffer;
+ uint32_t buffer_size = 0;
+ uint32_t unknown2 = 0;
+ uint32_t unknown3 = 0;
+
+ if (argc < 2) {
+ printf("usage: %s [devicepath]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ devicepath = argv[1];
+
+ status = rpccli_PNP_GetDeviceRegProp(cli, mem_ctx,
+ devicepath,
+ property,
+ &unknown1,
+ &buffer,
+ &buffer_size,
+ &unknown2,
+ unknown3,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+
+struct cmd_set ntsvcs_commands[] = {
+
+ { "NTSVCS" },
+ { "ntsvcs_getversion", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_get_version, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS version", "" },
+ { "ntsvcs_validatedevinst", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_validate_dev_inst, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS device instance", "" },
+ { "ntsvcs_getdevlistsize", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_get_device_list_size, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS get device list", "" },
+ { "ntsvcs_hwprofflags", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_hw_prof_flags, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS HW prof flags", "" },
+ { "ntsvcs_hwprofinfo", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_get_hw_prof_info, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS HW prof info", "" },
+ { "ntsvcs_getdevregprop", RPC_RTYPE_WERROR, NULL, cmd_ntsvcs_get_dev_reg_prop, &ndr_table_ntsvcs.syntax_id, NULL, "Query NTSVCS device registry property", "" },
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
new file mode 100644
index 0000000000..fa1e0fda4d
--- /dev/null
+++ b/source3/rpcclient/cmd_samr.c
@@ -0,0 +1,2763 @@
+/*
+ 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
+ Copyright (C) Guenther Deschner 2008
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+extern DOM_SID domain_sid;
+
+/****************************************************************************
+ display samr_user_info_7 structure
+ ****************************************************************************/
+static void display_samr_user_info_7(struct samr_UserInfo7 *r)
+{
+ printf("\tUser Name :\t%s\n", r->account_name.string);
+}
+
+/****************************************************************************
+ display samr_user_info_9 structure
+ ****************************************************************************/
+static void display_samr_user_info_9(struct samr_UserInfo9 *r)
+{
+ printf("\tPrimary group RID :\tox%x\n", r->primary_gid);
+}
+
+/****************************************************************************
+ display samr_user_info_16 structure
+ ****************************************************************************/
+static void display_samr_user_info_16(struct samr_UserInfo16 *r)
+{
+ printf("\tAcct Flags :\tox%x\n", r->acct_flags);
+}
+
+/****************************************************************************
+ display samr_user_info_20 structure
+ ****************************************************************************/
+static void display_samr_user_info_20(struct samr_UserInfo20 *r)
+{
+ printf("\tRemote Dial :\n");
+ dump_data(0, (uint8_t *)r->parameters.array, r->parameters.length*2);
+}
+
+
+/****************************************************************************
+ display samr_user_info_21 structure
+ ****************************************************************************/
+static void display_samr_user_info_21(struct samr_UserInfo21 *r)
+{
+ printf("\tUser Name :\t%s\n", r->account_name.string);
+ printf("\tFull Name :\t%s\n", r->full_name.string);
+ printf("\tHome Drive :\t%s\n", r->home_directory.string);
+ printf("\tDir Drive :\t%s\n", r->home_drive.string);
+ printf("\tProfile Path:\t%s\n", r->profile_path.string);
+ printf("\tLogon Script:\t%s\n", r->logon_script.string);
+ printf("\tDescription :\t%s\n", r->description.string);
+ printf("\tWorkstations:\t%s\n", r->workstations.string);
+ printf("\tComment :\t%s\n", r->comment.string);
+ printf("\tRemote Dial :\n");
+ dump_data(0, (uint8_t *)r->parameters.array, r->parameters.length*2);
+
+ printf("\tLogon Time :\t%s\n",
+ http_timestring(nt_time_to_unix(r->last_logon)));
+ printf("\tLogoff Time :\t%s\n",
+ http_timestring(nt_time_to_unix(r->last_logoff)));
+ printf("\tKickoff Time :\t%s\n",
+ http_timestring(nt_time_to_unix(r->acct_expiry)));
+ printf("\tPassword last set Time :\t%s\n",
+ http_timestring(nt_time_to_unix(r->last_password_change)));
+ printf("\tPassword can change Time :\t%s\n",
+ http_timestring(nt_time_to_unix(r->allow_password_change)));
+ printf("\tPassword must change Time:\t%s\n",
+ http_timestring(nt_time_to_unix(r->force_password_change)));
+
+ printf("\tunknown_2[0..31]...\n"); /* user passwords? */
+
+ printf("\tuser_rid :\t0x%x\n" , r->rid); /* User ID */
+ printf("\tgroup_rid:\t0x%x\n" , r->primary_gid); /* Group ID */
+ printf("\tacb_info :\t0x%08x\n", r->acct_flags); /* Account Control Info */
+
+ printf("\tfields_present:\t0x%08x\n", r->fields_present); /* 0x00ff ffff */
+ printf("\tlogon_divs:\t%d\n", r->logon_hours.units_per_week); /* 0x0000 00a8 which is 168 which is num hrs in a week */
+ printf("\tbad_password_count:\t0x%08x\n", r->bad_password_count);
+ printf("\tlogon_count:\t0x%08x\n", r->logon_count);
+
+ printf("\tpadding1[0..7]...\n");
+
+ if (r->logon_hours.bits) {
+ printf("\tlogon_hrs[0..%d]...\n", r->logon_hours.units_per_week/8);
+ }
+}
+
+
+static void display_password_properties(uint32_t password_properties)
+{
+ printf("password_properties: 0x%08x\n", password_properties);
+
+ if (password_properties & DOMAIN_PASSWORD_COMPLEX)
+ printf("\tDOMAIN_PASSWORD_COMPLEX\n");
+
+ if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
+ printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
+
+ if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
+ printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
+
+ if (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)
+ printf("\tDOMAIN_PASSWORD_LOCKOUT_ADMINS\n");
+
+ if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
+ printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
+
+ if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
+ printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
+}
+
+static void display_sam_dom_info_1(struct samr_DomInfo1 *info1)
+{
+ printf("Minimum password length:\t\t\t%d\n",
+ info1->min_password_length);
+ printf("Password uniqueness (remember x passwords):\t%d\n",
+ info1->password_history_length);
+ display_password_properties(info1->password_properties);
+ printf("password expire in:\t\t\t\t%s\n",
+ display_time(info1->max_password_age));
+ printf("Min password age (allow changing in x days):\t%s\n",
+ display_time(info1->min_password_age));
+}
+
+static void display_sam_dom_info_2(struct samr_DomInfo2 *info2)
+{
+ printf("Domain:\t\t%s\n", info2->domain_name.string);
+ printf("Server:\t\t%s\n", info2->primary.string);
+ printf("Comment:\t%s\n", info2->comment.string);
+
+ printf("Total Users:\t%d\n", info2->num_users);
+ printf("Total Groups:\t%d\n", info2->num_groups);
+ printf("Total Aliases:\t%d\n", info2->num_aliases);
+
+ printf("Sequence No:\t%llu\n", (unsigned long long)info2->sequence_num);
+
+ printf("Force Logoff:\t%d\n",
+ (int)nt_time_to_unix_abs(&info2->force_logoff_time));
+
+ printf("Unknown 2:\t0x%x\n", info2->unknown2);
+ printf("Server Role:\t%s\n", server_role_str(info2->role));
+ printf("Unknown 3:\t0x%x\n", info2->unknown3);
+}
+
+static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
+{
+ printf("Force Logoff:\t%d\n",
+ (int)nt_time_to_unix_abs(&info3->force_logoff_time));
+}
+
+static void display_sam_dom_info_4(struct samr_DomInfo4 *info4)
+{
+ printf("Comment:\t%s\n", info4->comment.string);
+}
+
+static void display_sam_dom_info_5(struct samr_DomInfo5 *info5)
+{
+ printf("Domain:\t\t%s\n", info5->domain_name.string);
+}
+
+static void display_sam_dom_info_6(struct samr_DomInfo6 *info6)
+{
+ printf("Server:\t\t%s\n", info6->primary.string);
+}
+
+static void display_sam_dom_info_7(struct samr_DomInfo7 *info7)
+{
+ printf("Server Role:\t%s\n", server_role_str(info7->role));
+}
+
+static void display_sam_dom_info_8(struct samr_DomInfo8 *info8)
+{
+ printf("Sequence No:\t%llu\n", (unsigned long long)info8->sequence_num);
+ printf("Domain Create Time:\t%s\n",
+ http_timestring(nt_time_to_unix(info8->domain_create_time)));
+}
+
+static void display_sam_dom_info_9(struct samr_DomInfo9 *info9)
+{
+ printf("unknown:\t%d (0x%08x)\n", info9->unknown, info9->unknown);
+}
+
+static void display_sam_dom_info_12(struct samr_DomInfo12 *info12)
+{
+ printf("Bad password lockout duration: %s\n",
+ display_time(info12->lockout_duration));
+ printf("Reset Lockout after: %s\n",
+ display_time(info12->lockout_window));
+ printf("Lockout after bad attempts: %d\n",
+ info12->lockout_threshold);
+}
+
+static void display_sam_dom_info_13(struct samr_DomInfo13 *info13)
+{
+ printf("Sequence No:\t%llu\n", (unsigned long long)info13->sequence_num);
+ printf("Domain Create Time:\t%s\n",
+ http_timestring(nt_time_to_unix(info13->domain_create_time)));
+ printf("Unknown1:\t%d\n", info13->unknown1);
+ printf("Unknown2:\t%d\n", info13->unknown2);
+
+}
+
+static void display_sam_info_1(struct samr_DispEntryGeneral *r)
+{
+ printf("index: 0x%x ", r->idx);
+ printf("RID: 0x%x ", r->rid);
+ printf("acb: 0x%08x ", r->acct_flags);
+ printf("Account: %s\t", r->account_name.string);
+ printf("Name: %s\t", r->full_name.string);
+ printf("Desc: %s\n", r->description.string);
+}
+
+static void display_sam_info_2(struct samr_DispEntryFull *r)
+{
+ printf("index: 0x%x ", r->idx);
+ printf("RID: 0x%x ", r->rid);
+ printf("acb: 0x%08x ", r->acct_flags);
+ printf("Account: %s\t", r->account_name.string);
+ printf("Desc: %s\n", r->description.string);
+}
+
+static void display_sam_info_3(struct samr_DispEntryFullGroup *r)
+{
+ printf("index: 0x%x ", r->idx);
+ printf("RID: 0x%x ", r->rid);
+ printf("acb: 0x%08x ", r->acct_flags);
+ printf("Account: %s\t", r->account_name.string);
+ printf("Desc: %s\n", r->description.string);
+}
+
+static void display_sam_info_4(struct samr_DispEntryAscii *r)
+{
+ printf("index: 0x%x ", r->idx);
+ printf("Account: %s\n", r->account_name.string);
+}
+
+static void display_sam_info_5(struct samr_DispEntryAscii *r)
+{
+ printf("index: 0x%x ", r->idx);
+ printf("Account: %s\n", r->account_name.string);
+}
+
+/**********************************************************************
+ * Query user information
+ */
+static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *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;
+ union samr_UserInfo *info = NULL;
+ uint32 user_rid = 0;
+
+ 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);
+
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ user_rid,
+ &user_pol);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
+ (user_rid == 0)) {
+
+ /* Probably this was a user name, try lookupnames */
+ struct samr_Ids rids, types;
+ struct lsa_String lsa_acct_name;
+
+ init_lsa_String(&lsa_acct_name, argv[1]);
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ 1,
+ &lsa_acct_name,
+ &rids,
+ &types);
+
+ if (NT_STATUS_IS_OK(result)) {
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ rids.ids[0],
+ &user_pol);
+ }
+ }
+
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
+ &user_pol,
+ info_level,
+ &info);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ switch (info_level) {
+ case 7:
+ display_samr_user_info_7(&info->info7);
+ break;
+ case 9:
+ display_samr_user_info_9(&info->info9);
+ break;
+ case 16:
+ display_samr_user_info_16(&info->info16);
+ break;
+ case 20:
+ display_samr_user_info_20(&info->info20);
+ break;
+ case 21:
+ display_samr_user_info_21(&info->info21);
+ break;
+ default:
+ printf("Unsupported infolevel: %d\n", info_level);
+ break;
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+done:
+ return result;
+}
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info1(struct samr_GroupInfoAll *info1)
+{
+ printf("\tGroup Name:\t%s\n", info1->name.string);
+ printf("\tDescription:\t%s\n", info1->description.string);
+ printf("\tGroup Attribute:%d\n", info1->attributes);
+ printf("\tNum Members:%d\n", info1->num_members);
+}
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info2(struct lsa_String *info2)
+{
+ printf("\tGroup Description:%s\n", info2->string);
+}
+
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info3(struct samr_GroupInfoAttributes *info3)
+{
+ printf("\tGroup Attribute:%d\n", info3->attributes);
+}
+
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info4(struct lsa_String *info4)
+{
+ printf("\tGroup Description:%s\n", info4->string);
+}
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info5(struct samr_GroupInfoAll *info5)
+{
+ printf("\tGroup Name:\t%s\n", info5->name.string);
+ printf("\tDescription:\t%s\n", info5->description.string);
+ printf("\tGroup Attribute:%d\n", info5->attributes);
+ printf("\tNum Members:%d\n", info5->num_members);
+}
+
+/****************************************************************************
+ display sam sync structure
+ ****************************************************************************/
+static void display_group_info(union samr_GroupInfo *info,
+ enum samr_GroupInfoEnum level)
+{
+ switch (level) {
+ case 1:
+ display_group_info1(&info->all);
+ break;
+ case 2:
+ display_group_info2(&info->name);
+ break;
+ case 3:
+ display_group_info3(&info->attributes);
+ break;
+ case 4:
+ display_group_info4(&info->description);
+ break;
+ case 5:
+ display_group_info5(&info->all2);
+ break;
+ }
+}
+
+/***********************************************************************
+ * Query group information
+ */
+static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ enum samr_GroupInfoEnum info_level = GROUPINFOALL;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ union samr_GroupInfo *group_info = NULL;
+ 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)
+ info_level = atoi(argv[2]);
+
+ if (argc > 3)
+ sscanf(argv[3], "%x", &access_mask);
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenGroup(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ group_rid,
+ &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_QueryGroupInfo(cli, mem_ctx,
+ &group_pol,
+ info_level,
+ &group_info);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ display_group_info(group_info, info_level);
+
+ rpccli_samr_Close(cli, mem_ctx, &group_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+done:
+ return result;
+}
+
+/* Query groups a user is a member of */
+
+static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol,
+ domain_pol,
+ user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 user_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ int i;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+
+ 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);
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ user_rid,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
+ &user_pol,
+ &rid_array);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < rid_array->count; i++) {
+ printf("\tgroup rid:[0x%x] attr:[0x%x]\n",
+ rid_array->rids[i].rid,
+ rid_array->rids[i].attributes);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Query aliases a user is a member of */
+
+static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID *sids;
+ size_t num_sids;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ int i;
+ struct lsa_SidArray sid_array;
+ struct samr_Ids alias_rids;
+
+ if (argc < 3) {
+ printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ sids = NULL;
+ num_sids = 0;
+
+ for (i=2; i<argc; i++) {
+ DOM_SID tmp_sid;
+ if (!string_to_sid(&tmp_sid, argv[i])) {
+ printf("%s is not a legal SID\n", argv[i]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ result = add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+ }
+
+ if (num_sids) {
+ sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_sids);
+ if (sid_array.sids == NULL)
+ return NT_STATUS_NO_MEMORY;
+ } else {
+ sid_array.sids = NULL;
+ }
+
+ for (i=0; i<num_sids; i++) {
+ sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[i]);
+ if (!sid_array.sids[i].sid) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ sid_array.num_sids = num_sids;
+
+ result = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
+ &domain_pol);
+ else {
+ printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
+ &domain_pol,
+ &sid_array,
+ &alias_rids);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < alias_rids.count; i++) {
+ printf("\tgroup rid:[0x%x]\n", alias_rids.ids[i]);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Query members of a group */
+
+static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 group_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ int i;
+ unsigned int old_timeout;
+ struct samr_RidTypeArray *rids = NULL;
+
+ 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);
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenGroup(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ group_rid,
+ &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Make sure to wait for our DC's reply */
+ old_timeout = rpccli_set_timeout(cli, 30000); /* 30 seconds. */
+ rpccli_set_timeout(cli, MAX(30000, old_timeout)); /* At least 30 sec */
+
+ result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
+ &group_pol,
+ &rids);
+
+ rpccli_set_timeout(cli, old_timeout);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < rids->count; i++) {
+ printf("\trid:[0x%x] attr:[0x%x]\n", rids->rids[i],
+ rids->types[i]);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &group_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Enumerate domain users */
+
+static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *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;
+ struct samr_SamArray *dom_users = NULL;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32 acb_mask = ACB_NORMAL;
+ bool got_connect_pol = False, got_domain_pol = False;
+
+ if ((argc < 1) || (argc > 3)) {
+ printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1)
+ sscanf(argv[1], "%x", &access_mask);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &acb_mask);
+
+ /* Get sam policy handle */
+
+ result = rpccli_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 = rpccli_samr_OpenDomain(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 = rpccli_samr_EnumDomainUsers(cli, mem_ctx,
+ &domain_pol,
+ &start_idx,
+ acb_mask,
+ &dom_users,
+ size,
+ &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("user:[%s] rid:[0x%x]\n",
+ dom_users->entries[i].name.string,
+ dom_users->entries[i].idx);
+ }
+
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Enumerate domain groups */
+
+static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *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 samr_SamArray *dom_groups = NULL;
+ 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 = rpccli_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 = rpccli_samr_OpenDomain(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 = rpccli_samr_EnumDomainGroups(cli, mem_ctx,
+ &domain_pol,
+ &start_idx,
+ &dom_groups,
+ size,
+ &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->entries[i].name.string,
+ dom_groups->entries[i].idx);
+ }
+
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Enumerate alias groups */
+
+static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *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 samr_SamArray *als_groups = NULL;
+ bool got_connect_pol = False, got_domain_pol = False;
+
+ 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 = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ CONST_DISCARD(struct dom_sid2 *, &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 = rpccli_samr_EnumDomainAliases(cli, mem_ctx,
+ &domain_pol,
+ &start_idx,
+ &als_groups,
+ size,
+ &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->entries[i].name.string,
+ als_groups->entries[i].idx);
+ }
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_domain_pol)
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+
+ if (got_connect_pol)
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+/* Enumerate domains */
+
+static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx, size, num_entries, i;
+ uint32 access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ bool got_connect_pol = false;
+ struct samr_SamArray *sam = NULL;
+
+ 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 = rpccli_try_samr_connects(cli, mem_ctx,
+ access_mask,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ got_connect_pol = true;
+
+ /* Enumerate alias groups */
+
+ start_idx = 0;
+ size = 0xffff;
+
+ do {
+ result = rpccli_samr_EnumDomains(cli, mem_ctx,
+ &connect_pol,
+ &start_idx,
+ &sam,
+ size,
+ &num_entries);
+
+ if (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
+
+ for (i = 0; i < num_entries; i++)
+ printf("name:[%s] idx:[0x%x]\n",
+ sam->entries[i].name.string,
+ sam->entries[i].idx);
+ }
+ } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
+
+ done:
+ if (got_connect_pol) {
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ }
+
+ return result;
+}
+
+
+/* Query alias membership */
+
+static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *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, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ struct lsa_SidArray sid_array;
+
+ 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 = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
+ &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on alias */
+
+ result = rpccli_samr_OpenAlias(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ alias_rid,
+ &alias_pol);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_GetMembersInAlias(cli, mem_ctx,
+ &alias_pol,
+ &sid_array);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < sid_array.num_sids; i++) {
+ fstring sid_str;
+
+ sid_to_fstring(sid_str, sid_array.sids[i].sid);
+ printf("\tsid:[%s]\n", sid_str);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &alias_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Query alias info */
+
+static NTSTATUS cmd_samr_query_aliasinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, alias_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32_t alias_rid;
+ uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ union samr_AliasInfo *info = NULL;
+ enum samr_AliasInfoEnum level = ALIASINFOALL;
+
+ if ((argc < 3) || (argc > 4)) {
+ printf("Usage: %s builtin|domain rid [level] [access mask]\n",
+ argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[2], "%i", &alias_rid);
+
+ if (argc > 2) {
+ level = atoi(argv[3]);
+ }
+
+ if (argc > 3) {
+ sscanf(argv[4], "%x", &access_mask);
+ }
+
+ /* Open SAMR handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ SEC_FLAG_MAXIMUM_ALLOWED,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Open handle on domain */
+
+ if (strequal(argv[1], "domain")) {
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ SEC_FLAG_MAXIMUM_ALLOWED,
+ &domain_sid,
+ &domain_pol);
+
+ } else if (strequal(argv[1], "builtin")) {
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ SEC_FLAG_MAXIMUM_ALLOWED,
+ CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
+ &domain_pol);
+
+ } else {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Open handle on alias */
+
+ result = rpccli_samr_OpenAlias(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ alias_rid,
+ &alias_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_QueryAliasInfo(cli, mem_ctx,
+ &alias_pol,
+ level,
+ &info);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ switch (level) {
+ case ALIASINFOALL:
+ printf("Name: %s\n", info->all.name.string);
+ printf("Description: %s\n", info->all.description.string);
+ printf("Num Members: %d\n", info->all.num_members);
+ break;
+ case ALIASINFONAME:
+ printf("Name: %s\n", info->name.string);
+ break;
+ case ALIASINFODESCRIPTION:
+ printf("Description: %s\n", info->description.string);
+ break;
+ default:
+ break;
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &alias_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+
+/* Query delete an alias membership */
+
+static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *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;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if (argc != 3) {
+ printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ alias_rid = strtoul(argv[2], NULL, 10);
+
+ /* Open SAMR handle */
+
+ result = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
+ &domain_pol);
+ else
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on alias */
+
+ result = rpccli_samr_OpenAlias(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ alias_rid,
+ &alias_pol);
+ if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
+ /* Probably this was a user name, try lookupnames */
+ struct samr_Ids rids, types;
+ struct lsa_String lsa_acct_name;
+
+ init_lsa_String(&lsa_acct_name, argv[2]);
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ 1,
+ &lsa_acct_name,
+ &rids,
+ &types);
+
+ if (NT_STATUS_IS_OK(result)) {
+ result = rpccli_samr_OpenAlias(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ rids.ids[0],
+ &alias_pol);
+ }
+ }
+
+ result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
+ &alias_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Query display info */
+
+static NTSTATUS cmd_samr_query_dispinfo_internal(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv,
+ uint32_t opcode)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries = 0, i;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32 info_level = 1;
+ union samr_DispInfo info;
+ int loop_count = 0;
+ bool got_params = False; /* Use get_query_dispinfo_params() or not? */
+ uint32_t total_size, returned_size;
+
+ if (argc > 6) {
+ 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 = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Query display info */
+
+ do {
+
+ if (!got_params)
+ get_query_dispinfo_params(
+ loop_count, &max_entries, &max_size);
+
+ switch (opcode) {
+ case NDR_SAMR_QUERYDISPLAYINFO:
+ result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
+ &domain_pol,
+ info_level,
+ start_idx,
+ max_entries,
+ max_size,
+ &total_size,
+ &returned_size,
+ &info);
+ break;
+ case NDR_SAMR_QUERYDISPLAYINFO2:
+ result = rpccli_samr_QueryDisplayInfo2(cli, mem_ctx,
+ &domain_pol,
+ info_level,
+ start_idx,
+ max_entries,
+ max_size,
+ &total_size,
+ &returned_size,
+ &info);
+
+ break;
+ case NDR_SAMR_QUERYDISPLAYINFO3:
+ result = rpccli_samr_QueryDisplayInfo3(cli, mem_ctx,
+ &domain_pol,
+ info_level,
+ start_idx,
+ max_entries,
+ max_size,
+ &total_size,
+ &returned_size,
+ &info);
+
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
+ break;
+ }
+
+ loop_count++;
+
+ switch (info_level) {
+ case 1:
+ num_entries = info.info1.count;
+ break;
+ case 2:
+ num_entries = info.info2.count;
+ break;
+ case 3:
+ num_entries = info.info3.count;
+ break;
+ case 4:
+ num_entries = info.info4.count;
+ break;
+ case 5:
+ num_entries = info.info5.count;
+ break;
+ default:
+ break;
+ }
+
+ start_idx += num_entries;
+
+ if (num_entries == 0)
+ break;
+
+ for (i = 0; i < num_entries; i++) {
+ switch (info_level) {
+ case 1:
+ display_sam_info_1(&info.info1.entries[i]);
+ break;
+ case 2:
+ display_sam_info_2(&info.info2.entries[i]);
+ break;
+ case 3:
+ display_sam_info_3(&info.info3.entries[i]);
+ break;
+ case 4:
+ display_sam_info_4(&info.info4.entries[i]);
+ break;
+ case 5:
+ display_sam_info_5(&info.info5.entries[i]);
+ break;
+ }
+ }
+ } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
+ NDR_SAMR_QUERYDISPLAYINFO);
+}
+
+static NTSTATUS cmd_samr_query_dispinfo2(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
+ NDR_SAMR_QUERYDISPLAYINFO2);
+}
+
+static NTSTATUS cmd_samr_query_dispinfo3(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
+ NDR_SAMR_QUERYDISPLAYINFO3);
+}
+
+/* Query domain info */
+
+static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *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;
+ union samr_DomainInfo *info = NULL;
+
+ if (argc > 3) {
+ 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 = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Query domain info */
+
+ result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
+ &domain_pol,
+ switch_level,
+ &info);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display domain info */
+
+ switch (switch_level) {
+ case 1:
+ display_sam_dom_info_1(&info->info1);
+ break;
+ case 2:
+ display_sam_dom_info_2(&info->info2);
+ break;
+ case 3:
+ display_sam_dom_info_3(&info->info3);
+ break;
+ case 4:
+ display_sam_dom_info_4(&info->info4);
+ break;
+ case 5:
+ display_sam_dom_info_5(&info->info5);
+ break;
+ case 6:
+ display_sam_dom_info_6(&info->info6);
+ break;
+ case 7:
+ display_sam_dom_info_7(&info->info7);
+ break;
+ case 8:
+ display_sam_dom_info_8(&info->info8);
+ break;
+ case 9:
+ display_sam_dom_info_9(&info->info9);
+ break;
+ case 12:
+ display_sam_dom_info_12(&info->info12);
+ break;
+ case 13:
+ display_sam_dom_info_13(&info->info13);
+ break;
+
+ default:
+ printf("cannot display domain info for switch value %d\n",
+ switch_level);
+ break;
+ }
+
+ done:
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ return result;
+}
+
+/* Create domain user */
+
+static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_String acct_name;
+ uint32 acb_info;
+ uint32 acct_flags, user_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32_t access_granted = 0;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s username [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ init_lsa_String(&acct_name, argv[1]);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(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;
+ acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
+ SEC_STD_WRITE_DAC | SEC_STD_DELETE |
+ SAMR_USER_ACCESS_SET_PASSWORD |
+ SAMR_USER_ACCESS_GET_ATTRIBUTES |
+ SAMR_USER_ACCESS_SET_ATTRIBUTES;
+
+ result = rpccli_samr_CreateUser2(cli, mem_ctx,
+ &domain_pol,
+ &acct_name,
+ acb_info,
+ acct_flags,
+ &user_pol,
+ &access_granted,
+ &user_rid);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+/* Create domain group */
+
+static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_String grp_name;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32_t rid = 0;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s groupname [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ init_lsa_String(&grp_name, argv[1]);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Create domain user */
+ result = rpccli_samr_CreateDomainGroup(cli, mem_ctx,
+ &domain_pol,
+ &grp_name,
+ MAXIMUM_ALLOWED_ACCESS,
+ &group_pol,
+ &rid);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+/* Create domain alias */
+
+static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, alias_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_String alias_name;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ uint32_t rid = 0;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s aliasname [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ init_lsa_String(&alias_name, argv[1]);
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Create domain user */
+
+ result = rpccli_samr_CreateDomAlias(cli, mem_ctx,
+ &domain_pol,
+ &alias_name,
+ MAXIMUM_ALLOWED_ACCESS,
+ &alias_pol,
+ &rid);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+/* Lookup sam names */
+
+static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol;
+ uint32 num_names;
+ struct samr_Ids rids, name_types;
+ int i;
+ struct lsa_String *names = NULL;;
+
+ 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 = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ CONST_DISCARD(struct dom_sid2 *, &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;
+
+ if ((names = TALLOC_ARRAY(mem_ctx, struct lsa_String, num_names)) == NULL) {
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < num_names; i++) {
+ init_lsa_String(&names[i], argv[i + 2]);
+ }
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ num_names,
+ names,
+ &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].string, rids.ids[i],
+ name_types.ids[i]);
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Lookup sam rids */
+
+static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol;
+ uint32_t num_rids, *rids;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+
+ int i;
+
+ if (argc < 3) {
+ printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get sam policy and domain handles */
+
+ result = rpccli_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 = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
+ &domain_pol);
+ else
+ return NT_STATUS_OK;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Look up rids */
+
+ num_rids = argc - 2;
+
+ if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < argc - 2; i++)
+ sscanf(argv[i + 2], "%i", &rids[i]);
+
+ result = rpccli_samr_LookupRids(cli, mem_ctx,
+ &domain_pol,
+ num_rids,
+ rids,
+ &names,
+ &types);
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
+ goto done;
+
+ /* Display results */
+
+ for (i = 0; i < num_rids; i++) {
+ printf("rid 0x%x: %s (%d)\n",
+ rids[i], names.names[i].string, types.ids[i]);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
+/* Delete domain group */
+
+static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol, group_pol;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s groupname\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* Get sam policy and domain handles */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get handle on group */
+
+ {
+ struct samr_Ids group_rids, name_types;
+ struct lsa_String lsa_acct_name;
+
+ init_lsa_String(&lsa_acct_name, argv[1]);
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ 1,
+ &lsa_acct_name,
+ &group_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenGroup(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ group_rids.ids[0],
+ &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+ }
+
+ /* Delete group */
+
+ result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
+ &group_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ rpccli_samr_Close(cli, mem_ctx, &group_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ done:
+ return result;
+}
+
+/* Delete domain user */
+
+static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *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 = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get handle on user */
+
+ {
+ struct samr_Ids user_rids, name_types;
+ struct lsa_String lsa_acct_name;
+
+ init_lsa_String(&lsa_acct_name, argv[1]);
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ 1,
+ &lsa_acct_name,
+ &user_rids,
+ &name_types);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ user_rids.ids[0],
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+ }
+
+ /* Delete user */
+
+ result = rpccli_samr_DeleteUser(cli, mem_ctx,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ done:
+ return result;
+}
+
+/**********************************************************************
+ * Query user security object
+ */
+static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *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 sec_info = DACL_SECURITY_INFORMATION;
+ 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 > 3)) {
+ printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
+ printf("\tSpecify rid for security on user, -d for security on domain\n");
+ talloc_destroy(ctx);
+ return NT_STATUS_OK;
+ }
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "-d") == 0)
+ domain = True;
+ else
+ sscanf(argv[1], "%i", &user_rid);
+ }
+
+ if (argc == 3) {
+ sec_info = atoi(argv[2]);
+ }
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (domain || user_rid)
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ if (user_rid)
+ result = rpccli_samr_OpenUser(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 = rpccli_samr_QuerySecurity(cli, mem_ctx,
+ pol,
+ sec_info,
+ &sec_desc_buf);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ display_sec_desc(sec_desc_buf->sd);
+
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+done:
+ talloc_destroy(ctx);
+ return result;
+}
+
+static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ struct samr_PwInfo info;
+ uint32_t rid;
+
+ if (argc != 2) {
+ printf("Usage: %s rid\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &rid);
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ rid,
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
+ if (NT_STATUS_IS_OK(result)) {
+ printf("min_password_length: %d\n", info.min_password_length);
+ printf("%s\n",
+ NDR_PRINT_STRUCT_STRING(mem_ctx,
+ samr_PasswordProperties, &info.password_properties));
+ }
+
+ done:
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_String domain_name;
+ struct samr_PwInfo info;
+
+ if (argc < 1 || argc > 3) {
+ printf("Usage: %s <domain>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ init_lsa_String(&domain_name, argv[1]);
+
+ result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
+
+ if (NT_STATUS_IS_OK(result)) {
+ printf("min_password_length: %d\n", info.min_password_length);
+ display_password_properties(info.password_properties);
+ }
+
+ return result;
+}
+
+/* Look up domain name */
+
+static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ fstring sid_string;
+ struct lsa_String domain_name;
+ DOM_SID *sid = NULL;
+
+ if (argc != 2) {
+ printf("Usage: %s domain_name\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ init_lsa_String(&domain_name, argv[1]);
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ access_mask,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_LookupDomain(cli, mem_ctx,
+ &connect_pol,
+ &domain_name,
+ &sid);
+
+ if (NT_STATUS_IS_OK(result)) {
+ sid_to_fstring(sid_string, sid);
+ printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
+ argv[1], sid_string);
+ }
+
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+done:
+ return result;
+}
+
+/* Change user password */
+
+static NTSTATUS cmd_samr_chgpasswd(struct rpc_pipe_client *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 *user, *oldpass, *newpass;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ struct samr_Ids rids, types;
+ struct lsa_String lsa_acct_name;
+
+ if (argc < 3) {
+ printf("Usage: %s username oldpass newpass\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ user = argv[1];
+ oldpass = argv[2];
+ newpass = argv[3];
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_acct_name, user);
+
+ result = rpccli_samr_LookupNames(cli, mem_ctx,
+ &domain_pol,
+ 1,
+ &lsa_acct_name,
+ &rids,
+ &types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ rids.ids[0],
+ &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Change user password */
+ result = rpccli_samr_chgpasswd_user(cli, mem_ctx,
+ &user_pol,
+ newpass,
+ oldpass);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ if (is_valid_policy_hnd(&user_pol)) {
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
+ }
+ if (is_valid_policy_hnd(&domain_pol)) {
+ rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ }
+ if (is_valid_policy_hnd(&connect_pol)) {
+ rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ }
+
+ return result;
+}
+
+
+/* Change user password */
+
+static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *user, *oldpass, *newpass;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if (argc < 3) {
+ printf("Usage: %s username oldpass newpass\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ user = argv[1];
+ oldpass = argv[2];
+ newpass = argv[3];
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Change user password */
+ result = rpccli_samr_chgpasswd_user2(cli, mem_ctx, user, newpass, oldpass);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+
+/* Change user password */
+
+static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *user, *oldpass, *newpass;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ struct samr_DomInfo1 *info = NULL;
+ struct samr_ChangeReject *reject = NULL;
+
+ if (argc < 3) {
+ printf("Usage: %s username oldpass newpass\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ user = argv[1];
+ oldpass = argv[2];
+ newpass = argv[3];
+
+ /* Get sam policy handle */
+
+ result = rpccli_try_samr_connects(cli, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_pol,
+ access_mask,
+ &domain_sid,
+ &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Change user password */
+ result = rpccli_samr_chgpasswd_user3(cli, mem_ctx,
+ user,
+ newpass,
+ oldpass,
+ &info,
+ &reject);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
+
+ display_sam_dom_info_1(info);
+
+ switch (reject->reason) {
+ case SAMR_REJECT_TOO_SHORT:
+ d_printf("SAMR_REJECT_TOO_SHORT\n");
+ break;
+ case SAMR_REJECT_IN_HISTORY:
+ d_printf("SAMR_REJECT_IN_HISTORY\n");
+ break;
+ case SAMR_REJECT_COMPLEXITY:
+ d_printf("SAMR_REJECT_COMPLEXITY\n");
+ break;
+ case SAMR_REJECT_OTHER:
+ d_printf("SAMR_REJECT_OTHER\n");
+ break;
+ default:
+ d_printf("unknown reject reason: %d\n",
+ reject->reason);
+ break;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+ return result;
+}
+
+static NTSTATUS cmd_samr_get_dispinfo_idx(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS status;
+ struct policy_handle connect_handle;
+ struct policy_handle domain_handle;
+ uint16_t level = 1;
+ struct lsa_String name;
+ uint32_t idx = 0;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s name level\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ init_lsa_String(&name, argv[1]);
+
+ if (argc == 3) {
+ level = atoi(argv[2]);
+ }
+
+ status = rpccli_try_samr_connects(cli, mem_ctx,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &connect_handle);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpccli_samr_OpenDomain(cli, mem_ctx,
+ &connect_handle,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain_sid,
+ &domain_handle);
+
+ if (!NT_STATUS_IS_OK(status))
+ goto done;
+
+
+ status = rpccli_samr_GetDisplayEnumerationIndex(cli, mem_ctx,
+ &domain_handle,
+ level,
+ &name,
+ &idx);
+
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
+ printf("idx: %d (0x%08x)\n", idx, idx);
+ }
+ done:
+
+ if (is_valid_policy_hnd(&domain_handle)) {
+ rpccli_samr_Close(cli, mem_ctx, &domain_handle);
+ }
+ if (is_valid_policy_hnd(&connect_handle)) {
+ rpccli_samr_Close(cli, mem_ctx, &connect_handle);
+ }
+
+ return status;
+
+}
+/* List of commands exported by this module */
+
+struct cmd_set samr_commands[] = {
+
+ { "SAMR" },
+
+ { "queryuser", RPC_RTYPE_NTSTATUS, cmd_samr_query_user, NULL, &ndr_table_samr.syntax_id, NULL, "Query user info", "" },
+ { "querygroup", RPC_RTYPE_NTSTATUS, cmd_samr_query_group, NULL, &ndr_table_samr.syntax_id, NULL, "Query group info", "" },
+ { "queryusergroups", RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups, NULL, &ndr_table_samr.syntax_id, NULL, "Query user groups", "" },
+ { "queryuseraliases", RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases, NULL, &ndr_table_samr.syntax_id, NULL, "Query user aliases", "" },
+ { "querygroupmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem, NULL, &ndr_table_samr.syntax_id, NULL, "Query group membership", "" },
+ { "queryaliasmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem, NULL, &ndr_table_samr.syntax_id, NULL, "Query alias membership", "" },
+ { "queryaliasinfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasinfo, NULL, &ndr_table_samr.syntax_id, NULL, "Query alias info", "" },
+ { "deletealias", RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias, NULL, &ndr_table_samr.syntax_id, NULL, "Delete an alias", "" },
+ { "querydispinfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo, NULL, &ndr_table_samr.syntax_id, NULL, "Query display info", "" },
+ { "querydispinfo2", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo2, NULL, &ndr_table_samr.syntax_id, NULL, "Query display info", "" },
+ { "querydispinfo3", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo3, NULL, &ndr_table_samr.syntax_id, NULL, "Query display info", "" },
+ { "querydominfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo, NULL, &ndr_table_samr.syntax_id, NULL, "Query domain info", "" },
+ { "enumdomusers", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users, NULL, &ndr_table_samr.syntax_id, NULL, "Enumerate domain users", "" },
+ { "enumdomgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups, NULL, &ndr_table_samr.syntax_id, NULL, "Enumerate domain groups", "" },
+ { "enumalsgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups, NULL, &ndr_table_samr.syntax_id, NULL, "Enumerate alias groups", "" },
+ { "enumdomains", RPC_RTYPE_NTSTATUS, cmd_samr_enum_domains, NULL, &ndr_table_samr.syntax_id, NULL, "Enumerate domains", "" },
+
+ { "createdomuser", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user, NULL, &ndr_table_samr.syntax_id, NULL, "Create domain user", "" },
+ { "createdomgroup", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group, NULL, &ndr_table_samr.syntax_id, NULL, "Create domain group", "" },
+ { "createdomalias", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias, NULL, &ndr_table_samr.syntax_id, NULL, "Create domain alias", "" },
+ { "samlookupnames", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names, NULL, &ndr_table_samr.syntax_id, NULL, "Look up names", "" },
+ { "samlookuprids", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids, NULL, &ndr_table_samr.syntax_id, NULL, "Look up names", "" },
+ { "deletedomgroup", RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group, NULL, &ndr_table_samr.syntax_id, NULL, "Delete domain group", "" },
+ { "deletedomuser", RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user, NULL, &ndr_table_samr.syntax_id, NULL, "Delete domain user", "" },
+ { "samquerysecobj", RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj, NULL, &ndr_table_samr.syntax_id, NULL, "Query SAMR security object", "" },
+ { "getdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo, NULL, &ndr_table_samr.syntax_id, NULL, "Retrieve domain password info", "" },
+ { "getusrdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo, NULL, &ndr_table_samr.syntax_id, NULL, "Retrieve user domain password info", "" },
+
+ { "lookupdomain", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain, NULL, &ndr_table_samr.syntax_id, NULL, "Lookup Domain Name", "" },
+ { "chgpasswd", RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd, NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
+ { "chgpasswd2", RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2, NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
+ { "chgpasswd3", RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3, NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
+ { "getdispinfoidx", RPC_RTYPE_NTSTATUS, cmd_samr_get_dispinfo_idx, NULL, &ndr_table_samr.syntax_id, NULL, "Get Display Information Index", "" },
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_shutdown.c b/source3/rpcclient/cmd_shutdown.c
new file mode 100644
index 0000000000..f79c9aad02
--- /dev/null
+++ b/source3/rpcclient/cmd_shutdown.c
@@ -0,0 +1,117 @@
+/*
+ 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,
+ Copyright (C) Jim McDonough (jmcd@us.ibm.com) 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+#if 0 /* don't uncomment this unless you remove the getopt() calls */
+ /* use net rpc shutdown instead */
+
+/****************************************************************************
+nt shutdown init
+****************************************************************************/
+static NTSTATUS cmd_shutdown_init(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':
+ fstrcpy(msg, optarg);
+ /*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_shutdown_init(cli, mem_ctx, msg, timeout, reboot, force);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("cmd_shutdown_init: query succeeded\n"));
+ else
+ DEBUG(5,("cmd_shutdown_init: query failed\n"));
+
+ return result;
+}
+
+/****************************************************************************
+abort a shutdown
+****************************************************************************/
+static NTSTATUS cmd_shutdown_abort(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ result = cli_shutdown_abort(cli, mem_ctx);
+
+ if (NT_STATUS_IS_OK(result))
+ DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
+ else
+ DEBUG(5,("cmd_shutdown_abort: query failed\n"));
+
+ return result;
+}
+#endif
+
+
+/* List of commands exported by this module */
+struct cmd_set shutdown_commands[] = {
+
+ { "SHUTDOWN" },
+
+#if 0
+ { "shutdowninit", RPC_RTYPE_NTSTATUS, cmd_shutdown_init, NULL, &ndr_table_initshutdown.syntax_id, "Remote Shutdown (over shutdown pipe)",
+ "syntax: shutdown [-m message] [-t timeout] [-r] [-h] [-f] (-r == reboot, -h == halt, -f == force)" },
+
+ { "shutdownabort", RPC_RTYPE_NTSTATUS, cmd_shutdown_abort, NULL, &ndr_table_initshutdown.syntax_id, "Abort Shutdown (over shutdown pipe)",
+ "syntax: shutdownabort" },
+#endif
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
new file mode 100644
index 0000000000..2a9f2b82bb
--- /dev/null
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -0,0 +1,2782 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Gerald Carter 2001-2005
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+struct table_node {
+ const char *long_archi;
+ const char *short_archi;
+ int version;
+};
+
+/* The version int is used by getdrivers. Note that
+ all architecture strings that support mutliple
+ versions must be grouped together since enumdrivers
+ uses this property to prevent issuing multiple
+ enumdriver calls for the same arch */
+
+
+static const struct table_node archi_table[]= {
+
+ {"Windows 4.0", "WIN40", 0 },
+ {"Windows NT x86", "W32X86", 2 },
+ {"Windows NT x86", "W32X86", 3 },
+ {"Windows NT R4000", "W32MIPS", 2 },
+ {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
+ {"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
+ {"Windows x64", "x64", 3 },
+ {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.
+****************************************************************************/
+
+static const char *cmd_spoolss_get_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 NULL;
+ }
+
+ /* this might be client code - but shouldn't this be an fstrcpy etc? */
+
+
+ DEBUGADD(108,("index: [%d]\n", i));
+ DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
+ DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
+
+ return archi_table[i].short_archi;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *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 WERR_OK;
+ }
+
+ if (!cli)
+ return WERR_GENERAL_FAILURE;
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+ fstrcpy(printername, argv[1]);
+
+ /* Open the printer handle */
+
+ werror = rpccli_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 = rpccli_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 werror;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+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");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_info_3(PRINTER_INFO_3 *i3)
+{
+ display_sec_desc(i3->secdesc);
+
+ printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_info_7(PRINTER_INFO_7 *i7)
+{
+ fstring guid = "";
+ rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
+ printf("\tguid:[%s]\n", guid);
+ printf("\taction:[0x%x]\n", i7->action);
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *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;
+ fstring name;
+
+ if (argc > 3)
+ {
+ printf("Usage: %s [level] [name]\n", argv[0]);
+ return WERR_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_m(name);
+ }
+
+ ZERO_STRUCT(ctr);
+
+ result = rpccli_spoolss_enum_printers(cli, mem_ctx, 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 result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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" );
+ if ( i2->port_type ) {
+ int comma = 0; /* hack */
+ printf( "[" );
+ if ( i2->port_type & PORT_TYPE_READ ) {
+ printf( "Read" );
+ comma = 1;
+ }
+ if ( i2->port_type & PORT_TYPE_WRITE ) {
+ printf( "%sWrite", comma ? ", " : "" );
+ comma = 1;
+ }
+ /* These two have slightly different interpretations
+ on 95/98/ME but I'm disregarding that for now */
+ if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
+ printf( "%sRedirected", comma ? ", " : "" );
+ comma = 1;
+ }
+ if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
+ printf( "%sNet-Attached", comma ? ", " : "" );
+ }
+ printf( "]\n" );
+ } else {
+ printf( "[Unset]\n" );
+ }
+ printf("\tReserved:\t[%d]\n", i2->reserved);
+ printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 info_level = 1;
+ PORT_INFO_CTR ctr;
+ uint32 returned;
+
+ if (argc > 2) {
+ printf("Usage: %s [level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ /* Enumerate ports */
+
+ ZERO_STRUCT(ctr);
+
+ result = rpccli_spoolss_enum_ports(cli, mem_ctx, 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 result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ 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 WERR_OK;
+ }
+
+ /* Open a printer handle */
+ if (argc == 3) {
+ fstrcpy(comment, argv[2]);
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* get a printer handle */
+ result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ALL_ACCESS, servername,
+ user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+ result = rpccli_spoolss_getprinter(cli, mem_ctx, &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 = rpccli_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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ uint32 info_level = 2;
+ bool opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ fstring printername,
+ servername,
+ user,
+ new_printername;
+
+ if (argc == 1 || argc > 3) {
+ printf("Usage: %s printername new_printername\n", argv[0]);
+
+ return WERR_OK;
+ }
+
+ /* Open a printer handle */
+ if (argc == 3) {
+ fstrcpy(new_printername, argv[2]);
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* get a printer handle */
+ result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ALL_ACCESS, servername,
+ user, &pol);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ opened_hnd = True;
+
+ /* Get printer info */
+ result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* Modify the printername. */
+ init_unistr(&ctr.printers_2->printername, new_printername);
+ ctr.printers_2->devmode = NULL;
+ ctr.printers_2->secdesc = NULL;
+
+ result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+ if (W_ERROR_IS_OK(result))
+ printf("Success in setting printername.\n");
+
+ done:
+ if (opened_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *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;
+
+ if (argc == 1 || argc > 3) {
+ printf("Usage: %s <printername> [level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Open a printer handle */
+ if (argc == 3) {
+ info_level = atoi(argv[2]);
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* get a printer handle */
+
+ result = rpccli_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 = rpccli_spoolss_getprinter(cli, mem_ctx, &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;
+ case 7:
+ display_print_info_7(ctr.printers_7);
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ if (opened_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_reg_value(REGISTRY_VALUE value)
+{
+ char *text = NULL;
+
+ 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_talloc(talloc_tos(),
+ &text,
+ value.data_p,
+ value.size,
+ STR_TERMINATE);
+ printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
+ break;
+ case REG_BINARY: {
+ char *hex = hex_encode(NULL, value.data_p, value.size);
+ size_t i, len;
+ printf("%s: REG_BINARY:", value.valuename);
+ len = strlen(hex);
+ for (i=0; i<len; i++) {
+ if (hex[i] == '\0') {
+ break;
+ }
+ if (i%40 == 0) {
+ putchar('\n');
+ }
+ putchar(hex[i]);
+ }
+ TALLOC_FREE(hex);
+ putchar('\n');
+ break;
+ }
+ case REG_MULTI_SZ: {
+ uint32 i, num_values;
+ char **values;
+
+ if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
+ value.size, &num_values,
+ &values))) {
+ d_printf("reg_pull_multi_sz failed\n");
+ break;
+ }
+
+ for (i=0; i<num_values; i++) {
+ d_printf("%s\n", values[i]);
+ }
+ TALLOC_FREE(values);
+ break;
+ }
+ default:
+ printf("%s: unknown type %d\n", value.valuename, value.type);
+ }
+
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ bool opened_hnd = False;
+ fstring printername,
+ servername,
+ user;
+ 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 WERR_OK;
+ }
+ valuename = argv[2];
+
+ /* Open a printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ if (strncmp(argv[1], ".", sizeof(".")) == 0)
+ fstrcpy(printername, servername);
+ else
+ slprintf(printername, sizeof(servername)-1, "%s\\%s",
+ servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* get a printer handle */
+
+ result = rpccli_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 = rpccli_spoolss_getprinterdata(cli, mem_ctx, &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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR result;
+ bool opened_hnd = False;
+ fstring printername,
+ servername,
+ user;
+ 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 WERR_OK;
+ }
+ valuename = argv[3];
+ keyname = argv[2];
+
+ /* Open a printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ if (strncmp(argv[1], ".", sizeof(".")) == 0)
+ fstrcpy(printername, servername);
+ else
+ slprintf(printername, sizeof(printername)-1, "%s\\%s",
+ servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* get a printer handle */
+
+ result = rpccli_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 = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND pol;
+ WERROR werror;
+ uint32 info_level = 3;
+ bool opened_hnd = False;
+ PRINTER_DRIVER_CTR ctr;
+ fstring printername,
+ servername,
+ user;
+ uint32 i;
+ bool success = False;
+
+ if ((argc == 1) || (argc > 3))
+ {
+ printf("Usage: %s <printername> [level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* get the arguments need to open the printer handle */
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+ slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+ if (argc == 3)
+ info_level = atoi(argv[2]);
+
+ /* Open a printer handle */
+
+ werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ACCESS_USE,
+ servername, user, &pol);
+
+ if (!W_ERROR_IS_OK(werror)) {
+ printf("Error opening printer handle for %s!\n", printername);
+ return werror;
+ }
+
+ opened_hnd = True;
+
+ /* loop through and print driver info level for each architecture */
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+
+ werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
+ archi_table[i].long_archi, archi_table[i].version,
+ &ctr);
+
+ if (!W_ERROR_IS_OK(werror))
+ continue;
+
+ /* need at least one success */
+
+ success = True;
+
+ 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)
+ rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
+
+ if ( success )
+ werror = WERR_OK;
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR werror = WERR_OK;
+ uint32 info_level = 1;
+ PRINTER_DRIVER_CTR ctr;
+ uint32 i, j,
+ returned;
+
+ if (argc > 2) {
+ printf("Usage: enumdrivers [level]\n");
+ return WERR_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++) {
+ /* check to see if we already asked for this architecture string */
+
+ if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
+ continue;
+
+ werror = rpccli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, info_level,
+ archi_table[i].long_archi, &returned, &ctr);
+
+ if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
+ printf ("Server does not support environment [%s]\n",
+ archi_table[i].long_archi);
+ werror = WERR_OK;
+ continue;
+ }
+
+ 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);
+ return WERR_UNKNOWN_LEVEL;
+ }
+ }
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ fstring env;
+ DRIVER_DIRECTORY_CTR ctr;
+
+ if (argc > 2) {
+ printf("Usage: %s [environment]\n", argv[0]);
+ return WERR_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 = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
+
+ if (W_ERROR_IS_OK(result))
+ display_printdriverdir_1(ctr.info1);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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 (char* str, const char* delim, UNISTR* dest,
+ char **saveptr)
+{
+ char *ptr;
+
+ /* get the next token */
+ ptr = strtok_r(str, delim, saveptr);
+
+ /* 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 (ptr && (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,
+ char *args )
+{
+ char *str, *str2;
+ uint32 len, i;
+ char *saveptr = NULL;
+
+ /* fill in the UNISTR fields */
+ str = get_driver_3_param (args, ":", &info->name, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
+ str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
+
+ /* <Comma Separated List of Dependent Files> */
+ /* save the beginning of the string */
+ str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
+ str = str2;
+
+ /* begin to strip out each filename */
+ str = strtok_r(str, ",", &saveptr);
+ len = 0;
+ while (str != NULL)
+ {
+ /* keep a cumlative count of the str lengths */
+ len += strlen(str)+1;
+ str = strtok_r(NULL, ",", &saveptr);
+ }
+
+ /* 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=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
+ {
+ DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
+ return False;
+ }
+ for (i=0; i<len; i++)
+ {
+ SSVAL(&info->dependentfiles[i], 0, str2[i]);
+ }
+ info->dependentfiles[len] = '\0';
+
+ return True;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ uint32 level = 3;
+ PRINTER_DRIVER_CTR ctr;
+ DRIVER_INFO_3 info3;
+ const char *arch;
+ fstring driver_name;
+ char *driver_args;
+
+ /* parse the command arguments */
+ if (argc != 3 && argc != 4)
+ {
+ 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");
+ printf ("\t[version]\n");
+
+ return WERR_OK;
+ }
+
+ /* Fill in the DRIVER_INFO_3 struct */
+ ZERO_STRUCT(info3);
+ if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
+ {
+ printf ("Error Unknown architechture [%s]\n", argv[1]);
+ return WERR_INVALID_PARAM;
+ }
+ else
+ set_drv_info_3_env(&info3, arch);
+
+ driver_args = talloc_strdup( mem_ctx, argv[2] );
+ if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
+ {
+ printf ("Error Invalid parameter list - %s.\n", argv[2]);
+ return WERR_INVALID_PARAM;
+ }
+
+ /* if printer driver version specified, override the default version
+ * used by the architecture. This allows installation of Windows
+ * 2000 (version 3) printer drivers. */
+ if (argc == 4)
+ {
+ info3.version = atoi(argv[3]);
+ }
+
+
+ ctr.info3 = &info3;
+ result = rpccli_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 result;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *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 arguments */
+ if (argc != 5)
+ {
+ printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+
+ /* Fill in the DRIVER_INFO_2 struct */
+ ZERO_STRUCT(info2);
+
+ 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 = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+
+ if (W_ERROR_IS_OK(result))
+ printf ("Printer %s successfully installed.\n", argv[1]);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *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;
+
+ /* parse the command arguments */
+ if (argc != 3)
+ {
+ printf ("Usage: %s <printer> <driver>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ /* Get a printer handle */
+
+ result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ALL_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 = rpccli_spoolss_getprinter(cli, mem_ctx, &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 = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("SetPrinter call failed!\n");
+ goto done;;
+ }
+
+ printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
+
+done:
+ /* Cleanup */
+
+ if (opened_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
+
+ int i;
+ int vers = -1;
+
+ const char *arch = NULL;
+
+ /* parse the command arguments */
+ if (argc < 2 || argc > 4) {
+ printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 3)
+ arch = argv[2];
+ if (argc == 4)
+ vers = atoi (argv[3]);
+
+
+ /* delete the driver for all architectures */
+ for (i=0; archi_table[i].long_archi; i++) {
+
+ if (arch && !strequal( archi_table[i].long_archi, arch))
+ continue;
+
+ if (vers >= 0 && archi_table[i].version != vers)
+ continue;
+
+ /* make the call to remove the driver */
+ result = rpccli_spoolss_deleteprinterdriverex(
+ cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version);
+
+ if ( !W_ERROR_IS_OK(result) )
+ {
+ if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
+ printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
+ argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
+ }
+ }
+ else
+ {
+ printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
+ archi_table[i].long_archi, archi_table[i].version);
+ ret = WERR_OK;
+ }
+ }
+
+ return ret;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result = WERR_OK;
+ fstring servername;
+ int i;
+
+ /* parse the command arguments */
+ if (argc != 2) {
+ printf ("Usage: %s <driver>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+
+ /* delete the driver for all architectures */
+ for (i=0; archi_table[i].long_archi; i++) {
+ /* make the call to remove the driver */
+ result = rpccli_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 result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ char *servername = NULL, *environment = NULL;
+ fstring procdir;
+
+ /* parse the command arguments */
+ if (argc > 2) {
+ printf ("Usage: %s [environment]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
+ return WERR_NOMEM;
+ strupper_m(servername);
+
+ if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
+ PRINTER_DRIVER_ARCHITECTURE) < 0) {
+ SAFE_FREE(servername);
+ return WERR_NOMEM;
+ }
+
+ result = rpccli_spoolss_getprintprocessordirectory(
+ cli, mem_ctx, servername, environment, procdir);
+
+ if (W_ERROR_IS_OK(result))
+ printf("%s\n", procdir);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(environment);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_addform(struct rpc_pipe_client *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 arguments */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+ PRINTER_ALL_ACCESS,
+ servername, cli->auth->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], UNI_STR_TERMINATE);
+
+ /* Add the form */
+
+
+ werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
+
+ done:
+ if (got_handle)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setform(struct rpc_pipe_client *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 arguments */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = rpccli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->auth->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], UNI_STR_TERMINATE);
+
+ /* Set the form */
+
+ werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
+
+ done:
+ if (got_handle)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static const char *get_form_flag(int form_flag)
+{
+ switch (form_flag) {
+ case FORM_USER:
+ return "FORM_USER";
+ case FORM_BUILTIN:
+ return "FORM_BUILTIN";
+ case FORM_PRINTER:
+ return "FORM_PRINTER";
+ default:
+ return "unknown";
+ }
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_form(FORM_1 *form)
+{
+ fstring form_name = "";
+
+ if (form->name.buffer)
+ rpcstr_pull(form_name, form->name.buffer,
+ sizeof(form_name), -1, STR_TERMINATE);
+
+ printf("%s\n" \
+ "\tflag: %s (%d)\n" \
+ "\twidth: %d, length: %d\n" \
+ "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
+ form_name, get_form_flag(form->flag), form->flag,
+ form->width, form->length,
+ form->left, form->right,
+ form->top, form->bottom);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getform(struct rpc_pipe_client *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;
+
+ /* Parse the command arguments */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = rpccli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->auth->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Get the form */
+
+ werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ display_form(&form);
+
+ done:
+ if (got_handle)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *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 arguments */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = rpccli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->auth->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Delete the form */
+
+ werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
+
+ done:
+ if (got_handle)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *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 num_forms, level = 1, i;
+ FORM_1 *forms;
+
+ /* Parse the command arguments */
+
+ if (argc != 2) {
+ printf ("Usage: %s <printer>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = rpccli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->auth->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Enumerate forms */
+
+ werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ /* Display output */
+
+ for (i = 0; i < num_forms; i++) {
+
+ display_form(&forms[i]);
+
+ }
+
+ done:
+ if (got_handle)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return werror;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ fstring servername, printername, user;
+ POLICY_HND pol;
+ bool opened_hnd = False;
+ PRINTER_INFO_CTR ctr;
+ PRINTER_INFO_0 info;
+ REGISTRY_VALUE value;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+
+ /* parse the command arguments */
+ if (argc < 5) {
+ printf ("Usage: %s <printer> <string|binary|dword|multistring>"
+ " <value> <data>\n",
+ argv[0]);
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+ fstrcpy(user, cli->auth->user_name);
+
+ value.type = REG_NONE;
+
+ if (strequal(argv[2], "string")) {
+ value.type = REG_SZ;
+ }
+
+ if (strequal(argv[2], "binary")) {
+ value.type = REG_BINARY;
+ }
+
+ if (strequal(argv[2], "dword")) {
+ value.type = REG_DWORD;
+ }
+
+ if (strequal(argv[2], "multistring")) {
+ value.type = REG_MULTI_SZ;
+ }
+
+ if (value.type == REG_NONE) {
+ printf("Unknown data type: %s\n", argv[2]);
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ /* get a printer handle */
+ result = rpccli_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 = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ printf("%s\n", current_timestring(tmp_ctx, True));
+ printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
+
+ /* Set the printer data */
+
+ fstrcpy(value.valuename, argv[3]);
+
+ switch (value.type) {
+ case REG_SZ: {
+ UNISTR2 data;
+ init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
+ value.size = data.uni_str_len * 2;
+ if (value.size) {
+ value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
+ value.size);
+ } else {
+ value.data_p = NULL;
+ }
+ break;
+ }
+ case REG_DWORD: {
+ uint32 data = strtoul(argv[4], NULL, 10);
+ value.size = sizeof(data);
+ if (sizeof(data)) {
+ value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
+ sizeof(data));
+ } else {
+ value.data_p = NULL;
+ }
+ break;
+ }
+ case REG_BINARY: {
+ DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
+ value.data_p = data.data;
+ value.size = data.length;
+ break;
+ }
+ case REG_MULTI_SZ: {
+ int i;
+ size_t len = 0;
+ char *p;
+
+ for (i=4; i<argc; i++) {
+ if (strcmp(argv[i], "NULL") == 0) {
+ argv[i] = "";
+ }
+ len += strlen(argv[i])+1;
+ }
+
+ value.size = len*2;
+ value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
+ if (value.data_p == NULL) {
+ result = WERR_NOMEM;
+ goto done;
+ }
+
+ p = (char *)value.data_p;
+ len = value.size;
+ for (i=4; i<argc; i++) {
+ size_t l = (strlen(argv[i])+1)*2;
+ rpcstr_push(p, argv[i], len, STR_TERMINATE);
+ p += l;
+ len -= l;
+ }
+ SMB_ASSERT(len == 0);
+ break;
+ }
+ default:
+ printf("Unknown data type: %s\n", argv[2]);
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
+ goto done;
+ }
+ printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
+
+ result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ printf("%s\n", current_timestring(tmp_ctx, True));
+ printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
+
+done:
+ /* cleanup */
+ TALLOC_FREE(tmp_ctx);
+ if (opened_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+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);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 level = 1, num_jobs, i;
+ bool got_hnd = False;
+ char *printername = NULL;
+ fstring servername, user;
+ POLICY_HND hnd;
+ JOB_INFO_CTR ctr;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s printername [level]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 3)
+ level = atoi(argv[2]);
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+ printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+ strupper_m(printername);
+ printername = talloc_asprintf_append(printername, "%s", argv[1]);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+
+ result = rpccli_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 = rpccli_spoolss_enumjobs(cli, mem_ctx, &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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 i=0, val_needed, data_needed;
+ bool got_hnd = False;
+ char *printername = NULL;
+ fstring servername, user;
+ POLICY_HND hnd;
+
+ if (argc != 2) {
+ printf("Usage: %s printername\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+ printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+ strupper_m(printername);
+ printername = talloc_asprintf_append(printername, "%s", argv[1]);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+
+ result = rpccli_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 = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
+ &val_needed, &data_needed,
+ NULL);
+ while (W_ERROR_IS_OK(result)) {
+ REGISTRY_VALUE value;
+ result = rpccli_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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ uint32 i;
+ bool got_hnd = False;
+ char *printername = NULL;
+ fstring servername, user;
+ const char *keyname = NULL;
+ POLICY_HND hnd;
+ REGVAL_CTR *ctr = NULL;
+
+ if (argc != 3) {
+ printf("Usage: %s printername <keyname>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ keyname = argv[2];
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+
+ printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+ strupper_m(printername);
+ printername = talloc_asprintf_append(printername, "%s", argv[1]);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+
+ result = rpccli_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 */
+
+ if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
+ return WERR_NOMEM;
+
+ result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &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]));
+ }
+
+ TALLOC_FREE( ctr );
+
+done:
+ if (got_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ WERROR result;
+ bool got_hnd = False;
+ char *printername = NULL;
+ 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 WERR_OK;
+ }
+
+ if (argc == 3)
+ keyname = argv[2];
+ else
+ keyname = "";
+
+ /* Open printer handle */
+
+ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+ strupper_m(servername);
+ fstrcpy(user, cli->auth->user_name);
+
+ printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+ strupper_m(printername);
+ printername = talloc_asprintf_append(printername, "%s", argv[1]);
+ if (!printername) {
+ return WERR_NOMEM;
+ }
+
+
+ result = rpccli_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 = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ curkey = keylist;
+ while (*curkey != 0) {
+ char *subkey = NULL;
+ rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
+ STR_TERMINATE);
+ if (!subkey) {
+ break;
+ }
+ printf("%s\n", subkey);
+ curkey += strlen(subkey) + 1;
+ }
+
+done:
+
+ SAFE_FREE(keylist);
+
+ if (got_hnd)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *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_m(servername);
+
+ slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s",
+ cli->desthost, argv[1]);
+ strupper_m(printername);
+
+ result = rpccli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->auth->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 = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
+ if (option.ctr.type == NULL) {
+ result = WERR_NOMEM;
+ goto done;
+ }
+
+ 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_m(servername);
+
+ result = rpccli_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)
+ rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+ struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+ PRINTER_INFO_CTR ctr1, ctr2;
+ WERROR werror;
+ TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
+
+ printf("Retrieving printer propertiesfor %s...", cli1->desthost);
+ werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ talloc_destroy(mem_ctx);
+ return False;
+ }
+ printf("ok\n");
+
+ printf("Retrieving printer properties for %s...", cli2->desthost);
+ werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ talloc_destroy(mem_ctx);
+ return False;
+ }
+ printf("ok\n");
+
+ talloc_destroy(mem_ctx);
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+ struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+ PRINTER_INFO_CTR ctr1, ctr2;
+ WERROR werror;
+ TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
+ SEC_DESC *sd1, *sd2;
+ bool result = True;
+
+
+ printf("Retrieving printer security for %s...", cli1->desthost);
+ werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ result = False;
+ goto done;
+ }
+ printf("ok\n");
+
+ printf("Retrieving printer security for %s...", cli2->desthost);
+ werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ result = False;
+ goto done;
+ }
+ printf("ok\n");
+
+
+ printf("++ ");
+
+ if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
+ printf("NULL PRINTER_INFO_3!\n");
+ result = False;
+ goto done;
+ }
+
+ sd1 = ctr1.printers_3->secdesc;
+ sd2 = ctr2.printers_3->secdesc;
+
+ if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
+ printf("NULL secdesc!\n");
+ result = False;
+ goto done;
+ }
+
+ if (!sec_desc_equal( sd1, sd2 ) ) {
+ printf("Security Descriptors *not* equal!\n");
+ result = False;
+ goto done;
+ }
+
+ printf("Security descriptors match\n");
+
+done:
+ talloc_destroy(mem_ctx);
+ return result;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ fstring printername, servername1, servername2;
+ char *printername_path = NULL;
+ struct cli_state *cli_server1 = rpc_pipe_np_smb_conn(cli);
+ struct cli_state *cli_server2 = NULL;
+ struct rpc_pipe_client *cli2 = NULL;
+ POLICY_HND hPrinter1, hPrinter2;
+ NTSTATUS nt_status;
+ WERROR werror;
+
+ if ( argc != 3 ) {
+ printf("Usage: %s <printer> <server>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ fstrcpy( printername, argv[1] );
+
+ fstrcpy( servername1, cli->desthost );
+ fstrcpy( servername2, argv[2] );
+ strupper_m( servername1 );
+ strupper_m( servername2 );
+
+ /* first get the connection to the remote server */
+
+ nt_status = cli_full_connection(&cli_server2, global_myname(), servername2,
+ NULL, 0,
+ "IPC$", "IPC",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+ get_cmdline_auth_info_signing_state(), NULL);
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
+ return WERR_GENERAL_FAILURE;
+
+ nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
+ &cli2);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ printf("failed to open spoolss pipe on server %s (%s)\n",
+ servername2, nt_errstr(nt_status));
+ return WERR_GENERAL_FAILURE;
+ }
+
+ /* now open up both printers */
+
+ printername_path = talloc_asprintf(mem_ctx,
+ "\\\\%s\\%s",
+ servername1,
+ printername);
+ if (!printername_path) {
+ return WERR_NOMEM;
+ }
+ printf("Opening %s...", printername_path);
+ werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path,
+ "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ goto done;
+ }
+ printf("ok\n");
+
+ printername_path = talloc_asprintf(mem_ctx,
+ "\\\\%s\\%s",
+ servername2,
+ printername);
+ if (!printername_path) {
+ return WERR_NOMEM;
+ }
+ printf("Opening %s...", printername_path);
+ werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,
+ "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
+ if ( !W_ERROR_IS_OK(werror) ) {
+ printf("failed (%s)\n", dos_errstr(werror));
+ goto done;
+ }
+ printf("ok\n");
+
+ compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
+ compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
+#if 0
+ compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
+#endif
+
+
+done:
+ /* cleanup */
+
+ printf("Closing printers...");
+ rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
+ rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
+ printf("ok\n");
+
+ /* close the second remote connection */
+
+ cli_shutdown( cli_server2 );
+ return WERR_OK;
+}
+
+/* List of commands exported by this module */
+struct cmd_set spoolss_commands[] = {
+
+ { "SPOOLSS" },
+
+ { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, &syntax_spoolss, NULL, "Add a print driver", "" },
+ { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, &syntax_spoolss, NULL, "Add a printer", "" },
+ { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, &syntax_spoolss, NULL, "Delete a printer driver", "" },
+ { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, &syntax_spoolss, NULL, "Delete a printer driver with files", "" },
+ { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, &syntax_spoolss, NULL, "Enumerate printer data", "" },
+ { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, &syntax_spoolss, NULL, "Enumerate printer data for a key", "" },
+ { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, &syntax_spoolss, NULL, "Enumerate printer keys", "" },
+ { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, &syntax_spoolss, NULL, "Enumerate print jobs", "" },
+ { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, &syntax_spoolss, NULL, "Enumerate printer ports", "" },
+ { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
+ { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, &syntax_spoolss, NULL, "Enumerate printers", "" },
+ { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, &syntax_spoolss, NULL, "Get print driver data", "" },
+ { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
+ { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, &syntax_spoolss, NULL, "Get print driver information", "" },
+ { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, &syntax_spoolss, NULL, "Get print driver upload directory", "" },
+ { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, &syntax_spoolss, NULL, "Get printer info", "" },
+ { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, &syntax_spoolss, NULL, "Open printer handle", "" },
+ { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, &syntax_spoolss, NULL, "Set printer driver", "" },
+ { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, &syntax_spoolss, NULL, "Get print processor directory", "" },
+ { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, &syntax_spoolss, NULL, "Add form", "" },
+ { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, &syntax_spoolss, NULL, "Set form", "" },
+ { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, &syntax_spoolss, NULL, "Get form", "" },
+ { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, &syntax_spoolss, NULL, "Delete form", "" },
+ { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, &syntax_spoolss, NULL, "Enumerate forms", "" },
+ { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, &syntax_spoolss, NULL, "Set printer comment", "" },
+ { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, &syntax_spoolss, NULL, "Set printername", "" },
+ { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, &syntax_spoolss, NULL, "Set REG_SZ printer data", "" },
+ { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, &syntax_spoolss, NULL, "Rffpcnex test", "" },
+ { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, &syntax_spoolss, NULL, "Printer comparison test", "" },
+
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_srvsvc.c b/source3/rpcclient/cmd_srvsvc.c
new file mode 100644
index 0000000000..10017fa19b
--- /dev/null
+++ b/source3/rpcclient/cmd_srvsvc.c
@@ -0,0 +1,891 @@
+/*
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#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(const 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(struct srvsvc_NetSrvInfo101 *r)
+{
+ display_server(r->server_name, r->server_type, r->comment);
+
+ printf("\tplatform_id :\t%d\n", r->platform_id);
+ printf("\tos version :\t%d.%d\n",
+ r->version_major, r->version_minor);
+ printf("\tserver type :\t0x%x\n", r->server_type);
+}
+
+static void display_srv_info_102(struct srvsvc_NetSrvInfo102 *r)
+{
+ display_server(r->server_name, r->server_type, r->comment);
+
+ printf("\tplatform_id :\t%d\n", r->platform_id);
+ printf("\tos version :\t%d.%d\n",
+ r->version_major, r->version_minor);
+ printf("\tserver type :\t0x%x\n", r->server_type);
+
+ printf("\tusers :\t%x\n", r->users);
+ printf("\tdisc, hidden :\t%x, %x\n", r->disc, r->hidden);
+ printf("\tannounce, delta :\t%d, %d\n", r->announce,
+ r->anndelta);
+ printf("\tlicenses :\t%d\n", r->licenses);
+ printf("\tuser path :\t%s\n", r->userpath);
+}
+
+/* Server query info */
+static WERROR cmd_srvsvc_srv_query_info(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 101;
+ union srvsvc_NetSrvInfo info;
+ WERROR result;
+ NTSTATUS status;
+
+ if (argc > 2) {
+ printf("Usage: %s [infolevel]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
+ cli->srv_name_slash,
+ info_level,
+ &info,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ switch (info_level) {
+ case 101:
+ display_srv_info_101(info.info101);
+ break;
+ case 102:
+ display_srv_info_102(info.info102);
+ break;
+ default:
+ printf("unsupported info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ return result;
+}
+
+static void display_share_info_1(struct srvsvc_NetShareInfo1 *r)
+{
+ printf("netname: %s\n", r->name);
+ printf("\tremark:\t%s\n", r->comment);
+}
+
+static void display_share_info_2(struct srvsvc_NetShareInfo2 *r)
+{
+ printf("netname: %s\n", r->name);
+ printf("\tremark:\t%s\n", r->comment);
+ printf("\tpath:\t%s\n", r->path);
+ printf("\tpassword:\t%s\n", r->password);
+}
+
+static void display_share_info_502(struct srvsvc_NetShareInfo502 *r)
+{
+ printf("netname: %s\n", r->name);
+ printf("\tremark:\t%s\n", r->comment);
+ printf("\tpath:\t%s\n", r->path);
+ printf("\tpassword:\t%s\n", r->password);
+
+ printf("\ttype:\t0x%x\n", r->type);
+ printf("\tperms:\t%d\n", r->permissions);
+ printf("\tmax_uses:\t%d\n", r->max_users);
+ printf("\tnum_uses:\t%d\n", r->current_users);
+
+ if (r->sd_buf.sd)
+ display_sec_desc(r->sd_buf.sd);
+
+}
+
+static WERROR cmd_srvsvc_net_share_enum_int(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv,
+ uint32_t opcode)
+{
+ uint32 info_level = 2;
+ struct srvsvc_NetShareInfoCtr info_ctr;
+ struct srvsvc_NetShareCtr0 ctr0;
+ struct srvsvc_NetShareCtr1 ctr1;
+ struct srvsvc_NetShareCtr2 ctr2;
+ struct srvsvc_NetShareCtr501 ctr501;
+ struct srvsvc_NetShareCtr502 ctr502;
+ struct srvsvc_NetShareCtr1004 ctr1004;
+ struct srvsvc_NetShareCtr1005 ctr1005;
+ struct srvsvc_NetShareCtr1006 ctr1006;
+ struct srvsvc_NetShareCtr1007 ctr1007;
+ struct srvsvc_NetShareCtr1501 ctr1501;
+ WERROR result;
+ NTSTATUS status;
+ uint32_t totalentries = 0;
+ uint32_t resume_handle = 0;
+ uint32_t *resume_handle_p = NULL;
+ uint32 preferred_len = 0xffffffff, i;
+
+ if (argc > 3) {
+ printf("Usage: %s [infolevel] [resume_handle]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ info_level = atoi(argv[1]);
+ }
+
+ if (argc == 3) {
+ resume_handle = atoi(argv[2]);
+ resume_handle_p = &resume_handle;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ info_ctr.level = info_level;
+
+ switch (info_level) {
+ case 0:
+ ZERO_STRUCT(ctr0);
+ info_ctr.ctr.ctr0 = &ctr0;
+ break;
+ case 1:
+ ZERO_STRUCT(ctr1);
+ info_ctr.ctr.ctr1 = &ctr1;
+ break;
+ case 2:
+ ZERO_STRUCT(ctr2);
+ info_ctr.ctr.ctr2 = &ctr2;
+ break;
+ case 501:
+ ZERO_STRUCT(ctr501);
+ info_ctr.ctr.ctr501 = &ctr501;
+ break;
+ case 502:
+ ZERO_STRUCT(ctr502);
+ info_ctr.ctr.ctr502 = &ctr502;
+ break;
+ case 1004:
+ ZERO_STRUCT(ctr1004);
+ info_ctr.ctr.ctr1004 = &ctr1004;
+ break;
+ case 1005:
+ ZERO_STRUCT(ctr1005);
+ info_ctr.ctr.ctr1005 = &ctr1005;
+ break;
+ case 1006:
+ ZERO_STRUCT(ctr1006);
+ info_ctr.ctr.ctr1006 = &ctr1006;
+ break;
+ case 1007:
+ ZERO_STRUCT(ctr1007);
+ info_ctr.ctr.ctr1007 = &ctr1007;
+ break;
+ case 1501:
+ ZERO_STRUCT(ctr1501);
+ info_ctr.ctr.ctr1501 = &ctr1501;
+ break;
+ }
+
+ switch (opcode) {
+ case NDR_SRVSVC_NETSHAREENUM:
+ status = rpccli_srvsvc_NetShareEnum(cli, mem_ctx,
+ cli->desthost,
+ &info_ctr,
+ preferred_len,
+ &totalentries,
+ resume_handle_p,
+ &result);
+ break;
+ case NDR_SRVSVC_NETSHAREENUMALL:
+ status = rpccli_srvsvc_NetShareEnumAll(cli, mem_ctx,
+ cli->desthost,
+ &info_ctr,
+ preferred_len,
+ &totalentries,
+ resume_handle_p,
+ &result);
+ break;
+ default:
+ return WERR_INVALID_PARAM;
+ }
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ switch (info_level) {
+ case 1:
+ for (i = 0; i < totalentries; i++)
+ display_share_info_1(&info_ctr.ctr.ctr1->array[i]);
+ break;
+ case 2:
+ for (i = 0; i < totalentries; i++)
+ display_share_info_2(&info_ctr.ctr.ctr2->array[i]);
+ break;
+ case 502:
+ for (i = 0; i < totalentries; i++)
+ display_share_info_502(&info_ctr.ctr.ctr502->array[i]);
+ break;
+ default:
+ printf("unsupported info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_share_enum(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ return cmd_srvsvc_net_share_enum_int(cli, mem_ctx,
+ argc, argv,
+ NDR_SRVSVC_NETSHAREENUM);
+}
+
+static WERROR cmd_srvsvc_net_share_enum_all(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ return cmd_srvsvc_net_share_enum_int(cli, mem_ctx,
+ argc, argv,
+ NDR_SRVSVC_NETSHAREENUMALL);
+}
+
+static WERROR cmd_srvsvc_net_share_get_info(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 502;
+ union srvsvc_NetShareInfo info;
+ WERROR result;
+ NTSTATUS status;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s [sharename] [infolevel]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 3)
+ info_level = atoi(argv[2]);
+
+ status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ info_level,
+ &info,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Display results */
+
+ switch (info_level) {
+ case 1:
+ display_share_info_1(info.info1);
+ break;
+ case 2:
+ display_share_info_2(info.info2);
+ break;
+ case 502:
+ display_share_info_502(info.info502);
+ break;
+ default:
+ printf("unsupported info level %d\n", info_level);
+ break;
+ }
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_share_set_info(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 502;
+ union srvsvc_NetShareInfo info_get;
+ WERROR result;
+ NTSTATUS status;
+ uint32_t parm_err = 0;
+
+ if (argc > 3) {
+ printf("Usage: %s [sharename] [comment]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ /* retrieve share info */
+ status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ info_level,
+ &info_get,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ info_get.info502->comment = argv[2];
+
+ /* set share info */
+ status = rpccli_srvsvc_NetShareSetInfo(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ info_level,
+ &info_get,
+ &parm_err,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ /* re-retrieve share info and display */
+ status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ info_level,
+ &info_get,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ display_share_info_502(info_get.info502);
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_remote_tod(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct srvsvc_NetRemoteTODInfo *tod = NULL;
+ WERROR result;
+ NTSTATUS status;
+
+ if (argc > 1) {
+ printf("Usage: %s\n", argv[0]);
+ return WERR_OK;
+ }
+
+ status = rpccli_srvsvc_NetRemoteTOD(cli, mem_ctx,
+ cli->srv_name_slash,
+ &tod,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ result = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_file_enum(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ uint32 info_level = 3;
+ struct srvsvc_NetFileInfoCtr info_ctr;
+ struct srvsvc_NetFileCtr3 ctr3;
+ WERROR result;
+ NTSTATUS status;
+ uint32 preferred_len = 0xffff;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+
+ if (argc > 2) {
+ printf("Usage: %s [infolevel]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 2)
+ info_level = atoi(argv[1]);
+
+ ZERO_STRUCT(info_ctr);
+ ZERO_STRUCT(ctr3);
+
+ info_ctr.level = info_level;
+ info_ctr.ctr.ctr3 = &ctr3;
+
+ status = rpccli_srvsvc_NetFileEnum(cli, mem_ctx,
+ cli->desthost,
+ NULL,
+ NULL,
+ &info_ctr,
+ preferred_len,
+ &total_entries,
+ &resume_handle,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_name_validate(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+ uint32_t name_type = 9;
+ uint32_t flags = 0;
+
+ if (argc < 2 || argc > 3) {
+ printf("Usage: %s [sharename] [type]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc == 3) {
+ name_type = atoi(argv[2]);
+ }
+
+ status = rpccli_srvsvc_NetNameValidate(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ name_type,
+ flags,
+ &result);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_file_get_sec(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+ struct sec_desc_buf *sd_buf = NULL;
+
+ if (argc < 2 || argc > 4) {
+ printf("Usage: %s [sharename] [file]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ status = rpccli_srvsvc_NetGetFileSecurity(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ argv[2],
+ SECINFO_DACL,
+ &sd_buf,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ display_sec_desc(sd_buf->sd);
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_sess_del(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+
+ if (argc < 2 || argc > 4) {
+ printf("Usage: %s [client] [user]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ status = rpccli_srvsvc_NetSessDel(cli, mem_ctx,
+ cli->desthost,
+ argv[1],
+ argv[2],
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_sess_enum(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS status;
+ struct srvsvc_NetSessInfoCtr info_ctr;
+ struct srvsvc_NetSessCtr0 ctr0;
+ struct srvsvc_NetSessCtr1 ctr1;
+ struct srvsvc_NetSessCtr2 ctr2;
+ struct srvsvc_NetSessCtr10 ctr10;
+ struct srvsvc_NetSessCtr502 ctr502;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ uint32_t *resume_handle_p = NULL;
+ uint32_t level = 1;
+ const char *client = NULL;
+ const char *user = NULL;
+
+ if (argc > 6) {
+ printf("Usage: %s [client] [user] [level] [resume_handle]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ client = argv[1];
+ }
+
+ if (argc >= 3) {
+ user = argv[2];
+ }
+
+ if (argc >= 4) {
+ level = atoi(argv[3]);
+ }
+
+ if (argc >= 5) {
+ resume_handle = atoi(argv[4]);
+ resume_handle_p = &resume_handle;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ info_ctr.level = level;
+
+ d_printf("trying level: %d\n", level);
+
+ switch (level) {
+ case 0:
+ ZERO_STRUCT(ctr0);
+ info_ctr.ctr.ctr0 = &ctr0;
+ break;
+ case 1:
+ ZERO_STRUCT(ctr1);
+ info_ctr.ctr.ctr1 = &ctr1;
+ break;
+ case 2:
+ ZERO_STRUCT(ctr2);
+ info_ctr.ctr.ctr2 = &ctr2;
+ break;
+ case 10:
+ ZERO_STRUCT(ctr10);
+ info_ctr.ctr.ctr10 = &ctr10;
+ break;
+ case 502:
+ ZERO_STRUCT(ctr502);
+ info_ctr.ctr.ctr502 = &ctr502;
+ break;
+ }
+
+ status = rpccli_srvsvc_NetSessEnum(cli, mem_ctx,
+ cli->desthost,
+ client,
+ user,
+ &info_ctr,
+ 0xffffffff,
+ &total_entries,
+ resume_handle_p,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_disk_enum(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct srvsvc_NetDiskInfo info;
+ WERROR result;
+ NTSTATUS status;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ uint32_t level = 0;
+
+ if (argc > 4) {
+ printf("Usage: %s [level] [resume_handle]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ level = atoi(argv[1]);
+ }
+
+ if (argc >= 3) {
+ resume_handle = atoi(argv[2]);
+ }
+
+ ZERO_STRUCT(info);
+
+ status = rpccli_srvsvc_NetDiskEnum(cli, mem_ctx,
+ cli->desthost,
+ level,
+ &info,
+ 0xffffffff,
+ &total_entries,
+ &resume_handle,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ return result;
+}
+
+static WERROR cmd_srvsvc_net_conn_enum(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct srvsvc_NetConnInfoCtr info_ctr;
+ struct srvsvc_NetConnCtr0 ctr0;
+ struct srvsvc_NetConnCtr1 ctr1;
+ WERROR result;
+ NTSTATUS status;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ uint32_t *resume_handle_p = NULL;
+ uint32_t level = 1;
+ const char *path = "IPC$";
+
+ if (argc > 4) {
+ printf("Usage: %s [level] [path] [resume_handle]\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc >= 2) {
+ level = atoi(argv[1]);
+ }
+
+ if (argc >= 3) {
+ path = argv[2];
+ }
+
+ if (argc >= 4) {
+ resume_handle = atoi(argv[3]);
+ resume_handle_p = &resume_handle;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ info_ctr.level = level;
+
+ switch (level) {
+ case 0:
+ ZERO_STRUCT(ctr0);
+ info_ctr.ctr.ctr0 = &ctr0;
+ break;
+ case 1:
+ ZERO_STRUCT(ctr1);
+ info_ctr.ctr.ctr1 = &ctr1;
+ break;
+ default:
+ return WERR_INVALID_PARAM;
+ }
+
+ status = rpccli_srvsvc_NetConnEnum(cli, mem_ctx,
+ cli->desthost,
+ path,
+ &info_ctr,
+ 0xffffffff,
+ &total_entries,
+ resume_handle_p,
+ &result);
+
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ return result;
+}
+
+
+/* List of commands exported by this module */
+
+struct cmd_set srvsvc_commands[] = {
+
+ { "SRVSVC" },
+
+ { "srvinfo", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, &ndr_table_srvsvc.syntax_id, NULL, "Server query info", "" },
+ { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate shares", "" },
+ { "netshareenumall",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum_all, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate all shares", "" },
+ { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, &ndr_table_srvsvc.syntax_id, NULL, "Get Share Info", "" },
+ { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, &ndr_table_srvsvc.syntax_id, NULL, "Set Share Info", "" },
+ { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate open files", "" },
+ { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, &ndr_table_srvsvc.syntax_id, NULL, "Fetch remote time of day", "" },
+ { "netnamevalidate", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_name_validate, &ndr_table_srvsvc.syntax_id, NULL, "Validate sharename", "" },
+ { "netfilegetsec", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_get_sec, &ndr_table_srvsvc.syntax_id, NULL, "Get File security", "" },
+ { "netsessdel", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_sess_del, &ndr_table_srvsvc.syntax_id, NULL, "Delete Session", "" },
+ { "netsessenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_sess_enum, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate Sessions", "" },
+ { "netdiskenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_disk_enum, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate Disks", "" },
+ { "netconnenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_conn_enum, &ndr_table_srvsvc.syntax_id, NULL, "Enumerate Connections", "" },
+
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_test.c b/source3/rpcclient/cmd_test.c
new file mode 100644
index 0000000000..0f1d4221ca
--- /dev/null
+++ b/source3/rpcclient/cmd_test.c
@@ -0,0 +1,75 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Volker Lendecke 2005
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct rpc_pipe_client *lsa_pipe = NULL, *samr_pipe = NULL;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND pol;
+
+ d_printf("testme\n");
+
+ status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli),
+ &ndr_table_lsarpc.syntax_id,
+ &lsa_pipe);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli),
+ &ndr_table_samr.syntax_id,
+ &samr_pipe);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
+ SEC_RIGHTS_QUERY_VALUE, &pol);
+
+ if (!NT_STATUS_IS_OK(status))
+ goto done;
+
+ status = rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
+
+ if (!NT_STATUS_IS_OK(status))
+ goto done;
+
+ done:
+ TALLOC_FREE(lsa_pipe);
+ TALLOC_FREE(samr_pipe);
+
+ return status;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set test_commands[] = {
+
+ { "TESTING" },
+
+ { "testme", RPC_RTYPE_NTSTATUS, cmd_testme, NULL,
+ NULL, NULL, "Sample test", "testme" },
+
+ { NULL }
+};
diff --git a/source3/rpcclient/cmd_wkssvc.c b/source3/rpcclient/cmd_wkssvc.c
new file mode 100644
index 0000000000..7a34c450ab
--- /dev/null
+++ b/source3/rpcclient/cmd_wkssvc.c
@@ -0,0 +1,170 @@
+/*
+ Unix SMB/CIFS implementation.
+ RPC pipe client
+
+ Copyright (C) Günther Deschner 2007
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+static WERROR cmd_wkssvc_wkstagetinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ NTSTATUS status;
+ WERROR werr;
+ uint32_t level = 100;
+ union wkssvc_NetWkstaInfo info;
+ const char *server_name;
+
+ if (argc > 2) {
+ printf("usage: %s <level>\n", argv[0]);
+ return WERR_OK;
+ }
+
+ if (argc > 1) {
+ level = atoi(argv[1]);
+ }
+
+ server_name = cli->desthost;
+
+ status = rpccli_wkssvc_NetWkstaGetInfo(cli, mem_ctx,
+ server_name,
+ level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_wkssvc_getjoininformation(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ const char *server_name;
+ const char *name_buffer;
+ enum wkssvc_NetJoinStatus name_type;
+ NTSTATUS status;
+ WERROR werr;
+
+ server_name = cli->desthost;
+ name_buffer = "";
+
+ status = rpccli_wkssvc_NetrGetJoinInformation(cli, mem_ctx,
+ server_name,
+ &name_buffer,
+ &name_type,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ printf("%s (%d)\n", name_buffer, name_type);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_wkssvc_messagebuffersend(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ const char *server_name = cli->desthost;
+ const char *message_name = cli->desthost;
+ const char *message_sender_name = cli->desthost;
+ smb_ucs2_t *message_buffer = NULL;
+ size_t message_size = 0;
+ const char *message = "my message";
+ NTSTATUS status;
+ WERROR werr;
+
+ if (argc > 1) {
+ message = argv[1];
+ }
+
+ if (!push_ucs2_talloc(mem_ctx, &message_buffer, message,
+ &message_size))
+ {
+ return WERR_NOMEM;
+ }
+
+ status = rpccli_wkssvc_NetrMessageBufferSend(cli, mem_ctx,
+ server_name,
+ message_name,
+ message_sender_name,
+ (uint8_t *)message_buffer,
+ message_size,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ return werr;
+}
+
+static WERROR cmd_wkssvc_enumeratecomputernames(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ const char *server_name;
+ enum wkssvc_ComputerNameType name_type = NetAllComputerNames;
+ NTSTATUS status;
+ struct wkssvc_ComputerNamesCtr *ctr = NULL;
+ WERROR werr;
+
+ server_name = cli->desthost;
+
+ if (argc >= 2) {
+ name_type = atoi(argv[1]);
+ }
+
+ status = rpccli_wkssvc_NetrEnumerateComputerNames(cli, mem_ctx,
+ server_name,
+ name_type, 0,
+ &ctr,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ if (W_ERROR_IS_OK(werr)) {
+ int i=0;
+ for (i = 0; i < ctr->count; i++) {
+ printf("name: %d %s\n", i, ctr->computer_name->string);
+ }
+ }
+
+ return werr;
+}
+
+struct cmd_set wkssvc_commands[] = {
+
+ { "WKSSVC" },
+ { "wkssvc_wkstagetinfo", RPC_RTYPE_WERROR, NULL, cmd_wkssvc_wkstagetinfo, &ndr_table_wkssvc.syntax_id, NULL, "Query WKSSVC Workstation Information", "" },
+ { "wkssvc_getjoininformation", RPC_RTYPE_WERROR, NULL, cmd_wkssvc_getjoininformation, &ndr_table_wkssvc.syntax_id, NULL, "Query WKSSVC Join Information", "" },
+ { "wkssvc_messagebuffersend", RPC_RTYPE_WERROR, NULL, cmd_wkssvc_messagebuffersend, &ndr_table_wkssvc.syntax_id, NULL, "Send WKSSVC message", "" },
+ { "wkssvc_enumeratecomputernames", RPC_RTYPE_WERROR, NULL, cmd_wkssvc_enumeratecomputernames, &ndr_table_wkssvc.syntax_id, NULL, "Enumerate WKSSVC computer names", "" },
+ { NULL }
+};
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
new file mode 100644
index 0000000000..e4cdd9c3f3
--- /dev/null
+++ b/source3/rpcclient/rpcclient.c
@@ -0,0 +1,959 @@
+/*
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpcclient.h"
+
+DOM_SID domain_sid;
+
+static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+static enum pipe_auth_level pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
+static unsigned int timeout = 0;
+
+/* 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(const 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 = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
+ if (!matches) {
+ return NULL;
+ }
+
+ matches[count++] = SMB_STRDUP(text);
+ if (!matches[0]) {
+ SAFE_FREE(matches);
+ 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].returntype == RPC_RTYPE_NTSTATUS &&
+ commands->cmd_set[i].ntfn ) ||
+ ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
+ commands->cmd_set[i].wfn))) {
+ matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
+ if (!matches[count]) {
+ for (i = 0; i < count; i++) {
+ SAFE_FREE(matches[count]);
+ }
+ SAFE_FREE(matches);
+ return NULL;
+ }
+ count++;
+ }
+ }
+ commands = commands->next;
+
+ }
+
+ if (count == 2) {
+ SAFE_FREE(matches[0]);
+ matches[0] = SMB_STRDUP(matches[1]);
+ }
+ matches[count] = NULL;
+ return matches;
+}
+
+static char *next_command (char **cmdstr)
+{
+ char *command;
+ char *p;
+
+ if (!cmdstr || !(*cmdstr))
+ return NULL;
+
+ p = strchr_m(*cmdstr, ';');
+ if (p)
+ *p = '\0';
+ command = SMB_STRDUP(*cmdstr);
+ if (p)
+ *cmdstr = p + 1;
+ else
+ *cmdstr = NULL;
+
+ return command;
+}
+
+/* Fetch the SID for this computer */
+
+static void fetch_machine_sid(struct cli_state *cli)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_OK;
+ static bool got_domain_sid;
+ TALLOC_CTX *mem_ctx;
+ struct rpc_pipe_client *lsapipe = NULL;
+ union lsa_PolicyInformation *info = NULL;
+
+ 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;
+ }
+
+ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
+ &lsapipe);
+ if (!NT_STATUS_IS_OK(result)) {
+ fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
+ goto error;
+ }
+
+ result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ result = rpccli_lsa_QueryInfoPolicy(lsapipe, mem_ctx,
+ &pol,
+ LSA_POLICY_INFO_ACCOUNT_DOMAIN,
+ &info);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto error;
+ }
+
+ got_domain_sid = True;
+ sid_copy(&domain_sid, info->account_domain.sid);
+
+ rpccli_lsa_Close(lsapipe, mem_ctx, &pol);
+ TALLOC_FREE(lsapipe);
+ talloc_destroy(mem_ctx);
+
+ return;
+
+ error:
+
+ if (lsapipe) {
+ TALLOC_FREE(lsapipe);
+ }
+
+ 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 rpc_pipe_client *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("%30s", tmp_set->name);
+ tmp_set++;
+ i++;
+ if (i%3 == 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 rpc_pipe_client *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 rpc_pipe_client *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 rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ exit(0);
+ return NT_STATUS_OK; /* NOTREACHED */
+}
+
+static NTSTATUS cmd_set_ss_level(void)
+{
+ struct cmd_list *tmp;
+
+ /* Close any existing connections not at this level. */
+
+ for (tmp = cmd_list; tmp; tmp = tmp->next) {
+ struct cmd_set *tmp_set;
+
+ for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
+ if (tmp_set->rpc_pipe == NULL) {
+ continue;
+ }
+
+ if ((tmp_set->rpc_pipe->auth->auth_type
+ != pipe_default_auth_type)
+ || (tmp_set->rpc_pipe->auth->auth_level
+ != pipe_default_auth_level)) {
+ TALLOC_FREE(tmp_set->rpc_pipe);
+ tmp_set->rpc_pipe = NULL;
+ }
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ const char *type = "NTLMSSP";
+
+ pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+ pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+ if (argc > 2) {
+ printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2) {
+ type = argv[1];
+ if (strequal(type, "NTLMSSP")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+ } else if (strequal(type, "NTLMSSP_SPNEGO")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+ } else if (strequal(type, "SCHANNEL")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+ } else {
+ printf("unknown type %s\n", type);
+ return NT_STATUS_INVALID_LEVEL;
+ }
+ }
+
+ d_printf("Setting %s - sign\n", type);
+
+ return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ const char *type = "NTLMSSP";
+
+ pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+ pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+ if (argc > 2) {
+ printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2) {
+ type = argv[1];
+ if (strequal(type, "NTLMSSP")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+ } else if (strequal(type, "NTLMSSP_SPNEGO")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+ } else if (strequal(type, "SCHANNEL")) {
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+ } else {
+ printf("unknown type %s\n", type);
+ return NT_STATUS_INVALID_LEVEL;
+ }
+ }
+
+ d_printf("Setting %s - sign and seal\n", type);
+
+ return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ struct cmd_list *tmp;
+
+ if (argc > 2) {
+ printf("Usage: %s timeout\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ if (argc == 2) {
+ timeout = atoi(argv[1]);
+
+ for (tmp = cmd_list; tmp; tmp = tmp->next) {
+
+ struct cmd_set *tmp_set;
+
+ for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
+ if (tmp_set->rpc_pipe == NULL) {
+ continue;
+ }
+
+ rpccli_set_timeout(tmp_set->rpc_pipe, timeout);
+ }
+ }
+ }
+
+ printf("timeout is %d\n", timeout);
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
+ pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+
+ return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ d_printf("Setting schannel - sign and seal\n");
+ pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+ return cmd_set_ss_level();
+}
+
+static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ d_printf("Setting schannel - sign only\n");
+ pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+ pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+ return cmd_set_ss_level();
+}
+
+
+/* Built in rpcclient commands */
+
+static struct cmd_set rpcclient_commands[] = {
+
+ { "GENERAL OPTIONS" },
+
+ { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL, NULL, NULL, "Get help on commands", "[command]" },
+ { "?", RPC_RTYPE_NTSTATUS, cmd_help, NULL, NULL, NULL, "Get help on commands", "[command]" },
+ { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, NULL, NULL, "Set debug level", "level" },
+ { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, NULL, NULL, "Set debug level", "level" },
+ { "list", RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, NULL, NULL, "List available commands on <pipe>", "pipe" },
+ { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, NULL, NULL, "Exit program", "" },
+ { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, NULL, NULL, "Exit program", "" },
+ { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, NULL, NULL, "Force RPC pipe connections to be signed", "" },
+ { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, NULL, NULL, "Force RPC pipe connections to be sealed", "" },
+ { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, NULL, NULL, "Force RPC pipe connections to be sealed with 'schannel'. Assumes valid machine account to this domain controller.", "" },
+ { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL, NULL, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'. Assumes valid machine account to this domain controller.", "" },
+ { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL, NULL, NULL, "Set timeout (in milliseonds) for RPC operations", "" },
+ { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, NULL, NULL, "Force RPC pipe connections to have no special properties", "" },
+
+ { NULL }
+};
+
+static struct cmd_set separator_command[] = {
+ { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL, NULL, NULL, "----------------------" },
+ { 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 ds_commands[];
+extern struct cmd_set echo_commands[];
+extern struct cmd_set shutdown_commands[];
+extern struct cmd_set test_commands[];
+extern struct cmd_set wkssvc_commands[];
+extern struct cmd_set ntsvcs_commands[];
+extern struct cmd_set drsuapi_commands[];
+
+static struct cmd_set *rpcclient_command_list[] = {
+ rpcclient_commands,
+ lsarpc_commands,
+ ds_commands,
+ samr_commands,
+ spoolss_commands,
+ netlogon_commands,
+ srvsvc_commands,
+ dfs_commands,
+ echo_commands,
+ shutdown_commands,
+ test_commands,
+ wkssvc_commands,
+ ntsvcs_commands,
+ drsuapi_commands,
+ NULL
+};
+
+static void add_command_set(struct cmd_set *cmd_set)
+{
+ struct cmd_list *entry;
+
+ if (!(entry = SMB_MALLOC_P(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 ntresult;
+ WERROR wresult;
+
+ TALLOC_CTX *mem_ctx;
+
+ /* Create mem_ctx */
+
+ if (!(mem_ctx = talloc_init("do_cmd"))) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Open pipe */
+
+ if ((cmd_entry->interface != NULL) && (cmd_entry->rpc_pipe == NULL)) {
+ switch (pipe_default_auth_type) {
+ case PIPE_AUTH_TYPE_NONE:
+ ntresult = cli_rpc_pipe_open_noauth(
+ cli, cmd_entry->interface,
+ &cmd_entry->rpc_pipe);
+ break;
+ case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+ ntresult = cli_rpc_pipe_open_spnego_ntlmssp(
+ cli, cmd_entry->interface,
+ pipe_default_auth_level,
+ lp_workgroup(),
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ &cmd_entry->rpc_pipe);
+ break;
+ case PIPE_AUTH_TYPE_NTLMSSP:
+ ntresult = cli_rpc_pipe_open_ntlmssp(
+ cli, cmd_entry->interface,
+ pipe_default_auth_level,
+ lp_workgroup(),
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ &cmd_entry->rpc_pipe);
+ break;
+ case PIPE_AUTH_TYPE_SCHANNEL:
+ ntresult = cli_rpc_pipe_open_schannel(
+ cli, cmd_entry->interface,
+ pipe_default_auth_level,
+ lp_workgroup(),
+ &cmd_entry->rpc_pipe);
+ break;
+ default:
+ DEBUG(0, ("Could not initialise %s. Invalid "
+ "auth type %u\n",
+ cli_get_pipe_name_from_iface(
+ debug_ctx(), cli,
+ cmd_entry->interface),
+ pipe_default_auth_type ));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (!NT_STATUS_IS_OK(ntresult)) {
+ DEBUG(0, ("Could not initialise %s. Error was %s\n",
+ cli_get_pipe_name_from_iface(
+ debug_ctx(), cli,
+ cmd_entry->interface),
+ nt_errstr(ntresult) ));
+ return ntresult;
+ }
+
+ if (ndr_syntax_id_equal(cmd_entry->interface,
+ &ndr_table_netlogon.syntax_id)) {
+ uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+ uint32 sec_channel_type;
+ uchar trust_password[16];
+
+ if (!secrets_fetch_trust_account_password(lp_workgroup(),
+ trust_password,
+ NULL, &sec_channel_type)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe,
+ cli->desthost, /* server name */
+ lp_workgroup(), /* domain */
+ global_myname(), /* client name */
+ global_myname(), /* machine account name */
+ trust_password,
+ sec_channel_type,
+ &neg_flags);
+
+ if (!NT_STATUS_IS_OK(ntresult)) {
+ DEBUG(0, ("Could not initialise credentials for %s.\n",
+ cli_get_pipe_name_from_iface(
+ debug_ctx(), cli,
+ cmd_entry->interface)));
+ return ntresult;
+ }
+ }
+ }
+
+ /* Run command */
+
+ if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
+ ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+ if (!NT_STATUS_IS_OK(ntresult)) {
+ printf("result was %s\n", nt_errstr(ntresult));
+ }
+ } else {
+ wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+ /* print out the DOS error */
+ if (!W_ERROR_IS_OK(wresult)) {
+ printf( "result was %s\n", dos_errstr(wresult));
+ }
+ ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Cleanup */
+
+ talloc_destroy(mem_ctx);
+
+ return ntresult;
+}
+
+
+/**
+ * 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->returntype == RPC_RTYPE_NTSTATUS && temp_set->ntfn ) &&
+ !(temp_set->returntype == RPC_RTYPE_WERROR && temp_set->wfn )) {
+ 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:
+/* moved to do_cmd()
+ if (!NT_STATUS_IS_OK(result)) {
+ printf("result was %s\n", nt_errstr(result));
+ }
+*/
+
+ /* 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[])
+{
+ int opt;
+ static char *cmdstr = NULL;
+ const char *server;
+ struct cli_state *cli = NULL;
+ static char *opt_ipaddr=NULL;
+ struct cmd_set **cmd_set;
+ struct sockaddr_storage server_ss;
+ NTSTATUS nt_status;
+ static int opt_port = 0;
+ fstring new_workgroup;
+ int result = 0;
+ TALLOC_CTX *frame = talloc_stackframe();
+ uint32_t flags = 0;
+
+ /* 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
+ {"command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
+ {"dest-ip", 'I', POPT_ARG_STRING, &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
+ {"port", 'p', POPT_ARG_INT, &opt_port, 'p', "Specify port number", "PORT"},
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CONNECTION
+ POPT_COMMON_CREDENTIALS
+ POPT_TABLEEND
+ };
+
+ load_case_tables();
+
+ zero_addr(&server_ss);
+
+ setlinebuf(stdout);
+
+ /* the following functions are part of the Samba debugging
+ facilities. See lib/debug.c */
+ setup_logging("rpcclient", True);
+
+ /* Parse options */
+
+ pc = poptGetContext("rpcclient", argc, (const char **) argv,
+ long_options, 0);
+
+ if (argc == 1) {
+ poptPrintHelp(pc, stderr, 0);
+ goto done;
+ }
+
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+
+ case 'I':
+ if (!interpret_string_addr(&server_ss,
+ opt_ipaddr,
+ AI_NUMERICHOST)) {
+ fprintf(stderr, "%s not a valid IP address\n",
+ opt_ipaddr);
+ result = 1;
+ goto done;
+ }
+ }
+ }
+
+ /* 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);
+ result = 1;
+ goto done;
+ }
+
+ poptFreeContext(pc);
+
+ load_interfaces();
+
+ if (!init_names()) {
+ result = 1;
+ goto done;
+ }
+
+ /* save the workgroup...
+
+ FIXME!! do we need to do this for other options as well
+ (or maybe a generic way to keep lp_load() from overwriting
+ everything)? */
+
+ fstrcpy( new_workgroup, lp_workgroup() );
+
+ /* Load smb.conf file */
+
+ if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True))
+ fprintf(stderr, "Can't load %s\n", get_dyn_CONFIGFILE());
+
+ if ( strlen(new_workgroup) != 0 )
+ set_global_myworkgroup( new_workgroup );
+
+ /*
+ * Get password
+ * from stdin if necessary
+ */
+
+ if (get_cmdline_auth_info_use_machine_account() &&
+ !set_cmdline_auth_info_machine_account_creds()) {
+ result = 1;
+ goto done;
+ }
+
+ if (!get_cmdline_auth_info_got_pass()) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ set_cmdline_auth_info_password(pass);
+ }
+ }
+
+ if ((server[0] == '/' && server[1] == '/') ||
+ (server[0] == '\\' && server[1] == '\\')) {
+ server += 2;
+ }
+
+ if (get_cmdline_auth_info_use_kerberos()) {
+ flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
+ CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
+ }
+
+
+ nt_status = cli_full_connection(&cli, global_myname(), server,
+ opt_ipaddr ? &server_ss : NULL, opt_port,
+ "IPC$", "IPC",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ flags,
+ get_cmdline_auth_info_signing_state(),NULL);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("Cannot connect to server. Error was %s\n", nt_errstr(nt_status)));
+ result = 1;
+ goto done;
+ }
+
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(cli,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ "IPC$");
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ result = 1;
+ goto done;
+ }
+ }
+
+#if 0 /* COMMENT OUT FOR TESTING */
+ memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
+#endif
+
+ /* Load command lists */
+
+ timeout = cli_set_timeout(cli, 10000);
+
+ 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 && cmdstr[0]) {
+ char *cmd;
+ char *p = cmdstr;
+
+ result = 0;
+
+ while((cmd=next_command(&p)) != NULL) {
+ NTSTATUS cmd_result = process_cmd(cli, cmd);
+ SAFE_FREE(cmd);
+ result = NT_STATUS_IS_ERR(cmd_result);
+ }
+
+ goto done;
+ }
+
+ /* Loop around accepting commands */
+
+ while(1) {
+ char *line = NULL;
+
+ line = smb_readline("rpcclient $> ", NULL, completion_fn);
+
+ if (line == NULL)
+ break;
+
+ if (line[0] != '\n')
+ process_cmd(cli, line);
+ SAFE_FREE(line);
+ }
+
+done:
+ if (cli != NULL) {
+ cli_shutdown(cli);
+ }
+ TALLOC_FREE(frame);
+ return result;
+}
diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h
new file mode 100644
index 0000000000..91810b63a9
--- /dev/null
+++ b/source3/rpcclient/rpcclient.h
@@ -0,0 +1,42 @@
+/*
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RPCCLIENT_H
+#define RPCCLIENT_H
+
+typedef enum {
+ RPC_RTYPE_NTSTATUS = 0,
+ RPC_RTYPE_WERROR,
+ MAX_RPC_RETURN_TYPE
+} RPC_RETURN_TYPE;
+
+struct cmd_set {
+ const char *name;
+ RPC_RETURN_TYPE returntype;
+ NTSTATUS (*ntfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc,
+ const char **argv);
+ WERROR (*wfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv);
+ const struct ndr_syntax_id *interface;
+ struct rpc_pipe_client *rpc_pipe;
+ const char *description;
+ const char *usage;
+};
+
+#endif /* RPCCLIENT_H */