source: vendor/current/source4/libcli/util/clilsa.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 9.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 lsa calls for file sharing connections
5
6 Copyright (C) Andrew Tridgell 2004
7
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 3 of the License, or
11 (at your option) any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/*
23 when dealing with ACLs the file sharing client code needs to
24 sometimes make LSA RPC calls. This code provides an easy interface
25 for doing those calls.
26*/
27
28#include "includes.h"
29#include "libcli/raw/libcliraw.h"
30#include "libcli/libcli.h"
31#include "libcli/security/security.h"
32#include "librpc/gen_ndr/ndr_lsa.h"
33#include "librpc/gen_ndr/ndr_lsa_c.h"
34#include "libcli/util/clilsa.h"
35#include "libcli/smb/smbXcli_base.h"
36
37struct smblsa_state {
38 struct dcerpc_binding_handle *binding_handle;
39 struct smbcli_tree *ipc_tree;
40 struct policy_handle handle;
41};
42
43/*
44 establish the lsa pipe connection
45*/
46static NTSTATUS smblsa_connect(struct smbcli_state *cli)
47{
48 struct smblsa_state *lsa;
49 struct dcerpc_pipe *lsa_pipe;
50 NTSTATUS status;
51 struct lsa_OpenPolicy r;
52 uint16_t system_name = '\\';
53 union smb_tcon tcon;
54 struct lsa_ObjectAttribute attr;
55 struct lsa_QosInfo qos;
56
57 if (cli->lsa != NULL) {
58 return NT_STATUS_OK;
59 }
60
61 lsa = talloc(cli, struct smblsa_state);
62 if (lsa == NULL) {
63 return NT_STATUS_NO_MEMORY;
64 }
65
66 lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, false);
67 if (lsa->ipc_tree == NULL) {
68 return NT_STATUS_NO_MEMORY;
69 }
70
71 /* connect to IPC$ */
72 tcon.generic.level = RAW_TCON_TCONX;
73 tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
74 tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
75 tcon.tconx.in.password = data_blob(NULL, 0);
76 tcon.tconx.in.path = "ipc$";
77 tcon.tconx.in.device = "IPC";
78 status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
79 if (!NT_STATUS_IS_OK(status)) {
80 talloc_free(lsa);
81 return status;
82 }
83 lsa->ipc_tree->tid = tcon.tconx.out.tid;
84
85 if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) {
86 smb1cli_session_protect_session_key(cli->session->smbXcli);
87 }
88
89 lsa_pipe = dcerpc_pipe_init(lsa, cli->transport->ev);
90 if (lsa_pipe == NULL) {
91 talloc_free(lsa);
92 return NT_STATUS_NO_MEMORY;
93 }
94
95 /* open the LSA pipe */
96 status = dcerpc_pipe_open_smb(lsa_pipe, lsa->ipc_tree, NDR_LSARPC_NAME);
97 if (!NT_STATUS_IS_OK(status)) {
98 talloc_free(lsa);
99 return status;
100 }
101
102 /* bind to the LSA pipe */
103 status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
104 if (!NT_STATUS_IS_OK(status)) {
105 talloc_free(lsa);
106 return status;
107 }
108 lsa->binding_handle = lsa_pipe->binding_handle;
109
110 /* open a lsa policy handle */
111 qos.len = 0;
112 qos.impersonation_level = 2;
113 qos.context_mode = 1;
114 qos.effective_only = 0;
115
116 attr.len = 0;
117 attr.root_dir = NULL;
118 attr.object_name = NULL;
119 attr.attributes = 0;
120 attr.sec_desc = NULL;
121 attr.sec_qos = &qos;
122
123 r.in.system_name = &system_name;
124 r.in.attr = &attr;
125 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
126 r.out.handle = &lsa->handle;
127
128 status = dcerpc_lsa_OpenPolicy_r(lsa->binding_handle, lsa, &r);
129 if (!NT_STATUS_IS_OK(status)) {
130 talloc_free(lsa);
131 return status;
132 }
133
134 if (!NT_STATUS_IS_OK(r.out.result)) {
135 talloc_free(lsa);
136 return r.out.result;
137 }
138
139 cli->lsa = lsa;
140
141 return NT_STATUS_OK;
142}
143
144
145/*
146 return the set of privileges for the given sid
147*/
148NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
149 TALLOC_CTX *mem_ctx,
150 struct lsa_RightSet *rights)
151{
152 NTSTATUS status;
153 struct lsa_EnumAccountRights r;
154
155 status = smblsa_connect(cli);
156 if (!NT_STATUS_IS_OK(status)) {
157 return status;
158 }
159
160 r.in.handle = &cli->lsa->handle;
161 r.in.sid = sid;
162 r.out.rights = rights;
163
164 status = dcerpc_lsa_EnumAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
165 if (!NT_STATUS_IS_OK(status)) {
166 return status;
167 }
168
169 return r.out.result;
170}
171
172
173/*
174 check if a named sid has a particular named privilege
175*/
176NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
177 const char *sid_str,
178 const char *privilege)
179{
180 struct lsa_RightSet rights;
181 NTSTATUS status;
182 TALLOC_CTX *mem_ctx = talloc_new(cli);
183 struct dom_sid *sid;
184 unsigned i;
185
186 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
187 if (sid == NULL) {
188 talloc_free(mem_ctx);
189 return NT_STATUS_INVALID_SID;
190 }
191
192 status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
193 if (!NT_STATUS_IS_OK(status)) {
194 talloc_free(mem_ctx);
195 return status;
196 }
197
198 for (i=0;i<rights.count;i++) {
199 if (strcmp(rights.names[i].string, privilege) == 0) {
200 talloc_free(mem_ctx);
201 return NT_STATUS_OK;
202 }
203 }
204
205 talloc_free(mem_ctx);
206 return NT_STATUS_NOT_FOUND;
207}
208
209
210/*
211 lookup a SID, returning its name
212*/
213NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
214 const char *sid_str,
215 TALLOC_CTX *mem_ctx,
216 const char **name)
217{
218 struct lsa_LookupSids r;
219 struct lsa_TransNameArray names;
220 struct lsa_SidArray sids;
221 struct lsa_RefDomainList *domains = NULL;
222 uint32_t count = 1;
223 NTSTATUS status;
224 struct dom_sid *sid;
225 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
226
227 status = smblsa_connect(cli);
228 if (!NT_STATUS_IS_OK(status)) {
229 return status;
230 }
231
232 sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
233 if (sid == NULL) {
234 return NT_STATUS_INVALID_SID;
235 }
236
237 names.count = 0;
238 names.names = NULL;
239
240 sids.num_sids = 1;
241 sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
242 sids.sids[0].sid = sid;
243
244 r.in.handle = &cli->lsa->handle;
245 r.in.sids = &sids;
246 r.in.names = &names;
247 r.in.level = 1;
248 r.in.count = &count;
249 r.out.count = &count;
250 r.out.names = &names;
251 r.out.domains = &domains;
252
253 status = dcerpc_lsa_LookupSids_r(cli->lsa->binding_handle, mem_ctx2, &r);
254 if (!NT_STATUS_IS_OK(status)) {
255 talloc_free(mem_ctx2);
256 return status;
257 }
258 if (!NT_STATUS_IS_OK(r.out.result)) {
259 talloc_free(mem_ctx2);
260 return r.out.result;
261 }
262 if (names.count != 1) {
263 talloc_free(mem_ctx2);
264 return NT_STATUS_INVALID_NETWORK_RESPONSE;
265 }
266 if (domains == NULL) {
267 talloc_free(mem_ctx2);
268 return NT_STATUS_INVALID_NETWORK_RESPONSE;
269 }
270 if (domains->count != 1) {
271 talloc_free(mem_ctx2);
272 return NT_STATUS_INVALID_NETWORK_RESPONSE;
273 }
274 if (names.names[0].sid_index != UINT32_MAX &&
275 names.names[0].sid_index >= domains->count)
276 {
277 talloc_free(mem_ctx2);
278 return NT_STATUS_INVALID_NETWORK_RESPONSE;
279 }
280
281 (*name) = talloc_asprintf(mem_ctx, "%s\\%s",
282 domains->domains[0].name.string,
283 names.names[0].name.string);
284
285 talloc_free(mem_ctx2);
286
287 return NT_STATUS_OK;
288}
289
290/*
291 lookup a name, returning its sid
292*/
293NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
294 const char *name,
295 TALLOC_CTX *mem_ctx,
296 const char **sid_str)
297{
298 struct lsa_LookupNames r;
299 struct lsa_TransSidArray sids;
300 struct lsa_String names;
301 struct lsa_RefDomainList *domains = NULL;
302 uint32_t count = 1;
303 NTSTATUS status;
304 struct dom_sid *sid;
305 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
306 uint32_t rid;
307
308 status = smblsa_connect(cli);
309 if (!NT_STATUS_IS_OK(status)) {
310 return status;
311 }
312
313 sids.count = 0;
314 sids.sids = NULL;
315
316 names.string = name;
317
318 r.in.handle = &cli->lsa->handle;
319 r.in.num_names = 1;
320 r.in.names = &names;
321 r.in.sids = &sids;
322 r.in.level = 1;
323 r.in.count = &count;
324 r.out.count = &count;
325 r.out.sids = &sids;
326 r.out.domains = &domains;
327
328 status = dcerpc_lsa_LookupNames_r(cli->lsa->binding_handle, mem_ctx2, &r);
329 if (!NT_STATUS_IS_OK(status)) {
330 talloc_free(mem_ctx2);
331 return status;
332 }
333 if (!NT_STATUS_IS_OK(r.out.result)) {
334 talloc_free(mem_ctx2);
335 return r.out.result;
336 }
337 if (sids.count != 1) {
338 talloc_free(mem_ctx2);
339 return NT_STATUS_INVALID_NETWORK_RESPONSE;
340 }
341 if (domains->count != 1) {
342 talloc_free(mem_ctx2);
343 return NT_STATUS_INVALID_NETWORK_RESPONSE;
344 }
345
346 sid = domains->domains[0].sid;
347 rid = sids.sids[0].rid;
348
349 (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u",
350 dom_sid_string(mem_ctx2, sid), rid);
351
352 talloc_free(mem_ctx2);
353
354 return NT_STATUS_OK;
355}
356
357
358/*
359 add a set of privileges to the given sid
360*/
361NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid,
362 TALLOC_CTX *mem_ctx,
363 struct lsa_RightSet *rights)
364{
365 NTSTATUS status;
366 struct lsa_AddAccountRights r;
367
368 status = smblsa_connect(cli);
369 if (!NT_STATUS_IS_OK(status)) {
370 return status;
371 }
372
373 r.in.handle = &cli->lsa->handle;
374 r.in.sid = sid;
375 r.in.rights = rights;
376
377 status = dcerpc_lsa_AddAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
378 if (!NT_STATUS_IS_OK(status)) {
379 return status;
380 }
381
382 return r.out.result;
383}
384
385/*
386 remove a set of privileges from the given sid
387*/
388NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid,
389 TALLOC_CTX *mem_ctx,
390 struct lsa_RightSet *rights)
391{
392 NTSTATUS status;
393 struct lsa_RemoveAccountRights r;
394
395 status = smblsa_connect(cli);
396 if (!NT_STATUS_IS_OK(status)) {
397 return status;
398 }
399
400 r.in.handle = &cli->lsa->handle;
401 r.in.sid = sid;
402 r.in.remove_all = 0;
403 r.in.rights = rights;
404
405 status = dcerpc_lsa_RemoveAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
406 if (!NT_STATUS_IS_OK(status)) {
407 return status;
408 }
409
410 return r.out.result;
411}
Note: See TracBrowser for help on using the repository browser.