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