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