Coverage Report

Created: 2025-07-23 07:04

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