1 /*
2 * Security functions
3 *
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "ntdll_misc.h"
39 #include "wine/exception.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
45
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
47
48 /* helper function to retrieve active length of an ACL */
49 static size_t acl_bytesInUse(PACL pAcl)
50 {
51 int i;
52 size_t bytesInUse = sizeof(ACL);
53 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
54 for (i = 0; i < pAcl->AceCount; i++)
55 {
56 bytesInUse += ace->AceSize;
57 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
58 }
59 return bytesInUse;
60 }
61
62 /* helper function to copy an ACL */
63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
64 {
65 DWORD size;
66
67 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
68 return FALSE;
69
70 size = pSourceAcl->AclSize;
71 if (nDestinationAclLength < size)
72 return FALSE;
73
74 memmove(pDestinationAcl, pSourceAcl, size);
75 return TRUE;
76 }
77
78 /* generically adds an ACE to an ACL */
79 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
80 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
81 {
82 ACE_HEADER *pAceHeader;
83 DWORD dwLengthSid;
84 DWORD dwAceSize;
85 DWORD *pAccessMask;
86 DWORD *pSidStart;
87
88 if (!RtlValidSid(pSid))
89 return STATUS_INVALID_SID;
90
91 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
92 return STATUS_REVISION_MISMATCH;
93
94 if (!RtlValidAcl(pAcl))
95 return STATUS_INVALID_ACL;
96
97 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
98 return STATUS_INVALID_ACL;
99
100 if (!pAceHeader)
101 return STATUS_ALLOTTED_SPACE_EXCEEDED;
102
103 /* calculate generic size of the ACE */
104 dwLengthSid = RtlLengthSid(pSid);
105 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
106 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
107 return STATUS_ALLOTTED_SPACE_EXCEEDED;
108
109 /* fill the new ACE */
110 pAceHeader->AceType = dwAceType;
111 pAceHeader->AceFlags = dwAceFlags;
112 pAceHeader->AceSize = dwAceSize;
113
114 /* skip past the ACE_HEADER of the ACE */
115 pAccessMask = (DWORD *)(pAceHeader + 1);
116 *pAccessMask = dwAccessMask;
117
118 /* skip past ACE->Mask */
119 pSidStart = pAccessMask + 1;
120 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
121
122 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
123 pAcl->AceCount++;
124
125 return STATUS_SUCCESS;
126 }
127
128 /*
129 * SID FUNCTIONS
130 */
131
132 /******************************************************************************
133 * RtlAllocateAndInitializeSid [NTDLL.@]
134 *
135 */
136 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
137 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
138 BYTE nSubAuthorityCount,
139 DWORD nSubAuthority0, DWORD nSubAuthority1,
140 DWORD nSubAuthority2, DWORD nSubAuthority3,
141 DWORD nSubAuthority4, DWORD nSubAuthority5,
142 DWORD nSubAuthority6, DWORD nSubAuthority7,
143 PSID *pSid )
144 {
145 SID *tmp_sid;
146
147 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
148 pIdentifierAuthority,nSubAuthorityCount,
149 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
150 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
151
152 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
153
154 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155 RtlLengthRequiredSid(nSubAuthorityCount))))
156 return STATUS_NO_MEMORY;
157
158 tmp_sid->Revision = SID_REVISION;
159
160 if (pIdentifierAuthority)
161 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
162 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
163
164 switch( nSubAuthorityCount )
165 {
166 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
167 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
168 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
169 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
170 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
171 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
172 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
173 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
174 break;
175 }
176 *pSid = tmp_sid;
177 return STATUS_SUCCESS;
178 }
179
180 /******************************************************************************
181 * RtlEqualSid [NTDLL.@]
182 *
183 * Determine if two SIDs are equal.
184 *
185 * PARAMS
186 * pSid1 [I] Source SID
187 * pSid2 [I] SID to compare with
188 *
189 * RETURNS
190 * TRUE, if pSid1 is equal to pSid2,
191 * FALSE otherwise.
192 */
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
194 {
195 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
196 return FALSE;
197
198 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
199 return FALSE;
200
201 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202 return FALSE;
203
204 return TRUE;
205 }
206
207 /******************************************************************************
208 * RtlEqualPrefixSid [NTDLL.@]
209 */
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
211 {
212 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
213 return FALSE;
214
215 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
216 return FALSE;
217
218 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
219 return FALSE;
220
221 return TRUE;
222 }
223
224
225 /******************************************************************************
226 * RtlFreeSid [NTDLL.@]
227 *
228 * Free the resources used by a SID.
229 *
230 * PARAMS
231 * pSid [I] SID to Free.
232 *
233 * RETURNS
234 * STATUS_SUCCESS.
235 */
236 DWORD WINAPI RtlFreeSid(PSID pSid)
237 {
238 TRACE("(%p)\n", pSid);
239 RtlFreeHeap( GetProcessHeap(), 0, pSid );
240 return STATUS_SUCCESS;
241 }
242
243 /**************************************************************************
244 * RtlLengthRequiredSid [NTDLL.@]
245 *
246 * Determine the amount of memory a SID will use
247 *
248 * PARAMS
249 * nrofsubauths [I] Number of Sub Authorities in the SID.
250 *
251 * RETURNS
252 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
253 */
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
255 {
256 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
257 }
258
259 /**************************************************************************
260 * RtlLengthSid [NTDLL.@]
261 *
262 * Determine the amount of memory a SID is using
263 *
264 * PARAMS
265 * pSid [I] SID to get the size of.
266 *
267 * RETURNS
268 * The size, in bytes, of pSid.
269 */
270 DWORD WINAPI RtlLengthSid(PSID pSid)
271 {
272 TRACE("sid=%p\n",pSid);
273 if (!pSid) return 0;
274 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
275 }
276
277 /**************************************************************************
278 * RtlInitializeSid [NTDLL.@]
279 *
280 * Initialise a SID.
281 *
282 * PARAMS
283 * pSid [I] SID to initialise
284 * pIdentifierAuthority [I] Identifier Authority
285 * nSubAuthorityCount [I] Number of Sub Authorities
286 *
287 * RETURNS
288 * Success: TRUE. pSid is initialised with the details given.
289 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
290 */
291 BOOL WINAPI RtlInitializeSid(
292 PSID pSid,
293 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294 BYTE nSubAuthorityCount)
295 {
296 int i;
297 SID* pisid=pSid;
298
299 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
300 return FALSE;
301
302 pisid->Revision = SID_REVISION;
303 pisid->SubAuthorityCount = nSubAuthorityCount;
304 if (pIdentifierAuthority)
305 pisid->IdentifierAuthority = *pIdentifierAuthority;
306
307 for (i = 0; i < nSubAuthorityCount; i++)
308 *RtlSubAuthoritySid(pSid, i) = 0;
309
310 return TRUE;
311 }
312
313 /**************************************************************************
314 * RtlSubAuthoritySid [NTDLL.@]
315 *
316 * Return the Sub Authority of a SID
317 *
318 * PARAMS
319 * pSid [I] SID to get the Sub Authority from.
320 * nSubAuthority [I] Sub Authority number.
321 *
322 * RETURNS
323 * A pointer to The Sub Authority value of pSid.
324 */
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
326 {
327 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
328 }
329
330 /**************************************************************************
331 * RtlIdentifierAuthoritySid [NTDLL.@]
332 *
333 * Return the Identifier Authority of a SID.
334 *
335 * PARAMS
336 * pSid [I] SID to get the Identifier Authority from.
337 *
338 * RETURNS
339 * A pointer to the Identifier Authority value of pSid.
340 */
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
342 {
343 return &(((SID*)pSid)->IdentifierAuthority);
344 }
345
346 /**************************************************************************
347 * RtlSubAuthorityCountSid [NTDLL.@]
348 *
349 * Get the number of Sub Authorities in a SID.
350 *
351 * PARAMS
352 * pSid [I] SID to get the count from.
353 *
354 * RETURNS
355 * A pointer to the Sub Authority count of pSid.
356 */
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
358 {
359 return &(((SID*)pSid)->SubAuthorityCount);
360 }
361
362 /**************************************************************************
363 * RtlCopySid [NTDLL.@]
364 */
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
366 {
367 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
369 return FALSE;
370
371 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
372 return FALSE;
373
374 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
375 return TRUE;
376 }
377 /******************************************************************************
378 * RtlValidSid [NTDLL.@]
379 *
380 * Determine if a SID is valid.
381 *
382 * PARAMS
383 * pSid [I] SID to check
384 *
385 * RETURNS
386 * TRUE if pSid is valid,
387 * FALSE otherwise.
388 */
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 {
391 BOOL ret;
392 __TRY
393 {
394 ret = TRUE;
395 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
397 {
398 ret = FALSE;
399 }
400 }
401 __EXCEPT_PAGE_FAULT
402 {
403 WARN("(%p): invalid pointer!\n", pSid);
404 return FALSE;
405 }
406 __ENDTRY
407 return ret;
408 }
409
410
411 /*
412 * security descriptor functions
413 */
414
415 /**************************************************************************
416 * RtlCreateSecurityDescriptor [NTDLL.@]
417 *
418 * Initialise a SECURITY_DESCRIPTOR.
419 *
420 * PARAMS
421 * lpsd [O] Descriptor to initialise.
422 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
423 *
424 * RETURNS
425 * Success: STATUS_SUCCESS.
426 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
427 */
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429 PSECURITY_DESCRIPTOR lpsd,
430 DWORD rev)
431 {
432 if (rev!=SECURITY_DESCRIPTOR_REVISION)
433 return STATUS_UNKNOWN_REVISION;
434 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
435 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
436 return STATUS_SUCCESS;
437 }
438
439 /**************************************************************************
440 * RtlCopySecurityDescriptor [NTDLL.@]
441 *
442 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
443 *
444 * PARAMS
445 * pSourceSD [O] SD to copy from.
446 * pDestinationSD [I] Destination SD.
447 *
448 * RETURNS
449 * Success: STATUS_SUCCESS.
450 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
451 */
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
453 {
454 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
455 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 BOOLEAN defaulted, present;
459 DWORD length;
460 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
461
462 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
464
465 /* copy initial data */
466 destSD->Revision = srcSD->Revision;
467 destSD->Sbz1 = srcSD->Sbz1;
468 destSD->Control = srcSD->Control;
469
470 /* copy Owner */
471 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472 length = RtlLengthSid(Owner);
473
474 if (isSelfRelative)
475 {
476 destSD->Owner = srcSD->Owner;
477 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
478 }
479 else
480 {
481 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482 RtlCopySid(length, destSD->Owner, Owner);
483 }
484
485 /* copy Group */
486 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487 length = RtlLengthSid(Group);
488
489 if (isSelfRelative)
490 {
491 destSD->Group = srcSD->Group;
492 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
493 }
494 else
495 {
496 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497 RtlCopySid(length, destSD->Group, Group);
498 }
499
500 /* copy Dacl */
501 if (srcSD->Control & SE_DACL_PRESENT)
502 {
503 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504 length = Dacl->AclSize;
505
506 if (isSelfRelative)
507 {
508 destSD->Dacl = srcSD->Dacl;
509 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
510 }
511 else
512 {
513 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, destSD->Dacl, Dacl);
515 }
516 }
517
518 /* copy Sacl */
519 if (srcSD->Control & SE_SACL_PRESENT)
520 {
521 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522 length = Sacl->AclSize;
523
524 if (isSelfRelative)
525 {
526 destSD->Sacl = srcSD->Sacl;
527 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
528 }
529 else
530 {
531 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532 copy_acl(length, destSD->Sacl, Sacl);
533 }
534 }
535
536 return STATUS_SUCCESS;
537 }
538
539 /**************************************************************************
540 * RtlValidSecurityDescriptor [NTDLL.@]
541 *
542 * Determine if a SECURITY_DESCRIPTOR is valid.
543 *
544 * PARAMS
545 * SecurityDescriptor [I] Descriptor to check.
546 *
547 * RETURNS
548 * Success: STATUS_SUCCESS.
549 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
550 */
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552 PSECURITY_DESCRIPTOR SecurityDescriptor)
553 {
554 if ( ! SecurityDescriptor )
555 return STATUS_INVALID_SECURITY_DESCR;
556 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557 return STATUS_UNKNOWN_REVISION;
558
559 return STATUS_SUCCESS;
560 }
561
562 /**************************************************************************
563 * RtlLengthSecurityDescriptor [NTDLL.@]
564 */
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566 PSECURITY_DESCRIPTOR pSecurityDescriptor)
567 {
568 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569 ULONG_PTR offset = 0;
570 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
571
572 if ( lpsd == NULL )
573 return 0;
574
575 if ( lpsd->Control & SE_SELF_RELATIVE)
576 offset = (ULONG_PTR) lpsd;
577
578 if ( lpsd->Owner != NULL )
579 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
580
581 if ( lpsd->Group != NULL )
582 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
583
584 if ( (lpsd->Control & SE_SACL_PRESENT) &&
585 lpsd->Sacl != NULL )
586 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
587
588 if ( (lpsd->Control & SE_DACL_PRESENT) &&
589 lpsd->Dacl != NULL )
590 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
591
592 return Size;
593 }
594
595 /******************************************************************************
596 * RtlGetDaclSecurityDescriptor [NTDLL.@]
597 *
598 */
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601 OUT PBOOLEAN lpbDaclPresent,
602 OUT PACL *pDacl,
603 OUT PBOOLEAN lpbDaclDefaulted)
604 {
605 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606
607 TRACE("(%p,%p,%p,%p)\n",
608 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609
610 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611 return STATUS_UNKNOWN_REVISION ;
612
613 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 {
615 if ( SE_SELF_RELATIVE & lpsd->Control)
616 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
617 else
618 *pDacl = lpsd->Dacl;
619
620 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
621 }
622 else
623 {
624 *pDacl = NULL;
625 *lpbDaclDefaulted = 0;
626 }
627
628 return STATUS_SUCCESS;
629 }
630
631 /**************************************************************************
632 * RtlSetDaclSecurityDescriptor [NTDLL.@]
633 */
634 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
635 PSECURITY_DESCRIPTOR pSecurityDescriptor,
636 BOOLEAN daclpresent,
637 PACL dacl,
638 BOOLEAN dacldefaulted )
639 {
640 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
641
642 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
643 return STATUS_UNKNOWN_REVISION;
644 if (lpsd->Control & SE_SELF_RELATIVE)
645 return STATUS_INVALID_SECURITY_DESCR;
646
647 if (!daclpresent)
648 {
649 lpsd->Control &= ~SE_DACL_PRESENT;
650 return STATUS_SUCCESS;
651 }
652
653 lpsd->Control |= SE_DACL_PRESENT;
654 lpsd->Dacl = dacl;
655
656 if (dacldefaulted)
657 lpsd->Control |= SE_DACL_DEFAULTED;
658 else
659 lpsd->Control &= ~SE_DACL_DEFAULTED;
660
661 return STATUS_SUCCESS;
662 }
663
664 /******************************************************************************
665 * RtlGetSaclSecurityDescriptor [NTDLL.@]
666 *
667 */
668 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
669 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
670 OUT PBOOLEAN lpbSaclPresent,
671 OUT PACL *pSacl,
672 OUT PBOOLEAN lpbSaclDefaulted)
673 {
674 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
675
676 TRACE("(%p,%p,%p,%p)\n",
677 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
678
679 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
680 return STATUS_UNKNOWN_REVISION;
681
682 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
683 {
684 if (SE_SELF_RELATIVE & lpsd->Control)
685 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
686 else
687 *pSacl = lpsd->Sacl;
688
689 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
690 }
691
692 return STATUS_SUCCESS;
693 }
694
695 /**************************************************************************
696 * RtlSetSaclSecurityDescriptor [NTDLL.@]
697 */
698 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
699 PSECURITY_DESCRIPTOR pSecurityDescriptor,
700 BOOLEAN saclpresent,
701 PACL sacl,
702 BOOLEAN sacldefaulted)
703 {
704 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
705
706 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
707 return STATUS_UNKNOWN_REVISION;
708 if (lpsd->Control & SE_SELF_RELATIVE)
709 return STATUS_INVALID_SECURITY_DESCR;
710 if (!saclpresent) {
711 lpsd->Control &= ~SE_SACL_PRESENT;
712 return 0;
713 }
714 lpsd->Control |= SE_SACL_PRESENT;
715 lpsd->Sacl = sacl;
716 if (sacldefaulted)
717 lpsd->Control |= SE_SACL_DEFAULTED;
718 else
719 lpsd->Control &= ~SE_SACL_DEFAULTED;
720 return STATUS_SUCCESS;
721 }
722
723 /**************************************************************************
724 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
725 */
726 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
727 PSECURITY_DESCRIPTOR pSecurityDescriptor,
728 PSID *Owner,
729 PBOOLEAN OwnerDefaulted)
730 {
731 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
732
733 if ( !lpsd || !Owner || !OwnerDefaulted )
734 return STATUS_INVALID_PARAMETER;
735
736 if ( lpsd->Control & SE_OWNER_DEFAULTED )
737 *OwnerDefaulted = TRUE;
738 else
739 *OwnerDefaulted = FALSE;
740
741 if (lpsd->Owner != NULL)
742 {
743 if (lpsd->Control & SE_SELF_RELATIVE)
744 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
745 else
746 *Owner = lpsd->Owner;
747
748 }
749 else
750 *Owner = NULL;
751
752 return STATUS_SUCCESS;
753 }
754
755 /**************************************************************************
756 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
757 */
758 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
759 PSECURITY_DESCRIPTOR pSecurityDescriptor,
760 PSID owner,
761 BOOLEAN ownerdefaulted)
762 {
763 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
764
765 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
766 return STATUS_UNKNOWN_REVISION;
767 if (lpsd->Control & SE_SELF_RELATIVE)
768 return STATUS_INVALID_SECURITY_DESCR;
769
770 lpsd->Owner = owner;
771 if (ownerdefaulted)
772 lpsd->Control |= SE_OWNER_DEFAULTED;
773 else
774 lpsd->Control &= ~SE_OWNER_DEFAULTED;
775 return STATUS_SUCCESS;
776 }
777
778 /**************************************************************************
779 * RtlSetGroupSecurityDescriptor [NTDLL.@]
780 */
781 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
782 PSECURITY_DESCRIPTOR pSecurityDescriptor,
783 PSID group,
784 BOOLEAN groupdefaulted)
785 {
786 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
787
788 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
789 return STATUS_UNKNOWN_REVISION;
790 if (lpsd->Control & SE_SELF_RELATIVE)
791 return STATUS_INVALID_SECURITY_DESCR;
792
793 lpsd->Group = group;
794 if (groupdefaulted)
795 lpsd->Control |= SE_GROUP_DEFAULTED;
796 else
797 lpsd->Control &= ~SE_GROUP_DEFAULTED;
798 return STATUS_SUCCESS;
799 }
800
801 /**************************************************************************
802 * RtlGetGroupSecurityDescriptor [NTDLL.@]
803 */
804 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
805 PSECURITY_DESCRIPTOR pSecurityDescriptor,
806 PSID *Group,
807 PBOOLEAN GroupDefaulted)
808 {
809 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
810
811 if ( !lpsd || !Group || !GroupDefaulted )
812 return STATUS_INVALID_PARAMETER;
813
814 if ( lpsd->Control & SE_GROUP_DEFAULTED )
815 *GroupDefaulted = TRUE;
816 else
817 *GroupDefaulted = FALSE;
818
819 if (lpsd->Group != NULL)
820 {
821 if (lpsd->Control & SE_SELF_RELATIVE)
822 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
823 else
824 *Group = lpsd->Group;
825 }
826 else
827 *Group = NULL;
828
829 return STATUS_SUCCESS;
830 }
831
832 /**************************************************************************
833 * RtlMakeSelfRelativeSD [NTDLL.@]
834 */
835 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
836 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
837 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
838 IN OUT LPDWORD lpdwBufferLength)
839 {
840 ULONG_PTR offsetRel;
841 ULONG length;
842 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
843 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
844
845 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
846 lpdwBufferLength ? *lpdwBufferLength: -1);
847
848 if (!lpdwBufferLength || !pAbs)
849 return STATUS_INVALID_PARAMETER;
850
851 length = RtlLengthSecurityDescriptor(pAbs);
852 if (*lpdwBufferLength < length)
853 {
854 *lpdwBufferLength = length;
855 return STATUS_BUFFER_TOO_SMALL;
856 }
857
858 if (!pRel)
859 return STATUS_INVALID_PARAMETER;
860
861 if (pAbs->Control & SE_SELF_RELATIVE)
862 {
863 memcpy(pRel, pAbs, length);
864 return STATUS_SUCCESS;
865 }
866
867 pRel->Revision = pAbs->Revision;
868 pRel->Sbz1 = pAbs->Sbz1;
869 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
870
871 offsetRel = sizeof(SECURITY_DESCRIPTOR);
872 if (pAbs->Owner)
873 {
874 pRel->Owner = (PSID) offsetRel;
875 length = RtlLengthSid(pAbs->Owner);
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
877 offsetRel += length;
878 }
879 else
880 {
881 pRel->Owner = NULL;
882 }
883
884 if (pAbs->Group)
885 {
886 pRel->Group = (PSID) offsetRel;
887 length = RtlLengthSid(pAbs->Group);
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
889 offsetRel += length;
890 }
891 else
892 {
893 pRel->Group = NULL;
894 }
895
896 if (pAbs->Sacl)
897 {
898 pRel->Sacl = (PACL) offsetRel;
899 length = pAbs->Sacl->AclSize;
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
901 offsetRel += length;
902 }
903 else
904 {
905 pRel->Sacl = NULL;
906 }
907
908 if (pAbs->Dacl)
909 {
910 pRel->Dacl = (PACL) offsetRel;
911 length = pAbs->Dacl->AclSize;
912 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
913 }
914 else
915 {
916 pRel->Dacl = NULL;
917 }
918
919 return STATUS_SUCCESS;
920 }
921
922
923 /**************************************************************************
924 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
925 */
926 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
927 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
928 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
929 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
930 OUT PACL pDacl,
931 OUT LPDWORD lpdwDaclSize,
932 OUT PACL pSacl,
933 OUT LPDWORD lpdwSaclSize,
934 OUT PSID pOwner,
935 OUT LPDWORD lpdwOwnerSize,
936 OUT PSID pPrimaryGroup,
937 OUT LPDWORD lpdwPrimaryGroupSize)
938 {
939 NTSTATUS status = STATUS_SUCCESS;
940 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
941 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
942
943 if (!pRel ||
944 !lpdwAbsoluteSecurityDescriptorSize ||
945 !lpdwDaclSize ||
946 !lpdwSaclSize ||
947 !lpdwOwnerSize ||
948 !lpdwPrimaryGroupSize ||
949 ~pRel->Control & SE_SELF_RELATIVE)
950 return STATUS_INVALID_PARAMETER;
951
952 /* Confirm buffers are sufficiently large */
953 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
954 {
955 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
956 status = STATUS_BUFFER_TOO_SMALL;
957 }
958
959 if (pRel->Control & SE_DACL_PRESENT &&
960 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
961 {
962 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
963 status = STATUS_BUFFER_TOO_SMALL;
964 }
965
966 if (pRel->Control & SE_SACL_PRESENT &&
967 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
968 {
969 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
970 status = STATUS_BUFFER_TOO_SMALL;
971 }
972
973 if (pRel->Owner &&
974 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
975 {
976 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
977 status = STATUS_BUFFER_TOO_SMALL;
978 }
979
980 if (pRel->Group &&
981 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
982 {
983 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
984 status = STATUS_BUFFER_TOO_SMALL;
985 }
986
987 if (status != STATUS_SUCCESS)
988 return status;
989
990 /* Copy structures, and clear the ones we don't set */
991 pAbs->Revision = pRel->Revision;
992 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
993 pAbs->Sacl = NULL;
994 pAbs->Dacl = NULL;
995 pAbs->Owner = NULL;
996 pAbs->Group = NULL;
997
998 if (pRel->Control & SE_SACL_PRESENT)
999 {
1000 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
1001
1002 memcpy(pSacl, pAcl, pAcl->AclSize);
1003 pAbs->Sacl = pSacl;
1004 }
1005
1006 if (pRel->Control & SE_DACL_PRESENT)
1007 {
1008 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1009 memcpy(pDacl, pAcl, pAcl->AclSize);
1010 pAbs->Dacl = pDacl;
1011 }
1012
1013 if (pRel->Owner)
1014 {
1015 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1016 memcpy(pOwner, psid, RtlLengthSid(psid));
1017 pAbs->Owner = pOwner;
1018 }
1019
1020 if (pRel->Group)
1021 {
1022 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1023 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1024 pAbs->Group = pPrimaryGroup;
1025 }
1026
1027 return status;
1028 }
1029
1030 /******************************************************************************
1031 * RtlGetControlSecurityDescriptor (NTDLL.@)
1032 */
1033 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1034 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1035 PSECURITY_DESCRIPTOR_CONTROL pControl,
1036 LPDWORD lpdwRevision)
1037 {
1038 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1039
1040 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1041
1042 *lpdwRevision = lpsd->Revision;
1043
1044 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1045 return STATUS_UNKNOWN_REVISION;
1046
1047 *pControl = lpsd->Control;
1048
1049 return STATUS_SUCCESS;
1050 }
1051
1052 /******************************************************************************
1053 * RtlSetControlSecurityDescriptor (NTDLL.@)
1054 */
1055 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1056 PSECURITY_DESCRIPTOR SecurityDescriptor,
1057 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1058 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1059 {
1060 SECURITY_DESCRIPTOR_CONTROL const immutable
1061 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1062 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1063 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1064 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1065 ;
1066
1067 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1068
1069 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1070 ControlBitsOfInterest, ControlBitsToSet);
1071
1072 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1073 return STATUS_INVALID_PARAMETER;
1074
1075 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1076 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1077
1078 return STATUS_SUCCESS;
1079 }
1080
1081
1082 /**************************************************************************
1083 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1084 */
1085 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1086 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1087 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1088 PULONG BufferLength)
1089 {
1090 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1091
1092 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1093 SelfRelativeSecurityDescriptor, BufferLength);
1094
1095 if (abs->Control & SE_SELF_RELATIVE)
1096 return STATUS_BAD_DESCRIPTOR_FORMAT;
1097
1098 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1099 SelfRelativeSecurityDescriptor, BufferLength);
1100 }
1101
1102
1103 /*
1104 * access control list's
1105 */
1106
1107 /**************************************************************************
1108 * RtlCreateAcl [NTDLL.@]
1109 *
1110 * NOTES
1111 * This should return NTSTATUS
1112 */
1113 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1114 {
1115 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1116
1117 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1118 return STATUS_INVALID_PARAMETER;
1119 if (size<sizeof(ACL))
1120 return STATUS_BUFFER_TOO_SMALL;
1121 if (size>0xFFFF)
1122 return STATUS_INVALID_PARAMETER;
1123
1124 memset(acl,'\0',sizeof(ACL));
1125 acl->AclRevision = rev;
1126 acl->AclSize = size;
1127 acl->AceCount = 0;
1128 return STATUS_SUCCESS;
1129 }
1130
1131 /**************************************************************************
1132 * RtlFirstFreeAce [NTDLL.@]
1133 * looks for the AceCount+1 ACE, and if it is still within the alloced
1134 * ACL, return a pointer to it
1135 */
1136 BOOLEAN WINAPI RtlFirstFreeAce(
1137 PACL acl,
1138 PACE_HEADER *x)
1139 {
1140 PACE_HEADER ace;
1141 int i;
1142
1143 *x = 0;
1144 ace = (PACE_HEADER)(acl+1);
1145 for (i=0;i<acl->AceCount;i++) {
1146 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1147 return 0;
1148 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1149 }
1150 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1151 return 0;
1152 *x = ace;
1153 return 1;
1154 }
1155
1156 /**************************************************************************
1157 * RtlAddAce [NTDLL.@]
1158 */
1159 NTSTATUS WINAPI RtlAddAce(
1160 PACL acl,
1161 DWORD rev,
1162 DWORD xnrofaces,
1163 PACE_HEADER acestart,
1164 DWORD acelen)
1165 {
1166 PACE_HEADER ace,targetace;
1167 int nrofaces;
1168
1169 if (acl->AclRevision != ACL_REVISION)
1170 return STATUS_INVALID_PARAMETER;
1171 if (!RtlFirstFreeAce(acl,&targetace))
1172 return STATUS_INVALID_PARAMETER;
1173 nrofaces=0;ace=acestart;
1174 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1175 nrofaces++;
1176 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1177 }
1178 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1179 return STATUS_INVALID_PARAMETER;
1180 memcpy((LPBYTE)targetace,acestart,acelen);
1181 acl->AceCount+=nrofaces;
1182 return STATUS_SUCCESS;
1183 }
1184
1185 /**************************************************************************
1186 * RtlDeleteAce [NTDLL.@]
1187 */
1188 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1189 {
1190 NTSTATUS status;
1191 PACE_HEADER pAce;
1192
1193 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1194
1195 if (STATUS_SUCCESS == status)
1196 {
1197 PACE_HEADER pcAce;
1198 DWORD len = 0;
1199
1200 /* skip over the ACE we are deleting */
1201 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1202 dwAceIndex++;
1203
1204 /* calculate the length of the rest */
1205 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1206 {
1207 len += pcAce->AceSize;
1208 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1209 }
1210
1211 /* slide them all backwards */
1212 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1213 pAcl->AceCount--;
1214 }
1215
1216 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1217
1218 return status;
1219 }
1220
1221 /******************************************************************************
1222 * RtlAddAccessAllowedAce [NTDLL.@]
1223 */
1224 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1225 IN OUT PACL pAcl,
1226 IN DWORD dwAceRevision,
1227 IN DWORD AccessMask,
1228 IN PSID pSid)
1229 {
1230 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1231 }
1232
1233 /******************************************************************************
1234 * RtlAddAccessAllowedAceEx [NTDLL.@]
1235 */
1236 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1237 IN OUT PACL pAcl,
1238 IN DWORD dwAceRevision,
1239 IN DWORD AceFlags,
1240 IN DWORD AccessMask,
1241 IN PSID pSid)
1242 {
1243 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1244
1245 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1246 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1247 }
1248
1249 /******************************************************************************
1250 * RtlAddAccessDeniedAce [NTDLL.@]
1251 */
1252 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1253 IN OUT PACL pAcl,
1254 IN DWORD dwAceRevision,
1255 IN DWORD AccessMask,
1256 IN PSID pSid)
1257 {
1258 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1259 }
1260
1261 /******************************************************************************
1262 * RtlAddAccessDeniedAceEx [NTDLL.@]
1263 */
1264 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1265 IN OUT PACL pAcl,
1266 IN DWORD dwAceRevision,
1267 IN DWORD AceFlags,
1268 IN DWORD AccessMask,
1269 IN PSID pSid)
1270 {
1271 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1272
1273 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1274 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1275 }
1276
1277 /**************************************************************************
1278 * RtlAddAuditAccessAce [NTDLL.@]
1279 */
1280 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1281 IN OUT PACL pAcl,
1282 IN DWORD dwAceRevision,
1283 IN DWORD dwAceFlags,
1284 IN DWORD dwAccessMask,
1285 IN PSID pSid,
1286 IN BOOL bAuditSuccess,
1287 IN BOOL bAuditFailure)
1288 {
1289 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1290 pSid,bAuditSuccess,bAuditFailure);
1291
1292 if (bAuditSuccess)
1293 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1294
1295 if (bAuditFailure)
1296 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1297
1298 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1299 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1300 }
1301
1302 /**************************************************************************
1303 * RtlAddAuditAccessAce [NTDLL.@]
1304 */
1305 NTSTATUS WINAPI RtlAddAuditAccessAce(
1306 IN OUT PACL pAcl,
1307 IN DWORD dwAceRevision,
1308 IN DWORD dwAccessMask,
1309 IN PSID pSid,
1310 IN BOOL bAuditSuccess,
1311 IN BOOL bAuditFailure)
1312 {
1313 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1314 }
1315
1316 /******************************************************************************
1317 * RtlValidAcl [NTDLL.@]
1318 */
1319 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1320 {
1321 BOOLEAN ret;
1322 TRACE("(%p)\n", pAcl);
1323
1324 __TRY
1325 {
1326 PACE_HEADER ace;
1327 int i;
1328
1329 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1330 pAcl->AclRevision > MAX_ACL_REVISION)
1331 ret = FALSE;
1332 else
1333 {
1334 ace = (PACE_HEADER)(pAcl+1);
1335 ret = TRUE;
1336 for (i=0;i<=pAcl->AceCount;i++)
1337 {
1338 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1339 {
1340 ret = FALSE;
1341 break;
1342 }
1343 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1344 }
1345 }
1346 }
1347 __EXCEPT_PAGE_FAULT
1348 {
1349 WARN("(%p): invalid pointer!\n", pAcl);
1350 return 0;
1351 }
1352 __ENDTRY
1353 return ret;
1354 }
1355
1356 /******************************************************************************
1357 * RtlGetAce [NTDLL.@]
1358 */
1359 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1360 {
1361 PACE_HEADER ace;
1362
1363 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1364
1365 if (dwAceIndex >= pAcl->AceCount)
1366 return STATUS_INVALID_PARAMETER;
1367
1368 ace = (PACE_HEADER)(pAcl + 1);
1369 for (;dwAceIndex;dwAceIndex--)
1370 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1371
1372 *pAce = (LPVOID) ace;
1373
1374 return STATUS_SUCCESS;
1375 }
1376
1377 /*
1378 * misc
1379 */
1380
1381 /******************************************************************************
1382 * RtlAdjustPrivilege [NTDLL.@]
1383 *
1384 * Enables or disables a privilege from the calling thread or process.
1385 *
1386 * PARAMS
1387 * Privilege [I] Privilege index to change.
1388 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1389 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1390 * Enabled [O] Whether privilege was previously enabled or disabled.
1391 *
1392 * RETURNS
1393 * Success: STATUS_SUCCESS.
1394 * Failure: NTSTATUS code.
1395 *
1396 * SEE ALSO
1397 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1398 *
1399 */
1400 NTSTATUS WINAPI
1401 RtlAdjustPrivilege(ULONG Privilege,
1402 BOOLEAN Enable,
1403 BOOLEAN CurrentThread,
1404 PBOOLEAN Enabled)
1405 {
1406 TOKEN_PRIVILEGES NewState;
1407 TOKEN_PRIVILEGES OldState;
1408 ULONG ReturnLength;
1409 HANDLE TokenHandle;
1410 NTSTATUS Status;
1411
1412 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1413 CurrentThread ? "TRUE" : "FALSE", Enabled);
1414
1415 if (CurrentThread)
1416 {
1417 Status = NtOpenThreadToken(GetCurrentThread(),
1418 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1419 FALSE,
1420 &TokenHandle);
1421 }
1422 else
1423 {
1424 Status = NtOpenProcessToken(GetCurrentProcess(),
1425 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1426 &TokenHandle);
1427 }
1428
1429 if (!NT_SUCCESS(Status))
1430 {
1431 WARN("Retrieving token handle failed (Status %x)\n", Status);
1432 return Status;
1433 }
1434
1435 OldState.PrivilegeCount = 1;
1436
1437 NewState.PrivilegeCount = 1;
1438 NewState.Privileges[0].Luid.LowPart = Privilege;
1439 NewState.Privileges[0].Luid.HighPart = 0;
1440 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1441
1442 Status = NtAdjustPrivilegesToken(TokenHandle,
1443 FALSE,
1444 &NewState,
1445 sizeof(TOKEN_PRIVILEGES),
1446 &OldState,
1447 &ReturnLength);
1448 NtClose (TokenHandle);
1449 if (Status == STATUS_NOT_ALL_ASSIGNED)
1450 {
1451 TRACE("Failed to assign all privileges\n");
1452 return STATUS_PRIVILEGE_NOT_HELD;
1453 }
1454 if (!NT_SUCCESS(Status))
1455 {
1456 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1457 return Status;
1458 }
1459
1460 if (OldState.PrivilegeCount == 0)
1461 *Enabled = Enable;
1462 else
1463 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1464
1465 return STATUS_SUCCESS;
1466 }
1467
1468 /******************************************************************************
1469 * RtlImpersonateSelf [NTDLL.@]
1470 *
1471 * Makes an impersonation token that represents the process user and assigns
1472 * to the current thread.
1473 *
1474 * PARAMS
1475 * ImpersonationLevel [I] Level at which to impersonate.
1476 *
1477 * RETURNS
1478 * Success: STATUS_SUCCESS.
1479 * Failure: NTSTATUS code.
1480 */
1481 NTSTATUS WINAPI
1482 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1483 {
1484 NTSTATUS Status;
1485 OBJECT_ATTRIBUTES ObjectAttributes;
1486 HANDLE ProcessToken;
1487 HANDLE ImpersonationToken;
1488
1489 TRACE("(%08x)\n", ImpersonationLevel);
1490
1491 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1492 &ProcessToken);
1493 if (Status != STATUS_SUCCESS)
1494 return Status;
1495
1496 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1497
1498 Status = NtDuplicateToken( ProcessToken,
1499 TOKEN_IMPERSONATE,
1500 &ObjectAttributes,
1501 ImpersonationLevel,
1502 TokenImpersonation,
1503 &ImpersonationToken );
1504 if (Status != STATUS_SUCCESS)
1505 {
1506 NtClose( ProcessToken );
1507 return Status;
1508 }
1509
1510 Status = NtSetInformationThread( GetCurrentThread(),
1511 ThreadImpersonationToken,
1512 &ImpersonationToken,
1513 sizeof(ImpersonationToken) );
1514
1515 NtClose( ImpersonationToken );
1516 NtClose( ProcessToken );
1517
1518 return Status;
1519 }
1520
1521 /******************************************************************************
1522 * NtAccessCheck [NTDLL.@]
1523 * ZwAccessCheck [NTDLL.@]
1524 *
1525 * Checks that a user represented by a token is allowed to access an object
1526 * represented by a security descriptor.
1527 *
1528 * PARAMS
1529 * SecurityDescriptor [I] The security descriptor of the object to check.
1530 * ClientToken [I] Token of the user accessing the object.
1531 * DesiredAccess [I] The desired access to the object.
1532 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1533 * PrivilegeSet [I/O] Privileges used during the access check.
1534 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1535 * GrantedAccess [O] The actual access rights granted.
1536 * AccessStatus [O] The status of the access check.
1537 *
1538 * RETURNS
1539 * NTSTATUS code.
1540 *
1541 * NOTES
1542 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1543 * the maximum access rights allowed by the SD and returns them in
1544 * GrantedAccess.
1545 * The SecurityDescriptor must have a valid owner and groups present,
1546 * otherwise the function will fail.
1547 */
1548 NTSTATUS WINAPI
1549 NtAccessCheck(
1550 PSECURITY_DESCRIPTOR SecurityDescriptor,
1551 HANDLE ClientToken,
1552 ACCESS_MASK DesiredAccess,
1553 PGENERIC_MAPPING GenericMapping,
1554 PPRIVILEGE_SET PrivilegeSet,
1555 PULONG ReturnLength,
1556 PULONG GrantedAccess,
1557 NTSTATUS *AccessStatus)
1558 {
1559 NTSTATUS status;
1560
1561 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1562 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1563 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1564
1565 if (!PrivilegeSet || !ReturnLength)
1566 return STATUS_ACCESS_VIOLATION;
1567
1568 SERVER_START_REQ( access_check )
1569 {
1570 struct security_descriptor sd;
1571 PSID owner;
1572 PSID group;
1573 PACL sacl;
1574 PACL dacl;
1575 BOOLEAN defaulted, present;
1576 DWORD revision;
1577 SECURITY_DESCRIPTOR_CONTROL control;
1578
1579 req->handle = wine_server_obj_handle( ClientToken );
1580 req->desired_access = DesiredAccess;
1581 req->mapping_read = GenericMapping->GenericRead;
1582 req->mapping_write = GenericMapping->GenericWrite;
1583 req->mapping_execute = GenericMapping->GenericExecute;
1584 req->mapping_all = GenericMapping->GenericAll;
1585
1586 /* marshal security descriptor */
1587 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1588 sd.control = control & ~SE_SELF_RELATIVE;
1589 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1590 sd.owner_len = RtlLengthSid( owner );
1591 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1592 sd.group_len = RtlLengthSid( group );
1593 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1594 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1595 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1596 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1597
1598 wine_server_add_data( req, &sd, sizeof(sd) );
1599 wine_server_add_data( req, owner, sd.owner_len );
1600 wine_server_add_data( req, group, sd.group_len );
1601 wine_server_add_data( req, sacl, sd.sacl_len );
1602 wine_server_add_data( req, dacl, sd.dacl_len );
1603
1604 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1605
1606 status = wine_server_call( req );
1607
1608 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1609 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1610
1611 if (status == STATUS_SUCCESS)
1612 {
1613 *AccessStatus = reply->access_status;
1614 *GrantedAccess = reply->access_granted;
1615 }
1616 }
1617 SERVER_END_REQ;
1618
1619 return status;
1620 }
1621
1622 /******************************************************************************
1623 * NtSetSecurityObject [NTDLL.@]
1624 * ZwSetSecurityObject [NTDLL.@]
1625 *
1626 * Sets specified parts of the object's security descriptor.
1627 *
1628 * PARAMS
1629 * Handle [I] Handle to the object to change security descriptor of.
1630 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1631 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1632 *
1633 * RETURNS
1634 * NTSTATUS code.
1635 *
1636 */
1637 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1638 SECURITY_INFORMATION SecurityInformation,
1639 PSECURITY_DESCRIPTOR SecurityDescriptor)
1640 {
1641 NTSTATUS status;
1642 struct security_descriptor sd;
1643 PACL dacl = NULL, sacl = NULL;
1644 PSID owner = NULL, group = NULL;
1645 BOOLEAN defaulted, present;
1646 DWORD revision;
1647 SECURITY_DESCRIPTOR_CONTROL control;
1648
1649 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1650
1651 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1652
1653 memset( &sd, 0, sizeof(sd) );
1654 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1655 if (status != STATUS_SUCCESS) return status;
1656 sd.control = control & ~SE_SELF_RELATIVE;
1657
1658 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1659 {
1660 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1661 if (status != STATUS_SUCCESS) return status;
1662 if (!(sd.owner_len = RtlLengthSid( owner )))
1663 return STATUS_INVALID_SECURITY_DESCR;
1664 }
1665
1666 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1667 {
1668 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1669 if (status != STATUS_SUCCESS) return status;
1670 if (!(sd.group_len = RtlLengthSid( group )))
1671 return STATUS_INVALID_SECURITY_DESCR;
1672 }
1673
1674 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1675 {
1676 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1677 if (status != STATUS_SUCCESS) return status;
1678 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1679 sd.control |= SE_SACL_PRESENT;
1680 }
1681
1682 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1683 {
1684 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1685 if (status != STATUS_SUCCESS) return status;
1686 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1687 sd.control |= SE_DACL_PRESENT;
1688 }
1689
1690 SERVER_START_REQ( set_security_object )
1691 {
1692 req->handle = wine_server_obj_handle( Handle );
1693 req->security_info = SecurityInformation;
1694
1695 wine_server_add_data( req, &sd, sizeof(sd) );
1696 wine_server_add_data( req, owner, sd.owner_len );
1697 wine_server_add_data( req, group, sd.group_len );
1698 wine_server_add_data( req, sacl, sd.sacl_len );
1699 wine_server_add_data( req, dacl, sd.dacl_len );
1700 status = wine_server_call( req );
1701 }
1702 SERVER_END_REQ;
1703
1704 return status;
1705 }
1706
1707 /******************************************************************************
1708 * RtlConvertSidToUnicodeString (NTDLL.@)
1709 *
1710 * The returned SID is used to access the USER registry hive usually
1711 *
1712 * the native function returns something like
1713 * "S-1-5-21-0000000000-000000000-0000000000-500";
1714 */
1715 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1716 PUNICODE_STRING String,
1717 PSID pSid,
1718 BOOLEAN AllocateString)
1719 {
1720 static const WCHAR formatW[] = {'-','%','u',0};
1721 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1722 WCHAR *p = buffer;
1723 const SID *sid = (const SID *)pSid;
1724 DWORD i, len;
1725
1726 *p++ = 'S';
1727 p += sprintfW( p, formatW, sid->Revision );
1728 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1729 sid->IdentifierAuthority.Value[4] ),
1730 MAKEWORD( sid->IdentifierAuthority.Value[3],
1731 sid->IdentifierAuthority.Value[2] )));
1732 for (i = 0; i < sid->SubAuthorityCount; i++)
1733 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1734
1735 len = (p + 1 - buffer) * sizeof(WCHAR);
1736
1737 String->Length = len - sizeof(WCHAR);
1738 if (AllocateString)
1739 {
1740 String->MaximumLength = len;
1741 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1742 return STATUS_NO_MEMORY;
1743 }
1744 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1745
1746 memcpy( String->Buffer, buffer, len );
1747 return STATUS_SUCCESS;
1748 }
1749
1750 /******************************************************************************
1751 * RtlQueryInformationAcl (NTDLL.@)
1752 */
1753 NTSTATUS WINAPI RtlQueryInformationAcl(
1754 PACL pAcl,
1755 LPVOID pAclInformation,
1756 DWORD nAclInformationLength,
1757 ACL_INFORMATION_CLASS dwAclInformationClass)
1758 {
1759 NTSTATUS status = STATUS_SUCCESS;
1760
1761 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1762 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1763
1764 switch (dwAclInformationClass)
1765 {
1766 case AclRevisionInformation:
1767 {
1768 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1769
1770 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1771 status = STATUS_INVALID_PARAMETER;
1772 else
1773 paclrev->AclRevision = pAcl->AclRevision;
1774
1775 break;
1776 }
1777
1778 case AclSizeInformation:
1779 {
1780 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1781
1782 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1783 status = STATUS_INVALID_PARAMETER;
1784 else
1785 {
1786 paclsize->AceCount = pAcl->AceCount;
1787 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1788 if (pAcl->AclSize < paclsize->AclBytesInUse)
1789 {
1790 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1791 paclsize->AclBytesFree = 0;
1792 paclsize->AclBytesInUse = pAcl->AclSize;
1793 }
1794 else
1795 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1796 }
1797
1798 break;
1799 }
1800
1801 default:
1802 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1803 status = STATUS_INVALID_PARAMETER;
1804 }
1805
1806 return status;
1807 }
1808
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.