//+----------------------------------------------------------------------- // // Microsoft Windows // // Copyright (c) Microsoft Corporation 1991 - 1992 // // File: sputil.c // // Contents: Security package utility functions. Functions for maintaining // the list of available packages are kept here. // // // // History: 9 Dec 91, richardw Created // 11 Mar 92, RichardW Recreated, reworked, etc. // 21 Mar 94, MikeSw Removed RPC stubs // //------------------------------------------------------------------------ #include extern "C" { #include "sesmgr.h" #include } // // Global variables and structures: // // // Debug stuff: // #if DBG ULONG NoUnload = 0; #endif extern WCHAR szLsaPath[] ; RTL_RESOURCE PackageListLock; PDLL_BINDING * pPackageDllList; ULONG PackageDllCount; ULONG PackageDllTotal; PLSAP_SECURITY_PACKAGE * pPackageControlList; ULONG PackageControlCount; ULONG PackageControlTotal; #define INITIAL_PACKAGE_DLL_SIZE 8 #define INITIAL_PACKAGE_CONTROL_SIZE 8 #define ReadLockPackageList() RtlAcquireResourceShared(&PackageListLock, TRUE) #define WriteLockPackageList() RtlAcquireResourceExclusive(&PackageListLock, TRUE) #define UnlockPackageList() RtlReleaseResource(&PackageListLock) PDLL_BINDING SpmpFindDll( PWSTR DllName); //+--------------------------------------------------------------------------- // // Function: BindOldPackage // // Synopsis: Loads an old style authentication package DLL // // Arguments: [hDll] -- // [pTable] -- // // History: 11-17-95 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL BindOldPackage( HANDLE hDll, PSECPKG_FUNCTION_TABLE pTable) { pTable->InitializePackage = (PLSA_AP_INITIALIZE_PACKAGE) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_INITIALIZE_PACKAGE); if (pTable->InitializePackage == NULL) { return(FALSE); } // // The package needs to support one of LogonUser, LogonUserEx, or LogonUserEx2 pTable->LogonUserEx2 = (PLSA_AP_LOGON_USER_EX2) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_LOGON_USER_EX2); // // If this is NULL, then the package should have exported a LsaApLogonUser or Ex // if (pTable->LogonUserEx2 == NULL) { pTable->LogonUserEx = (PLSA_AP_LOGON_USER_EX) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_LOGON_USER_EX); if (pTable->LogonUserEx == NULL) { pTable->LogonUser = (PLSA_AP_LOGON_USER) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_LOGON_USER); if (pTable->LogonUser == NULL) { return(FALSE); } } } pTable->CallPackage = (PLSA_AP_CALL_PACKAGE) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_CALL_PACKAGE); if (pTable->CallPackage == NULL) { return(FALSE); } // // CallPackageUntrusted is optional // pTable->CallPackageUntrusted = (PLSA_AP_CALL_PACKAGE_UNTRUSTED) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_CALL_PACKAGE_UNTRUSTED); pTable->CallPackagePassthrough = (PLSA_AP_CALL_PACKAGE_PASSTHROUGH) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_CALL_PACKAGE_PASSTHROUGH); pTable->LogonTerminated = (PLSA_AP_LOGON_TERMINATED) GetProcAddress((HMODULE)hDll, LSA_AP_NAME_LOGON_TERMINATED); if (pTable->LogonTerminated == NULL) { return(FALSE); } // // If the package supports accept credentials, great. Otherwise // just leave this blank. // pTable->AcceptCredentials = (SpAcceptCredentialsFn *) GetProcAddress((HMODULE) hDll, SP_ACCEPT_CREDENTIALS_NAME); return(TRUE); } //+------------------------------------------------------------------------- // // Function: WLsaEnumeratePackages() // // Synopsis: Worker function for LsaEnumeratePackages // // Effects: Fills in an array of SecPkgInfo structures // // Arguments: pcEntries - receives the number of packages // // pPackages - receives all the SecPkgInfo structures // // Requires: // // Returns: success // // Notes: // //-------------------------------------------------------------------------- static LPWSTR szInvalidPackage = L"Invalid Package"; NTSTATUS WLsaEnumeratePackages( PULONG pcEntries, PSecPkgInfo * pPackages) { unsigned int i; PSession pSession = GetCurrentSession(); ULONG cbSize; PSecPkgInfo pInfo; PSecPkgInfo pLocalInfo = NULL, pClientInfo = NULL; LONG cbMark, cbLength; NTSTATUS scRet; PLSAP_SECURITY_PACKAGE pPackage; PLSA_CALL_INFO CallInfo ; ULONG Filter ; Filter = SP_ORDINAL_GETINFO ; CallInfo = LsapGetCurrentCall(); if ( CallInfo->CallInfo.Attributes & SECPKG_CALL_WOWCLIENT ) { Filter |= SP_ITERATE_FILTER_WOW ; } cbSize = sizeof(SecPkgInfo) * lsState.cPackages; pInfo = (PSecPkgInfo) LsapAllocateLsaHeap(cbSize); if (!pInfo) { return(SEC_E_INSUFFICIENT_MEMORY); } pPackage = SpmpIteratePackagesByRequest( NULL, Filter ); i = 0; while (pPackage) { SetCurrentPackageId( pPackage->dwPackageID ); __try { (VOID) pPackage->FunctionTable.GetInfo( &pInfo[i] ); cbSize += (wcslen(pInfo[i].Name) + 1) * sizeof(WCHAR); cbSize += (wcslen(pInfo[i].Comment) + 1) * sizeof(WCHAR); } __except (SP_EXCEPTION) { SPException( GetExceptionCode(), pPackage->dwPackageID ); // // Catch it, kill the package, proceed... // } pPackage = SpmpIteratePackagesByRequest( pPackage, Filter ); i ++; } *pcEntries = i; pLocalInfo = (PSecPkgInfo) LsapAllocateLsaHeap(cbSize); if (!pLocalInfo) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; } pClientInfo = (PSecPkgInfo) LsapClientAllocate(cbSize); if (!pClientInfo) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; } // // Compute the offset to adjust the pointers by // cbMark = *pcEntries * sizeof(SecPkgInfo); RtlCopyMemory(pLocalInfo,pInfo,cbMark); for (i = 0; i < *pcEntries ; i++ ) { cbLength = (wcslen(pInfo[i].Name)+1)*sizeof(WCHAR); RtlCopyMemory( (PBYTE) pLocalInfo + cbMark, pInfo[i].Name, cbLength); pLocalInfo[i].Name = (LPWSTR) ((PBYTE) pClientInfo + cbMark); cbMark += cbLength; cbLength = (wcslen(pInfo[i].Comment)+1)*sizeof(WCHAR); RtlCopyMemory( (PBYTE) pLocalInfo + cbMark, pInfo[i].Comment, cbLength); pLocalInfo[i].Comment = (LPWSTR) ((PBYTE) pClientInfo + cbMark); cbMark += cbLength; } SetCurrentPackageId( SPMGR_ID ); scRet = LsapCopyToClient(pLocalInfo,pClientInfo,cbSize); if (SUCCEEDED(scRet)) { *pPackages = pClientInfo; } Cleanup: if (pLocalInfo != NULL) { LsapFreeLsaHeap(pLocalInfo); } if (FAILED(scRet) && (pClientInfo != NULL)) { LsapClientFree(pClientInfo); } if (pInfo != NULL) { LsapFreeLsaHeap(pInfo); } return(scRet); } //+------------------------------------------------------------------------- // // Function: WLsaGetBinding() // // Synopsis: Gets the full path/DLL name for a package, based on ID // // Effects: // // Arguments: dwPackageID - ID of the package the caller needs the path for // pssPackageName - returns the name of package caller // // pszModuleName - Receives the name of the package. // // Requires: // // Returns: // // Notes: // //-------------------------------------------------------------------------- NTSTATUS WLsaGetBinding( ULONG_PTR dwPackageID, PSEC_PACKAGE_BINDING_INFO BindingInfo, PULONG TotalSize, PWSTR * Base) { PLSAP_SECURITY_PACKAGE pPackage; PWSTR Buffer; PLSA_CALL_INFO CallInfo ; PSECURITY_STRING DllPath ; SECURITY_STRING NullString = { 0 }; ZeroMemory( BindingInfo, sizeof( SEC_PACKAGE_BINDING_INFO ) ); pPackage = SpmpValidateHandle(dwPackageID); CallInfo = LsapGetCurrentCall(); if ( (pPackage != NULL ) && ( CallInfo->CallInfo.Attributes & SECPKG_CALL_WOWCLIENT ) != 0 ) { // // If this is a WOW client, only return bindings for the packages // that support WOW clients. // if ( ( pPackage->fPackage & SP_WOW_SUPPORT ) == 0 ) { pPackage = NULL ; } } if (pPackage) { // // Easy stuff: // BindingInfo->fCapabilities = pPackage->fCapabilities; BindingInfo->PackageIndex = pPackage->PackageIndex ; BindingInfo->Version = pPackage->Version ; BindingInfo->RpcId = pPackage->dwRPCID ; BindingInfo->TokenSize = pPackage->TokenSize ; if (pPackage->fPackage & SPM_AUTH_PKG_FLAG) { BindingInfo->Flags = PACKAGEINFO_AUTHPKG; // // Old style package: no remote binding // return( SEC_E_INVALID_HANDLE ); } DllPath = &pPackage->pBinding->Filename ; if ( pPackage->pBinding->Flags & DLL_BUILTIN ) { BindingInfo->Flags = PACKAGEINFO_BUILTIN ; DllPath = &NullString ; } if ( pPackage->pBinding->Flags & DLL_SIGNED ) { BindingInfo->Flags |= PACKAGEINFO_SIGNED ; } if ( ( pPackage->fPackage & SP_WOW_SUPPORT ) && ( CallInfo->CallInfo.Attributes & SECPKG_CALL_WOWCLIENT ) ) { DllPath = &pPackage->WowClientDll ; } // // If context thunks are present, copy them in: // if ( pPackage->Thunks ) { BindingInfo->ContextThunksCount = pPackage->Thunks->Info.ContextThunks.InfoLevelCount ; if ( pPackage->Thunks->Info.ContextThunks.InfoLevelCount < PACKAGEINFO_THUNKS ) { CopyMemory( BindingInfo->ContextThunks, pPackage->Thunks->Info.ContextThunks.Levels, BindingInfo->ContextThunksCount * sizeof(DWORD) ); } else { CopyMemory( BindingInfo->ContextThunks, pPackage->Thunks->Info.ContextThunks.Levels, PACKAGEINFO_THUNKS * sizeof( DWORD ) ); } } else { BindingInfo->ContextThunksCount = 0 ; } // // Compute Sizes: // *TotalSize = pPackage->Name.Length + 2 + pPackage->Comment.Length + 2 + DllPath->Length + 2 ; Buffer = (PWSTR) LsapAllocateLsaHeap( *TotalSize ); if ( !Buffer ) { return( SEC_E_INSUFFICIENT_MEMORY ); } BindingInfo->PackageName.Buffer = Buffer ; BindingInfo->PackageName.Length = pPackage->Name.Length ; BindingInfo->PackageName.MaximumLength = pPackage->Name.Length + 2; CopyMemory( BindingInfo->PackageName.Buffer, pPackage->Name.Buffer, BindingInfo->PackageName.MaximumLength ); BindingInfo->Comment.Buffer = BindingInfo->PackageName.Buffer + BindingInfo->PackageName.MaximumLength / 2 ; BindingInfo->Comment.Length = pPackage->Comment.Length; BindingInfo->Comment.MaximumLength = BindingInfo->Comment.Length + 2; CopyMemory( BindingInfo->Comment.Buffer, pPackage->Comment.Buffer, BindingInfo->Comment.MaximumLength ); if ( DllPath->Buffer ) { BindingInfo->ModuleName.Buffer = BindingInfo->Comment.Buffer + BindingInfo->Comment.MaximumLength / 2; BindingInfo->ModuleName.Length = DllPath->Length; BindingInfo->ModuleName.MaximumLength = BindingInfo->ModuleName.Length + 2; CopyMemory( BindingInfo->ModuleName.Buffer, DllPath->Buffer, BindingInfo->ModuleName.MaximumLength ); } *Base = Buffer ; return( SEC_E_OK ); } return( SEC_E_INVALID_HANDLE ); } //+--------------------------------------------------------------------------- // // Function: LsapFindPackage // // Synopsis: Internal function for the security DLL to reference packages // by ID // // Arguments: [pPackage] -- name of package // [pdwPackageId] -- returned id // // Returns: STATUS_SUCCESS -- Package found // SEC_E_SECPKG_NOT_FOUND -- Package not found // // History: 5-26-93 RichardW Created // //---------------------------------------------------------------------------- NTSTATUS WLsaFindPackage(PUNICODE_STRING pPackageName, ULONG_PTR * pdwPackageId) { PLSAP_SECURITY_PACKAGE pPackage; pPackage = SpmpLookupPackage(pPackageName); if (!pPackage) { *pdwPackageId = SPMGR_ID; return(SEC_E_SECPKG_NOT_FOUND); } else { *pdwPackageId = pPackage->dwPackageID; return(S_OK); } } //+--------------------------------------------------------------------------- // // Function: WLsaAddPackage // // Synopsis: Adds a security package to the system // // Arguments: [PackageName] -- Package Name // [Options] -- Options // // History: 9-18-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- NTSTATUS WLsaAddPackage( PSECURITY_STRING PackageName, PSECURITY_PACKAGE_OPTIONS Options) { SECPKG_PARAMETERS Parameters; PLSAP_SECURITY_PACKAGE Package; SECPKG_EVENT_PACKAGE_CHANGE Event; BOOL Success; SECURITY_STATUS scRet; PLSAPR_POLICY_DNS_DOMAIN_INFO DnsDomainInfo = NULL; HKEY hKey ; DebugLog(( DEB_TRACE, "Adding Package %ws\n", PackageName->Buffer )); // // Make sure the caller has the rights to do this by impersonating them, // then opening the registry key. // scRet = LsapImpersonateClient(); if ( NT_SUCCESS( scRet ) ) { int err ; err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szLsaPath, 0, KEY_READ | KEY_WRITE, &hKey ); if ( err != 0 ) { scRet = NtCurrentTeb()->LastStatusValue ; } else { RegCloseKey( hKey ); } RevertToSelf(); } if ( !NT_SUCCESS( scRet ) ) { return scRet ; } // // Build up the initialization message, to give the packages a better idea // of what is going on, and reduce their later calls for the same info. // Parameters.MachineState = (ULONG) 0; Parameters.SetupMode = SetupPhase; // // Make sure we haven't been through this already: // if ( SpmpFindDll( PackageName->Buffer ) ) { DebugLog(( DEB_TRACE, "AddPackage: DLL %ws already loaded\n", PackageName->Buffer )); return STATUS_SUCCESS ; } scRet = LsaIQueryInformationPolicyTrusted( PolicyDnsDomainInformation, (PLSAPR_POLICY_INFORMATION *) &DnsDomainInfo ); if (!NT_SUCCESS(scRet)) { DebugLog((DEB_ERROR,"Failed to get primary domain info: 0x%x\n",scRet)); return(scRet); } Parameters.DomainName = * (PUNICODE_STRING) &DnsDomainInfo->Name; Parameters.DnsDomainName = * (PUNICODE_STRING) &DnsDomainInfo->DnsDomainName; Parameters.DomainSid = (PSID) DnsDomainInfo->Sid; DebugLog((DEB_TRACE_INIT, "Init Parameters = %d, %s\n", Parameters.MachineState, (Parameters.SetupMode ? "Setup" : "Normal") )); if (SpmpLoadDll( PackageName->Buffer, &Parameters )) { // // Successful Load! Update the registry! // if ( Options->Flags & SECPKG_OPTIONS_PERMANENT ) { Success = AddPackageToRegistry( PackageName ); } else { Success = TRUE ; } if ( !Success ) { // // Unload it! // } } else { Success = FALSE ; } LsaIFree_LSAPR_POLICY_INFORMATION( PolicyDnsDomainInformation, (PLSAPR_POLICY_INFORMATION) DnsDomainInfo ); if ( Success ) { return( SEC_E_OK ); } return( SEC_E_SECPKG_NOT_FOUND ); } //+--------------------------------------------------------------------------- // // Function: WLsaDeletePackage // // Synopsis: Delete a security package // // Arguments: [PackageName] -- // // History: 9-18-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- NTSTATUS WLsaDeletePackage( PSECURITY_STRING PackageName) { return( SEC_E_NOT_SUPPORTED ); } //+------------------------------------------------------------------------- // // Function: SpmCreateEvent // // Synopsis: Just like the Win32 function, except that it allows // for names at the root of the namespace. // // Effects: // // Arguments: // // Requires: // // Returns: // // Notes: // //-------------------------------------------------------------------------- HANDLE SpmCreateEvent( LPSECURITY_ATTRIBUTES lpsa, BOOL fManualReset, BOOL fInitialState, LPTSTR pszEventName) { HANDLE hEvent; OBJECT_ATTRIBUTES EventAttr; UNICODE_STRING usName; NTSTATUS Status; ULONG ulWin32Error; RtlInitUnicodeString(&usName, pszEventName); if (lpsa) { InitializeObjectAttributes(&EventAttr, &usName, (lpsa->bInheritHandle ? OBJ_INHERIT : 0), NULL, lpsa->lpSecurityDescriptor); } else { InitializeObjectAttributes(&EventAttr, &usName, 0, NULL, NULL); } Status = NtCreateEvent( &hEvent, EVENT_ALL_ACCESS, &EventAttr, (fManualReset ? NotificationEvent : SynchronizationEvent), (BOOLEAN) fInitialState); if (!NT_SUCCESS(Status)) { ulWin32Error = RtlNtStatusToDosError( Status ); SetLastError(ulWin32Error); return(NULL); } return(hEvent); } //+------------------------------------------------------------------------- // // Function: SpmOpenEvent // // Synopsis: Just like Win32 OpenEvent, except that this supports \ in name // // Effects: // // Arguments: // // Requires: // // Returns: // // Notes: // //-------------------------------------------------------------------------- HANDLE SpmOpenEvent( ULONG fdwAccess, BOOL fInherit, LPTSTR pszEventName) { HANDLE hEvent; OBJECT_ATTRIBUTES EventAttr; UNICODE_STRING usName; NTSTATUS Status; ULONG ulWin32Error; RtlInitUnicodeString(&usName, pszEventName); InitializeObjectAttributes(&EventAttr, &usName, OBJ_CASE_INSENSITIVE | (fInherit ? OBJ_INHERIT : 0), NULL, NULL); Status = NtOpenEvent( &hEvent, fdwAccess, &EventAttr); if (!NT_SUCCESS(Status)) { ulWin32Error = RtlNtStatusToDosError( Status ); SetLastError(ulWin32Error); return(NULL); } return(hEvent); } //////////////////////////////////////////////////////////////////////////// // // // Package List Manipulation: // // //////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // Function: SpmpAddPackage // // Synopsis: Adds a package to the list. // // Arguments: [pPackage] -- Package to add // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- ULONG SpmpAddPackage( PLSAP_SECURITY_PACKAGE pPackage) { PLSAP_SECURITY_PACKAGE * pList; ULONG PackageId; // // Grab excluse access to the list: // WriteLockPackageList(); // // If we don't have any left over space in the array, realloc it // if ( PackageControlCount == PackageControlTotal ) { pList = (PLSAP_SECURITY_PACKAGE *) LsapAllocateLsaHeap( sizeof(PLSAP_SECURITY_PACKAGE) * (PackageControlTotal + INITIAL_PACKAGE_CONTROL_SIZE)); if (!pList) { UnlockPackageList(); return( 0xFFFFFFFF ); } CopyMemory( pList, pPackageControlList, sizeof( PLSAP_SECURITY_PACKAGE ) * PackageControlTotal ); PackageControlTotal += INITIAL_PACKAGE_CONTROL_SIZE; LsapFreeLsaHeap( pPackageControlList ); pPackageControlList = pList; } // // Obtain a new package id (and slot) // PackageId = PackageControlCount++; pPackageControlList[ PackageId ] = pPackage; pPackage->pBinding->RefCount++; pPackage->dwPackageID = PackageId; UnlockPackageList(); return( PackageId ); } //+--------------------------------------------------------------------------- // // Function: SpmpRemovePackage // // Synopsis: Removes a package from the list // // Arguments: [PackageId] -- // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- VOID SpmpRemovePackage( ULONG PackageId) { WriteLockPackageList(); pPackageControlList[ PackageId ] = NULL; // // If the counter hasn't moved on, reclaim the index // if (PackageId == PackageControlCount - 1) { PackageControlCount--; } UnlockPackageList(); } //+--------------------------------------------------------------------------- // // Function: SpmpAddDll // // Synopsis: Add a DLL binding // // Arguments: [pBinding] -- // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpAddDll( PDLL_BINDING pBinding) { PDLL_BINDING * pList; ULONG DllId; WriteLockPackageList(); if ( PackageDllCount == PackageDllTotal ) { pList = (PDLL_BINDING *) LsapAllocateLsaHeap( sizeof(PDLL_BINDING) * (PackageDllTotal + INITIAL_PACKAGE_DLL_SIZE)); if (!pList) { UnlockPackageList(); return( FALSE ); } CopyMemory( pList, pPackageDllList, sizeof( PDLL_BINDING ) * PackageDllTotal ); PackageDllTotal += INITIAL_PACKAGE_DLL_SIZE; LsapFreeLsaHeap( pPackageDllList ); pPackageDllList = pList; } pPackageDllList[ PackageDllCount++ ] = pBinding; UnlockPackageList(); return( TRUE ); } //+--------------------------------------------------------------------------- // // Function: SpmpRemoveDll // // Synopsis: Removes a DLL binding // // Arguments: [pBinding] -- // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- VOID SpmpRemoveDll( PDLL_BINDING pBinding) { ULONG i; WriteLockPackageList(); if (pPackageDllList[PackageDllCount - 1] == pBinding ) { PackageDllCount --; pPackageDllList[ PackageDllCount ] = NULL; } else { for (i = 0; i < PackageDllCount ; i++ ) { if (pPackageDllList[ i ] == pBinding) { pPackageDllList[ i ] = NULL; break; } } } UnlockPackageList(); } //+--------------------------------------------------------------------------- // // Function: SpmpFindDll // // Synopsis: Searches set of DLLs already loaded for a DLL name // // Arguments: [DllName] -- absolute or relative path name // // History: 9-20-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PDLL_BINDING SpmpFindDll( PWSTR DllName) { WCHAR DllPath[ MAX_PATH ]; PWSTR FilePart; DWORD Length; UNICODE_STRING Search; PDLL_BINDING pBinding; DWORD i; pBinding = NULL ; Length = SearchPath(NULL, DllName, TEXT(".DLL"), MAX_PATH, DllPath, &FilePart ); if ( Length ) { // // Name hit, see if we've loaded it already: // Search.Buffer = DllPath; Search.Length = (USHORT) (Length * sizeof( WCHAR )); Search.MaximumLength = Search.Length + sizeof( WCHAR ) ; ReadLockPackageList(); for ( i = 0 ; i < PackageDllCount ; i++ ) { if ( RtlEqualUnicodeString( &Search, &(pPackageDllList[i]->Filename), TRUE) ) { pBinding = pPackageDllList[ i ]; break; } } UnlockPackageList(); } return( pBinding ); } //+--------------------------------------------------------------------------- // // Function: LsapGetExtendedPackageInfo // // Synopsis: Wrapper to get extended information from a package // // Arguments: [Package] -- Package to query // [Class] -- Information class // [Info] -- returned data // // History: 3-04-97 RichardW Created // // Notes: // //---------------------------------------------------------------------------- NTSTATUS LsapGetExtendedPackageInfo( PLSAP_SECURITY_PACKAGE Package, SECPKG_EXTENDED_INFORMATION_CLASS Class, PSECPKG_EXTENDED_INFORMATION * Info ) { NTSTATUS Status ; if ( (Package->fPackage & SP_INFO) == 0 ) { return SEC_E_NOT_SUPPORTED ; } DebugLog(( DEB_TRACE, "Getting extended information (%d) from %ws\n", Class, Package->Name.Buffer )); __try { Status = Package->FunctionTable.GetExtendedInformation( Class, Info ); } __except (SP_EXCEPTION) { Status = SPException(GetExceptionCode(), Package->dwPackageID); } return Status ; } NTSTATUS LsapSetExtendedPackageInfo( PLSAP_SECURITY_PACKAGE Package, SECPKG_EXTENDED_INFORMATION_CLASS Class, PSECPKG_EXTENDED_INFORMATION Info ) { NTSTATUS Status ; if ( ((Package->fPackage & SP_INFO) == 0 ) || ( Package->FunctionTable.SetExtendedInformation == NULL ) ) { return SEC_E_NOT_SUPPORTED ; } DebugLog(( DEB_TRACE, "Setting extended information (%d) from %ws\n", Class, Package->Name.Buffer )); __try { Status = Package->FunctionTable.SetExtendedInformation( Class, Info ); } __except (SP_EXCEPTION) { Status = SPException(GetExceptionCode(), Package->dwPackageID); } return Status ; } //+--------------------------------------------------------------------------- // // Function: LsapAuditPackageBoot // // Synopsis: Audit a package boot (load) // // Arguments: [pPackage] -- // // History: 5-06-97 RichardW Created // // Notes: // //---------------------------------------------------------------------------- VOID LsapAuditPackageBoot( IN PLSAP_SECURITY_PACKAGE pPackage ) { WCHAR PackageAndDll[ MAX_PATH ]; UNICODE_STRING AuditName; wcsncpy( PackageAndDll, pPackage->pBinding->Filename.Buffer, MAX_PATH ); wcsncat( PackageAndDll, L" : ", MAX_PATH - (pPackage->pBinding->Filename.Length / sizeof(WCHAR)) ); wcsncat( PackageAndDll, pPackage->Name.Buffer, MAX_PATH - ( pPackage->pBinding->Filename.Length / sizeof(WCHAR) + 4) ); RtlInitUnicodeString( &AuditName, PackageAndDll ); LsapAdtAuditPackageLoad( &AuditName ); } //+--------------------------------------------------------------------------- // // Function: SpmpBootPackage // // Synopsis: Initializes a package by calling it's entry points // // Arguments: [pPackage] -- Package to initialize // [pParameters] -- Initialization parameters // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpBootPackage( IN PLSAP_SECURITY_PACKAGE pPackage, IN PSECPKG_PARAMETERS pParameters ) { SECURITY_STATUS scRetCode; SecPkgInfo spiPackage = { 0 }; UNICODE_STRING TempString; PSECPKG_EXTENDED_INFORMATION WowClient ; // // Break now so debugging people can set breakpoints in the newly loaded // DLL. // BreakOnError(BREAK_ON_LOAD); // Call the packages initialize function. This gives the package a chance // to do whatever initialization it needs to do. E.g. the kerberos package // runs out and finds the KDC. // // Set the session ID for tracking and so forth. // SetCurrentPackageId(pPackage->dwPackageID); __try { scRetCode = pPackage->FunctionTable.Initialize( pPackage->dwPackageID, pParameters, &LsapSecpkgFunctionTable ); } __except (SP_EXCEPTION) { // // Well, this is odd. The initialization function blew chunks. That // means that the package itself can't be trusted. So, let's change // this to an error return, and let the error logic blow away the // package. // scRetCode = SEC_E_CANNOT_INSTALL; } // // Let's see if the package loaded. Hmm. // if (FAILED(scRetCode)) { goto Cleanup; } // // Hey, a good one. Now, determine the capabilities of the package by // calling it's getinfo function. // __try { scRetCode = pPackage->FunctionTable.GetInfo( &spiPackage ); } __except (SP_EXCEPTION) { // // If it blows, catch it, and kill the package. // scRetCode = SPException(GetExceptionCode(), pPackage->dwPackageID); } // // Reset the session ID. // SetCurrentPackageId( SPMGR_ID ); // // If it failed, note that and return. Note, if there was an exception // then SPException() will have tagged the package appropriately. // if (FAILED(scRetCode)) { goto Cleanup; } pPackage->fCapabilities = spiPackage.fCapabilities; pPackage->dwRPCID = spiPackage.wRPCID; pPackage->Version = spiPackage.wVersion ; pPackage->TokenSize = spiPackage.cbMaxToken ; RtlInitUnicodeString( &TempString, spiPackage.Name ); scRetCode = LsapDuplicateString( &pPackage->Name, &TempString ); if (!NT_SUCCESS(scRetCode)) { goto Cleanup; } RtlInitUnicodeString( &TempString, spiPackage.Comment ); scRetCode = LsapDuplicateString( &pPackage->Comment, &TempString ); if ( !NT_SUCCESS( scRetCode ) ) { goto Cleanup; } // // Find out if the package supports extended information. If so, // find out what context attrs it wants thunked to LSA mode. // if ( pPackage->FunctionTable.GetExtendedInformation ) { pPackage->fPackage |= SP_INFO ; scRetCode = LsapGetExtendedPackageInfo( pPackage, SecpkgContextThunks, &pPackage->Thunks ); if ( scRetCode != STATUS_SUCCESS ) { pPackage->Thunks = NULL ; scRetCode = 0 ; } if ( pPackage->Thunks ) { pPackage->fPackage |= SP_CONTEXT_INFO ; } scRetCode = LsapGetExtendedPackageInfo( pPackage, SecpkgWowClientDll, &WowClient ); if ( scRetCode == STATUS_SUCCESS ) { scRetCode = LsapDuplicateString( &pPackage->WowClientDll, &WowClient->Info.WowClientDll.WowClientDllPath); if ( NT_SUCCESS( scRetCode ) ) { pPackage->fPackage |= SP_WOW_SUPPORT ; } } } DebugLog((DEB_TRACE_INIT | DEB_TRACE, "Loaded %ws, assigned ID %d, flags %#x\n", spiPackage.Name, pPackage->dwPackageID, pPackage->fPackage )); lsState.cPackages++; if ((pPackage->fPackage & SPM_AUTH_PKG_FLAG) == 0) { lsState.cNewPackages ++; } // // And write the audit // LsapAuditPackageBoot( pPackage ); return( TRUE ); Cleanup: return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: SpmpBootAuthPackage // // Synopsis: Initializes an old-style authentication package. // // Arguments: [pPackage] -- // // History: 5-06-97 RichardW Created // // Notes: // //---------------------------------------------------------------------------- NTSTATUS SpmpBootAuthPackage( PLSAP_SECURITY_PACKAGE pPackage) { NTSTATUS scRet; PSTRING pNlsName; char * pszTemp; DebugLog((DEB_TRACE_LSA_AU, "Initializing package %d\n", pPackage->dwPackageID)); __try { scRet = pPackage->FunctionTable.InitializePackage( (ULONG) pPackage->dwPackageID, (PLSA_DISPATCH_TABLE) &LsapSecpkgFunctionTable, NULL, NULL, &pNlsName); if (NT_SUCCESS(scRet)) { // TODO: why is this alloc+copy here? pszTemp = (char *)LsapAllocateLsaHeap(pNlsName->Length + 1); if (pszTemp != NULL) { strncpy(pszTemp, pNlsName->Buffer, pNlsName->Length); scRet = RtlAnsiStringToUnicodeString( &pPackage->Name, pNlsName, TRUE // allocate destination ); LsapFreeLsaHeap(pszTemp); } else { scRet = STATUS_INSUFFICIENT_RESOURCES; } // // NTBUG 395189 // Do not free the returned name. There is no correct way to do // this, and some vendors do not separately allocate the string // and structure, and some might use some other part of memory. // So allow this potential leak, but since they are loaded only once // and at boot time, that's ok. // #if 0 // // Free the returned name // LsapFreeLsaHeap(pNlsName->Buffer); LsapFreeLsaHeap(pNlsName); #endif } } __except (SP_EXCEPTION) { scRet = SPException(GetExceptionCode(), pPackage->dwPackageID); } if (SUCCEEDED(scRet)) { lsState.cPackages ++; LsapAuditPackageBoot( pPackage ); } return(scRet); } //+--------------------------------------------------------------------------- // // Function: SpmpLoadPackage // // Synopsis: Loads a specific package from a DLL binding // // Arguments: [pBinding] -- Binding to work from // [Package] -- Package index to load // [pParameters] -- Parameters to pass for initialization // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpLoadPackage( PDLL_BINDING pBinding, ULONG Package, PSECPKG_PARAMETERS pParameters) { ULONG PackageId; PLSAP_SECURITY_PACKAGE pPackage; SECPKG_EVENT_PACKAGE_CHANGE Event; // // Get the package dispatch table: // pPackage = &pBinding->Packages[Package]; // // Update its binding entry // pPackage->pBinding = pBinding; pPackage->PackageIndex = Package ; // // Add it as a package to run // PackageId = SpmpAddPackage( pPackage ); if ( PackageId != 0xFFFFFFFF ) { // // Boot it, so it is initialized // if ( SpmpBootPackage(pPackage, pParameters) ) { // // Notify any listeners: // Event.ChangeType = SECPKG_PACKAGE_CHANGE_LOAD ; Event.PackageName = pPackage->Name ; Event.PackageId = PackageId ; LsapEventNotify( NOTIFY_CLASS_PACKAGE_CHANGE, 0, sizeof( Event ), &Event ); return( TRUE ); } SpmpRemovePackage( PackageId ); } return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: SpmpLoadDll // // Synopsis: Loads a new DLL, determines the packages, and loads them // // Arguments: [pszDll] -- DLL name // [pParameters] -- Parameters for initialization // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpLoadDll( PWSTR pszDll, PSECPKG_PARAMETERS pParameters) { HANDLE hDll; DLL_BINDING * pBinding = NULL ; PDLL_BINDING * pList; SpLsaModeInitializeFn Init; ULONG PackageVersion; SECURITY_STATUS scRet; PSECPKG_FUNCTION_TABLE pTables; HINSTANCE hInstance = NULL ; ULONG PackageCount; PWSTR pszPath; ULONG cchPath; ULONG i; ULONG SuccessCount; BOOL IsSigned ; hInstance = LoadLibrary( pszDll ); if (hInstance) { Init = (SpLsaModeInitializeFn) GetProcAddress( hInstance, SECPKG_LSAMODEINIT_NAME); if (Init) { scRet = Init( SECPKG_INTERFACE_VERSION, &PackageVersion, &pTables, &PackageCount ); if (SUCCEEDED(scRet)) { pBinding = (PDLL_BINDING) LsapAllocateLsaHeap( sizeof( DLL_BINDING ) + (PackageCount - 1) * sizeof( LSAP_SECURITY_PACKAGE ) ); if (pBinding) { pBinding->hInstance = hInstance; pszPath = (PWSTR) LsapAllocateLsaHeap( MAX_PATH * 2 * 2 ); if (pszPath) { UNICODE_STRING TempString; cchPath = GetModuleFileName( hInstance, pszPath, MAX_PATH * 2 ); RtlInitUnicodeString( &TempString, pszPath ); scRet = LsapDuplicateString( &pBinding->Filename, &TempString ); LsapFreeLsaHeap( pszPath ); if (!NT_SUCCESS(scRet)) { // // Bail out: // goto LoadDll_Error; } #ifdef LSA_IGNORE_SIGNATURE IsSigned = TRUE; #else IsSigned = FALSE; { const LPWSTR ExclusionList[] = { L"msv1_0", L"kerberos", L"schannel", L"wdigest", NULL }; ULONG ExclusionIndex = 0; while( ExclusionList[ExclusionIndex] != NULL ) { if( lstrcmpiW( pszDll, ExclusionList[ExclusionIndex] ) == 0 ) { IsSigned = TRUE; break; } ExclusionIndex++; } } if( !IsSigned ) { IsSigned = RtlCheckSignatureInFile( pBinding->Filename.Buffer ); } #endif if ( IsSigned ) { pBinding->Flags |= DLL_SIGNED ; } } pBinding->PackageCount = PackageCount; SuccessCount = 0; for (i = 0 ; i < PackageCount ; i++ ) { // // Old auth packages contain all functions up to but not including // SetContextAttributes. // if ( PackageVersion == SECPKG_INTERFACE_VERSION ) { // // Copy the exported table and zero the rest. // CopyMemory( &pBinding->Packages[i].FunctionTable, &pTables[i], offsetof(SECPKG_FUNCTION_TABLE, SetContextAttributes ) ); ZeroMemory( ((LPBYTE)(&pBinding->Packages[i].FunctionTable)) + offsetof(SECPKG_FUNCTION_TABLE, SetContextAttributes), sizeof(SECPKG_FUNCTION_TABLE) - offsetof(SECPKG_FUNCTION_TABLE, SetContextAttributes) ); } else { CopyMemory( &pBinding->Packages[i].FunctionTable, &pTables[i], sizeof(SECPKG_FUNCTION_TABLE) ); } if (SpmpLoadPackage( pBinding, i, pParameters )) { SuccessCount ++; } } if (SuccessCount) { SpmpAddDll( pBinding ); return( TRUE ); } } } } } LoadDll_Error : if ( pBinding != NULL ) { LsapFreeLsaHeap( pBinding ); } if ( hInstance != NULL ) { FreeLibrary( hInstance ); } return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: SpmpLoadAuthPkgDll // // Synopsis: Loads an old (msv1_0 style) DLL // // Arguments: [pszDll] -- // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpLoadAuthPkgDll( PWSTR pszDll) { SECURITY_STATUS scRet; HINSTANCE hInstance; PDLL_BINDING pBinding = NULL ; PLSAP_SECURITY_PACKAGE pPackage; ULONG PackageId; UNICODE_STRING PackageDll ; PWSTR pszPath ; DebugLog((DEB_TRACE_INIT, "Loading Old package %ws\n", pszDll)); hInstance = LoadLibrary( pszDll ); if ( hInstance ) { pBinding = (PDLL_BINDING) LsapAllocateLsaHeap( sizeof( DLL_BINDING ) ); if (pBinding) { pszPath = (PWSTR) LsapAllocateLsaHeap( MAX_PATH * 2 * 2 ); if (pszPath) { UNICODE_STRING TempString; DWORD cchPath ; cchPath = GetModuleFileName( hInstance, pszPath, MAX_PATH * 2 ); RtlInitUnicodeString( &TempString, pszPath ); scRet = LsapDuplicateString( &pBinding->Filename, &TempString ); LsapFreeLsaHeap( pszPath ); if (!NT_SUCCESS(scRet)) { goto LoadAuthDll_Error ; } } pBinding->Flags = DLL_AUTHPKG; pBinding->hInstance = hInstance; pPackage = pBinding->Packages; pPackage->pBinding = pBinding; pBinding->PackageCount = 1; if (BindOldPackage( hInstance, &pPackage->FunctionTable)) { pPackage->fPackage = SPM_AUTH_PKG_FLAG; pPackage->fCapabilities = SPM_AUTH_PKG_FLAG; pPackage->dwRPCID = SECPKG_ID_NONE; PackageId = SpmpAddPackage( pPackage ); if (PackageId != (ULONG) 0xFFFFFFFF) { if ( SpmpAddDll( pBinding ) ) { BreakOnError(BREAK_ON_LOAD); scRet = SpmpBootAuthPackage( pPackage ); if (SUCCEEDED(scRet)) { return( TRUE ); } SpmpRemoveDll( pBinding ); } LsapFreeString( &pBinding->Filename ); pBinding->Filename.Buffer = NULL ; SpmpRemovePackage( PackageId ); } } } } LoadAuthDll_Error: if ( pBinding ) { if ( pBinding->Filename.Buffer ) { LsapFreeString( &pBinding->Filename ); } LsapFreeLsaHeap( pBinding ); } if ( hInstance ) { FreeLibrary( hInstance ); } return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: SpmpLoadBuiltin // // Synopsis: Loads a builtin package // // Arguments: [Flags] -- Flags for the package // [pTable] -- Dispatch table // [pParameters] -- init parameters // // History: 7-26-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpLoadBuiltin( ULONG Flags, PSECPKG_FUNCTION_TABLE pTable, PSECPKG_PARAMETERS pParameters) { PDLL_BINDING pBinding; PLSAP_SECURITY_PACKAGE pPackage; SECURITY_STATUS scRetCode; SecPkgInfo spiPackage; ULONG PackageId; SECPKG_EVENT_PACKAGE_CHANGE Event; WCHAR Path[ MAX_PATH ]; SECURITY_STRING TempString ; pBinding = (PDLL_BINDING) LsapAllocateLsaHeap( sizeof( DLL_BINDING ) ); if (pBinding) { ZeroMemory( pBinding, sizeof( DLL_BINDING ) ); pBinding->Flags = DLL_BUILTIN; pBinding->PackageCount = 1; pBinding->hInstance = GetModuleHandle( L"lsasrv.dll" ); GetModuleFileName( (HINSTANCE) pBinding->hInstance, Path, MAX_PATH ); RtlInitUnicodeString( &TempString, Path ); scRetCode = LsapDuplicateString( &pBinding->Filename, &TempString ); if ( NT_SUCCESS( scRetCode ) ) { pPackage = pBinding->Packages; pPackage->pBinding = pBinding; pPackage->fPackage = Flags | SP_WOW_SUPPORT ; CopyMemory( &pPackage->FunctionTable, pTable, sizeof(SECPKG_FUNCTION_TABLE) ); // // Fake up the DLL binding: // if ( SpmpAddDll( pBinding ) ) { // // Add the package to the table: // PackageId = SpmpAddPackage( pPackage ); if ( PackageId != 0xFFFFFFFF ) { // // Initialize the package // if (SpmpBootPackage(pPackage, pParameters)) { // // Notify any listeners: // Event.PackageName = pPackage->Name ; Event.PackageId = PackageId ; Event.ChangeType = SECPKG_PACKAGE_CHANGE_LOAD ; LsapEventNotify( NOTIFY_CLASS_PACKAGE_CHANGE, 0, sizeof( Event ), &Event ); return( TRUE ); } SpmpRemovePackage( PackageId ); } SpmpRemoveDll( pBinding ); } } LsapFreeLsaHeap( pBinding->Filename.Buffer ); LsapFreeLsaHeap( pBinding ); } return( FALSE ); } BOOL SpmpLoadBuiltinAuthPkg( PSECPKG_FUNCTION_TABLE pTable) { PDLL_BINDING pBinding; ULONG PackageId; PLSAP_SECURITY_PACKAGE pPackage; SECURITY_STATUS scRet; WCHAR Path[ MAX_PATH ]; SECURITY_STRING TempString ; pBinding = (PDLL_BINDING) LsapAllocateLsaHeap( sizeof( DLL_BINDING ) ); if (pBinding) { pBinding->Flags = DLL_AUTHPKG | DLL_BUILTIN; pBinding->PackageCount = 1; pBinding->hInstance = GetModuleHandle( L"lsasrv.dll" ); GetModuleFileName( (HINSTANCE) pBinding->hInstance, Path, MAX_PATH ); RtlInitUnicodeString( &TempString, Path ); scRet = LsapDuplicateString( &pBinding->Filename, &TempString ); if ( NT_SUCCESS( scRet ) ) { pPackage = pBinding->Packages; pPackage->pBinding = pBinding; CopyMemory( &pPackage->FunctionTable, pTable, sizeof( SECPKG_FUNCTION_TABLE ) ); pPackage->fPackage = SPM_AUTH_PKG_FLAG; pPackage->fCapabilities = SPM_AUTH_PKG_FLAG; pPackage->dwRPCID = SECPKG_ID_NONE; PackageId = SpmpAddPackage( pPackage ); if (PackageId != (ULONG) 0xFFFFFFFF) { if ( SpmpAddDll( pBinding ) ) { BreakOnError(BREAK_ON_LOAD); scRet = SpmpBootAuthPackage( pPackage ); if (SUCCEEDED(scRet)) { return( TRUE ); } SpmpRemoveDll( pBinding ); } SpmpRemovePackage( PackageId ); } LsapFreeLsaHeap( pBinding ); } } return( FALSE ); } //+--------------------------------------------------------------------------- // // Function: SpmpLocatePackage // // Synopsis: Locates the package // // Arguments: [PackageId] -- // // History: 11-15-95 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpLocatePackage( ULONG_PTR PackageId) { PLSAP_SECURITY_PACKAGE pControl = NULL; ReadLockPackageList(); if( (ULONG)PackageId < PackageControlCount ) { pControl = pPackageControlList[PackageId]; } UnlockPackageList(); return( pControl ); } //+--------------------------------------------------------------------------- // // Function: SpmpValidateHandle // // Synopsis: Validates a package handle // // Arguments: [PackageHandle] -- // // History: 11-15-95 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpValidateHandle( ULONG_PTR PackageHandle) { PLSAP_SECURITY_PACKAGE pControl = NULL; ReadLockPackageList(); if ( PackageHandle < PackageControlCount ) { pControl = pPackageControlList[ PackageHandle ]; } UnlockPackageList(); return( pControl ); } //+--------------------------------------------------------------------------- // // Function: SpmpValidRequest // // Synopsis: Validates package handle, requested API code. // // Arguments: [PackageHandle] -- // [ApiCode] -- // // History: 11-15-95 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpValidRequest( ULONG_PTR PackageHandle, ULONG ApiCode) { PLSAP_SECURITY_PACKAGE pControl = NULL; PVOID * pTable; ReadLockPackageList(); if ( PackageHandle < PackageControlCount ) { pControl = pPackageControlList[ PackageHandle ]; } UnlockPackageList(); if (pControl) { if (pControl->fPackage & (SP_INVALID | SP_SHUTDOWN) ) { pControl = NULL; } } if (pControl) { pTable = (PVOID *) &pControl->FunctionTable; if (pTable[ApiCode]) { return( pControl ); } pControl = NULL; } return( pControl ); } //+--------------------------------------------------------------------------- // // Function: SpmpLookupPackage // // Synopsis: Looks up a package based on name // // Arguments: [pssPackageName] -- // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpLookupPackage( PUNICODE_STRING pssPackageName) { ULONG iPack; PLSAP_SECURITY_PACKAGE pPackage; PVOID * pTable; ReadLockPackageList(); for (iPack = 0; iPack < PackageControlCount ; iPack++ ) { pPackage = pPackageControlList[ iPack ]; if ( pPackage ) { if (RtlEqualUnicodeString( pssPackageName, &pPackageControlList[ iPack ]->Name, TRUE)) // case insensitive { UnlockPackageList(); return( pPackage ); } } } UnlockPackageList(); return(NULL); } //+--------------------------------------------------------------------------- // // Function: SpmpLookupPackageByRpcId // // Synopsis: Looks up a package based on RPC ID // // Arguments: [RpcId] -- // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpLookupPackageByRpcId( ULONG RpcId) { ULONG iPack; PLSAP_SECURITY_PACKAGE pPackage; PVOID * pTable; ReadLockPackageList(); for (iPack = 0; iPack < PackageControlCount ; iPack++ ) { pPackage = pPackageControlList[ iPack ]; if ( pPackage ) { if (RpcId == pPackageControlList[iPack]->dwRPCID) { UnlockPackageList(); return( pPackage ); } } } UnlockPackageList(); return(NULL); } //+--------------------------------------------------------------------------- // // Function: SpmpLookupPackageAndRequest // // Synopsis: Returns a package pointer based on a name and the API code // // Arguments: [pssPackageName] -- Package name // [ApiCode] -- Code // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpLookupPackageAndRequest( PUNICODE_STRING pssPackageName, ULONG ApiCode) { ULONG iPack; PLSAP_SECURITY_PACKAGE pPackage; PVOID * pTable; ReadLockPackageList(); for (iPack = 0; iPack < PackageControlCount ; iPack++ ) { pPackage = pPackageControlList[ iPack ]; if ( pPackage ) { if (RtlEqualUnicodeString( pssPackageName, &pPackageControlList[ iPack ]->Name, TRUE)) // case insensitive { UnlockPackageList(); if ((pPackage->fPackage & ( SP_INVALID | SP_SHUTDOWN )) == 0) { pTable = (PVOID *) &pPackage->FunctionTable; if (pTable[ApiCode]) { return( pPackage ); } } return( NULL ); } } } UnlockPackageList(); return(NULL); } //+--------------------------------------------------------------------------- // // Function: SpmpIteratePackagesByRequest // // Synopsis: Cycle through packages by request code, returning packages // that support supplied API // // Arguments: [pInitialPackage] -- // [ApiCode] -- // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpIteratePackagesByRequest( PLSAP_SECURITY_PACKAGE pInitialPackage, ULONG ApiCode) { ULONG_PTR NextPackage; PLSAP_SECURITY_PACKAGE pPackage = NULL; PVOID * pTable; ULONG Ordinal ; ULONG FlagMaskOn = 0 ; ULONG FlagMaskOff = SP_INVALID | SP_SHUTDOWN ; Ordinal = ApiCode & SP_ORDINAL_MASK ; if ( ApiCode & SP_ITERATE_FILTER_WOW ) { FlagMaskOn |= SP_WOW_SUPPORT ; } ReadLockPackageList(); if (pInitialPackage) { NextPackage = pInitialPackage->dwPackageID + 1; } else { NextPackage = 0; } // // Walk through the list of packages, filtering on package flags // and whether the package supported the requested function // while (NextPackage < PackageControlCount) { pPackage = pPackageControlList[ NextPackage ]; if ( pPackage ) { if ( ( pPackage->fPackage & FlagMaskOff ) == 0 ) { if ( ( pPackage->fPackage & FlagMaskOn ) == FlagMaskOn ) { pTable = (PVOID *) &pPackage->FunctionTable; if ( pTable[ Ordinal ] ) { // // Found one! // break; } } } pPackage = NULL; } NextPackage++; } UnlockPackageList(); return( pPackage ); } //+--------------------------------------------------------------------------- // // Function: SpmpIteratePackages // // Synopsis: Safe iteration of the packages // // Arguments: [pInitialPackage] -- Prior package // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- PLSAP_SECURITY_PACKAGE SpmpIteratePackages( PLSAP_SECURITY_PACKAGE pInitialPackage) { ULONG_PTR NextPackage; PLSAP_SECURITY_PACKAGE pPackage = NULL; ReadLockPackageList(); if (pInitialPackage) { NextPackage = pInitialPackage->dwPackageID + 1; } else { NextPackage = 0; } while (NextPackage < PackageControlCount) { pPackage = pPackageControlList[ NextPackage ]; if ( pPackage ) { break; } NextPackage++; } UnlockPackageList(); return( pPackage ); } //+--------------------------------------------------------------------------- // // Function: SpmpCurrentPackageCount // // Synopsis: Returns the current package count // // Arguments: (none) // // History: 7-30-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- ULONG SpmpCurrentPackageCount( VOID) { ULONG Count; ReadLockPackageList(); Count = PackageControlCount; UnlockPackageList(); return( Count ); } //+--------------------------------------------------------------------------- // // Function: LsapAddPackageHandle // // Synopsis: Increases the package handle count // // Arguments: [PackageId] -- // // History: 10-08-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- VOID LsapAddPackageHandle( ULONG_PTR PackageId, BOOL IsContext ) { #if DBG PLSAP_SECURITY_PACKAGE Package ; Package = pPackageControlList[ PackageId ]; if ( IsContext ) { InterlockedIncrement( (PLONG)&Package->ContextHandles ); } else { InterlockedIncrement( (PLONG)&Package->CredentialHandles ); } #else UNREFERENCED_PARAMETER( PackageId ); UNREFERENCED_PARAMETER( IsContext ); #endif } //+--------------------------------------------------------------------------- // // Function: LsapDelPackageHandle // // Synopsis: Decrements the package handle count // // Arguments: [PackageId] -- // // History: 10-08-96 RichardW Created // // Notes: // //---------------------------------------------------------------------------- VOID LsapDelPackageHandle( PLSAP_SECURITY_PACKAGE Package, BOOL IsContext ) { #ifdef DBG if ( IsContext ) { InterlockedDecrement( (PLONG)&Package->ContextHandles ); } else { InterlockedDecrement( (PLONG)&Package->CredentialHandles ); } #else UNREFERENCED_PARAMETER( Package ); UNREFERENCED_PARAMETER( IsContext ); #endif } //+--------------------------------------------------------------------------- // // Function: SpmpInitializePackageControl // // Synopsis: Initialize the package controls // // Arguments: (none) // // History: 11-15-95 RichardW Created // // Notes: // //---------------------------------------------------------------------------- BOOL SpmpInitializePackageControl( VOID) { RtlInitializeResource( &PackageListLock ); WriteLockPackageList(); pPackageDllList = (PDLL_BINDING *) LsapAllocateLsaHeap( sizeof(PDLL_BINDING) * INITIAL_PACKAGE_DLL_SIZE ); if (pPackageDllList) { PackageDllCount = 0; PackageDllTotal = INITIAL_PACKAGE_DLL_SIZE; pPackageControlList = (PLSAP_SECURITY_PACKAGE *) LsapAllocateLsaHeap( sizeof(PLSAP_SECURITY_PACKAGE) * INITIAL_PACKAGE_CONTROL_SIZE ); if (pPackageControlList) { PackageControlCount = 0; PackageControlTotal = INITIAL_PACKAGE_CONTROL_SIZE; UnlockPackageList(); return( TRUE ); } LsapFreeLsaHeap( pPackageDllList ); } // // KEEP the lock, so that nothing else tries to use the package list // return( FALSE ); }