2013-04-02 8 views
5

Jak mogę udzielić konkretnemu użytkownikowi (prawdopodobnie użytkownikowi usługi NET SERVICE) uprawnienia do uruchamiania i zatrzymywania określonej usługi przy użyciu tylko kodu C#.Jak przyznać użytkownikowi uprawnienia do uruchamiania i zatrzymywania określonej usługi przy użyciu kodu C#

muszę wygenerowany kod do pracy na wszystko z Windows XP do Windows 8.

[Edytuj] mam już serwis, który działa i rutynowych instalacyjny, który określa uprawnienia folderu, instaluje usługę, uruchamia go itp.

Usługa sprawdza adres URL, aby sprawdzić, czy jest dostępna aktualizacja, a jeśli tak, pobiera ją i uruchamia program aktualizujący w celu aktualizacji usługi (i sam się kończy).

Program aktualizujący aktualizuje usługę exe (i inne potrzebne pliki) i wymaga zrestartowania usługi.

Wiem z badań, że możliwe jest przyznanie użytkownikowi usługi (NETWORK SERVICE w tym przypadku) uprawnień do uruchamiania i zatrzymywania poszczególnych usług, ale nie znam api, aby zrobić to w kodzie.

+3

dobrze nie można utworzyć konto usługi dla tego konkretnego użytkownika? co obecnie masz ... pamiętaj: "SO to nie jest Code Factory", musisz spróbować samodzielnie, a następnie zgłoś, jakie masz problemy, a inni będą bardziej niż szczęśliwi, aby pomóc Ci nie oczekiwać od innych rób swoje 'praca dla ciebie' – MethodMan

+0

Potrzebuję tylko kilku wskazówek. Co to jest konto usługi? –

+0

Po prostu sprawdziłem. Nie jestem pewien, czy jest to istotne, ponieważ wtedy pojawia się pytanie: "w jaki sposób przyznać moje konto usługowe uprawnienia do uruchamiania i zatrzymywania usługi". Czy może czegoś brakuje? –

Odpowiedz

6

Mam kilka wskazówek od innych miejscach, i udało mi się ustalić to:

[StructLayoutAttribute(LayoutKind.Sequential)] 
struct SECURITY_DESCRIPTOR { 
    public byte revision; 
    public byte size; 
    public short control; 
    public IntPtr owner; 
    public IntPtr group; 
    public IntPtr sacl; 
    public IntPtr dacl; 
} 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool QueryServiceObjectSecurity(IntPtr serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfo, 
    ref SECURITY_DESCRIPTOR lpSecDesrBuf, 
    uint bufSize, 
    out uint bufSizeNeeded); 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool QueryServiceObjectSecurity(SafeHandle serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfo, 
    byte[] lpSecDesrBuf, 
    uint bufSize, 
    out uint bufSizeNeeded); 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool SetServiceObjectSecurity(SafeHandle serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfos, 
    byte[] lpSecDesrBuf); 

public void SetServicePermissions(string service, string username) { 
    System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(service, "."); 
    ServiceControllerStatus status = sc.Status; 
    byte[] psd = new byte[0]; 
    uint bufSizeNeeded; 
    bool ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, 0, out bufSizeNeeded); 
    if (!ok) { 
     int err = Marshal.GetLastWin32Error(); 
     if (err == 122 || err == 0) { // ERROR_INSUFFICIENT_BUFFER 
      // expected; now we know bufsize 
      psd = new byte[bufSizeNeeded]; 
      ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, bufSizeNeeded, out bufSizeNeeded); 
     } else { 
      throw new ApplicationException("error calling QueryServiceObjectSecurity() to get DACL for " + _name + ": error code=" + err); 
     } 
    } 
    if (!ok) 
     throw new ApplicationException("error calling QueryServiceObjectSecurity(2) to get DACL for " + _name + ": error code=" + Marshal.GetLastWin32Error()); 

    // get security descriptor via raw into DACL form so ACE 
    // ordering checks are done for us. 
    RawSecurityDescriptor rsd = new RawSecurityDescriptor(psd, 0); 
    RawAcl racl = rsd.DiscretionaryAcl; 
    DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, racl); 

    // Add start/stop/read access 
    NTAccount acct = new NTAccount(username); 
    SecurityIdentifier sid = (SecurityIdentifier) acct.Translate(typeof(SecurityIdentifier)); 
    // 0xf7 is SERVICE_QUERY_CONFIG|SERVICE_CHANGE_CONFIG|SERVICE_QUERY_STATUS| 
    // SERVICE_START|SERVICE_STOP|SERVICE_PAUSE_CONTINUE|SERVICE_INTERROGATE 
    dacl.AddAccess(AccessControlType.Allow, sid, 0xf7, InheritanceFlags.None, PropagationFlags.None); 

    // convert discretionary ACL back to raw form; looks like via byte[] is only way 
    byte[] rawdacl = new byte[dacl.BinaryLength]; 
    dacl.GetBinaryForm(rawdacl, 0); 
    rsd.DiscretionaryAcl = new RawAcl(rawdacl, 0); 

    // set raw security descriptor on service again 
    byte[] rawsd = new byte[rsd.BinaryLength]; 
    rsd.GetBinaryForm(rawsd, 0); 
    ok = SetServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, rawsd); 
    if (!ok) { 
     throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error()); 
    } 
} 
+0

"Modyfikowanie listy DACL dla usługi" https://msdn.microsoft.com/en-us/library/windows/desktop/ms684215(v=vs.85).aspx – Liviu