2010-01-19 3 views
5

Ich möchte programmgesteuert feststellen, ob der aktuelle Benutzer (oder der aktuelle Prozess) Zugriff auf symbolische Verknüpfungen hat. Unter Windows (Vista und höher) kann keine symbolische Verbindung ohne SeCreateSymbolicLinkPrivilege erstellt werden. Dies ist standardmäßig nur Administratoren zugewiesen. Wenn versucht wird, eine symbolische Verbindung ohne diese Berechtigung zu erstellen, tritt ein Windows-Fehler 1314 auf (eine erforderliche Berechtigung wird vom Client nicht gehalten).Ermitteln, ob der Windows-Prozess die Berechtigung zum Erstellen der symbolischen Verbindung hat

Diese Einschränkung Um zu demonstrieren, habe ich eine saubere Installation von Windows protokolliert als Anfangs Administrator-Konto in (durch UAC beschränkt), und war nicht in der Lage einen Symlink im Home-Verzeichnis zu erstellen.

Command Prompt demonstrates mklink fails due to insufficient privilege

Nach der Eingabeaufforderung als Administrator läuft oder UAC deaktivieren, führt dieser Befehl ohne Fehler.

Laut this article "hat jeder im Namen des Benutzers ausgeführte Prozess eine Kopie des Tokens [access]".

Also habe ich a Python script to query for the permissions erstellt. Für die Bequemlichkeit und die Nachwelt, schließe ich einen Auszug unten ein.

Die Idee hinter dem Skript ist, alle Privilegien aufzuzählen und bestimmen, ob der Prozess die erforderliche Berechtigung hat. Leider finde ich, dass der aktuelle Prozess nicht das gewünschte Privileg hat, selbst wenn er symbolische Links erzeugen kann.

Ich vermute, das Problem ist, dass, obwohl die aktuellen Benutzer Privilegien ausdrücklich nicht das Privileg gehören, seine Gruppenzugehörigkeit dieses Privileg nicht leisten.

Kurz gesagt, wie kann ich feststellen, ob ein bestimmte Prozess Privileg symbolische Links zu erstellen haben wird (ohne zu erstellen zu versuchen)? Ein Beispiel in C oder C++ oder Python wird bevorzugt, obwohl alles, das die Windows-API verwendet, geeignet ist.

def get_process_token(): 
    token = wintypes.HANDLE() 
    TOKEN_ALL_ACCESS = 0xf01ff 
    res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token) 
    if not res > 0: raise RuntimeError("Couldn't get process token") 
    return token 

def get_privilege_information(): 
    # first call with zero length to determine what size buffer we need 

    return_length = wintypes.DWORD() 
    params = [ 
     get_process_token(), 
     TOKEN_INFORMATION_CLASS.TokenPrivileges, 
     None, 
     0, 
     return_length, 
     ] 

    res = GetTokenInformation(*params) 

    # assume we now have the necessary length in return_length 

    buffer = ctypes.create_string_buffer(return_length.value) 
    params[2] = buffer 
    params[3] = return_length.value 

    res = GetTokenInformation(*params) 
    assert res > 0, "Error in second GetTokenInformation (%d)" % res 

    privileges = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents 
    return privileges 

privileges = get_privilege_information() 
print("found {0} privileges".format(privileges.count)) 
map(print, privileges) 
+0

Windows hat symbolische Links? –

+2

Welche Art von symbolischen Link möchten Sie erstellen? Es gibt eine Menge verschiedener Dinge, die als symbolische Links in Windows betrachtet werden können - Dateisystem-Junction-Punkte, Dateisystem-Hardlinks, symbolische Objektmanager-Links usw. Ich glaube, dass Sie nur die SeCreateSymbolicLink-Berechtigung benötigen, um symbolische Links für Objektmanager zu erstellen. –

+0

Ich versuche, auf Dateisystem-Junction-Point basierende symbolische Links zu erstellen, z. B. solche, die von CreateSymbolicLink erstellt wurden. –

