Ügyfél megszemélyesítése
Amikor egy felhasználói alkalmazás WMI-szolgáltatón keresztül kér adatokat a rendszer objektumaitól, a megszemélyesítés azt jelenti, hogy a szolgáltató a szolgáltató helyett az ügyfél biztonsági szintjét képviselő hitelesítő adatokat jelenít meg. A megszemélyesítés megakadályozza, hogy az ügyfél jogosulatlan hozzáférést kapjon a rendszer információihoz.
A következő szakaszokat tárgyaljuk ebben a témakörben:
- Szolgáltató regisztrálása megszemélyesítéshez
- Megszemélyesítési szintek beállítása egy szolgáltatón belül
- Biztonsági szintek fenntartása egy szolgáltató esetén
- Hozzáférés megtagadási üzenetek kezelése egy szolgáltatóban
- Jelentés a részleges példányokról
- Részleges felsorolások jelentése
- hozzáférés-megtagadott kód hibakeresése
- Kapcsolódó témakörök
A WMI általában magas biztonsági szintű rendszergazdai szolgáltatásként fut a LocalServer biztonsági környezet használatával. A rendszergazdai szolgáltatás használata lehetővé teszi a WMI számára a jogosultsági adatok elérését. Amikor egy szolgáltatót információkért hív meg, a WMI átadja a biztonsági azonosítóját (SID) a szolgáltatónak, lehetővé téve, hogy a szolgáltató azonos magas biztonsági szinten férhessen hozzá az információkhoz.
A WMI-alkalmazás indítása során a Windows operációs rendszer megadja a WMI-alkalmazásnak a folyamatot kezdő felhasználó biztonsági környezetét. A felhasználó biztonsági környezete általában alacsonyabb biztonsági szint, mint a LocalServer, ezért előfordulhat, hogy a felhasználó nem rendelkezik engedéllyel a WMI számára elérhető összes információ eléréséhez. Amikor a felhasználói alkalmazás dinamikus információkat kér, a WMI átadja a felhasználó SID-ét a megfelelő szolgáltatónak. Ha megfelelően meg van írva, a szolgáltató a szolgáltató SID-je helyett a felhasználói SID-vel próbál hozzáférni az adatokhoz.
Ahhoz, hogy a szolgáltató sikeresen megszemélyesítse az ügyfélalkalmazást, az ügyfélalkalmazásnak és a szolgáltatónak meg kell felelnie a következő feltételeknek:
- Az ügyfélalkalmazásnak a COM kapcsolatbiztonsági szintű RPC_C_IMP_LEVEL_IMPERSONATE vagy RPC_C_IMP_LEVEL_DELEGATEszinttel kell meghívnia a WMI-t. További információkért lásd: A WMI biztonság karbantartása.
- A szolgáltatónak megszemélyesítési szolgáltatóként kell regisztrálnia a WMI-ben. További információért lásd: Megszemélyesítési szolgáltató regisztrálása.
- A szolgáltatónak át kell váltania az ügyfélalkalmazás biztonsági szintjére a kiemelt információk elérése előtt. További információért lásd: Megszemélyesítési szintek beállítása egy szolgáltatón belül.
- Ha az információhoz való hozzáférés megtagadva van, a szolgáltatónak megfelelően kell kezelnie a hibafeltételeket. További információért lásd: Hozzáférés-megtagadási üzenetek kezelése szolgáltatónál.
Szolgáltató regisztrálása megszemélyesítésre
A WMI csak az ügyfélalkalmazás SID-címét továbbítja a megszemélyesítési szolgáltatóként regisztrált szolgáltatóknak. Ahhoz, hogy egy szolgáltató megszemélyesítést hajtson végre, módosítania kell a szolgáltató regisztrációs folyamatát.
Az alábbi eljárás bemutatja, hogyan regisztrálhat szolgáltatót megszemélyesítésre. Az eljárás feltételezi, hogy már ismeri a regisztrációs folyamatot. További információ a regisztrációs folyamatról: Egy szolgáltató regisztrációja.
Megszemélyesítéshez szolgáltató regisztrálása
Állítsa be a Megszemélyesítési szint tulajdonságát a __Win32Provider osztályban, amely a szolgáltatóját jelöli, 1 értékre.
A Megszemélyesítési szint tulajdonság dokumentálja, hogy a szolgáltató támogatja-e a megszemélyesítést. A Megszemélyesítési szint 0 értékre állítása azt jelzi, hogy a szolgáltató nem személyesíti meg az ügyfelet, és az összes kért műveletet ugyanabban a felhasználói környezetben hajtja végre, mint a WMI. A Megszemélyesítési szint 1 értékre állítása azt jelzi, hogy a szolgáltató megszemélyesítési hívásokkal ellenőrzi az ügyfél nevében végrehajtott műveleteket.
Állítsa be a PerUserInitialization tulajdonságot ugyanannak a __Win32Provider osztálynak TRUEértékre.
Jegyzet
Ha egy szolgáltatót a __Win32Provider tulajdonsággal regisztrál, a InitializeAsAdminFirst értékét TRUEállítva, akkor a szolgáltató csak az inicializálási fázisban használja az adminisztrációs szintű szálbiztonsági jogkivonatot. Bár a CoImpersonateClient hívása nem hiúsul meg, a szolgáltató a WMI biztonsági környezetét használja, nem pedig az ügyfélét.
Az alábbi példakód bemutatja, hogyan regisztrálhat szolgáltatót a megszemélyesítéshez.
instance of __Win32Provider
{
CLSID = "{FD4F53E0-65DC-11d1-AB64-00C04FD9159E}";
ImpersonationLevel = 1;
Name = "MS_NT_EVENTLOG_PROVIDER";
PerUserInitialization = TRUE;
};
Megszemélyesítési szintek beállítása egy szolgáltatón belül
Ha egy szolgáltatót regisztrál az __Win32Provider osztály tulajdonsággal, ahol a Megszemélyesítési szint 1-re van állítva, akkor a WMI meghívja a szolgáltatót, hogy különböző ügyfeleket megszemélyesítsen. A hívások kezeléséhez használja a CoImpersonateClient és CoRevertToSelf COM-függvényeket az IWbemServices felület megvalósításában.
A CoImpersonateClient függvény lehetővé teszi, hogy a kiszolgáló megszemélyesítse a hívást kezdeményező ügyfelet. Ha meghívja CoImpersonateClient a IWbemServicesimplementációjába, lehetővé teszi a szolgáltató számára, hogy a szolgáltató száljogkivonatát az ügyfél száljogkivonatának megfelelően állítsa be, és így megszemélyesítse az ügyfelet. Ha nem hívja meg CoImpersonateClient, a szolgáltató rendszergazdai szinten hajtja végre a kódot, ami potenciális biztonsági rést okoz. Ha a szolgáltatónak ideiglenesen rendszergazdaként kell működnie, vagy manuálisan kell elvégeznie a hozzáférés-ellenőrzést, hívja meg CoRevertToSelf.
Ellentétben CoImpersonateClientfunkcióval, CoRevertToSelf egy olyan COM függvény, amely a szálak megszemélyesítési szintjeit kezeli. Ebben az esetben CoRevertToSelf visszaállítja a megszemélyesítési szintet az eredeti megszemélyesítési beállításra. Általában a szolgáltató kezdetben rendszergazda, és a CoImpersonateClient és a CoRevertToSelf között váltakozik attól függően, hogy a hívót vagy a saját hívásait képviselő hívást kezdeményez. A szolgáltató felelőssége, hogy ezeket a hívásokat helyesen helyezze el, hogy ne tegye elérhetővé a végfelhasználó számára a biztonsági rést. A szolgáltatónak például csak natív Windows-függvényeket kell meghívnia a megszemélyesített kódütemezésen belül.
Jegyzet
A CoImpersonateClient és CoRevertToSelf célja a szolgáltató biztonságának beállítása. Ha megállapítja, hogy a megszemélyesítés sikertelen volt, megfelelő befejezési kódot kell visszaadnia a WMI-nek a következőn keresztül: IWbemObjectSink::SetStatus. További információért lásd: Hozzáférés megtagadva üzenetek kezelése a szolgáltatónál.
Biztonsági szintek fenntartása egy szolgáltatóban
A szolgáltatók nem hívhatják meg a CoImpersonateClient függvényt egyszer a IWbemServices implementáció során, és nem feltételezhetik, hogy a megszemélyesítési hitelesítő adatok érvényben maradnak a szolgáltató teljes működése alatt. Ehelyett egy implementáció során többször hívja meg CoImpersonateClient, hogy a WMI ne módosítsa a hitelesítő adatokat.
A szolgáltató megszemélyesítésének beállításával kapcsolatos fő szempont az újra beléphetőség. Ebben az összefüggésben a reentrancia az, amikor egy szolgáltató meghívja a WMI-t információkért, és megvárja, amíg a WMI visszahívja a szolgáltatót. Lényegében a végrehajtás szála elhagyja a szolgáltató kódját, hogy később visszatérjen oda. Az újrapróbálkozás a COM kialakításának része, és általában nem jelent problémát. Amikor azonban a végrehajtási szál a WMI-be kerül, a szál felveszi a WMI megszemélyesítési szintjeit. Amikor a szál visszatér a szolgáltatóhoz, szükséges a megszemélyesítési szinteket visszaállítani egy másik CoImpersonateClienthívással.
Ha meg szeretné védeni magát a szolgáltató biztonsági réseitől, csak az ügyfél megszemélyesítése közben kell újrahívásokat kezdeményeznie a WMI-be. Vagyis a CoImpersonateClient hívása után és CoRevertToSelfhívása előtt kell hívni a WMI-t. Mivel a CoRevertToSelf a megszemélyesítést arra a felhasználói szintre állítja be, amelyen a WMI fut, ami általában a LocalSystem, az ismétlődő WMI-hívások a CoRevertToSelf meghívása után sokkal több képességet biztosíthatnak a felhasználónak és a hívott szolgáltatóknak, mint amennyit kellene.
Jegyzet
Ha rendszerfüggvényt vagy más interfészmetódust hív meg, a hívási környezet nem garantáltan megmarad.
Hozzáférés-megtagadott üzenetek kezelése egy szolgáltatóban
A hozzáférés megtagadva hibaüzenetek többsége akkor jelenik meg, ha egy ügyfél olyan osztályt vagy információt kér, amelyhez nincs hozzáférése. Ha a szolgáltató hozzáférést megtagadó hibaüzenetet ad vissza a WMI-nek, és a WMI átadja ezt az ügyfélnek, az ügyfél arra következtethet, hogy az információ létezik. Bizonyos helyzetekben ez a biztonság megsértését okozhatja. Ezért a szolgáltató nem propagálja az üzenetet az ügyfélnek. Ehelyett a szolgáltató által megadott osztályok nem lesznek közzétéve. Hasonlóképpen, a dinamikus példányszolgáltatónak meg kell hívnia a mögöttes adatforrást annak megállapításához, hogyan kell kezelni a hozzáférés-megtagadott üzeneteket. A szolgáltató feladata, hogy replikálja ezt a filozófiát a WMI-környezetbe. További információ: Részleges példányok jelentése és Részleges enumerációk jelentése.
Ha megállapítja, hogy a szolgáltató hogyan kezelje a hozzáférés-megtagadott üzeneteket, meg kell írnia és hibakeresést kell végeznie a kódban. A hibakeresés során gyakran célszerű különbséget tenni az alacsony megszemélyesítés miatti megtagadás és a kód hibája miatti megtagadás között. A különbség meghatározásához használhat egy egyszerű tesztet a kódban. További információ: Hozzáférés-megtagadott kód hibakeresése.
Részleges példányok jelentése
A hozzáférés megtagadására vonatkozó üzenet egyik gyakori oka, hogy a WMI nem tudja megadni az összes szükséges információt a példány kitöltéséhez. Előfordulhat például, hogy az ügyfél rendelkezik a merevlemez-objektum megtekintésére vonatkozó jogosultsággal, de nem biztos, hogy rendelkezik jogosultsággal arra, hogy lássa, mennyi hely áll rendelkezésre magáról a merevlemez-meghajtóról. A szolgáltatónak meg kell határoznia, hogyan kezelje azokat a helyzeteket, amikor a szolgáltató nem tudja egy példányt tulajdonságokkal kitölteni a hozzáférési jog megsértése miatt.
A WMI nem igényel egyetlen választ azoknak az ügyfeleknek, amelyek részleges hozzáféréssel rendelkeznek egy példányhoz. Ehelyett a WMI 1.x-es verziója az alábbi lehetőségek egyikét teszi lehetővé a szolgáltató számára:
Sikertelen a teljes művelet a WBEM_E_ACCESS_DENIED hiba miatt, és nem ad vissza példányokat.
A megtagadás okának leírásához adjon vissza egy hibaobjektumot a WBEM_E_ACCESS_DENIEDegyütt.
Adja vissza az összes elérhető tulajdonságot, és töltse ki a nem elérhető tulajdonságokat NULL.
Jegyzet
Győződjön meg arról, hogy a visszaküldött WBEM_E_ACCESS_DENIED nem hoz létre biztonsági rést a vállalatnál.
Részleges számbavételek jelentése
A hozzáférés megsértése egy másik gyakori előfordulása, amikor a WMI nem tudja visszaadni az összes enumerálást. Előfordulhat például, hogy egy ügyfélnek hozzáférése van az összes helyi hálózati számítógép-objektum megtekintéséhez, de nem rendelkezik hozzáféréssel a tartományán kívüli számítógép-objektumok megtekintéséhez. A szolgáltatónak meg kell határoznia, hogyan kezelheti azokat a helyzeteket, amikor egy enumerálás nem hajtható végre hozzáférés-megsértés miatt.
A példányszolgáltatóhoz hasonlóan a WMI sem igényel egyetlen választ a részleges számbavételre. Ehelyett a WMI 1.x-es verziója az alábbi lehetőségek egyikét teszi lehetővé a szolgáltató számára:
Adja vissza WBEM_S_NO_ERROR minden példány esetében, amelyhez a szolgáltató hozzáférhet.
Ha ezt a lehetőséget használja, a felhasználó nem tudja, hogy egyes példányok nem voltak elérhetők. Számos szolgáltató, például a sorszintű biztonsággal rendelkező strukturált lekérdezési nyelvet (SQL) használó szolgáltatók sikeres részleges eredményeket adnak vissza a hívó biztonsági szintjének használatával az eredményhalmaz meghatározásához.
Szakítsa meg a teljes műveletet WBEM_E_ACCESS_DENIED, és ne adjon vissza példányokat.
A szolgáltató opcionálisan tartalmazhat egy hibaobjektumot, amely leírja az ügyfél helyzetét. Vegye figyelembe, hogy egyes szolgáltatók sorozatosan férhetnek hozzá az adatforrásokhoz, és előfordulhat, hogy csak az enumerálás során tapasztalnak megtagadásokat.
Adja vissza az összes elérhető példányt, de a nem érvénytelen állapotkódot is visszaadja WBEM_S_ACCESS_DENIED.
A szolgáltatónak fel kell jegyeznie a megtagadás eseményét az enumerálás során, és továbbra is biztosíthatja a példányokat. Végül hibamentes állapotkóddal zárhatja le. A szolgáltató dönthet úgy is, hogy az első megtagadáskor leállítja az enumerálást. Ennek a lehetőségnek az az oka, hogy a különböző szolgáltatók különböző lekérési paradigmával rendelkeznek. Előfordulhat, hogy a szolgáltató már kézbesített példányokat, mielőtt észlelte a hozzáférés megsértését. Egyes szolgáltatók dönthetnek úgy, hogy továbbra is más példányokat biztosítanak, míg mások megszüntethetik azokat.
A COM struktúrája miatt a hibaobjektumok kivételével a rendszer nem tud visszavenni semmilyen információt a hiba során. Ezért nem adhat vissza információt és hibakódot sem. Ha úgy dönt, hogy információt küld vissza, ehelyett egy nem-hibás állapotkódot kell használnia.
Hozzáférés-megtagadott kód hibakeresése
Egyes alkalmazások a RPC_C_IMP_LEVEL_IMPERSONATE-nál alacsonyabb megszemélyesítési szinteket használhatnak. Ebben az esetben az ügyfélalkalmazás szolgáltatója által kezdeményezett legtöbb megszemélyesítési hívás sikertelen lesz. A szolgáltató sikeres tervezéséhez és implementálásához szem előtt kell tartania ezt az ötletet.
Alapértelmezés szerint a szolgáltatóhoz csak a RPC_C_IMP_LEVEL_IDENTIFYmellett más megszemélyesítési szint férhet hozzá. Ha egy ügyfélalkalmazás RPC_C_IMP_LEVEL_IDENTIFYhasznál, CoImpersonateClient nem ad vissza hibakódot. Ehelyett a szolgáltató csak azonosítás céljából megszemélyesíti az ügyfelet. Ezért a szolgáltató által meghívott Windows-metódusok többsége egy hozzáférés-megtagadási üzenetet ad vissza. Ez a gyakorlatban ártalmatlan, mivel a felhasználók nem tehetnek semmi helytelent. A szolgáltató fejlesztése során azonban hasznos lehet tudni, hogy az ügyfél valóban megszemélyesítve volt-e.
A kód helyes fordításához a következő hivatkozásokra és #include utasításokra van szükség.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
Az alábbi példakód bemutatja, hogyan állapítható meg, hogy egy szolgáltató sikeresen megszemélyesített-e egy ügyfélalkalmazást.
DWORD dwImp = 0;
HANDLE hThreadTok;
DWORD dwBytesReturned;
BOOL bRes;
// You must call this before trying to open a thread token!
CoImpersonateClient();
bRes = OpenThreadToken(
GetCurrentThread(),
TOKEN_QUERY,
TRUE,
&hThreadTok
);
if (bRes == FALSE)
{
printf("Unable to read thread token (%d)\n", GetLastError());
return 0;
}
bRes = GetTokenInformation(
hThreadTok,
TokenImpersonationLevel,
&dwImp,
sizeof(DWORD),
&dwBytesReturned
);
if (!bRes)
{
printf("Unable to read impersonation level\n");
CloseHandle(hThreadTok);
return 0;
}
switch (dwImp)
{
case SecurityAnonymous:
printf("SecurityAnonymous\n");
break;
case SecurityIdentification:
printf("SecurityIdentification\n");
break;
case SecurityImpersonation:
printf("SecurityImpersonation\n");
break;
case SecurityDelegation:
printf("SecurityDelegation\n");
break;
default:
printf("Error. Unable to determine impersonation level\n");
break;
}
CloseHandle(hThreadTok);
Kapcsolódó témakörök
-
WMI-szolgáltatói fejlesztése
-
szolgáltatói biztonságossá tétele