update for HEAD-2003091401
[reactos.git] / ntoskrnl / se / acl.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Security manager
6  * FILE:              kernel/se/acl.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 #include <internal/se.h>
16
17 #include <internal/debug.h>
18
19 #define TAG_ACL    TAG('A', 'C', 'L', 'T')
20
21
22 /* GLOBALS ******************************************************************/
23
24 PACL EXPORTED SePublicDefaultDacl = NULL;
25 PACL EXPORTED SeSystemDefaultDacl = NULL;
26
27 PACL SePublicDefaultUnrestrictedDacl = NULL;
28 PACL SePublicOpenDacl = NULL;
29 PACL SePublicOpenUnrestrictedDacl = NULL;
30 PACL SeUnrestrictedDacl = NULL;
31
32
33 /* FUNCTIONS ****************************************************************/
34
35 BOOLEAN
36 SepInitDACLs(VOID)
37 {
38   ULONG AclLength2;
39   ULONG AclLength3;
40   ULONG AclLength4;
41
42   AclLength2 = sizeof(ACL) +
43                2 * (RtlLengthRequiredSid(1) + sizeof(ACE));
44   AclLength3 = sizeof(ACL) +
45                3 * (RtlLengthRequiredSid(1) + sizeof(ACE));
46   AclLength4 = sizeof(ACL) +
47                4 * (RtlLengthRequiredSid(1) + sizeof(ACE));
48
49   /* create PublicDefaultDacl */
50   SePublicDefaultDacl = ExAllocatePoolWithTag(NonPagedPool,
51                                               AclLength2,
52                                               TAG_ACL);
53   if (SePublicDefaultDacl == NULL)
54     return(FALSE);
55
56   RtlCreateAcl(SePublicDefaultDacl,
57                AclLength2,
58                2);
59
60   RtlAddAccessAllowedAce(SePublicDefaultDacl,
61                          2,
62                          GENERIC_EXECUTE,
63                          SeWorldSid);
64
65   RtlAddAccessAllowedAce(SePublicDefaultDacl,
66                          2,
67                          GENERIC_ALL,
68                          SeLocalSystemSid);
69
70
71   /* create PublicDefaultUnrestrictedDacl */
72   SePublicDefaultUnrestrictedDacl = ExAllocatePoolWithTag(NonPagedPool,
73                                                           AclLength4,
74                                                           TAG_ACL);
75   if (SePublicDefaultUnrestrictedDacl == NULL)
76     return(FALSE);
77
78   RtlCreateAcl(SePublicDefaultUnrestrictedDacl,
79                AclLength4,
80                2);
81
82   RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
83                          4,
84                          GENERIC_EXECUTE,
85                          SeWorldSid);
86
87   RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
88                          4,
89                          GENERIC_ALL,
90                          SeLocalSystemSid);
91
92   RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
93                          4,
94                          GENERIC_ALL,
95                          SeAliasAdminsSid);
96
97   RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
98                          4,
99                          GENERIC_READ | GENERIC_EXECUTE | STANDARD_RIGHTS_READ,
100                          SeRestrictedCodeSid);
101
102   /* create PublicOpenDacl */
103   SePublicOpenDacl = ExAllocatePoolWithTag(NonPagedPool,
104                                            AclLength3,
105                                            TAG_ACL);
106   if (SePublicOpenDacl == NULL)
107     return(FALSE);
108
109   RtlCreateAcl(SePublicOpenDacl,
110                AclLength3,
111                3);
112
113   RtlAddAccessAllowedAce(SePublicOpenDacl,
114                          2,
115                          GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
116                          SeWorldSid);
117
118   RtlAddAccessAllowedAce(SePublicOpenDacl,
119                          2,
120                          GENERIC_ALL,
121                          SeLocalSystemSid);
122
123   RtlAddAccessAllowedAce(SePublicOpenDacl,
124                          2,
125                          GENERIC_ALL,
126                          SeAliasAdminsSid);
127
128
129   return(TRUE);
130 }
131
132
133 BOOLEAN STDCALL
134 RtlFirstFreeAce(PACL Acl,
135                 PACE* Ace)
136 {
137   PACE Current;
138   PVOID AclEnd;
139   ULONG i;
140
141   Current = (PACE)(Acl + 1);
142   *Ace = NULL;
143   i = 0;
144   if (Acl->AceCount == 0)
145     {
146       *Ace = Current;
147       return(TRUE);
148     }
149
150   AclEnd = Acl->AclSize + (PVOID)Acl;
151   do
152     {
153       if ((PVOID)Current >= AclEnd)
154         {
155           return(FALSE);
156         }
157
158       if (Current->Header.AceType == 4)
159         {
160           if (Acl->AclRevision < 3)
161             {
162               return(FALSE);
163             }
164         }
165       Current = (PACE)((PVOID)Current + (ULONG)Current->Header.AceSize);
166       i++;
167     }
168   while (i < Acl->AceCount);
169
170   if ((PVOID)Current < AclEnd)
171     {
172       *Ace = Current;
173     }
174
175   return(TRUE);
176 }
177
178
179 NTSTATUS
180 RtlpAddKnownAce(PACL Acl,
181                 ULONG Revision,
182                 ACCESS_MASK AccessMask,
183                 PSID Sid,
184                 ULONG Type)
185 {
186   PACE Ace;
187
188   if (!RtlValidSid(Sid))
189     {
190       return(STATUS_INVALID_SID);
191     }
192   if (Acl->AclRevision > 3 ||
193       Revision > 3)
194     {
195       return(STATUS_UNKNOWN_REVISION);
196     }
197   if (Revision < Acl->AclRevision)
198     {
199       Revision = Acl->AclRevision;
200     }
201   if (!RtlFirstFreeAce(Acl, &Ace))
202     {
203       return(STATUS_BUFFER_TOO_SMALL);
204     }
205   if (Ace == NULL)
206     {
207       return(STATUS_UNSUCCESSFUL);
208     }
209   if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >= 
210       ((PVOID)Acl + Acl->AclSize))
211     {
212       return(STATUS_BUFFER_TOO_SMALL);
213     }
214   Ace->Header.AceFlags = 0;
215   Ace->Header.AceType = Type;
216   Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE);
217   Ace->AccessMask = AccessMask;
218   RtlCopySid(RtlLengthSid(Sid), (PSID)(Ace + 1), Sid);
219   Acl->AceCount++;
220   Acl->AclRevision = Revision;
221   return(STATUS_SUCCESS);
222 }
223
224
225 /*
226  * @implemented
227  */
228 NTSTATUS STDCALL
229 RtlAddAccessAllowedAce(PACL Acl,
230                        ULONG Revision,
231                        ACCESS_MASK AccessMask,
232                        PSID Sid)
233 {
234   return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 0));
235 }
236
237
238 /*
239  * @implemented
240  */
241 NTSTATUS STDCALL
242 RtlAddAce(PACL Acl,
243           ULONG AclRevision,
244           ULONG StartingIndex,
245           PACE AceList,
246           ULONG AceListLength)
247 {
248    PACE Ace;
249    ULONG i;
250    PACE Current;
251    ULONG j;
252    
253    if (Acl->AclRevision != 2 &&
254        Acl->AclRevision != 3)
255      {
256         return(STATUS_UNSUCCESSFUL);
257      }
258    if (!RtlFirstFreeAce(Acl,&Ace))
259      {
260         return(STATUS_UNSUCCESSFUL);
261      }
262    if (Acl->AclRevision <= AclRevision)
263      {
264         AclRevision = Acl->AclRevision;
265      }
266    if (((PVOID)AceList + AceListLength) <= (PVOID)AceList)
267      {
268         return(STATUS_UNSUCCESSFUL);
269      }
270    i = 0;
271    Current = (PACE)(Acl + 1);
272    while ((PVOID)Current < ((PVOID)AceList + AceListLength))
273      {
274         if (AceList->Header.AceType == 4 &&
275             AclRevision < 3)
276           {
277              return(STATUS_UNSUCCESSFUL);
278           }
279         Current = (PACE)((PVOID)Current + Current->Header.AceSize);
280      }
281    if (Ace == NULL)
282      {
283         return(STATUS_UNSUCCESSFUL);
284      }
285    if (((PVOID)Ace + AceListLength) >= ((PVOID)Acl + Acl->AclSize))
286      {
287         return(STATUS_UNSUCCESSFUL);
288      }
289    if (StartingIndex != 0)
290      {
291         if (Acl->AceCount > 0)
292           {
293              Current = (PACE)(Acl + 1);
294              for (j = 0; j < StartingIndex; j++)
295                {
296                   Current = (PACE)((PVOID)Current + Current->Header.AceSize);
297                }
298           }
299      }
300    /* RtlpAddData(AceList, AceListLength, Current, (PVOID)Ace - Current)); */
301    memcpy(Current, AceList, AceListLength);
302    Acl->AceCount = Acl->AceCount + i;
303    Acl->AclRevision = AclRevision;
304    return(TRUE);
305 }
306
307
308 /*
309  * @implemented
310  */
311 NTSTATUS STDCALL
312 RtlCreateAcl(PACL Acl,
313              ULONG AclSize,
314              ULONG AclRevision)
315 {
316   if (AclSize < 8)
317     {
318       return(STATUS_BUFFER_TOO_SMALL);
319     }
320   if (AclRevision != 2 &&
321       AclRevision != 3)
322     {
323       return(STATUS_UNKNOWN_REVISION);
324     }
325   if (AclSize > 0xffff)
326     {
327       return(STATUS_UNSUCCESSFUL);
328     }
329   AclSize = AclSize & ~(0x3);
330   Acl->AclSize = AclSize;
331   Acl->AclRevision = AclRevision;
332   Acl->AceCount = 0;
333   Acl->Sbz1 = 0;
334   Acl->Sbz2 = 0;
335   return(STATUS_SUCCESS);
336 }
337
338
339 BOOLEAN STDCALL
340 RtlValidAcl(PACL Acl)
341 {
342   PACE Ace;
343   USHORT Size;
344
345   Size = (Acl->AclSize + 3) & ~3;
346
347   if (Acl->AclRevision != 2 &&
348       Acl->AclRevision != 3)
349     {
350       return(FALSE);
351     }
352
353   if (Size != Acl->AclSize)
354     {
355       return(FALSE);
356     }
357
358   return(RtlFirstFreeAce(Acl, &Ace));
359 }
360
361 /* EOF */