Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/security/util_sid.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Samba utility functions
4
   Copyright (C) Andrew Tridgell    1992-1998
5
   Copyright (C) Luke Kenneth Caseson Leighton  1998-1999
6
   Copyright (C) Jeremy Allison     1999
7
   Copyright (C) Stefan (metze) Metzmacher  2002
8
   Copyright (C) Simo Sorce       2002
9
   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
10
   Copyright (C) Andrew Bartlett                2010
11
12
   This program is free software; you can redistribute it and/or modify
13
   it under the terms of the GNU General Public License as published by
14
   the Free Software Foundation; either version 3 of the License, or
15
   (at your option) any later version.
16
17
   This program is distributed in the hope that it will be useful,
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   GNU General Public License for more details.
21
22
   You should have received a copy of the GNU General Public License
23
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
*/
25
26
#include "replace.h"
27
#include "lib/util/samba_util.h"
28
#include "../librpc/gen_ndr/ndr_security.h"
29
#include "../librpc/gen_ndr/netlogon.h"
30
#include "../libcli/security/security.h"
31
#include "auth/auth.h"
32
33
34
#undef strcasecmp
35
#undef strncasecmp
36
37
/*
38
 * Some useful sids, more well known sids can be found at
39
 * http://support.microsoft.com/kb/243330/EN-US/
40
 */
