对于应用程序,我要检查特定用户是否已作为服务登录?如何以编程方式执行此操作?我在互联网上查了一下,找不到一些好的资源
谢谢
Upul
答案 0 :(得分:13)
我检查了所有以前的答案以及相关帖子中的其他许多内容,花了3天时间深入研究Win32 API,但没有得到这个问题的可靠答案(一些抛出的exeptions,有些甚至在尝试修复时都没有编译他们,有些只与当地账户合作)。最后,我找到了可以接受的答案。作为基础,我在technet forum上使用了Wieger1983的答案。我介绍了一些变化:
现在它适用于本地和Active Directory帐户,如果用户没有权限,则可以正常工作。我希望它能为像我这样的人节省时间=)。
警告:如果您将在x64架构上使用此代码,请注意以下EricRRichards的评论。我现在无法验证是否应该在每种情况下应用它。
//
// This code has been adapted from http://www.codeproject.com/KB/cs/lsadotnet.aspx
// The rights enumeration code came from http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.interop/2004-11/0394.html
//
// Windows Security via .NET is covered on by Pluralsight:http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HomePage.html
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace LSA
{
//
// Provides methods the local security authority which controls user rights. Managed via secpol.msc normally.
//
public class LocalSecurityAuthorityController
{
private const int Access = (int)(
LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
LSA_AccessPolicy.POLICY_CREATE_ACCOUNT |
LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE |
LSA_AccessPolicy.POLICY_CREATE_SECRET |
LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION |
LSA_AccessPolicy.POLICY_LOOKUP_NAMES |
LSA_AccessPolicy.POLICY_NOTIFICATION |
LSA_AccessPolicy.POLICY_SERVER_ADMIN |
LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS |
LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
LSA_AccessPolicy.POLICY_TRUST_ADMIN |
LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION |
LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
);
[DllImport("advapi32.dll", PreserveSig = true)]
private static extern UInt32 LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, Int32 DesiredAccess, out IntPtr PolicyHandle);
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
private static extern uint LsaAddAccountRights(IntPtr PolicyHandle, IntPtr AccountSid, LSA_UNICODE_STRING[] UserRights, int CountOfRights);
[DllImport("advapi32")]
public static extern void FreeSid(IntPtr pSid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
private static extern bool LookupAccountName(string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use);
[DllImport("advapi32.dll")]
private static extern bool IsValidSid(IntPtr pSid);
[DllImport("advapi32.dll")]
private static extern int LsaClose(IntPtr ObjectHandle);
[DllImport("kernel32.dll")]
private static extern int GetLastError();
[DllImport("advapi32.dll")]
private static extern int LsaNtStatusToWinError(uint status);
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
private static extern uint LsaEnumerateAccountRights(IntPtr PolicyHandle, IntPtr AccountSid, out IntPtr UserRightsPtr, out int CountOfRights);
[StructLayout(LayoutKind.Sequential)]
private struct LSA_UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
}
[StructLayout(LayoutKind.Sequential)]
private struct LSA_OBJECT_ATTRIBUTES
{
public int Length;
public IntPtr RootDirectory;
public LSA_UNICODE_STRING ObjectName;
public UInt32 Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[Flags]
private enum LSA_AccessPolicy : long
{
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
POLICY_TRUST_ADMIN = 0x00000008L,
POLICY_CREATE_ACCOUNT = 0x00000010L,
POLICY_CREATE_SECRET = 0x00000020L,
POLICY_CREATE_PRIVILEGE = 0x00000040L,
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
POLICY_SERVER_ADMIN = 0x00000400L,
POLICY_LOOKUP_NAMES = 0x00000800L,
POLICY_NOTIFICATION = 0x00001000L
}
// Returns the Local Security Authority rights granted to the account
public IList<string> GetRights(string accountName)
{
IList<string> rights = new List<string>();
string errorMessage = string.Empty;
long winErrorCode = 0;
IntPtr sid = IntPtr.Zero;
int sidSize = 0;
StringBuilder domainName = new StringBuilder();
int nameSize = 0;
int accountType = 0;
LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType);
domainName = new StringBuilder(nameSize);
sid = Marshal.AllocHGlobal(sidSize);
if (!LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType))
{
winErrorCode = GetLastError();
errorMessage = ("LookupAccountName failed: " + winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
else
{
LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();
IntPtr policyHandle = IntPtr.Zero;
IntPtr userRightsPtr = IntPtr.Zero;
int countOfRights = 0;
LSA_OBJECT_ATTRIBUTES objectAttributes = CreateLSAObject();
uint policyStatus = LsaOpenPolicy(ref systemName, ref objectAttributes, Access, out policyHandle);
winErrorCode = LsaNtStatusToWinError(policyStatus);
if (winErrorCode != 0)
{
errorMessage = string.Format("OpenPolicy failed: {0}.", winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
else
{
try
{
uint result = LsaEnumerateAccountRights(policyHandle, sid, out userRightsPtr, out countOfRights);
winErrorCode = LsaNtStatusToWinError(result);
if (winErrorCode != 0)
{
if (winErrorCode == 2)
{
return new List<string>();
}
errorMessage = string.Format("LsaEnumerateAccountRights failed: {0}", winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
Int32 ptr = userRightsPtr.ToInt32();
LSA_UNICODE_STRING userRight;
for (int i = 0; i < countOfRights; i++)
{
userRight = (LSA_UNICODE_STRING)Marshal.PtrToStructure(new IntPtr(ptr), typeof(LSA_UNICODE_STRING));
string userRightStr = Marshal.PtrToStringAuto(userRight.Buffer);
rights.Add(userRightStr);
ptr += Marshal.SizeOf(userRight);
}
}
finally
{
LsaClose(policyHandle);
}
}
FreeSid(sid);
}
return rights;
}
// Adds a privilege to an account
public void SetRight(string accountName, string privilegeName)
{
long winErrorCode = 0;
string errorMessage = string.Empty;
IntPtr sid = IntPtr.Zero;
int sidSize = 0;
StringBuilder domainName = new StringBuilder();
int nameSize = 0;
int accountType = 0;
LookupAccountName(String.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType);
domainName = new StringBuilder(nameSize);
sid = Marshal.AllocHGlobal(sidSize);
if (!LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType))
{
winErrorCode = GetLastError();
errorMessage = string.Format("LookupAccountName failed: {0}", winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
else
{
LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();
IntPtr policyHandle = IntPtr.Zero;
LSA_OBJECT_ATTRIBUTES objectAttributes = CreateLSAObject();
uint resultPolicy = LsaOpenPolicy(ref systemName, ref objectAttributes, Access, out policyHandle);
winErrorCode = LsaNtStatusToWinError(resultPolicy);
if (winErrorCode != 0)
{
errorMessage = string.Format("OpenPolicy failed: {0} ", winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
else
{
try
{
LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[1];
userRights[0] = new LSA_UNICODE_STRING();
userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName);
userRights[0].Length = (UInt16)(privilegeName.Length * UnicodeEncoding.CharSize);
userRights[0].MaximumLength = (UInt16)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);
uint res = LsaAddAccountRights(policyHandle, sid, userRights, 1);
winErrorCode = LsaNtStatusToWinError(res);
if (winErrorCode != 0)
{
errorMessage = string.Format("LsaAddAccountRights failed: {0}", winErrorCode);
throw new Win32Exception((int)winErrorCode, errorMessage);
}
}
finally
{
LsaClose(policyHandle);
}
}
FreeSid(sid);
}
}
private static LSA_OBJECT_ATTRIBUTES CreateLSAObject()
{
LSA_OBJECT_ATTRIBUTES newInstance = new LSA_OBJECT_ATTRIBUTES();
newInstance.Length = 0;
newInstance.RootDirectory = IntPtr.Zero;
newInstance.Attributes = 0;
newInstance.SecurityDescriptor = IntPtr.Zero;
newInstance.SecurityQualityOfService = IntPtr.Zero;
return newInstance;
}
}
// Local security rights managed by the Local Security Authority
public class LocalSecurityAuthorityRights
{
// Log on as a service right
public const string LogonAsService = "SeServiceLogonRight";
// Log on as a batch job right
public const string LogonAsBatchJob = "SeBatchLogonRight";
// Interactive log on right
public const string InteractiveLogon = "SeInteractiveLogonRight";
// Network log on right
public const string NetworkLogon = "SeNetworkLogonRight";
// Generate security audit logs right
public const string GenerateSecurityAudits = "SeAuditPrivilege";
}
/* added wrapper for PowerShell */
public class LSAWrapper
{
public static IList<string> GetRights(string accountName)
{
return new LocalSecurityAuthorityController().GetRights(accountName);
}
public static void SetRight(string accountName, string privilegeName)
{
new LocalSecurityAuthorityController().SetRight(accountName, privilegeName);
}
}
}
最后检查权利很容易:
var rights = LSAWrapper.GetRights("myMachineName\\TestUser");
if (rights.Contains(LocalSecurityAuthorityRights.LogonAsService))
{
Console.WriteLine("User has right to logon as a service");
}
else
{
Console.WriteLine("User doesn't have right to logon as a service");
}
答案 1 :(得分:3)
您是否拥有该帐户的令牌?如果是这样,您可以使用TokenInformationClass == TokenPrivileges
致电GetTokenInformation。这将返回与令牌关联的权限列表以及它们是否已被激活。
如果帐户未登录,因此您无法获取其令牌,则会变得更加困难。您无法查询帐户允许的权限,更不用说任何帐户的组带来的权限。您需要登录帐户才能检索令牌,然后按照之前的建议进行操作。
答案 2 :(得分:1)
答案 3 :(得分:1)
对Sasha解决方案的修改:
对于32/64位可移植性,您不需要使用其他代码或使用不安全的代码。而是使用:
LSA_UNICODE_STRING userRight;
for (int i = 0; i < countOfRights; i++)
{
var indexPointer = IntPtr.Add(userRightsPtr, i * Marshal.SizeOf(typeof(LSA_UNICODE_STRING)));
userRight = (LSA_UNICODE_STRING)Marshal.PtrToStructure(indexPointer, typeof(LSA_UNICODE_STRING));
string userRightStr = Marshal.PtrToStringAuto(userRight.Buffer);
rights.Add(userRightStr);
}
LsaFreeMemory(userRightsPtr);
此外,使用LsaFreeMemory可以在完成后释放userRightsPtr。参见doc for LsaEnumerateAccountRights。这说明您必须使用LsaFreeMemory释放LsaEnumerateAccountRights返回的用户权限指针。
[DllImport("advapi32.dll")]
private static extern int LsaFreeMemory(IntPtr ObjectHandle);
此外,对于内置计算机帐户,只需传递不带域的用户名,例如: IIS_IUSRS