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