41
42
43
/* S-1-1 */
44
const struct dom_sid global_sid_World_Domain =               /* Everyone domain */
45
{ 1, 0, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
46
/* S-1-1-0 */
47
const struct dom_sid global_sid_World =                      /* Everyone */
48
{ 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
49
/* S-1-2 */
50
const struct dom_sid global_sid_Local_Authority =            /* Local Authority */
51
{ 1, 0, {0,0,0,0,0,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
52
/* S-1-3 */
53
const struct dom_sid global_sid_Creator_Owner_Domain =       /* Creator Owner domain */
54
{ 1, 0, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
55
/* S-1-4 */
56
const struct dom_sid global_sid_NonUnique_Authority =        /* NonUnique Authority */
57
{ 1, 0, {0,0,0,0,0,4}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
58
/* S-1-5 */
59
const struct dom_sid global_sid_NT_Authority =        /* NT Authority */
60
{ 1, 0, {0,0,0,0,0,5}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
61
/* S-1-5-18 */
62
const struct dom_sid global_sid_System =      /* System */
63
{ 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
64
/* S-1-0-0 */
65
const struct dom_sid global_sid_NULL =                /* NULL sid */
66
{ 1, 1, {0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
67
/* S-1-5-10 */
68
const struct dom_sid global_sid_Self =        /* SELF */
69
{ 1, 1, {0,0,0,0,0,5}, {10,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
70
/* S-1-5-11 */
71
const struct dom_sid global_sid_Authenticated_Users = /* All authenticated rids */
72
{ 1, 1, {0,0,0,0,0,5}, {11,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
73
#if 0
74
/* for documentation S-1-5-12 */
75
const struct dom_sid global_sid_Restricted =      /* Restricted Code */
76
{ 1, 1, {0,0,0,0,0,5}, {12,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
77
#endif
78
79
/* S-1-5-64-10 NTLM Authentication */
80
const struct dom_sid global_sid_NTLM_Authentication =
81
{ 1, 2, {0,0,0,0,0,5}, {64,10,0,0,0,0,0,0,0,0,0,0,0,0,0}};
82
83
/* S-1-18 */
84
const struct dom_sid global_sid_Asserted_Identity =       /* Asserted Identity */
85
{ 1, 0, {0,0,0,0,0,18}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
86
/* S-1-18-1 */
87
const struct dom_sid global_sid_Asserted_Identity_Authentication_Authority =  /* Asserted Identity Authentication Authority */
88
{ 1, 1, {0,0,0,0,0,18}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
89
/* S-1-18-2 */
90
const struct dom_sid global_sid_Asserted_Identity_Service = /* Asserted Identity Service */
91
{ 1, 1, {0,0,0,0,0,18}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
92
93
/* S-1-18-3 */
94
const struct dom_sid global_sid_Fresh_Public_Key_Identity = /* Fresh Public Key Identity */
95
{ 1, 1, {0,0,0,0,0,18}, {3,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
96
97
/* S-1-5-2 */
98
const struct dom_sid global_sid_Network =     /* Network rids */
99
{ 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
100
101
/* S-1-3 */
102
const struct dom_sid global_sid_Creator_Owner =   /* Creator Owner */
103
{ 1, 1, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
104
/* S-1-3-1 */
105
const struct dom_sid global_sid_Creator_Group =   /* Creator Group */
106
{ 1, 1, {0,0,0,0,0,3}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
107
/* S-1-3-4 */
108
const struct dom_sid global_sid_Owner_Rights =    /* Owner Rights */
109
{ 1, 1, {0,0,0,0,0,3}, {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
110
/* S-1-5-7 */
111
const struct dom_sid global_sid_Anonymous =     /* Anonymous login */
112
{ 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
113
/* S-1-5-9 */
114
const struct dom_sid global_sid_Enterprise_DCs =    /* Enterprise DCs */
115
{ 1, 1, {0,0,0,0,0,5}, {9,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
116
/* S-1-5-21-0-0-0-496 */
117
const struct dom_sid global_sid_Compounded_Authentication =   /* Compounded Authentication */
118
{1, 5, {0,0,0,0,0,5}, {21,0,0,0,496,0,0,0,0,0,0,0,0,0,0}};
119
/* S-1-5-21-0-0-0-497 */
120
const struct dom_sid global_sid_Claims_Valid =    /* Claims Valid */
121
{1, 5, {0,0,0,0,0,5}, {21,0,0,0,497,0,0,0,0,0,0,0,0,0,0}};
122
123
/* S-1-5-15 This Organization */
124
const struct dom_sid global_sid_This_Organization =
125
{ 1, 1, {0,0,0,0,0,5}, {15,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
126
/* S-1-5-65-1 This Organization Certificate */
127
const struct dom_sid global_sid_This_Organization_Certificate =
128
{ 1, 2, {0,0,0,0,0,5}, {65,1,0,0,0,0,0,0,0,0,0,0,0,0,0}};
129
/* S-1-5-1000 Other Organization */
130
const struct dom_sid global_sid_Other_Organization =
131
{ 1, 1, {0,0,0,0,0,5}, {1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
132
133
/* S-1-10 Passport Authority */
134
const struct dom_sid global_sid_Passport_Authority =
135
{ 1, 0, {0,0,0,0,0,10}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
136
137
/* S-1-16 Mandatory Label Authority */
138
const struct dom_sid global_sid_Mandatory_Label_Authority =
139
{ 1, 0, {0,0,0,0,0,16}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
140
141
/* S-1-15-2-1 BUILTIN_PACKAGE_ANY_PACKAGE */
142
const struct dom_sid global_sid_Builtin_Package_Any_Package =
143
{ 1, 2, {0,0,0,0,0,15}, {2,1,0,0,0,0,0,0,0,0,0,0,0,0,0}};
144
145
/* S-1-5-32 */
146
const struct dom_sid global_sid_Builtin =       /* Local well-known domain */
147
{ 1, 1, {0,0,0,0,0,5}, {32,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
148
/* S-1-5-32-544 */
149
const struct dom_sid global_sid_Builtin_Administrators =  /* Builtin administrators */
150
{ 1, 2, {0,0,0,0,0,5}, {32,544,0,0,0,0,0,0,0,0,0,0,0,0,0}};
151
/* S-1-5-32-545 */
152
const struct dom_sid global_sid_Builtin_Users =   /* Builtin users */
153
{ 1, 2, {0,0,0,0,0,5}, {32,545,0,0,0,0,0,0,0,0,0,0,0,0,0}};
154
/* S-1-5-32-546 */
155
const struct dom_sid global_sid_Builtin_Guests =    /* Builtin guest users */
156
{ 1, 2, {0,0,0,0,0,5}, {32,546,0,0,0,0,0,0,0,0,0,0,0,0,0}};
157
/* S-1-5-32-547 */
158
const struct dom_sid global_sid_Builtin_Power_Users = /* Builtin power users */
159
{ 1, 2, {0,0,0,0,0,5}, {32,547,0,0,0,0,0,0,0,0,0,0,0,0,0}};
160
/* S-1-5-32-548 */
161
const struct dom_sid global_sid_Builtin_Account_Operators = /* Builtin account operators */
162
{ 1, 2, {0,0,0,0,0,5}, {32,548,0,0,0,0,0,0,0,0,0,0,0,0,0}};
163
/* S-1-5-32-549 */
164
const struct dom_sid global_sid_Builtin_Server_Operators =  /* Builtin server operators */
165
{ 1, 2, {0,0,0,0,0,5}, {32,549,0,0,0,0,0,0,0,0,0,0,0,0,0}};
166
/* S-1-5-32-550 */
167
const struct dom_sid global_sid_Builtin_Print_Operators = /* Builtin print operators */
168
{ 1, 2, {0,0,0,0,0,5}, {32,550,0,0,0,0,0,0,0,0,0,0,0,0,0}};
169
/* S-1-5-32-551 */
170
const struct dom_sid global_sid_Builtin_Backup_Operators =  /* Builtin backup operators */
171
{ 1, 2, {0,0,0,0,0,5}, {32,551,0,0,0,0,0,0,0,0,0,0,0,0,0}};
172
/* S-1-5-32-552 */
173
const struct dom_sid global_sid_Builtin_Replicator =    /* Builtin replicator */
174
{ 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
175
/* S-1-5-32-554 */
176
const struct dom_sid global_sid_Builtin_PreWin2kAccess =  /* Builtin pre win2k access */
177
{ 1, 2, {0,0,0,0,0,5}, {32,554,0,0,0,0,0,0,0,0,0,0,0,0,0}};
178
179
/* S-1-22-1 */
180
const struct dom_sid global_sid_Unix_Users =      /* Unmapped Unix users */
181
{ 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
182
/* S-1-22-2 */
183
const struct dom_sid global_sid_Unix_Groups =     /* Unmapped Unix groups */
184
{ 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
185
186
/*
187
 * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
188
 */
189
/* S-1-5-88 */
190
const struct dom_sid global_sid_Unix_NFS =             /* MS NFS and Apple style */
191
{ 1, 1, {0,0,0,0,0,5}, {88,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
192
/* S-1-5-88-1 */
193
const struct dom_sid global_sid_Unix_NFS_Users =    /* Unix uid, MS NFS and Apple style */
194
{ 1, 2, {0,0,0,0,0,5}, {88,1,0,0,0,0,0,0,0,0,0,0,0,0,0}};
195
/* S-1-5-88-2 */
196
const struct dom_sid global_sid_Unix_NFS_Groups =   /* Unix gid, MS NFS and Apple style */
197
{ 1, 2, {0,0,0,0,0,5}, {88,2,0,0,0,0,0,0,0,0,0,0,0,0,0}};
198
/* S-1-5-88-3 */
199
const struct dom_sid global_sid_Unix_NFS_Mode =     /* Unix mode */
200
{ 1, 2, {0,0,0,0,0,5}, {88,3,0,0,0,0,0,0,0,0,0,0,0,0,0}};
201
/* Unused, left here for documentary purposes */
202
#if 0
203
const struct dom_sid global_sid_Unix_NFS_Other =    /* Unix other, MS NFS and Apple style */
204
{ 1, 2, {0,0,0,0,0,5}, {88,4,0,0,0,0,0,0,0,0,0,0,0,0,0}};
205
#endif
206
207
/* Information passing via security token */
208
const struct dom_sid global_sid_Samba_SMB3 =
209
{1, 1, {0,0,0,0,0,22}, {1397571891, }};
210
211
const struct dom_sid global_sid_Samba_NPA_Flags = {1,
212
               1,
213
               {0, 0, 0, 0, 0, 22},
214
               {
215
                 2041152804,
216
               }};
217
218
/* Unused, left here for documentary purposes */
219
#if 0
220
#define SECURITY_NULL_SID_AUTHORITY    0
221
#define SECURITY_WORLD_SID_AUTHORITY   1
222
#define SECURITY_LOCAL_SID_AUTHORITY   2
223
#define SECURITY_CREATOR_SID_AUTHORITY 3
224
#define SECURITY_NT_AUTHORITY          5
225
#endif
226
227
static struct dom_sid system_sid_array[1] =
228
{ { 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} };
229
static const struct security_token system_token = {
230
  .num_sids       = ARRAY_SIZE(system_sid_array),
231
  .sids           = system_sid_array,
232
  .privilege_mask = SE_ALL_PRIVS
233
};
234
235
/****************************************************************************
236
 Lookup string names for SID types.
237
****************************************************************************/
238
239
const char *sid_type_lookup(uint32_t sid_type)
240
0
{
241
0
  switch (sid_type) {
242
0
  case SID_NAME_USE_NONE:
243
0
    return "None";
244
0
    break;
245
0
  case SID_NAME_USER:
246
0
    return "User";
247
0
    break;
248
0
  case SID_NAME_DOM_GRP:
249
0
    return "Domain Group";
250
0
    break;
251
0
  case SID_NAME_DOMAIN:
252
0
    return "Domain";
253
0
    break;
254
0
  case SID_NAME_ALIAS:
255
0
    return "Local Group";
256
0
    break;
257
0
  case SID_NAME_WKN_GRP:
258
0
    return "Well-known Group";
259
0
    break;
260
0
  case SID_NAME_DELETED:
261
0
    return "Deleted Account";
262
0
    break;
263
0
  case SID_NAME_INVALID:
264
0
    return "Invalid Account";
265
0
    break;
266
0
  case SID_NAME_UNKNOWN:
267
0
    return "UNKNOWN";
268
0
    break;
269
0
  case SID_NAME_COMPUTER:
270
0
    return "Computer";
271
0
    break;
272
0
  case SID_NAME_LABEL:
273
0
    return "Mandatory Label";
274
0
    break;
275
0
  }
276
277
  /* Default return */
278
0
  return "SID *TYPE* is INVALID";
279
0
}
280
281
/**************************************************************************
282
 Create the SYSTEM token.
283
***************************************************************************/
284
285
const struct security_token *get_system_token(void)
286
0
{
287
0
  return &system_token;
288
0
}
289
290
bool sid_compose(struct dom_sid *dst, const struct dom_sid *domain_sid, uint32_t rid)
291
27.7k
{
292
27.7k
  sid_copy(dst, domain_sid);
293
27.7k
  return sid_append_rid(dst, rid);
294
27.7k
}
295
296
/*****************************************************************
297
 Removes the last rid from the end of a sid
298
*****************************************************************/
299
300
bool sid_split_rid(struct dom_sid *sid, uint32_t *rid)
301
0
{
302
0
  if (sid->num_auths > 0) {
303
0
    sid->num_auths--;
304
0
    if (rid != NULL) {
305
0
      *rid = sid->sub_auths[sid->num_auths];
306
0
    }
307
0
    return true;
308
0
  }
309
0
  return false;
310
0
}
311
312
/*****************************************************************
313
 Return the last rid from the end of a sid
314
*****************************************************************/
315
316
bool sid_peek_rid(const struct dom_sid *sid, uint32_t *rid)
317
0
{
318
0
  if (!sid || !rid)
319
0
    return false;
320
321
0
  if (sid->num_auths > 0) {
322
0
    *rid = sid->sub_auths[sid->num_auths - 1];
323
0
    return true;
324
0
  }
325
0
  return false;
326
0
}
327
328
/*****************************************************************
329
 Return the last rid from the end of a sid
330
 and check the sid against the exp_dom_sid
331
*****************************************************************/
332
333
bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32_t *rid)
334
0
{
335
0
  if (!exp_dom_sid || !sid || !rid)
336
0
    return false;
337
338
0
  if (sid->num_auths != (exp_dom_sid->num_auths+1)) {
339
0
    return false;
340
0
  }
341
342
0
  if (dom_sid_compare_domain(exp_dom_sid, sid)!=0){
343
0
    *rid=(-1);
344
0
    return false;
345
0
  }
346
347
0
  return sid_peek_rid(sid, rid);
348
0
}
349
350
/*****************************************************************
351
 Copies a sid
352
*****************************************************************/
353
354
void sid_copy(struct dom_sid *dst, const struct dom_sid *src)
355
60.2k
{
356
60.2k
  const int8_t num_auths = MIN(15, MAX(0, src->num_auths));
357
60.2k
  int8_t i;
358
359
60.2k
  *dst = (struct dom_sid) {
360
60.2k
    .sid_rev_num = src->sid_rev_num,
361
60.2k
    .num_auths = num_auths,
362
60.2k
  };
363
364
60.2k
  memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
365
366
201k
  for (i = 0; i < num_auths; i++)
367
141k
    dst->sub_auths[i] = src->sub_auths[i];
368
60.2k
}
369
370
/*****************************************************************
371
 Parse a on-the-wire SID to a struct dom_sid.
372
*****************************************************************/
373
374
ssize_t sid_parse(const uint8_t *inbuf, size_t len, struct dom_sid *sid)
375
0
{
376
0
  DATA_BLOB in = data_blob_const(inbuf, len);
377
0
  enum ndr_err_code ndr_err;
378
379
0
  ndr_err = ndr_pull_struct_blob_all(
380
0
    &in, NULL, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
381
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
382
0
    return -1;
383
0
  }
384
0
  return ndr_size_dom_sid(sid, 0);
385
0
}
386
387
/********************************************************************
388
 Add SID to an array of SIDs
389
********************************************************************/
390
391
NTSTATUS add_sid_to_array(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
392
        struct dom_sid **sids, uint32_t *num)
393
24
{
394
24
  struct dom_sid *tmp;
395
396
24
  if ((*num) == UINT32_MAX) {
397
0
    return NT_STATUS_INTEGER_OVERFLOW;
398
0
  }
399
400
24
  tmp = talloc_realloc(mem_ctx, *sids, struct dom_sid, (*num)+1);
401
24
  if (tmp == NULL) {
402
0
    *num = 0;
403
0
    return NT_STATUS_NO_MEMORY;
404
0
  }
405
24
  *sids = tmp;
406
407
24
  sid_copy(&((*sids)[*num]), sid);
408
24
  *num += 1;
409
410
24
  return NT_STATUS_OK;
411
24
}
412
413
414
/********************************************************************
415
 Add SID to an array of SIDs ensuring that it is not already there
416
********************************************************************/
417
418
NTSTATUS add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
419
         struct dom_sid **sids, uint32_t *num_sids)
420
0
{
421
0
  bool contains;
422
423
0
  contains = sids_contains_sid(*sids, *num_sids, sid);
424
0
  if (contains) {
425
0
    return NT_STATUS_OK;
426
0
  }
427
428
0
  return add_sid_to_array(mem_ctx, sid, sids, num_sids);
429
0
}
430
431
/**
432
 * Appends a SID and attribute to an array of auth_SidAttr.
433
 *
434
 * @param [in] mem_ctx  Talloc memory context on which to allocate the array.
435
 * @param [in] sid  The SID to append.
436
 * @param [in] attrs  SE_GROUP_* flags to go with the SID.
437
 * @param [inout] sids  A pointer to the auth_SidAttr array.
438
 * @param [inout] num A pointer to the size of the auth_SidArray array.
439
 * @returns NT_STATUS_OK on success.
440
 */
441
NTSTATUS add_sid_to_array_attrs(TALLOC_CTX *mem_ctx,
442
        const struct dom_sid *sid, uint32_t attrs,
443
        struct auth_SidAttr **sids, uint32_t *num)
444
0
{
445
0
  struct auth_SidAttr *tmp = NULL;
446
447
0
  if (sid == NULL) {
448
0
    return NT_STATUS_INVALID_PARAMETER;
449
0
  }
450
451
0
  if ((*num) == UINT32_MAX) {
452
0
    return NT_STATUS_INTEGER_OVERFLOW;
453
0
  }
454
455
0
  tmp = talloc_realloc(mem_ctx, *sids, struct auth_SidAttr, (*num)+1);
456
0
  if (tmp == NULL) {
457
0
    *num = 0;
458
0
    return NT_STATUS_NO_MEMORY;
459
0
  }
460
0
  *sids = tmp;
461
462
0
  (*sids)[*num] = (struct auth_SidAttr) {
463
0
    .sid = *sid,
464
0
    .attrs = attrs,
465
0
  };
466
0
  *num += 1;
467
468
0
  return NT_STATUS_OK;
469
0
}
470
471
472
/**
473
 * Appends a SID and attribute to an array of auth_SidAttr,
474
 * ensuring that it is not already there.
475
 *
476
 * @param [in] mem_ctx  Talloc memory context on which to allocate the array.
477
 * @param [in] sid  The SID to append.
478
 * @param [in] attrs  SE_GROUP_* flags to go with the SID.
479
 * @param [inout] sids  A pointer to the auth_SidAttr array.
480
 * @param [inout] num_sids  A pointer to the size of the auth_SidArray array.
481
 * @returns NT_STATUS_OK on success.
482
 */
483
NTSTATUS add_sid_to_array_attrs_unique(TALLOC_CTX *mem_ctx,
484
               const struct dom_sid *sid, uint32_t attrs,
485
               struct auth_SidAttr **sids, uint32_t *num_sids)
486
0
{
487
0
  bool contains;
488
489
0
  contains = sids_contains_sid_attrs(*sids, *num_sids, sid, attrs);
490
0
  if (contains) {
491
0
    return NT_STATUS_OK;
492
0
  }
493
494
0
  return add_sid_to_array_attrs(mem_ctx, sid, attrs, sids, num_sids);
495
0
}
496
497
/********************************************************************
498
 Remove SID from an array
499
********************************************************************/
500
501
void del_sid_from_array(const struct dom_sid *sid, struct dom_sid **sids,
502
      uint32_t *num)
503
0
{
504
0
  struct dom_sid *sid_list = *sids;
505
0
  uint32_t i;
506
507
0
  for ( i=0; i<*num; i++ ) {
508
509
    /* if we find the SID, then decrement the count
510
       and break out of the loop */
511
512
0
    if (dom_sid_equal(sid, &sid_list[i])) {
513
0
      *num -= 1;
514
0
      break;
515
0
    }
516
0
  }
517
518
  /* This loop will copy the remainder of the array
519
     if i < num of sids in the array */
520
521
0
  for ( ; i<*num; i++ ) {
522
0
    sid_copy( &sid_list[i], &sid_list[i+1] );
523
0
  }
524
0
}
525
526
bool add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
527
           uint32_t rid, uint32_t **pp_rids, size_t *p_num)
528
0
{
529
0
  size_t i;
530
531
0
  for (i=0; i<*p_num; i++) {
532
0
    if ((*pp_rids)[i] == rid)
533
0
      return true;
534
0
  }
535
536
0
  *pp_rids = talloc_realloc(mem_ctx, *pp_rids, uint32_t, *p_num+1);
537
538
0
  if (*pp_rids == NULL) {
539
0
    *p_num = 0;
540
0
    return false;
541
0
  }
542
543
0
  (*pp_rids)[*p_num] = rid;
544
0
  *p_num += 1;
545
0
  return true;
546
0
}
547
548
bool is_null_sid(const struct dom_sid *sid)
549
0
{
550
0
  static const struct dom_sid null_sid = {0};
551
0
  return dom_sid_equal(sid, &null_sid);
552
0
}
553
554
/**
555
 * Return true if an array of SIDs contains a certain SID.
556
 *
557
 * @param [in] sids The SID array.
558
 * @param [in] num_sids The size of the SID array.
559
 * @param [in] sid  The SID in question.
560
 * @returns true if the array contains the SID.
561
 */
562
bool sids_contains_sid(const struct dom_sid *sids,
563
           const uint32_t num_sids,
564
           const struct dom_sid *sid)
565
0
{
566
0
  uint32_t i;
567
568
0
  for (i = 0; i < num_sids; i++) {
569
0
    if (dom_sid_equal(&sids[i], sid)) {
570
0
      return true;
571
0
    }
572
0
  }
573
0
  return false;
574
0
}
575
576
/**
577
 * Return true if an array of auth_SidAttr contains a certain SID.
578
 *
579
 * @param [in] sids The auth_SidAttr array.
580
 * @param [in] num_sids The size of the auth_SidArray array.
581
 * @param [in] sid  The SID in question.
582
 * @returns true if the array contains the SID.
583
 */
584
bool sid_attrs_contains_sid(const struct auth_SidAttr *sids,
585
          const uint32_t num_sids,
586
          const struct dom_sid *sid)
587
0
{
588
0
  uint32_t i;
589
590
0
  for (i = 0; i < num_sids; i++) {
591
0
    if (dom_sid_equal(&sids[i].sid, sid)) {
592
0
      return true;
593
0
    }
594
0
  }
595
0
  return false;
596
0
}
597
598
/**
599
 * Return true if an array of auth_SidAttr contains a certain SID with certain
600
 * attributes.
601
 *
602
 * @param [in] sids The auth_SidAttr array.
603
 * @param [in] num_sids The size of the auth_SidArray array.
604
 * @param [in] sid  The SID in question.
605
 * @param [in] attrs  The attributes of the SID.
606
 * @returns true if the array contains the SID.
607
 */
608
bool sids_contains_sid_attrs(const struct auth_SidAttr *sids,
609
           const uint32_t num_sids,
610
           const struct dom_sid *sid,
611
           uint32_t attrs)
612
0
{
613
0
  uint32_t i;
614
615
0
  for (i = 0; i < num_sids; i++) {
616
0
    if (attrs != sids[i].attrs) {
617
0
      continue;
618
0
    }
619
0
    if (!dom_sid_equal(&sids[i].sid, sid)) {
620
0
      continue;
621
0
    }
622
623
0
    return true;
624
0
  }
625
0
  return false;
626
0
}
627
628
/*
629
 * See [MS-LSAT] 3.1.1.1.1 Predefined Translation Database and Corresponding View
630
 */
631
struct predefined_name_mapping {
632
  const char *name;
633
  enum lsa_SidType type;
634
  struct dom_sid sid;
635
};
636
637
struct predefined_domain_mapping {
638
  const char *domain;
639
  struct dom_sid sid;
640
  size_t num_names;
641
  const struct predefined_name_mapping *names;
642
};
643
644
/* S-1-${AUTHORITY} */
645
#define _SID0(authority) \
646
  { 1, 0, {0,0,0,0,0,authority}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
647
/* S-1-${AUTHORITY}-${SUB1} */
648
#define _SID1(authority,sub1) \
649
  { 1, 1, {0,0,0,0,0,authority}, {sub1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
650
/* S-1-${AUTHORITY}-${SUB1}-${SUB2} */
651
#define _SID2(authority,sub1,sub2) \
652
  { 1, 2, {0,0,0,0,0,authority}, {sub1,sub2,0,0,0,0,0,0,0,0,0,0,0,0,0}}
653
654
/*
655
 * S-1-0
656
 */
657
static const struct predefined_name_mapping predefined_names_S_1_0[] = {
658
  {
659
    .name = "NULL SID",
660
    .type = SID_NAME_WKN_GRP,
661
    .sid = _SID1(0, 0), /* S-1-0-0 */
662
  },
663
};
664
665
/*
666
 * S-1-1
667
 */
668
static const struct predefined_name_mapping predefined_names_S_1_1[] = {
669
  {
670
    .name = "Everyone",
671
    .type = SID_NAME_WKN_GRP,
672
    .sid = _SID1(1, 0), /* S-1-1-0 */
673
  },
674
};
675
676
/*
677
 * S-1-2
678
 */
679
static const struct predefined_name_mapping predefined_names_S_1_2[] = {
680
  {
681
    .name = "LOCAL",
682
    .type = SID_NAME_WKN_GRP,
683
    .sid = _SID1(2, 0), /* S-1-2-0 */
684
  },
685
};
686
687
/*
688
 * S-1-3
689
 */
690
static const struct predefined_name_mapping predefined_names_S_1_3[] = {
691
  {
692
    .name = "CREATOR OWNER",
693
    .type = SID_NAME_WKN_GRP,
694
    .sid = _SID1(3, 0), /* S-1-3-0 */
695
  },
696
  {
697
    .name = "CREATOR GROUP",
698
    .type = SID_NAME_WKN_GRP,
699
    .sid = _SID1(3, 1), /* S-1-3-1 */
700
  },
701
  {
702
    .name = "CREATOR OWNER SERVER",
703
    .type = SID_NAME_WKN_GRP,
704
    .sid = _SID1(3, 0), /* S-1-3-2 */
705
  },
706
  {
707
    .name = "CREATOR GROUP SERVER",
708
    .type = SID_NAME_WKN_GRP,
709
    .sid = _SID1(3, 1), /* S-1-3-3 */
710
  },
711
  {
712
    .name = "OWNER RIGHTS",
713
    .type = SID_NAME_WKN_GRP,
714
    .sid = _SID1(3, 4), /* S-1-3-4 */
715
  },
716
};
717
718
/*
719
 * S-1-5 only 'NT Pseudo Domain'
720
 */
721
static const struct predefined_name_mapping predefined_names_S_1_5p[] = {
722
  {
723
    .name = "NT Pseudo Domain",
724
    .type = SID_NAME_DOMAIN,
725
    .sid = _SID0(5), /* S-1-5 */
726
  },
727
};
728
729
/*
730
 * S-1-5 'NT AUTHORITY'
731
 */
732
static const struct predefined_name_mapping predefined_names_S_1_5a[] = {
733
  {
734
    .name = "DIALUP",
735
    .type = SID_NAME_WKN_GRP,
736
    .sid = _SID1(5, 1), /* S-1-5-1 */
737
  },
738
  {
739
    .name = "NETWORK",
740
    .type = SID_NAME_WKN_GRP,
741
    .sid = _SID1(5, 2), /* S-1-5-2 */
742
  },
743
  {
744
    .name = "BATCH",
745
    .type = SID_NAME_WKN_GRP,
746
    .sid = _SID1(5, 3), /* S-1-5-3 */
747
  },
748
  {
749
    .name = "INTERACTIVE",
750
    .type = SID_NAME_WKN_GRP,
751
    .sid = _SID1(5, 4), /* S-1-5-4 */
752
  },
753
  {
754
    .name = "SERVICE",
755
    .type = SID_NAME_WKN_GRP,
756
    .sid = _SID1(5, 6), /* S-1-5-6 */
757
  },
758
  {
759
    .name = "ANONYMOUS LOGON",
760
    .type = SID_NAME_WKN_GRP,
761
    .sid = _SID1(5, 7), /* S-1-5-7 */
762
  },
763
  {
764
    .name = "PROXY",
765
    .type = SID_NAME_WKN_GRP,
766
    .sid = _SID1(5, 8), /* S-1-5-8 */
767
  },
768
  {
769
    .name = "ENTERPRISE DOMAIN CONTROLLERS",
770
    .type = SID_NAME_WKN_GRP,
771
    .sid = _SID1(5, 9), /* S-1-5-9 */
772
  },
773
  {
774
    .name = "SELF",
775
    .type = SID_NAME_WKN_GRP,
776
    .sid = _SID1(5, 10), /* S-1-5-10 */
777
  },
778
  {
779
    .name = "Authenticated Users",
780
    .type = SID_NAME_WKN_GRP,
781
    .sid = _SID1(5, 11), /* S-1-5-11 */
782
  },
783
  {
784
    .name = "RESTRICTED",
785
    .type = SID_NAME_WKN_GRP,
786
    .sid = _SID1(5, 12), /* S-1-5-12 */
787
  },
788
  {
789
    .name = "TERMINAL SERVER USER",
790
    .type = SID_NAME_WKN_GRP,
791
    .sid = _SID1(5, 13), /* S-1-5-13 */
792
  },
793
  {
794
    .name = "REMOTE INTERACTIVE LOGON",
795
    .type = SID_NAME_WKN_GRP,
796
    .sid = _SID1(5, 14), /* S-1-5-14 */
797
  },
798
  {
799
    .name = "This Organization",
800
    .type = SID_NAME_WKN_GRP,
801
    .sid = _SID1(5, 15), /* S-1-5-15 */
802
  },
803
  {
804
    .name = "IUSR",
805
    .type = SID_NAME_WKN_GRP,
806
    .sid = _SID1(5, 17), /* S-1-5-17 */
807
  },
808
  {
809
    .name = "SYSTEM",
810
    .type = SID_NAME_WKN_GRP,
811
    .sid = _SID1(5, 18), /* S-1-5-18 */
812
  },
813
  {
814
    .name = "LOCAL SERVICE",
815
    .type = SID_NAME_WKN_GRP,
816
    .sid = _SID1(5, 19), /* S-1-5-19 */
817
  },
818
  {
819
    .name = "NETWORK SERVICE",
820
    .type = SID_NAME_WKN_GRP,
821
    .sid = _SID1(5, 20), /* S-1-5-20 */
822
  },
823
  {
824
    .name = "WRITE RESTRICTED",
825
    .type = SID_NAME_WKN_GRP,
826
    .sid = _SID1(5, 33), /* S-1-5-33 */
827
  },
828
  {
829
    .name = "Other Organization",
830
    .type = SID_NAME_WKN_GRP,
831
    .sid = _SID1(5, 1000), /* S-1-5-1000 */
832
  },
833
};
834
835
/*
836
 * S-1-5-32
837
 */
838
static const struct predefined_name_mapping predefined_names_S_1_5_32[] = {
839
  {
840
    .name = "BUILTIN",
841
    .type = SID_NAME_DOMAIN,
842
    .sid = _SID1(5, 32), /* S-1-5-32 */
843
  },
844
};
845
846
/*
847
 * S-1-5-64
848
 */
849
static const struct predefined_name_mapping predefined_names_S_1_5_64[] = {
850
  {
851
    .name = "NTLM Authentication",
852
    .type = SID_NAME_WKN_GRP,
853
    .sid = _SID2(5, 64, 10), /* S-1-5-64-10 */
854
  },
855
  {
856
    .name = "SChannel Authentication",
857
    .type = SID_NAME_WKN_GRP,
858
    .sid = _SID2(5, 64, 14), /* S-1-5-64-14 */
859
  },
860
  {
861
    .name = "Digest Authentication",
862
    .type = SID_NAME_WKN_GRP,
863
    .sid = _SID2(5, 64, 21), /* S-1-5-64-21 */
864
  },
865
};
866
867
/*
868
 * S-1-7
869
 */
870
static const struct predefined_name_mapping predefined_names_S_1_7[] = {
871
  {
872
    .name = "Internet$",
873
    .type = SID_NAME_DOMAIN,
874
    .sid = _SID0(7), /* S-1-7 */
875
  },
876
};
877
878
/*
879
 * S-1-16
880
 */
881
static const struct predefined_name_mapping predefined_names_S_1_16[] = {
882
  {
883
    .name = "Mandatory Label",
884
    .type = SID_NAME_DOMAIN,
885
    .sid = _SID0(16), /* S-1-16 */
886
  },
887
  {
888
    .name = "Untrusted Mandatory Level",
889
    .type = SID_NAME_LABEL,
890
    .sid = _SID1(16, 0), /* S-1-16-0 */
891
  },
892
  {
893
    .name = "Low Mandatory Level",
894
    .type = SID_NAME_LABEL,
895
    .sid = _SID1(16, 4096), /* S-1-16-4096 */
896
  },
897
  {
898
    .name = "Medium Mandatory Level",
899
    .type = SID_NAME_LABEL,
900
    .sid = _SID1(16, 8192), /* S-1-16-8192 */
901
  },
902
  {
903
    .name = "High Mandatory Level",
904
    .type = SID_NAME_LABEL,
905
    .sid = _SID1(16, 12288), /* S-1-16-12288 */
906
  },
907
  {
908
    .name = "System Mandatory Level",
909
    .type = SID_NAME_LABEL,
910
    .sid = _SID1(16, 16384), /* S-1-16-16384 */
911
  },
912
  {
913
    .name = "Protected Process Mandatory Level",
914
    .type = SID_NAME_LABEL,
915
    .sid = _SID1(16, 20480), /* S-1-16-20480 */
916
  },
917
};
918
919
static const struct predefined_domain_mapping predefined_domains[] = {
920
  {
921
    .domain = "",
922
    .sid = _SID0(0), /* S-1-0 */
923
    .num_names = ARRAY_SIZE(predefined_names_S_1_0),
924
    .names = predefined_names_S_1_0,
925
  },
926
  {
927
    .domain = "",
928
    .sid = _SID0(1), /* S-1-1 */
929
    .num_names = ARRAY_SIZE(predefined_names_S_1_1),
930
    .names = predefined_names_S_1_1,
931
  },
932
  {
933
    .domain = "",
934
    .sid = _SID0(2), /* S-1-2 */
935
    .num_names = ARRAY_SIZE(predefined_names_S_1_2),
936
    .names = predefined_names_S_1_2,
937
  },
938
  {
939
    .domain = "",
940
    .sid = _SID0(3), /* S-1-3 */
941
    .num_names = ARRAY_SIZE(predefined_names_S_1_3),
942
    .names = predefined_names_S_1_3,
943
  },
944
  {
945
    .domain = "",
946
    .sid = _SID0(3), /* S-1-3 */
947
    .num_names = ARRAY_SIZE(predefined_names_S_1_3),
948
    .names = predefined_names_S_1_3,
949
  },
950
  /*
951
   * S-1-5 is split here
952
   *
953
   * 'NT Pseudo Domain' has precedence before 'NT AUTHORITY'.
954
   *
955
   * In a LookupSids with multiple sids e.g. S-1-5 and S-1-5-7
956
   * the domain section (struct lsa_DomainInfo) gets
957
   * 'NT Pseudo Domain' with S-1-5. If asked in reversed order
958
   * S-1-5-7 and then S-1-5, you get struct lsa_DomainInfo
959
   * with 'NT AUTHORITY' and S-1-5.
960
   */
961
  {
962
    .domain = "NT Pseudo Domain",
963
    .sid = _SID0(5), /* S-1-5 */
964
    .num_names = ARRAY_SIZE(predefined_names_S_1_5p),
965
    .names = predefined_names_S_1_5p,
966
  },
967
  {
968
    .domain = "NT AUTHORITY",
969
    .sid = _SID0(5), /* S-1-5 */
970
    .num_names = ARRAY_SIZE(predefined_names_S_1_5a),
971
    .names = predefined_names_S_1_5a,
972
  },
973
  {
974
    .domain = "BUILTIN",
975
    .sid = _SID1(5, 32), /* S-1-5-32 */
976
    .num_names = ARRAY_SIZE(predefined_names_S_1_5_32),
977
    .names = predefined_names_S_1_5_32,
978
  },
979
  /*
980
   * 'NT AUTHORITY' again with S-1-5-64 this time
981
   */
982
  {
983
    .domain = "NT AUTHORITY",
984
    .sid = _SID1(5, 64), /* S-1-5-64 */
985
    .num_names = ARRAY_SIZE(predefined_names_S_1_5_64),
986
    .names = predefined_names_S_1_5_64,
987
  },
988
  {
989
    .domain = "Internet$",
990
    .sid = _SID0(7), /* S-1-7 */
991
    .num_names = ARRAY_SIZE(predefined_names_S_1_7),
992
    .names = predefined_names_S_1_7,
993
  },
994
  {
995
    .domain = "Mandatory Label",
996
    .sid = _SID0(16), /* S-1-16 */
997
    .num_names = ARRAY_SIZE(predefined_names_S_1_16),
998
    .names = predefined_names_S_1_16,
999
  },
1000
};
1001
1002
NTSTATUS dom_sid_lookup_predefined_name(const char *name,
1003
          const struct dom_sid **sid,
1004
          enum lsa_SidType *type,
1005
          const struct dom_sid **authority_sid,
1006
          const char **authority_name)
1007
0
{
1008
0
  size_t di;
1009
0
  const char *domain = "";
1010
0
  size_t domain_len = 0;
1011
0
  const char *p;
1012
0
  bool match;
1013
1014
0
  *sid = NULL;
1015
0
  *type = SID_NAME_UNKNOWN;
1016
0
  *authority_sid = NULL;
1017
0
  *authority_name = NULL;
1018
1019
0
  if (name == NULL) {
1020
0
    name = "";
1021
0
  }
1022
1023
0
  p = strchr(name, '\\');
1024
0
  if (p != NULL) {
1025
0
    domain = name;
1026
0
    domain_len = PTR_DIFF(p, domain);
1027
0
    name = p + 1;
1028
0
  }
1029
1030
0
  match = strequal(name, "");
1031
0
  if (match) {
1032
    /*
1033
     * Strange, but that's what W2012R2 does.
1034
     */
1035
0
    name = "BUILTIN";
1036
0
  }
1037
1038
0
  for (di = 0; di < ARRAY_SIZE(predefined_domains); di++) {
1039
0
    const struct predefined_domain_mapping *d =
1040
0
      &predefined_domains[di];
1041
0
    size_t ni;
1042
1043
0
    if (domain_len != 0) {
1044
0
      int cmp;
1045
1046
0
      cmp = strncasecmp(d->domain, domain, domain_len);
1047
0
      if (cmp != 0) {
1048
0
        continue;
1049
0
      }
1050
0
    }
1051
1052
0
    for (ni = 0; ni < d->num_names; ni++) {
1053
0
      const struct predefined_name_mapping *n =
1054
0
        &d->names[ni];
1055
1056
0
      match = strequal(n->name, name);
1057
0
      if (!match) {
1058
0
        continue;
1059
0
      }
1060
1061
0
      *sid = &n->sid;
1062
0
      *type = n->type;
1063
0
      *authority_sid = &d->sid;
1064
0
      *authority_name = d->domain;
1065
0
      return NT_STATUS_OK;
1066
0
    }
1067
0
  }
1068
1069
0
  return NT_STATUS_NONE_MAPPED;
1070
0
}
1071
1072
bool dom_sid_lookup_is_predefined_domain(const char *domain)
1073
0
{
1074
0
  size_t di;
1075
0
  bool match;
1076
1077
0
  if (domain == NULL) {
1078
0
    domain = "";
1079
0
  }
1080
1081
0
  match = strequal(domain, "");
1082
0
  if (match) {
1083
    /*
1084
     * Strange, but that's what W2012R2 does.
1085
     */
1086
0
    domain = "BUILTIN";
1087
0
  }
1088
1089
0
  for (di = 0; di < ARRAY_SIZE(predefined_domains); di++) {
1090
0
    const struct predefined_domain_mapping *d =
1091
0
      &predefined_domains[di];
1092
0
    int cmp;
1093
1094
0
    cmp = strcasecmp(d->domain, domain);
1095
0
    if (cmp != 0) {
1096
0
      continue;
1097
0
    }
1098
1099
0
    return true;
1100
0
  }
1101
1102
0
  return false;
1103
0
}
1104
1105
NTSTATUS dom_sid_lookup_predefined_sid(const struct dom_sid *sid,
1106
               const char **name,
1107
               enum lsa_SidType *type,
1108
               const struct dom_sid **authority_sid,
1109
               const char **authority_name)
1110
0
{
1111
0
  size_t di;
1112
1113
0
  *name = NULL;
1114
0
  *type = SID_NAME_UNKNOWN;
1115
0
  *authority_sid = NULL;
1116
0
  *authority_name = NULL;
1117
1118
0
  if (sid == NULL) {
1119
0
    return NT_STATUS_INVALID_SID;
1120
0
  }
1121
1122
0
  for (di = 0; di < ARRAY_SIZE(predefined_domains); di++) {
1123
0
    const struct predefined_domain_mapping *d =
1124
0
      &predefined_domains[di];
1125
0
    size_t ni;
1126
0
    int cmp;
1127
1128
0
    cmp = dom_sid_compare_auth(&d->sid, sid);
1129
0
    if (cmp != 0) {
1130
0
      continue;
1131
0
    }
1132
1133
0
    for (ni = 0; ni < d->num_names; ni++) {
1134
0
      const struct predefined_name_mapping *n =
1135
0
        &d->names[ni];
1136
1137
0
      cmp = dom_sid_compare(&n->sid, sid);
1138
0
      if (cmp != 0) {
1139
0
        continue;
1140
0
      }
1141
1142
0
      *name = n->name;
1143
0
      *type = n->type;
1144
0
      *authority_sid = &d->sid;
1145
0
      *authority_name = d->domain;
1146
0
      return NT_STATUS_OK;
1147
0
    }
1148
0
  }
1149
1150
0
  if (sid->num_auths == 0) {
1151
0
    return NT_STATUS_INVALID_SID;
1152
0
  }
1153
1154
0
  return NT_STATUS_NONE_MAPPED;
1155
0
}