Antwort

4

Ich fand eine Lösung. Der folgende Python-Code ist ein voll funktionsfähiges Skript unter Python 2.6 oder 3.1, das demonstriert, wie man die Berechtigung zum Erstellen von Symlinks festlegen kann. Die Ausführung unter dem Administratorkonto erfolgt mit Erfolg, und die Ausführung unter dem Gastkonto reagiert mit einem Fehler.

Hinweis, die ersten 3/4 des Skripts ist meist API-Definitionen. Die neue Arbeit beginnt mit get_process_token().

from __future__ import print_function 
import ctypes 
from ctypes import wintypes 

GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess 
GetCurrentProcess.restype = wintypes.HANDLE 
OpenProcessToken = ctypes.windll.advapi32.OpenProcessToken 
OpenProcessToken.argtypes = (wintypes.HANDLE, wintypes.DWORD, ctypes.POINTER(wintypes.HANDLE)) 
OpenProcessToken.restype = wintypes.BOOL 

class LUID(ctypes.Structure): 
    _fields_ = [ 
     ('low_part', wintypes.DWORD), 
     ('high_part', wintypes.LONG), 
     ] 

    def __eq__(self, other): 
     return (
      self.high_part == other.high_part and 
      self.low_part == other.low_part 
      ) 

    def __ne__(self, other): 
     return not (self==other) 

LookupPrivilegeValue = ctypes.windll.advapi32.LookupPrivilegeValueW 
LookupPrivilegeValue.argtypes = (
    wintypes.LPWSTR, # system name 
    wintypes.LPWSTR, # name 
    ctypes.POINTER(LUID), 
    ) 
LookupPrivilegeValue.restype = wintypes.BOOL 

class TOKEN_INFORMATION_CLASS: 
    TokenUser = 1 
    TokenGroups = 2 
    TokenPrivileges = 3 
    # ... see http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx 

SE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001) 
SE_PRIVILEGE_ENABLED   = (0x00000002) 
SE_PRIVILEGE_REMOVED   = (0x00000004) 
SE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000) 

class LUID_AND_ATTRIBUTES(ctypes.Structure): 
    _fields_ = [ 
     ('LUID', LUID), 
     ('attributes', wintypes.DWORD), 
     ] 

    def is_enabled(self): 
     return bool(self.attributes & SE_PRIVILEGE_ENABLED) 

    def enable(self): 
     self.attributes |= SE_PRIVILEGE_ENABLED 

    def get_name(self): 
     size = wintypes.DWORD(10240) 
     buf = ctypes.create_unicode_buffer(size.value) 
     res = LookupPrivilegeName(None, self.LUID, buf, size) 
     if res == 0: raise RuntimeError 
     return buf[:size.value] 

    def __str__(self): 
     res = self.get_name() 
     if self.is_enabled(): res += ' (enabled)' 
     return res 

LookupPrivilegeName = ctypes.windll.advapi32.LookupPrivilegeNameW 
LookupPrivilegeName.argtypes = (
    wintypes.LPWSTR, # lpSystemName 
    ctypes.POINTER(LUID), # lpLuid 
    wintypes.LPWSTR, # lpName 
    ctypes.POINTER(wintypes.DWORD), #cchName 
    ) 
LookupPrivilegeName.restype = wintypes.BOOL 

class TOKEN_PRIVILEGES(ctypes.Structure): 
    _fields_ = [ 
     ('count', wintypes.DWORD), 
     ('privileges', LUID_AND_ATTRIBUTES*0), 
     ] 

    def get_array(self): 
     array_type = LUID_AND_ATTRIBUTES*self.count 
     privileges = ctypes.cast(self.privileges, ctypes.POINTER(array_type)).contents 
     return privileges 

    def __iter__(self): 
     return iter(self.get_array()) 

PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES) 

