mdscli: correct handling of in-progress searches
[samba.git] / source3 / rpc_client / cli_lsarpc.c
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 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         struct lsa_ObjectAttribute attr = { .len = 0x18, };
54         struct lsa_QosInfo qos;
55         uint16_t system_name = '\\';
56
57         if (sec_qos) {
58                 qos.len                 = 0xc;
59                 qos.impersonation_level = 2;
60                 qos.context_mode        = 1;
61                 qos.effective_only      = 0;
62
63                 attr.sec_qos            = &qos;
64         }
65
66         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 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         NTSTATUS status;
85         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
86
87         status = dcerpc_lsa_open_policy(cli->binding_handle,
88                                         mem_ctx,
89                                         sec_qos,
90                                         des_access,
91                                         pol,
92                                         &result);
93         if (!NT_STATUS_IS_OK(status)) {
94                 return status;
95         }
96
97         return result;
98 }
99
100 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         struct lsa_ObjectAttribute attr = { .len = 0x18, };
109         struct lsa_QosInfo qos;
110
111         if (sec_qos) {
112                 qos.len                 = 0xc;
113                 qos.impersonation_level = 2;
114                 qos.context_mode        = 1;
115                 qos.effective_only      = 0;
116
117                 attr.sec_qos            = &qos;
118         }
119
120         return dcerpc_lsa_OpenPolicy2(h,
121                                       mem_ctx,
122                                       srv_name_slash,
123                                       &attr,
124                                       des_access,
125                                       pol,
126                                       result);
127 }
128
129 /** Open a LSA policy handle
130   *
131   * @param cli Handle on an initialised SMB connection
132   */
133
134 NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli,
135                                  TALLOC_CTX *mem_ctx, bool sec_qos,
136                                  uint32_t des_access, struct policy_handle *pol)
137 {
138         NTSTATUS status;
139         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
140
141         status = dcerpc_lsa_open_policy2(cli->binding_handle,
142                                          mem_ctx,
143                                          cli->srv_name_slash,
144                                          sec_qos,
145                                          des_access,
146                                          pol,
147                                          &result);
148         if (!NT_STATUS_IS_OK(status)) {
149                 return status;
150         }
151
152         return result;
153 }
154
155 /* Lookup a list of sids
156  *
157  * internal version withOUT memory allocation of the target arrays.
158  * this assumes sufficiently sized arrays to store domains, names and types. */
159
160 static NTSTATUS dcerpc_lsa_lookup_sids_noalloc(struct dcerpc_binding_handle *h,
161                                                TALLOC_CTX *mem_ctx,
162                                                TALLOC_CTX *domains_ctx,
163                                                TALLOC_CTX *names_ctx,
164                                                struct policy_handle *pol,
165                                                int num_sids,
166                                                const struct dom_sid *sids,
167                                                enum lsa_LookupNamesLevel level,
168                                                char **domains,
169                                                char **names,
170                                                enum lsa_SidType *types,
171                                                bool use_lookupsids3,
172                                                NTSTATUS *presult)
173 {
174         NTSTATUS status;
175         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
176         struct lsa_SidArray sid_array;
177         struct lsa_RefDomainList *ref_domains = NULL;
178         struct lsa_TransNameArray lsa_names = { .count = 0, };
179         uint32_t count = 0;
180         int i;
181
182         sid_array.num_sids = num_sids;
183         sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids);
184         if (sid_array.sids == NULL) {
185                 return NT_STATUS_NO_MEMORY;
186         }
187
188         for (i = 0; i<num_sids; i++) {
189                 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[i]);
190                 if (!sid_array.sids[i].sid) {
191                         return NT_STATUS_NO_MEMORY;
192                 }
193         }
194
195         if (use_lookupsids3) {
196                 struct lsa_TransNameArray2 lsa_names2;
197                 uint32_t n;
198
199                 ZERO_STRUCT(lsa_names2);
200
201                 status = dcerpc_lsa_LookupSids3(h,
202                                                 mem_ctx,
203                                                 &sid_array,
204                                                 &ref_domains,
205                                                 &lsa_names2,
206                                                 level,
207                                                 &count,
208                                                 LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
209                                                 LSA_CLIENT_REVISION_2,
210                                                 &result);
211                 if (!NT_STATUS_IS_OK(status)) {
212                         return status;
213                 }
214
215                 if (!NT_STATUS_LOOKUP_ERR(result)) {
216                         lsa_names.count = lsa_names2.count;
217                         lsa_names.names = talloc_array(mem_ctx,
218                                                        struct lsa_TranslatedName,
219                                                        lsa_names.count);
220                         if (lsa_names.names == NULL) {
221                                 return NT_STATUS_NO_MEMORY;
222                         }
223                         for (n=0; n < lsa_names.count; n++) {
224                                 lsa_names.names[n].sid_type     = lsa_names2.names[n].sid_type;
225                                 lsa_names.names[n].name         = lsa_names2.names[n].name;
226                                 lsa_names.names[n].sid_index    = lsa_names2.names[n].sid_index;
227                         }
228                 }
229
230         } else {
231                 status = dcerpc_lsa_LookupSids(h,
232                                                mem_ctx,
233                                                pol,
234                                                &sid_array,
235                                                &ref_domains,
236                                                &lsa_names,
237                                                level,
238                                                &count,
239                                                &result);
240         }
241
242         DEBUG(10, ("LSA_LOOKUPSIDS returned status: '%s', result: '%s', "
243                    "mapped count = %d'\n",
244                    nt_errstr(status), nt_errstr(result), count));
245
246         if (!NT_STATUS_IS_OK(status)) {
247                 return status;
248         }
249
250         if (NT_STATUS_LOOKUP_ERR(result)) {
251                 *presult = result;
252                 return status;
253         }
254
255         /* Return output parameters */
256         if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
257             (count == 0))
258         {
259                 for (i = 0; i < num_sids; i++) {
260                         (names)[i] = NULL;
261                         (domains)[i] = NULL;
262                         (types)[i] = SID_NAME_UNKNOWN;
263                 }
264                 *presult = NT_STATUS_NONE_MAPPED;
265                 return status;
266         }
267
268         for (i = 0; i < num_sids; i++) {
269                 const char *name, *dom_name;
270                 uint32_t dom_idx;
271
272                 if (i >= lsa_names.count) {
273                         *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
274                         return status;
275                 }
276
277                 dom_idx = lsa_names.names[i].sid_index;
278
279                 /* Translate optimised name through domain index array */
280
281                 if (dom_idx != 0xffffffff) {
282                         if (ref_domains == NULL) {
283                                 *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
284                                 return status;
285                         }
286                         if (dom_idx >= ref_domains->count) {
287                                 *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
288                                 return status;
289                         }
290
291                         dom_name = ref_domains->domains[dom_idx].name.string;
292                         name = lsa_names.names[i].name.string;
293
294                         if (name) {
295                                 (names)[i] = talloc_strdup(names_ctx, name);
296                                 if ((names)[i] == NULL) {
297                                         DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n"));
298                                         *presult = NT_STATUS_UNSUCCESSFUL;
299                                         return status;
300                                 }
301                         } else {
302                                 (names)[i] = NULL;
303                         }
304                         domains[i] = talloc_strdup(domains_ctx,
305                                                    dom_name ? dom_name : "");
306                         (types)[i] = lsa_names.names[i].sid_type;
307                         if ((domains)[i] == NULL) {
308                                 DEBUG(0, ("cli_lsa_lookup_sids_noalloc(): out of memory\n"));
309                                 *presult = NT_STATUS_UNSUCCESSFUL;
310                                 return status;
311                         }
312
313                 } else {
314                         (names)[i] = NULL;
315                         (domains)[i] = NULL;
316                         (types)[i] = SID_NAME_UNKNOWN;
317                 }
318         }
319
320         *presult = NT_STATUS_OK;
321         return status;
322 }
323
324 /* Lookup a list of sids
325  *
326  * do it the right way: there is a limit (of 20480 for w2k3) entries
327  * returned by this call. when the sids list contains more entries,
328  * empty lists are returned. This version of lsa_lookup_sids passes
329  * the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call. */
330
331 /* This constant defines the limit of how many sids to look up
332  * in one call (maximum). the limit from the server side is
333  * at 20480 for win2k3, but we keep it at a save 1000 for now. */
334 #define LOOKUP_SIDS_HUNK_SIZE 1000
335
336 NTSTATUS dcerpc_lsa_lookup_sids_generic(struct dcerpc_binding_handle *h,
337                                         TALLOC_CTX *mem_ctx,
338                                         struct policy_handle *pol,
339                                         int num_sids,
340                                         const struct dom_sid *sids,
341                                         enum lsa_LookupNamesLevel level,
342                                         char ***pdomains,
343                                         char ***pnames,
344                                         enum lsa_SidType **ptypes,
345                                         bool use_lookupsids3,
346                                         NTSTATUS *presult)
347 {
348         NTSTATUS status = NT_STATUS_OK;
349         NTSTATUS result = NT_STATUS_OK;
350         int sids_left = 0;
351         int sids_processed = 0;
352         const struct dom_sid *hunk_sids = sids;
353         char **hunk_domains;
354         char **hunk_names;
355         enum lsa_SidType *hunk_types;
356         char **domains = NULL;
357         char **names = NULL;
358         enum lsa_SidType *types = NULL;
359         bool have_mapped = false;
360         bool have_unmapped = false;
361
362         if (num_sids) {
363                 domains = talloc_zero_array(mem_ctx, char *, num_sids);
364                 if (domains == NULL) {
365                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
366                         status = NT_STATUS_NO_MEMORY;
367                         goto fail;
368                 }
369
370                 names = talloc_zero_array(mem_ctx, char *, num_sids);
371                 if (names == NULL) {
372                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
373                         status = NT_STATUS_NO_MEMORY;
374                         goto fail;
375                 }
376
377                 types = talloc_zero_array(mem_ctx, enum lsa_SidType, num_sids);
378                 if (types == NULL) {
379                         DEBUG(0, ("rpccli_lsa_lookup_sids(): out of memory\n"));
380                         status = NT_STATUS_NO_MEMORY;
381                         goto fail;
382                 }
383         }
384
385         sids_left = num_sids;
386         hunk_domains = domains;
387         hunk_names = names;
388         hunk_types = types;
389
390         while (sids_left > 0) {
391                 int hunk_num_sids;
392                 NTSTATUS hunk_result = NT_STATUS_UNSUCCESSFUL;
393
394                 hunk_num_sids = ((sids_left > LOOKUP_SIDS_HUNK_SIZE)
395                                 ? LOOKUP_SIDS_HUNK_SIZE
396                                 : sids_left);
397
398                 DEBUG(10, ("rpccli_lsa_lookup_sids: processing items "
399                            "%d -- %d of %d.\n",
400                            sids_processed,
401                            sids_processed + hunk_num_sids - 1,
402                            num_sids));
403
404                 status = dcerpc_lsa_lookup_sids_noalloc(h,
405                                                         mem_ctx,
406                                                         (TALLOC_CTX *)domains,
407                                                         (TALLOC_CTX *)names,
408                                                         pol,
409                                                         hunk_num_sids,
410                                                         hunk_sids,
411                                                         level,
412                                                         hunk_domains,
413                                                         hunk_names,
414                                                         hunk_types,
415                                                         use_lookupsids3,
416                                                         &hunk_result);
417                 if (!NT_STATUS_IS_OK(status)) {
418                         goto fail;
419                 }
420
421                 if (!NT_STATUS_IS_OK(hunk_result) &&
422                     !NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED) &&
423                     !NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED))
424                 {
425                         /* An actual error occurred */
426                         *presult = hunk_result;
427                         goto fail;
428                 }
429
430                 if (NT_STATUS_IS_OK(hunk_result)) {
431                         have_mapped = true;
432                 }
433                 if (NT_STATUS_EQUAL(hunk_result, NT_STATUS_NONE_MAPPED)) {
434                         have_unmapped = true;
435                 }
436                 if (NT_STATUS_EQUAL(hunk_result, STATUS_SOME_UNMAPPED)) {
437                         int i;
438                         for (i=0; i<hunk_num_sids; i++) {
439                                 if (hunk_types[i] == SID_NAME_UNKNOWN) {
440                                         have_unmapped = true;
441                                 } else {
442                                         have_mapped = true;
443                                 }
444                         }
445                 }
446
447                 sids_left -= hunk_num_sids;
448                 sids_processed += hunk_num_sids;
449                 hunk_sids += hunk_num_sids;
450                 hunk_domains += hunk_num_sids;
451                 hunk_names += hunk_num_sids;
452                 hunk_types += hunk_num_sids;
453         }
454
455         *pdomains = domains;
456         *pnames = names;
457         *ptypes = types;
458
459         if (!have_mapped) {
460                 result = NT_STATUS_NONE_MAPPED;
461         }
462         if (have_unmapped) {
463                 result = STATUS_SOME_UNMAPPED;
464         }
465         *presult = result;
466
467         return status;
468
469 fail:
470         TALLOC_FREE(domains);
471         TALLOC_FREE(names);
472         TALLOC_FREE(types);
473
474         return status;
475 }
476
477 NTSTATUS dcerpc_lsa_lookup_sids(struct dcerpc_binding_handle *h,
478                                 TALLOC_CTX *mem_ctx,
479                                 struct policy_handle *pol,
480                                 int num_sids,
481                                 const struct dom_sid *sids,
482                                 char ***pdomains,
483                                 char ***pnames,
484                                 enum lsa_SidType **ptypes,
485                                 NTSTATUS *result)
486 {
487         enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
488         return dcerpc_lsa_lookup_sids_generic(h,
489                                               mem_ctx,
490                                               pol,
491                                               num_sids,
492                                               sids,
493                                               level,
494                                               pdomains,
495                                               pnames,
496                                               ptypes,
497                                               false,
498                                               result);
499 }
500
501 NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
502                                 TALLOC_CTX *mem_ctx,
503                                 struct policy_handle *pol,
504                                 int num_sids,
505                                 const struct dom_sid *sids,
506                                 char ***pdomains,
507                                 char ***pnames,
508                                 enum lsa_SidType **ptypes)
509 {
510         NTSTATUS status;
511         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
512         enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
513
514         status = dcerpc_lsa_lookup_sids_generic(cli->binding_handle,
515                                                 mem_ctx,
516                                                 pol,
517                                                 num_sids,
518                                                 sids,
519                                                 level,
520                                                 pdomains,
521                                                 pnames,
522                                                 ptypes,
523                                                 false,
524                                                 &result);
525         if (!NT_STATUS_IS_OK(status)) {
526                 return status;
527         }
528
529         return result;
530 }
531
532 NTSTATUS dcerpc_lsa_lookup_sids3(struct dcerpc_binding_handle *h,
533                                  TALLOC_CTX *mem_ctx,
534                                  struct policy_handle *pol,
535                                  int num_sids,
536                                  const struct dom_sid *sids,
537                                  char ***pdomains,
538                                  char ***pnames,
539                                  enum lsa_SidType **ptypes,
540                                  NTSTATUS *result)
541 {
542         enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL;
543         return dcerpc_lsa_lookup_sids_generic(h,
544                                               mem_ctx,
545                                               pol,
546                                               num_sids,
547                                               sids,
548                                               level,
549                                               pdomains,
550                                               pnames,
551                                               ptypes,
552                                               true,
553                                               result);
554 }
555
556 /** Lookup a list of names */
557
558 NTSTATUS dcerpc_lsa_lookup_names_generic(struct dcerpc_binding_handle *h,
559                                          TALLOC_CTX *mem_ctx,
560                                          struct policy_handle *pol,
561                                          uint32_t num_names,
562                                          const char **names,
563                                          const char ***dom_names,
564                                          enum lsa_LookupNamesLevel level,
565                                          struct dom_sid **sids,
566                                          enum lsa_SidType **types,
567                                          bool use_lookupnames4,
568                                          NTSTATUS *presult)
569 {
570         NTSTATUS status;
571         struct lsa_String *lsa_names = NULL;
572         struct lsa_RefDomainList *domains = NULL;
573         struct lsa_TransSidArray sid_array = { .count = 0, };
574         struct lsa_TransSidArray3 sid_array3 = { .count = 0, };
575         uint32_t count = 0;
576         uint32_t i;
577
578         lsa_names = talloc_array(mem_ctx, struct lsa_String, num_names);
579         if (lsa_names == NULL) {
580                 return NT_STATUS_NO_MEMORY;
581         }
582
583         for (i = 0; i < num_names; i++) {
584                 init_lsa_String(&lsa_names[i], names[i]);
585         }
586
587         if (use_lookupnames4) {
588                 status = dcerpc_lsa_LookupNames4(h,
589                                                  mem_ctx,
590                                                  num_names,
591                                                  lsa_names,
592                                                  &domains,
593                                                  &sid_array3,
594                                                  level,
595                                                  &count,
596                                                  LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES,
597                                                  LSA_CLIENT_REVISION_2,
598                                                  presult);
599         } else {
600                 status = dcerpc_lsa_LookupNames(h,
601                                                 mem_ctx,
602                                                 pol,
603                                                 num_names,
604                                                 lsa_names,
605                                                 &domains,
606                                                 &sid_array,
607                                                 level,
608                                                 &count,
609                                                 presult);
610         }
611         if (!NT_STATUS_IS_OK(status)) {
612                 goto done;
613         }
614
615         if (!NT_STATUS_IS_OK(*presult) &&
616             !NT_STATUS_EQUAL(*presult, STATUS_SOME_UNMAPPED)) {
617                 /* An actual error occurred */
618                 goto done;
619         }
620
621         /* Return output parameters */
622         if (count == 0) {
623                 *presult = NT_STATUS_NONE_MAPPED;
624                 goto done;
625         }
626
627         if (num_names) {
628                 *sids = talloc_zero_array(mem_ctx, struct dom_sid, num_names);
629                 if (*sids == NULL) {
630                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
631                         *presult = NT_STATUS_NO_MEMORY;
632                         goto done;
633                 }
634
635                 *types = talloc_zero_array(mem_ctx, enum lsa_SidType, num_names);
636                 if (*types == NULL) {
637                         DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
638                         *presult = NT_STATUS_NO_MEMORY;
639                         goto done;
640                 }
641
642                 if (dom_names != NULL) {
643                         *dom_names = talloc_zero_array(mem_ctx, const char *, num_names);
644                         if (*dom_names == NULL) {
645                                 DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
646                                 *presult = NT_STATUS_NO_MEMORY;
647                                 goto done;
648                         }
649                 }
650         } else {
651                 *sids = NULL;
652                 *types = NULL;
653                 if (dom_names != NULL) {
654                         *dom_names = NULL;
655                 }
656         }
657
658         for (i = 0; i < num_names; i++) {
659                 uint32_t dom_idx;
660                 struct dom_sid *sid = &(*sids)[i];
661
662                 if (use_lookupnames4) {
663                         if (i >= sid_array3.count) {
664                                 *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
665                                 goto done;
666                         }
667
668                         dom_idx         = sid_array3.sids[i].sid_index;
669                         (*types)[i]     = sid_array3.sids[i].sid_type;
670                 } else {
671                         if (i >= sid_array.count) {
672                                 *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
673                                 goto done;
674                         }
675
676                         dom_idx         = sid_array.sids[i].sid_index;
677                         (*types)[i]     = sid_array.sids[i].sid_type;
678                 }
679
680                 /* Translate optimised sid through domain index array */
681
682                 if (dom_idx == 0xffffffff) {
683                         /* Nothing to do, this is unknown */
684                         ZERO_STRUCTP(sid);
685                         (*types)[i] = SID_NAME_UNKNOWN;
686                         continue;
687                 }
688                 if (domains == NULL) {
689                         *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
690                         goto done;
691                 }
692                 if (dom_idx >= domains->count) {
693                         *presult = NT_STATUS_INVALID_NETWORK_RESPONSE;
694                         goto done;
695                 }
696
697                 if (use_lookupnames4) {
698                         sid_copy(sid, sid_array3.sids[i].sid);
699                 } else {
700                         sid_copy(sid, domains->domains[dom_idx].sid);
701
702                         if (sid_array.sids[i].rid != 0xffffffff) {
703                                 sid_append_rid(sid, sid_array.sids[i].rid);
704                         }
705                 }
706
707                 if (dom_names == NULL) {
708                         continue;
709                 }
710
711                 (*dom_names)[i] = domains->domains[dom_idx].name.string;
712         }
713
714  done:
715         return status;
716 }
717
718 NTSTATUS dcerpc_lsa_lookup_names(struct dcerpc_binding_handle *h,
719                                  TALLOC_CTX *mem_ctx,
720                                  struct policy_handle *pol,
721                                  uint32_t num_names,
722                                  const char **names,
723                                  const char ***dom_names,
724                                  enum lsa_LookupNamesLevel level,
725                                  struct dom_sid **sids,
726                                  enum lsa_SidType **types,
727                                  NTSTATUS *result)
728 {
729         return dcerpc_lsa_lookup_names_generic(h,
730                                                mem_ctx,
731                                                pol,
732                                                num_names,
733                                                names,
734                                                dom_names,
735                                                level,
736                                                sids,
737                                                types,
738                                                false,
739                                                result);
740 }
741
742 NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
743                                  TALLOC_CTX *mem_ctx,
744                                  struct policy_handle *pol,
745                                  int num_names,
746                                  const char **names,
747                                  const char ***dom_names,
748                                  int level,
749                                  struct dom_sid **sids,
750                                  enum lsa_SidType **types)
751 {
752         NTSTATUS status;
753         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
754
755         status = dcerpc_lsa_lookup_names(cli->binding_handle,
756                                          mem_ctx,
757                                          pol,
758                                          num_names,
759                                          names,
760                                          dom_names,
761                                          level,
762                                          sids,
763                                          types,
764                                          &result);
765         if (!NT_STATUS_IS_OK(status)) {
766                 return status;
767         }
768
769         return result;
770 }
771
772 NTSTATUS dcerpc_lsa_lookup_names4(struct dcerpc_binding_handle *h,
773                                   TALLOC_CTX *mem_ctx,
774                                   struct policy_handle *pol,
775                                   uint32_t num_names,
776                                   const char **names,
777                                   const char ***dom_names,
778                                   enum lsa_LookupNamesLevel level,
779                                   struct dom_sid **sids,
780                                   enum lsa_SidType **types,
781                                   NTSTATUS *result)
782 {
783         return dcerpc_lsa_lookup_names_generic(h,
784                                                mem_ctx,
785                                                pol,
786                                                num_names,
787                                                names,
788                                                dom_names,
789                                                level,
790                                                sids,
791                                                types,
792                                                true,
793                                                result);
794 }