188 lines
7.1 KiB
C#
188 lines
7.1 KiB
C#
|
|
using Insight.Agent.Interfaces;
|
|||
|
|
using Insight.Agent.Messages;
|
|||
|
|
using System.Management;
|
|||
|
|
using System.Runtime.Versioning;
|
|||
|
|
|
|||
|
|
namespace Insight.Agent.Network.Handlers
|
|||
|
|
{
|
|||
|
|
[SupportedOSPlatform("windows")]
|
|||
|
|
public class UserHandler : IAgentMessageHandler<AgentSession>
|
|||
|
|
{
|
|||
|
|
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
|
|||
|
|
{
|
|||
|
|
if (message is GetInventory)
|
|||
|
|
{
|
|||
|
|
var result = new UserList();
|
|||
|
|
result.AddRange(GetUsers());
|
|||
|
|
|
|||
|
|
await sender.SendAsync(result, cancellationToken);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static List<User> GetUsers()
|
|||
|
|
{
|
|||
|
|
var users = QueryUsers();
|
|||
|
|
var groups = GetGroups();
|
|||
|
|
var usergrouping = QueryUserGroupMaps();
|
|||
|
|
|
|||
|
|
foreach (var u in users)
|
|||
|
|
{
|
|||
|
|
u.Groups = new List<Group>();
|
|||
|
|
|
|||
|
|
foreach (var ug in usergrouping.Where(ug => ug.UserDomain == u.Domain && ug.UserName == u.Name))
|
|||
|
|
{
|
|||
|
|
var grps = groups.Where(g => g.Domain == ug.GroupDomain && g.Name == ug.GroupName);
|
|||
|
|
|
|||
|
|
if (grps is not null)
|
|||
|
|
{
|
|||
|
|
u.Groups.AddRange(grps);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return users;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static List<Group> GetGroups()
|
|||
|
|
{
|
|||
|
|
using var searcher = new ManagementObjectSearcher
|
|||
|
|
{
|
|||
|
|
Scope = new ManagementScope(@"root\cimv2"),
|
|||
|
|
Query = new ObjectQuery("select sid, domain, name, description, localaccount from win32_group")
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out var collection) is false)
|
|||
|
|
{
|
|||
|
|
searcher.Query = new ObjectQuery("select * from win32_group");
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var groups = new List<Group>();
|
|||
|
|
|
|||
|
|
using (collection)
|
|||
|
|
{
|
|||
|
|
foreach (ManagementObject @object in collection)
|
|||
|
|
{
|
|||
|
|
var group = new Group();
|
|||
|
|
|
|||
|
|
var properties = @object.GetPropertyHashes();
|
|||
|
|
|
|||
|
|
group.Sid = @object.GetValue<string>(properties, "sid")?.Trim();
|
|||
|
|
group.Domain = @object.GetValue<string>(properties, "domain")?.Trim();
|
|||
|
|
group.Name = @object.GetValue<string>(properties, "name")?.Trim();
|
|||
|
|
group.Description = @object.GetValue<string>(properties, "description")?.Trim();
|
|||
|
|
group.LocalAccount = @object.GetValue<bool>(properties, "localaccount");
|
|||
|
|
|
|||
|
|
groups.Add(group);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return groups.OrderBy(x => x.Name)?.ToList();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static List<User> QueryUsers()
|
|||
|
|
{
|
|||
|
|
using var searcher = new ManagementObjectSearcher
|
|||
|
|
{
|
|||
|
|
Scope = new ManagementScope(@"root\cimv2"),
|
|||
|
|
Query = new ObjectQuery("select sid, name, fullname, description, domain, localaccount, disabled, lockout, status, passwordchangeable, passwordexpires, passwordrequired from win32_useraccount")
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out var collection) is false)
|
|||
|
|
{
|
|||
|
|
searcher.Query = new ObjectQuery("select * from win32_useraccount");
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var users = new List<User>();
|
|||
|
|
|
|||
|
|
using (collection)
|
|||
|
|
{
|
|||
|
|
foreach (ManagementObject @object in collection)
|
|||
|
|
{
|
|||
|
|
var user = new User();
|
|||
|
|
|
|||
|
|
var properties = @object.GetPropertyHashes();
|
|||
|
|
|
|||
|
|
user.Sid = @object.GetValue<string>(properties, "sid")?.Trim();
|
|||
|
|
user.Name = @object.GetValue<string>(properties, "name")?.Trim();
|
|||
|
|
user.FullName = @object.GetValue<string>(properties, "fullname")?.Trim();
|
|||
|
|
user.Description = @object.GetValue<string>(properties, "description")?.Trim();
|
|||
|
|
user.Domain = @object.GetValue<string>(properties, "domain")?.Trim();
|
|||
|
|
user.LocalAccount = @object.GetValue<bool>(properties, "localaccount");
|
|||
|
|
user.Disabled = @object.GetValue<bool>(properties, "disabled");
|
|||
|
|
user.Lockout = @object.GetValue<bool>(properties, "lockout");
|
|||
|
|
user.Status = @object.GetValue<string>(properties, "status")?.Trim();
|
|||
|
|
user.PasswordChangeable = @object.GetValue<bool>(properties, "passwordchangeable");
|
|||
|
|
user.PasswordExpires = @object.GetValue<bool>(properties, "passwordexpires");
|
|||
|
|
user.PasswordRequired = @object.GetValue<bool>(properties, "passwordrequired");
|
|||
|
|
|
|||
|
|
users.Add(user);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return users;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static List<UserGroupMap> QueryUserGroupMaps()
|
|||
|
|
{
|
|||
|
|
using var searcher = new ManagementObjectSearcher
|
|||
|
|
{
|
|||
|
|
Scope = new ManagementScope(@"root\cimv2"),
|
|||
|
|
Query = new ObjectQuery("select groupcomponent, partcomponent from win32_groupuser")
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out var collection) is false)
|
|||
|
|
{
|
|||
|
|
searcher.Query = new ObjectQuery("select * from win32_groupuser");
|
|||
|
|
|
|||
|
|
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var usergroups = new List<UserGroupMap>();
|
|||
|
|
|
|||
|
|
using (collection)
|
|||
|
|
{
|
|||
|
|
foreach (ManagementObject @object in collection)
|
|||
|
|
{
|
|||
|
|
var usergroup = new UserGroupMap();
|
|||
|
|
|
|||
|
|
var properties = @object.GetPropertyHashes();
|
|||
|
|
|
|||
|
|
var raw = @object.GetValue<string>(properties, "groupcomponent");
|
|||
|
|
var split = raw?.Split(".Domain=")[1]?.Split(",Name=");
|
|||
|
|
|
|||
|
|
if (split is not null && split.Length > 1)
|
|||
|
|
{
|
|||
|
|
usergroup.GroupDomain = split[0].TrimStart('"').TrimEnd('"');
|
|||
|
|
usergroup.GroupName = split[1].TrimStart('"').TrimEnd('"');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
raw = @object.GetValue<string>(properties, "partcomponent");
|
|||
|
|
split = raw?.Split(".Domain=")[1]?.Split(",Name=");
|
|||
|
|
|
|||
|
|
if (split is not null && split.Length > 1)
|
|||
|
|
{
|
|||
|
|
usergroup.UserDomain = split[0].TrimStart('"').TrimEnd('"');
|
|||
|
|
usergroup.UserName = split[1].TrimStart('"').TrimEnd('"');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
usergroups.Add(usergroup);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return usergroups;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private class UserGroupMap
|
|||
|
|
{
|
|||
|
|
public string? GroupDomain { get; set; }
|
|||
|
|
public string? GroupName { get; set; }
|
|||
|
|
|
|||
|
|
public string? UserDomain { get; set; }
|
|||
|
|
public string? UserName { get; set; }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|