GetTokenInformation = ctypes.windll.advapi32.GetTokenInformation 
GetTokenInformation.argtypes = [ 
    wintypes.HANDLE, # TokenHandle 
    ctypes.c_uint, # TOKEN_INFORMATION_CLASS value 
    ctypes.c_void_p, # TokenInformation 
    wintypes.DWORD, # TokenInformationLength 
    ctypes.POINTER(wintypes.DWORD), # ReturnLength 
    ] 
GetTokenInformation.restype = wintypes.BOOL 

# http://msdn.microsoft.com/en-us/library/aa375202%28VS.85%29.aspx 
AdjustTokenPrivileges = ctypes.windll.advapi32.AdjustTokenPrivileges 
AdjustTokenPrivileges.restype = wintypes.BOOL 
AdjustTokenPrivileges.argtypes = [ 
    wintypes.HANDLE,    # TokenHandle 
    wintypes.BOOL,     # DisableAllPrivileges 
    PTOKEN_PRIVILEGES,    # NewState (optional) 
    wintypes.DWORD,     # BufferLength of PreviousState 
    PTOKEN_PRIVILEGES,    # PreviousState (out, optional) 
    ctypes.POINTER(wintypes.DWORD), # ReturnLength 
    ] 

def get_process_token(): 
    """ 
    Get the current process token 
    """ 
    token = wintypes.HANDLE() 
    TOKEN_ALL_ACCESS = 0xf01ff 
    res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token) 
    if not res > 0: raise RuntimeError("Couldn't get process token") 
    return token 

def get_symlink_luid(): 
    """ 
    Get the LUID for the SeCreateSymbolicLinkPrivilege 
    """ 
    symlink_luid = LUID() 
    res = LookupPrivilegeValue(None, "SeCreateSymbolicLinkPrivilege", symlink_luid) 
    if not res > 0: raise RuntimeError("Couldn't lookup privilege value") 
    return symlink_luid 

def get_privilege_information(): 
    """ 
    Get all privileges associated with the current process. 
    """ 
    # first call with zero length to determine what size buffer we need 

    return_length = wintypes.DWORD() 
    params = [ 
     get_process_token(), 
     TOKEN_INFORMATION_CLASS.TokenPrivileges, 
     None, 
     0, 
     return_length, 
     ] 

    res = GetTokenInformation(*params) 

    # assume we now have the necessary length in return_length 

    buffer = ctypes.create_string_buffer(return_length.value) 
    params[2] = buffer 
    params[3] = return_length.value 

    res = GetTokenInformation(*params) 
    assert res > 0, "Error in second GetTokenInformation (%d)" % res 

    privileges = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents 
    return privileges 

def report_privilege_information(): 
    """ 
    Report all privilege information assigned to the current process. 
    """ 
    privileges = get_privilege_information() 
    print("found {0} privileges".format(privileges.count)) 
    tuple(map(print, privileges)) 

def enable_symlink_privilege(): 
    """ 
    Try to assign the symlink privilege to the current process token. 
    Return True if the assignment is successful. 
    """ 
    # create a space in memory for a TOKEN_PRIVILEGES structure 
    # with one element 
    size = ctypes.sizeof(TOKEN_PRIVILEGES) 
    size += ctypes.sizeof(LUID_AND_ATTRIBUTES) 
    buffer = ctypes.create_string_buffer(size) 
    tp = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents 
    tp.count = 1 
    tp.get_array()[0].enable() 
    tp.get_array()[0].LUID = get_symlink_luid() 
    token = get_process_token() 
    res = AdjustTokenPrivileges(token, False, tp, 0, None, None) 
    if res == 0: 
     raise RuntimeError("Error in AdjustTokenPrivileges") 

    ERROR_NOT_ALL_ASSIGNED = 1300 
    return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED 

def main(): 
    assigned = enable_symlink_privilege() 
    msg = ['failure', 'success'][assigned] 

    print("Symlink privilege assignment completed with {0}".format(msg)) 

if __name__ == '__main__': main() 
Verwandte Themen