Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : RPC pipe client
4 : Copyright (C) Tim Potter 2000-2001,
5 : Copyright (C) Andrew Tridgell 1992-1997,2000,
6 : Copyright (C) Rafal Szczesniak 2002
7 : Copyright (C) Jeremy Allison 2005.
8 : Copyright (C) Michael Adam 2007.
9 : Copyright (C) Guenther Deschner 2008.
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "rpc_client/rpc_client.h"
27 : #include "../librpc/gen_ndr/ndr_lsa_c.h"
28 : #include "rpc_client/cli_lsarpc.h"
29 : #include "rpc_client/init_lsa.h"
30 : #include "../libcli/security/security.h"
31 : #include "lsa.h"
32 :
33 : /** @defgroup lsa LSA - Local Security Architecture
34 : * @ingroup rpc_client
35 : *
36 : * @{
37 : **/
38 :
39 : /**
40 : * @file cli_lsarpc.c
41 : *
42 : * RPC client routines for the LSA RPC pipe. LSA means "local
43 : * security authority", which is half of a password database.
44 : **/
45 :
46 8500 : NTSTATUS dcerpc_lsa_open_policy(struct dcerpc_binding_handle *h,
47 : TALLOC_CTX *mem_ctx,
48 : bool sec_qos,
49 : uint32_t des_access,
50 : struct policy_handle *pol,
51 : NTSTATUS *result)
52 : {
53 8500 : struct lsa_ObjectAttribute attr = { .len = 0x18, };
54 0 : struct lsa_QosInfo qos;
55 8500 : uint16_t system_name = '\\';
56 :
57 8500 : if (sec_qos) {
58 7556 : qos.len = 0xc;
59 7556 : qos.impersonation_level = 2;
60 7556 : qos.context_mode = 1;
61 7556 : qos.effective_only = 0;
62 :
63 7556 : attr.sec_qos = &qos;
64 : }
65 :
66 8500 : return dcerpc_lsa_OpenPolicy(h,
67 : mem_ctx,
68 : &system_name,
69 : &attr,
70 : des_access,
71 : pol,
72 : result);
73 : }
74 :
75 : /** Open a LSA policy handle
76 : *
77 : * @param cli Handle on an initialised SMB connection */
78 :
79 8500 : NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli,
80 : TALLOC_CTX *mem_ctx,
81 : bool sec_qos, uint32_t des_access,
82 : struct policy_handle *pol)
83 : {
84 0 : NTSTATUS status;
85 8500 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
86 :
87 8500 : status = dcerpc_lsa_open_policy(cli->binding_handle,
88 : mem_ctx,
89 : sec_qos,
90 : des_access,
91 : pol,
92 : &result);
93 8500 : if (!NT_STATUS_IS_OK(status)) {
94 0 : return status;
95 : }
96 :
97 8500 : return result;
98 : }
99 :
100 0 : NTSTATUS dcerpc_lsa_open_policy2(struct dcerpc_binding_handle *h,
101 : TALLOC_CTX *mem_ctx,
102 : const char *srv_name_slash,
103 : bool sec_qos,
104 : uint32_t des_access,
105 : struct policy_handle *pol,
106 : NTSTATUS *result)
107 : {
108 0 : struct lsa_ObjectAttribute attr = { .len = 0x18, };
109 0 : struct lsa_QosInfo qos;
110 :
111 0 : if (sec_qos) {
112 0 : qos.len = 0xc;
113 0 : qos.impersonation_level = 2;
114 0 : qos.context_mode = 1;
115 0 : qos.effective_only = 0;
116 :
117 0 : attr.sec_qos = &qos;
118 : }
119 :
120 0 : return dcerpc_lsa_OpenPolicy2(h,
121 : mem_ctx,
122 : srv_name_slash,
123 : &attr,
124 : des_access,
125 : pol,
126 : result);
127 : }
128 :
129 48 : NTSTATUS dcerpc_lsa_open_policy3(struct dcerpc_binding_handle *h,
130 : TALLOC_CTX *mem_ctx,
131 : const char *srv_name_slash,
132 : bool sec_qos,
133 : uint32_t des_access,
134 : uint32_t *out_version,
135 : union lsa_revision_info *out_revision_info,
136 : struct policy_handle *pol,
137 : NTSTATUS *result)
138 : {
139 48 : struct lsa_ObjectAttribute attr = { .len = 0x18, };
140 0 : struct lsa_QosInfo qos;
141 48 : union lsa_revision_info in_revision_info = {
142 : .info1 = {
143 : .revision = 1,
144 : },
145 : };
146 48 : uint32_t in_version = 1;
147 :
148 48 : if (sec_qos) {
149 44 : qos.len = 0xc;
150 44 : qos.impersonation_level = 2;
151 44 : qos.context_mode = 1;
152 44 : qos.effective_only = 0;
153 :
154 44 : attr.sec_qos = &qos;
155 : }
156 :
157 48 : return dcerpc_lsa_OpenPolicy3(h,
158 : mem_ctx,
159 : srv_name_slash,
160 : &attr,
161 : des_access,
162 : in_version,
163 : &in_revision_info,
164 : out_version,
165 : out_revision_info,
166 : pol,
167 : result);
168 : }
169 :
170 48 : NTSTATUS dcerpc_lsa_open_policy_fallback(struct dcerpc_binding_handle *h,
171 : TALLOC_CTX *mem_ctx,
172 : const char *srv_name_slash,
173 : bool sec_qos,
174 : uint32_t desired_access,
175 : uint32_t *out_version,
176 : union lsa_revision_info *out_revision_info,
177 : struct policy_handle *pol,
178 : NTSTATUS *result)
179 : {
180 0 : NTSTATUS status;
181 :
182 48 : status = dcerpc_lsa_open_policy3(h,
183 : mem_ctx,
184 : srv_name_slash,
185 : sec_qos,
186 : desired_access,
187 : out_version,
188 : out_revision_info,
189 : pol,
190 : result);
191 48 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
192 0 : *out_version = 1;
193 0 : *out_revision_info = (union lsa_revision_info) {
194 : .info1 = {
195 : .revision = 1,
196 : }
197 : };
198 :
199 0 : status = dcerpc_lsa_open_policy2(h,
200 : mem_ctx,
201 : srv_name_slash,
202 : sec_qos,
203 : desired_access,
204 : pol,
205 : result);
206 : }
207 :
208 48 : return status;
209 : }
210 :
211 : /* Lookup a list of sids
212 : *
213 : * internal version withOUT memory allocation of the target arrays.
214 : * this assumes sufficiently sized arrays to store domains, names and types. */
215 :
216 7074 : static NTSTATUS dcerpc_lsa_lookup_sids_noalloc(struct dcerpc_binding_handle *h,
217 : TALLOC_CTX *mem_ctx,
218 : TALLOC_CTX *domains_ctx,
219 : TALLOC_CTX *names_ctx,
220 : struct policy_handle *pol,
221 : int num_sids,
222 : const struct dom_sid *sids,
223 : enum lsa_LookupNamesLevel level,
224 : char **domains,
225 : char **names,
226 : enum lsa_SidType *types,
227 : bool use_lookupsids3,
228 : NTSTATUS *presult)
229 : {
230 0 : NTSTATUS status;
231 7074 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
232 0 : struct lsa_SidArray sid_array;
233 7074 : struct lsa_RefDomainList *ref_domains = NULL;
234 7074 : struct lsa_TransNameArray lsa_names = { .count = 0, };
235 7074 : uint32_t count = 0;
236 0 : int i;
237 :
238 7074 : sid_array.num_sids = num_sids;
239 7074 : sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids);
240 7074 : if (sid_array.sids == NULL) {
241 0 : return NT_STATUS_NO_MEMORY;
242 : }
243 :
244 14156 : for (i = 0; i<num_sids; i++) {
245 7082 : sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[i]);
246 7082 : if (!sid_array.sids[i].sid) {
247 0 : return NT_STATUS_NO_MEMORY;
248 : }
249 : }
250 :
251 7074 : if (use_lookupsids3) {
252 0 : struct lsa_TransNameArray2 lsa_names2;
253 0 : uint32_t n;
254 :
255 0 : ZERO_STRUCT(lsa_names2);
256 :
257 0 : status = dcerpc_lsa_LookupSids3(h,
258 : mem_ctx,
259 : &sid_array,
260 : &ref_domains,
261 : &lsa_names2,
262 : level,
263 : &count,
264 : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
265 : LSA_CLIENT_REVISION_2,
266 : &result);
267 0 : if (!NT_STATUS_IS_OK(status)) {
268 0 : return status;
269 : }
270 :
271 0 : if (!NT_STATUS_LOOKUP_ERR(result)) {
272 0 : lsa_names.count = lsa_names2.count;
273 0 : lsa_names.names = talloc_array(mem_ctx,
274 : struct lsa_TranslatedName,
275 : lsa_names.count);
276 0 : if (lsa_names.names == NULL) {
277 0 : return NT_STATUS_NO_MEMORY;
278 : }
279 0 : for (n=0; n < lsa_names.count; n++) {
280 0 : lsa_names.names[n].sid_type = lsa_names2.names[n].sid_type;
281 0 : lsa_names.names[n].name = lsa_names2.names[n].name;
282 0 : lsa_names.names[n].sid_index = lsa_names2.names[n].sid_index;
283 : }
284 : }
285 :
286 : } else {
287 7074 : status = dcerpc_lsa_LookupSids(h,
288 : mem_ctx,
289 : pol,
290 : &sid_array,
291 : &ref_domains,
292 : &lsa_names,
293 : level,
294 : &count,
295 : &result);
296 : }
297 :
298 7074 : DEBUG(10, ("LSA_LOOKUPSIDS returned status: '%s', result: '%s', "
299 : "mapped count = %d'\n",
300 : nt_errstr(status), nt_errstr(result), count));
301 :
302 7074 : if (!NT_STATUS_IS_OK(status)) {
303 0 : return status;
304 : }
305 :
306 7074 : if (NT_STATUS_LOOKUP_ERR(result)) {
307 0 : *presult = result;
308 0 : return status;
309 : }
310 :
311 : /* Return output parameters */
312 7074 : if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
313 7074 : (count == 0))
314 : {
315 0 : for (i = 0; i < num_sids; i++) {
316 0 : (names)[i] = NULL;
317 0 : (domains)[i] = NULL;
318 0 : (types)[i] = SID_NAME_UNKNOWN;
319 : }
320 0 : *presult = NT_STATUS_NONE_MAPPED;
321 0 : return status;
322 : }
323 :
324 14156 : for (i = 0; i < num_sids; i++) {
325 0 : const char *name, *dom_name;
326 0 : uint32_t dom_idx;
327 :
328 7082 : if (i >= lsa_names.count) {
329 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
330 0 : return status;
331 : }
332 :
333 7082 : dom_idx = lsa_names.names[i].sid_index;
334 :
335 : /* Translate optimised name through domain index array */
336 :
337 7082 : if (dom_idx != 0xffffffff) {
338 7074 : if (ref_domains == NULL) {
339 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
340 0 : return status;
341 : }
342 7074 : if (dom_idx >= ref_domains->count) {
343 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
344 0 : return status;
345 : }
346 :
347 7074 : dom_name = ref_domains->domains[dom_idx].name.string;
348 7074 : name = lsa_names.names[i].name.string;
349 :
350 7074 : if (name) {
351 7074 : (names)[i] = talloc_strdup(names_ctx, name);
352 7074 : if ((names)[i] == NULL) {
353 0 : DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n"));
354 0 : *presult = NT_STATUS_UNSUCCESSFUL;
355 0 : return status;
356 : }
357 : } else {
358 0 : (names)[i] = NULL;
359 : }
360 7074 : domains[i] = talloc_strdup(domains_ctx,
361 : dom_name ? dom_name : "");
362 7074 : (types)[i] = lsa_names.names[i].sid_type;
363 7074 : if ((domains)[i] == NULL) {
364 0 : DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n"));
365 0 : *presult = NT_STATUS_UNSUCCESSFUL;
366 0 : return status;
367 : }
368 :
369 : } else {
370 8 : (names)[i] = NULL;
371 8 : (domains)[i] = NULL;
372 8 : (types)[i] = SID_NAME_UNKNOWN;
373 : }
374 : }
375 :
376 7074 : *presult = NT_STATUS_OK;
377 7074 : return status;
378 : }
379 :
380 : /* Lookup a list of sids
381 : *
382 : * do it the right way: there is a limit (of 20480 for w2k3) entries
383 : * returned by this call. when the sids list contains more entries,
384 : * empty lists are returned. This version of lsa_lookup_sids passes
385 : * the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call. */
386 :
387 : /* This constant defines the limit of how many sids to look up
388 : * in one call (maximum). the limit from the server side is
389 : * at 20480 for win2k3, but we keep it at a save 1000 for now. */
390 : #define LOOKUP_SIDS_HUNK_SIZE 1000
391 :
392 7074 : NTSTATUS dcerpc_lsa_lookup_sids_generic(struct dcerpc_binding_handle *h,
393 : TALLOC_CTX *mem_ctx,
394 : struct policy_handle *pol,
395 : int num_sids,
396 : const struct dom_sid *sids,
397 : enum lsa_LookupNamesLevel level,
398 : char ***pdomains,
399 : char ***pnames,
400 : enum lsa_SidType **ptypes,
401 : bool use_lookupsids3,
402 : NTSTATUS *presult)
403 : {
404 7074 : NTSTATUS status = NT_STATUS_OK;
405 7074 : NTSTATUS result = NT_STATUS_OK;
406 7074 : int sids_left = 0;
407 7074 : int sids_processed = 0;
408 7074 : const struct dom_sid *hunk_sids = sids;
409 0 : char **hunk_domains;
410 0 : char **hunk_names;
411 0 : enum lsa_SidType *hunk_types;
412 7074 : char **domains = NULL;
413 7074 : char **names = NULL;
414 7074 : enum lsa_SidType *types = NULL;
415 7074 : bool have_mapped = false;
416 7074 : bool have_unmapped = false;
417 :
418 7074 : if (num_sids) {
419 7074 : domains = talloc_zero_array(mem_ctx, char *, num_sids);
420 7074 : if (domains == NULL) {
421 0 : DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
422 0 : status = NT_STATUS_NO_MEMORY;
423 0 : goto fail;
424 : }
425 :
426 7074 : names = talloc_zero_array(mem_ctx, char *, num_sids);
427 7074 : if (names == NULL) {
428 0 : DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
429 0 : status = NT_STATUS_NO_MEMORY;
430 0 : goto fail;
431 : }
432 :
433 7074 : types = talloc_zero_array(mem_ctx, enum lsa_SidType, num_sids);
434 7074 : if (types == NULL) {
435 0 : DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
436 0 : status = NT_STATUS_NO_MEMORY;
437 0 : goto fail;
438 : }
439 : }
440 :
441 7074 : sids_left = num_sids;
442 7074 : hunk_domains = domains;
443 7074 : hunk_names = names;
444 7074 : hunk_types = types;
445 :
446 14148 : while (sids_left > 0) {
447 0 : int hunk_num_sids;
448 7074 : NTSTATUS hunk_result = NT_STATUS_UNSUCCESSFUL;
449 :
450 7074 : hunk_num_sids = ((sids_left > LOOKUP_SIDS_HUNK_SIZE)
451 : ? LOOKUP_SIDS_HUNK_SIZE
452 : : sids_left);
453 :
454 7074 : DEBUG(10, ("rpccli_lsa_lookup_sids: processing items "
455 : "%d -- %d of %d.\n",
456 : sids_processed,
457 : sids_processed + hunk_num_sids - 1,
458 : num_sids));
459 :
460 7074 : status = dcerpc_lsa_lookup_sids_noalloc(h,
461 : mem_ctx,
462 : (TALLOC_CTX *)domains,
463 : (TALLOC_CTX *)names,
464 : pol,
465 : hunk_num_sids,
466 : hunk_sids,
467 : level,
468 : hunk_domains,
469 : hunk_names,
470 : hunk_types,
471 : use_lookupsids3,
472 : &hunk_result);
473 7074 : if (!NT_STATUS_IS_OK(status)) {
474 0 : goto fail;
475 : }
476 :
477 7074 : if (!NT_STATUS_IS_OK(hunk_result) &&
478 0 : !NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED) &&
479 0 : !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED))
480 : {
481 : /* An actual error occurred */
482 0 : *presult = hunk_result;
483 0 : goto fail;
484 : }
485 :
486 7074 : if (NT_STATUS_IS_OK(hunk_result)) {
487 7074 : have_mapped = true;
488 : }
489 7074 : if (NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)) {
490 0 : have_unmapped = true;
491 : }
492 7074 : if (NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED)) {
493 : int i;
494 0 : for (i=0; i<hunk_num_sids; i++) {
495 0 : if (hunk_types[i] == SID_NAME_UNKNOWN) {
496 0 : have_unmapped = true;
497 : } else {
498 0 : have_mapped = true;
499 : }
500 : }
501 : }
502 :
503 7074 : sids_left -= hunk_num_sids;
504 7074 : sids_processed += hunk_num_sids;
505 7074 : hunk_sids += hunk_num_sids;
506 7074 : hunk_domains += hunk_num_sids;
507 7074 : hunk_names += hunk_num_sids;
508 7074 : hunk_types += hunk_num_sids;
509 : }
510 :
511 7074 : *pdomains = domains;
512 7074 : *pnames = names;
513 7074 : *ptypes = types;
514 :
515 7074 : if (!have_mapped) {
516 0 : result = NT_STATUS_NONE_MAPPED;
517 : }
518 7074 : if (have_unmapped) {
519 0 : result = STATUS_SOME_UNMAPPED;
520 : }
521 7074 : *presult = result;
522 :
523 7074 : return status;
524 :
525 0 : fail:
526 0 : TALLOC_FREE(domains);
527 0 : TALLOC_FREE(names);
528 0 : TALLOC_FREE(types);
529 :
530 0 : return status;
531 : }
532 :
533 0 : NTSTATUS dcerpc_lsa_lookup_sids(struct dcerpc_binding_handle *h,
534 : TALLOC_CTX *mem_ctx,
535 : struct policy_handle *pol,
536 : int num_sids,
537 : const struct dom_sid *sids,
538 : char ***pdomains,
539 : char ***pnames,
540 : enum lsa_SidType **ptypes,
541 : NTSTATUS *result)
542 : {
543 0 : enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
544 0 : return dcerpc_lsa_lookup_sids_generic(h,
545 : mem_ctx,
546 : pol,
547 : num_sids,
548 : sids,
549 : level,
550 : pdomains,
551 : pnames,
552 : ptypes,
553 : false,
554 : result);
555 : }
556 :
557 7072 : NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
558 : TALLOC_CTX *mem_ctx,
559 : struct policy_handle *pol,
560 : int num_sids,
561 : const struct dom_sid *sids,
562 : char ***pdomains,
563 : char ***pnames,
564 : enum lsa_SidType **ptypes)
565 : {
566 0 : NTSTATUS status;
567 7072 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
568 7072 : enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
569 :
570 7072 : status = dcerpc_lsa_lookup_sids_generic(cli->binding_handle,
571 : mem_ctx,
572 : pol,
573 : num_sids,
574 : sids,
575 : level,
576 : pdomains,
577 : pnames,
578 : ptypes,
579 : false,
580 : &result);
581 7072 : if (!NT_STATUS_IS_OK(status)) {
582 0 : return status;
583 : }
584 :
585 7072 : return result;
586 : }
587 :
588 0 : NTSTATUS dcerpc_lsa_lookup_sids3(struct dcerpc_binding_handle *h,
589 : TALLOC_CTX *mem_ctx,
590 : struct policy_handle *pol,
591 : int num_sids,
592 : const struct dom_sid *sids,
593 : char ***pdomains,
594 : char ***pnames,
595 : enum lsa_SidType **ptypes,
596 : NTSTATUS *result)
597 : {
598 0 : enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
599 0 : return dcerpc_lsa_lookup_sids_generic(h,
600 : mem_ctx,
601 : pol,
602 : num_sids,
603 : sids,
604 : level,
605 : pdomains,
606 : pnames,
607 : ptypes,
608 : true,
609 : result);
610 : }
611 :
612 : /** Lookup a list of names */
613 :
614 1664 : NTSTATUS dcerpc_lsa_lookup_names_generic(struct dcerpc_binding_handle *h,
615 : TALLOC_CTX *mem_ctx,
616 : struct policy_handle *pol,
617 : uint32_t num_names,
618 : const char **names,
619 : const char ***dom_names,
620 : enum lsa_LookupNamesLevel level,
621 : struct dom_sid **sids,
622 : enum lsa_SidType **types,
623 : bool use_lookupnames4,
624 : NTSTATUS *presult)
625 : {
626 0 : NTSTATUS status;
627 1664 : struct lsa_String *lsa_names = NULL;
628 1664 : struct lsa_RefDomainList *domains = NULL;
629 1664 : struct lsa_TransSidArray sid_array = { .count = 0, };
630 1664 : struct lsa_TransSidArray3 sid_array3 = { .count = 0, };
631 1664 : uint32_t count = 0;
632 0 : uint32_t i;
633 :
634 1664 : lsa_names = talloc_array(mem_ctx, struct lsa_String, num_names);
635 1664 : if (lsa_names == NULL) {
636 0 : return NT_STATUS_NO_MEMORY;
637 : }
638 :
639 3328 : for (i = 0; i < num_names; i++) {
640 1664 : init_lsa_String(&lsa_names[i], names[i]);
641 : }
642 :
643 1664 : if (use_lookupnames4) {
644 0 : status = dcerpc_lsa_LookupNames4(h,
645 : mem_ctx,
646 : num_names,
647 : lsa_names,
648 : &domains,
649 : &sid_array3,
650 : level,
651 : &count,
652 : LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
653 : LSA_CLIENT_REVISION_2,
654 : presult);
655 : } else {
656 1664 : status = dcerpc_lsa_LookupNames(h,
657 : mem_ctx,
658 : pol,
659 : num_names,
660 : lsa_names,
661 : &domains,
662 : &sid_array,
663 : level,
664 : &count,
665 : presult);
666 : }
667 1664 : if (!NT_STATUS_IS_OK(status)) {
668 0 : goto done;
669 : }
670 :
671 1664 : if (!NT_STATUS_IS_OK(*presult) &&
672 22 : !NT_STATUS_EQUAL(*presult, STATUS_SOME_UNMAPPED)) {
673 : /* An actual error occurred */
674 22 : goto done;
675 : }
676 :
677 : /* Return output parameters */
678 1642 : if (count == 0) {
679 0 : *presult = NT_STATUS_NONE_MAPPED;
680 0 : goto done;
681 : }
682 :
683 1642 : if (num_names) {
684 1642 : *sids = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
685 1642 : if (*sids == NULL) {
686 0 : DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
687 0 : *presult = NT_STATUS_NO_MEMORY;
688 0 : goto done;
689 : }
690 :
691 1642 : *types = talloc_zero_array(mem_ctx, enum lsa_SidType, num_names);
692 1642 : if (*types == NULL) {
693 0 : DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
694 0 : *presult = NT_STATUS_NO_MEMORY;
695 0 : goto done;
696 : }
697 :
698 1642 : if (dom_names != NULL) {
699 0 : *dom_names = talloc_zero_array(mem_ctx, const char *, num_names);
700 0 : if (*dom_names == NULL) {
701 0 : DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
702 0 : *presult = NT_STATUS_NO_MEMORY;
703 0 : goto done;
704 : }
705 : }
706 : } else {
707 0 : *sids = NULL;
708 0 : *types = NULL;
709 0 : if (dom_names != NULL) {
710 0 : *dom_names = NULL;
711 : }
712 : }
713 :
714 3284 : for (i = 0; i < num_names; i++) {
715 0 : uint32_t dom_idx;
716 1642 : struct dom_sid *sid = &(*sids)[i];
717 :
718 1642 : if (use_lookupnames4) {
719 0 : if (i >= sid_array3.count) {
720 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
721 0 : goto done;
722 : }
723 :
724 0 : dom_idx = sid_array3.sids[i].sid_index;
725 0 : (*types)[i] = sid_array3.sids[i].sid_type;
726 : } else {
727 1642 : if (i >= sid_array.count) {
728 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
729 0 : goto done;
730 : }
731 :
732 1642 : dom_idx = sid_array.sids[i].sid_index;
733 1642 : (*types)[i] = sid_array.sids[i].sid_type;
734 : }
735 :
736 : /* Translate optimised sid through domain index array */
737 :
738 1642 : if (dom_idx == 0xffffffff) {
739 : /* Nothing to do, this is unknown */
740 0 : ZERO_STRUCTP(sid);
741 0 : (*types)[i] = SID_NAME_UNKNOWN;
742 0 : continue;
743 : }
744 1642 : if (domains == NULL) {
745 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
746 0 : goto done;
747 : }
748 1642 : if (dom_idx >= domains->count) {
749 0 : *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
750 0 : goto done;
751 : }
752 :
753 1642 : if (use_lookupnames4) {
754 0 : sid_copy(sid, sid_array3.sids[i].sid);
755 : } else {
756 1642 : sid_copy(sid, domains->domains[dom_idx].sid);
757 :
758 1642 : if (sid_array.sids[i].rid != 0xffffffff) {
759 1604 : sid_append_rid(sid, sid_array.sids[i].rid);
760 : }
761 : }
762 :
763 1642 : if (dom_names == NULL) {
764 1642 : continue;
765 : }
766 :
767 0 : (*dom_names)[i] = domains->domains[dom_idx].name.string;
768 : }
769 :
770 1642 : done:
771 1664 : return status;
772 : }
773 :
774 1664 : NTSTATUS dcerpc_lsa_lookup_names(struct dcerpc_binding_handle *h,
775 : TALLOC_CTX *mem_ctx,
776 : struct policy_handle *pol,
777 : uint32_t num_names,
778 : const char **names,
779 : const char ***dom_names,
780 : enum lsa_LookupNamesLevel level,
781 : struct dom_sid **sids,
782 : enum lsa_SidType **types,
783 : NTSTATUS *result)
784 : {
785 1664 : return dcerpc_lsa_lookup_names_generic(h,
786 : mem_ctx,
787 : pol,
788 : num_names,
789 : names,
790 : dom_names,
791 : level,
792 : sids,
793 : types,
794 : false,
795 : result);
796 : }
797 :
798 1664 : NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
799 : TALLOC_CTX *mem_ctx,
800 : struct policy_handle *pol,
801 : int num_names,
802 : const char **names,
803 : const char ***dom_names,
804 : int level,
805 : struct dom_sid **sids,
806 : enum lsa_SidType **types)
807 : {
808 0 : NTSTATUS status;
809 1664 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
810 :
811 1664 : status = dcerpc_lsa_lookup_names(cli->binding_handle,
812 : mem_ctx,
813 : pol,
814 : num_names,
815 : names,
816 : dom_names,
817 : level,
818 : sids,
819 : types,
820 : &result);
821 1664 : if (!NT_STATUS_IS_OK(status)) {
822 0 : return status;
823 : }
824 :
825 1664 : return result;
826 : }
827 :
828 0 : NTSTATUS dcerpc_lsa_lookup_names4(struct dcerpc_binding_handle *h,
829 : TALLOC_CTX *mem_ctx,
830 : struct policy_handle *pol,
831 : uint32_t num_names,
832 : const char **names,
833 : const char ***dom_names,
834 : enum lsa_LookupNamesLevel level,
835 : struct dom_sid **sids,
836 : enum lsa_SidType **types,
837 : NTSTATUS *result)
838 : {
839 0 : return dcerpc_lsa_lookup_names_generic(h,
840 : mem_ctx,
841 : pol,
842 : num_names,
843 : names,
844 : dom_names,
845 : level,
846 : sids,
847 : types,
848 : true,
849 : result);
850 : }
|