/*++ 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 #include "hwxobj.h" #define _USEINIME_ //#ifndef _USEINIME_ // .IME does not need //#include //#include //#endif // _USEINIME_ #include "immsec.h" #define MEMALLOC(x) LocalAlloc(LMEM_FIXED, x) #define MEMFREE(x) LocalFree(x) // // internal functions // PSID MyCreateSid( DWORD dwSubAuthority ); #ifndef _USEINIME_ POSVERSIONINFO GetVersionInfo(VOID); #endif // _USEINIME_ // // 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 pSAIME = NULL; static PSECURITY_ATTRIBUTES pSAIME_UserDic = NULL; static INT nNT95 = 0; //0...Not examined, 1...NT, 2...Not NT PSECURITY_ATTRIBUTES GetIMESecurityAttributes(VOID) { if (nNT95 == 0) nNT95 = IsWinNT() ? 1 : 2; if (nNT95==1) return (pSAIME==NULL) ? (pSAIME=CreateSecurityAttributes()) : pSAIME; else return NULL; // To avoid CreateSecurityAttributes from being called every time when OS is not NT. } #if NOT_USED PSECURITY_ATTRIBUTES GetIMESecurityAttributesEx(VOID) { if (nNT95 == 0) nNT95 = IsWinNT() ? 1 : 2; //IsNT is not for multi-threaded programs, right? if (nNT95==1) return (pSAIME_UserDic==NULL) ? (pSAIME_UserDic=CreateSecurityAttributesEx()) : pSAIME_UserDic; else return NULL; // To avoid CreateSecurityAttributes from being called every time when OS is not NT. } #endif // // FreeIMESecurityAttributes() // // The purpose of this function: // // Frees the memory objects allocated by previous // GetIMESecurityAttributes() call. // VOID FreeIMESecurityAttributes() { if (pSAIME!=NULL) FreeSecurityAttributes(pSAIME); if (pSAIME_UserDic!=NULL) FreeSecurityAttributes(pSAIME_UserDic); pSAIME = NULL; pSAIME_UserDic = 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; DWORD cbacl; PSID psid1, psid2; BOOL fResult; psid1 = MyCreateSid( SECURITY_INTERACTIVE_RID ); if ( psid1 == NULL ) { return NULL; } psid2 = MyCreateSid( SECURITY_LOCAL_SYSTEM_RID ); if ( psid2 == NULL ) { FreeSid ( psid1 ); return NULL; } // // allocate and initialize an access control list (ACL) that will // contain the SIDs we've just created. // cbacl = sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) * 2 + GetLengthSid(psid1) + GetLengthSid(psid2); pacl = (PACL)MEMALLOC( cbacl ); if ( pacl == NULL ) { ERROROUT( TEXT("CreateSecurityAttributes:LocalAlloc for ACL failed") ); FreeSid ( psid1 ); FreeSid ( psid2 ); return NULL; } fResult = InitializeAcl( pacl, cbacl, ACL_REVISION ); if ( ! fResult ) { ERROROUT( TEXT("CreateSecurityAttributes:InitializeAcl failed") ); FreeSid ( psid1 ); FreeSid ( psid2 ); MEMFREE( pacl ); return NULL; } // // 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") ); MEMFREE( pacl ); FreeSid ( psid1 ); FreeSid ( psid2 ); return NULL; } // // 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") ); MEMFREE( pacl ); FreeSid ( psid1 ); FreeSid ( psid2 ); return NULL; } // // Those SIDs have been copied into the ACL. We don't need'em any more. // FreeSid ( psid1 ); FreeSid ( psid2 ); // // 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, TRUE, pacl, FALSE ); // 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 = FALSE; return psa; } 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 ); } #if NOT_USED // // Function Below is added to give GENERIC_ALL to everyone for UserDictionary // which is accessed from network (not interactive). // 960911 HiroakiK NT #11911 // // // CreateSecurityAttributesEx() // // 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 for everyone // ^^^^^^^^ // // 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 CreateSecurityAttributesEx() { PSECURITY_ATTRIBUTES psa; PSECURITY_DESCRIPTOR psd; PACL pacl; DWORD cbacl; PSID psid; BOOL fResult; // // create a sid for everyone access // psid = MyCreateSidEx(); if ( psid == NULL ) { return NULL; } // // allocate and initialize an access control list (ACL) that will // contain the SID we've just created. // cbacl = sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetLengthSid(psid); pacl = (PACL)MEMALLOC( cbacl ); if ( pacl == NULL ) { ERROROUT( TEXT("CreateSecurityAttributes:LocalAlloc for ACL failed") ); FreeSid ( psid ); return NULL; } fResult = InitializeAcl( pacl, cbacl, ACL_REVISION ); if ( ! fResult ) { ERROROUT( TEXT("CreateSecurityAttributes:InitializeAcl failed") ); FreeSid ( psid ); MEMFREE( pacl ); return NULL; } // // adds an access-allowed ACE for interactive users to the ACL // fResult = AddAccessAllowedAce( pacl, ACL_REVISION, GENERIC_ALL, psid ); if ( !fResult ) { ERROROUT( TEXT("CreateSecurityAttributes:AddAccessAllowedAce failed") ); MEMFREE( pacl ); FreeSid ( psid ); return NULL; } // // Those SIDs have been copied into the ACL. We don't need'em any more. // FreeSid ( psid ); // // 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, TRUE, pacl, FALSE ); // 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 = FALSE; return psa; } PSID MyCreateSidEx(VOID) { PSID psid; BOOL fResult; SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_WORLD_SID_AUTHORITY; // // allocate and initialize an SID // fResult = AllocateAndInitializeSid( &SidAuthority, 1, SECURITY_WORLD_RID, 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; } #endif