/* $Id$
* reactos security thin manager emulation of libcaptive
- * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
+ * Copyright (C) 2002-2003 Jan Kratochvil <project-captive@jankratochvil.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "config.h"
#include "reactos/ddk/setypes.h" /* self */
+#include <glib/gmessages.h>
+#include "reactos/ddk/status.h"
+#include "reactos/ddk/exfuncs.h" /* for ExAllocatePool() */
-static SE_EXPORTS SeExports_static;
+/**
+ * SeLockSubjectContext:
+ * @SubjectContext: Security context to read lock.
+ * %NULL value is forbidden.
+ *
+ * Obtain read locks on the security context @SubjectContext.
+ * @SubjectContext must be already acquired by SeCaptureSubjectContext().
+ *
+ * This functions is a NOP in libcaptive as there is no threading implemented.
+ * FIXME: No sanity checks are currently done by libcaptive.
+ */
+VOID SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+ g_return_if_fail(SubjectContext!=NULL);
+
+ /* NOP; TODO:thread */
+}
+
+
+/**
+ * SeUnlockSubjectContext:
+ * @SubjectContext: Security context to unlock.
+ * %NULL value is forbidden.
+ *
+ * Release read locks on the security context @SubjectContext.
+ * @SubjectContext must be currently locked by SeLockSubjectContext().
+ *
+ * This functions is a NOP in libcaptive as there is no threading implemented.
+ * FIXME: No sanity checks are currently done by libcaptive.
+ */
+VOID SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+{
+ g_return_if_fail(SubjectContext!=NULL);
+
+ /* NOP; TODO:thread */
+}
+
+
+static SID *SID_dup(SID *sid,SECURITY_DESCRIPTOR *src,SECURITY_DESCRIPTOR *dest,gpointer *destdatap)
+{
+SID *r;
+gsize size;
+
+ /* 'sid' may be NULL */
+ g_return_val_if_fail(src!=NULL,NULL);
+ g_return_val_if_fail(dest!=NULL,NULL);
+ g_return_val_if_fail(destdatap!=NULL,NULL);
+ g_return_val_if_fail(*destdatap!=NULL,NULL);
+
+ if (!sid)
+ return NULL;
+ if (src->Control & SE_SELF_RELATIVE)
+ sid=(SID *)(((ULONG)sid)+((ULONG)src));
+ if (!sid)
+ return NULL;
+
+ size=sizeof(*r)+sizeof(*r->SubAuthority)*(sid->SubAuthorityCount-1);
+ g_assert(size==(gsize)((*(guint8 *)(((char *)sid)+0x01))*4+8)); /* 0x14h is sizeof(SECURITY_DESCRIPTOR) */
+ g_assert(!(size&3)); /* sizeof(ULONG)-alignment */
+ r=*destdatap;
+ (*(char **)destdatap)+=size;
+ memcpy(r,sid,size);
+ if (dest->Control & SE_SELF_RELATIVE)
+ r=(SID *)(((ULONG)r)-((ULONG)dest));
+
+ return r;
+}
+
+static ACL *ACL_dup(ACL *acl,SECURITY_DESCRIPTOR *src,SECURITY_DESCRIPTOR *dest,gpointer *destdatap)
+{
+ACL *r;
+gsize size;
+
+ /* 'acl' may be NULL */
+ g_return_val_if_fail(src!=NULL,NULL);
+ g_return_val_if_fail(dest!=NULL,NULL);
+ g_return_val_if_fail(destdatap!=NULL,NULL);
+ g_return_val_if_fail(*destdatap!=NULL,NULL);
+
+ if (!acl)
+ return NULL;
+ if (src->Control & SE_SELF_RELATIVE)
+ acl=(ACL *)(((ULONG)acl)+((ULONG)src));
+ if (!acl)
+ r=NULL;
+ else {
+ /* W32 undocumented: ReactOS uses '&0xFF' notation, I have seen value PAGE_SIZE.
+ * W32 doc says it is a regular size.
+ */
+ size=acl->AclSize;
+ g_assert(!(size&3)); /* sizeof(ULONG)-alignment */
+ r=*destdatap;
+ (*(char **)destdatap)+=size;
+ memcpy(r,acl,size);
+ }
+ if (dest->Control & SE_SELF_RELATIVE)
+ r=(ACL *)(((ULONG)r)-((ULONG)dest));
+
+ return r;
+}
+
+/**
+ * SeAssignSecurity:
+ * @ParentDescriptor: Optional parent object security descriptor.
+ * %NULL value is permitted.
+ * @ExplicitDescriptor: Optional overriding descriptor for the new object.
+ * FIXME: %NULL value should be permitted but it is currently forbidden by libcaptive.
+ * @NewDescriptor: Returns the new generated descriptor.
+ * %NULL value is forbidden.
+ * @IsDirectoryObject: Will the new object contain its subobjects?
+ * @SubjectContext: Security context of the caller.
+ * %NULL value is forbidden.
+ * @GenericMapping: Rights mapping (?).
+ * %NULL value is forbidden.
+ * @PoolType: #POOL_TYPE to allocate new @NewDescriptor from.
+ *
+ * libcaptive requires either @ExplicitDescriptor or @ParentDescriptor
+ * to be presents and it recursively copies the structures to the
+ * target (allocated) @NewDescriptor. @ExplicitDescriptor is preferred
+ * over @ParentDescriptor if present. No structures merging is done.
+ *
+ * Returns: %STATUS_SUCCESS if @NewDescriptor was successfuly filled.
+ */
+NTSTATUS SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
+ PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,PSECURITY_DESCRIPTOR *NewDescriptor,
+ BOOLEAN IsDirectoryObject,PSECURITY_SUBJECT_CONTEXT SubjectContext,PGENERIC_MAPPING GenericMapping,POOL_TYPE PoolType)
+{
+SECURITY_DESCRIPTOR *src,*dest;
+ULONG size;
+gpointer destdata;
+
+ g_return_val_if_fail(NewDescriptor!=NULL,STATUS_INVALID_PARAMETER);
+ g_return_val_if_fail(SubjectContext!=NULL,STATUS_INVALID_PARAMETER);
+ g_return_val_if_fail(GenericMapping!=NULL,STATUS_INVALID_PARAMETER);
+
+ /* #2 0x40067021 in SeAssignSecurity (ParentDescriptor=0x0,
+ * ExplicitDescriptor=0xbfffe7f4, NewDescriptor=0x40b5873c,
+ * IsDirectoryObject=0 '\0', SubjectContext=0x409d2ff0,
+ * GenericMapping=0x40088014, PoolType=1) at semgr.c:79
+ * #2 0x4006fe45 in SeAssignSecurity (ParentDescriptor=0x411b3fd0,
+ * ExplicitDescriptor=0x0, NewDescriptor=0xbfffe39c,
+ * IsDirectoryObject=1 '\001', SubjectContext=0xbfffe90c,
+ * GenericMapping=0x40094014, PoolType=1) at semgr.c:99
+ */
+ g_return_val_if_fail(ExplicitDescriptor!=NULL || ParentDescriptor!=NULL,STATUS_NOT_IMPLEMENTED); /* NOT YET IMPLEMENTED */
+
+ src=(ExplicitDescriptor ? ExplicitDescriptor : ParentDescriptor);
+
+ size=RtlLengthSecurityDescriptor(src);
+ g_assert(!(size&3)); /* sizeof(ULONG)-alignment */
+
+ dest=ExAllocatePool(PagedPool,size);
+ g_return_val_if_fail(dest!=NULL,STATUS_NO_MEMORY);
+
+ dest->Revision=src->Revision;
+ dest->Control=src->Control;
+ destdata=(dest+1);
+ dest->Owner=SID_dup(src->Owner,src,dest,&destdata);
+ dest->Group=SID_dup(src->Group,src,dest,&destdata);
+ if (src->Control & SE_SACL_PRESENT) {
+ /* 'SE_SACL_PRESENT' may be site while 'Sacl==NULL'.
+ * FIXME: How it differs from '!SE_SACL_PRESENT'?
+ */
+ dest->Sacl=ACL_dup(src->Sacl,src,dest,&destdata);
+ }
+ else
+ dest->Sacl=NULL;
+ if (src->Control & SE_DACL_PRESENT) {
+ /* 'SE_DACL_PRESENT' may be site while 'Dacl==NULL'.
+ * FIXME: How it differs from '!SE_DACL_PRESENT'?
+ */
+ dest->Dacl=ACL_dup(src->Dacl,src,dest,&destdata);
+ }
+ else
+ dest->Dacl=NULL;
+
+ g_assert(((char *)dest)+size==destdata);
+
+ *NewDescriptor=dest;
+
+ return STATUS_SUCCESS;
+}
+
+
+/**
+ * SeAccessCheck:
+ * @SecurityDescriptor: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ * @SubjectSecurityContext: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ * @SubjectContextLocked: IGNORED; ignored by libcaptive.
+ * @DesiredAccess: IGNORED; ignored by libcaptive.
+ * @PreviouslyGrantedAccess: IGNORED; ignored by libcaptive.
+ * @Privileges: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ * @GenericMapping: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ * @AccessMode: IGNORED; ignored by libcaptive.
+ * @GrantedAccess: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ * @AccessStatus: IGNORED; ignored by libcaptive.
+ * %NULL value is forbidden.
+ *
+ * Query the rights of IGNORED to access IGNORED.
+ *
+ * libcaptive does not support any security and therefore it always returns %TRUE.
+ *
+ * Returns: %TRUE if the access is granted.
+ */
+BOOLEAN SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
+ IN BOOLEAN SubjectContextLocked,IN ACCESS_MASK DesiredAccess,IN ACCESS_MASK PreviouslyGrantedAccess,
+ OUT PPRIVILEGE_SET* Privileges,IN PGENERIC_MAPPING GenericMapping,IN KPROCESSOR_MODE AccessMode,
+ OUT PACCESS_MODE GrantedAccess,OUT PNTSTATUS AccessStatus)
+{
+ g_return_val_if_fail(SecurityDescriptor!=NULL,FALSE); /* means 'access denied' */
+ g_return_val_if_fail(SubjectSecurityContext!=NULL,FALSE); /* means 'access denied' */
+ g_return_val_if_fail(Privileges!=NULL,FALSE); /* means 'access denied' */
+ g_return_val_if_fail(GenericMapping!=NULL,FALSE); /* means 'access denied' */
+ g_return_val_if_fail(GrantedAccess!=NULL,FALSE); /* means 'access denied' */
+ g_return_val_if_fail(AccessStatus!=NULL,FALSE); /* means 'access denied' */
-SE_EXPORTS *SeExports=&SeExports_static;
+ return TRUE; /* access granted */
+}