Een client imiteren
Wanneer een gebruikerstoepassing gegevens van objecten op het systeem aanvraagt via een WMI-provider, betekent imitatie dat de provider referenties presenteert die het beveiligingsniveau van de client vertegenwoordigen in plaats van de provider. Imitatie voorkomt dat een client onbevoegde toegang krijgt tot informatie op het systeem.
In dit onderwerp worden de volgende secties besproken:
- Een provider registreren voor impersonatie
- imitatieniveaus instellen binnen een provider
- beveiligingsniveaus onderhouden in een provider-
- toegang geweigerde berichten verwerken in een provider-
- Gedeeltelijke gevallen rapporteren
- het rapporteren van gedeeltelijke opsommingen
- foutopsporing van uw code voor geweigerde toegang
- Verwante onderwerpen
WMI wordt doorgaans uitgevoerd als een beheerservice op hoog beveiligingsniveau, met behulp van de LocalServer-beveiligingscontext. Als u een beheerservice gebruikt, beschikt WMI over de middelen voor toegang tot bevoegde informatie. Bij het aanroepen van een provider voor informatie geeft WMI de beveiligings-id (SID) door aan de provider, zodat de provider toegang heeft tot informatie op hetzelfde hoge beveiligingsniveau.
Tijdens het startproces van de WMI-toepassing geeft het Windows-besturingssysteem de WMI-toepassing de beveiligingscontext van de gebruiker die het proces heeft gestart. De beveiligingscontext van de gebruiker is doorgaans een lager beveiligingsniveau dan LocalServer, dus de gebruiker heeft mogelijk geen toegang tot alle informatie die beschikbaar is voor WMI. Wanneer de gebruikerstoepassing om dynamische informatie vraagt, geeft WMI de SID van de gebruiker door aan de bijbehorende provider. Indien nodig probeert de provider toegang te krijgen tot informatie met de gebruikers-SID in plaats van de provider-SID.
Opdat de provider met succes de clienttoepassing kan imiteren, moeten zowel de clienttoepassing als de provider aan de volgende criteria voldoen:
- De clienttoepassing moet WMI aanroepen met een COM-verbindingsbeveiligingsniveau van RPC_C_IMP_LEVEL_IMPERSONATE of RPC_C_IMP_LEVEL_DELEGATE. Zie WMI-beveiliging onderhoudenvoor meer informatie.
- De provider moet zich registreren bij WMI als een imitatieprovider. Voor meer informatie, zie Een provider registreren voor impersonatie.
- De provider moet overschakelen naar het beveiligingsniveau van de clienttoepassing voordat toegang wordt geboden tot bevoegde informatie. Voor meer informatie, zie Imitatieniveaus instellen binnen een provider.
- De provider moet foutvoorwaarden correct afhandelen als de toegang tot deze informatie wordt geweigerd. Voor meer informatie, zie Het verwerken van toegang geweigerde berichten in een provider.
Een provider registreren voor imitatie
WMI geeft alleen de SID van een clienttoepassing door aan providers die zijn geregistreerd als imitatieproviders. Als u een provider inschakelt om imitatie uit te voeren, moet u het registratieproces van de provider wijzigen.
De volgende procedure beschrijft hoe u een provider registreert voor impersonatie. In de procedure wordt ervan uitgegaan dat u het registratieproces al begrijpt. Zie Een provider registrerenvoor meer informatie over het registratieproces.
Een provider registreren voor impersonatie
Stel de eigenschap ImpersonationLevel van de __Win32Provider-klasse in die uw provider vertegenwoordigt op 1.
De eigenschap ImpersonationLevel documenteert of de provider imitatie ondersteunt of niet. Als u ImpersonationLevel instelt op 0, geeft u aan dat de provider de client niet imiteert en alle aangevraagde bewerkingen uitvoert in dezelfde gebruikerscontext als WMI. Het instellen van ImpersonationLevel op 1 geeft aan dat de provider imitatie-aanroepen gebruikt om bewerkingen te controleren die namens de client worden uitgevoerd.
Stel de eigenschap PerUserInitialization van dezelfde __Win32Provider klasse in op TRUE-.
Notitie
Als u een provider registreert met de eigenschap __Win32ProviderInitializeAsAdminFirst ingesteld op TRUE, gebruikt de provider het threadbeveiligingstoken op beheerniveau alleen tijdens de initialisatiefase. Hoewel een aanroep naar CoImpersonateClient- niet mislukt, gebruikt de provider de beveiligingscontext van WMI en niet van de client.
In het volgende codevoorbeeld ziet u hoe u een provider registreert voor imitatie.
instance of __Win32Provider
{
CLSID = "{FD4F53E0-65DC-11d1-AB64-00C04FD9159E}";
ImpersonationLevel = 1;
Name = "MS_NT_EVENTLOG_PROVIDER";
PerUserInitialization = TRUE;
};
Imitatieniveaus instellen binnen een provider
Als u een provider registreert bij de eigenschap __Win32Provider klasse ImpersonationLevel ingesteld op 1, roept WMI uw provider aan om verschillende clients te imiteren. Als u deze aanroepen wilt afhandelen, gebruikt u de functies CoImpersonateClient en CoRevertToSelf COM-functies in uw implementatie van de IWbemServices interface.
Met de functie CoImpersonateClient kan een server de client imiteren die de aanroep heeft uitgevoerd. Door een aanroep naar CoImpersonateClient in uw implementatie van IWbemServices, stelt u uw provider in staat om het threadtoken van de provider in te stellen op overeenstemming met het threadtoken van de client, en dus de client te imiteren. Als u CoImpersonateClientniet aanroept, voert uw provider code uit op een beheerdersniveau van beveiliging, waardoor er een mogelijk beveiligingsprobleem ontstaat. Als uw provider tijdelijk als beheerder moet fungeren of de toegangscontrole handmatig moet uitvoeren, roept u CoRevertToSelf-aan.
In tegenstelling tot CoImpersonateClientis CoRevertToSelf- een COM-functie die thread-imitatieniveaus verwerkt. In dit geval wijzigt CoRevertToSelf het imitatieniveau weer in de oorspronkelijke imitatie-instelling. Over het algemeen is de provider in eerste instantie een beheerder en schakelt deze in tussen CoImpersonateClient en CoRevertToSelf, afhankelijk van of er een oproep wordt uitgevoerd die de beller of de eigen oproepen vertegenwoordigt. Het is de verantwoordelijkheid van de provider om deze aanroepen correct te plaatsen, zodat de eindgebruiker geen beveiligingsgat kan blootstellen. De provider mag bijvoorbeeld alleen systeemeigen Windows-functies aanroepen binnen de geïmiteerde codereeks.
Notitie
Het doel van CoImpersonateClient en CoRevertToSelf is het instellen van beveiliging voor een provider. Als u vaststelt dat uw imitatie is mislukt, moet u een juiste voltooiingscode naar WMI retourneren via IWbemObjectSink::SetStatus. Voor meer informatie, zie Verwerken van toegang geweigerde berichten in een provider.
Beveiligingsniveaus in een provider onderhouden
Providers kunnen CoImpersonateClient niet één keer aanroepen in een implementatie van IWbemServices en aannemen dat de geïmpersonificeerde referenties gedurende de gehele looptijd van de provider blijven bestaan. Roep in plaats daarvan CoImpersonateClient meerdere keren aan tijdens een implementatie om te voorkomen dat WMI de referenties wijzigt.
De belangrijkste zorg bij het instellen van impersonatie voor een provider is re-entrantheid. In deze context betekent reentrancy dat een provider een aanroep naar WMI doet voor informatie en wacht totdat WMI terugbelt naar de provider. In wezen verlaat de thread van de uitvoering de providercode, alleen om de code op een later tijdstip opnieuw in te voeren. Opnieuw proberen maakt deel uit van het ontwerp van COM en is over het algemeen geen probleem. Wanneer de uitvoeringsthread echter WMI binnenkomt, neemt de thread de impersonatieniveaus van WMI over. Wanneer de thread terugkeert naar de provider, moet u de imitatieniveaus opnieuw instellen met een andere aanroep naar CoImpersonateClient.
Als u uzelf wilt beschermen tegen beveiligingsgaten in uw provider, moet u alleen nieuwe aanroepen naar WMI uitvoeren terwijl u de client nabootst. Dat wil zeggen, moeten oproepen naar WMI gedaan worden nadat u CoImpersonateClient uitvoert en voordat u CoRevertToSelfuitvoert. Omdat CoRevertToSelf ervoor zorgt dat de imitatie wordt ingesteld op het gebruikersniveau waarop WMI draait, over het algemeen LocalSystem, kunnen reentrant-aanroepen naar WMI na het aanroepen van CoRevertToSelf de gebruiker, en alle geroepen providers, veel meer mogelijkheden geven dan ze zouden moeten hebben.
Notitie
Als u een systeemfunctie of een andere interfacemethode aanroept, wordt de aanroepcontext niet gegarandeerd onderhouden.
Berichten met geweigerde toegang verwerken in een provider
De meeste foutberichten over geweigerde toegang worden weergegeven wanneer een client een klasse of informatie aanvraagt waartoe ze geen toegang hebben. Als de provider een foutbericht 'Toegang geweigerd' retourneert aan WMI en WMI dit doorgeeft aan de cliënt, kan de cliënt afleiden dat de informatie bestaat. In sommige situaties kan dit een schending van de beveiliging zijn. Daarom mag uw provider het bericht niet doorgeven aan de client. In plaats daarvan mag de set klassen die de provider zou hebben opgegeven, niet zichtbaar zijn. Op dezelfde manier moet een dynamische instantieprovider de onderliggende gegevensbron aanroepen om te bepalen hoe berichten met geweigerde toegang moeten worden verwerkt. Het is de verantwoordelijkheid van de provider om die filosofie te repliceren naar de WMI-omgeving. Zie Gedeeltelijke exemplaren rapporteren en Gedeeltelijke inventarisaties rapporterenvoor meer informatie.
Wanneer u bepaalt hoe uw provider berichten met geweigerde toegang moet verwerken, moet u uw code schrijven en fouten opsporen. Tijdens foutopsporing is het vaak handig om onderscheid te maken tussen een denial vanwege een lage imitatie en een weigering vanwege een fout in uw code. U kunt een eenvoudige test in uw code gebruiken om het verschil te bepalen. Zie Foutopsporing van uw code voor geweigerde toegangvoor meer informatie.
Gedeeltelijke gevallen rapporteren
Een veelvoorkomende oorzaak van een 'Toegang Geweigerd'-melding is wanneer WMI niet alle informatie kan verstrekken om een instantie in te vullen. Een client kan bijvoorbeeld de autoriteit hebben om een hardeschijfschijfobject weer te geven, maar heeft mogelijk geen bevoegdheid om te zien hoeveel ruimte er beschikbaar is op de harde schijf zelf. Uw provider moet bepalen hoe de provider een situatie moet afhandelen wanneer de provider een exemplaar niet volledig met eigenschappen kan vullen vanwege een toegangsovertreding.
WMI vereist niet dat een reactie in een keer wordt gegeven aan clients die gedeeltelijke toegang tot een exemplaar hebben. In plaats daarvan staat WMI versie 1.x de provider een van de volgende opties toe:
Laat de hele bewerking mislukken met WBEM_E_ACCESS_DENIED en geef geen exemplaren terug.
Retourneert een foutobject samen met WBEM_E_ACCESS_DENIEDom de reden voor de weigering te beschrijven.
Retourneer alle beschikbare eigenschappen en vul niet-beschikbare eigenschappen in met NULL-.
Notitie
Zorg ervoor dat het retourneren van WBEM_E_ACCESS_DENIED geen beveiligingsgat in uw onderneming creëert.
Gedeeltelijke inventarisaties rapporteren
Een andere veelvoorkomende gebeurtenis van een toegangsschending is wanneer WMI niet alle opsommingen kan retourneren. Een client heeft bijvoorbeeld toegang om alle objecten van de lokale netwerkcomputer weer te geven, maar heeft mogelijk geen toegang om computerobjecten buiten zijn domein weer te geven. Uw provider moet bepalen hoe u een situatie moet afhandelen wanneer een opsomming niet kan worden voltooid vanwege een schending van de toegang.
Net als bij een instantieprovider vereist WMI geen enkele reactie op een gedeeltelijke opsomming. In plaats daarvan staat WMI versie 1.x een provider een van de volgende opties toe:
Retourneer WBEM_S_NO_ERROR voor alle exemplaren waartoe de provider toegang heeft.
Als u deze optie gebruikt, weet de gebruiker niet dat sommige exemplaren niet beschikbaar waren. Een aantal providers, zoals die gebruikmaken van Structured Query Language (SQL) met beveiliging op rijniveau, retourneren geslaagde gedeeltelijke resultaten met behulp van het beveiligingsniveau van de aanroeper om de resultatenset te definiëren.
De gehele operatie mislukt met WBEM_E_ACCESS_DENIED en retourneert geen instanties.
De provider kan eventueel een foutobject bevatten waarin de situatie aan de client wordt beschreven. Let erop dat sommige providers mogelijk seriële toegang hebben tot gegevensbronnen en pas weigeringen tegenkomen wanneer de enumeratie halverwege is.
Retourneer alle exemplaren die toegankelijk zijn en retourneer ook de statuscode zonder fout WBEM_S_ACCESS_DENIED.
De provider moet tijdens de inventarisatie noteren dat er een weigering is opgetreden en kan exemplaren blijven leveren, waarbij het afsluiten gebeurt met de statuscode voor geen fout. De provider kan er ook voor kiezen om de opsomming bij de eerste weigering te beëindigen. De reden voor deze optie is dat verschillende providers verschillende ophaalparadigma's hebben. Een provider heeft mogelijk al exemplaren geleverd voordat een toegangsschending wordt gedetecteerd. Sommige providers kunnen ervoor kiezen om andere diensten te blijven leveren, terwijl anderen mogelijk hun diensten willen beëindigen.
Vanwege de structuur van COM kunt u geen informatie achterhalen tijdens een fout, met uitzondering van een foutobject. Daarom kunt u zowel informatie als een foutcode niet retourneren. Als u ervoor kiest om informatie te retourneren, moet u in plaats daarvan een nonerror-statuscode gebruiken.
Fouten opsporen in uw code voor geweigerde toegang
Sommige toepassingen kunnen imitatieniveaus gebruiken die lager zijn dan RPC_C_IMP_LEVEL_IMPERSONATE. In dit geval mislukken de meeste imitatie-aanroepen van de provider voor de clienttoepassing. Als u een provider wilt ontwerpen en implementeren, moet u rekening houden met dit idee.
Standaard is het enige andere imitatieniveau dat toegang heeft tot een provider RPC_C_IMP_LEVEL_IDENTIFY. In gevallen waarin een clienttoepassing gebruikmaakt van RPC_C_IMP_LEVEL_IDENTIFY, retourneert CoImpersonateClient geen foutcode. In plaats daarvan imiteert de provider alleen de client voor identificatiedoeleinden. De meeste Windows-methoden die door de provider worden aangeroepen, retourneren daarom een bericht dat de toegang is geweigerd. Dit is in de praktijk ongevaarlijk, omdat gebruikers niets ongepasts mogen doen. Het kan echter nuttig zijn tijdens het ontwikkelen van providers om te weten of de client echt is geïmiteerd of niet.
De code vereist de volgende verwijzingen en #include instructies om correct te compileren.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
In het volgende codevoorbeeld ziet u hoe u kunt bepalen of een provider een clienttoepassing heeft geïmiteerd.
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);
Verwante onderwerpen