diff options
-rw-r--r-- | source4/client/client.c | 110 | ||||
-rw-r--r-- | source4/client/config.mk | 3 | ||||
-rw-r--r-- | source4/include/cli_context.h | 1 | ||||
-rw-r--r-- | source4/include/structs.h | 2 | ||||
-rw-r--r-- | source4/libcli/cliconnect.c | 2 | ||||
-rw-r--r-- | source4/libcli/config.mk | 4 | ||||
-rw-r--r-- | source4/libcli/util/clilsa.c | 299 |
7 files changed, 419 insertions, 2 deletions
diff --git a/source4/client/client.c b/source4/client/client.c index f17586f994..1bad697da7 100644 --- a/source4/client/client.c +++ b/source4/client/client.c @@ -26,6 +26,7 @@ #include "clilist.h" #include "lib/cmdline/popt_common.h" #include "librpc/gen_ndr/ndr_srvsvc.h" +#include "librpc/gen_ndr/ndr_lsa.h" #include "libcli/raw/libcliraw.h" #include "system/time.h" #include "system/dir.h" @@ -1835,6 +1836,112 @@ done: return ret; } +/**************************************************************************** +lookup a sid +****************************************************************************/ +static int cmd_lookupsid(const char **cmd_ptr) +{ + fstring buf; + TALLOC_CTX *mem_ctx = talloc(NULL, 0); + NTSTATUS status; + const char *name; + + if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + d_printf("lookupsid <sid>\n"); + talloc_free(mem_ctx); + return 1; + } + + status = smblsa_lookup_sid(cli, buf, mem_ctx, &name); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupSids - %s\n", nt_errstr(status)); + talloc_free(mem_ctx); + return 1; + } + + d_printf("%s\n", name); + + talloc_free(mem_ctx); + + return 0; +} + +/**************************************************************************** +lookup a name, showing sid +****************************************************************************/ +static int cmd_lookupname(const char **cmd_ptr) +{ + fstring buf; + TALLOC_CTX *mem_ctx = talloc(NULL, 0); + NTSTATUS status; + const char *sid; + + if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + d_printf("lookupname <name>\n"); + talloc_free(mem_ctx); + return 1; + } + + status = smblsa_lookup_name(cli, buf, mem_ctx, &sid); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + talloc_free(mem_ctx); + return 1; + } + + d_printf("%s\n", sid); + + talloc_free(mem_ctx); + + return 0; +} + +/**************************************************************************** +show privileges for a user +****************************************************************************/ +static int cmd_privileges(const char **cmd_ptr) +{ + fstring buf; + TALLOC_CTX *mem_ctx = talloc(NULL, 0); + NTSTATUS status; + struct dom_sid *sid; + struct lsa_RightSet rights; + unsigned i; + + if (!next_token(cmd_ptr,buf,NULL,sizeof(buf))) { + d_printf("lookupsid <sid>\n"); + talloc_free(mem_ctx); + return 1; + } + + sid = dom_sid_parse_talloc(mem_ctx, buf); + if (sid == NULL) { + const char *sid_str; + status = smblsa_lookup_name(cli, buf, mem_ctx, &sid_str); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_LookupNames - %s\n", nt_errstr(status)); + talloc_free(mem_ctx); + return 1; + } + sid = dom_sid_parse_talloc(mem_ctx, sid_str); + } + + status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights); + if (!NT_STATUS_IS_OK(status)) { + d_printf("lsa_EnumAccountRights - %s\n", nt_errstr(status)); + talloc_free(mem_ctx); + return 1; + } + + for (i=0;i<rights.count;i++) { + d_printf("\t%s\n", rights.names[i].string); + } + + talloc_free(mem_ctx); + + return 0; +} + /**************************************************************************** ****************************************************************************/ @@ -2403,6 +2510,8 @@ static struct {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}}, {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}}, {"link",cmd_link,"<src> <dest> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}}, + {"lookupname",cmd_lookupname,"<name> show SID for name",{COMPL_NONE,COMPL_NONE}}, + {"lookupsid",cmd_lookupsid,"<sid> show name for SID",{COMPL_NONE,COMPL_NONE}}, {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}}, {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}}, {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}}, @@ -2413,6 +2522,7 @@ static struct {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}}, {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}}, {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}}, + {"privileges",cmd_privileges,"<user> show privileges for a user",{COMPL_NONE,COMPL_NONE}}, {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}}, {"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}}, {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}}, diff --git a/source4/client/config.mk b/source4/client/config.mk index a04bb43f29..a4abdcbaa6 100644 --- a/source4/client/config.mk +++ b/source4/client/config.mk @@ -10,6 +10,7 @@ REQUIRED_SUBSYSTEMS = \ LIBCMDLINE \ LIBBASIC \ LIBSMB \ - RPC_NDR_SRVSVC + RPC_NDR_SRVSVC \ + LIBCLI_LSA # End BINARY smbclient ################################# diff --git a/source4/include/cli_context.h b/source4/include/cli_context.h index a8c3f2d2e1..843e8e8ca9 100644 --- a/source4/include/cli_context.h +++ b/source4/include/cli_context.h @@ -28,4 +28,5 @@ struct smbcli_state { struct smbcli_session *session; struct smbcli_tree *tree; struct substitute_context *substitute; + struct smblsa_state *lsa; }; diff --git a/source4/include/structs.h b/source4/include/structs.h index 9a2c965671..46deaa52c7 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -127,3 +127,5 @@ struct security_acl; struct security_ace; typedef struct security_descriptor SEC_DESC; + +struct lsa_RightSet; diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c index 2c66a1b5b3..6185ba7b7d 100644 --- a/source4/libcli/cliconnect.c +++ b/source4/libcli/cliconnect.c @@ -216,7 +216,7 @@ struct smbcli_state *smbcli_state_init(TALLOC_CTX *mem_ctx) { struct smbcli_state *cli; - cli = talloc_p(mem_ctx, struct smbcli_state); + cli = talloc_zero_p(mem_ctx, struct smbcli_state); if (cli) { ZERO_STRUCTP(cli); } diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index e48e5b5066..853dea7f98 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -13,6 +13,10 @@ ADD_OBJ_FILES = libcli/unexpected.o \ libcli/namecache.o \ libcli/nmblib.o \ libcli/namequery.o +REQUIRED_SUBSYSTEMS = RPC_NDR_LSA + +[SUBSYSTEM::LIBCLI_LSA] +ADD_OBJ_FILES = libcli/util/clilsa.o [SUBSYSTEM::LIBCLI] REQUIRED_SUBSYSTEMS = LIBCLI_RAW LIBCLI_UTILS LIBCLI_AUTH LIBCLI_NMB diff --git a/source4/libcli/util/clilsa.c b/source4/libcli/util/clilsa.c new file mode 100644 index 0000000000..c3c7f8cc77 --- /dev/null +++ b/source4/libcli/util/clilsa.c @@ -0,0 +1,299 @@ +/* + Unix SMB/CIFS implementation. + + lsa calls for file sharing connections + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + when dealing with ACLs the file sharing client code needs to + sometimes make LSA RPC calls. This code provides an easy interface + for doing those calls. +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "librpc/gen_ndr/ndr_lsa.h" + +struct smblsa_state { + struct dcerpc_pipe *pipe; + struct smbcli_tree *ipc_tree; + struct policy_handle handle; +}; + +/* + establish the lsa pipe connection +*/ +static NTSTATUS smblsa_connect(struct smbcli_state *cli) +{ + struct smblsa_state *lsa; + NTSTATUS status; + struct lsa_OpenPolicy r; + uint16_t system_name = '\\'; + union smb_tcon tcon; + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + + if (cli->lsa != NULL) { + return NT_STATUS_OK; + } + + lsa = talloc_p(cli, struct smblsa_state); + if (lsa == NULL) { + return NT_STATUS_NO_MEMORY; + } + + lsa->ipc_tree = smbcli_tree_init(cli->session); + if (lsa->ipc_tree == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* connect to IPC$ */ + tcon.generic.level = RAW_TCON_TCONX; + tcon.tconx.in.flags = 0; + tcon.tconx.in.password = data_blob(NULL, 0); + tcon.tconx.in.path = "ipc$"; + tcon.tconx.in.device = "IPC"; + status = smb_tree_connect(lsa->ipc_tree, lsa, &tcon); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lsa); + return status; + } + lsa->ipc_tree->tid = tcon.tconx.out.cnum; + + /* open the LSA pipe */ + status = dcerpc_pipe_open_smb(&lsa->pipe, lsa->ipc_tree, DCERPC_LSARPC_NAME); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lsa); + return status; + } + + /* bind to the LSA pipe */ + status = dcerpc_bind_auth_none(lsa->pipe, DCERPC_LSARPC_UUID, DCERPC_LSARPC_VERSION); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lsa); + return status; + } + + + /* open a lsa policy handle */ + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = &system_name; + r.in.attr = &attr; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.handle = &lsa->handle; + + status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lsa); + return status; + } + + cli->lsa = lsa; + + return NT_STATUS_OK; +} + + +/* + return the set of privileges for the given sid +*/ +NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid, + TALLOC_CTX *mem_ctx, + struct lsa_RightSet *rights) +{ + NTSTATUS status; + struct lsa_EnumAccountRights r; + + status = smblsa_connect(cli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + r.in.handle = &cli->lsa->handle; + r.in.sid = sid; + r.out.rights = rights; + + return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r); +} + + +/* + check if a named sid has a particular named privilege +*/ +NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli, + const char *sid_str, + const char *privilege) +{ + struct lsa_RightSet rights; + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc(cli, 0); + struct dom_sid *sid; + unsigned i; + + sid = dom_sid_parse_talloc(mem_ctx, sid_str); + if (sid == NULL) { + talloc_free(mem_ctx); + return NT_STATUS_INVALID_SID; + } + + status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); + return status; + } + + for (i=0;i<rights.count;i++) { + if (strcmp(rights.names[i].string, privilege) == 0) { + talloc_free(mem_ctx); + return NT_STATUS_OK; + } + } + + talloc_free(mem_ctx); + return NT_STATUS_NOT_FOUND; +} + + +/* + lookup a SID, returning its name +*/ +NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli, + const char *sid_str, + TALLOC_CTX *mem_ctx, + const char **name) +{ + struct lsa_LookupSids r; + struct lsa_TransNameArray names; + struct lsa_SidArray sids; + uint32_t count = 1; + NTSTATUS status; + struct dom_sid *sid; + TALLOC_CTX *mem_ctx2 = talloc(mem_ctx, 0); + + status = smblsa_connect(cli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + sid = dom_sid_parse_talloc(mem_ctx2, sid_str); + if (sid == NULL) { + return NT_STATUS_INVALID_SID; + } + + names.count = 0; + names.names = NULL; + + sids.num_sids = 1; + sids.sids = talloc_p(mem_ctx2, struct lsa_SidPtr); + sids.sids[0].sid = sid; + + r.in.handle = &cli->lsa->handle; + r.in.sids = &sids; + r.in.names = &names; + r.in.level = 1; + r.in.count = &count; + r.out.count = &count; + r.out.names = &names; + + status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx2); + return status; + } + if (names.count != 1) { + talloc_free(mem_ctx2); + return NT_STATUS_UNSUCCESSFUL; + } + + (*name) = talloc_asprintf(mem_ctx, "%s\\%s", + r.out.domains->domains[0].name.string, + names.names[0].name.string); + + talloc_free(mem_ctx2); + + return NT_STATUS_OK; +} + +/* + lookup a name, returning its sid +*/ +NTSTATUS smblsa_lookup_name(struct smbcli_state *cli, + const char *name, + TALLOC_CTX *mem_ctx, + const char **sid_str) +{ + struct lsa_LookupNames r; + struct lsa_TransSidArray sids; + struct lsa_String names; + uint32_t count = 1; + NTSTATUS status; + struct dom_sid *sid; + TALLOC_CTX *mem_ctx2 = talloc(mem_ctx, 0); + uint32_t rid; + + status = smblsa_connect(cli); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + sids.count = 0; + sids.sids = NULL; + + names.string = name; + + r.in.handle = &cli->lsa->handle; + r.in.num_names = 1; + r.in.names = &names; + r.in.sids = &sids; + r.in.level = 1; + r.in.count = &count; + r.out.count = &count; + r.out.sids = &sids; + + status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx2); + return status; + } + if (sids.count != 1) { + talloc_free(mem_ctx2); + return NT_STATUS_UNSUCCESSFUL; + } + + sid = r.out.domains->domains[0].sid; + rid = sids.sids[0].rid; + + (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u", + dom_sid_string(mem_ctx2, sid), rid); + + talloc_free(mem_ctx2); + + return NT_STATUS_OK; +} |