summaryrefslogtreecommitdiff
path: root/source/lib/netapi
diff options
context:
space:
mode:
Diffstat (limited to 'source/lib/netapi')
-rw-r--r--source/lib/netapi/cm.c95
-rw-r--r--source/lib/netapi/examples/Makefile.in228
-rw-r--r--source/lib/netapi/examples/file/file_close.c83
-rw-r--r--source/lib/netapi/examples/file/file_enum.c146
-rw-r--r--source/lib/netapi/examples/file/file_getinfo.c112
-rw-r--r--source/lib/netapi/examples/group/group_add.c90
-rw-r--r--source/lib/netapi/examples/group/group_adduser.c91
-rw-r--r--source/lib/netapi/examples/group/group_del.c82
-rw-r--r--source/lib/netapi/examples/group/group_deluser.c91
-rw-r--r--source/lib/netapi/examples/group/group_enum.c153
-rw-r--r--source/lib/netapi/examples/group/group_getinfo.c127
-rw-r--r--source/lib/netapi/examples/group/group_getusers.c132
-rw-r--r--source/lib/netapi/examples/group/group_setinfo.c142
-rw-r--r--source/lib/netapi/examples/group/group_setusers.c142
-rw-r--r--source/lib/netapi/examples/join/getjoinableous.c (renamed from source/lib/netapi/examples/getjoinableous/getjoinableous.c)0
-rw-r--r--source/lib/netapi/examples/join/netdomjoin.c (renamed from source/lib/netapi/examples/netdomjoin/netdomjoin.c)4
-rw-r--r--source/lib/netapi/examples/join/rename_machine.c86
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_add.c106
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_addmembers.c141
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_del.c83
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_delmembers.c141
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_enum.c126
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_getinfo.c112
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_getmembers.c165
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_setinfo.c128
-rw-r--r--source/lib/netapi/examples/localgroup/localgroup_setmembers.c146
-rw-r--r--source/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c238
-rw-r--r--source/lib/netapi/examples/server/remote_tod.c83
-rw-r--r--source/lib/netapi/examples/server/server_getinfo.c128
-rw-r--r--source/lib/netapi/examples/share/share_add.c110
-rw-r--r--source/lib/netapi/examples/share/share_del.c85
-rw-r--r--source/lib/netapi/examples/share/share_enum.c142
-rw-r--r--source/lib/netapi/examples/share/share_getinfo.c152
-rw-r--r--source/lib/netapi/examples/share/share_setinfo.c105
-rw-r--r--source/lib/netapi/examples/user/user_chgpwd.c99
-rw-r--r--source/lib/netapi/examples/user/user_dispinfo.c4
-rw-r--r--source/lib/netapi/examples/user/user_enum.c71
-rw-r--r--source/lib/netapi/examples/user/user_getgroups.c133
-rw-r--r--source/lib/netapi/examples/user/user_getinfo.c293
-rw-r--r--source/lib/netapi/examples/user/user_getlocalgroups.c122
-rw-r--r--source/lib/netapi/examples/user/user_modalsget.c131
-rw-r--r--source/lib/netapi/examples/user/user_modalsset.c141
-rw-r--r--source/lib/netapi/examples/user/user_setgroups.c144
-rw-r--r--source/lib/netapi/examples/user/user_setinfo.c207
-rw-r--r--source/lib/netapi/file.c289
-rw-r--r--source/lib/netapi/getdc.c34
-rw-r--r--source/lib/netapi/group.c1691
-rw-r--r--source/lib/netapi/joindomain.c96
-rw-r--r--source/lib/netapi/libnetapi.c1718
-rw-r--r--source/lib/netapi/libnetapi.h315
-rw-r--r--source/lib/netapi/localgroup.c1358
-rw-r--r--source/lib/netapi/netapi.c57
-rw-r--r--source/lib/netapi/netapi.h1370
-rw-r--r--source/lib/netapi/netapi_private.h63
-rw-r--r--source/lib/netapi/samr.c319
-rw-r--r--source/lib/netapi/serverinfo.c181
-rw-r--r--source/lib/netapi/share.c555
-rw-r--r--source/lib/netapi/sid.c76
-rw-r--r--source/lib/netapi/tests/Makefile.in57
-rw-r--r--source/lib/netapi/tests/common.c86
-rw-r--r--source/lib/netapi/tests/common.h57
-rw-r--r--source/lib/netapi/tests/netapitest.c97
-rw-r--r--source/lib/netapi/tests/netdisplay.c150
-rw-r--r--source/lib/netapi/tests/netgroup.c286
-rw-r--r--source/lib/netapi/tests/netlocalgroup.c226
-rw-r--r--source/lib/netapi/tests/netshare.c232
-rw-r--r--source/lib/netapi/tests/netuser.c458
-rw-r--r--source/lib/netapi/user.c3176
68 files changed, 17705 insertions, 582 deletions
diff --git a/source/lib/netapi/cm.c b/source/lib/netapi/cm.c
index 071ebfd4bc..a5c85bfe6b 100644
--- a/source/lib/netapi/cm.c
+++ b/source/lib/netapi/cm.c
@@ -25,9 +25,9 @@
/********************************************************************
********************************************************************/
-WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
- const char *server_name,
- struct cli_state **cli)
+static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ struct cli_state **cli)
{
struct cli_state *cli_ipc = NULL;
@@ -91,98 +91,107 @@ static struct client_pipe_connection *pipe_connections;
/********************************************************************
********************************************************************/
-static struct rpc_pipe_client *pipe_cm_find(struct cli_state *cli,
- int pipe_idx,
- NTSTATUS *status)
+static NTSTATUS pipe_cm_find(struct cli_state *cli,
+ const struct ndr_syntax_id *interface,
+ struct rpc_pipe_client **presult)
{
struct client_pipe_connection *p;
for (p = pipe_connections; p; p = p->next) {
- if (!p->pipe->cli) {
- *status = NT_STATUS_PIPE_EMPTY;
- return NULL;
+ if (!rpc_pipe_np_smb_conn(p->pipe)) {
+ return NT_STATUS_PIPE_EMPTY;
}
- if (strequal(cli->desthost, p->pipe->cli->desthost) &&
- pipe_idx == p->pipe->pipe_idx) {
- *status = NT_STATUS_OK;
- return p->pipe;
+ if (strequal(cli->desthost, p->pipe->desthost)
+ && ndr_syntax_id_equal(&p->pipe->abstract_syntax,
+ interface)) {
+ *presult = p->pipe;
+ return NT_STATUS_OK;
}
}
- *status = NT_STATUS_PIPE_NOT_AVAILABLE;
-
- return NULL;
+ return NT_STATUS_PIPE_NOT_AVAILABLE;
}
/********************************************************************
********************************************************************/
-static struct rpc_pipe_client *pipe_cm_connect(TALLOC_CTX *mem_ctx,
- struct cli_state *cli,
- int pipe_idx,
- NTSTATUS *status)
+static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli,
+ const struct ndr_syntax_id *interface,
+ struct rpc_pipe_client **presult)
{
struct client_pipe_connection *p;
+ NTSTATUS status;
p = TALLOC_ZERO_ARRAY(mem_ctx, struct client_pipe_connection, 1);
if (!p) {
- *status = NT_STATUS_NO_MEMORY;
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
- p->pipe = cli_rpc_pipe_open_noauth(cli, pipe_idx, status);
- if (!p->pipe) {
+ status = cli_rpc_pipe_open_noauth(cli, interface, &p->pipe);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(p);
- return NULL;
+ return status;
}
DLIST_ADD(pipe_connections, p);
- return p->pipe;
+ *presult = p->pipe;
+ return NT_STATUS_OK;
}
/********************************************************************
********************************************************************/
-static struct rpc_pipe_client *pipe_cm_open(TALLOC_CTX *ctx,
- struct cli_state *cli,
- int pipe_idx,
- NTSTATUS *status)
+static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx,
+ struct cli_state *cli,
+ const struct ndr_syntax_id *interface,
+ struct rpc_pipe_client **presult)
{
- struct rpc_pipe_client *p;
-
- p = pipe_cm_find(cli, pipe_idx, status);
- if (!p) {
- p = pipe_cm_connect(ctx, cli, pipe_idx, status);
+ if (NT_STATUS_IS_OK(pipe_cm_find(cli, interface, presult))) {
+ return NT_STATUS_OK;
}
- return p;
+ return pipe_cm_connect(ctx, cli, interface, presult);
}
/********************************************************************
********************************************************************/
WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
- struct cli_state *cli,
- int pipe_idx,
- struct rpc_pipe_client **pipe_cli)
+ const char *server_name,
+ const struct ndr_syntax_id *interface,
+ struct cli_state **pcli,
+ struct rpc_pipe_client **presult)
{
+ struct rpc_pipe_client *result = NULL;
NTSTATUS status;
+ WERROR werr;
+ struct cli_state *cli = NULL;
- if (!cli || !pipe_cli) {
+ if (!presult) {
return WERR_INVALID_PARAM;
}
- *pipe_cli = pipe_cm_open(ctx, cli, pipe_idx, &status);
- if (!*pipe_cli) {
+ werr = libnetapi_open_ipc_connection(ctx, server_name, &cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
+ status = pipe_cm_open(ctx, cli, interface, &result);
+ if (!NT_STATUS_IS_OK(status)) {
libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s",
- cli_get_pipe_name(pipe_idx),
+ cli_get_pipe_name_from_iface(debug_ctx(), cli,
+ interface),
get_friendly_nt_error_msg(status));
return WERR_DEST_NOT_FOUND;
}
+ *presult = result;
+ *pcli = cli;
+
return WERR_OK;
}
diff --git a/source/lib/netapi/examples/Makefile.in b/source/lib/netapi/examples/Makefile.in
index 1e2e28c471..b1c1e59be7 100644
--- a/source/lib/netapi/examples/Makefile.in
+++ b/source/lib/netapi/examples/Makefile.in
@@ -22,10 +22,47 @@ PROGS = bin/getdc@EXEEXT@ \
bin/netdomjoin@EXEEXT@ \
bin/netdomjoin-gui@EXEEXT@ \
bin/getjoinableous@EXEEXT@ \
+ bin/rename_machine@EXEEXT@ \
bin/user_add@EXEEXT@ \
bin/user_del@EXEEXT@ \
bin/user_enum@EXEEXT@ \
- bin/user_dispinfo@EXEEXT@
+ bin/user_dispinfo@EXEEXT@ \
+ bin/user_chgpwd@EXEEXT@ \
+ bin/user_getinfo@EXEEXT@ \
+ bin/user_setinfo@EXEEXT@ \
+ bin/user_modalsget@EXEEXT@ \
+ bin/user_modalsset@EXEEXT@ \
+ bin/user_getgroups@EXEEXT@ \
+ bin/user_setgroups@EXEEXT@ \
+ bin/user_getlocalgroups@EXEEXT@ \
+ bin/group_add@EXEEXT@ \
+ bin/group_del@EXEEXT@ \
+ bin/group_enum@EXEEXT@ \
+ bin/group_setinfo@EXEEXT@ \
+ bin/group_getinfo@EXEEXT@ \
+ bin/group_adduser@EXEEXT@ \
+ bin/group_deluser@EXEEXT@ \
+ bin/group_getusers@EXEEXT@ \
+ bin/group_setusers@EXEEXT@ \
+ bin/localgroup_add@EXEEXT@ \
+ bin/localgroup_del@EXEEXT@ \
+ bin/localgroup_getinfo@EXEEXT@ \
+ bin/localgroup_setinfo@EXEEXT@ \
+ bin/localgroup_enum@EXEEXT@ \
+ bin/localgroup_addmembers@EXEEXT@ \
+ bin/localgroup_delmembers@EXEEXT@ \
+ bin/localgroup_setmembers@EXEEXT@ \
+ bin/localgroup_getmembers@EXEEXT@ \
+ bin/remote_tod@EXEEXT@ \
+ bin/server_getinfo@EXEEXT@ \
+ bin/share_add@EXEEXT@ \
+ bin/share_del@EXEEXT@ \
+ bin/share_enum@EXEEXT@ \
+ bin/share_getinfo@EXEEXT@ \
+ bin/share_setinfo@EXEEXT@ \
+ bin/file_close@EXEEXT@ \
+ bin/file_getinfo@EXEEXT@ \
+ bin/file_enum@EXEEXT@
all: $(PROGS)
@@ -56,13 +93,50 @@ bin/.dummy:
CMDLINE_OBJ = common.o
GETDC_OBJ = getdc/getdc.o $(CMDLINE_OBJ)
DSGETDC_OBJ = dsgetdc/dsgetdc.o $(CMDLINE_OBJ)
-NETDOMJOIN_OBJ = netdomjoin/netdomjoin.o $(CMDLINE_OBJ)
+NETDOMJOIN_OBJ = join/netdomjoin.o $(CMDLINE_OBJ)
NETDOMJOIN_GUI_OBJ = netdomjoin-gui/netdomjoin-gui.o
-GETJOINABLEOUS_OBJ = getjoinableous/getjoinableous.o $(CMDLINE_OBJ)
+GETJOINABLEOUS_OBJ = join/getjoinableous.o $(CMDLINE_OBJ)
+RENAMEMACHINE_OBJ = join/rename_machine.o $(CMDLINE_OBJ)
USERADD_OBJ = user/user_add.o $(CMDLINE_OBJ)
USERDEL_OBJ = user/user_del.o $(CMDLINE_OBJ)
USERENUM_OBJ = user/user_enum.o $(CMDLINE_OBJ)
USERDISPINFO_OBJ = user/user_dispinfo.o $(CMDLINE_OBJ)
+USERCHGPWD_OBJ = user/user_chgpwd.o $(CMDLINE_OBJ)
+USERGETINFO_OBJ = user/user_getinfo.o $(CMDLINE_OBJ)
+USERSETINFO_OBJ = user/user_setinfo.o $(CMDLINE_OBJ)
+USERMODALSGET_OBJ = user/user_modalsget.o $(CMDLINE_OBJ)
+USERMODALSSET_OBJ = user/user_modalsset.o $(CMDLINE_OBJ)
+USERGETGROUPS_OBJ = user/user_getgroups.o $(CMDLINE_OBJ)
+USERSETGROUPS_OBJ = user/user_setgroups.o $(CMDLINE_OBJ)
+USERGETLOCALGROUPS_OBJ = user/user_getlocalgroups.o $(CMDLINE_OBJ)
+GROUPADD_OBJ = group/group_add.o $(CMDLINE_OBJ)
+GROUPDEL_OBJ = group/group_del.o $(CMDLINE_OBJ)
+GROUPENUM_OBJ = group/group_enum.o $(CMDLINE_OBJ)
+GROUPSETINFO_OBJ = group/group_setinfo.o $(CMDLINE_OBJ)
+GROUPGETINFO_OBJ = group/group_getinfo.o $(CMDLINE_OBJ)
+GROUPADDUSER_OBJ = group/group_adduser.o $(CMDLINE_OBJ)
+GROUPDELUSER_OBJ = group/group_deluser.o $(CMDLINE_OBJ)
+GROUPGETUSERS_OBJ = group/group_getusers.o $(CMDLINE_OBJ)
+GROUPSETUSERS_OBJ = group/group_setusers.o $(CMDLINE_OBJ)
+LOCALGROUPADD_OBJ = localgroup/localgroup_add.o $(CMDLINE_OBJ)
+LOCALGROUPDEL_OBJ = localgroup/localgroup_del.o $(CMDLINE_OBJ)
+LOCALGROUPGETINFO_OBJ = localgroup/localgroup_getinfo.o $(CMDLINE_OBJ)
+LOCALGROUPSETINFO_OBJ = localgroup/localgroup_setinfo.o $(CMDLINE_OBJ)
+LOCALGROUPENUM_OBJ = localgroup/localgroup_enum.o $(CMDLINE_OBJ)
+LOCALGROUPADDMEMBERS_OBJ = localgroup/localgroup_addmembers.o $(CMDLINE_OBJ)
+LOCALGROUPDELMEMBERS_OBJ = localgroup/localgroup_delmembers.o $(CMDLINE_OBJ)
+LOCALGROUPSETMEMBERS_OBJ = localgroup/localgroup_setmembers.o $(CMDLINE_OBJ)
+LOCALGROUPGETMEMBERS_OBJ = localgroup/localgroup_getmembers.o $(CMDLINE_OBJ)
+REMOTETOD_OBJ = server/remote_tod.o $(CMDLINE_OBJ)
+SERVERGETINFO_OBJ = server/server_getinfo.o $(CMDLINE_OBJ)
+SHAREADD_OBJ = share/share_add.o $(CMDLINE_OBJ)
+SHAREDEL_OBJ = share/share_del.o $(CMDLINE_OBJ)
+SHAREENUM_OBJ = share/share_enum.o $(CMDLINE_OBJ)
+SHAREGETINFO_OBJ = share/share_getinfo.o $(CMDLINE_OBJ)
+SHARESETINFO_OBJ = share/share_setinfo.o $(CMDLINE_OBJ)
+FILECLOSE_OBJ = file/file_close.o $(CMDLINE_OBJ)
+FILEGETINFO_OBJ = file/file_getinfo.o $(CMDLINE_OBJ)
+FILEENUM_OBJ = file/file_enum.o $(CMDLINE_OBJ)
bin/getdc@EXEEXT@: $(BINARY_PREREQS) $(GETDC_OBJ)
@echo Linking $@
@@ -76,6 +150,10 @@ bin/getjoinableous@EXEEXT@: $(BINARY_PREREQS) $(GETJOINABLEOUS_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(GETJOINABLEOUS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+bin/rename_machine@EXEEXT@: $(BINARY_PREREQS) $(RENAMEMACHINE_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(RENAMEMACHINE_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
bin/netdomjoin@EXEEXT@: $(BINARY_PREREQS) $(NETDOMJOIN_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(NETDOMJOIN_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
@@ -100,6 +178,150 @@ bin/user_dispinfo@EXEEXT@: $(BINARY_PREREQS) $(USERDISPINFO_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(USERDISPINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+bin/user_chgpwd@EXEEXT@: $(BINARY_PREREQS) $(USERCHGPWD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERCHGPWD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_getinfo@EXEEXT@: $(BINARY_PREREQS) $(USERGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_setinfo@EXEEXT@: $(BINARY_PREREQS) $(USERSETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERSETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_modalsget@EXEEXT@: $(BINARY_PREREQS) $(USERMODALSGET_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERMODALSGET_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_modalsset@EXEEXT@: $(BINARY_PREREQS) $(USERMODALSSET_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERMODALSSET_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_getgroups@EXEEXT@: $(BINARY_PREREQS) $(USERGETGROUPS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERGETGROUPS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_setgroups@EXEEXT@: $(BINARY_PREREQS) $(USERSETGROUPS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERSETGROUPS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/user_getlocalgroups@EXEEXT@: $(BINARY_PREREQS) $(USERGETLOCALGROUPS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(USERGETLOCALGROUPS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_add@EXEEXT@: $(BINARY_PREREQS) $(GROUPADD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPADD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_del@EXEEXT@: $(BINARY_PREREQS) $(GROUPDEL_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPDEL_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_enum@EXEEXT@: $(BINARY_PREREQS) $(GROUPENUM_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPENUM_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_setinfo@EXEEXT@: $(BINARY_PREREQS) $(GROUPSETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPSETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_getinfo@EXEEXT@: $(BINARY_PREREQS) $(GROUPGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_adduser@EXEEXT@: $(BINARY_PREREQS) $(GROUPADDUSER_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPADDUSER_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_deluser@EXEEXT@: $(BINARY_PREREQS) $(GROUPDELUSER_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPDELUSER_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_getusers@EXEEXT@: $(BINARY_PREREQS) $(GROUPGETUSERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPGETUSERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/group_setusers@EXEEXT@: $(BINARY_PREREQS) $(GROUPSETUSERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GROUPSETUSERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_add@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPADD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPADD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_del@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPDEL_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPDEL_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_getinfo@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_setinfo@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPSETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPSETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_enum@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPENUM_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPENUM_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_addmembers@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPADDMEMBERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPADDMEMBERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_delmembers@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPDELMEMBERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPDELMEMBERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_setmembers@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPSETMEMBERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPSETMEMBERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/localgroup_getmembers@EXEEXT@: $(BINARY_PREREQS) $(LOCALGROUPGETMEMBERS_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LOCALGROUPGETMEMBERS_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/remote_tod@EXEEXT@: $(BINARY_PREREQS) $(REMOTETOD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(REMOTETOD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/server_getinfo@EXEEXT@: $(BINARY_PREREQS) $(SERVERGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SERVERGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/share_add@EXEEXT@: $(BINARY_PREREQS) $(SHAREADD_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHAREADD_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/share_del@EXEEXT@: $(BINARY_PREREQS) $(SHAREDEL_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHAREDEL_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/share_enum@EXEEXT@: $(BINARY_PREREQS) $(SHAREENUM_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHAREENUM_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/share_getinfo@EXEEXT@: $(BINARY_PREREQS) $(SHAREGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHAREGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/share_setinfo@EXEEXT@: $(BINARY_PREREQS) $(SHARESETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SHARESETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/file_close@EXEEXT@: $(BINARY_PREREQS) $(FILECLOSE_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(FILECLOSE_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/file_getinfo@EXEEXT@: $(BINARY_PREREQS) $(FILEGETINFO_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(FILEGETINFO_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+bin/file_enum@EXEEXT@: $(BINARY_PREREQS) $(FILEENUM_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(FILEENUM_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
clean:
-rm -f $(PROGS)
-rm -f core */*~ *~ \
diff --git a/source/lib/netapi/examples/file/file_close.c b/source/lib/netapi/examples/file/file_close.c
new file mode 100644
index 0000000000..759173a0ec
--- /dev/null
+++ b/source/lib/netapi/examples/file/file_close.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileClose query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t fileid = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_close", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname fileid");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ fileid = atoi(poptGetArg(pc));
+
+ /* NetFileClose */
+
+ status = NetFileClose(hostname, fileid);
+ if (status != 0) {
+ printf("NetFileClose failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/file/file_enum.c b/source/lib/netapi/examples/file/file_enum.c
new file mode 100644
index 0000000000..5fbb285194
--- /dev/null
+++ b/source/lib/netapi/examples/file/file_enum.c
@@ -0,0 +1,146 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileEnum query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *basepath = NULL;
+ const char *username = NULL;
+ uint32_t level = 3;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct FILE_INFO_2 *i2 = NULL;
+ struct FILE_INFO_3 *i3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname basepath username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ basepath = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetFileEnum */
+
+ do {
+
+ status = NetFileEnum(hostname,
+ basepath,
+ username,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 2:
+ printf("file_id: %d\n", i2->fi2_id);
+ i2++;
+ break;
+ case 3:
+ printf("file_id: %d\n", i3->fi3_id);
+ printf("permissions: %d\n", i3->fi3_permissions);
+ printf("num_locks: %d\n", i3->fi3_num_locks);
+ printf("pathname: %s\n", i3->fi3_pathname);
+ printf("username: %s\n", i3->fi3_username);
+ i3++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetFileEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/file/file_getinfo.c b/source/lib/netapi/examples/file/file_getinfo.c
new file mode 100644
index 0000000000..9ad8305bc5
--- /dev/null
+++ b/source/lib/netapi/examples/file/file_getinfo.c
@@ -0,0 +1,112 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetFileGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t fileid = 0;
+ uint32_t level = 3;
+ uint8_t *buffer = NULL;
+
+ struct FILE_INFO_2 *i2 = NULL;
+ struct FILE_INFO_3 *i3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("file_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname fileid");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ fileid = atoi(poptGetArg(pc));
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetFileGetInfo */
+
+ status = NetFileGetInfo(hostname,
+ fileid,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetFileGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 2:
+ i2 = (struct FILE_INFO_2 *)buffer;
+ printf("file_id: %d\n", i2->fi2_id);
+ break;
+ case 3:
+ i3 = (struct FILE_INFO_3 *)buffer;
+ printf("file_id: %d\n", i3->fi3_id);
+ printf("permissions: %d\n", i3->fi3_permissions);
+ printf("num_locks: %d\n", i3->fi3_num_locks);
+ printf("pathname: %s\n", i3->fi3_pathname);
+ printf("username: %s\n", i3->fi3_username);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_add.c b/source/lib/netapi/examples/group/group_add.c
new file mode 100644
index 0000000000..4da97c5fc5
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_add.c
@@ -0,0 +1,90 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupAdd query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct GROUP_INFO_1 g1;
+ uint32_t parm_error = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetGroupAdd */
+
+ g1.grpi1_name = groupname;
+ g1.grpi1_comment = "Domain Group created using NetApi example code";
+
+ status = NetGroupAdd(hostname,
+ 1,
+ (uint8_t *)&g1,
+ &parm_error);
+ if (status != 0) {
+ printf("NetGroupAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_adduser.c b/source/lib/netapi/examples/group/group_adduser.c
new file mode 100644
index 0000000000..253b3c5ab4
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_adduser.c
@@ -0,0 +1,91 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupAddUser query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *username = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_adduser", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetGroupAddUser */
+
+ status = NetGroupAddUser(hostname,
+ groupname,
+ username);
+ if (status != 0) {
+ printf("NetGroupAddUser failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_del.c b/source/lib/netapi/examples/group/group_del.c
new file mode 100644
index 0000000000..789e429ea2
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_del.c
@@ -0,0 +1,82 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupDel query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetGroupDel */
+
+ status = NetGroupDel(hostname, groupname);
+ if (status != 0) {
+ printf("NetGroupDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_deluser.c b/source/lib/netapi/examples/group/group_deluser.c
new file mode 100644
index 0000000000..751ab5c630
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_deluser.c
@@ -0,0 +1,91 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupDelUser query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *username = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_deluser", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetGroupDelUser */
+
+ status = NetGroupDelUser(hostname,
+ groupname,
+ username);
+ if (status != 0) {
+ printf("NetGroupDelUser failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_enum.c b/source/lib/netapi/examples/group/group_enum.c
new file mode 100644
index 0000000000..fe2aee1dab
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_enum.c
@@ -0,0 +1,153 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupEnum query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+ char *sid_str = NULL;
+
+ struct GROUP_INFO_0 *info0 = NULL;
+ struct GROUP_INFO_1 *info1 = NULL;
+ struct GROUP_INFO_2 *info2 = NULL;
+ struct GROUP_INFO_3 *info3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupEnum */
+
+ do {
+ status = NetGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->grpi0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->grpi1_name);
+ printf("#%d comment: %s\n", i, info1->grpi1_comment);
+ info1++;
+ break;
+ case 2:
+ printf("#%d group: %s\n", i, info2->grpi2_name);
+ printf("#%d comment: %s\n", i, info2->grpi2_comment);
+ printf("#%d rid: %d\n", i, info2->grpi2_group_id);
+ printf("#%d attributes: 0x%08x\n", i, info2->grpi2_attributes);
+ info2++;
+ break;
+ case 3:
+ printf("#%d group: %s\n", i, info3->grpi3_name);
+ printf("#%d comment: %s\n", i, info3->grpi3_comment);
+ if (ConvertSidToStringSid(info3->grpi3_group_sid,
+ &sid_str)) {
+ printf("#%d group_sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d attributes: 0x%08x\n", i, info3->grpi3_attributes);
+ info3++;
+ break;
+
+
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetGroupEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_getinfo.c b/source/lib/netapi/examples/group/group_getinfo.c
new file mode 100644
index 0000000000..2e5b793905
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_getinfo.c
@@ -0,0 +1,127 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct GROUP_INFO_0 *g0;
+ struct GROUP_INFO_1 *g1;
+ struct GROUP_INFO_2 *g2;
+ struct GROUP_INFO_3 *g3;
+ char *sid_str = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupGetInfo */
+
+ status = NetGroupGetInfo(hostname,
+ groupname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetGroupGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ g0 = (struct GROUP_INFO_0 *)buffer;
+ printf("name: %s\n", g0->grpi0_name);
+ break;
+ case 1:
+ g1 = (struct GROUP_INFO_1 *)buffer;
+ printf("name: %s\n", g1->grpi1_name);
+ printf("comment: %s\n", g1->grpi1_comment);
+ break;
+ case 2:
+ g2 = (struct GROUP_INFO_2 *)buffer;
+ printf("name: %s\n", g2->grpi2_name);
+ printf("comment: %s\n", g2->grpi2_comment);
+ printf("group_id: %d\n", g2->grpi2_group_id);
+ printf("attributes: %d\n", g2->grpi2_attributes);
+ break;
+ case 3:
+ g3 = (struct GROUP_INFO_3 *)buffer;
+ printf("name: %s\n", g3->grpi3_name);
+ printf("comment: %s\n", g3->grpi3_comment);
+ if (ConvertSidToStringSid(g3->grpi3_group_sid,
+ &sid_str)) {
+ printf("group_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ printf("attributes: %d\n", g3->grpi3_attributes);
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_getusers.c b/source/lib/netapi/examples/group/group_getusers.c
new file mode 100644
index 0000000000..72e79ec3a2
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_getusers.c
@@ -0,0 +1,132 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupGetUsers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_getusers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetGroupGetUsers */
+
+ do {
+ status = NetGroupGetUsers(hostname,
+ groupname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d member: %s\n", i, info0->grui0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d member: %s\n", i, info1->grui1_name);
+ printf("#%d attributes: %d\n", i, info1->grui1_attributes);
+ info1++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetGroupGetUsers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_setinfo.c b/source/lib/netapi/examples/group/group_setinfo.c
new file mode 100644
index 0000000000..cd30d8b9b8
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_setinfo.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupSetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *option = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+ struct GROUP_INFO_0 g0;
+ struct GROUP_INFO_1 g1;
+ struct GROUP_INFO_2 g2;
+ struct GROUP_INFO_3 g3;
+ struct GROUP_INFO_1002 g1002;
+ struct GROUP_INFO_1005 g1005;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level option");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ level = atoi(poptGetArg(pc));
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ option = poptGetArg(pc);
+
+ /* NetGroupSetInfo */
+
+ switch (level) {
+ case 0:
+ g0.grpi0_name = option;
+ buffer = (uint8_t *)&g0;
+ break;
+ case 1:
+ g1.grpi1_name = option; /* this one will be ignored */
+ g1.grpi1_comment = option;
+ buffer = (uint8_t *)&g1;
+ break;
+ case 2:
+ g2.grpi2_name = option; /* this one will be ignored */
+ g2.grpi2_comment = option;
+ g2.grpi2_group_id = 4711; /* this one will be ignored */
+ g2.grpi2_attributes = 7;
+ buffer = (uint8_t *)&g2;
+ break;
+ case 3:
+ g3.grpi3_name = option; /* this one will be ignored */
+ g3.grpi3_comment = option;
+ g2.grpi2_attributes = 7;
+ buffer = (uint8_t *)&g3;
+ break;
+ case 1002:
+ g1002.grpi1002_comment = option;
+ buffer = (uint8_t *)&g1002;
+ break;
+ case 1005:
+ g1005.grpi1005_attributes = atoi(option);
+ buffer = (uint8_t *)&g1005;
+ break;
+ }
+
+ status = NetGroupSetInfo(hostname,
+ groupname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetGroupSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/group/group_setusers.c b/source/lib/netapi/examples/group/group_setusers.c
new file mode 100644
index 0000000000..70cf10514c
--- /dev/null
+++ b/source/lib/netapi/examples/group/group_setusers.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroupSetUsers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t num_entries = 0;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ struct GROUP_USERS_INFO_0 *g0 = NULL;
+ struct GROUP_USERS_INFO_1 *g1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("group_setusers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ num_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g0[i].grui0_name = names[i];
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 1:
+ buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g1);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g1[i].grui1_name = names[i];
+ }
+
+ buffer = (uint8_t *)g1;
+ break;
+ default:
+ break;
+ }
+
+ /* NetGroupSetUsers */
+
+ status = NetGroupSetUsers(hostname,
+ groupname,
+ level,
+ buffer,
+ num_entries);
+ if (status != 0) {
+ printf("NetGroupSetUsers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/getjoinableous/getjoinableous.c b/source/lib/netapi/examples/join/getjoinableous.c
index 732f73dd57..732f73dd57 100644
--- a/source/lib/netapi/examples/getjoinableous/getjoinableous.c
+++ b/source/lib/netapi/examples/join/getjoinableous.c
diff --git a/source/lib/netapi/examples/netdomjoin/netdomjoin.c b/source/lib/netapi/examples/join/netdomjoin.c
index bd7c36382a..08ce71b938 100644
--- a/source/lib/netapi/examples/netdomjoin/netdomjoin.c
+++ b/source/lib/netapi/examples/join/netdomjoin.c
@@ -39,7 +39,9 @@ int main(int argc, const char **argv)
const char *account_ou = NULL;
const char *account = NULL;
const char *password = NULL;
- uint32_t join_flags = 0x00000023;
+ uint32_t join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED;
struct libnetapi_ctx *ctx = NULL;
poptContext pc;
diff --git a/source/lib/netapi/examples/join/rename_machine.c b/source/lib/netapi/examples/join/rename_machine.c
new file mode 100644
index 0000000000..a21f9198d8
--- /dev/null
+++ b/source/lib/netapi/examples/join/rename_machine.c
@@ -0,0 +1,86 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetRenameMachineInDomain query
+ * 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 <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ const char *host_name = NULL;
+ const char *new_machine_name = NULL;
+ uint32_t rename_opt = 0;
+ struct libnetapi_ctx *ctx = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("rename_machine", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname newmachinename");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ host_name = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ new_machine_name = poptGetArg(pc);
+
+ /* NetRenameMachineInDomain */
+
+ status = NetRenameMachineInDomain(host_name,
+ new_machine_name,
+ ctx->username,
+ ctx->password,
+ rename_opt);
+ if (status != 0) {
+ printf("failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_add.c b/source/lib/netapi/examples/localgroup/localgroup_add.c
new file mode 100644
index 0000000000..7f23c99db1
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_add.c
@@ -0,0 +1,106 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupAdd query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ const char *comment = NULL;
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ uint32_t parm_error = 0;
+ uint8_t *buf = NULL;
+ uint32_t level = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname comment");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ comment = poptGetArg(pc);
+ }
+
+ /* NetLocalGroupAdd */
+
+ if (comment) {
+ level = 1;
+ g1.lgrpi1_name = groupname;
+ g1.lgrpi1_comment = comment;
+ buf = (uint8_t *)&g1;
+ } else {
+ level = 0;
+ g0.lgrpi0_name = groupname;
+ buf = (uint8_t *)&g0;
+ }
+
+ status = NetLocalGroupAdd(hostname,
+ level,
+ buf,
+ &parm_error);
+ if (status != 0) {
+ printf("NetLocalGroupAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_addmembers.c b/source/lib/netapi/examples/localgroup/localgroup_addmembers.c
new file mode 100644
index 0000000000..aa4a9b59b0
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_addmembers.c
@@ -0,0 +1,141 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupAddMembers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_addmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries,
+ (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries,
+ (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupAddMembers */
+
+ status = NetLocalGroupAddMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupAddMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_del.c b/source/lib/netapi/examples/localgroup/localgroup_del.c
new file mode 100644
index 0000000000..a2515dfdcd
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_del.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupDel query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ /* NetLocalGroupDel */
+
+ status = NetLocalGroupDel(hostname,
+ groupname);
+ if (status != 0) {
+ printf("NetLocalGroupDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_delmembers.c b/source/lib/netapi/examples/localgroup/localgroup_delmembers.c
new file mode 100644
index 0000000000..7bd3ec0993
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_delmembers.c
@@ -0,0 +1,141 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupDelMembers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_delmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries,
+ (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ status = NetApiBufferAllocate(sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries,
+ (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupDelMembers */
+
+ status = NetLocalGroupDelMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupDelMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_enum.c b/source/lib/netapi/examples/localgroup/localgroup_enum.c
new file mode 100644
index 0000000000..6fe0cf4173
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_enum.c
@@ -0,0 +1,126 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupEnum query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct LOCALGROUP_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupEnum */
+
+ do {
+ status = NetLocalGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->lgrpi0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->lgrpi1_name);
+ printf("#%d comment: %s\n", i, info1->lgrpi1_comment);
+ info1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetLocalGroupEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_getinfo.c b/source/lib/netapi/examples/localgroup/localgroup_getinfo.c
new file mode 100644
index 0000000000..cd8fa8c3b3
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_getinfo.c
@@ -0,0 +1,112 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct LOCALGROUP_INFO_0 *g0;
+ struct LOCALGROUP_INFO_1 *g1;
+ struct LOCALGROUP_INFO_1002 *g1002;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupGetInfo */
+
+ status = NetLocalGroupGetInfo(hostname,
+ groupname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetLocalGroupGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ g0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ printf("name: %s\n", g0->lgrpi0_name);
+ break;
+ case 1:
+ g1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ printf("name: %s\n", g1->lgrpi1_name);
+ printf("comment: %s\n", g1->lgrpi1_comment);
+ break;
+ case 1002:
+ g1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
+ printf("comment: %s\n", g1002->lgrpi1002_comment);
+ break;
+ }
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_getmembers.c b/source/lib/netapi/examples/localgroup/localgroup_getmembers.c
new file mode 100644
index 0000000000..0589870d02
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_getmembers.c
@@ -0,0 +1,165 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupGetMembers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ char *sid_str = NULL;
+ int i;
+
+ struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_1 *info1 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_2 *info2 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_getmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetLocalGroupGetMembers */
+
+ do {
+ status = NetLocalGroupGetMembers(hostname,
+ groupname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_MEMBERS_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct LOCALGROUP_MEMBERS_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ if (ConvertSidToStringSid(info0->lgrmi0_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ info0++;
+ break;
+ case 1:
+ if (ConvertSidToStringSid(info1->lgrmi1_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d sid type: %d\n", i, info1->lgrmi1_sidusage);
+ printf("#%d name: %s\n", i, info1->lgrmi1_name);
+ info1++;
+ break;
+ case 2:
+ if (ConvertSidToStringSid(info2->lgrmi2_sid,
+ &sid_str)) {
+ printf("#%d member sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ printf("#%d sid type: %d\n", i, info2->lgrmi2_sidusage);
+ printf("#%d full name: %s\n", i, info2->lgrmi2_domainandname);
+ info2++;
+ break;
+ case 3:
+ printf("#%d full name: %s\n", i, info3->lgrmi3_domainandname);
+ info3++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetLocalGroupGetMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_setinfo.c b/source/lib/netapi/examples/localgroup/localgroup_setinfo.c
new file mode 100644
index 0000000000..efcec76786
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_setinfo.c
@@ -0,0 +1,128 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupSetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ struct LOCALGROUP_INFO_1002 g1002;
+ const char *newname = NULL;
+ const char *newcomment = NULL;
+ uint32_t parm_err = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ { "newname", 0, POPT_ARG_STRING, NULL, 'n', "New Local Group Name", "NEWNAME" },
+ { "newcomment", 0, POPT_ARG_STRING, NULL, 'c', "New Local Group Comment", "NETCOMMENT" },
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case 'n':
+ newname = poptGetOptArg(pc);
+ break;
+ case 'c':
+ newcomment = poptGetOptArg(pc);
+ break;
+ }
+
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ if (newname && !newcomment) {
+ g0.lgrpi0_name = newname;
+ buffer = (uint8_t *)&g0;
+ level = 0;
+ } else if (newcomment && !newname) {
+ g1002.lgrpi1002_comment = newcomment;
+ buffer = (uint8_t *)&g1002;
+ level = 1002;
+ } else if (newname && newcomment) {
+ g1.lgrpi1_name = newname;
+ g1.lgrpi1_comment = newcomment;
+ buffer = (uint8_t *)&g1;
+ level = 1;
+ } else {
+ printf("not enough input\n");
+ goto out;
+ }
+
+ /* NetLocalGroupSetInfo */
+
+ status = NetLocalGroupSetInfo(hostname,
+ groupname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetLocalGroupSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/localgroup/localgroup_setmembers.c b/source/lib/netapi/examples/localgroup/localgroup_setmembers.c
new file mode 100644
index 0000000000..c35f2bbb81
--- /dev/null
+++ b/source/lib/netapi/examples/localgroup/localgroup_setmembers.c
@@ -0,0 +1,146 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroupSetMembers query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *groupname = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_0 *g0;
+ struct LOCALGROUP_MEMBERS_INFO_3 *g3;
+ uint32_t total_entries = 0;
+ uint8_t *buffer = NULL;
+ uint32_t level = 3;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("localgroup_setmembers", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname groupname member1 member2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ groupname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ total_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct LOCALGROUP_MEMBERS_INFO_0) * total_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ if (!ConvertStringSidToSid(names[i], &g0[i].lgrmi0_sid)) {
+ printf("could not convert sid\n");
+ goto out;
+ }
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 3:
+ buf_size = sizeof(struct LOCALGROUP_MEMBERS_INFO_3) * total_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g3);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<total_entries; i++) {
+ g3[i].lgrmi3_domainandname = names[i];
+ }
+
+ buffer = (uint8_t *)g3;
+ break;
+ default:
+ break;
+ }
+
+ /* NetLocalGroupSetMembers */
+
+ status = NetLocalGroupSetMembers(hostname,
+ groupname,
+ level,
+ buffer,
+ total_entries);
+ if (status != 0) {
+ printf("NetLocalGroupSetMembers failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
index 418b9c8b8e..40a6e415eb 100644
--- a/source/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
+++ b/source/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
@@ -38,14 +38,6 @@
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
-#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
-#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
-#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
-#define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
-
-#define NetSetupWorkgroupName ( 2 )
-#define NetSetupDomainName ( 3 )
-
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
static gboolean verbose = FALSE;
@@ -85,6 +77,7 @@ typedef struct join_state {
gboolean settings_changed;
gboolean hostname_changed;
uint32_t stored_num_ous;
+ char *target_hostname;
} join_state;
static void debug(const char *format, ...)
@@ -108,14 +101,23 @@ static gboolean callback_delete_event(GtkWidget *widget,
return FALSE;
}
-static void callback_do_close(GtkWidget *widget,
- gpointer data)
+static void callback_do_close_data(GtkWidget *widget,
+ gpointer data)
{
- debug("callback_do_close called\n");
+ debug("callback_do_close_data called\n");
if (data) {
gtk_widget_destroy(GTK_WIDGET(data));
- data = NULL;
+ }
+}
+
+static void callback_do_close_widget(GtkWidget *widget,
+ gpointer data)
+{
+ debug("callback_do_close_widget called\n");
+
+ if (widget) {
+ gtk_widget_destroy(widget);
}
}
@@ -185,7 +187,10 @@ static void callback_apply_description_change(GtkWidget *widget,
info1005.sv1005_comment = state->comment_new;
- status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err);
+ status = NetServerSetInfo(state->target_hostname,
+ 1005,
+ (uint8_t *)&info1005,
+ &parm_err);
if (status) {
debug("NetServerSetInfo failed with: %s\n",
libnetapi_errstr(status));
@@ -196,6 +201,7 @@ static void callback_apply_description_change(GtkWidget *widget,
"Failed to change computer description: %s.",
libnetapi_get_error_string(state->ctx, status));
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
@@ -267,6 +273,7 @@ static void callback_do_reboot(GtkWidget *widget,
GTK_BUTTONS_OK,
"You must restart this computer for the changes to take effect.");
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
#if 0
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
@@ -290,7 +297,9 @@ static void callback_do_reboot(GtkWidget *widget,
const char *buffer;
uint16_t type;
- status = NetGetJoinInformation(NULL, &buffer, &type);
+ status = NetGetJoinInformation(state->target_hostname,
+ &buffer,
+ &type);
if (status != 0) {
g_print("failed to query status\n");
return;
@@ -466,6 +475,7 @@ static void callback_do_hostname_change(GtkWidget *widget,
str);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
dialog);
@@ -495,9 +505,11 @@ static void callback_creds_prompt(GtkWidget *widget,
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_do_change));
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
g_signal_connect(G_OBJECT(window), "delete_event",
- G_CALLBACK(callback_do_close), window);
+ G_CALLBACK(callback_do_close_widget), NULL);
state->window_creds_prompt = window;
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
@@ -631,9 +643,9 @@ static void callback_do_join(GtkWidget *widget,
if (state->name_type_new == NetSetupDomainName) {
domain_join = TRUE;
join_creds_required = TRUE;
- join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
- WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
- WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
+ join_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_CREATE |
+ NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
}
if ((state->name_type_initial == NetSetupDomainName) &&
@@ -641,8 +653,8 @@ static void callback_do_join(GtkWidget *widget,
try_unjoin = TRUE;
unjoin_creds_required = TRUE;
join_creds_required = FALSE;
- unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
- WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+ unjoin_flags = NETSETUP_JOIN_DOMAIN |
+ NETSETUP_ACCT_DELETE;
}
if (try_unjoin) {
@@ -663,7 +675,7 @@ static void callback_do_join(GtkWidget *widget,
}
}
- status = NetUnjoinDomain(NULL,
+ status = NetUnjoinDomain(state->target_hostname,
state->account,
state->password,
unjoin_flags);
@@ -717,6 +729,7 @@ static void callback_do_join(GtkWidget *widget,
err_str);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
dialog);
@@ -753,7 +766,7 @@ static void callback_do_join(GtkWidget *widget,
}
debug("\n");
- status = NetJoinDomain(NULL,
+ status = NetJoinDomain(state->target_hostname,
state->name_buffer_new,
account_ou,
state->account,
@@ -774,6 +787,7 @@ static void callback_do_join(GtkWidget *widget,
err_str);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
dialog);
@@ -796,6 +810,7 @@ static void callback_do_join(GtkWidget *widget,
new_workgroup_type);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -819,13 +834,19 @@ static void callback_enter_hostname_and_unlock(GtkWidget *widget,
if (strcasecmp(state->my_hostname, entry_text) == 0) {
state->hostname_changed = FALSE;
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
- return;
+ /* return; */
+ } else {
+ state->hostname_changed = TRUE;
}
- state->hostname_changed = TRUE;
+
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
+ return;
+ }
} else {
- asprintf(&str, "%s.", entry_text);
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
}
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
free(str);
@@ -840,7 +861,7 @@ static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
{
const gchar *entry_text = NULL;
struct join_state *state = (struct join_state *)data;
- int string_unchanged = 0;
+ int string_unchanged = FALSE;
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
debug("callback_enter_computer_description_and_unlock: %s\n",
@@ -853,8 +874,8 @@ static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
return;
}
#endif
- if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
- string_unchanged = 1;
+ if (entry_text && state->comment && strcasecmp(state->comment, entry_text) == 0) {
+ string_unchanged = TRUE;
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
FALSE);
return;
@@ -983,6 +1004,7 @@ static void callback_do_getous(GtkWidget *widget,
err_str);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
g_signal_connect_swapped(dialog, "response",
G_CALLBACK(gtk_widget_destroy),
dialog);
@@ -1004,7 +1026,8 @@ static void callback_do_getous(GtkWidget *widget,
return;
}
- status = NetGetJoinableOUs(NULL, domain,
+ status = NetGetJoinableOUs(state->target_hostname,
+ domain,
state->account,
state->password,
&num_ous, &ous);
@@ -1019,6 +1042,7 @@ static void callback_do_getous(GtkWidget *widget,
"Failed to query joinable OUs: %s",
libnetapi_get_error_string(state->ctx, status));
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return;
@@ -1084,9 +1108,11 @@ static void callback_do_change(GtkWidget *widget,
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_main));
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
g_signal_connect(G_OBJECT(window), "delete_event",
- G_CALLBACK(callback_do_close), window);
+ G_CALLBACK(callback_do_close_widget), NULL);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
@@ -1132,10 +1158,14 @@ static void callback_do_change(GtkWidget *widget,
char *str = NULL;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text,
- state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", entry_text,
+ state->my_dnsdomain) == -1) {
+ return;
+ }
} else {
- asprintf(&str, "%s.", entry_text);
+ if (asprintf(&str, "%s.", entry_text) == -1) {
+ return;
+ }
}
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
str);
@@ -1280,6 +1310,8 @@ static void callback_do_about(GtkWidget *widget,
GError *error = NULL;
GtkWidget *about;
+ struct join_state *state = (struct join_state *)data;
+
debug("callback_do_about called\n");
logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
@@ -1303,6 +1335,7 @@ static void callback_do_about(GtkWidget *widget,
}
gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
gtk_window_set_modal(GTK_WINDOW(about), TRUE);
+ gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(state->window_main));
g_signal_connect_swapped(about, "response",
G_CALLBACK(gtk_widget_destroy),
about);
@@ -1349,6 +1382,7 @@ static int draw_main_window(struct join_state *state)
gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(callback_delete_event), NULL);
@@ -1436,10 +1470,14 @@ static int draw_main_window(struct join_state *state)
/* Label */
char *str = NULL;
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", state->my_hostname,
- state->my_dnsdomain);
+ if (asprintf(&str, "%s.%s", state->my_hostname,
+ state->my_dnsdomain) == -1) {
+ return -1;
+ }
} else {
- asprintf(&str, "%s.", state->my_hostname);
+ if (asprintf(&str, "%s.", state->my_hostname) == -1) {
+ return -1;
+ }
}
label = gtk_label_new(str);
@@ -1539,7 +1577,7 @@ static int draw_main_window(struct join_state *state)
gtk_container_add(GTK_CONTAINER(bbox2), button2);
g_signal_connect(G_OBJECT(button2), "clicked",
G_CALLBACK(callback_do_about),
- window);
+ state);
#if 0
button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
gtk_container_add(GTK_CONTAINER(bbox2), button2);
@@ -1571,8 +1609,55 @@ static int init_join_state(struct join_state **state)
return 0;
}
+static NET_API_STATUS get_server_comment(struct join_state *state)
+{
+ struct SERVER_INFO_101 *info101 = NULL;
+ struct SERVER_INFO_1005 *info1005 = NULL;
+ NET_API_STATUS status;
+
+ status = NetServerGetInfo(state->target_hostname,
+ 101,
+ (uint8_t **)&info101);
+ if (status == 0) {
+ state->comment = strdup(info101->sv101_comment);
+ if (!state->comment) {
+ return -1;
+ }
+ NetApiBufferFree(info101);
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ switch (status) {
+ case 124: /* WERR_UNKNOWN_LEVEL */
+ case 50: /* WERR_NOT_SUPPORTED */
+ break;
+ default:
+ goto failed;
+ }
+
+ status = NetServerGetInfo(state->target_hostname,
+ 1005,
+ (uint8_t **)&info1005);
+ if (status == 0) {
+ state->comment = strdup(info1005->sv1005_comment);
+ if (!state->comment) {
+ return -1;
+ }
+ NetApiBufferFree(info1005);
+ return NET_API_STATUS_SUCCESS;
+ }
+
+ failed:
+ printf("NetServerGetInfo failed with: %s\n",
+ libnetapi_get_error_string(state->ctx, status));
+
+ return status;
+}
+
static int initialize_join_state(struct join_state *state,
- const char *debug_level)
+ const char *debug_level,
+ const char *target_hostname,
+ const char *target_username)
{
struct libnetapi_ctx *ctx = NULL;
NET_API_STATUS status = 0;
@@ -1586,6 +1671,30 @@ static int initialize_join_state(struct join_state *state,
libnetapi_set_debuglevel(ctx, debug_level);
}
+ if (target_hostname) {
+ state->target_hostname = strdup(target_hostname);
+ if (!state->target_hostname) {
+ return -1;
+ }
+ }
+
+ if (target_username) {
+ char *puser = strdup(target_username);
+ char *p = NULL;
+
+ if ((p = strchr(puser,'%'))) {
+ size_t len;
+ *p = 0;
+ libnetapi_set_username(ctx, puser);
+ libnetapi_set_password(ctx, p+1);
+ len = strlen(p+1);
+ memset(strchr(target_username,'%')+1,'X',len);
+ } else {
+ libnetapi_set_username(ctx, puser);
+ }
+ free(puser);
+ }
+
{
char my_hostname[HOST_NAME_MAX];
const char *p = NULL;
@@ -1632,7 +1741,9 @@ static int initialize_join_state(struct join_state *state,
{
const char *buffer = NULL;
uint16_t type = 0;
- status = NetGetJoinInformation(NULL, &buffer, &type);
+ status = NetGetJoinInformation(state->target_hostname,
+ &buffer,
+ &type);
if (status != 0) {
printf("NetGetJoinInformation failed with: %s\n",
libnetapi_get_error_string(state->ctx, status));
@@ -1647,43 +1758,10 @@ static int initialize_join_state(struct join_state *state,
NetApiBufferFree((void *)buffer);
}
- {
- struct SERVER_INFO_1005 *info1005 = NULL;
- uint8_t *buffer = NULL;
-
- status = NetServerGetInfo(NULL, 1005, &buffer);
- if (status != 0) {
- printf("NetServerGetInfo failed with: %s\n",
- libnetapi_get_error_string(state->ctx, status));
- return status;
- }
-
- info1005 = (struct SERVER_INFO_1005 *)buffer;
-
- state->comment = strdup(info1005->sv1005_comment);
- if (!state->comment) {
- return -1;
- }
- NetApiBufferFree(buffer);
- }
-#if 0
- {
- struct srvsvc_NetSrvInfo100 *info100 = NULL;
- uint8_t *buffer = NULL;
-
- status = NetServerGetInfo(NULL, 100, &buffer);
- if (status) {
- return status;
- }
-
- info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
-
- state->comment = strdup(info100->comment);
- if (!state->comment) {
- return -1;
- }
+ status = get_server_comment(state);
+ if (status != 0) {
+ return -1;
}
-#endif
state->ctx = ctx;
@@ -1694,6 +1772,8 @@ int main(int argc, char **argv)
{
GOptionContext *context = NULL;
static const char *debug_level = NULL;
+ static const char *target_hostname = NULL;
+ static const char *target_username = NULL;
struct join_state *state = NULL;
GError *error = NULL;
int ret = 0;
@@ -1701,6 +1781,8 @@ int main(int argc, char **argv)
static GOptionEntry entries[] = {
{ "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
+ { "target", 'S', 0, G_OPTION_ARG_STRING, &target_hostname, "Target hostname", 0 },
+ { "username", 'U', 0, G_OPTION_ARG_STRING, &target_username, "Target hostname", 0 },
{ NULL }
};
@@ -1718,7 +1800,9 @@ int main(int argc, char **argv)
return ret;
}
- ret = initialize_join_state(state, debug_level);
+ ret = initialize_join_state(state, debug_level,
+ target_hostname,
+ target_username);
if (ret) {
return ret;
}
diff --git a/source/lib/netapi/examples/server/remote_tod.c b/source/lib/netapi/examples/server/remote_tod.c
new file mode 100644
index 0000000000..7636f6ac95
--- /dev/null
+++ b/source/lib/netapi/examples/server/remote_tod.c
@@ -0,0 +1,83 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetRemoteTOD query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ struct TIME_OF_DAY_INFO *tod = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("tod", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+
+ /* NetRemoteTOD */
+
+ status = NetRemoteTOD(hostname,
+ (uint8_t **)&tod);
+ if (status != 0) {
+ printf("NetRemoteTOD failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ } else {
+ printf("%d-%d-%d %d:%d:%d\n",
+ tod->tod_day, tod->tod_month, tod->tod_year,
+ tod->tod_hours, tod->tod_mins, tod->tod_secs);
+ NetApiBufferFree(tod);
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/server/server_getinfo.c b/source/lib/netapi/examples/server/server_getinfo.c
new file mode 100644
index 0000000000..afd2edd05d
--- /dev/null
+++ b/source/lib/netapi/examples/server/server_getinfo.c
@@ -0,0 +1,128 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetServerGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 100;
+
+ struct SERVER_INFO_100 *i100;
+ struct SERVER_INFO_101 *i101;
+ struct SERVER_INFO_102 *i102;
+ struct SERVER_INFO_1005 *i1005;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("server_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetServerGetInfo */
+
+ status = NetServerGetInfo(hostname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetServerGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 100:
+ i100 = (struct SERVER_INFO_100 *)buffer;
+ printf("platform id: %d\n", i100->sv100_platform_id);
+ printf("name: %s\n", i100->sv100_name);
+ break;
+ case 101:
+ i101 = (struct SERVER_INFO_101 *)buffer;
+ printf("platform id: %d\n", i101->sv101_platform_id);
+ printf("name: %s\n", i101->sv101_name);
+ printf("version major: %d\n", i101->sv101_version_major);
+ printf("version minor: %d\n", i101->sv101_version_minor);
+ printf("type: 0x%08x\n", i101->sv101_type);
+ printf("comment: %s\n", i101->sv101_comment);
+ break;
+ case 102:
+ i102 = (struct SERVER_INFO_102 *)buffer;
+ printf("platform id: %d\n", i102->sv102_platform_id);
+ printf("name: %s\n", i102->sv102_name);
+ printf("version major: %d\n", i102->sv102_version_major);
+ printf("version minor: %d\n", i102->sv102_version_minor);
+ printf("type: 0x%08x\n", i102->sv102_type);
+ printf("comment: %s\n", i102->sv102_comment);
+ printf("users: %d\n", i102->sv102_users);
+ printf("disc: %d\n", i102->sv102_disc);
+ printf("hidden: %d\n", i102->sv102_hidden);
+ printf("announce: %d\n", i102->sv102_announce);
+ printf("anndelta: %d\n", i102->sv102_anndelta);
+ printf("licenses: %d\n", i102->sv102_licenses);
+ printf("userpath: %s\n", i102->sv102_userpath);
+ break;
+ case 1005:
+ i1005 = (struct SERVER_INFO_1005 *)buffer;
+ printf("comment: %s\n", i1005->sv1005_comment);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/share/share_add.c b/source/lib/netapi/examples/share/share_add.c
new file mode 100644
index 0000000000..3d7948840d
--- /dev/null
+++ b/source/lib/netapi/examples/share/share_add.c
@@ -0,0 +1,110 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareAdd query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ const char *path = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+
+ struct SHARE_INFO_2 i2;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_add", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename path");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ path = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareAdd */
+
+ i2.shi2_netname = sharename;
+ i2.shi2_type = 0;
+ i2.shi2_remark = "Test share created via NetApi";
+ i2.shi2_permissions = 0;
+ i2.shi2_max_uses = (uint32_t)-1;
+ i2.shi2_current_uses = 0;
+ i2.shi2_path = path;
+ i2.shi2_passwd = NULL;
+
+ status = NetShareAdd(hostname,
+ 2,
+ (uint8_t *)&i2,
+ &parm_err);
+ if (status != 0) {
+ printf("NetShareAdd failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/share/share_del.c b/source/lib/netapi/examples/share/share_del.c
new file mode 100644
index 0000000000..20e3ce5a8b
--- /dev/null
+++ b/source/lib/netapi/examples/share/share_del.c
@@ -0,0 +1,85 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareDel query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_del", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ /* NetShareDel */
+
+ status = NetShareDel(hostname,
+ sharename,
+ 0);
+ if (status != 0) {
+ printf("NetShareDel failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/share/share_enum.c b/source/lib/netapi/examples/share/share_enum.c
new file mode 100644
index 0000000000..b1f4043795
--- /dev/null
+++ b/source/lib/netapi/examples/share/share_enum.c
@@ -0,0 +1,142 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareEnum query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int i;
+
+ struct SHARE_INFO_0 *i0 = NULL;
+ struct SHARE_INFO_1 *i1 = NULL;
+ struct SHARE_INFO_2 *i2 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_enum", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareEnum */
+
+ do {
+ status = NetShareEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ printf("total entries: %d\n", total_entries);
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ default:
+ break;
+ }
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d netname: %s\n", i, i0->shi0_netname);
+ i0++;
+ break;
+ case 1:
+ printf("#%d netname: %s\n", i, i1->shi1_netname);
+ printf("#%d type: %d\n", i, i1->shi1_type);
+ printf("#%d remark: %s\n", i, i1->shi1_remark);
+ i1++;
+ break;
+ case 2:
+ printf("#%d netname: %s\n", i, i2->shi2_netname);
+ printf("#%d type: %d\n", i, i2->shi2_type);
+ printf("#%d remark: %s\n", i, i2->shi2_remark);
+ printf("#%d permissions: %d\n", i, i2->shi2_permissions);
+ printf("#%d max users: %d\n", i, i2->shi2_max_uses);
+ printf("#%d current users: %d\n", i, i2->shi2_current_uses);
+ printf("#%d path: %s\n", i, i2->shi2_path);
+ printf("#%d password: %s\n", i, i2->shi2_passwd);
+ i2++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetShareEnum failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/share/share_getinfo.c b/source/lib/netapi/examples/share/share_getinfo.c
new file mode 100644
index 0000000000..479da5cc4a
--- /dev/null
+++ b/source/lib/netapi/examples/share/share_getinfo.c
@@ -0,0 +1,152 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ uint32_t level = 2;
+ uint8_t *buffer = NULL;
+
+ struct SHARE_INFO_0 *i0 = NULL;
+ struct SHARE_INFO_1 *i1 = NULL;
+ struct SHARE_INFO_2 *i2 = NULL;
+ struct SHARE_INFO_501 *i501 = NULL;
+ struct SHARE_INFO_1005 *i1005 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetShareGetInfo */
+
+ status = NetShareGetInfo(hostname,
+ sharename,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetShareGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ case 501:
+ i501 = (struct SHARE_INFO_501 *)buffer;
+ break;
+ case 1005:
+ i1005 = (struct SHARE_INFO_1005 *)buffer;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (level) {
+ case 0:
+ printf("netname: %s\n", i0->shi0_netname);
+ break;
+ case 1:
+ printf("netname: %s\n", i1->shi1_netname);
+ printf("type: %d\n", i1->shi1_type);
+ printf("remark: %s\n", i1->shi1_remark);
+ break;
+ case 2:
+ printf("netname: %s\n", i2->shi2_netname);
+ printf("type: %d\n", i2->shi2_type);
+ printf("remark: %s\n", i2->shi2_remark);
+ printf("permissions: %d\n", i2->shi2_permissions);
+ printf("max users: %d\n", i2->shi2_max_uses);
+ printf("current users: %d\n", i2->shi2_current_uses);
+ printf("path: %s\n", i2->shi2_path);
+ printf("password: %s\n", i2->shi2_passwd);
+ break;
+ case 501:
+ printf("netname: %s\n", i501->shi501_netname);
+ printf("type: %d\n", i501->shi501_type);
+ printf("remark: %s\n", i501->shi501_remark);
+ printf("flags: %d\n", i501->shi501_flags);
+ break;
+ case 1005:
+ printf("flags: %d\n", i1005->shi1005_flags);
+ break;
+ default:
+ break;
+ }
+ NetApiBufferFree(buffer);
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/share/share_setinfo.c b/source/lib/netapi/examples/share/share_setinfo.c
new file mode 100644
index 0000000000..f4748f4122
--- /dev/null
+++ b/source/lib/netapi/examples/share/share_setinfo.c
@@ -0,0 +1,105 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShareSetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *sharename = NULL;
+ const char *comment = "NetApi generated Share comment";
+ uint32_t level = 1004;
+ uint8_t *buffer = NULL;
+ uint32_t parm_err = 0;
+
+ struct SHARE_INFO_1004 i1004;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("share_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname sharename comment");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ sharename = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ comment = poptGetArg(pc);
+ }
+
+ /* NetShareSetInfo */
+ switch (level) {
+ case 1004:
+ i1004.shi1004_remark = comment;
+ buffer = (uint8_t *)&i1004;
+ break;
+ default:
+ break;
+ }
+
+ status = NetShareSetInfo(hostname,
+ sharename,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetShareSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_chgpwd.c b/source/lib/netapi/examples/user/user_chgpwd.c
new file mode 100644
index 0000000000..8b37ec2a99
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_chgpwd.c
@@ -0,0 +1,99 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserChangePassword query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ const char *old_password = NULL;
+ const char *new_password = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_chgpwd", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username old_password new_password");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ old_password = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ new_password = poptGetArg(pc);
+
+ /* NetUserChangePassword */
+
+ status = NetUserChangePassword(hostname,
+ username,
+ old_password,
+ new_password);
+ if (status != 0) {
+ printf("NetUserChangePassword failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_dispinfo.c b/source/lib/netapi/examples/user/user_dispinfo.c
index 9f862505aa..23024fe9fe 100644
--- a/source/lib/netapi/examples/user/user_dispinfo.c
+++ b/source/lib/netapi/examples/user/user_dispinfo.c
@@ -78,11 +78,13 @@ int main(int argc, const char **argv)
if (status == 0 || status == ERROR_MORE_DATA) {
user = (struct NET_DISPLAY_USER *)buffer;
for (i=0; i<entries_read; i++) {
- printf("user %d: %s\n", i, user->usri1_name);
+ printf("user %d: %s\n", i + idx,
+ user->usri1_name);
user++;
}
NetApiBufferFree(buffer);
}
+ idx += entries_read;
} while (status == ERROR_MORE_DATA);
if (status != 0) {
diff --git a/source/lib/netapi/examples/user/user_enum.c b/source/lib/netapi/examples/user/user_enum.c
index e1f6bda10b..cf77bf2d54 100644
--- a/source/lib/netapi/examples/user/user_enum.c
+++ b/source/lib/netapi/examples/user/user_enum.c
@@ -32,13 +32,18 @@ int main(int argc, const char **argv)
NET_API_STATUS status;
struct libnetapi_ctx *ctx = NULL;
const char *hostname = NULL;
+ uint32_t level = 0;
uint8_t *buffer = NULL;
uint32_t entries_read = 0;
uint32_t total_entries = 0;
uint32_t resume_handle = 0;
+ char *sid_str = NULL;
int i;
- struct USER_INFO_0 *info0;
+ struct USER_INFO_0 *info0 = NULL;
+ struct USER_INFO_10 *info10 = NULL;
+ struct USER_INFO_20 *info20 = NULL;
+ struct USER_INFO_23 *info23 = NULL;
poptContext pc;
int opt;
@@ -56,7 +61,7 @@ int main(int argc, const char **argv)
pc = poptGetContext("user_enum", argc, argv, long_options, 0);
- poptSetOtherOptionHelp(pc, "hostname");
+ poptSetOtherOptionHelp(pc, "hostname level");
while((opt = poptGetNextOpt(pc)) != -1) {
}
@@ -66,22 +71,74 @@ int main(int argc, const char **argv)
}
hostname = poptGetArg(pc);
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
/* NetUserEnum */
do {
status = NetUserEnum(hostname,
- 0,
- 0,
+ level,
+ FILTER_NORMAL_ACCOUNT,
&buffer,
(uint32_t)-1,
&entries_read,
&total_entries,
&resume_handle);
if (status == 0 || status == ERROR_MORE_DATA) {
- info0 = (struct USER_INFO_0 *)buffer;
+
+ switch (level) {
+ case 0:
+ info0 = (struct USER_INFO_0 *)buffer;
+ break;
+ case 10:
+ info10 = (struct USER_INFO_10 *)buffer;
+ break;
+ case 20:
+ info20 = (struct USER_INFO_20 *)buffer;
+ break;
+ case 23:
+ info23 = (struct USER_INFO_23 *)buffer;
+ break;
+ default:
+ break;
+ }
+
for (i=0; i<entries_read; i++) {
- printf("user %d: %s\n", i, info0->usri0_name);
- info0++;
+ switch (level) {
+ case 0:
+ printf("#%d user: %s\n", i, info0->usri0_name);
+ info0++;
+ break;
+ case 10:
+ printf("#%d user: %s\n", i, info10->usri10_name);
+ printf("#%d comment: %s\n", i, info10->usri10_comment);
+ printf("#%d usr_comment: %s\n", i, info10->usri10_usr_comment);
+ printf("#%d full_name: %s\n", i, info10->usri10_full_name);
+ info10++;
+ break;
+ case 20:
+ printf("#%d user: %s\n", i, info20->usri20_name);
+ printf("#%d comment: %s\n", i, info20->usri20_comment);
+ printf("#%d flags: 0x%08x\n", i, info20->usri20_flags);
+ printf("#%d rid: %d\n", i, info20->usri20_user_id);
+ info20++;
+ break;
+ case 23:
+ printf("#%d user: %s\n", i, info23->usri23_name);
+ printf("#%d comment: %s\n", i, info23->usri23_comment);
+ printf("#%d flags: 0x%08x\n", i, info23->usri23_flags);
+ if (ConvertSidToStringSid(info23->usri23_user_sid,
+ &sid_str)) {
+ printf("#%d sid: %s\n", i, sid_str);
+ free(sid_str);
+ }
+ info23++;
+ break;
+ default:
+ break;
+ }
}
NetApiBufferFree(buffer);
}
diff --git a/source/lib/netapi/examples/user/user_getgroups.c b/source/lib/netapi/examples/user/user_getgroups.c
new file mode 100644
index 0000000000..939415e0eb
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_getgroups.c
@@ -0,0 +1,133 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetGroups query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *info0 = NULL;
+ struct GROUP_USERS_INFO_1 *info1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserGetGroups */
+
+ do {
+ status = NetUserGetGroups(hostname,
+ username,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->grui0_name);
+ info0++;
+ break;
+ case 1:
+ printf("#%d group: %s\n", i, info1->grui1_name);
+ printf("#%d attributes: %d\n", i, info1->grui1_attributes);
+ info1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserGetGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_getinfo.c b/source/lib/netapi/examples/user/user_getinfo.c
new file mode 100644
index 0000000000..9e95260b5a
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_getinfo.c
@@ -0,0 +1,293 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ char *sid_str = NULL;
+ int i;
+
+ struct USER_INFO_0 *u0;
+ struct USER_INFO_1 *u1;
+ struct USER_INFO_2 *u2;
+ struct USER_INFO_3 *u3;
+ struct USER_INFO_4 *u4;
+ struct USER_INFO_10 *u10;
+ struct USER_INFO_11 *u11;
+ struct USER_INFO_20 *u20;
+ struct USER_INFO_23 *u23;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserGetInfo */
+
+ status = NetUserGetInfo(hostname,
+ username,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetUserGetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ u0 = (struct USER_INFO_0 *)buffer;
+ printf("name: %s\n", u0->usri0_name);
+ break;
+ case 1:
+ u1 = (struct USER_INFO_1 *)buffer;
+ printf("name: %s\n", u1->usri1_name);
+ printf("password: %s\n", u1->usri1_password);
+ printf("password_age: %d\n", u1->usri1_password_age);
+ printf("priv: %d\n", u1->usri1_priv);
+ printf("homedir: %s\n", u1->usri1_home_dir);
+ printf("comment: %s\n", u1->usri1_comment);
+ printf("flags: 0x%08x\n", u1->usri1_flags);
+ printf("script: %s\n", u1->usri1_script_path);
+ break;
+ case 2:
+ u2 = (struct USER_INFO_2 *)buffer;
+ printf("name: %s\n", u2->usri2_name);
+ printf("password: %s\n", u2->usri2_password);
+ printf("password_age: %d\n", u2->usri2_password_age);
+ printf("priv: %d\n", u2->usri2_priv);
+ printf("homedir: %s\n", u2->usri2_home_dir);
+ printf("comment: %s\n", u2->usri2_comment);
+ printf("flags: 0x%08x\n", u2->usri2_flags);
+ printf("script: %s\n", u2->usri2_script_path);
+ printf("auth flags: 0x%08x\n", u2->usri2_auth_flags);
+ printf("full name: %s\n", u2->usri2_full_name);
+ printf("user comment: %s\n", u2->usri2_usr_comment);
+ printf("user parameters: %s\n", u2->usri2_parms);
+ printf("workstations: %s\n", u2->usri2_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u2->usri2_acct_expires);
+ printf("max storage: %d\n", u2->usri2_max_storage);
+ printf("units per week: %d\n", u2->usri2_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u2->usri2_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u2->usri2_bad_pw_count);
+ printf("logon count: %d\n", u2->usri2_num_logons);
+ printf("logon server: %s\n", u2->usri2_logon_server);
+ printf("country code: %d\n", u2->usri2_country_code);
+ printf("code page: %d\n", u2->usri2_code_page);
+ break;
+ case 3:
+ u3 = (struct USER_INFO_3 *)buffer;
+ printf("name: %s\n", u3->usri3_name);
+ printf("password_age: %d\n", u3->usri3_password_age);
+ printf("priv: %d\n", u3->usri3_priv);
+ printf("homedir: %s\n", u3->usri3_home_dir);
+ printf("comment: %s\n", u3->usri3_comment);
+ printf("flags: 0x%08x\n", u3->usri3_flags);
+ printf("script: %s\n", u3->usri3_script_path);
+ printf("auth flags: 0x%08x\n", u3->usri3_auth_flags);
+ printf("full name: %s\n", u3->usri3_full_name);
+ printf("user comment: %s\n", u3->usri3_usr_comment);
+ printf("user parameters: %s\n", u3->usri3_parms);
+ printf("workstations: %s\n", u3->usri3_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u3->usri3_acct_expires);
+ printf("max storage: %d\n", u3->usri3_max_storage);
+ printf("units per week: %d\n", u3->usri3_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u3->usri3_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u3->usri3_bad_pw_count);
+ printf("logon count: %d\n", u3->usri3_num_logons);
+ printf("logon server: %s\n", u3->usri3_logon_server);
+ printf("country code: %d\n", u3->usri3_country_code);
+ printf("code page: %d\n", u3->usri3_code_page);
+ printf("user id: %d\n", u3->usri3_user_id);
+ printf("primary group id: %d\n", u3->usri3_primary_group_id);
+ printf("profile: %s\n", u3->usri3_profile);
+ printf("home dir drive: %s\n", u3->usri3_home_dir_drive);
+ printf("password expired: %d\n", u3->usri3_password_expired);
+ break;
+ case 4:
+ u4 = (struct USER_INFO_4 *)buffer;
+ printf("name: %s\n", u4->usri4_name);
+ printf("password: %s\n", u4->usri4_password);
+ printf("password_age: %d\n", u4->usri4_password_age);
+ printf("priv: %d\n", u4->usri4_priv);
+ printf("homedir: %s\n", u4->usri4_home_dir);
+ printf("comment: %s\n", u4->usri4_comment);
+ printf("flags: 0x%08x\n", u4->usri4_flags);
+ printf("script: %s\n", u4->usri4_script_path);
+ printf("auth flags: 0x%08x\n", u4->usri4_auth_flags);
+ printf("full name: %s\n", u4->usri4_full_name);
+ printf("user comment: %s\n", u4->usri4_usr_comment);
+ printf("user parameters: %s\n", u4->usri4_parms);
+ printf("workstations: %s\n", u4->usri4_workstations);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_last_logoff);
+ printf("account expires (seconds since jan. 1, 1970 GMT): %d\n",
+ u4->usri4_acct_expires);
+ printf("max storage: %d\n", u4->usri4_max_storage);
+ printf("units per week: %d\n", u4->usri4_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u4->usri4_logon_hours[i]);
+ }
+ printf("\n");
+ printf("bad password count: %d\n", u4->usri4_bad_pw_count);
+ printf("logon count: %d\n", u4->usri4_num_logons);
+ printf("logon server: %s\n", u4->usri4_logon_server);
+ printf("country code: %d\n", u4->usri4_country_code);
+ printf("code page: %d\n", u4->usri4_code_page);
+ if (ConvertSidToStringSid(u4->usri4_user_sid,
+ &sid_str)) {
+ printf("user_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ printf("primary group id: %d\n", u4->usri4_primary_group_id);
+ printf("profile: %s\n", u4->usri4_profile);
+ printf("home dir drive: %s\n", u4->usri4_home_dir_drive);
+ printf("password expired: %d\n", u4->usri4_password_expired);
+ break;
+ case 10:
+ u10 = (struct USER_INFO_10 *)buffer;
+ printf("name: %s\n", u10->usri10_name);
+ printf("comment: %s\n", u10->usri10_comment);
+ printf("usr_comment: %s\n", u10->usri10_usr_comment);
+ printf("full_name: %s\n", u10->usri10_full_name);
+ break;
+ case 11:
+ u11 = (struct USER_INFO_11 *)buffer;
+ printf("name: %s\n", u11->usri11_name);
+ printf("comment: %s\n", u11->usri11_comment);
+ printf("user comment: %s\n", u11->usri11_usr_comment);
+ printf("full name: %s\n", u11->usri11_full_name);
+ printf("priv: %d\n", u11->usri11_priv);
+ printf("auth flags: 0x%08x\n", u11->usri11_auth_flags);
+ printf("password_age: %d\n", u11->usri11_password_age);
+ printf("homedir: %s\n", u11->usri11_home_dir);
+ printf("user parameters: %s\n", u11->usri11_parms);
+ printf("last logon (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logon);
+ printf("last logoff (seconds since jan. 1, 1970 GMT): %d\n",
+ u11->usri11_last_logoff);
+ printf("bad password count: %d\n", u11->usri11_bad_pw_count);
+ printf("logon count: %d\n", u11->usri11_num_logons);
+ printf("logon server: %s\n", u11->usri11_logon_server);
+ printf("country code: %d\n", u11->usri11_country_code);
+ printf("workstations: %s\n", u11->usri11_workstations);
+ printf("max storage: %d\n", u11->usri11_max_storage);
+ printf("units per week: %d\n", u11->usri11_units_per_week);
+ printf("logon hours:");
+ for (i=0; i<21; i++) {
+ printf(" %x", (uint8_t)u11->usri11_logon_hours[i]);
+ }
+ printf("\n");
+ printf("code page: %d\n", u11->usri11_code_page);
+ break;
+ case 20:
+ u20 = (struct USER_INFO_20 *)buffer;
+ printf("name: %s\n", u20->usri20_name);
+ printf("comment: %s\n", u20->usri20_comment);
+ printf("flags: 0x%08x\n", u20->usri20_flags);
+ printf("rid: %d\n", u20->usri20_user_id);
+ break;
+ case 23:
+ u23 = (struct USER_INFO_23 *)buffer;
+ printf("name: %s\n", u23->usri23_name);
+ printf("comment: %s\n", u23->usri23_comment);
+ printf("flags: 0x%08x\n", u23->usri23_flags);
+ if (ConvertSidToStringSid(u23->usri23_user_sid,
+ &sid_str)) {
+ printf("user_sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_getlocalgroups.c b/source/lib/netapi/examples/user/user_getlocalgroups.c
new file mode 100644
index 0000000000..133104d7c1
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_getlocalgroups.c
@@ -0,0 +1,122 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserGetLocalGroups query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t flags = 0;
+ int i;
+
+ struct LOCALGROUP_USERS_INFO_0 *info0 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_getlocalgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ /* NetUserGetLocalGroups */
+
+ do {
+ status = NetUserGetLocalGroups(hostname,
+ username,
+ level,
+ flags,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_USERS_INFO_0 *)buffer;
+ break;
+ default:
+ break;
+ }
+
+ for (i=0; i<entries_read; i++) {
+ switch (level) {
+ case 0:
+ printf("#%d group: %s\n", i, info0->lgrui0_name);
+ info0++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status != 0) {
+ printf("NetUserGetLocalGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_modalsget.c b/source/lib/netapi/examples/user/user_modalsget.c
new file mode 100644
index 0000000000..4dcb41bef7
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_modalsget.c
@@ -0,0 +1,131 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserModalsGet query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ char *sid_str = NULL;
+
+ struct USER_MODALS_INFO_0 *u0;
+ struct USER_MODALS_INFO_1 *u1;
+ struct USER_MODALS_INFO_2 *u2;
+ struct USER_MODALS_INFO_3 *u3;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_modalsget", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ /* NetUserModalsGet */
+
+ status = NetUserModalsGet(hostname,
+ level,
+ &buffer);
+ if (status != 0) {
+ printf("NetUserModalsGet failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ switch (level) {
+ case 0:
+ u0 = (struct USER_MODALS_INFO_0 *)buffer;
+ printf("min passwd len: %d character\n",
+ u0->usrmod0_min_passwd_len);
+ printf("max passwd age: %d (days)\n",
+ u0->usrmod0_max_passwd_age/86400);
+ printf("min passwd age: %d (days)\n",
+ u0->usrmod0_min_passwd_age/86400);
+ printf("force logoff: %d (seconds)\n",
+ u0->usrmod0_force_logoff);
+ printf("password history length: %d entries\n",
+ u0->usrmod0_password_hist_len);
+ break;
+ case 1:
+ u1 = (struct USER_MODALS_INFO_1 *)buffer;
+ printf("role: %d\n", u1->usrmod1_role);
+ printf("primary: %s\n", u1->usrmod1_primary);
+ break;
+ case 2:
+ u2 = (struct USER_MODALS_INFO_2 *)buffer;
+ printf("domain name: %s\n", u2->usrmod2_domain_name);
+ if (ConvertSidToStringSid(u2->usrmod2_domain_id,
+ &sid_str)) {
+ printf("domain sid: %s\n", sid_str);
+ free(sid_str);
+ }
+ break;
+ case 3:
+ u3 = (struct USER_MODALS_INFO_3 *)buffer;
+ printf("lockout duration: %d (seconds)\n",
+ u3->usrmod3_lockout_duration);
+ printf("lockout observation window: %d (seconds)\n",
+ u3->usrmod3_lockout_observation_window);
+ printf("lockout threshold: %d entries\n",
+ u3->usrmod3_lockout_threshold);
+ break;
+ default:
+ break;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_modalsset.c b/source/lib/netapi/examples/user/user_modalsset.c
new file mode 100644
index 0000000000..57e1ef70ea
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_modalsset.c
@@ -0,0 +1,141 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserModalsSet query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t level = 0;
+ uint32_t value = 0;
+ uint32_t parm_err = 0;
+
+ struct USER_MODALS_INFO_0 u0;
+ struct USER_MODALS_INFO_1 u1;
+ struct USER_MODALS_INFO_2 u2;
+ struct USER_MODALS_INFO_3 u3;
+ struct USER_MODALS_INFO_1001 u1001;
+ struct USER_MODALS_INFO_1002 u1002;
+ struct USER_MODALS_INFO_1003 u1003;
+ struct USER_MODALS_INFO_1004 u1004;
+ struct USER_MODALS_INFO_1005 u1005;
+ struct USER_MODALS_INFO_1006 u1006;
+ struct USER_MODALS_INFO_1007 u1007;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_modalsset", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname level value");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (poptPeekArg(pc)) {
+ level = atoi(poptGetArg(pc));
+ }
+
+ if (poptPeekArg(pc)) {
+ value = atoi(poptGetArg(pc));
+ }
+
+ switch (level) {
+ case 0:
+ u0.usrmod0_min_passwd_len = 0;
+ u0.usrmod0_max_passwd_age = (86400 * 30); /* once a month */
+ u0.usrmod0_min_passwd_age = 0;
+ u0.usrmod0_force_logoff = TIMEQ_FOREVER;
+ u0.usrmod0_password_hist_len = 0;
+ buffer = (uint8_t *)&u0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 1001:
+ u1001.usrmod1001_min_passwd_len = 0;
+ buffer = (uint8_t *)&u1001;
+ break;
+ case 1002:
+ u1002.usrmod1002_max_passwd_age = 0;
+ buffer = (uint8_t *)&u1002;
+ break;
+ case 1003:
+ u1003.usrmod1003_min_passwd_age = (86400 * 30); /* once a month */
+ buffer = (uint8_t *)&u1003;
+ break;
+ case 1004:
+ u1004.usrmod1004_force_logoff = TIMEQ_FOREVER;
+ buffer = (uint8_t *)&u1004;
+ break;
+ case 1005:
+ u1005.usrmod1005_password_hist_len = 0;
+ buffer = (uint8_t *)&u1005;
+ break;
+ case 1006:
+ case 1007:
+ default:
+ break;
+ }
+
+ /* NetUserModalsSet */
+
+ status = NetUserModalsSet(hostname,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetUserModalsSet failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_setgroups.c b/source/lib/netapi/examples/user/user_setgroups.c
new file mode 100644
index 0000000000..de3ff22ec8
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_setgroups.c
@@ -0,0 +1,144 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserSetGroups query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint8_t *buffer = NULL;
+ uint32_t num_entries = 0;
+ const char **names = NULL;
+ int i = 0;
+ size_t buf_size = 0;
+
+ struct GROUP_USERS_INFO_0 *g0 = NULL;
+ struct GROUP_USERS_INFO_1 *g1 = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_setgroups", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username group1 group2 ...");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+
+ names = poptGetArgs(pc);
+ for (i=0; names[i] != NULL; i++) {
+ num_entries++;
+ }
+
+ switch (level) {
+ case 0:
+ buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g0);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g0[i].grui0_name = names[i];
+ }
+
+ buffer = (uint8_t *)g0;
+ break;
+ case 1:
+ buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
+
+ status = NetApiBufferAllocate(buf_size, (void **)&g1);
+ if (status) {
+ printf("NetApiBufferAllocate failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ for (i=0; i<num_entries; i++) {
+ g1[i].grui1_name = names[i];
+ g1[i].grui1_attributes = 0; /* ? */
+ }
+
+ buffer = (uint8_t *)g1;
+ break;
+ default:
+ break;
+ }
+
+ /* NetUserSetGroups */
+
+ status = NetUserSetGroups(hostname,
+ username,
+ level,
+ buffer,
+ num_entries);
+ if (status != 0) {
+ printf("NetUserSetGroups failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ out:
+ NetApiBufferFree(buffer);
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/examples/user/user_setinfo.c b/source/lib/netapi/examples/user/user_setinfo.c
new file mode 100644
index 0000000000..4f02ae7781
--- /dev/null
+++ b/source/lib/netapi/examples/user/user_setinfo.c
@@ -0,0 +1,207 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUserSetInfo query
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+ const char *username = NULL;
+ uint32_t level = 0;
+ uint32_t parm_err = 0;
+ uint8_t *buffer = NULL;
+ const char *val = NULL;
+
+ struct USER_INFO_0 u0;
+ struct USER_INFO_1 u1;
+ struct USER_INFO_2 u2;
+ struct USER_INFO_3 u3;
+ struct USER_INFO_4 u4;
+ struct USER_INFO_21 u21;
+ struct USER_INFO_22 u22;
+ struct USER_INFO_1003 u1003;
+ struct USER_INFO_1005 u1005;
+ struct USER_INFO_1006 u1006;
+ struct USER_INFO_1007 u1007;
+ struct USER_INFO_1008 u1008;
+ struct USER_INFO_1009 u1009;
+ struct USER_INFO_1010 u1010;
+ struct USER_INFO_1011 u1011;
+ struct USER_INFO_1012 u1012;
+ struct USER_INFO_1014 u1014;
+ struct USER_INFO_1017 u1017;
+ struct USER_INFO_1020 u1020;
+ struct USER_INFO_1024 u1024;
+ struct USER_INFO_1051 u1051;
+ struct USER_INFO_1052 u1052;
+ struct USER_INFO_1053 u1053;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("user_setinfo", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname username level");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ username = poptGetArg(pc);
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ level = atoi(poptGetArg(pc));
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ val = poptGetArg(pc);
+
+ /* NetUserSetInfo */
+
+ switch (level) {
+ case 0:
+ u0.usri0_name = val;
+ buffer = (uint8_t *)&u0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ case 21:
+ break;
+ case 22:
+ break;
+ case 1003:
+ u1003.usri1003_password = val;
+ buffer = (uint8_t *)&u1003;
+ break;
+ case 1005:
+ u1005.usri1005_priv = atoi(val);
+ buffer = (uint8_t *)&u1005;
+ break;
+ case 1006:
+ u1006.usri1006_home_dir = val;
+ buffer = (uint8_t *)&u1006;
+ break;
+ case 1007:
+ u1007.usri1007_comment = val;
+ buffer = (uint8_t *)&u1007;
+ break;
+ case 1008:
+ u1008.usri1008_flags = atoi(val);
+ buffer = (uint8_t *)&u1008;
+ break;
+ case 1009:
+ u1009.usri1009_script_path = val;
+ buffer = (uint8_t *)&u1009;
+ break;
+ case 1010:
+ u1010.usri1010_auth_flags = atoi(val);
+ buffer = (uint8_t *)&u1010;
+ break;
+ case 1011:
+ u1011.usri1011_full_name = val;
+ buffer = (uint8_t *)&u1011;
+ break;
+ case 1012:
+ u1012.usri1012_usr_comment = val;
+ buffer = (uint8_t *)&u1012;
+ break;
+ case 1014:
+ u1014.usri1014_workstations = val;
+ buffer = (uint8_t *)&u1014;
+ break;
+ case 1017:
+ u1017.usri1017_acct_expires = atoi(val);
+ buffer = (uint8_t *)&u1017;
+ break;
+ case 1020:
+ break;
+ case 1024:
+ u1024.usri1024_country_code = atoi(val);
+ buffer = (uint8_t *)&u1024;
+ break;
+ case 1051:
+ u1051.usri1051_primary_group_id = atoi(val);
+ buffer = (uint8_t *)&u1051;
+ break;
+ case 1052:
+ u1052.usri1052_profile = val;
+ buffer = (uint8_t *)&u1052;
+ break;
+ case 1053:
+ u1053.usri1053_home_dir_drive = val;
+ buffer = (uint8_t *)&u1053;
+ break;
+ default:
+ break;
+ }
+
+ status = NetUserSetInfo(hostname,
+ username,
+ level,
+ buffer,
+ &parm_err);
+ if (status != 0) {
+ printf("NetUserSetInfo failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ goto out;
+ }
+
+ out:
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/file.c b/source/lib/netapi/file.c
new file mode 100644
index 0000000000..036af32f38
--- /dev/null
+++ b/source/lib/netapi/file.c
@@ -0,0 +1,289 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi File Support
+ * 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 "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileClose_r(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetFileClose(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.fileid,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileClose_l(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileClose);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_srvsvc_FileInfo_to_FILE_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetFileInfo *info,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct FILE_INFO_2 i2;
+ struct FILE_INFO_3 i3;
+
+ switch (level) {
+ case 2:
+ i2.fi2_id = info->info2->fid;
+
+ ADD_TO_ARRAY(mem_ctx, struct FILE_INFO_2, i2,
+ (struct FILE_INFO_2 **)buffer,
+ num_entries);
+ break;
+ case 3:
+ i3.fi3_id = info->info3->fid;
+ i3.fi3_permissions = info->info3->permissions;
+ i3.fi3_num_locks = info->info3->num_locks;
+ i3.fi3_pathname = talloc_strdup(mem_ctx, info->info3->path);
+ i3.fi3_username = talloc_strdup(mem_ctx, info->info3->user);
+
+ NT_STATUS_HAVE_NO_MEMORY(i3.fi3_pathname);
+ NT_STATUS_HAVE_NO_MEMORY(i3.fi3_username);
+
+ ADD_TO_ARRAY(mem_ctx, struct FILE_INFO_3, i3,
+ (struct FILE_INFO_3 **)buffer,
+ num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ union srvsvc_NetFileInfo info;
+ uint32_t num_entries = 0;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetFileGetInfo(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.fileid,
+ r->in.level,
+ &info,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_srvsvc_FileInfo_to_FILE_INFO_buffer(ctx,
+ r->in.level,
+ &info,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileEnum_r(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct srvsvc_NetFileInfoCtr info_ctr;
+ struct srvsvc_NetFileCtr2 ctr2;
+ struct srvsvc_NetFileCtr3 ctr3;
+ uint32_t num_entries = 0;
+ uint32_t i;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ info_ctr.level = r->in.level;
+ switch (r->in.level) {
+ case 2:
+ ZERO_STRUCT(ctr2);
+ info_ctr.ctr.ctr2 = &ctr2;
+ break;
+ case 3:
+ ZERO_STRUCT(ctr3);
+ info_ctr.ctr.ctr3 = &ctr3;
+ break;
+ }
+
+ status = rpccli_srvsvc_NetFileEnum(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.base_path,
+ r->in.user_name,
+ &info_ctr,
+ r->in.prefmaxlen,
+ r->out.total_entries,
+ r->out.resume_handle,
+ &werr);
+ if (NT_STATUS_IS_ERR(status)) {
+ goto done;
+ }
+
+ for (i=0; i < info_ctr.ctr.ctr2->count; i++) {
+ union srvsvc_NetFileInfo _i;
+ switch (r->in.level) {
+ case 2:
+ _i.info2 = &info_ctr.ctr.ctr2->array[i];
+ break;
+ case 3:
+ _i.info3 = &info_ctr.ctr.ctr3->array[i];
+ break;
+ }
+
+ status = map_srvsvc_FileInfo_to_FILE_INFO_buffer(ctx,
+ r->in.level,
+ &_i,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = num_entries;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = num_entries;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetFileEnum_l(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetFileEnum);
+}
diff --git a/source/lib/netapi/getdc.c b/source/lib/netapi/getdc.c
index c1d021b1d4..07a6544af1 100644
--- a/source/lib/netapi/getdc.c
+++ b/source/lib/netapi/getdc.c
@@ -31,7 +31,7 @@
WERROR NetGetDCName_l(struct libnetapi_ctx *ctx,
struct NetGetDCName *r)
{
- return WERR_NOT_SUPPORTED;
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGetDCName);
}
/********************************************************************
@@ -45,12 +45,10 @@ WERROR NetGetDCName_r(struct libnetapi_ctx *ctx,
NTSTATUS status;
WERROR werr;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_NETLOGON, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_netlogon.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -71,7 +69,7 @@ WERROR NetGetDCName_r(struct libnetapi_ctx *ctx,
WERROR NetGetAnyDCName_l(struct libnetapi_ctx *ctx,
struct NetGetAnyDCName *r)
{
- return WERR_NOT_SUPPORTED;
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGetAnyDCName);
}
/********************************************************************
@@ -85,12 +83,10 @@ WERROR NetGetAnyDCName_r(struct libnetapi_ctx *ctx,
NTSTATUS status;
WERROR werr;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_NETLOGON, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_netlogon.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -144,12 +140,10 @@ WERROR DsGetDcName_r(struct libnetapi_ctx *ctx,
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_NETLOGON, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_netlogon.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
diff --git a/source/lib/netapi/group.c b/source/lib/netapi/group.c
new file mode 100644
index 0000000000..c3fccb4840
--- /dev/null
+++ b/source/lib/netapi/group.c
@@ -0,0 +1,1691 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Group Support
+ * 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 "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t rid = 0;
+
+ struct GROUP_INFO_0 *info0 = NULL;
+ struct GROUP_INFO_1 *info1 = NULL;
+ struct GROUP_INFO_2 *info2 = NULL;
+ struct GROUP_INFO_3 *info3 = NULL;
+ union samr_GroupInfo info;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)r->in.buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)r->in.buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)r->in.buffer;
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_GROUP |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_group_name, info0->grpi0_name);
+ break;
+ case 1:
+ init_lsa_String(&lsa_group_name, info1->grpi1_name);
+ break;
+ case 2:
+ init_lsa_String(&lsa_group_name, info2->grpi2_name);
+ break;
+ case 3:
+ init_lsa_String(&lsa_group_name, info3->grpi3_name);
+ break;
+ }
+
+ status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
+ &domain_handle,
+ &lsa_group_name,
+ SEC_STD_DELETE |
+ SAMR_GROUP_ACCESS_SET_INFO,
+ &group_handle,
+ &rid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 1:
+ if (info1->grpi1_comment) {
+ init_lsa_String(&info.description,
+ info1->grpi1_comment);
+
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ }
+ break;
+ case 2:
+ if (info2->grpi2_comment) {
+ init_lsa_String(&info.description,
+ info2->grpi2_comment);
+
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+ }
+
+ if (info2->grpi2_attributes != 0) {
+ info.attributes.attributes = info2->grpi2_attributes;
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+
+ }
+ break;
+ case 3:
+ if (info3->grpi3_comment) {
+ init_lsa_String(&info.description,
+ info3->grpi3_comment);
+
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+ }
+
+ if (info3->grpi3_attributes != 0) {
+ info.attributes.attributes = info3->grpi3_attributes;
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto failed;
+ }
+
+ werr = WERR_OK;
+ goto done;
+
+ failed:
+ rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
+ &group_handle);
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+ int i = 0;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo *info = NULL;
+ struct samr_RidTypeArray *rid_array = NULL;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SEC_STD_DELETE |
+ SAMR_GROUP_ACCESS_GET_MEMBERS |
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER |
+ SAMR_GROUP_ACCESS_ADD_MEMBER |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+#if 0
+ /* breaks against NT4 */
+ if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
+ werr = WERR_ACCESS_DENIED;
+ goto done;
+ }
+#endif
+ status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
+ &group_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ {
+ struct lsa_Strings names;
+ struct samr_Ids member_types;
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &domain_handle,
+ rid_array->count,
+ rid_array->rids,
+ &names,
+ &member_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+
+ status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
+ &group_handle,
+ rid_array->rids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ ZERO_STRUCT(group_handle);
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo info;
+ struct GROUP_INFO_0 *g0;
+ struct GROUP_INFO_1 *g1;
+ struct GROUP_INFO_2 *g2;
+ struct GROUP_INFO_3 *g3;
+ struct GROUP_INFO_1002 *g1002;
+ struct GROUP_INFO_1005 *g1005;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_SET_INFO |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ g0 = (struct GROUP_INFO_0 *)r->in.buffer;
+ init_lsa_String(&info.name, g0->grpi0_name);
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFONAME,
+ &info);
+ break;
+ case 1:
+ g1 = (struct GROUP_INFO_1 *)r->in.buffer;
+ init_lsa_String(&info.description, g1->grpi1_comment);
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ break;
+ case 2:
+ g2 = (struct GROUP_INFO_2 *)r->in.buffer;
+ init_lsa_String(&info.description, g2->grpi2_comment);
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ info.attributes.attributes = g2->grpi2_attributes;
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+ break;
+ case 3:
+ g3 = (struct GROUP_INFO_3 *)r->in.buffer;
+ init_lsa_String(&info.description, g3->grpi3_comment);
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ info.attributes.attributes = g3->grpi3_attributes;
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+ break;
+ case 1002:
+ g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
+ init_lsa_String(&info.description, g1002->grpi1002_comment);
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFODESCRIPTION,
+ &info);
+ break;
+ case 1005:
+ g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
+ info.attributes.attributes = g1005->grpi1005_attributes;
+ status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &info);
+ break;
+ default:
+ status = NT_STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ struct samr_GroupInfoAll *info,
+ struct dom_sid2 *domain_sid,
+ uint32_t rid,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_0 info0;
+ struct GROUP_INFO_1 info1;
+ struct GROUP_INFO_2 info2;
+ struct GROUP_INFO_3 info3;
+ struct dom_sid sid;
+
+ switch (level) {
+ case 0:
+ info0.grpi0_name = info->name.string;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
+
+ break;
+ case 1:
+ info1.grpi1_name = info->name.string;
+ info1.grpi1_comment = info->description.string;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
+
+ break;
+ case 2:
+ info2.grpi2_name = info->name.string;
+ info2.grpi2_comment = info->description.string;
+ info2.grpi2_group_id = rid;
+ info2.grpi2_attributes = info->attributes;
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
+
+ break;
+ case 3:
+ if (!sid_compose(&sid, domain_sid, rid)) {
+ return WERR_NOMEM;
+ }
+
+ info3.grpi3_name = info->name.string;
+ info3.grpi3_comment = info->description.string;
+ info3.grpi3_attributes = info->attributes;
+ info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
+
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name;
+ struct dom_sid2 *domain_sid = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+ union samr_GroupInfo *info = NULL;
+ bool group_info_all = false;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_INVALID_DATATYPE;
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOALL2,
+ &info);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOALL,
+ &info);
+ group_info_all = true;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = map_group_info_to_buffer(ctx, r->in.level,
+ group_info_all ? &info->all : &info->all2,
+ domain_sid, rids.ids[0],
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name, lsa_user_name;
+ struct dom_sid2 *domain_sid = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = WERR_GROUP_NOT_FOUND;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_GROUP_NOT_FOUND;
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_ADD_MEMBER,
+ rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ init_lsa_String(&lsa_user_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_user_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = WERR_USER_NOT_FOUND;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_USER) {
+ werr = WERR_USER_NOT_FOUND;
+ goto done;
+ }
+
+ status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
+ &group_handle,
+ rids.ids[0],
+ 7); /* why ? */
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ POLICY_HND connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_group_name, lsa_user_name;
+ struct dom_sid2 *domain_sid = NULL;
+
+ struct samr_Ids rids;
+ struct samr_Ids types;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(group_handle);
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_group_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_group_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = WERR_GROUP_NOT_FOUND;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_DOM_GRP) {
+ werr = WERR_GROUP_NOT_FOUND;
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER,
+ rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ init_lsa_String(&lsa_user_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_user_name,
+ &rids,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = WERR_USER_NOT_FOUND;
+ goto done;
+ }
+
+ if (types.ids[0] != SID_NAME_USER) {
+ werr = WERR_USER_NOT_FOUND;
+ goto done;
+ }
+
+ status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
+ &group_handle,
+ rids.ids[0]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_0 *g0;
+ int i;
+
+ g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g0);
+
+ for (i=0; i<groups->count; i++) {
+ g0[i].grpi0_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
+ sizeof(struct GROUP_INFO_0) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_1 *g1;
+ int i;
+
+ g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g1);
+
+ for (i=0; i<groups->count; i++) {
+ g1[i].grpi1_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g1[i].grpi1_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
+ sizeof(struct GROUP_INFO_1) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_2 *g2;
+ int i;
+
+ g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g2);
+
+ for (i=0; i<groups->count; i++) {
+ g2[i].grpi2_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g2[i].grpi2_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ g2[i].grpi2_group_id = groups->entries[i].rid;
+ g2[i].grpi2_attributes = groups->entries[i].acct_flags;
+ W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
+ sizeof(struct GROUP_INFO_2) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
+ struct samr_DispInfoFullGroups *groups,
+ const struct dom_sid *domain_sid,
+ uint8_t **buffer)
+{
+ struct GROUP_INFO_3 *g3;
+ int i;
+
+ g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
+ W_ERROR_HAVE_NO_MEMORY(g3);
+
+ for (i=0; i<groups->count; i++) {
+
+ struct dom_sid sid;
+
+ if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
+ return WERR_NOMEM;
+ }
+
+ g3[i].grpi3_name = talloc_strdup(mem_ctx,
+ groups->entries[i].account_name.string);
+ g3[i].grpi3_comment = talloc_strdup(mem_ctx,
+ groups->entries[i].description.string);
+ g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+ g3[i].grpi3_attributes = groups->entries[i].acct_flags;
+ W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
+ }
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
+ sizeof(struct GROUP_INFO_3) * groups->count);
+ W_ERROR_HAVE_NO_MEMORY(*buffer);
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ struct samr_DispInfoFullGroups *groups,
+ const struct dom_sid *domain_sid,
+ uint32_t *entries_read,
+ uint8_t **buffer)
+{
+ if (entries_read) {
+ *entries_read = groups->count;
+ }
+
+ switch (level) {
+ case 0:
+ return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
+ case 1:
+ return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
+ case 2:
+ return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
+ case 3:
+ return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct policy_handle domain_handle;
+ union samr_DispInfo info;
+ union samr_DomainInfo *domain_info = NULL;
+
+ uint32_t total_size = 0;
+ uint32_t returned_size = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr, tmp_werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
+ &domain_handle,
+ 2,
+ &domain_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = domain_info->info2.num_groups;
+ }
+
+ status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
+ ctx,
+ &domain_handle,
+ 3,
+ r->in.resume_handle ?
+ *r->in.resume_handle : 0,
+ (uint32_t)-1,
+ r->in.prefmaxlen,
+ &total_size,
+ &returned_size,
+ &info);
+ werr = ntstatus_to_werror(status);
+ if (NT_STATUS_IS_ERR(status)) {
+ goto done;
+ }
+
+ if (r->out.resume_handle) {
+ *r->out.resume_handle =
+ info.info3.entries[info.info3.count-1].idx;
+ }
+
+ tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
+ r->in.level,
+ &info.info3,
+ domain_sid,
+ r->out.entries_read,
+ r->out.buffer);
+ if (!W_ERROR_IS_OK(tmp_werr)) {
+ werr = tmp_werr;
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ /* if last query */
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_IS_ERR(status)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ /* FIXME: this call needs to cope with large replies */
+
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids group_rids, name_types;
+ struct samr_RidTypeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids member_types;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS,
+ group_rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
+ &group_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &domain_handle,
+ rid_array->count,
+ rid_array->rids,
+ &names,
+ &member_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+
+ if (member_types.ids[i] != SID_NAME_USER) {
+ continue;
+ }
+
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ 7,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = entries_read;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = entries_read;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_GroupInfo *group_info = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_Ids group_rids, group_types;
+ struct samr_RidTypeArray *rid_array = NULL;
+ struct lsa_String *lsa_names = NULL;
+
+ uint32_t *add_rids = NULL;
+ uint32_t *del_rids = NULL;
+ size_t num_add_rids = 0;
+ size_t num_del_rids = 0;
+
+ uint32_t *member_rids = NULL;
+ size_t num_member_rids = 0;
+
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ int i, k;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &group_rids,
+ &group_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_GET_MEMBERS |
+ SAMR_GROUP_ACCESS_ADD_MEMBER |
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER |
+ SAMR_GROUP_ACCESS_LOOKUP_INFO,
+ group_rids.ids[0],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
+ &group_handle,
+ GROUPINFOATTRIBUTES,
+ &group_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
+ break;
+ }
+
+ lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
+ if (!lsa_names) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < r->in.num_entries; i++) {
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_names[i], i0->grui0_name);
+ i0++;
+ break;
+ case 1:
+ init_lsa_String(&lsa_names[i], i1->grui1_name);
+ i1++;
+ break;
+ }
+ }
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ r->in.num_entries,
+ lsa_names,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ member_rids = user_rids.ids;
+ num_member_rids = user_rids.count;
+
+ status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
+ &group_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.num_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < rid_array->count; k++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ if (!add_rid_to_array_unique(ctx,
+ member_rids[i],
+ &add_rids, &num_add_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < rid_array->count; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.num_entries; i++) {
+ if (member_rids[i] == rid_array->rids[k]) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ if (!add_rid_to_array_unique(ctx,
+ rid_array->rids[k],
+ &del_rids, &num_del_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_rids; i++) {
+ status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
+ &group_handle,
+ add_rids[i],
+ 7 /* ? */);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_rids; i++) {
+ status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
+ &group_handle,
+ del_rids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);
+}
diff --git a/source/lib/netapi/joindomain.c b/source/lib/netapi/joindomain.c
index 66f7cfb13f..d15e2e733c 100644
--- a/source/lib/netapi/joindomain.c
+++ b/source/lib/netapi/joindomain.c
@@ -105,12 +105,10 @@ WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
WERROR werr;
unsigned int old_timeout = 0;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server,
+ &ndr_table_wkssvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -236,12 +234,10 @@ WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
WERROR werr;
unsigned int old_timeout = 0;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -288,12 +284,10 @@ WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
WERROR werr;
const char *buffer = NULL;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -370,7 +364,7 @@ WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
dc = strip_hostname(info->dc_unc);
- ads = ads_init(r->in.domain, r->in.domain, dc);
+ ads = ads_init(info->domain_name, info->domain_name, dc);
if (!ads) {
return WERR_GENERAL_FAILURE;
}
@@ -389,7 +383,7 @@ WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
ads->auth.password = SMB_STRDUP(ctx->password);
}
- ads_status = ads_connect(ads);
+ ads_status = ads_connect_user_creds(ads);
if (!ADS_ERR_OK(ads_status)) {
ads_destroy(&ads);
return WERR_DEFAULT_JOIN_REQUIRED;
@@ -422,12 +416,10 @@ WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
NTSTATUS status;
WERROR werr;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -453,9 +445,57 @@ WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
}
done:
- if (cli) {
- cli_shutdown(cli);
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_wkssvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ if (r->in.password) {
+ encode_wkssvc_join_password_buffer(ctx,
+ r->in.password,
+ &cli->user_session_key,
+ &encrypted_password);
}
+ status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.new_machine_name,
+ r->in.account,
+ encrypted_password,
+ r->in.rename_options,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
return werr;
}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
+}
diff --git a/source/lib/netapi/libnetapi.c b/source/lib/netapi/libnetapi.c
index e71adc6893..043190a1f9 100644
--- a/source/lib/netapi/libnetapi.c
+++ b/source/lib/netapi/libnetapi.c
@@ -21,7 +21,7 @@
#include "librpc/gen_ndr/libnetapi.h"
#include "lib/netapi/netapi.h"
#include "lib/netapi/netapi_private.h"
-#include "libnetapi.h"
+#include "lib/netapi/libnetapi.h"
#include "librpc/gen_ndr/ndr_libnetapi.h"
/****************************************************************
@@ -215,6 +215,54 @@ NET_API_STATUS NetGetJoinableOUs(const char * server_name /* [in] [unique] */,
}
/****************************************************************
+ NetRenameMachineInDomain
+****************************************************************/
+
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */)
+{
+ struct NetRenameMachineInDomain r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.new_machine_name = new_machine_name;
+ r.in.account = account;
+ r.in.password = password;
+ r.in.rename_options = rename_options;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetRenameMachineInDomain, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetRenameMachineInDomain_l(ctx, &r);
+ } else {
+ werr = NetRenameMachineInDomain_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetRenameMachineInDomain, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
NetServerGetInfo
****************************************************************/
@@ -586,6 +634,390 @@ NET_API_STATUS NetUserEnum(const char * server_name /* [in] [unique] */,
}
/****************************************************************
+ NetUserChangePassword
+****************************************************************/
+
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */)
+{
+ struct NetUserChangePassword r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.domain_name = domain_name;
+ r.in.user_name = user_name;
+ r.in.old_password = old_password;
+ r.in.new_password = new_password;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserChangePassword, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(domain_name)) {
+ werr = NetUserChangePassword_l(ctx, &r);
+ } else {
+ werr = NetUserChangePassword_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserChangePassword, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserGetInfo
+****************************************************************/
+
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetUserGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetInfo_l(ctx, &r);
+ } else {
+ werr = NetUserGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserSetInfo
+****************************************************************/
+
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetUserSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserSetInfo_l(ctx, &r);
+ } else {
+ werr = NetUserSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserSetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserGetGroups
+****************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */)
+{
+ struct NetUserGetGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetGroups_l(ctx, &r);
+ } else {
+ werr = NetUserGetGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetGroups, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserSetGroups
+****************************************************************/
+
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */)
+{
+ struct NetUserSetGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.num_entries = num_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserSetGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserSetGroups_l(ctx, &r);
+ } else {
+ werr = NetUserSetGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserSetGroups, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserGetLocalGroups
+****************************************************************/
+
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */)
+{
+ struct NetUserGetLocalGroups r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.flags = flags;
+ r.in.prefmaxlen = prefmaxlen;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserGetLocalGroups, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserGetLocalGroups_l(ctx, &r);
+ } else {
+ werr = NetUserGetLocalGroups_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserGetLocalGroups, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserModalsGet
+****************************************************************/
+
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetUserModalsGet r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserModalsGet, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserModalsGet_l(ctx, &r);
+ } else {
+ werr = NetUserModalsGet_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserModalsGet, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetUserModalsSet
+****************************************************************/
+
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetUserModalsSet r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetUserModalsSet, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetUserModalsSet_l(ctx, &r);
+ } else {
+ werr = NetUserModalsSet_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetUserModalsSet, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
NetQueryDisplayInformation
****************************************************************/
@@ -637,3 +1069,1287 @@ NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [uniq
return r.out.result;
}
+/****************************************************************
+ NetGroupAdd
+****************************************************************/
+
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetGroupAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupAdd_l(ctx, &r);
+ } else {
+ werr = NetGroupAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupAdd, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupDel
+****************************************************************/
+
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */)
+{
+ struct NetGroupDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupDel_l(ctx, &r);
+ } else {
+ werr = NetGroupDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupDel, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupEnum
+****************************************************************/
+
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetGroupEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupEnum_l(ctx, &r);
+ } else {
+ werr = NetGroupEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupEnum, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupSetInfo
+****************************************************************/
+
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetGroupSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupSetInfo_l(ctx, &r);
+ } else {
+ werr = NetGroupSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupSetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupGetInfo
+****************************************************************/
+
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetGroupGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupGetInfo_l(ctx, &r);
+ } else {
+ werr = NetGroupGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupGetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupAddUser
+****************************************************************/
+
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */)
+{
+ struct NetGroupAddUser r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.user_name = user_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupAddUser, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupAddUser_l(ctx, &r);
+ } else {
+ werr = NetGroupAddUser_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupAddUser, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupDelUser
+****************************************************************/
+
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */)
+{
+ struct NetGroupDelUser r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.user_name = user_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupDelUser, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupDelUser_l(ctx, &r);
+ } else {
+ werr = NetGroupDelUser_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupDelUser, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupGetUsers
+****************************************************************/
+
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetGroupGetUsers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupGetUsers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupGetUsers_l(ctx, &r);
+ } else {
+ werr = NetGroupGetUsers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupGetUsers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetGroupSetUsers
+****************************************************************/
+
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */)
+{
+ struct NetGroupSetUsers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.num_entries = num_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetGroupSetUsers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetGroupSetUsers_l(ctx, &r);
+ } else {
+ werr = NetGroupSetUsers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetGroupSetUsers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupAdd
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetLocalGroupAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupAdd_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupAdd, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupDel
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */)
+{
+ struct NetLocalGroupDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupDel_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupDel, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupGetInfo
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetLocalGroupGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupGetInfo_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupGetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupSetInfo
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetLocalGroupSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupSetInfo_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupSetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupEnum
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetLocalGroupEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupEnum_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupEnum, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupAddMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupAddMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupAddMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupAddMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupAddMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupAddMembers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupDelMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupDelMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupDelMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupDelMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupDelMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupDelMembers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupGetMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetLocalGroupGetMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.local_group_name = local_group_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupGetMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupGetMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupGetMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupGetMembers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetLocalGroupSetMembers
+****************************************************************/
+
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */)
+{
+ struct NetLocalGroupSetMembers r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.group_name = group_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+ r.in.total_entries = total_entries;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetLocalGroupSetMembers, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetLocalGroupSetMembers_l(ctx, &r);
+ } else {
+ werr = NetLocalGroupSetMembers_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetLocalGroupSetMembers, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetRemoteTOD
+****************************************************************/
+
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetRemoteTOD r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetRemoteTOD, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetRemoteTOD_l(ctx, &r);
+ } else {
+ werr = NetRemoteTOD_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetRemoteTOD, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetShareAdd
+****************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetShareAdd r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareAdd, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareAdd_l(ctx, &r);
+ } else {
+ werr = NetShareAdd_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareAdd, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetShareDel
+****************************************************************/
+
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */)
+{
+ struct NetShareDel r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.reserved = reserved;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareDel, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareDel_l(ctx, &r);
+ } else {
+ werr = NetShareDel_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareDel, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetShareEnum
+****************************************************************/
+
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetShareEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareEnum_l(ctx, &r);
+ } else {
+ werr = NetShareEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareEnum, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetShareGetInfo
+****************************************************************/
+
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetShareGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareGetInfo_l(ctx, &r);
+ } else {
+ werr = NetShareGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareGetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetShareSetInfo
+****************************************************************/
+
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */)
+{
+ struct NetShareSetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.net_name = net_name;
+ r.in.level = level;
+ r.in.buffer = buffer;
+
+ /* Out parameters */
+ r.out.parm_err = parm_err;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetShareSetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetShareSetInfo_l(ctx, &r);
+ } else {
+ werr = NetShareSetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetShareSetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetFileClose
+****************************************************************/
+
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */)
+{
+ struct NetFileClose r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.fileid = fileid;
+
+ /* Out parameters */
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileClose, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileClose_l(ctx, &r);
+ } else {
+ werr = NetFileClose_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileClose, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetFileGetInfo
+****************************************************************/
+
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */)
+{
+ struct NetFileGetInfo r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.fileid = fileid;
+ r.in.level = level;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileGetInfo, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileGetInfo_l(ctx, &r);
+ } else {
+ werr = NetFileGetInfo_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileGetInfo, &r);
+ }
+
+ return r.out.result;
+}
+
+/****************************************************************
+ NetFileEnum
+****************************************************************/
+
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */)
+{
+ struct NetFileEnum r;
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ /* In parameters */
+ r.in.server_name = server_name;
+ r.in.base_path = base_path;
+ r.in.user_name = user_name;
+ r.in.level = level;
+ r.in.prefmaxlen = prefmaxlen;
+ r.in.resume_handle = resume_handle;
+
+ /* Out parameters */
+ r.out.buffer = buffer;
+ r.out.entries_read = entries_read;
+ r.out.total_entries = total_entries;
+ r.out.resume_handle = resume_handle;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_IN_DEBUG(NetFileEnum, &r);
+ }
+
+ if (LIBNETAPI_LOCAL_SERVER(server_name)) {
+ werr = NetFileEnum_l(ctx, &r);
+ } else {
+ werr = NetFileEnum_r(ctx, &r);
+ }
+
+ r.out.result = W_ERROR_V(werr);
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_OUT_DEBUG(NetFileEnum, &r);
+ }
+
+ return r.out.result;
+}
+
diff --git a/source/lib/netapi/libnetapi.h b/source/lib/netapi/libnetapi.h
index 7aff355652..1b84b75f94 100644
--- a/source/lib/netapi/libnetapi.h
+++ b/source/lib/netapi/libnetapi.h
@@ -35,6 +35,15 @@ WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
struct NetGetJoinableOUs *r);
WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
struct NetGetJoinableOUs *r);
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */);
+WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r);
+WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
+ struct NetRenameMachineInDomain *r);
NET_API_STATUS NetServerGetInfo(const char * server_name /* [in] [unique] */,
uint32_t level /* [in] */,
uint8_t **buffer /* [out] [ref] */);
@@ -100,6 +109,78 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
struct NetUserEnum *r);
WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
struct NetUserEnum *r);
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */);
+WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r);
+WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r);
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r);
+WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r);
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r);
+WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r);
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r);
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r);
+WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r);
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r);
+WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r);
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r);
+WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r);
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r);
+WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r);
NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [unique] */,
uint32_t level /* [in] */,
uint32_t idx /* [in] */,
@@ -111,4 +192,238 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
struct NetQueryDisplayInformation *r);
WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
struct NetQueryDisplayInformation *r);
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r);
+WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAdd *r);
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r);
+WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDel *r);
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r);
+WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetGroupEnum *r);
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r);
+WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetInfo *r);
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r);
+WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetInfo *r);
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r);
+WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupAddUser *r);
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r);
+WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
+ struct NetGroupDelUser *r);
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r);
+WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupGetUsers *r);
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r);
+WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
+ struct NetGroupSetUsers *r);
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r);
+WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r);
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r);
+WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r);
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r);
+WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r);
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r);
+WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r);
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r);
+WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r);
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r);
+WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r);
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r);
+WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r);
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r);
+WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r);
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r);
+WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r);
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r);
+WERROR NetRemoteTOD_l(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r);
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r);
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */);
+WERROR NetShareDel_r(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r);
+WERROR NetShareDel_l(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r);
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetShareEnum_r(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r);
+WERROR NetShareEnum_l(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r);
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r);
+WERROR NetShareGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r);
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r);
+WERROR NetShareSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r);
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */);
+WERROR NetFileClose_r(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r);
+WERROR NetFileClose_l(struct libnetapi_ctx *ctx,
+ struct NetFileClose *r);
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r);
+WERROR NetFileGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetFileGetInfo *r);
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+WERROR NetFileEnum_r(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r);
+WERROR NetFileEnum_l(struct libnetapi_ctx *ctx,
+ struct NetFileEnum *r);
#endif /* __LIBNETAPI_LIBNETAPI__ */
diff --git a/source/lib/netapi/localgroup.c b/source/lib/netapi/localgroup.c
new file mode 100644
index 0000000000..25a3427bc1
--- /dev/null
+++ b/source/lib/netapi/localgroup.c
@@ -0,0 +1,1358 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi LocalGroup Support
+ * 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 "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ const char *group_name,
+ uint32_t access_rights,
+ struct policy_handle *alias_handle)
+{
+ NTSTATUS status;
+
+ struct lsa_String lsa_account_name;
+ struct samr_Ids user_rids, name_types;
+
+ init_lsa_String(&lsa_account_name, group_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
+ domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ switch (name_types.ids[0]) {
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ break;
+ default:
+ return NT_STATUS_INVALID_SID;
+ }
+
+ return rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
+ domain_handle,
+ access_rights,
+ user_rids.ids[0],
+ alias_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *handle,
+ uint32_t rid,
+ uint32_t access_rights,
+ enum samr_AliasInfoEnum level,
+ union samr_AliasInfo **alias_info)
+{
+ NTSTATUS status;
+ struct policy_handle alias_handle;
+ union samr_AliasInfo *_alias_info = NULL;
+
+ ZERO_STRUCT(alias_handle);
+
+ status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
+ handle,
+ access_rights,
+ rid,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
+ &alias_handle,
+ level,
+ &_alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ *alias_info = _alias_info;
+
+ done:
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
+ }
+
+ return status;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t rid;
+
+ struct LOCALGROUP_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_INFO_1 *info1 = NULL;
+
+ const char *alias_name = NULL;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
+ alias_name = info0->lgrpi0_name;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
+ alias_name = info1->lgrpi1_name;
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ alias_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ werr = WERR_ALIAS_EXISTS;
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, alias_name);
+
+ status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
+ &domain_handle,
+ &lsa_account_name,
+ SEC_STD_DELETE |
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle,
+ &rid);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->in.level == 1 && info1->lgrpi1_comment) {
+
+ union samr_AliasInfo alias_info;
+
+ init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
+
+ status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
+ &alias_handle,
+ ALIASINFODESCRIPTION,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+
+WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SEC_STD_DELETE,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto delete_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SEC_STD_DELETE,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+
+ delete_alias:
+ status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ ZERO_STRUCT(alias_handle);
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
+ const char *alias_name,
+ struct samr_AliasInfoAll *info,
+ uint32_t level,
+ uint32_t *entries_read,
+ uint8_t **buffer)
+{
+ struct LOCALGROUP_INFO_0 g0;
+ struct LOCALGROUP_INFO_1 g1;
+ struct LOCALGROUP_INFO_1002 g1002;
+
+ switch (level) {
+ case 0:
+ g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
+ W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
+ (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
+
+ break;
+ case 1:
+ g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
+ g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
+ W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
+ (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
+
+ break;
+ case 1002:
+ g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
+ (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
+
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ union samr_AliasInfo *alias_info = NULL;
+ uint32_t entries_read = 0;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 1002:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto query_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ query_alias:
+ status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
+ &alias_handle,
+ ALIASINFOALL,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ r->in.group_name,
+ &alias_info->all,
+ r->in.level, &entries_read,
+ r->out.buffer);
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ uint8_t *buffer,
+ enum samr_AliasInfoEnum *alias_level,
+ union samr_AliasInfo **alias_info)
+{
+ struct LOCALGROUP_INFO_0 *info0;
+ struct LOCALGROUP_INFO_1 *info1;
+ struct LOCALGROUP_INFO_1002 *info1002;
+ union samr_AliasInfo *info = NULL;
+
+ info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
+ W_ERROR_HAVE_NO_MEMORY(info);
+
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ init_lsa_String(&info->name, info0->lgrpi0_name);
+ *alias_level = ALIASINFONAME;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ /* group name will be ignored */
+ init_lsa_String(&info->description, info1->lgrpi1_comment);
+ *alias_level = ALIASINFODESCRIPTION;
+ break;
+ case 1002:
+ info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
+ init_lsa_String(&info->description, info1002->lgrpi1002_comment);
+ *alias_level = ALIASINFODESCRIPTION;
+ break;
+ }
+
+ *alias_info = info;
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ enum samr_AliasInfoEnum alias_level = 0;
+ union samr_AliasInfo *alias_info = NULL;
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 1002:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto set_alias;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_SET_INFO,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ set_alias:
+
+ werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
+ &alias_level, &alias_info);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
+ &alias_handle,
+ alias_level,
+ alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t entries_read = 0;
+ union samr_DomainInfo *domain_info = NULL;
+ union samr_DomainInfo *builtin_info = NULL;
+ struct samr_SamArray *domain_sam_array = NULL;
+ struct samr_SamArray *builtin_sam_array = NULL;
+ int i;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries = 0;
+ }
+ if (r->out.entries_read) {
+ *r->out.entries_read = 0;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
+ &builtin_handle,
+ 2,
+ &builtin_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries += builtin_info->info2.num_aliases;
+ }
+
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
+ &domain_handle,
+ 2,
+ &domain_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (r->out.total_entries) {
+ *r->out.total_entries += domain_info->info2.num_aliases;
+ }
+
+ status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
+ &builtin_handle,
+ r->in.resume_handle,
+ &builtin_sam_array,
+ r->in.prefmaxlen,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<builtin_sam_array->count; i++) {
+ union samr_AliasInfo *alias_info = NULL;
+
+ if (r->in.level == 1) {
+
+ status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
+ &builtin_handle,
+ builtin_sam_array->entries[i].idx,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ ALIASINFOALL,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ builtin_sam_array->entries[i].name.string,
+ alias_info ? &alias_info->all : NULL,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ }
+
+ status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
+ &domain_handle,
+ r->in.resume_handle,
+ &domain_sam_array,
+ r->in.prefmaxlen,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<domain_sam_array->count; i++) {
+
+ union samr_AliasInfo *alias_info = NULL;
+
+ if (r->in.level == 1) {
+ status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
+ &domain_handle,
+ domain_sam_array->entries[i].idx,
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ ALIASINFOALL,
+ &alias_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = map_alias_info_to_buffer(ctx,
+ domain_sam_array->entries[i].name.string,
+ alias_info ? &alias_info->all : NULL,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *lsa_pipe,
+ const char *name,
+ struct dom_sid *sid)
+{
+ NTSTATUS status;
+ struct policy_handle lsa_handle;
+
+ struct lsa_RefDomainList *domains = NULL;
+ struct lsa_TransSidArray3 sids;
+ uint32_t count = 0;
+
+ struct lsa_String names;
+ uint32_t num_names = 1;
+
+ if (!sid || !name) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(sids);
+
+ init_lsa_String(&names, name);
+
+ status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
+ false,
+ STD_RIGHT_READ_CONTROL_ACCESS |
+ LSA_POLICY_VIEW_LOCAL_INFORMATION |
+ LSA_POLICY_LOOKUP_NAMES,
+ &lsa_handle);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
+ &lsa_handle,
+ num_names,
+ &names,
+ &domains,
+ &sids,
+ LSA_LOOKUP_NAMES_ALL, /* sure ? */
+ &count,
+ 0, 0);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ if (count != 1 || sids.count != 1) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ sid_copy(sid, sids.sids[0].sid);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *add,
+ struct NetLocalGroupDelMembers *del,
+ struct NetLocalGroupSetMembers *set)
+{
+ struct NetLocalGroupAddMembers *r = NULL;
+
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct rpc_pipe_client *lsa_pipe = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct lsa_String lsa_account_name;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ struct dom_sid *member_sids = NULL;
+ int i = 0, k = 0;
+
+ struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
+ struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
+
+ struct dom_sid *add_sids = NULL;
+ struct dom_sid *del_sids = NULL;
+ size_t num_add_sids = 0;
+ size_t num_del_sids = 0;
+
+ if ((!add && !del && !set) || (add && del && set)) {
+ return WERR_INVALID_PARAM;
+ }
+
+ if (add) {
+ r = add;
+ }
+
+ if (del) {
+ r = (struct NetLocalGroupAddMembers *)del;
+ }
+
+ if (set) {
+ r = (struct NetLocalGroupAddMembers *)set;
+ }
+
+ if (!r->in.group_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 3:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ if (r->in.total_entries == 0 || !r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(alias_handle);
+
+ member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
+ r->in.total_entries);
+ W_ERROR_HAVE_NO_MEMORY(member_sids);
+
+ switch (r->in.level) {
+ case 0:
+ info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
+ for (i=0; i < r->in.total_entries; i++) {
+ sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
+ }
+ break;
+ case 3:
+ info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
+ break;
+ default:
+ break;
+ }
+
+ if (r->in.level == 3) {
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_lsarpc.syntax_id,
+ &cli,
+ &lsa_pipe);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ for (i=0; i < r->in.total_entries; i++) {
+ status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
+ info3[i].lgrmi3_domainandname,
+ &member_sids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ TALLOC_FREE(lsa_pipe);
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_OPEN_DOMAIN |
+ SAMR_ACCESS_ENUM_DOMAINS,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.group_name);
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &builtin_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_ADD_MEMBER |
+ SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+ SAMR_ALIAS_ACCESS_GET_MEMBERS |
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto modify_membership;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+ &domain_handle,
+ r->in.group_name,
+ SAMR_ALIAS_ACCESS_ADD_MEMBER |
+ SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+ SAMR_ALIAS_ACCESS_GET_MEMBERS |
+ SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+ &alias_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ }
+
+ modify_membership:
+
+ if (add) {
+ for (i=0; i < r->in.total_entries; i++) {
+ status = add_sid_to_array_unique(ctx, &member_sids[i],
+ &add_sids,
+ &num_add_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ if (del) {
+ for (i=0; i < r->in.total_entries; i++) {
+ status = add_sid_to_array_unique(ctx, &member_sids[i],
+ &del_sids,
+ &num_del_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ if (set) {
+
+ struct lsa_SidArray current_sids;
+
+ status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
+ &alias_handle,
+ &current_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.total_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < current_sids.num_sids; k++) {
+ if (sid_equal(&member_sids[i],
+ current_sids.sids[k].sid)) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ status = add_sid_to_array_unique(ctx,
+ &member_sids[i],
+ &add_sids, &num_add_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < current_sids.num_sids; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.total_entries; i++) {
+ if (sid_equal(&member_sids[i],
+ current_sids.sids[k].sid)) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ status = add_sid_to_array_unique(ctx,
+ current_sids.sids[k].sid,
+ &del_sids, &num_del_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_sids; i++) {
+ status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
+ &alias_handle,
+ &add_sids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_sids; i++) {
+ status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
+ &alias_handle,
+ &del_sids[i]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&alias_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupAddMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupDelMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupGetMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r)
+{
+ return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
+ struct NetLocalGroupSetMembers *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);
+}
+
diff --git a/source/lib/netapi/netapi.c b/source/lib/netapi/netapi.c
index cf1be00849..889388173f 100644
--- a/source/lib/netapi/netapi.c
+++ b/source/lib/netapi/netapi.c
@@ -30,8 +30,30 @@ static bool libnetapi_initialized = false;
/****************************************************************
****************************************************************/
+static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!ctx) {
+ return W_ERROR_V(WERR_INVALID_PARAM);
+ }
+
+ priv = TALLOC_ZERO_P(ctx, struct libnetapi_private_ctx);
+ if (!priv) {
+ return W_ERROR_V(WERR_NOMEM);
+ }
+
+ ctx->private_data = priv;
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
{
+ NET_API_STATUS status;
struct libnetapi_ctx *ctx = NULL;
char *krb5_cc_env = NULL;
@@ -96,6 +118,12 @@ NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
return W_ERROR_V(WERR_NOMEM);
}
+ status = libnetapi_init_private_context(ctx);
+ if (status != 0) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
libnetapi_initialized = true;
*context = stat_ctx = ctx;
@@ -125,6 +153,8 @@ NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
return NET_API_STATUS_SUCCESS;
}
+ libnetapi_samr_free(ctx);
+
libnetapi_shutdown_cm(ctx);
if (ctx->krb5_cc_env) {
@@ -279,6 +309,33 @@ const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
/****************************************************************
****************************************************************/
+NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
+ void **buffer)
+{
+ void *buf = NULL;
+
+ if (!buffer) {
+ return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
+ }
+
+ if (byte_count == 0) {
+ goto done;
+ }
+
+ buf = talloc_size(NULL, byte_count);
+ if (!buf) {
+ return W_ERROR_V(WERR_NOMEM);
+ }
+
+ done:
+ *buffer = buf;
+
+ return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
NET_API_STATUS NetApiBufferFree(void *buffer)
{
if (!buffer) {
diff --git a/source/lib/netapi/netapi.h b/source/lib/netapi/netapi.h
index ce97e4c02e..9687461920 100644
--- a/source/lib/netapi/netapi.h
+++ b/source/lib/netapi/netapi.h
@@ -33,6 +33,8 @@ typedef enum {
#define ERROR_MORE_DATA ( 234L )
+#define ENCRYPTED_PWLEN ( 16 )
+
/****************************************************************
****************************************************************/
@@ -50,6 +52,17 @@ struct GUID {
#ifndef _HEADER_libnetapi
+#ifndef MAXSUBAUTHS
+#define MAXSUBAUTHS 15 /* max sub authorities in a SID */
+#endif
+
+struct domsid {
+ uint8_t sid_rev_num;
+ uint8_t num_auths;
+ uint8_t id_auth[6];
+ uint32_t sub_auths[MAXSUBAUTHS];
+};
+
struct DOMAIN_CONTROLLER_INFO {
const char * domain_controller_name;
const char * domain_controller_address;
@@ -62,6 +75,66 @@ struct DOMAIN_CONTROLLER_INFO {
const char * client_site_name;
};
+/* bitmap NetJoinFlags */
+#define NETSETUP_JOIN_DOMAIN ( 0x00000001 )
+#define NETSETUP_ACCT_CREATE ( 0x00000002 )
+#define NETSETUP_ACCT_DELETE ( 0x00000004 )
+#define NETSETUP_WIN9X_UPGRADE ( 0x00000010 )
+#define NETSETUP_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define NETSETUP_JOIN_UNSECURE ( 0x00000040 )
+#define NETSETUP_MACHINE_PWD_PASSED ( 0x00000080 )
+#define NETSETUP_DEFER_SPN_SET ( 0x00000100 )
+#define NETSETUP_JOIN_DC_ACCOUNT ( 0x00000200 )
+#define NETSETUP_JOIN_WITH_NEW_NAME ( 0x00000400 )
+#define NETSETUP_INSTALL_INVOCATION ( 0x00040000 )
+#define NETSETUP_IGNORE_UNSUPPORTED_FLAGS ( 0x10000000 )
+
+#define FILTER_TEMP_DUPLICATE_ACCOUNT ( 0x0001 )
+#define FILTER_NORMAL_ACCOUNT ( 0x0002 )
+#define FILTER_INTERDOMAIN_TRUST_ACCOUNT ( 0x0008 )
+#define FILTER_WORKSTATION_TRUST_ACCOUNT ( 0x0010 )
+#define FILTER_SERVER_TRUST_ACCOUNT ( 0x0020 )
+
+#define TIMEQ_FOREVER ( (uint32_t)-1L )
+
+enum NETSETUP_JOIN_STATUS {
+ NetSetupUnknownStatus=0,
+ NetSetupUnjoined=1,
+ NetSetupWorkgroupName=2,
+ NetSetupDomainName=3
+};
+
+struct SERVER_INFO_100 {
+ uint32_t sv100_platform_id;
+ const char * sv100_name;
+};
+
+struct SERVER_INFO_101 {
+ uint32_t sv101_platform_id;
+ const char * sv101_name;
+ uint32_t sv101_version_major;
+ uint32_t sv101_version_minor;
+ uint32_t sv101_type;
+ const char * sv101_comment;
+};
+
+struct SERVER_INFO_102 {
+ uint32_t sv102_platform_id;
+ const char * sv102_name;
+ uint32_t sv102_version_major;
+ uint32_t sv102_version_minor;
+ uint32_t sv102_type;
+ const char * sv102_comment;
+ uint32_t sv102_users;
+ uint32_t sv102_disc;
+ uint8_t sv102_hidden;
+ uint32_t sv102_announce;
+ uint32_t sv102_anndelta;
+ uint32_t sv102_licenses;
+ const char * sv102_userpath;
+};
+
+
struct SERVER_INFO_1005 {
const char * sv1005_comment;
};
@@ -70,6 +143,10 @@ struct USER_INFO_0 {
const char * usri0_name;
};
+#define USER_PRIV_GUEST ( 0 )
+#define USER_PRIV_USER ( 1 )
+#define USER_PRIV_ADMIN ( 2 )
+
struct USER_INFO_1 {
const char * usri1_name;
const char * usri1_password;
@@ -81,6 +158,311 @@ struct USER_INFO_1 {
const char * usri1_script_path;
};
+#define AF_OP_PRINT ( 0x1 )
+#define AF_OP_COMM ( 0x2 )
+#define AF_OP_SERVER ( 0x4 )
+#define AF_OP_ACCOUNTS ( 0x8 )
+
+struct USER_INFO_2 {
+ const char * usri2_name;
+ const char * usri2_password;
+ uint32_t usri2_password_age;
+ uint32_t usri2_priv;
+ const char * usri2_home_dir;
+ const char * usri2_comment;
+ uint32_t usri2_flags;
+ const char * usri2_script_path;
+ uint32_t usri2_auth_flags;
+ const char * usri2_full_name;
+ const char * usri2_usr_comment;
+ const char * usri2_parms;
+ const char * usri2_workstations;
+ uint32_t usri2_last_logon;
+ uint32_t usri2_last_logoff;
+ uint32_t usri2_acct_expires;
+ uint32_t usri2_max_storage;
+ uint32_t usri2_units_per_week;
+ uint8_t *usri2_logon_hours;/* [unique] */
+ uint32_t usri2_bad_pw_count;
+ uint32_t usri2_num_logons;
+ const char * usri2_logon_server;
+ uint32_t usri2_country_code;
+ uint32_t usri2_code_page;
+};
+
+struct USER_INFO_3 {
+ const char * usri3_name;
+ uint32_t usri3_password_age;
+ uint32_t usri3_priv;
+ const char * usri3_home_dir;
+ const char * usri3_comment;
+ uint32_t usri3_flags;
+ const char * usri3_script_path;
+ uint32_t usri3_auth_flags;
+ const char * usri3_full_name;
+ const char * usri3_usr_comment;
+ const char * usri3_parms;
+ const char * usri3_workstations;
+ uint32_t usri3_last_logon;
+ uint32_t usri3_last_logoff;
+ uint32_t usri3_acct_expires;
+ uint32_t usri3_max_storage;
+ uint32_t usri3_units_per_week;
+ uint8_t *usri3_logon_hours;/* [unique] */
+ uint32_t usri3_bad_pw_count;
+ uint32_t usri3_num_logons;
+ const char * usri3_logon_server;
+ uint32_t usri3_country_code;
+ uint32_t usri3_code_page;
+ uint32_t usri3_user_id;
+ uint32_t usri3_primary_group_id;
+ const char * usri3_profile;
+ const char * usri3_home_dir_drive;
+ uint32_t usri3_password_expired;
+};
+
+struct USER_INFO_4 {
+ const char * usri4_name;
+ const char * usri4_password;
+ uint32_t usri4_password_age;
+ uint32_t usri4_priv;
+ const char * usri4_home_dir;
+ const char * usri4_comment;
+ uint32_t usri4_flags;
+ const char * usri4_script_path;
+ uint32_t usri4_auth_flags;
+ const char * usri4_full_name;
+ const char * usri4_usr_comment;
+ const char * usri4_parms;
+ const char * usri4_workstations;
+ uint32_t usri4_last_logon;
+ uint32_t usri4_last_logoff;
+ uint32_t usri4_acct_expires;
+ uint32_t usri4_max_storage;
+ uint32_t usri4_units_per_week;
+ uint8_t *usri4_logon_hours;/* [unique] */
+ uint32_t usri4_bad_pw_count;
+ uint32_t usri4_num_logons;
+ const char * usri4_logon_server;
+ uint32_t usri4_country_code;
+ uint32_t usri4_code_page;
+ struct domsid *usri4_user_sid;/* [unique] */
+ uint32_t usri4_primary_group_id;
+ const char * usri4_profile;
+ const char * usri4_home_dir_drive;
+ uint32_t usri4_password_expired;
+};
+
+struct USER_INFO_10 {
+ const char * usri10_name;
+ const char * usri10_comment;
+ const char * usri10_usr_comment;
+ const char * usri10_full_name;
+};
+
+struct USER_INFO_11 {
+ const char * usri11_name;
+ const char * usri11_comment;
+ const char * usri11_usr_comment;
+ const char * usri11_full_name;
+ uint32_t usri11_priv;
+ uint32_t usri11_auth_flags;
+ uint32_t usri11_password_age;
+ const char * usri11_home_dir;
+ const char * usri11_parms;
+ uint32_t usri11_last_logon;
+ uint32_t usri11_last_logoff;
+ uint32_t usri11_bad_pw_count;
+ uint32_t usri11_num_logons;
+ const char * usri11_logon_server;
+ uint32_t usri11_country_code;
+ const char * usri11_workstations;
+ uint32_t usri11_max_storage;
+ uint32_t usri11_units_per_week;
+ uint8_t *usri11_logon_hours;/* [unique] */
+ uint32_t usri11_code_page;
+};
+
+struct USER_INFO_20 {
+ const char * usri20_name;
+ const char * usri20_full_name;
+ const char * usri20_comment;
+ uint32_t usri20_flags;
+ uint32_t usri20_user_id;
+};
+
+struct USER_INFO_21 {
+ uint8_t *usri21_password;
+};
+
+struct USER_INFO_22 {
+ const char * usri22_name;
+ uint8_t *usri22_password;
+ uint32_t usri22_password_age;
+ uint32_t usri22_priv;
+ const char * usri22_home_dir;
+ const char * usri22_comment;
+ uint32_t usri22_flags;
+ uint32_t usri22_script_path;
+ uint32_t usri22_auth_flags;
+ const char * usri22_full_name;
+ const char * usri22_usr_comment;
+ const char * usri22_parms;
+ const char * usri22_workstations;
+ uint32_t usri22_last_logon;
+ uint32_t usri22_last_logoff;
+ uint32_t usri22_acct_expires;
+ uint32_t usri22_max_storage;
+ uint32_t usri22_units_per_week;
+ uint8_t *usri22_logon_hours;/* [unique] */
+ uint32_t usri22_bad_pw_count;
+ uint32_t usri22_num_logons;
+ const char * usri22_logon_server;
+ uint32_t usri22_country_code;
+ uint32_t usri22_code_page;
+};
+
+struct USER_INFO_23 {
+ const char * usri23_name;
+ const char * usri23_full_name;
+ const char * usri23_comment;
+ uint32_t usri23_flags;
+ struct domsid *usri23_user_sid;/* [unique] */
+};
+
+struct USER_INFO_1003 {
+ const char * usri1003_password;
+};
+
+struct USER_INFO_1005 {
+ uint32_t usri1005_priv;
+};
+
+struct USER_INFO_1006 {
+ const char * usri1006_home_dir;
+};
+
+struct USER_INFO_1007 {
+ const char * usri1007_comment;
+};
+
+struct USER_INFO_1008 {
+ uint32_t usri1008_flags;
+};
+
+struct USER_INFO_1009 {
+ const char * usri1009_script_path;
+};
+
+struct USER_INFO_1010 {
+ uint32_t usri1010_auth_flags;
+};
+
+struct USER_INFO_1011 {
+ const char * usri1011_full_name;
+};
+
+struct USER_INFO_1012 {
+ const char * usri1012_usr_comment;
+};
+
+struct USER_INFO_1013 {
+ const char * usri1013_parms;
+};
+
+struct USER_INFO_1014 {
+ const char * usri1014_workstations;
+};
+
+struct USER_INFO_1017 {
+ uint32_t usri1017_acct_expires;
+};
+
+struct USER_INFO_1018 {
+ uint32_t usri1018_max_storage;
+};
+
+struct USER_INFO_1020 {
+ uint32_t usri1020_units_per_week;
+ uint8_t *usri1020_logon_hours;/* [unique] */
+};
+
+struct USER_INFO_1023 {
+ const char * usri1023_logon_server;
+};
+
+struct USER_INFO_1024 {
+ uint32_t usri1024_country_code;
+};
+
+struct USER_INFO_1025 {
+ uint32_t usri1025_code_page;
+};
+
+struct USER_INFO_1051 {
+ uint32_t usri1051_primary_group_id;
+};
+
+struct USER_INFO_1052 {
+ const char * usri1052_profile;
+};
+
+struct USER_INFO_1053 {
+ const char * usri1053_home_dir_drive;
+};
+
+struct USER_MODALS_INFO_0 {
+ uint32_t usrmod0_min_passwd_len;
+ uint32_t usrmod0_max_passwd_age;
+ uint32_t usrmod0_min_passwd_age;
+ uint32_t usrmod0_force_logoff;
+ uint32_t usrmod0_password_hist_len;
+};
+
+struct USER_MODALS_INFO_1 {
+ uint32_t usrmod1_role;
+ const char * usrmod1_primary;
+};
+
+struct USER_MODALS_INFO_2 {
+ const char * usrmod2_domain_name;
+ struct domsid *usrmod2_domain_id;/* [unique] */
+};
+
+struct USER_MODALS_INFO_3 {
+ uint32_t usrmod3_lockout_duration;
+ uint32_t usrmod3_lockout_observation_window;
+ uint32_t usrmod3_lockout_threshold;
+};
+
+struct USER_MODALS_INFO_1001 {
+ uint32_t usrmod1001_min_passwd_len;
+};
+
+struct USER_MODALS_INFO_1002 {
+ uint32_t usrmod1002_max_passwd_age;
+};
+
+struct USER_MODALS_INFO_1003 {
+ uint32_t usrmod1003_min_passwd_age;
+};
+
+struct USER_MODALS_INFO_1004 {
+ uint32_t usrmod1004_force_logoff;
+};
+
+struct USER_MODALS_INFO_1005 {
+ uint32_t usrmod1005_password_hist_len;
+};
+
+struct USER_MODALS_INFO_1006 {
+ uint32_t usrmod1006_role;
+};
+
+struct USER_MODALS_INFO_1007 {
+ const char * usrmod1007_primary;
+};
+
struct NET_DISPLAY_USER {
const char * usri1_name;
const char * usri1_comment;
@@ -106,6 +488,163 @@ struct NET_DISPLAY_GROUP {
uint32_t grpi3_next_index;
};
+struct GROUP_INFO_0 {
+ const char * grpi0_name;
+};
+
+struct GROUP_INFO_1 {
+ const char * grpi1_name;
+ const char * grpi1_comment;
+};
+
+struct GROUP_INFO_2 {
+ const char * grpi2_name;
+ const char * grpi2_comment;
+ uint32_t grpi2_group_id;
+ uint32_t grpi2_attributes;
+};
+
+struct GROUP_INFO_3 {
+ const char * grpi3_name;
+ const char * grpi3_comment;
+ struct domsid * grpi3_group_sid;
+ uint32_t grpi3_attributes;
+};
+
+struct GROUP_INFO_1002 {
+ const char * grpi1002_comment;
+};
+
+struct GROUP_INFO_1005 {
+ uint32_t grpi1005_attributes;
+};
+
+struct GROUP_USERS_INFO_0 {
+ const char * grui0_name;
+};
+
+struct GROUP_USERS_INFO_1 {
+ const char * grui1_name;
+ uint32_t grui1_attributes;
+};
+
+struct LOCALGROUP_INFO_0 {
+ const char * lgrpi0_name;
+};
+
+struct LOCALGROUP_INFO_1 {
+ const char * lgrpi1_name;
+ const char * lgrpi1_comment;
+};
+
+struct LOCALGROUP_INFO_1002 {
+ const char * lgrpi1002_comment;
+};
+
+enum SID_NAME_USE {
+ SidTypeUser=1,
+ SidTypeGroup=2,
+ SidTypeDomain=3,
+ SidTypeAlias=4,
+ SidTypeWellKnownGroup=5,
+ SidTypeDeletedAccount=6,
+ SidTypeInvalid=7,
+ SidTypeUnknown=8,
+ SidTypeComputer=9,
+ SidTypeLabel=10
+};
+
+struct LOCALGROUP_MEMBERS_INFO_0 {
+ struct domsid *lgrmi0_sid;/* [unique] */
+};
+
+struct LOCALGROUP_MEMBERS_INFO_1 {
+ struct domsid *lgrmi1_sid;/* [unique] */
+ enum SID_NAME_USE lgrmi1_sidusage;
+ const char * lgrmi1_name;
+};
+
+struct LOCALGROUP_MEMBERS_INFO_2 {
+ struct domsid *lgrmi2_sid;/* [unique] */
+ enum SID_NAME_USE lgrmi2_sidusage;
+ const char * lgrmi2_domainandname;
+};
+
+struct LOCALGROUP_MEMBERS_INFO_3 {
+ const char * lgrmi3_domainandname;
+};
+
+struct LOCALGROUP_USERS_INFO_0 {
+ const char * lgrui0_name;
+};
+
+struct TIME_OF_DAY_INFO {
+ uint32_t tod_elapsedt;
+ uint32_t tod_msecs;
+ uint32_t tod_hours;
+ uint32_t tod_mins;
+ uint32_t tod_secs;
+ uint32_t tod_hunds;
+ int32_t tod_timezone;
+ uint32_t tod_tinterval;
+ uint32_t tod_day;
+ uint32_t tod_month;
+ uint32_t tod_year;
+ uint32_t tod_weekday;
+};
+
+struct SHARE_INFO_0 {
+ const char * shi0_netname;
+};
+
+struct SHARE_INFO_1 {
+ const char * shi1_netname;
+ uint32_t shi1_type;
+ const char * shi1_remark;
+};
+
+struct SHARE_INFO_2 {
+ const char * shi2_netname;
+ uint32_t shi2_type;
+ const char * shi2_remark;
+ uint32_t shi2_permissions;
+ uint32_t shi2_max_uses;
+ uint32_t shi2_current_uses;
+ const char * shi2_path;
+ const char * shi2_passwd;
+};
+
+struct SHARE_INFO_501 {
+ const char * shi501_netname;
+ uint32_t shi501_type;
+ const char * shi501_remark;
+ uint32_t shi501_flags;
+};
+
+struct SHARE_INFO_1004 {
+ const char * shi1004_remark;
+};
+
+struct SHARE_INFO_1005 {
+ uint32_t shi1005_flags;
+};
+
+struct SHARE_INFO_1006 {
+ uint32_t shi1006_max_uses;
+};
+
+struct FILE_INFO_2 {
+ uint32_t fi2_id;
+};
+
+struct FILE_INFO_3 {
+ uint32_t fi3_id;
+ uint32_t fi3_permissions;
+ uint32_t fi3_num_locks;
+ const char * fi3_pathname;
+ const char * fi3_username;
+};
+
#endif /* _HEADER_libnetapi */
/****************************************************************
@@ -119,6 +658,9 @@ struct libnetapi_ctx {
char *password;
char *krb5_cc_env;
int use_kerberos;
+ int disable_policy_handle_cache;
+
+ void *private_data;
};
/****************************************************************
@@ -176,6 +718,12 @@ const char *libnetapi_errstr(NET_API_STATUS status);
const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
NET_API_STATUS status);
+/****************************************************************
+ NetApiBufferAllocate
+****************************************************************/
+
+NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
+ void **buffer);
/****************************************************************
NetApiBufferFree
@@ -185,6 +733,36 @@ NET_API_STATUS NetApiBufferFree(void *buffer);
/************************************************************//**
*
+ * ConvertSidToStringSid
+ *
+ * @brief Convert a domain sid into a string
+ *
+ * @param[in] sid A pointer to a sid structure
+ * @param[in,out] sid_string A pointer that holds a pointer to a sid string. Caller
+ * needs to free with free(3)
+ * @return bool
+ ***************************************************************/
+
+int ConvertSidToStringSid(const struct domsid *sid,
+ char **sid_string);
+
+/************************************************************//**
+ *
+ * ConvertStringSidToSid
+ *
+ * @brief Convert a string into a domain sid
+ *
+ * @param[in] sid_string A pointer to a sid string.
+ * @param[in,out] sid A pointer that holds a pointer to a sid structure.
+ * Caller needs to free with free(3)
+ * @return bool
+ ***************************************************************/
+
+int ConvertStringSidToSid(const char *sid_string,
+ struct domsid **sid);
+
+/************************************************************//**
+ *
* NetJoinDomain
*
* @brief Join a computer to a domain or workgroup
@@ -274,6 +852,29 @@ NET_API_STATUS NetGetJoinableOUs(const char * server_name /* [in] */,
/************************************************************//**
*
+ * NetRenameMachineInDomain
+ *
+ * @brief Rename a machine in a domain
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] new_machine_name The new machine name
+ * @param[in] account The domain account used for the query
+ * @param[in] password The domain account's password used for the query
+ * @param[in] rename_options Options used for the rename operation
+ * @return NET_API_STATUS
+ *
+ * example join/rename_machine.c
+ *
+ ***************************************************************/
+
+NET_API_STATUS NetRenameMachineInDomain(const char * server_name /* [in] */,
+ const char * new_machine_name /* [in] */,
+ const char * account /* [in] */,
+ const char * password /* [in] */,
+ uint32_t rename_options /* [in] */);
+
+/************************************************************//**
+ *
* NetServerGetInfo
*
* @brief Get Information on a server
@@ -439,6 +1040,183 @@ NET_API_STATUS NetUserEnum(const char * server_name /* [in] */,
/************************************************************//**
*
+ * NetUserChangePassword
+ *
+ * @brief Change the password for a user on a given server or in a given domain
+ *
+ * @param[in] domain_name The server or domain name to connect to
+ * @param[in] user_name The user account to change the password for
+ * @param[in] old_password The user account's old password
+ * @param[in] new_password The user account's new password
+ * @return NET_API_STATUS
+ *
+ * example user/user_chgpwd.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserChangePassword(const char * domain_name /* [in] */,
+ const char * user_name /* [in] */,
+ const char * old_password /* [in] */,
+ const char * new_password /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUserGetInfo
+ *
+ * @brief Get User Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The name of the user that is going to be queried
+ * @param[in] level The level defining the requested USER_INFO_X structure
+ * @param[out] buffer The buffer containing a USER_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example user/user_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserSetInfo
+ *
+ * @brief Set User Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The name of the user that is going to be modified
+ * @param[in] level The level defining the requested USER_INFO_X structure
+ * @param[in] buffer The buffer containing a USER_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example user/user_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserSetInfo(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserModalsGet
+ *
+ * @brief Get SAM domain and password information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining which USER_MODALS_INFO_X buffer to query
+ * @param[out] buffer The returned USER_MODALS_INFO_X buffer
+ * @return NET_API_STATUS
+ *
+ * example user/user_modalsget.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserModalsGet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserModalsSet
+ *
+ * @brief Set SAM domain and password information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining which USER_MODALS_INFO_X buffer to query
+ * @param[out] buffer The buffer conntaing a USER_MODALS_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example user/user_modalsset.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserModalsSet(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserGetGroups
+ *
+ * @brief Enumerate grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @return NET_API_STATUS
+ *
+ * example user/user_getgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetUserSetGroups
+ *
+ * @brief Set grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The level defining the GROUP_USERS_INFO_X structures in the buffer
+ * @param[in] buffer The buffer containing GROUP_USERS_INFO_X structures
+ * @param[in] num_entries The number of X structures in the buffer
+ * @return NET_API_STATUS
+ *
+ * example user/user_setgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserSetGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetUserGetLocalGroups
+ *
+ * @brief Enumerate local grouplist of a user on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] user_name The user name to query
+ * @param[in] level The enumeration level used for the query
+ * @param[in] flags The flags used for the query
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @return NET_API_STATUS
+ *
+ * example user/user_getlocalgroups.c
+ ***************************************************************/
+
+NET_API_STATUS NetUserGetLocalGroups(const char * server_name /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint32_t flags /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */);
+
+/************************************************************//**
+ *
* NetQueryDisplayInformation
*
* @brief Enumerate accounts on a server
@@ -463,6 +1241,598 @@ NET_API_STATUS NetQueryDisplayInformation(const char * server_name /* [in] [uniq
uint32_t *entries_read /* [out] [ref] */,
void **buffer /* [out] [noprint,ref] */);
+/************************************************************//**
+ *
+ * NetGroupAdd
+ *
+ * @brief Create Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level used for the new group creation
+ * @param[in] buf The buffer containing the group structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example group/group_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupDel
+ *
+ * @brief Delete Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be deleted
+ * @return NET_API_STATUS
+ *
+ * example group/group_del.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupEnum
+ *
+ * @brief Enumerate groups on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example group/group_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupSetInfo
+ *
+ * @brief Set Domain Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] level The level defining the structure type in buf
+ * @param[in] buf The buffer containing a GROUP_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example group/group_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupGetInfo
+ *
+ * @brief Get Domain Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be queried
+ * @param[in] level The level defining the requested GROUP_INFO_X structure
+ * @param[out] buf The buffer containing a GROUP_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example group/group_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupAddUser
+ *
+ * @brief Add existing User to existing Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] user_name The name of the user that is going to be added to the
+ * group
+ * @return NET_API_STATUS
+ *
+ * example group/group_adduser.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupAddUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupDelUser
+ *
+ * @brief Remove User from Domain Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] user_name The name of the user that is going to be removed from
+ * the group
+ * @return NET_API_STATUS
+ *
+ * example group/group_deluser.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupDelUser(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ const char * user_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetGroupGetUsers
+ *
+ * @brief Get Users for a group on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The group name to enumerate users for
+ * @param[in] level The enumeration level used for the query
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example group/group_getusers.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupGetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetGroupSetUsers
+ *
+ * @brief Set Users for a group on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The group name to enumerate users for
+ * @param[in] level The enumeration level used for the query
+ * @param[in] buffer The buffer containing a X structure
+ * @param[in] num_entries The number of X entries in the buffer
+ * @return NET_API_STATUS
+ *
+ * example group/group_setusers.c
+ ***************************************************************/
+
+NET_API_STATUS NetGroupSetUsers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t num_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupAdd
+ *
+ * @brief Create Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level used for the new group creation
+ * @param[in] buf The buffer containing the group structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupDel
+ *
+ * @brief Delete Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be deleted
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_del.c
+ ***************************************************************/
+
+
+NET_API_STATUS NetLocalGroupDel(const char * server_name /* [in] */,
+ const char * group_name /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupGetInfo
+ *
+ * @brief Get Local Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be queried
+ * @param[in] level The level defining the requested LOCALGROUP_INFO_X structure
+ * @param[out] buf The buffer containing a LOCALGROUP_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupGetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupSetInfo
+ *
+ * @brief Set Local Group Information
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to be modified
+ * @param[in] level The level defining the requested LOCALGROUP_INFO_X structure
+ * @param[in] buf The buffer containing a LOCALGROUP_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_setinfo.c
+ ***************************************************************/
+
+
+NET_API_STATUS NetLocalGroupSetInfo(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buf /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupEnum
+ *
+ * @brief Enumerate local groups on a server
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The enumeration level used for the query (Currently only
+ * level 0 is supported)
+ * @param[out] buffer The returned enumeration buffer
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of returned entries
+ * @param[out] total_entries The number of total entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupAddMembers
+ *
+ * @brief Add Members to a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_addmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupAddMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupDelMembers
+ *
+ * @brief Delete Members from a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_delmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupDelMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupGetMembers
+ *
+ * @brief Enumerate Members in a local group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] local_group_name The localgroup that is going to be queried
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[out] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X
+ * structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of LOCALGROUP_MEMBERS_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of LOCALGROUP_MEMBERS_INFO_X entries for that group
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_getmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupGetMembers(const char * server_name /* [in] */,
+ const char * local_group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetLocalGroupSetMembers
+ *
+ * @brief Set Members in a Local Group
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] group_name The name of the group that is going to modified
+ * @param[in] level The level defining the LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] buffer The buffer containing a LOCALGROUP_MEMBERS_INFO_X structure
+ * @param[in] total_entries The number of LOCALGROUP_MEMBERS_INFO_X entries in
+ * the buffer
+ * @return NET_API_STATUS
+ *
+ * example localgroup/localgroup_setmembers.c
+ ***************************************************************/
+
+NET_API_STATUS NetLocalGroupSetMembers(const char * server_name /* [in] */,
+ const char * group_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t total_entries /* [in] */);
+
+/************************************************************//**
+ *
+ * NetRemoteTOD
+ *
+ * @brief Query remote Time of Day
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[out] buf The buffer containing a TIME_OF_DAY_INFO structure
+ * @return NET_API_STATUS
+ *
+ * example server/remote_tod.c
+ ***************************************************************/
+
+NET_API_STATUS NetRemoteTOD(const char * server_name /* [in] */,
+ uint8_t **buf /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareAdd
+ *
+ * @brief Add Share
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining the requested SHARE_INFO_X structure
+ * @param[in] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example share/share_add.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareAdd(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareDel
+ *
+ * @brief Delete Share
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to delete
+ * @param[in] reserved
+ * @return NET_API_STATUS
+ *
+ * example share/share_del.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareDel(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t reserved /* [in] */);
+
+/************************************************************//**
+ *
+ * NetShareEnum
+ *
+ * @brief Enumerate Shares
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[out] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of SHARE_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of SHARE_INFO_X entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example share/share_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareEnum(const char * server_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareGetInfo
+ *
+ * @brief Get Share Info
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to query
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[out] buffer The buffer containing a SHARE_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example share/share_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareGetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetShareSetInfo
+ *
+ * @brief Set Share Info
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] net_name The name of the share to query
+ * @param[in] level The level defining the SHARE_INFO_X structure
+ * @param[in] buffer The buffer containing a SHARE_INFO_X structure
+ * @param[out] parm_err The returned parameter error number if any
+ * @return NET_API_STATUS
+ *
+ * example share/share_setinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetShareSetInfo(const char * server_name /* [in] */,
+ const char * net_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t *buffer /* [in] [ref] */,
+ uint32_t *parm_err /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetFileClose
+ *
+ * @brief Close a file
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] fileid The fileid of the file that is going to be closed
+ * @return NET_API_STATUS
+ *
+ * example file/file_close.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileClose(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */);
+
+/************************************************************//**
+ *
+ * NetFileGetInfo
+ *
+ * @brief Close a file
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] fileid The fileid of the file that is going to be closed
+ * @param[in] level The level of the FILE_INFO_X buffer
+ * @param[out] buffer The buffer containing a FILE_INFO_X structure
+ * @return NET_API_STATUS
+ *
+ * example file/file_getinfo.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileGetInfo(const char * server_name /* [in] */,
+ uint32_t fileid /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */);
+
+/************************************************************//**
+ *
+ * NetFileEnum
+ *
+ * @brief Enumerate Files
+ *
+ * @param[in] server_name The server name to connect to
+ * @param[in] base_path The
+ * @param[in] user_name The
+ * @param[in] level The level defining the FILE_INFO_X structure
+ * @param[out] buffer The buffer containing a FILE_INFO_X structure
+ * @param[in] prefmaxlen The requested maximal buffer size
+ * @param[out] entries_read The number of FILE_INFO_X entries in the buffer
+ * @param[out] total_entries The total number of FILE_INFO_X entries
+ * @param[in,out] resume_handle A handle passed in and returned for resuming
+ * operations
+ * @return NET_API_STATUS
+ *
+ * example file/file_enum.c
+ ***************************************************************/
+
+NET_API_STATUS NetFileEnum(const char * server_name /* [in] */,
+ const char * base_path /* [in] */,
+ const char * user_name /* [in] */,
+ uint32_t level /* [in] */,
+ uint8_t **buffer /* [out] [ref] */,
+ uint32_t prefmaxlen /* [in] */,
+ uint32_t *entries_read /* [out] [ref] */,
+ uint32_t *total_entries /* [out] [ref] */,
+ uint32_t *resume_handle /* [in,out] [ref] */);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/source/lib/netapi/netapi_private.h b/source/lib/netapi/netapi_private.h
index a575f42f4e..e6a2eb8e99 100644
--- a/source/lib/netapi/netapi_private.h
+++ b/source/lib/netapi/netapi_private.h
@@ -20,17 +20,68 @@
#ifndef __LIB_NETAPI_PRIVATE_H__
#define __LIB_NETAPI_PRIVATE_H__
+#define LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, fn) \
+ DEBUG(10,("redirecting call %s to localhost\n", #fn)); \
+ if (!r->in.server_name) { \
+ r->in.server_name = "localhost"; \
+ } \
+ return fn ## _r(ctx, r);
+
+struct libnetapi_private_ctx {
+ struct {
+ const char *domain_name;
+ struct dom_sid *domain_sid;
+ struct rpc_pipe_client *cli;
+
+ uint32_t connect_mask;
+ struct policy_handle connect_handle;
+
+ uint32_t domain_mask;
+ struct policy_handle domain_handle;
+
+ uint32_t builtin_mask;
+ struct policy_handle builtin_handle;
+ } samr;
+
+};
+
NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx, char **password);
NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx, char **username);
NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx, const char *format, ...);
NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, char **debuglevel);
-WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
- const char *server_name,
- struct cli_state **cli);
WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx);
WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
- struct cli_state *cli,
- int pipe_idx,
- struct rpc_pipe_client **pipe_cli);
+ const char *server_name,
+ const struct ndr_syntax_id *interface,
+ struct cli_state **pcli,
+ struct rpc_pipe_client **presult);
+WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t domain_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *domain_handle,
+ struct dom_sid2 **domain_sid);
+WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t builtin_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *builtin_handle);
+void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle);
+void libnetapi_samr_free(struct libnetapi_ctx *ctx);
+
+NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint32_t attributes,
+ uint8_t **buffer,
+ uint32_t *num_entries);
+
#endif
diff --git a/source/lib/netapi/samr.c b/source/lib/netapi/samr.c
new file mode 100644
index 0000000000..dbcef38dc7
--- /dev/null
+++ b/source/lib/netapi/samr.c
@@ -0,0 +1,319 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Samr Support
+ * 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 "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+
+/****************************************************************
+****************************************************************/
+
+WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t domain_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *domain_handle,
+ struct dom_sid2 **domain_sid)
+{
+ NTSTATUS status;
+ WERROR werr;
+ struct libnetapi_private_ctx *priv;
+ uint32_t resume_handle = 0;
+ uint32_t num_entries = 0;
+ struct samr_SamArray *sam = NULL;
+ const char *domain_name = NULL;
+ struct lsa_String lsa_domain_name;
+ bool domain_found = true;
+ int i;
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
+ if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
+ *connect_handle = priv->samr.connect_handle;
+ } else {
+ libnetapi_samr_close_connect_handle(mem_ctx,
+ &priv->samr.connect_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.domain_handle)) {
+ if ((priv->samr.domain_mask & domain_mask) == domain_mask) {
+ *domain_handle = priv->samr.domain_handle;
+ } else {
+ libnetapi_samr_close_domain_handle(mem_ctx,
+ &priv->samr.domain_handle);
+ }
+ }
+
+ if (priv->samr.domain_sid) {
+ *domain_sid = priv->samr.domain_sid;
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
+ ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
+ is_valid_policy_hnd(&priv->samr.domain_handle) &&
+ (priv->samr.domain_mask & domain_mask) == domain_mask) {
+ return WERR_OK;
+ }
+
+ if (!is_valid_policy_hnd(connect_handle)) {
+ status = rpccli_try_samr_connects(pipe_cli, mem_ctx,
+ connect_mask,
+ connect_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_EnumDomains(pipe_cli, mem_ctx,
+ connect_handle,
+ &resume_handle,
+ &sam,
+ 0xffffffff,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i<num_entries; i++) {
+
+ domain_name = sam->entries[i].name.string;
+
+ if (strequal(domain_name, builtin_domain_name())) {
+ continue;
+ }
+
+ domain_found = true;
+ break;
+ }
+
+ if (!domain_found) {
+ werr = WERR_NO_SUCH_DOMAIN;
+ goto done;
+ }
+
+ init_lsa_String(&lsa_domain_name, domain_name);
+
+ status = rpccli_samr_LookupDomain(pipe_cli, mem_ctx,
+ connect_handle,
+ &lsa_domain_name,
+ domain_sid);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenDomain(pipe_cli, mem_ctx,
+ connect_handle,
+ domain_mask,
+ *domain_sid,
+ domain_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ priv->samr.cli = pipe_cli;
+
+ priv->samr.domain_name = domain_name;
+ priv->samr.domain_sid = *domain_sid;
+
+ priv->samr.connect_mask = connect_mask;
+ priv->samr.connect_handle = *connect_handle;
+
+ priv->samr.domain_mask = domain_mask;
+ priv->samr.domain_handle = *domain_handle;
+
+ werr = WERR_OK;
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t connect_mask,
+ uint32_t builtin_mask,
+ struct policy_handle *connect_handle,
+ struct policy_handle *builtin_handle)
+{
+ NTSTATUS status;
+ WERROR werr;
+ struct libnetapi_private_ctx *priv;
+
+ priv = talloc_get_type_abort(mem_ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
+ if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
+ *connect_handle = priv->samr.connect_handle;
+ } else {
+ libnetapi_samr_close_connect_handle(mem_ctx,
+ &priv->samr.connect_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.builtin_handle)) {
+ if ((priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
+ *builtin_handle = priv->samr.builtin_handle;
+ } else {
+ libnetapi_samr_close_builtin_handle(mem_ctx,
+ &priv->samr.builtin_handle);
+ }
+ }
+
+ if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
+ ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
+ is_valid_policy_hnd(&priv->samr.builtin_handle) &&
+ (priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
+ return WERR_OK;
+ }
+
+ if (!is_valid_policy_hnd(connect_handle)) {
+ status = rpccli_try_samr_connects(pipe_cli, mem_ctx,
+ connect_mask,
+ connect_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_OpenDomain(pipe_cli, mem_ctx,
+ connect_handle,
+ builtin_mask,
+ CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
+ builtin_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ priv->samr.cli = pipe_cli;
+
+ priv->samr.connect_mask = connect_mask;
+ priv->samr.connect_handle = *connect_handle;
+
+ priv->samr.builtin_mask = builtin_mask;
+ priv->samr.builtin_handle = *builtin_handle;
+
+ werr = WERR_OK;
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!policy_hnd_equal(handle, &priv->samr.domain_handle)) {
+ return;
+ }
+
+ rpccli_samr_Close(priv->samr.cli, ctx, handle);
+
+ ZERO_STRUCT(priv->samr.domain_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!policy_hnd_equal(handle, &priv->samr.builtin_handle)) {
+ return;
+ }
+
+ rpccli_samr_Close(priv->samr.cli, ctx, handle);
+
+ ZERO_STRUCT(priv->samr.builtin_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx,
+ struct policy_handle *handle)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!is_valid_policy_hnd(handle)) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ if (!policy_hnd_equal(handle, &priv->samr.connect_handle)) {
+ return;
+ }
+
+ rpccli_samr_Close(priv->samr.cli, ctx, handle);
+
+ ZERO_STRUCT(priv->samr.connect_handle);
+}
+
+/****************************************************************
+****************************************************************/
+
+void libnetapi_samr_free(struct libnetapi_ctx *ctx)
+{
+ struct libnetapi_private_ctx *priv;
+
+ if (!ctx->private_data) {
+ return;
+ }
+
+ priv = talloc_get_type_abort(ctx->private_data,
+ struct libnetapi_private_ctx);
+
+ libnetapi_samr_close_domain_handle(ctx, &priv->samr.domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &priv->samr.builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &priv->samr.connect_handle);
+}
diff --git a/source/lib/netapi/serverinfo.c b/source/lib/netapi/serverinfo.c
index dd7a8808b4..b2a134b0af 100644
--- a/source/lib/netapi/serverinfo.c
+++ b/source/lib/netapi/serverinfo.c
@@ -28,6 +28,29 @@
/****************************************************************
****************************************************************/
+static WERROR NetServerGetInfo_l_101(struct libnetapi_ctx *ctx,
+ uint8_t **buffer)
+{
+ struct SERVER_INFO_101 i;
+
+ i.sv101_platform_id = PLATFORM_ID_NT;
+ i.sv101_name = global_myname();
+ i.sv101_version_major = lp_major_announce_version();
+ i.sv101_version_minor = lp_minor_announce_version();
+ i.sv101_type = lp_default_server_announce();
+ i.sv101_comment = lp_serverstring();
+
+ *buffer = (uint8_t *)talloc_memdup(ctx, &i, sizeof(i));
+ if (!*buffer) {
+ return WERR_NOMEM;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
static WERROR NetServerGetInfo_l_1005(struct libnetapi_ctx *ctx,
uint8_t **buffer)
{
@@ -49,6 +72,8 @@ WERROR NetServerGetInfo_l(struct libnetapi_ctx *ctx,
struct NetServerGetInfo *r)
{
switch (r->in.level) {
+ case 101:
+ return NetServerGetInfo_l_101(ctx, r->out.buffer);
case 1005:
return NetServerGetInfo_l_1005(ctx, r->out.buffer);
default:
@@ -61,6 +86,78 @@ WERROR NetServerGetInfo_l(struct libnetapi_ctx *ctx,
/****************************************************************
****************************************************************/
+static NTSTATUS map_server_info_to_SERVER_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetSrvInfo *i,
+ uint8_t **buffer)
+{
+ struct SERVER_INFO_100 i100;
+ struct SERVER_INFO_101 i101;
+ struct SERVER_INFO_102 i102;
+ struct SERVER_INFO_1005 i1005;
+
+ uint32_t num_info = 0;
+
+ switch (level) {
+ case 100:
+ i100.sv100_platform_id = i->info100->platform_id;
+ i100.sv100_name = talloc_strdup(mem_ctx, i->info100->server_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_100, i100,
+ (struct SERVER_INFO_100 **)buffer,
+ &num_info);
+ break;
+
+ case 101:
+ i101.sv101_platform_id = i->info101->platform_id;
+ i101.sv101_name = talloc_strdup(mem_ctx, i->info101->server_name);
+ i101.sv101_version_major = i->info101->version_major;
+ i101.sv101_version_minor = i->info101->version_minor;
+ i101.sv101_type = i->info101->server_type;
+ i101.sv101_comment = talloc_strdup(mem_ctx, i->info101->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_101, i101,
+ (struct SERVER_INFO_101 **)buffer,
+ &num_info);
+ break;
+
+ case 102:
+ i102.sv102_platform_id = i->info102->platform_id;
+ i102.sv102_name = talloc_strdup(mem_ctx, i->info102->server_name);
+ i102.sv102_version_major = i->info102->version_major;
+ i102.sv102_version_minor = i->info102->version_minor;
+ i102.sv102_type = i->info102->server_type;
+ i102.sv102_comment = talloc_strdup(mem_ctx, i->info102->comment);
+ i102.sv102_users = i->info102->users;
+ i102.sv102_disc = i->info102->disc;
+ i102.sv102_hidden = i->info102->hidden;
+ i102.sv102_announce = i->info102->announce;
+ i102.sv102_anndelta = i->info102->anndelta;
+ i102.sv102_licenses = i->info102->licenses;
+ i102.sv102_userpath = talloc_strdup(mem_ctx, i->info102->userpath);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_102, i102,
+ (struct SERVER_INFO_102 **)buffer,
+ &num_info);
+ break;
+
+ case 1005:
+ i1005.sv1005_comment = talloc_strdup(mem_ctx, i->info1005->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SERVER_INFO_1005, i1005,
+ (struct SERVER_INFO_1005 **)buffer,
+ &num_info);
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx,
struct NetServerGetInfo *r)
{
@@ -70,12 +167,24 @@ WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx,
WERROR werr;
union srvsvc_NetSrvInfo info;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 100:
+ case 101:
+ case 102:
+ case 1005:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
}
- werr = libnetapi_open_pipe(ctx, cli, PI_SRVSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -90,9 +199,10 @@ WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx,
goto done;
}
- *r->out.buffer = (uint8_t *)talloc_memdup(ctx, &info, sizeof(info));
- if (!*r->out.buffer) {
- werr = WERR_NOMEM;
+ status = map_server_info_to_SERVER_INFO_buffer(ctx, r->in.level, &info,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
goto done;
}
@@ -170,12 +280,10 @@ WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx,
WERROR werr;
union srvsvc_NetSrvInfo info;
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = libnetapi_open_pipe(ctx, cli, PI_SRVSVC, &pipe_cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -203,3 +311,50 @@ WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx,
done:
return werr;
}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ struct srvsvc_NetRemoteTODInfo *info = NULL;
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetRemoteTOD(pipe_cli, ctx,
+ r->in.server_name,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ *r->out.buffer = (uint8_t *)talloc_memdup(ctx, info,
+ sizeof(struct srvsvc_NetRemoteTODInfo));
+ W_ERROR_HAVE_NO_MEMORY(*r->out.buffer);
+
+ done:
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetRemoteTOD_l(struct libnetapi_ctx *ctx,
+ struct NetRemoteTOD *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRemoteTOD);
+}
+
diff --git a/source/lib/netapi/share.c b/source/lib/netapi/share.c
new file mode 100644
index 0000000000..1d0e1810f1
--- /dev/null
+++ b/source/lib/netapi/share.c
@@ -0,0 +1,555 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Share Support
+ * 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 "librpc/gen_ndr/libnetapi.h"
+#include "lib/netapi/netapi.h"
+#include "lib/netapi/netapi_private.h"
+#include "lib/netapi/libnetapi.h"
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_srvsvc_share_info_to_SHARE_INFO_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union srvsvc_NetShareInfo *info,
+ uint8_t **buffer,
+ uint32_t *num_shares)
+{
+ struct SHARE_INFO_0 i0;
+ struct SHARE_INFO_1 i1;
+ struct SHARE_INFO_2 i2;
+ struct SHARE_INFO_501 i501;
+ struct SHARE_INFO_1005 i1005;
+
+ struct srvsvc_NetShareInfo0 *s0;
+ struct srvsvc_NetShareInfo1 *s1;
+ struct srvsvc_NetShareInfo2 *s2;
+ struct srvsvc_NetShareInfo501 *s501;
+ struct srvsvc_NetShareInfo1005 *s1005;
+
+ if (!buffer) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 0:
+ s0 = info->info0;
+
+ i0.shi0_netname = talloc_strdup(mem_ctx, s0->name);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_0, i0,
+ (struct SHARE_INFO_0 **)buffer,
+ num_shares);
+ break;
+
+ case 1:
+ s1 = info->info1;
+
+ i1.shi1_netname = talloc_strdup(mem_ctx, s1->name);
+ i1.shi1_type = s1->type;
+ i1.shi1_remark = talloc_strdup(mem_ctx, s1->comment);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1, i1,
+ (struct SHARE_INFO_1 **)buffer,
+ num_shares);
+ break;
+
+ case 2:
+ s2 = info->info2;
+
+ i2.shi2_netname = talloc_strdup(mem_ctx, s2->name);
+ i2.shi2_type = s2->type;
+ i2.shi2_remark = talloc_strdup(mem_ctx, s2->comment);
+ i2.shi2_permissions = s2->permissions;
+ i2.shi2_max_uses = s2->max_users;
+ i2.shi2_current_uses = s2->current_users;
+ i2.shi2_path = talloc_strdup(mem_ctx, s2->path);
+ i2.shi2_passwd = talloc_strdup(mem_ctx, s2->password);
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_2, i2,
+ (struct SHARE_INFO_2 **)buffer,
+ num_shares);
+ break;
+
+ case 501:
+ s501 = info->info501;
+
+ i501.shi501_netname = talloc_strdup(mem_ctx, s501->name);
+ i501.shi501_type = s501->type;
+ i501.shi501_remark = talloc_strdup(mem_ctx, s501->comment);
+ i501.shi501_flags = s501->csc_policy;
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_501, i501,
+ (struct SHARE_INFO_501 **)buffer,
+ num_shares);
+ break;
+
+ case 1005:
+ s1005 = info->info1005;
+
+ i1005.shi1005_flags = s1005->dfs_flags;
+
+ ADD_TO_ARRAY(mem_ctx, struct SHARE_INFO_1005, i1005,
+ (struct SHARE_INFO_1005 **)buffer,
+ num_shares);
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS map_SHARE_INFO_buffer_to_srvsvc_share_info(TALLOC_CTX *mem_ctx,
+ uint8_t *buffer,
+ uint32_t level,
+ union srvsvc_NetShareInfo *info)
+{
+ struct SHARE_INFO_2 *i2 = NULL;
+ struct SHARE_INFO_1004 *i1004 = NULL;
+ struct srvsvc_NetShareInfo2 *s2 = NULL;
+ struct srvsvc_NetShareInfo1004 *s1004 = NULL;
+
+ if (!buffer) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (level) {
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+
+ s2 = TALLOC_P(mem_ctx, struct srvsvc_NetShareInfo2);
+ NT_STATUS_HAVE_NO_MEMORY(s2);
+
+ s2->name = i2->shi2_netname;
+ s2->type = i2->shi2_type;
+ s2->comment = i2->shi2_remark;
+ s2->permissions = i2->shi2_permissions;
+ s2->max_users = i2->shi2_max_uses;
+ s2->current_users = i2->shi2_current_uses;
+ s2->path = i2->shi2_path;
+ s2->password = i2->shi2_passwd;
+
+ info->info2 = s2;
+
+ break;
+ case 1004:
+ i1004 = (struct SHARE_INFO_1004 *)buffer;
+
+ s1004 = TALLOC_P(mem_ctx, struct srvsvc_NetShareInfo1004);
+ NT_STATUS_HAVE_NO_MEMORY(s1004);
+
+ s1004->comment = i1004->shi1004_remark;
+
+ info->info1004 = s1004;
+
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_r(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ union srvsvc_NetShareInfo info;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ break;
+ case 502:
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
+ r->in.buffer,
+ r->in.level,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetShareAdd(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.level,
+ &info,
+ r->out.parm_err,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareAdd_l(struct libnetapi_ctx *ctx,
+ struct NetShareAdd *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareAdd);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareDel_r(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+
+ if (!r->in.net_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetShareDel(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.net_name,
+ r->in.reserved,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareDel_l(struct libnetapi_ctx *ctx,
+ struct NetShareDel *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareEnum_r(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct srvsvc_NetShareInfoCtr info_ctr;
+ struct srvsvc_NetShareCtr0 ctr0;
+ struct srvsvc_NetShareCtr1 ctr1;
+ struct srvsvc_NetShareCtr2 ctr2;
+ uint32_t i;
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ break;
+ case 502:
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ ZERO_STRUCT(info_ctr);
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ info_ctr.level = r->in.level;
+ switch (r->in.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;
+ }
+
+ status = rpccli_srvsvc_NetShareEnumAll(pipe_cli, ctx,
+ r->in.server_name,
+ &info_ctr,
+ r->in.prefmaxlen,
+ r->out.total_entries,
+ r->out.resume_handle,
+ &werr);
+ if (NT_STATUS_IS_ERR(status)) {
+ goto done;
+ }
+
+ for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
+ union srvsvc_NetShareInfo _i;
+ switch (r->in.level) {
+ case 0:
+ _i.info0 = &info_ctr.ctr.ctr0->array[i];
+ break;
+ case 1:
+ _i.info1 = &info_ctr.ctr.ctr1->array[i];
+ break;
+ case 2:
+ _i.info2 = &info_ctr.ctr.ctr2->array[i];
+ break;
+ }
+
+ status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
+ r->in.level,
+ &_i,
+ r->out.buffer,
+ r->out.entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ }
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareEnum_l(struct libnetapi_ctx *ctx,
+ struct NetShareEnum *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ union srvsvc_NetShareInfo info;
+ uint32_t num_entries = 0;
+
+ if (!r->in.net_name || !r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ case 2:
+ case 501:
+ case 1005:
+ break;
+ case 502:
+ case 503:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetShareGetInfo(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.net_name,
+ r->in.level,
+ &info,
+ &werr);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_srvsvc_share_info_to_SHARE_INFO_buffer(ctx,
+ r->in.level,
+ &info,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r)
+{
+ WERROR werr;
+ NTSTATUS status;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ union srvsvc_NetShareInfo info;
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 2:
+ case 1004:
+ break;
+ case 1:
+ case 502:
+ case 503:
+ case 1005:
+ case 1006:
+ case 1501:
+ return WERR_NOT_SUPPORTED;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_srvsvc.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = map_SHARE_INFO_buffer_to_srvsvc_share_info(ctx,
+ r->in.buffer,
+ r->in.level,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetShareSetInfo(pipe_cli, ctx,
+ r->in.server_name,
+ r->in.net_name,
+ r->in.level,
+ &info,
+ r->out.parm_err,
+ &werr);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetShareSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetShareSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetShareSetInfo);
+}
diff --git a/source/lib/netapi/sid.c b/source/lib/netapi/sid.c
new file mode 100644
index 0000000000..a9bca2689f
--- /dev/null
+++ b/source/lib/netapi/sid.c
@@ -0,0 +1,76 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * 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 "lib/netapi/netapi.h"
+
+/****************************************************************
+****************************************************************/
+
+int ConvertSidToStringSid(const struct domsid *sid,
+ char **sid_string)
+{
+ char *ret;
+
+ if (!sid || !sid_string) {
+ return false;
+ }
+
+ ret = sid_string_talloc(NULL, (const struct dom_sid *)sid);
+ if (!ret) {
+ return false;
+ }
+
+ *sid_string = SMB_STRDUP(ret);
+
+ TALLOC_FREE(ret);
+
+ if (!*sid_string) {
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************
+****************************************************************/
+
+int ConvertStringSidToSid(const char *sid_string,
+ struct domsid **sid)
+{
+ struct dom_sid _sid;
+
+ if (!sid_string || !sid) {
+ return false;
+ }
+
+ if (!string_to_sid(&_sid, sid_string)) {
+ return false;
+ }
+
+ *sid = (struct domsid *)SMB_MALLOC(sizeof(struct domsid));
+ if (!*sid) {
+ return false;
+ }
+
+ sid_copy((struct dom_sid*)*sid, &_sid);
+
+ return true;
+}
diff --git a/source/lib/netapi/tests/Makefile.in b/source/lib/netapi/tests/Makefile.in
new file mode 100644
index 0000000000..d3f0663908
--- /dev/null
+++ b/source/lib/netapi/tests/Makefile.in
@@ -0,0 +1,57 @@
+KRB5LIBS=@KRB5_LIBS@
+LDAP_LIBS=@LDAP_LIBS@
+LIBS=@LIBS@ -lnetapi -ltdb -ltalloc
+DEVELOPER_CFLAGS=@DEVELOPER_CFLAGS@
+FLAGS=-I../ -L../../../bin @CFLAGS@ $(GTK_FLAGS)
+CC=@CC@
+PICFLAG=@PICFLAG@
+LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@
+DYNEXP=@DYNEXP@
+NETAPI_LIBS=$(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+CMDLINE_LIBS=$(NETAPI_LIBS) @POPTLIBS@
+
+# Compile a source file.
+COMPILE_CC = $(CC) -I. $(FLAGS) $(PICFLAG) -c $< -o $@
+COMPILE = $(COMPILE_CC)
+
+PROGS = bin/netapitest@EXEEXT@
+
+all: $(PROGS)
+
+MAKEDIR = || exec false; \
+ if test -d "$$dir"; then :; else \
+ echo mkdir "$$dir"; \
+ mkdir -p "$$dir" >/dev/null 2>&1 || \
+ test -d "$$dir" || \
+ mkdir "$$dir" || \
+ exec false; fi || exec false
+
+BINARY_PREREQS = bin/.dummy
+
+bin/.dummy:
+ @if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \
+ dir=bin $(MAKEDIR); fi
+ @: >> $@ || : > $@ # what a fancy emoticon!
+
+.c.o:
+ @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
+ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
+ @echo Compiling $*.c
+ @$(COMPILE) && exit 0;\
+ echo "The following command failed:" 1>&2;\
+ echo "$(COMPILE_CC)" 1>&2;\
+ $(COMPILE_CC) >/dev/null 2>&1
+
+CMDLINE_OBJ = common.o
+NETAPIBUFFER_OBJ = netapibuffer.o
+NETAPITEST_OBJ = netapitest.o netlocalgroup.o netuser.o netgroup.o netdisplay.o netshare.o $(CMDLINE_OBJ)
+
+bin/netapitest@EXEEXT@: $(BINARY_PREREQS) $(NETAPITEST_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(NETAPITEST_OBJ) $(LDFLAGS) $(DYNEXP) $(CMDLINE_LIBS)
+
+clean:
+ -rm -f $(PROGS)
+ -rm -f core */*~ *~ \
+ */*.o */*/*.o */*/*/*.o
+
diff --git a/source/lib/netapi/tests/common.c b/source/lib/netapi/tests/common.c
new file mode 100644
index 0000000000..22175afb48
--- /dev/null
+++ b/source/lib/netapi/tests/common.c
@@ -0,0 +1,86 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * 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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <popt.h>
+#include <netapi.h>
+
+#include "common.h"
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data)
+{
+ struct libnetapi_ctx *ctx = NULL;
+
+ libnetapi_getctx(&ctx);
+
+ if (reason == POPT_CALLBACK_REASON_PRE) {
+ }
+
+ if (reason == POPT_CALLBACK_REASON_POST) {
+ }
+
+ if (!opt) {
+ return;
+ }
+ switch (opt->val) {
+ case 'U': {
+ char *puser = strdup(arg);
+ char *p = NULL;
+
+ if ((p = strchr(puser,'%'))) {
+ size_t len;
+ *p = 0;
+ libnetapi_set_username(ctx, puser);
+ libnetapi_set_password(ctx, p+1);
+ len = strlen(p+1);
+ memset(strchr(arg,'%')+1,'X',len);
+ } else {
+ libnetapi_set_username(ctx, puser);
+ }
+ free(puser);
+ break;
+ }
+ case 'd':
+ libnetapi_set_debuglevel(ctx, arg);
+ break;
+ case 'p':
+ libnetapi_set_password(ctx, arg);
+ break;
+ case 'k':
+ libnetapi_set_use_kerberos(ctx);
+ break;
+ }
+}
+
+struct poptOption popt_common_netapi_examples[] = {
+ { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, (void *)popt_common_callback },
+ { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Username used for connection", "USERNAME" },
+ { "password", 'p', POPT_ARG_STRING, NULL, 'p', "Password used for connection", "PASSWORD" },
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Debuglevel", "DEBUGLEVEL" },
+ { "kerberos", 'k', POPT_ARG_NONE, NULL, 'k', "Use Kerberos", NULL },
+ POPT_TABLEEND
+};
+
diff --git a/source/lib/netapi/tests/common.h b/source/lib/netapi/tests/common.h
new file mode 100644
index 0000000000..5a320321ba
--- /dev/null
+++ b/source/lib/netapi/tests/common.h
@@ -0,0 +1,57 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * 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 <popt.h>
+
+void popt_common_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg, const void *data);
+
+extern struct poptOption popt_common_netapi_examples[];
+
+#define POPT_COMMON_LIBNETAPI_EXAMPLES { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netapi_examples, 0, "Common samba netapi example options:", NULL },
+
+NET_API_STATUS test_netuseradd(const char *hostname,
+ const char *username);
+
+NET_API_STATUS netapitest_localgroup(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_user(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_group(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx,
+ const char *hostname);
+NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx,
+ const char *hostname);
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+#define NETAPI_STATUS(x,y,fn) \
+ printf("FAILURE: line %d: %s failed with status: %s (%d)\n", \
+ __LINE__, fn, libnetapi_get_error_string(x,y), y);
+
+#define NETAPI_STATUS_MSG(x,y,fn,z) \
+ printf("FAILURE: line %d: %s failed with status: %s (%d), %s\n", \
+ __LINE__, fn, libnetapi_get_error_string(x,y), y, z);
+
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
diff --git a/source/lib/netapi/tests/netapitest.c b/source/lib/netapi/tests/netapitest.c
new file mode 100644
index 0000000000..87144020f5
--- /dev/null
+++ b/source/lib/netapi/tests/netapitest.c
@@ -0,0 +1,97 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+int main(int argc, const char **argv)
+{
+ NET_API_STATUS status = 0;
+ struct libnetapi_ctx *ctx = NULL;
+ const char *hostname = NULL;
+
+ poptContext pc;
+ int opt;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_LIBNETAPI_EXAMPLES
+ POPT_TABLEEND
+ };
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ pc = poptGetContext("netapitest", argc, argv, long_options, 0);
+
+ poptSetOtherOptionHelp(pc, "hostname");
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ }
+
+ if (!poptPeekArg(pc)) {
+ poptPrintHelp(pc, stderr, 0);
+ goto out;
+ }
+ hostname = poptGetArg(pc);
+
+ status = netapitest_localgroup(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_user(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_group(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_display(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = netapitest_share(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ out:
+ if (status != 0) {
+ printf("testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ libnetapi_free(ctx);
+ poptFreeContext(pc);
+
+ return status;
+}
diff --git a/source/lib/netapi/tests/netdisplay.c b/source/lib/netapi/tests/netdisplay.c
new file mode 100644
index 0000000000..090792cec2
--- /dev/null
+++ b/source/lib/netapi/tests/netdisplay.c
@@ -0,0 +1,150 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroup testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netquerydisplayinformation(const char *hostname,
+ uint32_t level,
+ const char *name)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ int found_name = 0;
+ const char *current_name;
+ uint8_t *buffer = NULL;
+ uint32_t idx = 0;
+ int i;
+
+ struct NET_DISPLAY_USER *user;
+ struct NET_DISPLAY_GROUP *group;
+ struct NET_DISPLAY_MACHINE *machine;
+
+ printf("testing NetQueryDisplayInformation level %d\n", level);
+
+ do {
+ status = NetQueryDisplayInformation(hostname,
+ level,
+ idx,
+ 1000,
+ (uint32_t)-1,
+ &entries_read,
+ (void **)&buffer);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 1:
+ user = (struct NET_DISPLAY_USER *)buffer;
+ break;
+ case 2:
+ machine = (struct NET_DISPLAY_MACHINE *)buffer;
+ break;
+ case 3:
+ group = (struct NET_DISPLAY_GROUP *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 1:
+ current_name = user->usri1_name;
+ break;
+ case 2:
+ current_name = machine->usri2_name;
+ break;
+ case 3:
+ current_name = group->grpi3_name;
+ break;
+ default:
+ break;
+ }
+
+ if (name && strcasecmp(current_name, name) == 0) {
+ found_name = 1;
+ }
+
+ switch (level) {
+ case 1:
+ user++;
+ break;
+ case 2:
+ machine++;
+ break;
+ case 3:
+ group++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ idx += entries_read;
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (name && !found_name) {
+ printf("failed to get name\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ uint32_t levels[] = { 1, 2, 3};
+ int i;
+
+ printf("NetDisplay tests\n");
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ status = test_netquerydisplayinformation(hostname, levels[i], NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetQueryDisplayInformation");
+ goto out;
+ }
+ }
+
+ status = 0;
+
+ printf("NetDisplay tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetDisplay testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source/lib/netapi/tests/netgroup.c b/source/lib/netapi/tests/netgroup.c
new file mode 100644
index 0000000000..a89a772ce4
--- /dev/null
+++ b/source/lib/netapi/tests/netgroup.c
@@ -0,0 +1,286 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetGroup testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netgroupenum(const char *hostname,
+ uint32_t level,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_group = 0;
+ const char *current_name;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct GROUP_INFO_0 *info0;
+ struct GROUP_INFO_1 *info1;
+ struct GROUP_INFO_2 *info2;
+ struct GROUP_INFO_3 *info3;
+
+ printf("testing NetGroupEnum level %d\n", level);
+
+ do {
+ status = NetGroupEnum(hostname,
+ level,
+ &buffer,
+ 120, //(uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct GROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct GROUP_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct GROUP_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct GROUP_INFO_3 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->grpi0_name;
+ break;
+ case 1:
+ current_name = info1->grpi1_name;
+ break;
+ case 2:
+ current_name = info2->grpi2_name;
+ break;
+ case 3:
+ current_name = info3->grpi3_name;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ case 2:
+ info2++;
+ break;
+ case 3:
+ info3++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_group) {
+ printf("failed to get group\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_group(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *username, *groupname, *groupname2;
+ uint8_t *buffer = NULL;
+ struct GROUP_INFO_0 g0;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 3};
+ uint32_t enum_levels[] = { 0, 1, 2, 3};
+ int i;
+
+ printf("NetGroup tests\n");
+
+ username = "torture_test_user";
+ groupname = "torture_test_group";
+ groupname2 = "torture_test_group2";
+
+ /* cleanup */
+ NetGroupDel(hostname, groupname);
+ NetGroupDel(hostname, groupname2);
+ NetUserDel(hostname, username);
+
+ /* add a group */
+
+ g0.grpi0_name = groupname;
+
+ printf("testing NetGroupAdd\n");
+
+ status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupAdd");
+ goto out;
+ }
+
+ /* 2nd add must fail */
+
+ status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetGroupAdd");
+ goto out;
+ }
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netgroupenum(hostname, enum_levels[i], groupname);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetGroupGetInfo level %d\n", levels[i]);
+
+ status = NetGroupGetInfo(hostname, groupname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetInfo");
+ goto out;
+ }
+ }
+
+ /* group rename */
+
+ g0.grpi0_name = groupname2;
+
+ printf("testing NetGroupSetInfo level 0\n");
+
+ status = NetGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupSetInfo");
+ goto out;
+ }
+
+ /* should not exist anymore */
+
+ status = NetGroupDel(hostname, groupname);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetGroupDel");
+ goto out;
+ }
+
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ status = NetGroupGetInfo(hostname, groupname2, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetGroupGetInfo");
+ goto out;
+ }
+ }
+
+ /* add user to group */
+
+ status = test_netuseradd(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserAdd");
+ goto out;
+ }
+
+ printf("testing NetGroupAddUser\n");
+
+ status = NetGroupAddUser(hostname, groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupAddUser");
+ goto out;
+ }
+
+ printf("testing NetGroupDelUser\n");
+
+ status = NetGroupDelUser(hostname, groupname2, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupDelUser");
+ goto out;
+ }
+
+ status = NetUserDel(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserDel");
+ goto out;
+ }
+
+ /* delete */
+
+ printf("testing NetGroupDel\n");
+
+ status = NetGroupDel(hostname, groupname2);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetGroupDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetGroupGetInfo(hostname, groupname2, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS_MSG(ctx, status, "NetGroupGetInfo", "expected failure and error code");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetGroup tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetGroup testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source/lib/netapi/tests/netlocalgroup.c b/source/lib/netapi/tests/netlocalgroup.c
new file mode 100644
index 0000000000..0d82059356
--- /dev/null
+++ b/source/lib/netapi/tests/netlocalgroup.c
@@ -0,0 +1,226 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetLocalGroup testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netlocalgroupenum(const char *hostname,
+ uint32_t level,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_group = 0;
+ const char *current_name;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct LOCALGROUP_INFO_0 *info0;
+ struct LOCALGROUP_INFO_1 *info1;
+
+ printf("testing NetLocalGroupEnum level %d\n", level);
+
+ do {
+ status = NetLocalGroupEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct LOCALGROUP_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct LOCALGROUP_INFO_1 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->lgrpi0_name;
+ break;
+ case 1:
+ current_name = info1->lgrpi1_name;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_group) {
+ printf("failed to get group\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_localgroup(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *groupname, *groupname2;
+ uint8_t *buffer = NULL;
+ struct LOCALGROUP_INFO_0 g0;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 1002 };
+ uint32_t enum_levels[] = { 0, 1 };
+ int i;
+
+ printf("NetLocalgroup tests\n");
+
+ groupname = "torture_test_localgroup";
+ groupname2 = "torture_test_localgroup2";
+
+ /* cleanup */
+ NetLocalGroupDel(hostname, groupname);
+ NetLocalGroupDel(hostname, groupname2);
+
+ /* add a localgroup */
+
+ printf("testing NetLocalGroupAdd\n");
+
+ g0.lgrpi0_name = groupname;
+
+ status = NetLocalGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupAdd");
+ goto out;
+ };
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netlocalgroupenum(hostname, enum_levels[i], groupname);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupEnum");
+ goto out;
+ }
+ }
+
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetLocalGroupGetInfo level %d\n", levels[i]);
+
+ status = NetLocalGroupGetInfo(hostname, groupname, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+ }
+
+ /* alias rename */
+
+ printf("testing NetLocalGroupSetInfo level 0\n");
+
+ g0.lgrpi0_name = groupname2;
+
+ status = NetLocalGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupSetInfo");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetLocalGroupDel(hostname, groupname);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupDel");
+ goto out;
+ };
+
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ status = NetLocalGroupGetInfo(hostname, groupname2, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+ }
+
+ /* delete */
+
+ printf("testing NetLocalGroupDel\n");
+
+ status = NetLocalGroupDel(hostname, groupname2);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetLocalGroupGetInfo(hostname, groupname2, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetLocalGroupGetInfo");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetLocalgroup tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetLocalGroup testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source/lib/netapi/tests/netshare.c b/source/lib/netapi/tests/netshare.c
new file mode 100644
index 0000000000..9446c307b3
--- /dev/null
+++ b/source/lib/netapi/tests/netshare.c
@@ -0,0 +1,232 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetShare testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netshareenum(const char *hostname,
+ uint32_t level,
+ const char *sharename)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ int found_share = 0;
+ const char *current_name;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct SHARE_INFO_0 *i0;
+ struct SHARE_INFO_1 *i1;
+ struct SHARE_INFO_2 *i2;
+
+ printf("testing NetShareEnum level %d\n", level);
+
+ do {
+ status = NetShareEnum(hostname,
+ level,
+ &buffer,
+ (uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ i0 = (struct SHARE_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct SHARE_INFO_1 *)buffer;
+ break;
+ case 2:
+ i2 = (struct SHARE_INFO_2 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = i0->shi0_netname;
+ break;
+ case 1:
+ current_name = i1->shi1_netname;
+ break;
+ case 2:
+ current_name = i2->shi2_netname;
+ break;
+ default:
+ break;
+ }
+
+ if (strcasecmp(current_name, sharename) == 0) {
+ found_share = 1;
+ }
+
+ switch (level) {
+ case 0:
+ i0++;
+ break;
+ case 1:
+ i1++;
+ break;
+ case 2:
+ i2++;
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_share) {
+ printf("failed to get share\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *sharename, *comment;
+ uint8_t *buffer = NULL;
+ struct SHARE_INFO_2 i2;
+ struct SHARE_INFO_1004 i1004;
+ struct SHARE_INFO_501 *i501 = NULL;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 501, 1005 };
+ uint32_t enum_levels[] = { 0, 1, 2 };
+ int i;
+
+ printf("NetShare tests\n");
+
+ sharename = "torture_test_share";
+
+ /* cleanup */
+ NetShareDel(hostname, sharename, 0);
+
+ /* add a share */
+
+ printf("testing NetShareAdd\n");
+
+ ZERO_STRUCT(i2);
+
+ i2.shi2_netname = sharename;
+ i2.shi2_path = "c:\\";
+
+ status = NetShareAdd(hostname, 2, (uint8_t *)&i2, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareAdd");
+ goto out;
+ };
+
+ /* test enum */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netshareenum(hostname, enum_levels[i], sharename);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetShareGetInfo level %d\n", levels[i]);
+
+ status = NetShareGetInfo(hostname, sharename, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+ }
+
+
+ comment = "NetApi generated comment";
+
+ i1004.shi1004_remark = comment;
+
+ printf("testing NetShareSetInfo level 1004\n");
+
+ status = NetShareSetInfo(hostname, sharename, 1004, (uint8_t *)&i1004, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareSetInfo");
+ goto out;
+ }
+
+ status = NetShareGetInfo(hostname, sharename, 501, (uint8_t **)&i501);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+
+ if (strcasecmp(i501->shi501_remark, comment) != 0) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ }
+
+ /* delete */
+
+ printf("testing NetShareDel\n");
+
+ status = NetShareDel(hostname, sharename, 0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetShareDel");
+ goto out;
+ };
+
+ /* should not exist anymore */
+
+ status = NetShareGetInfo(hostname, sharename, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetShareGetInfo");
+ goto out;
+ };
+
+ status = 0;
+
+ printf("NetShare tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetShare testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source/lib/netapi/tests/netuser.c b/source/lib/netapi/tests/netuser.c
new file mode 100644
index 0000000000..f1622e45c4
--- /dev/null
+++ b/source/lib/netapi/tests/netuser.c
@@ -0,0 +1,458 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetUser testsuite
+ * 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 <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+#include "common.h"
+
+static NET_API_STATUS test_netuserenum(const char *hostname,
+ uint32_t level,
+ const char *username)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ uint32_t resume_handle = 0;
+ const char *current_name;
+ int found_user = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct USER_INFO_0 *info0;
+ struct USER_INFO_1 *info1;
+ struct USER_INFO_2 *info2;
+ struct USER_INFO_3 *info3;
+ struct USER_INFO_4 *info4;
+ struct USER_INFO_10 *info10;
+ struct USER_INFO_11 *info11;
+ struct USER_INFO_20 *info20;
+ struct USER_INFO_23 *info23;
+
+ printf("testing NetUserEnum level %d\n", level);
+
+ do {
+ status = NetUserEnum(hostname,
+ level,
+ FILTER_NORMAL_ACCOUNT,
+ &buffer,
+ 120, //(uint32_t)-1,
+ &entries_read,
+ &total_entries,
+ &resume_handle);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ info0 = (struct USER_INFO_0 *)buffer;
+ break;
+ case 1:
+ info1 = (struct USER_INFO_1 *)buffer;
+ break;
+ case 2:
+ info2 = (struct USER_INFO_2 *)buffer;
+ break;
+ case 3:
+ info3 = (struct USER_INFO_3 *)buffer;
+ break;
+ case 4:
+ info4 = (struct USER_INFO_4 *)buffer;
+ break;
+ case 10:
+ info10 = (struct USER_INFO_10 *)buffer;
+ break;
+ case 11:
+ info11 = (struct USER_INFO_11 *)buffer;
+ break;
+ case 20:
+ info20 = (struct USER_INFO_20 *)buffer;
+ break;
+ case 23:
+ info23 = (struct USER_INFO_23 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = info0->usri0_name;
+ break;
+ case 1:
+ current_name = info1->usri1_name;
+ break;
+ case 2:
+ current_name = info2->usri2_name;
+ break;
+ case 3:
+ current_name = info3->usri3_name;
+ break;
+ case 4:
+ current_name = info4->usri4_name;
+ break;
+ case 10:
+ current_name = info10->usri10_name;
+ break;
+ case 11:
+ current_name = info11->usri11_name;
+ break;
+ case 20:
+ current_name = info20->usri20_name;
+ break;
+ case 23:
+ current_name = info23->usri23_name;
+ break;
+ default:
+ return -1;
+ }
+
+ if (strcasecmp(current_name, username) == 0) {
+ found_user = 1;
+ }
+
+ switch (level) {
+ case 0:
+ info0++;
+ break;
+ case 1:
+ info1++;
+ break;
+ case 2:
+ info2++;
+ break;
+ case 3:
+ info3++;
+ break;
+ case 4:
+ info4++;
+ break;
+ case 10:
+ info10++;
+ break;
+ case 11:
+ info11++;
+ break;
+ case 20:
+ info20++;
+ break;
+ case 23:
+ info23++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (!found_user) {
+ printf("failed to get user\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS test_netuseradd(const char *hostname,
+ const char *username)
+{
+ struct USER_INFO_1 u1;
+ uint32_t parm_err = 0;
+
+ ZERO_STRUCT(u1);
+
+ printf("testing NetUserAdd\n");
+
+ u1.usri1_name = username;
+ u1.usri1_password = "W297!832jD8J";
+ u1.usri1_password_age = 0;
+ u1.usri1_priv = 0;
+ u1.usri1_home_dir = NULL;
+ u1.usri1_comment = "User created using Samba NetApi Example code";
+ u1.usri1_flags = 0;
+ u1.usri1_script_path = NULL;
+
+ return NetUserAdd(hostname, 1, (uint8_t *)&u1, &parm_err);
+}
+
+static NET_API_STATUS test_netusermodals(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status;
+ struct USER_MODALS_INFO_0 *u0 = NULL;
+ struct USER_MODALS_INFO_0 *_u0 = NULL;
+ uint8_t *buffer = NULL;
+ uint32_t parm_err = 0;
+ uint32_t levels[] = { 0, 1, 2, 3 };
+ int i = 0;
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetUserModalsGet level %d\n", levels[i]);
+
+ status = NetUserModalsGet(hostname, levels[i], &buffer);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+ }
+
+ status = NetUserModalsGet(hostname, 0, (uint8_t **)&u0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+
+ printf("testing NetUserModalsSet\n");
+
+ status = NetUserModalsSet(hostname, 0, (uint8_t *)u0, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsSet");
+ return status;
+ }
+
+ status = NetUserModalsGet(hostname, 0, (uint8_t **)&_u0);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserModalsGet");
+ return status;
+ }
+
+ if (memcmp(u0, _u0, sizeof(u0) != 0)) {
+ printf("USER_MODALS_INFO_0 struct has changed!!!!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static NET_API_STATUS test_netusergetgroups(const char *hostname,
+ uint32_t level,
+ const char *username,
+ const char *groupname)
+{
+ NET_API_STATUS status;
+ uint32_t entries_read = 0;
+ uint32_t total_entries = 0;
+ const char *current_name;
+ int found_group = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ struct GROUP_USERS_INFO_0 *i0;
+ struct GROUP_USERS_INFO_1 *i1;
+
+ printf("testing NetUserGetGroups level %d\n", level);
+
+ do {
+ status = NetUserGetGroups(hostname,
+ username,
+ level,
+ &buffer,
+ 120, //(uint32_t)-1,
+ &entries_read,
+ &total_entries);
+ if (status == 0 || status == ERROR_MORE_DATA) {
+ switch (level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)buffer;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i=0; i<entries_read; i++) {
+
+ switch (level) {
+ case 0:
+ current_name = i0->grui0_name;
+ break;
+ case 1:
+ current_name = i1->grui1_name;
+ break;
+ default:
+ return -1;
+ }
+
+ if (groupname && strcasecmp(current_name, groupname) == 0) {
+ found_group = 1;
+ }
+
+ switch (level) {
+ case 0:
+ i0++;
+ break;
+ case 1:
+ i1++;
+ break;
+ default:
+ break;
+ }
+ }
+ NetApiBufferFree(buffer);
+ }
+ } while (status == ERROR_MORE_DATA);
+
+ if (status) {
+ return status;
+ }
+
+ if (groupname && !found_group) {
+ printf("failed to get membership\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+NET_API_STATUS netapitest_user(struct libnetapi_ctx *ctx,
+ const char *hostname)
+{
+ NET_API_STATUS status = 0;
+ const char *username, *username2;
+ uint8_t *buffer = NULL;
+ uint32_t levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
+ uint32_t enum_levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
+ uint32_t getgr_levels[] = { 0, 1 };
+ int i;
+
+ struct USER_INFO_1007 u1007;
+ uint32_t parm_err = 0;
+
+ printf("NetUser tests\n");
+
+ username = "torture_test_user";
+ username2 = "torture_test_user2";
+
+ /* cleanup */
+ NetUserDel(hostname, username);
+ NetUserDel(hostname, username2);
+
+ /* add a user */
+
+ status = test_netuseradd(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserAdd");
+ goto out;
+ }
+
+ /* enum the new user */
+
+ for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
+
+ status = test_netuserenum(hostname, enum_levels[i], username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserEnum");
+ goto out;
+ }
+ }
+
+ /* basic queries */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ printf("testing NetUserGetInfo level %d\n", levels[i]);
+
+ status = NetUserGetInfo(hostname, username, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+ }
+
+ /* testing getgroups */
+
+ for (i=0; i<ARRAY_SIZE(getgr_levels); i++) {
+
+ status = test_netusergetgroups(hostname, getgr_levels[i], username, NULL);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserGetGroups");
+ goto out;
+ }
+ }
+
+ /* modify description */
+
+ printf("testing NetUserSetInfo level %d\n", 1007);
+
+ u1007.usri1007_comment = "NetApi modified user";
+
+ status = NetUserSetInfo(hostname, username, 1007, (uint8_t *)&u1007, &parm_err);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserSetInfo");
+ goto out;
+ }
+
+ /* query info */
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ status = NetUserGetInfo(hostname, username, levels[i], &buffer);
+ if (status && status != 124) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+ }
+
+ /* delete */
+
+ printf("testing NetUserDel\n");
+
+ status = NetUserDel(hostname, username);
+ if (status) {
+ NETAPI_STATUS(ctx, status, "NetUserDel");
+ goto out;
+ }
+
+ /* should not exist anymore */
+
+ status = NetUserGetInfo(hostname, username, 0, &buffer);
+ if (status == 0) {
+ NETAPI_STATUS(ctx, status, "NetUserGetInfo");
+ goto out;
+ }
+
+ status = test_netusermodals(ctx, hostname);
+ if (status) {
+ goto out;
+ }
+
+ status = 0;
+
+ printf("NetUser tests succeeded\n");
+ out:
+ if (status != 0) {
+ printf("NetUser testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ }
+
+ return status;
+}
diff --git a/source/lib/netapi/user.c b/source/lib/netapi/user.c
index 05a051067a..7d0c47f331 100644
--- a/source/lib/netapi/user.c
+++ b/source/lib/netapi/user.c
@@ -27,102 +27,283 @@
/****************************************************************
****************************************************************/
-static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1,
- DATA_BLOB *user_session_key,
- struct samr_UserInfo25 *info25)
+static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
+ struct samr_UserInfo21 *info21)
{
- uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
+ uint32_t fields_present = 0;
struct samr_LogonHours zero_logon_hours;
struct lsa_BinaryString zero_parameters;
- uint32_t acct_flags = 0;
NTTIME password_age;
- ZERO_STRUCTP(info25);
+ ZERO_STRUCTP(info21);
ZERO_STRUCT(zero_logon_hours);
ZERO_STRUCT(zero_parameters);
- if (info1->usri1_name) {
- fields_present |= SAMR_FIELD_FULL_NAME;
+ if (infoX->usriX_flags) {
+ fields_present |= SAMR_FIELD_ACCT_FLAGS;
+ }
+ if (infoX->usriX_name) {
+ fields_present |= SAMR_FIELD_ACCOUNT_NAME;
}
- if (info1->usri1_password) {
+ if (infoX->usriX_password) {
fields_present |= SAMR_FIELD_PASSWORD;
}
- if (info1->usri1_flags) {
+ if (infoX->usriX_flags) {
fields_present |= SAMR_FIELD_ACCT_FLAGS;
}
- if (info1->usri1_name) {
+ if (infoX->usriX_name) {
fields_present |= SAMR_FIELD_FULL_NAME;
}
- if (info1->usri1_home_dir) {
+ if (infoX->usriX_home_dir) {
fields_present |= SAMR_FIELD_HOME_DIRECTORY;
}
- if (info1->usri1_script_path) {
+ if (infoX->usriX_script_path) {
fields_present |= SAMR_FIELD_LOGON_SCRIPT;
}
- if (info1->usri1_comment) {
+ if (infoX->usriX_comment) {
fields_present |= SAMR_FIELD_DESCRIPTION;
}
- if (info1->usri1_password_age) {
+ if (infoX->usriX_password_age) {
fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
}
+ if (infoX->usriX_full_name) {
+ fields_present |= SAMR_FIELD_FULL_NAME;
+ }
+ if (infoX->usriX_usr_comment) {
+ fields_present |= SAMR_FIELD_COMMENT;
+ }
+ if (infoX->usriX_profile) {
+ fields_present |= SAMR_FIELD_PROFILE_PATH;
+ }
+ if (infoX->usriX_home_dir_drive) {
+ fields_present |= SAMR_FIELD_HOME_DRIVE;
+ }
+ if (infoX->usriX_primary_group_id) {
+ fields_present |= SAMR_FIELD_PRIMARY_GID;
+ }
+ if (infoX->usriX_country_code) {
+ fields_present |= SAMR_FIELD_COUNTRY_CODE;
+ }
+ if (infoX->usriX_workstations) {
+ fields_present |= SAMR_FIELD_WORKSTATIONS;
+ }
- acct_flags |= info1->usri1_flags | ACB_NORMAL;
-
- unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
+ unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
- /* TODO: info1->usri1_priv */
- init_samr_user_info21(&info25->info,
+ /* TODO: infoX->usriX_priv */
+ init_samr_user_info21(info21,
0,
0,
0,
0,
0,
password_age,
- NULL,
- info1->usri1_name,
- info1->usri1_home_dir,
- NULL,
- info1->usri1_script_path,
- NULL,
- info1->usri1_comment,
- NULL,
- NULL,
+ infoX->usriX_name,
+ infoX->usriX_full_name,
+ infoX->usriX_home_dir,
+ infoX->usriX_home_dir_drive,
+ infoX->usriX_script_path,
+ infoX->usriX_profile,
+ infoX->usriX_comment,
+ infoX->usriX_workstations,
+ infoX->usriX_usr_comment,
&zero_parameters,
0,
- 0,
- acct_flags,
+ infoX->usriX_primary_group_id,
+ infoX->usriX_flags,
fields_present,
zero_logon_hours,
0,
0,
- 0,
+ infoX->usriX_country_code,
0,
0,
0,
0);
+}
- if (info1->usri1_password) {
- uchar pwbuf[532];
- struct MD5Context ctx;
- uint8_t confounder[16];
- DATA_BLOB confounded_session_key = data_blob(NULL, 16);
+/****************************************************************
+****************************************************************/
- encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
+static NTSTATUS construct_USER_INFO_X(uint32_t level,
+ uint8_t *buffer,
+ struct USER_INFO_X *uX)
+{
+ struct USER_INFO_0 *u0 = NULL;
+ struct USER_INFO_1 *u1 = NULL;
+ struct USER_INFO_2 *u2 = NULL;
+ struct USER_INFO_1003 *u1003 = NULL;
+ struct USER_INFO_1006 *u1006 = NULL;
+ struct USER_INFO_1007 *u1007 = NULL;
+ struct USER_INFO_1009 *u1009 = NULL;
+ struct USER_INFO_1011 *u1011 = NULL;
+ struct USER_INFO_1012 *u1012 = NULL;
+ struct USER_INFO_1014 *u1014 = NULL;
+ struct USER_INFO_1024 *u1024 = NULL;
+ struct USER_INFO_1051 *u1051 = NULL;
+ struct USER_INFO_1052 *u1052 = NULL;
+ struct USER_INFO_1053 *u1053 = NULL;
+
+ if (!buffer || !uX) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCTP(uX);
- generate_random_buffer((uint8_t *)confounder, 16);
+ switch (level) {
+ case 0:
+ u0 = (struct USER_INFO_0 *)buffer;
+ uX->usriX_name = u0->usri0_name;
+ break;
+ case 1:
+ u1 = (struct USER_INFO_1 *)buffer;
+ uX->usriX_name = u1->usri1_name;
+ uX->usriX_password = u1->usri1_password;
+ uX->usriX_password_age = u1->usri1_password_age;
+ uX->usriX_priv = u1->usri1_priv;
+ uX->usriX_home_dir = u1->usri1_home_dir;
+ uX->usriX_comment = u1->usri1_comment;
+ uX->usriX_flags = u1->usri1_flags;
+ uX->usriX_script_path = u1->usri1_script_path;
+ break;
+ case 2:
+ u2 = (struct USER_INFO_2 *)buffer;
+ uX->usriX_name = u2->usri2_name;
+ uX->usriX_password = u2->usri2_password;
+ uX->usriX_password_age = u2->usri2_password_age;
+ uX->usriX_priv = u2->usri2_priv;
+ uX->usriX_home_dir = u2->usri2_home_dir;
+ uX->usriX_comment = u2->usri2_comment;
+ uX->usriX_flags = u2->usri2_flags;
+ uX->usriX_script_path = u2->usri2_script_path;
+ uX->usriX_auth_flags = u2->usri2_auth_flags;
+ uX->usriX_full_name = u2->usri2_full_name;
+ uX->usriX_usr_comment = u2->usri2_usr_comment;
+ uX->usriX_parms = u2->usri2_parms;
+ uX->usriX_workstations = u2->usri2_workstations;
+ uX->usriX_last_logon = u2->usri2_last_logon;
+ uX->usriX_last_logoff = u2->usri2_last_logoff;
+ uX->usriX_acct_expires = u2->usri2_acct_expires;
+ uX->usriX_max_storage = u2->usri2_max_storage;
+ uX->usriX_units_per_week= u2->usri2_units_per_week;
+ uX->usriX_logon_hours = u2->usri2_logon_hours;
+ uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
+ uX->usriX_num_logons = u2->usri2_num_logons;
+ uX->usriX_logon_server = u2->usri2_logon_server;
+ uX->usriX_country_code = u2->usri2_country_code;
+ uX->usriX_code_page = u2->usri2_code_page;
+ break;
+ case 1003:
+ u1003 = (struct USER_INFO_1003 *)buffer;
+ uX->usriX_password = u1003->usri1003_password;
+ break;
+ case 1006:
+ u1006 = (struct USER_INFO_1006 *)buffer;
+ uX->usriX_home_dir = u1006->usri1006_home_dir;
+ break;
+ case 1007:
+ u1007 = (struct USER_INFO_1007 *)buffer;
+ uX->usriX_comment = u1007->usri1007_comment;
+ break;
+ case 1009:
+ u1009 = (struct USER_INFO_1009 *)buffer;
+ uX->usriX_script_path = u1009->usri1009_script_path;
+ break;
+ case 1011:
+ u1011 = (struct USER_INFO_1011 *)buffer;
+ uX->usriX_full_name = u1011->usri1011_full_name;
+ break;
+ case 1012:
+ u1012 = (struct USER_INFO_1012 *)buffer;
+ uX->usriX_usr_comment = u1012->usri1012_usr_comment;
+ break;
+ case 1014:
+ u1014 = (struct USER_INFO_1014 *)buffer;
+ uX->usriX_workstations = u1014->usri1014_workstations;
+ break;
+ case 1024:
+ u1024 = (struct USER_INFO_1024 *)buffer;
+ uX->usriX_country_code = u1024->usri1024_country_code;
+ break;
+ case 1051:
+ u1051 = (struct USER_INFO_1051 *)buffer;
+ uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
+ break;
+ case 1052:
+ u1052 = (struct USER_INFO_1052 *)buffer;
+ uX->usriX_profile = u1052->usri1052_profile;
+ break;
+ case 1053:
+ u1053 = (struct USER_INFO_1053 *)buffer;
+ uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
+ break;
+ case 3:
+ case 4:
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
- MD5Init(&ctx);
- MD5Update(&ctx, confounder, 16);
- MD5Update(&ctx, user_session_key->data,
- user_session_key->length);
- MD5Final(confounded_session_key.data, &ctx);
+ return NT_STATUS_OK;
+}
- SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
- memcpy(&pwbuf[516], confounder, 16);
+/****************************************************************
+****************************************************************/
- memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
- data_blob_free(&confounded_session_key);
+static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
+ struct rpc_pipe_client *pipe_cli,
+ DATA_BLOB *session_key,
+ struct policy_handle *user_handle,
+ struct USER_INFO_X *uX)
+{
+ union samr_UserInfo user_info;
+ struct samr_UserInfo21 info21;
+ NTSTATUS status;
+
+ if (!uX) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
+
+ ZERO_STRUCT(user_info);
+
+ if (uX->usriX_password) {
+
+ user_info.info25.info = info21;
+
+ init_samr_CryptPasswordEx(uX->usriX_password,
+ session_key,
+ &user_info.info25.password);
+
+ status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
+ user_handle,
+ 25,
+ &user_info);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
+
+ user_info.info23.info = info21;
+
+ init_samr_CryptPassword(uX->usriX_password,
+ session_key,
+ &user_info.info23.password);
+
+ status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
+ user_handle,
+ 23,
+ &user_info);
+ }
+ } else {
+
+ user_info.info21 = info21;
+
+ status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
+ user_handle,
+ 21,
+ &user_info);
}
+
+ return status;
}
/****************************************************************
@@ -135,21 +316,14 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- uint32_t resume_handle = 0;
- uint32_t num_entries = 0;
POLICY_HND connect_handle, domain_handle, user_handle;
- struct samr_SamArray *sam = NULL;
- const char *domain_name = NULL;
- struct lsa_String lsa_domain_name, lsa_account_name;
+ struct lsa_String lsa_account_name;
struct dom_sid2 *domain_sid = NULL;
- struct samr_UserInfo25 info25;
union samr_UserInfo *user_info = NULL;
struct samr_PwInfo pw_info;
uint32_t access_granted = 0;
uint32_t rid = 0;
- bool domain_found = true;
- int i;
- struct USER_INFO_1 *info1;
+ struct USER_INFO_X uX;
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(domain_handle);
@@ -161,7 +335,6 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
switch (r->in.level) {
case 1:
- info1 = (struct USER_INFO_1 *)r->in.buffer;
break;
case 2:
case 3:
@@ -171,77 +344,34 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
goto done;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- status = rpccli_try_samr_connects(pipe_cli, ctx,
- SAMR_ACCESS_ENUM_DOMAINS |
- SAMR_ACCESS_OPEN_DOMAIN,
- &connect_handle);
+ status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- status = rpccli_samr_EnumDomains(pipe_cli, ctx,
- &connect_handle,
- &resume_handle,
- &sam,
- 0xffffffff,
- &num_entries);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- for (i=0; i<num_entries; i++) {
-
- domain_name = sam->entries[i].name.string;
-
- if (strequal(domain_name, builtin_domain_name())) {
- continue;
- }
-
- domain_found = true;
- break;
- }
-
- if (!domain_found) {
- werr = WERR_NO_SUCH_DOMAIN;
- goto done;
- }
-
- init_lsa_String(&lsa_domain_name, domain_name);
-
- status = rpccli_samr_LookupDomain(pipe_cli, ctx,
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_CREATE_USER |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
&connect_handle,
- &lsa_domain_name,
+ &domain_handle,
&domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- status = rpccli_samr_OpenDomain(pipe_cli, ctx,
- &connect_handle,
- SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
- SAMR_DOMAIN_ACCESS_CREATE_USER |
- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
- domain_sid,
- &domain_handle);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
+ if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- init_lsa_String(&lsa_account_name, info1->usri1_name);
+ init_lsa_String(&lsa_account_name, uX.usriX_name);
status = rpccli_samr_CreateUser2(pipe_cli, ctx,
&domain_handle,
@@ -282,26 +412,12 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
goto done;
}
- ZERO_STRUCTP(user_info);
-
- convert_USER_INFO_1_to_samr_user_info25(info1,
- &cli->user_session_key,
- &info25);
+ uX.usriX_flags |= ACB_NORMAL;
- if (info1->usri1_password) {
- user_info->info25 = info25;
- status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
- &user_handle,
- 25,
- user_info);
- } else {
- user_info->info21 = info25.info;
- status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
- &user_handle,
- 21,
- user_info);
-
- }
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &cli->user_session_key,
+ &user_handle,
+ &uX);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto failed;
@@ -322,11 +438,10 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
if (is_valid_policy_hnd(&user_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &user_handle);
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
@@ -338,12 +453,7 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
struct NetUserAdd *r)
{
- /* for now just talk to local RPC server */
- if (!r->in.server_name) {
- r->in.server_name = "localhost";
- }
-
- return NetUserAdd_r(ctx, r);
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
}
/****************************************************************
@@ -356,88 +466,34 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
- uint32_t resume_handle = 0;
- uint32_t num_entries = 0;
POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
- struct samr_SamArray *sam = NULL;
- const char *domain_name = NULL;
- struct lsa_String lsa_domain_name, lsa_account_name;
+ struct lsa_String lsa_account_name;
struct samr_Ids user_rids, name_types;
struct dom_sid2 *domain_sid = NULL;
struct dom_sid2 user_sid;
- bool domain_found = true;
- int i;
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(builtin_handle);
ZERO_STRUCT(domain_handle);
ZERO_STRUCT(user_handle);
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- status = rpccli_try_samr_connects(pipe_cli, ctx,
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
SAMR_ACCESS_ENUM_DOMAINS |
SAMR_ACCESS_OPEN_DOMAIN,
- &connect_handle);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- status = rpccli_samr_EnumDomains(pipe_cli, ctx,
- &connect_handle,
- &resume_handle,
- &sam,
- 0xffffffff,
- &num_entries);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- for (i=0; i<num_entries; i++) {
-
- domain_name = sam->entries[i].name.string;
-
- if (strequal(domain_name, builtin_domain_name())) {
- continue;
- }
-
- domain_found = true;
- break;
- }
-
- if (!domain_found) {
- werr = WERR_NO_SUCH_DOMAIN;
- goto done;
- }
-
- init_lsa_String(&lsa_domain_name, domain_name);
-
- status = rpccli_samr_LookupDomain(pipe_cli, ctx,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
&connect_handle,
- &lsa_domain_name,
+ &domain_handle,
&domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- status = rpccli_samr_OpenDomain(pipe_cli, ctx,
- &connect_handle,
- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
- domain_sid,
- &domain_handle);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
+ if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -501,14 +557,11 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
if (is_valid_policy_hnd(&user_handle)) {
rpccli_samr_Close(pipe_cli, ctx, &user_handle);
}
- if (is_valid_policy_hnd(&builtin_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
- }
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
@@ -520,46 +573,576 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
struct NetUserDel *r)
{
- /* for now just talk to local RPC server */
- if (!r->in.server_name) {
- r->in.server_name = "localhost";
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct policy_handle *builtin_handle,
+ const char *user_name,
+ const struct dom_sid *domain_sid,
+ uint32_t rid,
+ uint32_t level,
+ struct samr_UserInfo21 **info21,
+ struct sec_desc_buf **sec_desc,
+ uint32_t *auth_flag_p)
+{
+ NTSTATUS status;
+
+ struct policy_handle user_handle;
+ union samr_UserInfo *user_info = NULL;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ uint32_t access_mask = SEC_STD_READ_CONTROL |
+ SAMR_USER_ACCESS_GET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_NAME_ETC;
+
+ ZERO_STRUCT(user_handle);
+
+ switch (level) {
+ case 0:
+ break;
+ case 1:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 11:
+ access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
+ SAMR_USER_ACCESS_GET_GROUPS |
+ SAMR_USER_ACCESS_GET_LOCALE;
+ break;
+ case 10:
+ case 20:
+ case 23:
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (level == 0) {
+ return NT_STATUS_OK;
}
- return NetUserDel_r(ctx, r);
+ status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
+ domain_handle,
+ access_mask,
+ rid,
+ &user_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
+ &user_handle,
+ 21,
+ &user_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
+ &user_handle,
+ SECINFO_DACL,
+ sec_desc);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
+
+ struct lsa_SidArray sid_array;
+ struct samr_Ids alias_rids;
+ int i;
+ uint32_t auth_flag = 0;
+ struct dom_sid sid;
+
+ status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
+ &user_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ sid_array.num_sids = rid_array->count + 1;
+ sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
+ sid_array.num_sids);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
+
+ for (i=0; i<rid_array->count; i++) {
+ sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
+ sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+ }
+
+ sid_compose(&sid, domain_sid, rid);
+ sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
+
+ status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
+ builtin_handle,
+ &sid_array,
+ &alias_rids);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ for (i=0; i<alias_rids.count; i++) {
+ switch (alias_rids.ids[i]) {
+ case 550: /* Print Operators */
+ auth_flag |= AF_OP_PRINT;
+ break;
+ case 549: /* Server Operators */
+ auth_flag |= AF_OP_SERVER;
+ break;
+ case 548: /* Account Operators */
+ auth_flag |= AF_OP_ACCOUNTS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (auth_flag_p) {
+ *auth_flag_p = auth_flag;
+ }
+ }
+
+ *info21 = &user_info->info21;
+
+ done:
+ if (is_valid_policy_hnd(&user_handle)) {
+ rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
+ }
+
+ return status;
}
/****************************************************************
****************************************************************/
-static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
- struct samr_SamArray *sam_array,
- uint32_t level,
- uint8_t **buffer)
+static uint32_t samr_rid_to_priv_level(uint32_t rid)
{
- struct USER_INFO_0 *info0 = NULL;
- int i;
+ switch (rid) {
+ case DOMAIN_RID_ADMINISTRATOR:
+ return USER_PRIV_ADMIN;
+ case DOMAIN_RID_GUEST:
+ return USER_PRIV_GUEST;
+ default:
+ return USER_PRIV_USER;
+ }
+}
+
+/****************************************************************
+****************************************************************/
+
+static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
+{
+ uint32_t fl = UF_SCRIPT; /* god knows why */
+
+ fl |= ads_acb2uf(acb);
+
+ return fl;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_1 *i)
+{
+ ZERO_STRUCTP(i);
+ i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
+ i->usri1_password = NULL;
+ i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri1_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_2 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
+ i->usri2_password = NULL;
+ i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri2_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri2_auth_flags = auth_flag;
+ i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri2_units_per_week = i21->logon_hours.units_per_week;
+ i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri2_bad_pw_count = i21->bad_password_count;
+ i->usri2_num_logons = i21->logon_count;
+ i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri2_country_code = i21->country_code;
+ i->usri2_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_3 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
+ i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri3_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri3_auth_flags = auth_flag;
+ i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri3_units_per_week = i21->logon_hours.units_per_week;
+ i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri3_bad_pw_count = i21->bad_password_count;
+ i->usri3_num_logons = i21->logon_count;
+ i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri3_country_code = i21->country_code;
+ i->usri3_code_page = i21->code_page;
+ i->usri3_user_id = i21->rid;
+ i->usri3_primary_group_id = i21->primary_gid;
+ i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri3_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_4 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
+ i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri4_password = NULL;
+ i->usri4_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
+ i->usri4_auth_flags = auth_flag;
+ i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
+ i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri4_units_per_week = i21->logon_hours.units_per_week;
+ i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri4_bad_pw_count = i21->bad_password_count;
+ i->usri4_num_logons = i21->logon_count;
+ i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri4_country_code = i21->country_code;
+ i->usri4_code_page = i21->code_page;
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri4_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+ i->usri4_primary_group_id = i21->primary_gid;
+ i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
+ i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
+ i->usri4_password_expired = i21->password_expired;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_10 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
+ i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ uint32_t auth_flag,
+ struct USER_INFO_11 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
+ i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
+ i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri11_priv = samr_rid_to_priv_level(i21->rid);
+ i->usri11_auth_flags = auth_flag;
+ i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
+ i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
+ i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
+ i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
+ i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
+ i->usri11_bad_pw_count = i21->bad_password_count;
+ i->usri11_num_logons = i21->logon_count;
+ i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
+ i->usri11_country_code = i21->country_code;
+ i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
+ i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
+ i->usri11_units_per_week = i21->logon_hours.units_per_week;
+ i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
+ i->usri11_code_page = i21->code_page;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct USER_INFO_20 *i)
+{
+ ZERO_STRUCTP(i);
+
+ i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
+ i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ i->usri20_user_id = i21->rid;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
+ const struct samr_UserInfo21 *i21,
+ struct dom_sid *domain_sid,
+ struct USER_INFO_23 *i)
+{
+ struct dom_sid sid;
+
+ ZERO_STRUCTP(i);
+
+ i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
+ NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
+ i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
+ i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
+ i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
+ if (!sid_compose(&sid, domain_sid, i21->rid)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ i->usri23_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct dom_sid *domain_sid,
+ struct policy_handle *domain_handle,
+ struct policy_handle *builtin_handle,
+ const char *user_name,
+ uint32_t rid,
+ uint32_t level,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ NTSTATUS status;
+
+ struct samr_UserInfo21 *info21 = NULL;
+ struct sec_desc_buf *sec_desc = NULL;
+ uint32_t auth_flag = 0;
+
+ struct USER_INFO_0 info0;
+ struct USER_INFO_1 info1;
+ struct USER_INFO_2 info2;
+ struct USER_INFO_3 info3;
+ struct USER_INFO_4 info4;
+ struct USER_INFO_10 info10;
+ struct USER_INFO_11 info11;
+ struct USER_INFO_20 info20;
+ struct USER_INFO_23 info23;
switch (level) {
case 0:
- info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
- sam_array->count);
- W_ERROR_HAVE_NO_MEMORY(info0);
-
- for (i=0; i<sam_array->count; i++) {
- info0[i].usri0_name = talloc_strdup(mem_ctx,
- sam_array->entries[i].name.string);
- W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
- }
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 10:
+ case 11:
+ case 20:
+ case 23:
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (level == 0) {
+ info0.usri0_name = talloc_strdup(mem_ctx, user_name);
+ NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
+ (struct USER_INFO_0 **)buffer, num_entries);
+
+ return NT_STATUS_OK;
+ }
+
+ status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
+ domain_handle,
+ builtin_handle,
+ user_name,
+ domain_sid,
+ rid,
+ level,
+ &info21,
+ &sec_desc,
+ &auth_flag);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ switch (level) {
+ case 0:
+ /* already returned above */
+ break;
+ case 1:
+ status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
+ (struct USER_INFO_1 **)buffer, num_entries);
+
+ break;
+ case 2:
+ status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
+ (struct USER_INFO_2 **)buffer, num_entries);
+
+ break;
+ case 3:
+ status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
+ (struct USER_INFO_3 **)buffer, num_entries);
+
+ break;
+ case 4:
+ status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
+ (struct USER_INFO_4 **)buffer, num_entries);
- *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
- sizeof(struct USER_INFO_0) * sam_array->count);
- W_ERROR_HAVE_NO_MEMORY(*buffer);
+ break;
+ case 10:
+ status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
+ (struct USER_INFO_10 **)buffer, num_entries);
+
+ break;
+ case 11:
+ status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
+ (struct USER_INFO_11 **)buffer, num_entries);
+
+ break;
+ case 20:
+ status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
+ (struct USER_INFO_20 **)buffer, num_entries);
+
+ break;
+ case 23:
+ status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
+ (struct USER_INFO_23 **)buffer, num_entries);
break;
default:
- return WERR_NOT_SUPPORTED;
+ return NT_STATUS_INVALID_LEVEL;
}
- return WERR_OK;
+ done:
+ return status;
}
/****************************************************************
@@ -572,133 +1155,137 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
struct rpc_pipe_client *pipe_cli = NULL;
struct policy_handle connect_handle;
struct dom_sid2 *domain_sid = NULL;
- struct policy_handle domain_handle;
+ struct policy_handle domain_handle, builtin_handle;
struct samr_SamArray *sam = NULL;
- uint32_t num_entries = 0;
+ uint32_t filter = ACB_NORMAL;
int i;
- const char *domain_name = NULL;
- bool domain_found = true;
- uint32_t dom_resume_handle = 0;
- struct lsa_String lsa_domain_name;
+ uint32_t entries_read = 0;
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_OK;
WERROR werr;
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
switch (r->in.level) {
case 0:
- break;
case 1:
case 2:
case 3:
+ case 4:
case 10:
case 11:
case 20:
case 23:
+ break;
default:
- return WERR_NOT_SUPPORTED;
+ return WERR_UNKNOWN_LEVEL;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- status = rpccli_try_samr_connects(pipe_cli, ctx,
- SAMR_ACCESS_OPEN_DOMAIN |
- SAMR_ACCESS_ENUM_DOMAINS,
- &connect_handle);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- status = rpccli_samr_EnumDomains(pipe_cli, ctx,
- &connect_handle,
- &dom_resume_handle,
- &sam,
- 0xffffffff,
- &num_entries);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
- }
-
- for (i=0; i<num_entries; i++) {
-
- domain_name = sam->entries[i].name.string;
-
- if (strequal(domain_name, builtin_domain_name())) {
- continue;
- }
-
- domain_found = true;
- break;
- }
-
- if (!domain_found) {
- werr = WERR_NO_SUCH_DOMAIN;
- goto done;
- }
-
- init_lsa_String(&lsa_domain_name, domain_name);
-
- status = rpccli_samr_LookupDomain(pipe_cli, ctx,
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
&connect_handle,
- &lsa_domain_name,
+ &domain_handle,
&domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
+ if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- status = rpccli_samr_OpenDomain(pipe_cli,
- ctx,
- &connect_handle,
- SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
- SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
- domain_sid,
- &domain_handle);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
- goto done;
+ switch (r->in.filter) {
+ case FILTER_NORMAL_ACCOUNT:
+ filter = ACB_NORMAL;
+ break;
+ case FILTER_TEMP_DUPLICATE_ACCOUNT:
+ filter = ACB_TEMPDUP;
+ break;
+ case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
+ filter = ACB_DOMTRUST;
+ break;
+ case FILTER_WORKSTATION_TRUST_ACCOUNT:
+ filter = ACB_WSTRUST;
+ break;
+ case FILTER_SERVER_TRUST_ACCOUNT:
+ filter = ACB_SVRTRUST;
+ break;
+ default:
+ break;
}
status = rpccli_samr_EnumDomainUsers(pipe_cli,
ctx,
&domain_handle,
r->in.resume_handle,
- r->in.filter,
+ filter,
&sam,
r->in.prefmaxlen,
- r->out.entries_read);
- if (!NT_STATUS_IS_OK(status)) {
- werr = ntstatus_to_werror(status);
+ &entries_read);
+ werr = ntstatus_to_werror(status);
+ if (NT_STATUS_IS_ERR(status)) {
goto done;
}
- werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
- r->in.level,
- r->out.buffer);
+ for (i=0; i < sam->count; i++) {
+
+ status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
+ domain_sid,
+ &domain_handle,
+ &builtin_handle,
+ sam->entries[i].name.string,
+ sam->entries[i].idx,
+ r->in.level,
+ r->out.buffer,
+ r->out.entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
done:
if (!cli) {
return werr;
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
- }
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+ /* if last query */
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_IS_ERR(status)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
}
return werr;
@@ -710,7 +1297,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
struct NetUserEnum *r)
{
- return WERR_NOT_SUPPORTED;
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
}
/****************************************************************
@@ -845,11 +1432,11 @@ static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
/****************************************************************
****************************************************************/
-WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
- union samr_DispInfo *info,
- uint32_t level,
- uint32_t *entries_read,
- void **buffer)
+static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
+ union samr_DispInfo *info,
+ uint32_t level,
+ uint32_t *entries_read,
+ void **buffer)
{
switch (level) {
case 1:
@@ -886,143 +1473,1968 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
struct dom_sid2 *domain_sid = NULL;
struct policy_handle domain_handle;
union samr_DispInfo info;
- struct samr_SamArray *sam = NULL;
- uint32_t num_entries = 0;
- int i;
- const char *domain_name = NULL;
- bool domain_found = true;
- uint32_t dom_resume_handle = 0;
- struct lsa_String lsa_domain_name;
uint32_t total_size = 0;
uint32_t returned_size = 0;
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ switch (r->in.level) {
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
+ ctx,
+ &domain_handle,
+ r->in.level,
+ r->in.idx,
+ r->in.entries_requested,
+ r->in.prefmaxlen,
+ &total_size,
+ &returned_size,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
+ r->in.level,
+ r->out.entries_read,
+ r->out.buffer);
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ /* if last query */
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_IS_ERR(status)) {
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+ }
+
+ return werr;
+
+}
+
+/****************************************************************
+****************************************************************/
+
+
+WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
+ struct NetQueryDisplayInformation *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
+ struct NetUserChangePassword *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
NTSTATUS status;
WERROR werr;
+ struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ uint32_t num_entries = 0;
+
ZERO_STRUCT(connect_handle);
ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(user_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
switch (r->in.level) {
+ case 0:
case 1:
case 2:
case 3:
+ case 4:
+ case 10:
+ case 11:
+ case 20:
+ case 23:
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
+ domain_sid,
+ &domain_handle,
+ &builtin_handle,
+ r->in.user_name,
+ user_rids.ids[0],
+ r->in.level,
+ r->out.buffer,
+ &num_entries);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&user_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &user_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ uint32_t user_mask = 0;
+
+ struct USER_INFO_X uX;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+ ZERO_STRUCT(builtin_handle);
+ ZERO_STRUCT(user_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1003:
+ user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
+ break;
+ case 1006:
+ case 1007:
+ case 1009:
+ case 1011:
+ case 1014:
+ case 1052:
+ case 1053:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
+ break;
+ case 1012:
+ case 1024:
+ user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
+ case 1051:
+ user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
+ SAMR_USER_ACCESS_GET_GROUPS;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 21:
+ case 22:
+ case 1005:
+ case 1008:
+ case 1010:
+ case 1017:
+ case 1020:
+ werr = WERR_NOT_SUPPORTED;
+ goto done;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenUser(pipe_cli, ctx,
+ &domain_handle,
+ user_mask,
+ user_rids.ids[0],
+ &user_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = set_user_info_USER_INFO_X(ctx, pipe_cli,
+ &cli->user_session_key,
+ &user_handle,
+ &uX);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (is_valid_policy_hnd(&user_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &user_handle);
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetInfo *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct samr_DomInfo1 *info1,
+ struct samr_DomInfo3 *info3,
+ struct samr_DomInfo5 *info5,
+ struct samr_DomInfo6 *info6,
+ struct samr_DomInfo7 *info7,
+ struct samr_DomInfo12 *info12)
+{
+ NTSTATUS status;
+ union samr_DomainInfo *dom_info = NULL;
+
+ if (info1) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 1,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info1 = dom_info->info1;
+ }
+
+ if (info3) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 3,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info3 = dom_info->info3;
+ }
+
+ if (info5) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 5,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info5 = dom_info->info5;
+ }
+
+ if (info6) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 6,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info6 = dom_info->info6;
+ }
+
+ if (info7) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 7,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info7 = dom_info->info7;
+ }
+
+ if (info12) {
+ status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
+ domain_handle,
+ 12,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info12 = dom_info->info12;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_0 *info0)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info1;
+ struct samr_DomInfo3 dom_info3;
+
+ ZERO_STRUCTP(info0);
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info1,
+ &dom_info3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info0->usrmod0_min_passwd_len =
+ dom_info1.min_password_length;
+ info0->usrmod0_max_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
+ info0->usrmod0_min_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
+ info0->usrmod0_password_hist_len =
+ dom_info1.password_history_length;
+
+ info0->usrmod0_force_logoff =
+ nt_time_to_unix_abs(&dom_info3.force_logoff_time);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1 *info1)
+{
+ NTSTATUS status;
+ struct samr_DomInfo6 dom_info6;
+ struct samr_DomInfo7 dom_info7;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info6,
+ &dom_info7,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info1->usrmod1_primary =
+ talloc_strdup(mem_ctx, dom_info6.primary.string);
+
+ info1->usrmod1_role = dom_info7.role;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ struct USER_MODALS_INFO_2 *info2)
+{
+ NTSTATUS status;
+ struct samr_DomInfo5 dom_info5;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ &dom_info5,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info2->usrmod2_domain_name =
+ talloc_strdup(mem_ctx, dom_info5.domain_name.string);
+ info2->usrmod2_domain_id =
+ (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
+
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_3 *info3)
+{
+ NTSTATUS status;
+ struct samr_DomInfo12 dom_info12;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info12);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info3->usrmod3_lockout_duration =
+ nt_time_to_unix_abs(&dom_info12.lockout_duration);
+ info3->usrmod3_lockout_observation_window =
+ nt_time_to_unix_abs(&dom_info12.lockout_window);
+ info3->usrmod3_lockout_threshold =
+ dom_info12.lockout_threshold;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t level,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ uint8_t **buffer)
+{
+ NTSTATUS status;
+
+ struct USER_MODALS_INFO_0 info0;
+ struct USER_MODALS_INFO_1 info1;
+ struct USER_MODALS_INFO_2 info2;
+ struct USER_MODALS_INFO_3 info3;
+
+ if (!buffer) {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ switch (level) {
+ case 0:
+ status = query_USER_MODALS_INFO_0(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info0);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
+ sizeof(info0));
+ break;
+
+ case 1:
+ status = query_USER_MODALS_INFO_1(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
+ sizeof(info1));
+ break;
+ case 2:
+ status = query_USER_MODALS_INFO_2(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ domain_sid,
+ &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
+ sizeof(info2));
+ break;
+ case 3:
+ status = query_USER_MODALS_INFO_3(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
+ sizeof(info3));
+ break;
+ default:
+ break;
+ }
+
+ NT_STATUS_HAVE_NO_MEMORY(*buffer);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 1:
+ case 2:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 3:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ access_mask,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ /* 0: 1 + 3 */
+ /* 1: 6 + 7 */
+ /* 2: 5 */
+ /* 3: 12 (DomainInfo2) */
+
+ status = query_USER_MODALS_INFO_to_buffer(ctx,
+ pipe_cli,
+ r->in.level,
+ &domain_handle,
+ domain_sid,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsGet *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct samr_DomInfo1 *info1,
+ struct samr_DomInfo3 *info3,
+ struct samr_DomInfo12 *info12)
+{
+ NTSTATUS status;
+ union samr_DomainInfo dom_info;
+
+ if (info1) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info1 = *info1;
+
+ status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 1,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+
+ if (info3) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info3 = *info3;
+
+ status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 3,
+ &dom_info);
+
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+
+ if (info12) {
+
+ ZERO_STRUCT(dom_info);
+
+ dom_info.info12 = *info12;
+
+ status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 12,
+ &dom_info);
+
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_0 *info0)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+ struct samr_DomInfo3 dom_info_3;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ &dom_info_3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.min_password_length =
+ info0->usrmod0_min_passwd_len;
+ dom_info_1.password_history_length =
+ info0->usrmod0_password_hist_len;
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
+ info0->usrmod0_max_passwd_age);
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
+ info0->usrmod0_min_passwd_age);
+
+ unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
+ info0->usrmod0_force_logoff);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ &dom_info_3,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_3 *info3)
+{
+ NTSTATUS status;
+ struct samr_DomInfo12 dom_info_12;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info_12);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
+ info3->usrmod3_lockout_duration);
+ unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
+ info3->usrmod3_lockout_observation_window);
+ dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ &dom_info_12);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1001 *info1001)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.min_password_length =
+ info1001->usrmod1001_min_passwd_len;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1002 *info1002)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
+ info1002->usrmod1002_max_passwd_age);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1003 *info1003)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
+ info1003->usrmod1003_min_passwd_age);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1004 *info1004)
+{
+ NTSTATUS status;
+ struct samr_DomInfo3 dom_info_3;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ &dom_info_3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
+ info1004->usrmod1004_force_logoff);
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ &dom_info_3,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1005 *info1005)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info_1;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dom_info_1.password_history_length =
+ info1005->usrmod1005_password_hist_len;
+
+ return set_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info_1,
+ NULL,
+ NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t level,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ uint8_t *buffer)
+{
+ struct USER_MODALS_INFO_0 *info0;
+ struct USER_MODALS_INFO_3 *info3;
+ struct USER_MODALS_INFO_1001 *info1001;
+ struct USER_MODALS_INFO_1002 *info1002;
+ struct USER_MODALS_INFO_1003 *info1003;
+ struct USER_MODALS_INFO_1004 *info1004;
+ struct USER_MODALS_INFO_1005 *info1005;
+
+ if (!buffer) {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ switch (level) {
+ case 0:
+ info0 = (struct USER_MODALS_INFO_0 *)buffer;
+ return set_USER_MODALS_INFO_0_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info0);
+ case 3:
+ info3 = (struct USER_MODALS_INFO_3 *)buffer;
+ return set_USER_MODALS_INFO_3_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info3);
+ case 1001:
+ info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
+ return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1001);
+ case 1002:
+ info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
+ return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1002);
+ case 1003:
+ info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
+ return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1003);
+ case 1004:
+ info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
+ return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1004);
+ case 1005:
+ info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
+ return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ info1005);
+
+ default:
+ break;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_1 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_2;
+ break;
+ case 3:
+ case 1001:
+ case 1002:
+ case 1003:
+ case 1005:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_1;
+ break;
+ case 1004:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
+ SAMR_DOMAIN_ACCESS_SET_INFO_2;
+ break;
+ case 1:
+ case 2:
+ case 1006:
+ case 1007:
+ werr = WERR_NOT_SUPPORTED;
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ access_mask,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ status = set_USER_MODALS_INFO_buffer(ctx,
+ pipe_cli,
+ r->in.level,
+ &domain_handle,
+ domain_sid,
+ r->in.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
+ struct NetUserModalsSet *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
+}
+
+/****************************************************************
+****************************************************************/
+
+NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint32_t attributes,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct GROUP_USERS_INFO_0 u0;
+ struct GROUP_USERS_INFO_1 u1;
+
+ switch (level) {
+ case 0:
+ u0.grui0_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
+ (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
+ break;
+ case 1:
+ u1.grui1_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
+
+ u1.grui1_attributes = attributes;
+
+ ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
+ (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+ uint32_t *rids = NULL;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
break;
default:
return WERR_UNKNOWN_LEVEL;
}
- werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- status = rpccli_try_samr_connects(pipe_cli, ctx,
- SAMR_ACCESS_OPEN_DOMAIN |
- SAMR_ACCESS_ENUM_DOMAINS,
- &connect_handle);
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- status = rpccli_samr_EnumDomains(pipe_cli, ctx,
- &connect_handle,
- &dom_resume_handle,
- &sam,
- 0xffffffff,
- &num_entries);
+ status = rpccli_samr_OpenUser(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- for (i=0; i<num_entries; i++) {
+ status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
+ &user_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
- domain_name = sam->entries[i].name.string;
+ rids = talloc_array(ctx, uint32_t, rid_array->count);
+ if (!rids) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ rids[i] = rid_array->rids[i].rid;
+ }
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &domain_handle,
+ rid_array->count,
+ rids,
+ &names,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
- if (strequal(domain_name, builtin_domain_name())) {
- continue;
+ for (i=0; i < rid_array->count; i++) {
+ status = add_GROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ rid_array->rids[i].attributes,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
}
+ }
- domain_found = true;
- break;
+ if (r->out.entries_read) {
+ *r->out.entries_read = entries_read;
+ }
+ if (r->out.total_entries) {
+ *r->out.total_entries = entries_read;
}
- if (!domain_found) {
- werr = WERR_NO_SUCH_DOMAIN;
- goto done;
+ done:
+ if (!cli) {
+ return werr;
}
- init_lsa_String(&lsa_domain_name, domain_name);
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_Ids group_rids;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_String *lsa_names = NULL;
+
+ uint32_t *add_rids = NULL;
+ uint32_t *del_rids = NULL;
+ size_t num_add_rids = 0;
+ size_t num_del_rids = 0;
+
+ uint32_t *member_rids = NULL;
+ size_t num_member_rids = 0;
- status = rpccli_samr_LookupDomain(pipe_cli, ctx,
+ struct GROUP_USERS_INFO_0 *i0 = NULL;
+ struct GROUP_USERS_INFO_1 *i1 = NULL;
+
+ int i, k;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->in.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
&connect_handle,
- &lsa_domain_name,
+ &domain_handle,
&domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- status = rpccli_samr_OpenDomain(pipe_cli,
- ctx,
- &connect_handle,
- SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
- SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
- domain_sid,
- &domain_handle);
+ status = rpccli_samr_OpenUser(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
- ctx,
- &domain_handle,
- r->in.level,
- r->in.idx,
- r->in.entries_requested,
- r->in.prefmaxlen,
- &total_size,
- &returned_size,
- &info);
+ switch (r->in.level) {
+ case 0:
+ i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
+ break;
+ case 1:
+ i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
+ break;
+ }
+
+ lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
+ if (!lsa_names) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < r->in.num_entries; i++) {
+
+ switch (r->in.level) {
+ case 0:
+ init_lsa_String(&lsa_names[i], i0->grui0_name);
+ i0++;
+ break;
+ case 1:
+ init_lsa_String(&lsa_names[i], i1->grui1_name);
+ i1++;
+ break;
+ }
+ }
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ r->in.num_entries,
+ lsa_names,
+ &group_rids,
+ &name_types);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
- r->in.level,
- r->out.entries_read,
- r->out.buffer);
+ member_rids = group_rids.ids;
+ num_member_rids = group_rids.count;
+
+ status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
+ &user_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ /* add list */
+
+ for (i=0; i < r->in.num_entries; i++) {
+ bool already_member = false;
+ for (k=0; k < rid_array->count; k++) {
+ if (member_rids[i] == rid_array->rids[k].rid) {
+ already_member = true;
+ break;
+ }
+ }
+ if (!already_member) {
+ if (!add_rid_to_array_unique(ctx,
+ member_rids[i],
+ &add_rids, &num_add_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* del list */
+
+ for (k=0; k < rid_array->count; k++) {
+ bool keep_member = false;
+ for (i=0; i < r->in.num_entries; i++) {
+ if (member_rids[i] == rid_array->rids[k].rid) {
+ keep_member = true;
+ break;
+ }
+ }
+ if (!keep_member) {
+ if (!add_rid_to_array_unique(ctx,
+ rid_array->rids[k].rid,
+ &del_rids, &num_del_rids)) {
+ werr = WERR_GENERAL_FAILURE;
+ goto done;
+ }
+ }
+ }
+
+ /* add list */
+
+ for (i=0; i < num_add_rids; i++) {
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_ADD_MEMBER,
+ add_rids[i],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
+ &group_handle,
+ user_rids.ids[0],
+ 7 /* ? */);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+ }
+
+ /* del list */
+
+ for (i=0; i < num_del_rids; i++) {
+ status = rpccli_samr_OpenGroup(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_GROUP_ACCESS_REMOVE_MEMBER,
+ del_rids[i],
+ &group_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
+ &group_handle,
+ user_rids.ids[0]);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
+ }
+ }
+
+ werr = WERR_OK;
+
done:
if (!cli) {
return werr;
}
- if (is_valid_policy_hnd(&domain_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
+ if (is_valid_policy_hnd(&group_handle)) {
+ rpccli_samr_Close(pipe_cli, ctx, &group_handle);
}
- if (is_valid_policy_hnd(&connect_handle)) {
- rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
}
return werr;
+}
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserSetGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
}
/****************************************************************
****************************************************************/
+static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ const char *group_name,
+ uint8_t **buffer,
+ uint32_t *num_entries)
+{
+ struct LOCALGROUP_USERS_INFO_0 u0;
-WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
- struct NetQueryDisplayInformation *r)
+ switch (level) {
+ case 0:
+ u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
+ NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
+
+ ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
+ (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
+ break;
+ default:
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r)
{
- return WERR_NOT_SUPPORTED;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct policy_handle connect_handle, domain_handle, user_handle,
+ builtin_handle;
+ struct lsa_String lsa_account_name;
+ struct dom_sid2 *domain_sid = NULL;
+ struct samr_Ids user_rids, name_types;
+ struct samr_RidWithAttributeArray *rid_array = NULL;
+ struct lsa_Strings names;
+ struct samr_Ids types;
+ uint32_t *rids = NULL;
+ size_t num_rids = 0;
+ struct dom_sid user_sid;
+ struct lsa_SidArray sid_array;
+ struct samr_Ids domain_rids;
+ struct samr_Ids builtin_rids;
+
+ int i;
+ uint32_t entries_read = 0;
+
+ NTSTATUS status = NT_STATUS_OK;
+ WERROR werr;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ *r->out.buffer = NULL;
+ *r->out.entries_read = 0;
+
+ switch (r->in.level) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ werr = libnetapi_open_pipe(ctx, r->in.server_name,
+ &ndr_table_samr.syntax_id,
+ &cli,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
+ SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
+ &connect_handle,
+ &builtin_handle);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ init_lsa_String(&lsa_account_name, r->in.user_name);
+
+ status = rpccli_samr_LookupNames(pipe_cli, ctx,
+ &domain_handle,
+ 1,
+ &lsa_account_name,
+ &user_rids,
+ &name_types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_OpenUser(pipe_cli, ctx,
+ &domain_handle,
+ SAMR_USER_ACCESS_GET_GROUPS,
+ user_rids.ids[0],
+ &user_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
+ &user_handle,
+ &rid_array);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ sid_array.num_sids = rid_array->count + 1;
+ sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
+ if (!sid_array.sids) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
+ if (!sid_array.sids[0].sid) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (i=0; i < rid_array->count; i++) {
+ struct dom_sid sid;
+
+ if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
+ if (!sid_array.sids[i+1].sid) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
+ &domain_handle,
+ &sid_array,
+ &domain_rids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < domain_rids.count; i++) {
+ if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
+ &rids, &num_rids)) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
+ &builtin_handle,
+ &sid_array,
+ &builtin_rids);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < builtin_rids.count; i++) {
+ if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
+ &rids, &num_rids)) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+ }
+
+ status = rpccli_samr_LookupRids(pipe_cli, ctx,
+ &builtin_handle,
+ num_rids,
+ rids,
+ &names,
+ &types);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ for (i=0; i < names.count; i++) {
+ status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
+ r->in.level,
+ names.names[i].string,
+ r->out.buffer,
+ &entries_read);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+ }
+
+ if (r->out.entries_read) {
+ *r->out.entries_read = entries_read;
+ }
+ if (r->out.total_entries) {
+ *r->out.total_entries = entries_read;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
+ struct NetUserGetLocalGroups *r)
+{
+ LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
}