2013-03-15 17 views
5

Moje kod C# używa personifikacji poprzez wywołanie funkcji Win32 poprzez P/InvokeDlaczego wyjątek od nieotrzymanego kodu nie został złapany?

internal class Win32Native 
{ 
    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern int ImpersonateLoggedOnUser(IntPtr token); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern int RevertToSelf(); 
} 

try { 
    var token = obtainTokenFromLogonUser(); 
    Win32Native.ImpersonateLoggedOnUser(token); 
    throw new Exception(); // this is for simulation 
    Win32Native.RevertToSelf() 
} catch(Exception e) { 
    LogException(e); 
    throw; 
} 

też mam AppDomain.CurrentDomain.UnhandledException obsługi zainstalowane że również rejestruje wszystkie nieobsługiwany wyjątek.

Jestem pewien, że kod, który rejestruje wyjątki, działa dobrze zarówno z podszywaniem jak i bez niego.

Problem polega na tym, że w powyższym kodzie wygląda na to, że catch nie jest wpisany, a UnhandledException również nie jest wywoływany. Jedynym śladem wyjątku jest wpis w przeglądarce zdarzeń.

Jeśli dodać finally takiego:

try { 
    var token = obtainTokenFromLogonUser(); 
    Win32Native.ImpersonateLoggedOnUser(token); 
    try { 
     throw new Exception(); // this is for simulation 
    } finally { 
     Win32Native.RevertToSelf() 
    } 
} catch(Exception e) { 
    LogException(e); 
    throw; 
} 

następnie wyjątek jest zalogowany w porządku zarówno z catch iz UnhandledException obsługi.

Co się dzieje? Czy podszywanie się pod wątek zapobiega zwykłemu traktowaniu wyjątków?

+0

jeśli umieścisz punkt przerwania w 'LogException': dostaniesz się tam? –

+0

@MarcGravell: Nie wiem, nie ma debuggera tam, gdzie jest on odtwarzany. Zdaję sobie sprawę, że może wystąpić problem z samym 'LogException()', ale do tej pory kod, na którym się opiera, działał dobrze zarówno podszyty, jak i podszywany. – sharptooth

+0

Odgadnij tutaj: ponieważ .NET śledzi kontekst wykonania, obsługa wyjątków może świadczyć o tym, że kontekst się zmienił i uniemożliwia wykonanie procedury obsługi wyjątku, o ile nie zostanie najpierw wykonane odwrócenie. Niewykonanie tego spowodowałoby podniesienie uprawnień, gdyby kod był uruchamiany z podszukanym użytkownikiem ... –

Odpowiedz

3

Nie widząc kodu wyjątku LogException, nie mogę być pewien, ale możliwe, że cokolwiek robisz, robi to w kontekście użytkownika podszywającego się/zalogowanego i że ten użytkownik nie ma użytkownika prawa do robienia tego, co robisz np zapisywanie do pliku itp., a następnie kod ulega awarii w tym momencie. Fakt, że twój kod działa tylko po "Reverted to Self" wydaje się to potwierdzać.

Więc próbuję to powiedzieć, jest szansa, że ​​twój wyjątek jest faktycznie przechwytywany przez catch, ale że LogException zawodzi, ponieważ próbuje wykonać pracę w kontekście niewłaściwego użytkownika.

Aby przetestować to, w swoim Logexception, spróbuj wymusić aktualny kontekst na "Self" przed próbą logowania i zobacz, czy pierwszy fragment zaczyna działać.

1

Okazało się, że problem dotyczył kodu logowania. W pewnym momencie dodaliśmy kod, który pobiera bieżący czas rozpoczęcia procesu (Process.StartTime) i ten kod zwalnia Access denied po wywołaniu z podanego wątku.

Access is denied 
System.ComponentModel.Win32Exception 
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited) 
at System.Diagnostics.Process.GetProcessTimes() 
at System.Diagnostics.Process.get_StartTime() 
//our logging code here 

kod Logging zwany także System.Diagnostics.Trace.WriteLine()przed wywoływanie kodu z Process.StartTime i pisze przez „słuchaczy śladowych” udało, tylko pisze się przez ten ostatni kod nie powiodło się.

Nie ma więc żadnej różnicy w wyłapywaniu wyjątków z podszywaniem się lub bez niego. Możliwe jest nawet zainstalowanie filtru wyjątków, tak aby był wywoływany w kontekście bezpieczeństwa podanego kodu, co może skutkować podniesieniem uprawnień. Details for the latter here.

Powiązane problemy