r21535: - fixed a crash in the RAW-ACLS test. When a dcerpc_pipe is created
[Samba.git] / source / libcli / util / clilsa.c
blobcd9a02deb1b15ac62efb1600cbc0646b7c23e1a4
1 /*
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.
29 #include "includes.h"
30 #include "libcli/raw/libcliraw.h"
31 #include "libcli/libcli.h"
32 #include "libcli/security/security.h"
33 #include "librpc/gen_ndr/ndr_lsa.h"
34 #include "librpc/gen_ndr/ndr_lsa_c.h"
36 struct smblsa_state {
37 struct dcerpc_pipe *pipe;
38 struct smbcli_tree *ipc_tree;
39 struct policy_handle handle;
43 establish the lsa pipe connection
45 static NTSTATUS smblsa_connect(struct smbcli_state *cli)
47 struct smblsa_state *lsa;
48 NTSTATUS status;
49 struct lsa_OpenPolicy r;
50 uint16_t system_name = '\\';
51 union smb_tcon tcon;
52 struct lsa_ObjectAttribute attr;
53 struct lsa_QosInfo qos;
55 if (cli->lsa != NULL) {
56 return NT_STATUS_OK;
59 lsa = talloc(cli, struct smblsa_state);
60 if (lsa == NULL) {
61 return NT_STATUS_NO_MEMORY;
64 lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, False);
65 if (lsa->ipc_tree == NULL) {
66 return NT_STATUS_NO_MEMORY;
69 /* connect to IPC$ */
70 tcon.generic.level = RAW_TCON_TCONX;
71 tcon.tconx.in.flags = 0;
72 tcon.tconx.in.password = data_blob(NULL, 0);
73 tcon.tconx.in.path = "ipc$";
74 tcon.tconx.in.device = "IPC";
75 status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
76 if (!NT_STATUS_IS_OK(status)) {
77 talloc_free(lsa);
78 return status;
80 lsa->ipc_tree->tid = tcon.tconx.out.tid;
82 lsa->pipe = dcerpc_pipe_init(lsa, cli->transport->socket->event.ctx);
83 if (lsa->pipe == NULL) {
84 talloc_free(lsa);
85 return NT_STATUS_NO_MEMORY;
88 /* open the LSA pipe */
89 status = dcerpc_pipe_open_smb(lsa->pipe, lsa->ipc_tree, DCERPC_LSARPC_NAME);
90 if (!NT_STATUS_IS_OK(status)) {
91 talloc_free(lsa);
92 return status;
95 /* bind to the LSA pipe */
96 status = dcerpc_bind_auth_none(lsa->pipe, &dcerpc_table_lsarpc);
97 if (!NT_STATUS_IS_OK(status)) {
98 talloc_free(lsa);
99 return status;
103 /* open a lsa policy handle */
104 qos.len = 0;
105 qos.impersonation_level = 2;
106 qos.context_mode = 1;
107 qos.effective_only = 0;
109 attr.len = 0;
110 attr.root_dir = NULL;
111 attr.object_name = NULL;
112 attr.attributes = 0;
113 attr.sec_desc = NULL;
114 attr.sec_qos = &qos;
116 r.in.system_name = &system_name;
117 r.in.attr = &attr;
118 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
119 r.out.handle = &lsa->handle;
121 status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r);
122 if (!NT_STATUS_IS_OK(status)) {
123 talloc_free(lsa);
124 return status;
127 cli->lsa = lsa;
129 return NT_STATUS_OK;
134 return the set of privileges for the given sid
136 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
137 TALLOC_CTX *mem_ctx,
138 struct lsa_RightSet *rights)
140 NTSTATUS status;
141 struct lsa_EnumAccountRights r;
143 status = smblsa_connect(cli);
144 if (!NT_STATUS_IS_OK(status)) {
145 return status;
148 r.in.handle = &cli->lsa->handle;
149 r.in.sid = sid;
150 r.out.rights = rights;
152 return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r);
157 check if a named sid has a particular named privilege
159 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
160 const char *sid_str,
161 const char *privilege)
163 struct lsa_RightSet rights;
164 NTSTATUS status;
165 TALLOC_CTX *mem_ctx = talloc_new(cli);
166 struct dom_sid *sid;
167 unsigned i;
169 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
170 if (sid == NULL) {
171 talloc_free(mem_ctx);
172 return NT_STATUS_INVALID_SID;
175 status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
176 if (!NT_STATUS_IS_OK(status)) {
177 talloc_free(mem_ctx);
178 return status;
181 for (i=0;i<rights.count;i++) {
182 if (strcmp(rights.names[i].string, privilege) == 0) {
183 talloc_free(mem_ctx);
184 return NT_STATUS_OK;
188 talloc_free(mem_ctx);
189 return NT_STATUS_NOT_FOUND;
194 lookup a SID, returning its name
196 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
197 const char *sid_str,
198 TALLOC_CTX *mem_ctx,
199 const char **name)
201 struct lsa_LookupSids r;
202 struct lsa_TransNameArray names;
203 struct lsa_SidArray sids;
204 uint32_t count = 1;
205 NTSTATUS status;
206 struct dom_sid *sid;
207 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
209 status = smblsa_connect(cli);
210 if (!NT_STATUS_IS_OK(status)) {
211 return status;
214 sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
215 if (sid == NULL) {
216 return NT_STATUS_INVALID_SID;
219 names.count = 0;
220 names.names = NULL;
222 sids.num_sids = 1;
223 sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
224 sids.sids[0].sid = sid;
226 r.in.handle = &cli->lsa->handle;
227 r.in.sids = &sids;
228 r.in.names = &names;
229 r.in.level = 1;
230 r.in.count = &count;
231 r.out.count = &count;
232 r.out.names = &names;
234 status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r);
235 if (!NT_STATUS_IS_OK(status)) {
236 talloc_free(mem_ctx2);
237 return status;
239 if (names.count != 1) {
240 talloc_free(mem_ctx2);
241 return NT_STATUS_UNSUCCESSFUL;
244 (*name) = talloc_asprintf(mem_ctx, "%s\\%s",
245 r.out.domains->domains[0].name.string,
246 names.names[0].name.string);
248 talloc_free(mem_ctx2);
250 return NT_STATUS_OK;
254 lookup a name, returning its sid
256 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
257 const char *name,
258 TALLOC_CTX *mem_ctx,
259 const char **sid_str)
261 struct lsa_LookupNames r;
262 struct lsa_TransSidArray sids;
263 struct lsa_String names;
264 uint32_t count = 1;
265 NTSTATUS status;
266 struct dom_sid *sid;
267 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
268 uint32_t rid;
270 status = smblsa_connect(cli);
271 if (!NT_STATUS_IS_OK(status)) {
272 return status;
275 sids.count = 0;
276 sids.sids = NULL;
278 names.string = name;
280 r.in.handle = &cli->lsa->handle;
281 r.in.num_names = 1;
282 r.in.names = &names;
283 r.in.sids = &sids;
284 r.in.level = 1;
285 r.in.count = &count;
286 r.out.count = &count;
287 r.out.sids = &sids;
289 status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r);
290 if (!NT_STATUS_IS_OK(status)) {
291 talloc_free(mem_ctx2);
292 return status;
294 if (sids.count != 1) {
295 talloc_free(mem_ctx2);
296 return NT_STATUS_UNSUCCESSFUL;
299 sid = r.out.domains->domains[0].sid;
300 rid = sids.sids[0].rid;
302 (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u",
303 dom_sid_string(mem_ctx2, sid), rid);
305 talloc_free(mem_ctx2);
307 return NT_STATUS_OK;
312 add a set of privileges to the given sid
314 NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid,
315 TALLOC_CTX *mem_ctx,
316 struct lsa_RightSet *rights)
318 NTSTATUS status;
319 struct lsa_AddAccountRights r;
321 status = smblsa_connect(cli);
322 if (!NT_STATUS_IS_OK(status)) {
323 return status;
326 r.in.handle = &cli->lsa->handle;
327 r.in.sid = sid;
328 r.in.rights = rights;
330 return dcerpc_lsa_AddAccountRights(cli->lsa->pipe, mem_ctx, &r);
334 remove a set of privileges from the given sid
336 NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid,
337 TALLOC_CTX *mem_ctx,
338 struct lsa_RightSet *rights)
340 NTSTATUS status;
341 struct lsa_RemoveAccountRights r;
343 status = smblsa_connect(cli);
344 if (!NT_STATUS_IS_OK(status)) {
345 return status;
348 r.in.handle = &cli->lsa->handle;
349 r.in.sid = sid;
350 r.in.unknown = 0;
351 r.in.rights = rights;
353 return dcerpc_lsa_RemoveAccountRights(cli->lsa->pipe, mem_ctx, &r);