192 lines
No EOL
6.8 KiB
C#
192 lines
No EOL
6.8 KiB
C#
using Insight.Domain.Interfaces;
|
|
using Insight.Domain.Network;
|
|
using Insight.Domain.Network.Agent.Messages;
|
|
using System.Management;
|
|
using System.Runtime.Versioning;
|
|
|
|
namespace Insight.Agent.Network.Handlers;
|
|
|
|
[SupportedOSPlatform("windows")]
|
|
public class UserHandler : IMessageHandler<AgentSession>
|
|
{
|
|
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IMessage
|
|
{
|
|
switch (message)
|
|
{
|
|
case InventoryRequest:
|
|
{
|
|
var result = new Collection<User>();
|
|
result.AddRange(GetUsers());
|
|
|
|
await sender.SendAsync(result, cancellationToken);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static List<User> GetUsers()
|
|
{
|
|
var users = QueryUsers();
|
|
var groups = GetGroups();
|
|
var usergrouping = QueryUserGroupMaps();
|
|
|
|
foreach (var u in users)
|
|
{
|
|
u.Groups = [];
|
|
|
|
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.Cast<ManagementObject>())
|
|
{
|
|
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)];
|
|
}
|
|
|
|
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.Cast<ManagementObject>())
|
|
{
|
|
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.Cast<ManagementObject>())
|
|
{
|
|
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; }
|
|
}
|
|
} |