r4073: - added a set of lsa helper routines to make lsa lookups that are
authorAndrew Tridgell <tridge@samba.org>
Mon, 6 Dec 2004 07:12:38 +0000 (07:12 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:06:23 +0000 (13:06 -0500)
  related to filesharing. For example, in order to manipulate ACLs
  properly its important to be able to call LookupSids, and to be able
  to lookup what privileges a SID has.

- added 3 new commands to smbclient "lookupname", "lookupsid" and
  "privileges"

source/client/client.c
source/client/config.mk
source/include/cli_context.h
source/include/structs.h
source/libcli/cliconnect.c
source/libcli/config.mk
source/libcli/util/clilsa.c [new file with mode: 0644]

index f17586f994a10ce5ee5724bcfb8bee9dcfab5ba6..1bad697da7289fa265b887cd8177b6ebd36b6afa 100644 (file)
@@ -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}},  
index a04bb43f29e5aa039beb463e98e56b7ab07c6178..a4abdcbaa6433b9cb04d349e0fc6f4487a29a40d 100644 (file)
@@ -10,6 +10,7 @@ REQUIRED_SUBSYSTEMS = \
                LIBCMDLINE \
                LIBBASIC \
                LIBSMB \
-               RPC_NDR_SRVSVC
+               RPC_NDR_SRVSVC \
+               LIBCLI_LSA
 # End BINARY smbclient
 #################################
index a8c3f2d2e11e286e8b281fd8a93279a96eb2d727..843e8e8ca942948f56cf0edc556801d4100b61ea 100644 (file)
@@ -28,4 +28,5 @@ struct smbcli_state {
        struct smbcli_session *session;
        struct smbcli_tree *tree;
        struct substitute_context *substitute;
+       struct smblsa_state *lsa;
 };
index 9a2c965671b6cb042efe4bb7a660986c8b63413b..46deaa52c73db0e91cfa340dece343cc7df94aa0 100644 (file)
@@ -127,3 +127,5 @@ struct security_acl;
 struct security_ace;
 
 typedef struct security_descriptor SEC_DESC;
+
+struct lsa_RightSet;
index 2c66a1b5b3e08005807a33a87314b1f657ee7634..6185ba7b7d0f737c8dc1c429f78fdb903e4f56cb 100644 (file)
@@ -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);
        }
index e48e5b5066ea2490dd4a582c4fbd09f8f1e1b0e2..853dea7f988fc6a381e51ceb8efbfe9976a5c023 100644 (file)
@@ -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/source/libcli/util/clilsa.c b/source/libcli/util/clilsa.c
new file mode 100644 (file)
index 0000000..c3c7f8c
--- /dev/null
@@ -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;    
+}