2 Unix SMB/CIFS implementation.
4 lsa calls for file sharing connections
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 when dealing with ACLs the file sharing client code needs to
25 sometimes make LSA RPC calls. This code provides an easy interface
26 for doing those calls.
30 #include "libcli/raw/libcliraw.h"
31 #include "libcli/libcli.h"
32 #include "libcli/security/proto.h"
33 #include "librpc/gen_ndr/ndr_security.h"
34 #include "librpc/gen_ndr/ndr_lsa.h"
35 #include "librpc/gen_ndr/ndr_lsa_c.h"
38 struct dcerpc_pipe *pipe;
39 struct smbcli_tree *ipc_tree;
40 struct policy_handle handle;
44 establish the lsa pipe connection
46 static NTSTATUS smblsa_connect(struct smbcli_state *cli)
48 struct smblsa_state *lsa;
50 struct lsa_OpenPolicy r;
51 uint16_t system_name = '\\';
53 struct lsa_ObjectAttribute attr;
54 struct lsa_QosInfo qos;
56 if (cli->lsa != NULL) {
60 lsa = talloc(cli, struct smblsa_state);
62 return NT_STATUS_NO_MEMORY;
65 lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, False);
66 if (lsa->ipc_tree == NULL) {
67 return NT_STATUS_NO_MEMORY;
71 tcon.generic.level = RAW_TCON_TCONX;
72 tcon.tconx.in.flags = 0;
73 tcon.tconx.in.password = data_blob(NULL, 0);
74 tcon.tconx.in.path = "ipc$";
75 tcon.tconx.in.device = "IPC";
76 status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
77 if (!NT_STATUS_IS_OK(status)) {
81 lsa->ipc_tree->tid = tcon.tconx.out.tid;
83 lsa->pipe = dcerpc_pipe_init(lsa, cli->transport->socket->event.ctx);
84 if (lsa->pipe == NULL) {
86 return NT_STATUS_NO_MEMORY;
89 /* open the LSA pipe */
90 status = dcerpc_pipe_open_smb(lsa->pipe->conn, lsa->ipc_tree, DCERPC_LSARPC_NAME);
91 if (!NT_STATUS_IS_OK(status)) {
96 /* bind to the LSA pipe */
97 status = dcerpc_bind_auth_none(lsa->pipe, &dcerpc_table_lsarpc);
98 if (!NT_STATUS_IS_OK(status)) {
104 /* open a lsa policy handle */
106 qos.impersonation_level = 2;
107 qos.context_mode = 1;
108 qos.effective_only = 0;
111 attr.root_dir = NULL;
112 attr.object_name = NULL;
114 attr.sec_desc = NULL;
117 r.in.system_name = &system_name;
119 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
120 r.out.handle = &lsa->handle;
122 status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r);
123 if (!NT_STATUS_IS_OK(status)) {
135 return the set of privileges for the given sid
137 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
139 struct lsa_RightSet *rights)
142 struct lsa_EnumAccountRights r;
144 status = smblsa_connect(cli);
145 if (!NT_STATUS_IS_OK(status)) {
149 r.in.handle = &cli->lsa->handle;
151 r.out.rights = rights;
153 return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r);
158 check if a named sid has a particular named privilege
160 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
162 const char *privilege)
164 struct lsa_RightSet rights;
166 TALLOC_CTX *mem_ctx = talloc_new(cli);
170 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
172 talloc_free(mem_ctx);
173 return NT_STATUS_INVALID_SID;
176 status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
177 if (!NT_STATUS_IS_OK(status)) {
178 talloc_free(mem_ctx);
182 for (i=0;i<rights.count;i++) {
183 if (strcmp(rights.names[i].string, privilege) == 0) {
184 talloc_free(mem_ctx);
189 talloc_free(mem_ctx);
190 return NT_STATUS_NOT_FOUND;
195 lookup a SID, returning its name
197 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
202 struct lsa_LookupSids r;
203 struct lsa_TransNameArray names;
204 struct lsa_SidArray sids;
208 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
210 status = smblsa_connect(cli);
211 if (!NT_STATUS_IS_OK(status)) {
215 sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
217 return NT_STATUS_INVALID_SID;
224 sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
225 sids.sids[0].sid = sid;
227 r.in.handle = &cli->lsa->handle;
232 r.out.count = &count;
233 r.out.names = &names;
235 status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r);
236 if (!NT_STATUS_IS_OK(status)) {
237 talloc_free(mem_ctx2);
240 if (names.count != 1) {
241 talloc_free(mem_ctx2);
242 return NT_STATUS_UNSUCCESSFUL;
245 (*name) = talloc_asprintf(mem_ctx, "%s\\%s",
246 r.out.domains->domains[0].name.string,
247 names.names[0].name.string);
249 talloc_free(mem_ctx2);
255 lookup a name, returning its sid
257 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
260 const char **sid_str)
262 struct lsa_LookupNames r;
263 struct lsa_TransSidArray sids;
264 struct lsa_String names;
268 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
271 status = smblsa_connect(cli);
272 if (!NT_STATUS_IS_OK(status)) {
281 r.in.handle = &cli->lsa->handle;
287 r.out.count = &count;
290 status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r);
291 if (!NT_STATUS_IS_OK(status)) {
292 talloc_free(mem_ctx2);
295 if (sids.count != 1) {
296 talloc_free(mem_ctx2);
297 return NT_STATUS_UNSUCCESSFUL;
300 sid = r.out.domains->domains[0].sid;
301 rid = sids.sids[0].rid;
303 (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u",
304 dom_sid_string(mem_ctx2, sid), rid);
306 talloc_free(mem_ctx2);
313 add a set of privileges to the given sid
315 NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid,
317 struct lsa_RightSet *rights)
320 struct lsa_AddAccountRights r;
322 status = smblsa_connect(cli);
323 if (!NT_STATUS_IS_OK(status)) {
327 r.in.handle = &cli->lsa->handle;
329 r.in.rights = rights;
331 return dcerpc_lsa_AddAccountRights(cli->lsa->pipe, mem_ctx, &r);
335 remove a set of privileges from the given sid
337 NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid,
339 struct lsa_RightSet *rights)
342 struct lsa_RemoveAccountRights r;
344 status = smblsa_connect(cli);
345 if (!NT_STATUS_IS_OK(status)) {
349 r.in.handle = &cli->lsa->handle;
352 r.in.rights = rights;
354 return dcerpc_lsa_RemoveAccountRights(cli->lsa->pipe, mem_ctx, &r);