3dfde97d9e003d49019aa28ca32cefcf3fa6e06c
[captive.git] / src / libcaptive / se / semgr.c
1 /* $Id$
2  * reactos security thin manager emulation of libcaptive
3  * Copyright (C) 2002-2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "reactos/ddk/setypes.h"        /* self */
23 #include <glib/gmessages.h>
24 #include "reactos/ddk/status.h"
25 #include "reactos/ddk/exfuncs.h"        /* for ExAllocatePool() */
26
27
28 /**
29  * SeLockSubjectContext:
30  * @SubjectContext: Security context to read lock.
31  * %NULL value is forbidden.
32  *
33  * Obtain read locks on the security context @SubjectContext.
34  * @SubjectContext must be already acquired by SeCaptureSubjectContext().
35  *
36  * This functions is a NOP in libcaptive as there is no threading implemented.
37  * FIXME: No sanity checks are currently done by libcaptive.
38  */
39 VOID SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
40 {
41         g_return_if_fail(SubjectContext!=NULL);
42
43         /* NOP; TODO:thread */
44 }
45
46
47 /**
48  * SeUnlockSubjectContext:
49  * @SubjectContext: Security context to unlock.
50  * %NULL value is forbidden.
51  *
52  * Release read locks on the security context @SubjectContext.
53  * @SubjectContext must be currently locked by SeLockSubjectContext().
54  *
55  * This functions is a NOP in libcaptive as there is no threading implemented.
56  * FIXME: No sanity checks are currently done by libcaptive.
57  */
58 VOID SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
59 {
60         g_return_if_fail(SubjectContext!=NULL);
61
62         /* NOP; TODO:thread */
63 }
64
65
66 static SID *SID_dup(SID *sid,SECURITY_DESCRIPTOR *src,SECURITY_DESCRIPTOR *dest,gpointer *destdatap)
67 {
68 SID *r;
69 gsize size;
70
71         /* 'sid' may be NULL */
72         g_return_val_if_fail(src!=NULL,NULL);
73         g_return_val_if_fail(dest!=NULL,NULL);
74         g_return_val_if_fail(destdatap!=NULL,NULL);
75         g_return_val_if_fail(*destdatap!=NULL,NULL);
76
77         if (!sid)
78                 return NULL;
79         if (src->Control & SE_SELF_RELATIVE)
80                 sid=(SID *)(((ULONG)sid)+((ULONG)src));
81         if (!sid)
82                 return NULL;
83
84         size=sizeof(*r)+sizeof(*r->SubAuthority)*(sid->SubAuthorityCount-1);
85         g_assert(size==(gsize)((*(guint8 *)(((char *)sid)+0x01))*4+8)); /* 0x14h is sizeof(SECURITY_DESCRIPTOR) */
86         g_assert(!(size&3));    /* sizeof(ULONG)-alignment */
87         r=*destdatap;
88         (*(char **)destdatap)+=size;
89         memcpy(r,sid,size);
90         if (dest->Control & SE_SELF_RELATIVE)
91                 r=(SID *)(((ULONG)r)-((ULONG)dest));
92
93         return r;
94 }
95
96 static ACL *ACL_dup(ACL *acl,SECURITY_DESCRIPTOR *src,SECURITY_DESCRIPTOR *dest,gpointer *destdatap)
97 {
98 ACL *r;
99 gsize size;
100
101         g_return_val_if_fail(acl!=NULL,NULL);
102         g_return_val_if_fail(src!=NULL,NULL);
103         g_return_val_if_fail(dest!=NULL,NULL);
104         g_return_val_if_fail(destdatap!=NULL,NULL);
105         g_return_val_if_fail(*destdatap!=NULL,NULL);
106
107         if (!acl)
108                 return NULL;
109         if (src->Control & SE_SELF_RELATIVE)
110                 acl=(ACL *)(((ULONG)acl)+((ULONG)src));
111         if (!acl)
112                 return NULL;
113
114         /* W32 undocumented: ReactOS uses '&0xFF' notation, I have seen value PAGE_SIZE.
115          * W32 doc says it is a regular size.
116          */
117         size=acl->AclSize;
118         g_assert(!(size&3));    /* sizeof(ULONG)-alignment */
119         r=*destdatap;
120         (*(char **)destdatap)+=size;
121         memcpy(r,acl,size);
122         if (dest->Control & SE_SELF_RELATIVE)
123                 r=(ACL *)(((ULONG)r)-((ULONG)dest));
124
125         return r;
126 }
127
128 /**
129  * SeAssignSecurity:
130  * @ParentDescriptor: Optional parent object security descriptor.
131  * %NULL value is permitted.
132  * @ExplicitDescriptor: Optional overriding descriptor for the new object.
133  * FIXME: %NULL value should be permitted but it is currently forbidden by libcaptive.
134  * @NewDescriptor: Returns the new generated descriptor.
135  * %NULL value is forbidden.
136  * @IsDirectoryObject: Will the new object contain its subobjects?
137  * @SubjectContext: Security context of the caller.
138  * %NULL value is forbidden.
139  * @GenericMapping: Rights mapping (?).
140  * %NULL value is forbidden.
141  * @PoolType: #POOL_TYPE to allocate new @NewDescriptor from.
142  *
143  * libcaptive requires either @ExplicitDescriptor or @ParentDescriptor
144  * to be presents and it recursively copies the structures to the
145  * target (allocated) @NewDescriptor. @ExplicitDescriptor is preferred
146  * over @ParentDescriptor if present. No structures merging is done.
147  *
148  * Returns: %STATUS_SUCCESS if @NewDescriptor was successfuly filled.
149  */
150 NTSTATUS SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
151                 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,PSECURITY_DESCRIPTOR *NewDescriptor,
152                 BOOLEAN IsDirectoryObject,PSECURITY_SUBJECT_CONTEXT SubjectContext,PGENERIC_MAPPING GenericMapping,POOL_TYPE PoolType)
153 {
154 SECURITY_DESCRIPTOR *src,*dest;
155 ULONG size;
156 gpointer destdata;
157
158         g_return_val_if_fail(NewDescriptor!=NULL,STATUS_INVALID_PARAMETER);
159         g_return_val_if_fail(SubjectContext!=NULL,STATUS_INVALID_PARAMETER);
160         g_return_val_if_fail(GenericMapping!=NULL,STATUS_INVALID_PARAMETER);
161
162         /* #2  0x40067021 in SeAssignSecurity (ParentDescriptor=0x0,
163          *     ExplicitDescriptor=0xbfffe7f4, NewDescriptor=0x40b5873c,
164          *     IsDirectoryObject=0 '\0', SubjectContext=0x409d2ff0,
165          *     GenericMapping=0x40088014, PoolType=1) at semgr.c:79
166          * #2  0x4006fe45 in SeAssignSecurity (ParentDescriptor=0x411b3fd0,
167          *     ExplicitDescriptor=0x0, NewDescriptor=0xbfffe39c,
168          *     IsDirectoryObject=1 '\001', SubjectContext=0xbfffe90c,
169          *     GenericMapping=0x40094014, PoolType=1) at semgr.c:99
170          */
171         g_return_val_if_fail(ExplicitDescriptor!=NULL || ParentDescriptor!=NULL,STATUS_NOT_IMPLEMENTED);        /* NOT YET IMPLEMENTED */
172
173         src=(ExplicitDescriptor ? ExplicitDescriptor : ParentDescriptor);
174
175         size=RtlLengthSecurityDescriptor(src);
176         g_assert(!(size&3));    /* sizeof(ULONG)-alignment */
177
178         dest=ExAllocatePool(PagedPool,size);
179         g_return_val_if_fail(dest!=NULL,STATUS_NO_MEMORY);
180
181         dest->Revision=src->Revision;
182         dest->Control=src->Control;
183         destdata=(dest+1);
184         dest->Owner=SID_dup(src->Owner,src,dest,&destdata);
185         dest->Group=SID_dup(src->Group,src,dest,&destdata);
186         if (src->Control & SE_SACL_PRESENT) {
187                 if (!(dest->Sacl=ACL_dup(src->Sacl,src,dest,&destdata)))
188                         dest->Control&=~SE_SACL_PRESENT;
189                 }
190         if (src->Control & SE_DACL_PRESENT) {
191                 if (!(dest->Dacl=ACL_dup(src->Dacl,src,dest,&destdata)))
192                         dest->Control&=~SE_DACL_PRESENT;
193                 }
194
195         g_assert(((char *)dest)+size==destdata);
196
197         *NewDescriptor=dest;
198
199         return STATUS_SUCCESS;
200 }
201
202
203 /**
204  * SeAccessCheck:
205  * @SecurityDescriptor: IGNORED; ignored by libcaptive.
206  * %NULL value is forbidden.
207  * @SubjectSecurityContext: IGNORED; ignored by libcaptive.
208  * %NULL value is forbidden.
209  * @SubjectContextLocked: IGNORED; ignored by libcaptive.
210  * @DesiredAccess: IGNORED; ignored by libcaptive.
211  * @PreviouslyGrantedAccess: IGNORED; ignored by libcaptive.
212  * @Privileges: IGNORED; ignored by libcaptive.
213  * %NULL value is forbidden.
214  * @GenericMapping: IGNORED; ignored by libcaptive.
215  * %NULL value is forbidden.
216  * @AccessMode: IGNORED; ignored by libcaptive.
217  * @GrantedAccess: IGNORED; ignored by libcaptive.
218  * %NULL value is forbidden.
219  * @AccessStatus: IGNORED; ignored by libcaptive.
220  * %NULL value is forbidden.
221  * 
222  * Query the rights of IGNORED to access IGNORED.
223  *
224  * libcaptive does not support any security and therefore it always returns %TRUE.
225  *
226  * Returns: %TRUE if the access is granted.
227  */
228 BOOLEAN SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
229                 IN BOOLEAN SubjectContextLocked,IN ACCESS_MASK DesiredAccess,IN ACCESS_MASK PreviouslyGrantedAccess,
230                 OUT PPRIVILEGE_SET* Privileges,IN PGENERIC_MAPPING GenericMapping,IN KPROCESSOR_MODE AccessMode,
231                 OUT PACCESS_MODE GrantedAccess,OUT PNTSTATUS AccessStatus)
232 {
233         g_return_val_if_fail(SecurityDescriptor!=NULL,FALSE);   /* means 'access denied' */
234         g_return_val_if_fail(SubjectSecurityContext!=NULL,FALSE);       /* means 'access denied' */
235         g_return_val_if_fail(Privileges!=NULL,FALSE);   /* means 'access denied' */
236         g_return_val_if_fail(GenericMapping!=NULL,FALSE);       /* means 'access denied' */
237         g_return_val_if_fail(GrantedAccess!=NULL,FALSE);        /* means 'access denied' */
238         g_return_val_if_fail(AccessStatus!=NULL,FALSE); /* means 'access denied' */
239
240         return TRUE;    /* access granted */
241 }