update for HEAD-2003050101
[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 NTSTATUS STDCALL
226 RtlAddAccessAllowedAce(PACL Acl,
227                        ULONG Revision,
228                        ACCESS_MASK AccessMask,
229                        PSID Sid)
230 {
231   return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 0));
232 }
233
234
235 NTSTATUS STDCALL
236 RtlAddAce(PACL Acl,
237           ULONG AclRevision,
238           ULONG StartingIndex,
239           PACE AceList,
240           ULONG AceListLength)
241 {
242    PACE Ace;
243    ULONG i;
244    PACE Current;
245    ULONG j;
246    
247    if (Acl->AclRevision != 2 &&
248        Acl->AclRevision != 3)
249      {
250         return(STATUS_UNSUCCESSFUL);
251      }
252    if (!RtlFirstFreeAce(Acl,&Ace))
253      {
254         return(STATUS_UNSUCCESSFUL);
255      }
256    if (Acl->AclRevision <= AclRevision)
257      {
258         AclRevision = Acl->AclRevision;
259      }
260    if (((PVOID)AceList + AceListLength) <= (PVOID)AceList)
261      {
262         return(STATUS_UNSUCCESSFUL);
263      }
264    i = 0;
265    Current = (PACE)(Acl + 1);
266    while ((PVOID)Current < ((PVOID)AceList + AceListLength))
267      {
268         if (AceList->Header.AceType == 4 &&
269             AclRevision < 3)
270           {
271              return(STATUS_UNSUCCESSFUL);
272           }
273         Current = (PACE)((PVOID)Current + Current->Header.AceSize);
274      }
275    if (Ace == NULL)
276      {
277         return(STATUS_UNSUCCESSFUL);
278      }
279    if (((PVOID)Ace + AceListLength) >= ((PVOID)Acl + Acl->AclSize))
280      {
281         return(STATUS_UNSUCCESSFUL);
282      }
283    if (StartingIndex != 0)
284      {
285         if (Acl->AceCount > 0)
286           {
287              Current = (PACE)(Acl + 1);
288              for (j = 0; j < StartingIndex; j++)
289                {
290                   Current = (PACE)((PVOID)Current + Current->Header.AceSize);
291                }
292           }
293      }
294    /* RtlpAddData(AceList, AceListLength, Current, (PVOID)Ace - Current)); */
295    memcpy(Current, AceList, AceListLength);
296    Acl->AceCount = Acl->AceCount + i;
297    Acl->AclRevision = AclRevision;
298    return(TRUE);
299 }
300
301
302 NTSTATUS STDCALL
303 RtlCreateAcl(PACL Acl,
304              ULONG AclSize,
305              ULONG AclRevision)
306 {
307   if (AclSize < 8)
308     {
309       return(STATUS_BUFFER_TOO_SMALL);
310     }
311   if (AclRevision != 2 &&
312       AclRevision != 3)
313     {
314       return(STATUS_UNKNOWN_REVISION);
315     }
316   if (AclSize > 0xffff)
317     {
318       return(STATUS_UNSUCCESSFUL);
319     }
320   AclSize = AclSize & ~(0x3);
321   Acl->AclSize = AclSize;
322   Acl->AclRevision = AclRevision;
323   Acl->AceCount = 0;
324   Acl->Sbz1 = 0;
325   Acl->Sbz2 = 0;
326   return(STATUS_SUCCESS);
327 }
328
329
330 BOOLEAN STDCALL
331 RtlValidAcl(PACL Acl)
332 {
333   PACE Ace;
334   USHORT Size;
335
336   Size = (Acl->AclSize + 3) & ~3;
337
338   if (Acl->AclRevision != 2 &&
339       Acl->AclRevision != 3)
340     {
341       return(FALSE);
342     }
343
344   if (Size != Acl->AclSize)
345     {
346       return(FALSE);
347     }
348
349   return(RtlFirstFreeAce(Acl, &Ace));
350 }
351
352 /* EOF */