< Summary

Class:SharpHoundCommonLib.Processors.GroupProcessor
Assembly:SharpHoundCommonLib
File(s):D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Processors\GroupProcessor.cs
Covered lines:56
Uncovered lines:7
Coverable lines:63
Total lines:115
Line coverage:88.8% (56 of 63)
Covered branches:19
Total branches:20
Branch coverage:95% (19 of 20)

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%20100%
ReadGroupMembers(...)100%100%
ReadGroupMembers()100%140100%
GetPrimaryGroupInfo(...)75%4092.3%

File(s)

D:\a\SharpHoundCommon\SharpHoundCommon\src\CommonLib\Processors\GroupProcessor.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Security.Principal;
 5using Microsoft.Extensions.Logging;
 6using SharpHoundCommonLib.Enums;
 7using SharpHoundCommonLib.OutputTypes;
 8
 9namespace SharpHoundCommonLib.Processors
 10{
 11    public class GroupProcessor
 12    {
 13        private readonly ILogger _log;
 14        private readonly ILDAPUtils _utils;
 15
 716        public GroupProcessor(ILDAPUtils utils, ILogger log = null)
 717        {
 718            _utils = utils;
 719            _log = log ?? Logging.LogProvider.CreateLogger("GroupProc");
 720        }
 21
 22        public IEnumerable<TypedPrincipal> ReadGroupMembers(ResolvedSearchResult result, ISearchResultEntry entry)
 023        {
 024            var members = entry.GetArrayProperty(LDAPProperties.Members);
 025            var name = result.DisplayName;
 026            var dn = entry.DistinguishedName;
 27
 028            return ReadGroupMembers(dn, members, name);
 029        }
 30
 31        /// <summary>
 32        ///     Processes the "member" property of groups and converts the resulting list of distinguishednames to Typed
 33        /// </summary>
 34        /// <param name="distinguishedName"></param>
 35        /// <param name="members"></param>
 36        /// <param name="objectName"></param>
 37        /// <returns></returns>
 38        public IEnumerable<TypedPrincipal> ReadGroupMembers(string distinguishedName, string[] members,
 39            string objectName = "")
 240        {
 41            // If our returned array has a length of 0, one of two things is happening
 42            // The first possibility we'll look at is we need to use ranged retrieval, because AD will not return
 43            // more than a certain number of items. If we get nothing back from this, then the group is empty
 244            if (members.Length == 0)
 145            {
 146                _log.LogTrace("Member property for {ObjectName} is empty, trying range retrieval",
 147                    objectName);
 1148                foreach (var member in _utils.DoRangedRetrieval(distinguishedName, "member"))
 449                {
 450                    _log.LogTrace("Got member {DN} for {ObjectName} from ranged retrieval", member, objectName);
 451                    var res = _utils.ResolveDistinguishedName(member);
 52
 453                    if (res == null)
 154                        yield return new TypedPrincipal
 155                        {
 156                            ObjectIdentifier = member.ToUpper(),
 157                            ObjectType = Label.Base
 158                        };
 59                    else
 360                    {
 361                        if (!Helpers.IsSidFiltered(res.ObjectIdentifier))
 362                            yield return res;
 363                    }
 464                }
 165            }
 66            else
 167            {
 68                //If we're here, we just read the data directly and life is good
 1169                foreach (var member in members)
 470                {
 471                    _log.LogTrace("Got member {DN} for {ObjectName}", member, objectName);
 472                    var res = _utils.ResolveDistinguishedName(member);
 73
 474                    if (res == null)
 175                        yield return new TypedPrincipal
 176                        {
 177                            ObjectIdentifier = member.ToUpper(),
 178                            ObjectType = Label.Base
 179                        };
 80                    else
 381                    {
 382                        if (!Helpers.IsSidFiltered(res.ObjectIdentifier))
 383                            yield return res;
 384                    }
 485                }
 186            }
 287        }
 88
 89        /// <summary>
 90        ///     Reads the primary group info from a user or computer object and massages it into the proper format.
 91        /// </summary>
 92        /// <param name="primaryGroupId"></param>
 93        /// <param name="objectId"></param>
 94        /// <returns></returns>
 95        public static string GetPrimaryGroupInfo(string primaryGroupId, string objectId)
 396        {
 397            if (primaryGroupId == null)
 198                return null;
 99
 2100            if (objectId == null)
 0101                return null;
 102
 103            try
 2104            {
 2105                var domainSid = new SecurityIdentifier(objectId).AccountDomainSid.Value;
 1106                var primaryGroupSid = $"{domainSid}-{primaryGroupId}";
 1107                return primaryGroupSid;
 108            }
 1109            catch
 1110            {
 1111                return null;
 112            }
 3113        }
 114    }
 115}