2010-12-20

Cofnięcie uprawnień administracyjnych

Od czasu Visty istnieje zjawisko zwane UAC. Powoduje ono, przy odrobinie szczęścia, podniesienie uprawnień aplikacji do poziomu administratora po akceptacji użytkownika, w sposób całkowicie przezroczysty dla systemu. Przynajmniej tak być powinno, jednak przezroczystość ta jest fikcyjna. Weźmy dla przykładu aplikację uruchamianą z prawami admina, która potrzebuje poprzez COM (dokładniej: API oparte na COM) skomunikować się z aplikacją działającą w trybie użytkownika. Nie działa. Są też różne inne przypadki (File manager? Installer?) wymagające łatwego uruchomienia aplikacji w trybie użytkownika. Jak to zrobić?

Zadanie: mając aplikację działającą z prawami administratora uruchomić inny proces z prawami zwykłego użytkownika. Aplikacja ma działać poprawnie na Windows XP SP2 oraz wyżej.
Założenia: używamy C#.NET 2.0, znamy pełną ścieżkę docelowej aplikacji.

Ciekawostką jest fakt, że o ile MS doskonale udokumentował podnoszenie uprawnień dla aplikacji (manifest, pobieranie admin tokena), o tyle obniżenie w jakiś sposób tychże uprawnień staje się zadaniem zgoła niemożliwym. Najprostsze, oczywiście, rozwiązanie to uruchomienie odpowiedniego procesu.

Do tego użyta zostanie aplikacja runas, pozwalająca na uruchomienie aplikacji jako zwykły użytkownik. Na chwilę obecną (sprawdzone doświadczalnie, na około 20 maszynach z Windows Vista i Windows 7) dokładne parametry wiersza polecenia dla aplikacji są identyczne. Uwaga: w podany sposób nie uda się uruchomić aplikacji pod Windows XP! Tam składnia runas jest inna, co może być problematyczne.

Nasza komenda to: runas /trustlevel:0x20000 "ścieżka\względna\lub\bezwzględna\do\aplikacji.exe". W ten sposób aplikacja zostanie uruchomiona jako zwykły użytkownik, nawet jeśli komenda została wywołana z prawami administratora. Przykładowy kod stosujący tą metodę poniżej:

static void RunAsUser(string application)
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal p = new WindowsPrincipal(id);
System.OperatingSystem osInfo = System.Environment.OSVersion;
if (p.IsInRole(WindowsBuiltInRole.Administrator) && osInfo.Version.Major >= 6)
{
System.Diagnostics.Process.Start("runas", "/trustlevel:0x20000 \"" + application + "\"");
}
else
{
System.Diagnostics.Process.Start(application);
}
}

Brak komentarzy:

Prześlij komentarz