Initial original import from: fuse-2.4.2-2.fc4
[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         /* 'acl' may be 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                 r=NULL;
113         else {
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                 }
123         if (dest->Control & SE_SELF_RELATIVE)
124                 r=(ACL *)(((ULONG)r)-((ULONG)dest));
125
126         return r;
127 }
128
129 /**
130  * SeAssignSecurity:
131  * @ParentDescriptor: Optional parent object security descriptor.
132  * %NULL value is permitted.
133  * @ExplicitDescriptor: Optional overriding descriptor for the new object.
134  * FIXME: %NULL value should be permitted but it is currently forbidden by libcaptive.
135  * @NewDescriptor: Returns the new generated descriptor.
136  * %NULL value is forbidden.
137  * @IsDirectoryObject: Will the new object contain its subobjects?
138  * @SubjectContext: Security context of the caller.
139  * %NULL value is forbidden.
140  * @GenericMapping: Rights mapping (?).
141  * %NULL value is forbidden.
142  * @PoolType: #POOL_TYPE to allocate new @NewDescriptor from.
143  *
144  * libcaptive requires either @ExplicitDescriptor or @ParentDescriptor
145  * to be presents and it recursively copies the structures to the
146  * target (allocated) @NewDescriptor. @ExplicitDescriptor is preferred
147  * over @ParentDescriptor if present. No structures merging is done.
148  *
149  * Returns: %STATUS_SUCCESS if @NewDescriptor was successfuly filled.
150  */
151 NTSTATUS SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
152                 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,PSECURITY_DESCRIPTOR *NewDescriptor,
153                 BOOLEAN IsDirectoryObject,PSECURITY_SUBJECT_CONTEXT SubjectContext,PGENERIC_MAPPING GenericMapping,POOL_TYPE PoolType)
154 {
155 SECURITY_DESCRIPTOR *src,*dest;
156 ULONG size;
157 gpointer destdata;
158
159         g_return_val_if_fail(NewDescriptor!=NULL,STATUS_INVALID_PARAMETER);
160         g_return_val_if_fail(SubjectContext!=NULL,STATUS_INVALID_PARAMETER);
161         g_return_val_if_fail(GenericMapping!=NULL,STATUS_INVALID_PARAMETER);
162
163         /* #2  0x40067021 in SeAssignSecurity (ParentDescriptor=0x0,
164          *     ExplicitDescriptor=0xbfffe7f4, NewDescriptor=0x40b5873c,
165          *     IsDirectoryObject=0 '\0', SubjectContext=0x409d2ff0,
166          *     GenericMapping=0x40088014, PoolType=1) at semgr.c:79
167          * #2  0x4006fe45 in SeAssignSecurity (ParentDescriptor=0x411b3fd0,
168          *     ExplicitDescriptor=0x0, NewDescriptor=0xbfffe39c,
169          *     IsDirectoryObject=1 '\001', SubjectContext=0xbfffe90c,
170          *     GenericMapping=0x40094014, PoolType=1) at semgr.c:99
171          */
172         g_return_val_if_fail(ExplicitDescriptor!=NULL || ParentDescriptor!=NULL,STATUS_NOT_IMPLEMENTED);        /* NOT YET IMPLEMENTED */
173
174         src=(ExplicitDescriptor ? ExplicitDescriptor : ParentDescriptor);
175
176         size=RtlLengthSecurityDescriptor(src);
177         g_assert(!(size&3));    /* sizeof(ULONG)-alignment */
178
179         dest=ExAllocatePool(PagedPool,size);
180         g_return_val_if_fail(dest!=NULL,STATUS_NO_MEMORY);
181
182         dest->Revision=src->Revision;
183         dest->Control=src->Control;
184         destdata=(dest+1);
185         dest->Owner=SID_dup(src->Owner,src,dest,&destdata);
186         dest->Group=SID_dup(src->Group,src,dest,&destdata);
187         if (src->Control & SE_SACL_PRESENT) {
188                 /* 'SE_SACL_PRESENT' may be site while 'Sacl==NULL'.
189                  * FIXME: How it differs from '!SE_SACL_PRESENT'?
190                  */
191                 dest->Sacl=ACL_dup(src->Sacl,src,dest,&destdata);
192                 }
193         else
194                 dest->Sacl=NULL;
195         if (src->Control & SE_DACL_PRESENT) {
196                 /* 'SE_DACL_PRESENT' may be site while 'Dacl==NULL'.
197                  * FIXME: How it differs from '!SE_DACL_PRESENT'?
198                  */
199                 dest->Dacl=ACL_dup(src->Dacl,src,dest,&destdata);
200                 }
201         else
202                 dest->Dacl=NULL;
203
204         g_assert(((char *)dest)+size==destdata);
205
206         *NewDescriptor=dest;
207
208         return STATUS_SUCCESS;
209 }
210
211
212 /**
213  * SeAccessCheck:
214  * @SecurityDescriptor: IGNORED; ignored by libcaptive.
215  * %NULL value is forbidden.
216  * @SubjectSecurityContext: IGNORED; ignored by libcaptive.
217  * %NULL value is forbidden.
218  * @SubjectContextLocked: IGNORED; ignored by libcaptive.
219  * @DesiredAccess: IGNORED; ignored by libcaptive.
220  * @PreviouslyGrantedAccess: IGNORED; ignored by libcaptive.
221  * @Privileges: IGNORED; ignored by libcaptive.
222  * %NULL value is forbidden.
223  * @GenericMapping: IGNORED; ignored by libcaptive.
224  * %NULL value is forbidden.
225  * @AccessMode: IGNORED; ignored by libcaptive.
226  * @GrantedAccess: IGNORED; ignored by libcaptive.
227  * %NULL value is forbidden.
228  * @AccessStatus: IGNORED; ignored by libcaptive.
229  * %NULL value is forbidden.
230  * 
231  * Query the rights of IGNORED to access IGNORED.
232  *
233  * libcaptive does not support any security and therefore it always returns %TRUE.
234  *
235  * Returns: %TRUE if the access is granted.
236  */
237 BOOLEAN SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
238                 IN BOOLEAN SubjectContextLocked,IN ACCESS_MASK DesiredAccess,IN ACCESS_MASK PreviouslyGrantedAccess,
239                 OUT PPRIVILEGE_SET* Privileges,IN PGENERIC_MAPPING GenericMapping,IN KPROCESSOR_MODE AccessMode,
240                 OUT PACCESS_MODE GrantedAccess,OUT PNTSTATUS AccessStatus)
241 {
242         g_return_val_if_fail(SecurityDescriptor!=NULL,FALSE);   /* means 'access denied' */
243         g_return_val_if_fail(SubjectSecurityContext!=NULL,FALSE);       /* means 'access denied' */
244         g_return_val_if_fail(Privileges!=NULL,FALSE);   /* means 'access denied' */
245         g_return_val_if_fail(GenericMapping!=NULL,FALSE);       /* means 'access denied' */
246         g_return_val_if_fail(GrantedAccess!=NULL,FALSE);        /* means 'access denied' */
247         g_return_val_if_fail(AccessStatus!=NULL,FALSE); /* means 'access denied' */
248
249         return TRUE;    /* access granted */
250 }