1511d0027282e100d3009961f381f4aa0e3e9330
[reactos.git] / lib / ntdll / rtl / sd.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Security descriptor functions
6  * FILE:              lib/ntdll/rtl/sd.c
7  * PROGRAMER:         David Welch <welch@cwcom.net>
8  * REVISION HISTORY:
9  *                 26/07/98: Added stubs for security functions
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15
16 #include <ntdll/ntdll.h>
17
18 /* FUNCTIONS ***************************************************************/
19
20 NTSTATUS STDCALL
21 RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
22                             ULONG Revision)
23 {
24   if (Revision != 1)
25     {
26       return(STATUS_UNSUCCESSFUL);
27     }
28
29   SecurityDescriptor->Revision = 1;
30   SecurityDescriptor->Sbz1 = 0;
31   SecurityDescriptor->Control = 0;
32   SecurityDescriptor->Owner = NULL;
33   SecurityDescriptor->Group = NULL;
34   SecurityDescriptor->Sacl = NULL;
35   SecurityDescriptor->Dacl = NULL;
36
37   return(STATUS_SUCCESS);
38 }
39
40 /*
41  * @implemented
42  */
43 ULONG STDCALL
44 RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor)
45 {
46   PSID Owner;
47   PSID Group;
48   ULONG Length;
49   PACL Dacl;
50   PACL Sacl;
51
52   Length = sizeof(SECURITY_DESCRIPTOR);
53
54   if (SecurityDescriptor->Owner != NULL)
55     {
56         Owner = SecurityDescriptor->Owner;
57         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
58           {
59              Owner = (PSID)((ULONG)Owner + 
60                             (ULONG)SecurityDescriptor);
61           }
62         Length = Length + ((sizeof(SID) + (Owner->SubAuthorityCount - 1) * 
63                            sizeof(ULONG) + 3) & 0xfc);
64     }
65
66   if (SecurityDescriptor->Group != NULL)
67     {
68         Group = SecurityDescriptor->Group;
69         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
70           {
71              Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor);
72           }
73         Length = Length + ((sizeof(SID) + (Group->SubAuthorityCount - 1) *
74                            sizeof(ULONG) + 3) & 0xfc);
75     }
76
77   if (SecurityDescriptor->Control & SE_DACL_PRESENT &&
78       SecurityDescriptor->Dacl != NULL)
79     {
80         Dacl = SecurityDescriptor->Dacl;
81         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
82           {
83              Dacl = (PACL)((ULONG)Dacl + (PVOID)SecurityDescriptor);
84           }
85         Length = Length + ((Dacl->AclSize + 3) & 0xfc);
86     }
87
88   if (SecurityDescriptor->Control & SE_SACL_PRESENT &&
89       SecurityDescriptor->Sacl != NULL)
90     {
91         Sacl = SecurityDescriptor->Sacl;
92         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
93           {
94              Sacl = (PACL)((ULONG)Sacl + (PVOID)SecurityDescriptor);
95           }
96         Length = Length + ((Sacl->AclSize + 3) & 0xfc);
97     }
98
99   return(Length);
100 }
101
102
103 /*
104  * @implemented
105  */
106 NTSTATUS STDCALL
107 RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
108                              PBOOLEAN DaclPresent,
109                              PACL* Dacl,
110                              PBOOLEAN DaclDefaulted)
111 {
112    if (SecurityDescriptor->Revision != 1)
113      {
114         return(STATUS_UNSUCCESSFUL);
115      }
116    if (!(SecurityDescriptor->Control & SE_DACL_PRESENT))
117      {
118         *DaclPresent = 0;
119         return(STATUS_SUCCESS);
120      }
121    *DaclPresent = 1;
122    if (SecurityDescriptor->Dacl == NULL)
123      {
124         *Dacl = NULL;
125      }
126    else
127      {
128         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
129           {
130              *Dacl = (PACL)((ULONG)SecurityDescriptor->Dacl +
131                             (PVOID)SecurityDescriptor);
132           }
133         else
134           {
135              *Dacl = SecurityDescriptor->Dacl;
136           }
137      }
138    if (SecurityDescriptor->Control & SE_DACL_DEFAULTED)
139      {
140         *DaclDefaulted = 1;
141      }
142    else
143      {
144         *DaclDefaulted = 0;
145      }
146    return(STATUS_SUCCESS);
147 }
148
149
150 /*
151  * @implemented
152  */
153 NTSTATUS STDCALL
154 RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
155                              BOOLEAN DaclPresent,
156                              PACL Dacl,
157                              BOOLEAN DaclDefaulted)
158 {
159    if (SecurityDescriptor->Revision != 1)
160      {
161         return(STATUS_UNSUCCESSFUL);
162      }
163    if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
164      {
165         return(STATUS_UNSUCCESSFUL);
166      }
167    if (!DaclPresent)
168      {
169         SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_PRESENT);
170         return(STATUS_SUCCESS);
171      }
172    SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_PRESENT;
173    SecurityDescriptor->Dacl = Dacl;
174    SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_DEFAULTED);
175    if (DaclDefaulted)
176      {
177         SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_DEFAULTED;
178      }
179    return(STATUS_SUCCESS);
180 }
181
182
183 /*
184  * @implemented
185  */
186 BOOLEAN STDCALL
187 RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor)
188 {
189   PSID Owner;
190   PSID Group;
191   PACL Sacl;
192   PACL Dacl;
193
194   if (SecurityDescriptor->Revision != 1)
195     {
196       return(FALSE);
197     }
198
199   Owner = SecurityDescriptor->Owner;
200   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
201     {
202       Owner = (PSID)((ULONG)Owner + (ULONG)SecurityDescriptor);
203     }
204
205   if (!RtlValidSid(Owner))
206     {
207       return(FALSE);
208     }
209
210   Group = SecurityDescriptor->Group;
211   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
212     {
213       Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor);
214     }
215
216   if (!RtlValidSid(Group))
217     {
218       return(FALSE);
219     }
220
221   if (SecurityDescriptor->Control & SE_DACL_PRESENT &&
222       SecurityDescriptor->Dacl != NULL)
223     {
224       Dacl = SecurityDescriptor->Dacl;
225       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
226         {
227           Dacl = (PACL)((ULONG)Dacl + (ULONG)SecurityDescriptor);
228         }
229
230       if (!RtlValidAcl(Dacl))
231         {
232           return(FALSE);
233         }
234     }
235
236   if (SecurityDescriptor->Control & SE_SACL_PRESENT &&
237       SecurityDescriptor->Sacl != NULL)
238     {
239       Sacl = SecurityDescriptor->Sacl;
240       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
241         {
242           Sacl = (PACL)((ULONG)Sacl + (ULONG)SecurityDescriptor);
243         }
244
245       if (!RtlValidAcl(Sacl))
246         {
247           return(FALSE);
248         }
249     }
250
251   return(TRUE);
252 }
253
254
255 /*
256  * @implemented
257  */
258 NTSTATUS STDCALL
259 RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
260                               PSID Owner,
261                               BOOLEAN OwnerDefaulted)
262 {
263    if (SecurityDescriptor->Revision != 1)
264      {
265         return(STATUS_UNSUCCESSFUL);
266      }
267    if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
268      {
269         return(STATUS_UNSUCCESSFUL);
270      }
271    SecurityDescriptor->Owner = Owner;
272    SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_OWNER_DEFAULTED);
273    if (OwnerDefaulted)
274      {
275         SecurityDescriptor->Control = SecurityDescriptor->Control | SE_OWNER_DEFAULTED;
276      }
277    return(STATUS_SUCCESS);
278 }
279
280 /*
281  * @implemented
282  */
283 NTSTATUS STDCALL
284 RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
285                               PSID* Owner,
286                               PBOOLEAN OwnerDefaulted)
287 {
288    if (SecurityDescriptor->Revision != 1)
289      {
290         return(STATUS_UNSUCCESSFUL);
291      }
292    if (SecurityDescriptor->Owner != NULL)
293      {
294         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
295           {
296              *Owner = (PSID)((ULONG)SecurityDescriptor->Owner +
297                              (PVOID)SecurityDescriptor);
298           }
299         else
300           {
301              *Owner = SecurityDescriptor->Owner;
302           }
303      }
304    else
305      {
306         *Owner = NULL;
307      }
308    if (SecurityDescriptor->Control & SE_OWNER_DEFAULTED)
309      {
310         *OwnerDefaulted = 1;
311      }
312    else
313      {
314         *OwnerDefaulted = 0;
315      }
316    return(STATUS_SUCCESS);
317 }
318
319 /*
320  * @implemented
321  */
322 NTSTATUS STDCALL
323 RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
324                               PSID Group,
325                               BOOLEAN GroupDefaulted)
326 {
327    if (SecurityDescriptor->Revision != 1)
328      {
329         return(STATUS_UNSUCCESSFUL);
330      }
331    if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
332      {
333         return(STATUS_UNSUCCESSFUL);
334      }
335    SecurityDescriptor->Group = Group;
336    SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_GROUP_DEFAULTED);
337    if (GroupDefaulted)
338      {
339         SecurityDescriptor->Control = SecurityDescriptor->Control | SE_GROUP_DEFAULTED;
340      }
341    return(STATUS_SUCCESS);
342 }
343
344 /*
345  * @implemented
346  */
347 NTSTATUS STDCALL
348 RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
349                               PSID* Group,
350                               PBOOLEAN GroupDefaulted)
351 {
352    if (SecurityDescriptor->Revision != 1)
353      {
354         return(STATUS_UNSUCCESSFUL);
355      }
356    if (SecurityDescriptor->Group != NULL)
357      {
358         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
359           {
360              *Group = (PSID)((ULONG)SecurityDescriptor->Group +
361                              (PVOID)SecurityDescriptor);
362           }
363         else
364           {
365              *Group = SecurityDescriptor->Group;
366           }
367      }
368    else
369      {
370         *Group = NULL;
371      }
372    if (SecurityDescriptor->Control & SE_GROUP_DEFAULTED)
373      {
374         *GroupDefaulted = 1;
375      }
376    else
377      {
378         *GroupDefaulted = 0;
379      }
380    return(STATUS_SUCCESS);
381 }
382
383
384 static VOID
385 RtlpQuerySecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
386                             PSID* Owner,
387                             PULONG OwnerLength,
388                             PSID* Group,
389                             PULONG GroupLength,
390                             PACL* Dacl,
391                             PULONG DaclLength,
392                             PACL* Sacl,
393                             PULONG SaclLength)
394 {
395   if (SecurityDescriptor->Owner == NULL)
396     {
397       *Owner = NULL;
398     }
399   else
400     {
401       *Owner = SecurityDescriptor->Owner;
402       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
403         {
404           *Owner = (PSID)((ULONG)*Owner + (ULONG)SecurityDescriptor);
405         }
406     }
407
408   if (*Owner != NULL)
409     {
410       *OwnerLength = (RtlLengthSid(*Owner) + 3) & ~3;
411     }
412   else
413     {
414       *OwnerLength = 0;
415     }
416
417   if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
418       SecurityDescriptor->Dacl != NULL)
419     {
420       *Dacl = SecurityDescriptor->Dacl;
421       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
422         {
423           *Dacl = (PACL)((ULONG)*Dacl + (ULONG)SecurityDescriptor);
424         }
425     }
426   else
427     {
428       *Dacl = NULL;
429     }
430
431   if (*Dacl != NULL)
432     {
433       *DaclLength = ((*Dacl)->AclSize + 3) & ~3;
434     }
435   else
436     {
437       *DaclLength = 0;
438     }
439
440   if (SecurityDescriptor->Group != NULL)
441     {
442       *Group = NULL;
443     }
444   else
445     {
446       *Group = SecurityDescriptor->Group;
447       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
448         {
449           *Group = (PSID)((ULONG)*Group + (ULONG)SecurityDescriptor);
450         }
451     }
452
453   if (*Group != NULL)
454     {
455       *GroupLength = (RtlLengthSid(*Group) + 3) & ~3;
456     }
457   else
458     {
459       *GroupLength = 0;
460     }
461
462   if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
463       SecurityDescriptor->Sacl != NULL)
464     {
465       *Sacl = SecurityDescriptor->Sacl;
466       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
467         {
468           *Sacl = (PACL)((ULONG)*Sacl + (ULONG)SecurityDescriptor);
469         }
470     }
471   else
472     {
473       *Sacl = NULL;
474     }
475
476   if (*Sacl != NULL)
477     {
478       *SaclLength = ((*Sacl)->AclSize + 3) & ~3;
479     }
480 }
481
482
483 /*
484  * @implemented
485  */
486 NTSTATUS STDCALL
487 RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD,
488                       PSECURITY_DESCRIPTOR RelSD,
489                       PULONG BufferLength)
490 {
491   PSID Owner;
492   PSID Group;
493   PACL Sacl;
494   PACL Dacl;
495   ULONG OwnerLength;
496   ULONG GroupLength;
497   ULONG SaclLength;
498   ULONG DaclLength;
499   ULONG TotalLength;
500   ULONG Current;
501
502   RtlpQuerySecurityDescriptor(AbsSD,
503                               &Owner,
504                               &OwnerLength,
505                               &Group,
506                               &GroupLength,
507                               &Dacl,
508                               &DaclLength,
509                               &Sacl,
510                               &SaclLength);
511
512   TotalLength = OwnerLength + GroupLength + SaclLength + DaclLength + sizeof(SECURITY_DESCRIPTOR);
513   if (*BufferLength < TotalLength)
514     {
515       return(STATUS_BUFFER_TOO_SMALL);
516     }
517
518   RtlZeroMemory(RelSD,
519                 TotalLength);
520   memmove(RelSD,
521           AbsSD,
522           sizeof(SECURITY_DESCRIPTOR));
523   Current = (ULONG)RelSD + sizeof(SECURITY_DESCRIPTOR);
524
525   if (SaclLength != 0)
526     {
527       memmove((PVOID)Current,
528               Sacl,
529               SaclLength);
530       RelSD->Sacl = (PACL)((ULONG)Current - (ULONG)RelSD);
531       Current += SaclLength;
532     }
533
534   if (DaclLength != 0)
535     {
536       memmove((PVOID)Current,
537               Dacl,
538               DaclLength);
539       RelSD->Dacl = (PACL)((ULONG)Current - (ULONG)RelSD);
540       Current += DaclLength;
541     }
542
543   if (OwnerLength != 0)
544     {
545       memmove((PVOID)Current,
546               Owner,
547               OwnerLength);
548       RelSD->Owner = (PSID)((ULONG)Current - (ULONG)RelSD);
549       Current += OwnerLength;
550     }
551
552   if (GroupLength != 0)
553     {
554       memmove((PVOID)Current,
555               Group,
556               GroupLength);
557       RelSD->Group = (PSID)((ULONG)Current - (ULONG)RelSD);
558     }
559
560   RelSD->Control |= SE_SELF_RELATIVE;
561
562   return(STATUS_SUCCESS);
563 }
564
565
566 /*
567  * @implemented
568  */
569 NTSTATUS STDCALL
570 RtlAbsoluteToSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD,
571                             PSECURITY_DESCRIPTOR RelSD,
572                             PULONG BufferLength
573         )
574 {
575   if (AbsSD->Control & SE_SELF_RELATIVE)
576     {
577       return(STATUS_BAD_DESCRIPTOR_FORMAT);
578     }
579
580   return(RtlMakeSelfRelativeSD(AbsSD, RelSD, BufferLength));
581 }
582
583
584 /*
585  * @implemented
586  */
587 NTSTATUS STDCALL
588 RtlGetControlSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
589                                 PSECURITY_DESCRIPTOR_CONTROL Control,
590                                 PULONG Revision)
591 {
592   *Revision = SecurityDescriptor->Revision;
593
594   if (SecurityDescriptor->Revision != 1)
595     {
596       return(STATUS_UNKNOWN_REVISION);
597     }
598
599   *Control = SecurityDescriptor->Control;
600
601   return(STATUS_SUCCESS);
602 }
603
604
605 /*
606  * @implemented
607  */
608 NTSTATUS STDCALL
609 RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
610                              PBOOLEAN SaclPresent,
611                              PACL *Sacl,
612                              PBOOLEAN SaclDefaulted)
613 {
614    if (SecurityDescriptor->Revision != 1)
615      {
616         return(STATUS_UNSUCCESSFUL);
617      }
618    if (!(SecurityDescriptor->Control & SE_SACL_PRESENT))
619      {
620         *SaclPresent = 0;
621         return(STATUS_SUCCESS);
622      }
623    *SaclPresent = 1;
624    if (SecurityDescriptor->Sacl == NULL)
625      {
626         *Sacl = NULL;
627      }
628    else
629      {
630         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
631           {
632              *Sacl = (PACL)((ULONG)SecurityDescriptor->Sacl +
633                             (PVOID)SecurityDescriptor);
634           }
635         else
636           {
637              *Sacl = SecurityDescriptor->Sacl;
638           }
639      }
640    if (SecurityDescriptor->Control & SE_SACL_DEFAULTED)
641      {
642         *SaclDefaulted = 1;
643      }
644    else
645      {
646         *SaclDefaulted = 0;
647      }
648    return(STATUS_SUCCESS);
649 }
650
651 /*
652  * @implemented
653  */
654 NTSTATUS STDCALL
655 RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
656                              BOOLEAN SaclPresent,
657                              PACL Sacl,
658                              BOOLEAN SaclDefaulted)
659 {
660    if (SecurityDescriptor->Revision != 1)
661      {
662         return(STATUS_UNSUCCESSFUL);
663      }
664    if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
665      {
666         return(STATUS_UNSUCCESSFUL);
667      }
668    if (!SaclPresent)
669      {
670         SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_PRESENT);
671         return(STATUS_SUCCESS);
672      }
673    SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_PRESENT;
674    SecurityDescriptor->Sacl = Sacl;
675    SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_DEFAULTED);
676    if (SaclDefaulted)
677      {
678         SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_DEFAULTED;
679      }
680    return(STATUS_SUCCESS);
681 }
682
683
684 /*
685  * @implemented
686  */
687 NTSTATUS STDCALL
688 RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD,
689                             PSECURITY_DESCRIPTOR AbsSD,
690                             PDWORD AbsSDSize,
691                             PACL Dacl,
692                             PDWORD DaclSize,
693                             PACL Sacl,
694                             PDWORD SaclSize,
695                             PSID Owner,
696                             PDWORD OwnerSize,
697                             PSID Group,
698                             PDWORD GroupSize)
699 {
700   ULONG OwnerLength;
701   ULONG GroupLength;
702   ULONG DaclLength;
703   ULONG SaclLength;
704   PSID pOwner;
705   PSID pGroup;
706   PACL pDacl;
707   PACL pSacl;
708
709   if (!(RelSD->Control & SE_SELF_RELATIVE))
710     return STATUS_BAD_DESCRIPTOR_FORMAT;
711
712   RtlpQuerySecurityDescriptor (RelSD,
713                                &pOwner,
714                                &OwnerLength,
715                                &pGroup,
716                                &GroupLength,
717                                &pDacl,
718                                &DaclLength,
719                                &pSacl,
720                                &SaclLength);
721
722   if (OwnerLength > *OwnerSize ||
723       GroupLength > *GroupSize ||
724       DaclLength > *DaclSize ||
725       SaclLength > *SaclSize)
726     return STATUS_BUFFER_TOO_SMALL;
727
728   memmove (Owner, pOwner, OwnerLength);
729   memmove (Group, pGroup, GroupLength);
730   memmove (Dacl, pDacl, DaclLength);
731   memmove (Sacl, pSacl, SaclLength);
732
733   memmove (AbsSD, RelSD, sizeof (SECURITY_DESCRIPTOR));
734
735   AbsSD->Control &= ~SE_SELF_RELATIVE;
736   AbsSD->Owner = Owner;
737   AbsSD->Group = Group;
738   AbsSD->Dacl = Dacl;
739   AbsSD->Sacl = Sacl;
740
741   *OwnerSize = OwnerLength;
742   *GroupSize = GroupLength;
743   *DaclSize = DaclLength;
744   *SaclSize = SaclLength;
745
746   return STATUS_SUCCESS;
747 }
748
749 /* EOF */