You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
429 lines
11 KiB
429 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
immsec.c
|
|
|
|
Abstract:
|
|
|
|
security code called by IMEs
|
|
|
|
Author:
|
|
|
|
Chae Seong Lim [cslim] 23-Dec-1997
|
|
Takao Kitano [takaok] 01-May-1996
|
|
|
|
Revision History:
|
|
Chae Seong Lim [cslim] 971223 Korean IME version
|
|
Hiroaki Kanokogi [hiroakik] 960624 Modified for MSIME96
|
|
Hiroaki Kanokogi [hiroakik] 960911 NT #11911
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "immsec.h"
|
|
#include "winex.h"
|
|
|
|
|
|
#define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x)
|
|
#define MEMFREE(x) LocalFree(x)
|
|
|
|
//
|
|
// internal functions
|
|
//
|
|
PSID MyCreateSid( DWORD dwSubAuthority );
|
|
|
|
//
|
|
// debug functions
|
|
//
|
|
#ifdef DEBUG
|
|
#define ERROROUT(x) ErrorOut( x )
|
|
#define WARNOUT(x) WarnOut( x )
|
|
#else
|
|
#define ERROROUT(x)
|
|
#define WARNOUT(x)
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
VOID WarnOut( PTSTR pStr )
|
|
{
|
|
OutputDebugString( pStr );
|
|
}
|
|
|
|
VOID ErrorOut( PTSTR pStr )
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwResult;
|
|
static TCHAR buf1[512];
|
|
static TCHAR buf2[512];
|
|
|
|
dwError = GetLastError();
|
|
dwResult = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwError,
|
|
MAKELANGID( LANG_ENGLISH, LANG_NEUTRAL ),
|
|
buf1,
|
|
512,
|
|
NULL );
|
|
|
|
if (dwResult > 0)
|
|
{
|
|
wsprintfA(buf2, "%s:%s(0x%x)", pStr, buf1, dwError);
|
|
}
|
|
else
|
|
{
|
|
wsprintfA(buf2, "%s:(0x%x)", pStr, dwError);
|
|
}
|
|
OutputDebugString( buf2 );
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// GetIMESecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Allocate and set the security attributes that is
|
|
// appropriate for named objects created by an IME.
|
|
// The security attributes will give GENERIC_ALL
|
|
// access to the following users:
|
|
//
|
|
// o Users who log on for interactive operation
|
|
// o The user account used by the operating system
|
|
//
|
|
// Return value:
|
|
//
|
|
// If the function succeeds, the return value is a
|
|
// pointer to SECURITY_ATTRIBUTES. If the function fails,
|
|
// the return value is NULL. To get extended error
|
|
// information, call GetLastError().
|
|
//
|
|
// Remarks:
|
|
//
|
|
// FreeIMESecurityAttributes() should be called to free up the
|
|
// SECURITY_ATTRIBUTES allocated by this function.
|
|
//
|
|
|
|
static PSECURITY_ATTRIBUTES g_pSAIME = NULL;
|
|
|
|
PSECURITY_ATTRIBUTES GetIMESecurityAttributes(VOID)
|
|
{
|
|
if (IsWinNT())
|
|
return (g_pSAIME == NULL) ? (g_pSAIME = CreateSecurityAttributes()) : g_pSAIME;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// FreeIMESecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Frees the memory objects allocated by previous
|
|
// GetIMESecurityAttributes() call.
|
|
//
|
|
|
|
VOID FreeIMESecurityAttributes()
|
|
{
|
|
if (g_pSAIME != NULL)
|
|
FreeSecurityAttributes(g_pSAIME);
|
|
|
|
g_pSAIME = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// CreateSecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Allocate and set the security attributes that is
|
|
// appropriate for named objects created by an IME.
|
|
// The security attributes will give GENERIC_ALL
|
|
// access to the following users:
|
|
//
|
|
// o Users who log on for interactive operation
|
|
// o The user account used by the operating system
|
|
//
|
|
// Return value:
|
|
//
|
|
// If the function succeeds, the return value is a
|
|
// pointer to SECURITY_ATTRIBUTES. If the function fails,
|
|
// the return value is NULL. To get extended error
|
|
// information, call GetLastError().
|
|
//
|
|
// Remarks:
|
|
//
|
|
// FreeSecurityAttributes() should be called to free up the
|
|
// SECURITY_ATTRIBUTES allocated by this function.
|
|
//
|
|
PSECURITY_ATTRIBUTES CreateSecurityAttributes()
|
|
{
|
|
PSECURITY_ATTRIBUTES psa;
|
|
PSECURITY_DESCRIPTOR psd;
|
|
PACL pacl;
|
|
ULONG AclSize;
|
|
|
|
PSID psid1, psid2, psid3, psid4;
|
|
BOOL fResult;
|
|
|
|
psid1 = MyCreateSid(SECURITY_INTERACTIVE_RID);
|
|
if (psid1 == NULL)
|
|
return NULL;
|
|
|
|
psid2 = MyCreateSid(SECURITY_LOCAL_SYSTEM_RID);
|
|
if (psid2 == NULL)
|
|
goto Fail5;
|
|
|
|
psid3 = MyCreateSid(SECURITY_SERVICE_RID);
|
|
if (psid3 == NULL)
|
|
goto Fail4;
|
|
|
|
psid4 = MyCreateSid(SECURITY_NETWORK_RID);
|
|
if (psid4 == NULL)
|
|
goto Fail3;
|
|
|
|
//
|
|
// allocate and initialize an access control list (ACL) that will
|
|
// contain the SIDs we've just created.
|
|
//
|
|
AclSize = sizeof(ACL) +
|
|
(4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
|
|
GetLengthSid(psid1) +
|
|
GetLengthSid(psid2) +
|
|
GetLengthSid(psid3) +
|
|
GetLengthSid(psid4);
|
|
|
|
pacl = (PACL)MEMALLOC(AclSize);
|
|
if (pacl == NULL)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:LocalAlloc for ACL failed"));
|
|
goto Fail2;
|
|
}
|
|
|
|
fResult = InitializeAcl(pacl, AclSize, ACL_REVISION);
|
|
if (!fResult)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:InitializeAcl failed"));
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for interactive users to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid1);
|
|
|
|
if (!fResult)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:AddAccessAllowedAce failed"));
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid2);
|
|
|
|
if (!fResult)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:AddAccessAllowedAce failed"));
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid3);
|
|
|
|
if (!fResult)
|
|
{
|
|
ERROROUT( TEXT("CreateSecurityAttributes:AddAccessAllowedAce failed") );
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce(pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid4);
|
|
|
|
if (!fResult)
|
|
{
|
|
ERROROUT( TEXT("CreateSecurityAttributes:AddAccessAllowedAce failed") );
|
|
goto Fail;
|
|
}
|
|
|
|
//
|
|
// Those SIDs have been copied into the ACL. We don't need'em any more.
|
|
//
|
|
FreeSid(psid1);
|
|
FreeSid(psid2);
|
|
FreeSid(psid3);
|
|
FreeSid(psid4);
|
|
|
|
//
|
|
// Let's make sure that our ACL is valid.
|
|
//
|
|
if (!IsValidAcl(pacl))
|
|
{
|
|
WARNOUT(TEXT("CreateSecurityAttributes:IsValidAcl returns fFalse!"));
|
|
MEMFREE(pacl);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// allocate security attribute
|
|
//
|
|
psa = (PSECURITY_ATTRIBUTES)MEMALLOC(sizeof(SECURITY_ATTRIBUTES));
|
|
if (psa == NULL)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:LocalAlloc for psa failed"));
|
|
MEMFREE(pacl);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// allocate and initialize a new security descriptor
|
|
//
|
|
psd = MEMALLOC(SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
if (psd == NULL)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:LocalAlloc for psd failed"));
|
|
MEMFREE(pacl);
|
|
MEMFREE(psa);
|
|
return NULL;
|
|
}
|
|
|
|
if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:InitializeSecurityDescriptor failed"));
|
|
MEMFREE(pacl);
|
|
MEMFREE(psa);
|
|
MEMFREE(psd);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
fResult = SetSecurityDescriptorDacl(psd, fTrue, pacl, fFalse );
|
|
|
|
// The discretionary ACL is referenced by, not copied
|
|
// into, the security descriptor. We shouldn't free up ACL
|
|
// after the SetSecurityDescriptorDacl call.
|
|
|
|
if (!fResult)
|
|
{
|
|
ERROROUT(TEXT("CreateSecurityAttributes:SetSecurityDescriptorDacl failed"));
|
|
MEMFREE(pacl);
|
|
MEMFREE(psa);
|
|
MEMFREE(psd);
|
|
return NULL;
|
|
}
|
|
|
|
if (!IsValidSecurityDescriptor(psd))
|
|
{
|
|
WARNOUT(TEXT("CreateSecurityAttributes:IsValidSecurityDescriptor failed!"));
|
|
MEMFREE(pacl);
|
|
MEMFREE(psa);
|
|
MEMFREE(psd);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// everything is done
|
|
//
|
|
psa->nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
psa->lpSecurityDescriptor = (PVOID)psd;
|
|
psa->bInheritHandle = fTrue;
|
|
|
|
return psa;
|
|
|
|
Fail:
|
|
MEMFREE(pacl);
|
|
Fail2:
|
|
FreeSid(psid4);
|
|
Fail3:
|
|
FreeSid(psid3);
|
|
Fail4:
|
|
FreeSid(psid2);
|
|
Fail5:
|
|
FreeSid(psid1);
|
|
return NULL;
|
|
}
|
|
|
|
PSID MyCreateSid(DWORD dwSubAuthority)
|
|
{
|
|
PSID psid;
|
|
BOOL fResult;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
//
|
|
// allocate and initialize an SID
|
|
//
|
|
fResult = AllocateAndInitializeSid(&SidAuthority,
|
|
1,
|
|
dwSubAuthority,
|
|
0,0,0,0,0,0,0,
|
|
&psid );
|
|
if (!fResult)
|
|
{
|
|
ERROROUT(TEXT("MyCreateSid:AllocateAndInitializeSid failed"));
|
|
return NULL;
|
|
}
|
|
|
|
if (!IsValidSid(psid))
|
|
{
|
|
WARNOUT(TEXT("MyCreateSid:AllocateAndInitializeSid returns bogus sid"));
|
|
FreeSid(psid);
|
|
return NULL;
|
|
}
|
|
|
|
return psid;
|
|
}
|
|
|
|
//
|
|
// FreeSecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Frees the memory objects allocated by previous
|
|
// CreateSecurityAttributes() call.
|
|
//
|
|
VOID FreeSecurityAttributes( PSECURITY_ATTRIBUTES psa )
|
|
{
|
|
BOOL fResult;
|
|
BOOL fDaclPresent;
|
|
BOOL fDaclDefaulted;
|
|
PACL pacl;
|
|
|
|
fResult = GetSecurityDescriptorDacl(psa->lpSecurityDescriptor,
|
|
&fDaclPresent,
|
|
&pacl,
|
|
&fDaclDefaulted);
|
|
if (fResult)
|
|
{
|
|
|
|
if (pacl != NULL)
|
|
MEMFREE(pacl);
|
|
}
|
|
else
|
|
{
|
|
ERROROUT( TEXT("FreeSecurityAttributes:GetSecurityDescriptorDacl failed") );
|
|
}
|
|
|
|
MEMFREE(psa->lpSecurityDescriptor);
|
|
MEMFREE(psa);
|
|
}
|