diff options
Diffstat (limited to 'source/lib/netapi')
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, + ¤t_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); } |