gpt4 book ai didi

c# - 如何使用 C# 代码授予用户启动和停止特定服务的权限

转载 作者:太空狗 更新时间:2023-10-29 23:00:21 25 4
gpt4 key购买 nike

如何仅使用 C# 代码授予特定用户(可能是 NET SERVICE 用户)启动和停止特定服务的权限。

我需要生成的代码适用于从 Windows XP 到 Windows 8 的所有系统。

[编辑]我已经有一个可用的服务,以及一个设置文件夹权限、安装服务、启动服务等的安装例程。

服务检查 url 以查看是否有更新,如果有,则下载它,并启动更新程序来更新服务(并自行终止)。

更新程序更新服务exe(和其他需要的文件),需要重启服务。

我从研究中知道可以向服务用户(在本例中为 NETWORK SERVICE)授予启动和停止单个服务的权限,但我不知道在代码中执行此操作的 API。

最佳答案

我从别处得到了一些线索,并设法弄明白了:

[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());
}
}

关于c# - 如何使用 C# 代码授予用户启动和停止特定服务的权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15771998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com