Skip to content

Commit

Permalink
chore: update output types to lift domain up a level
Browse files Browse the repository at this point in the history
  • Loading branch information
urangel committed Oct 10, 2023
1 parent 23a541b commit f9b904f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 31 deletions.
64 changes: 34 additions & 30 deletions src/CommonLib/LDAPUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class LDAPUtils : ILDAPUtils
0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21,
0x00, 0x01
};


private static readonly ConcurrentDictionary<string, ResolvedWellKnownPrincipal>
SeenWellKnownPrincipals = new();
Expand Down Expand Up @@ -204,7 +204,7 @@ public string[] GetUserGlobalCatalogMatches(string name)
return sids;

var query = new LDAPFilter().AddUsers($"samaccountname={tempName}").GetFilter();
var results = QueryLDAP(query, SearchScope.Subtree, new[] {"objectsid"}, globalCatalog: true)
var results = QueryLDAP(query, SearchScope.Subtree, new[] { "objectsid" }, globalCatalog: true)
.Select(x => x.GetSid()).Where(x => x != null).ToArray();
Cache.AddGCCache(tempName, results);
return results;
Expand Down Expand Up @@ -238,14 +238,14 @@ public TypedPrincipal ResolveCertTemplateByProperty(string propValue, string pro

if (res == null)
{
_log.LogWarning("Could not find certificate template with '{propertyName}:{propValue}' under {containerDN}", propertyName, propValue, containerDN);
_log.LogWarning("Could not find certificate template with '{propertyName}:{propValue}' under {containerDN}; null result", propertyName, propValue, containerDN);
return null;
}

List<ISearchResultEntry> resList = new List<ISearchResultEntry>(res);
if (resList.Count == 0)
{
_log.LogWarning("Could not find certificate template with '{propertyName}:{propValue}' under {containerDN}", propertyName, propValue, containerDN);
_log.LogWarning("Could not find certificate template with '{propertyName}:{propValue}' under {containerDN}; empty list", propertyName, propValue, containerDN);
return null;
}

Expand Down Expand Up @@ -495,21 +495,21 @@ public IEnumerable<string> DoRangedRetrieval(string distinguishedName, string at
var currentRange = $"{baseString};range={index}-*";
var complete = false;

var searchRequest = CreateSearchRequest($"{attributeName}=*", SearchScope.Base, new[] {currentRange},
var searchRequest = CreateSearchRequest($"{attributeName}=*", SearchScope.Base, new[] { currentRange },
domainName, distinguishedName);

if (searchRequest == null)
yield break;

var backoffDelay = MinBackoffDelay;
var retryCount = 0;

while (true)
{
SearchResponse response;
try
{
response = (SearchResponse) conn.SendRequest(searchRequest);
response = (SearchResponse)conn.SendRequest(searchRequest);
}
catch (LdapException le) when (le.ErrorCode == (int)LdapErrorCodes.Busy && retryCount < MaxRetries)
{
Expand Down Expand Up @@ -717,7 +717,7 @@ public TypedPrincipal ResolveAccountName(string name, string domain)
_log.LogDebug("ResolveAccountName - unable to get result for {Name}", name);
return null;
}

type = result.GetLabel();
id = result.GetObjectIdentifier();

Expand Down Expand Up @@ -838,14 +838,14 @@ public IEnumerable<ISearchResultEntry> QueryLDAP(string ldapFilter, SearchScope
{
var queryParams = SetupLDAPQueryFilter(
ldapFilter, scope, props, includeAcl, domainName, includeAcl, adsPath, globalCatalog, skipCache);

if (queryParams.Exception != null)
{
_log.LogWarning("Failed to setup LDAP Query Filter: {Message}", queryParams.Exception.Message);
if (throwException) throw new LDAPQueryException("Failed to setup LDAP Query Filter", queryParams.Exception);
yield break;
}

var conn = queryParams.Connection;
var request = queryParams.SearchRequest;
var pageControl = queryParams.PageControl;
Expand All @@ -862,17 +862,21 @@ public IEnumerable<ISearchResultEntry> QueryLDAP(string ldapFilter, SearchScope
try
{
_log.LogTrace("Sending LDAP request for {Filter}", ldapFilter);
response = (SearchResponse) conn.SendRequest(request);
response = (SearchResponse)conn.SendRequest(request);
if (response != null)
pageResponse = (PageResultResponseControl) response.Controls
pageResponse = (PageResultResponseControl)response.Controls
.Where(x => x is PageResultResponseControl).DefaultIfEmpty(null).FirstOrDefault();
}catch (LdapException le) when (le.ErrorCode == (int)LdapErrorCodes.Busy && retryCount < MaxRetries) {
}
catch (LdapException le) when (le.ErrorCode == (int)LdapErrorCodes.Busy && retryCount < MaxRetries)
{
retryCount++;
Thread.Sleep(backoffDelay);
backoffDelay = TimeSpan.FromSeconds(Math.Min(
backoffDelay.TotalSeconds * BackoffDelayMultiplier.TotalSeconds, MaxBackoffDelay.TotalSeconds));
continue;
} catch (LdapException le) {
}
catch (LdapException le)
{
if (le.ErrorCode != 82)
if (throwException)
throw new LDAPQueryException(
Expand Down Expand Up @@ -955,20 +959,20 @@ public virtual IEnumerable<ISearchResultEntry> QueryLDAP(string ldapFilter, Sear
var pageControl = queryParams.PageControl;

PageResultResponseControl pageResponse = null;

var backoffDelay = MinBackoffDelay;
var retryCount = 0;

while (true)
{
SearchResponse response;

try
{
_log.LogTrace("Sending LDAP request for {Filter}", ldapFilter);
response = (SearchResponse) conn.SendRequest(request);
response = (SearchResponse)conn.SendRequest(request);
if (response != null)
pageResponse = (PageResultResponseControl) response.Controls
pageResponse = (PageResultResponseControl)response.Controls
.Where(x => x is PageResultResponseControl).DefaultIfEmpty(null).FirstOrDefault();
}
catch (LdapException le) when (le.ErrorCode == (int)LdapErrorCodes.Busy && retryCount < MaxRetries)
Expand Down Expand Up @@ -1068,7 +1072,7 @@ public bool TestLDAPConfig(string domain)
{
var filter = new LDAPFilter();
filter.AddDomains();

var resDomain = GetDomain(domain)?.Name ?? domain;
_log.LogTrace("Testing LDAP connection for domain {Domain}", resDomain);

Expand Down Expand Up @@ -1108,7 +1112,7 @@ public virtual Domain GetDomain(string domainName = null)
}
catch (Exception e)
{
_log.LogDebug(e,"GetDomain call failed at {StackTrace}", new StackFrame());
_log.LogDebug(e, "GetDomain call failed at {StackTrace}", new StackFrame());
domain = null;
}

Expand Down Expand Up @@ -1221,7 +1225,7 @@ private Group GetBaseEnterpriseDC(string domain)
{
var forest = GetForest(domain)?.Name;
if (forest == null) _log.LogWarning("Error getting forest, ENTDC sid is likely incorrect");
var g = new Group {ObjectIdentifier = $"{forest}-S-1-5-9".ToUpper()};
var g = new Group { ObjectIdentifier = $"{forest}-S-1-5-9".ToUpper() };
g.Properties.Add("name", $"ENTERPRISE DOMAIN CONTROLLERS@{forest ?? "UNKNOWN"}".ToUpper());
g.Properties.Add("domainsid", GetSidFromDomainName(forest));
g.Properties.Add("domain", forest);
Expand All @@ -1247,7 +1251,7 @@ private string GetDomainNameFromSidLdap(string sid)
//Search using objectsid first
var result =
QueryLDAP($"(&(objectclass=domain)(objectsid={hexSid}))", SearchScope.Subtree,
new[] {"distinguishedname"}, globalCatalog: true).DefaultIfEmpty(null).FirstOrDefault();
new[] { "distinguishedname" }, globalCatalog: true).DefaultIfEmpty(null).FirstOrDefault();

if (result != null)
{
Expand All @@ -1258,7 +1262,7 @@ private string GetDomainNameFromSidLdap(string sid)
//Try trusteddomain objects with the securityidentifier attribute
result =
QueryLDAP($"(&(objectclass=trusteddomain)(securityidentifier={sid}))", SearchScope.Subtree,
new[] {"cn"}, globalCatalog: true).DefaultIfEmpty(null).FirstOrDefault();
new[] { "cn" }, globalCatalog: true).DefaultIfEmpty(null).FirstOrDefault();

if (result != null)
{
Expand Down Expand Up @@ -1456,7 +1460,7 @@ private async Task<LdapConnection> CreateLDAPConnection(string domainName = null
{
string targetServer;
if (_ldapConfig.Server != null)
targetServer = _ldapConfig.Server;
targetServer = _ldapConfig.Server;
else
{
var domain = GetDomain(domainName);
Expand All @@ -1472,14 +1476,14 @@ private async Task<LdapConnection> CreateLDAPConnection(string domainName = null

if (targetServer == null)
throw new LDAPQueryException($"No usable domain controller found for {domainName}");

if (!skipCache)
if (_ldapConnections.TryGetValue(targetServer, out var conn))
return conn;

var port = _ldapConfig.GetPort();
var ident = new LdapDirectoryIdentifier(targetServer, port, false, false);
var connection = new LdapConnection(ident) {Timeout = new TimeSpan(0, 0, 5, 0)};
var connection = new LdapConnection(ident) { Timeout = new TimeSpan(0, 0, 5, 0) };
if (_ldapConfig.Username != null)
{
var cred = new NetworkCredential(_ldapConfig.Username, _ldapConfig.Password);
Expand Down Expand Up @@ -1514,7 +1518,7 @@ private async Task<string> GetUsableDomainController(Domain domain, bool gc = fa
{
if (!gc && _domainControllerCache.TryGetValue(domain.Name.ToUpper(), out var dc))
return dc;

var port = gc ? 3268 : _ldapConfig.GetPort();
var pdc = domain.PdcRoleOwner.Name;
if (await _portScanner.CheckPort(pdc, port))
Expand Down Expand Up @@ -1614,7 +1618,7 @@ public int GetDomainRangeSize(string domainName = null, int defaultRangeSize = 7

var configPath = CommonPaths.CreateDNPath(CommonPaths.QueryPolicyPath, domainPath);
var enumerable = QueryLDAP("(objectclass=*)", SearchScope.Base, null, adsPath: configPath);
var config = enumerable.DefaultIfEmpty(null).FirstOrDefault();
var config = enumerable.DefaultIfEmpty(null).FirstOrDefault();
var pageSize = config?.GetArrayProperty(LDAPProperties.LdapAdminLimits).FirstOrDefault(x => x.StartsWith("MaxPageSize", StringComparison.OrdinalIgnoreCase));
if (pageSize == null)
{
Expand All @@ -1629,13 +1633,13 @@ public int GetDomainRangeSize(string domainName = null, int defaultRangeSize = 7
_log.LogInformation("Found page size {PageSize} for {Domain}", parsedPageSize, domainName ?? "current domain");
return parsedPageSize;
}

_log.LogDebug("Failed to parse pagesize for {Domain}, returning default", domainName ?? "current domain");

_ldapRangeSizeCache.TryAdd(domainPath.ToUpper(), defaultRangeSize);
return defaultRangeSize;
}

private string DomainNameToDistinguishedName(string domain)
{
var resolvedDomain = GetDomain(domain)?.Name ?? domain;
Expand Down
3 changes: 2 additions & 1 deletion src/CommonLib/OutputTypes/EnterpriseCA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
{
public class EnterpriseCA : OutputBase
{
public TypedPrincipal[] EnabledCertTemplates { get; set; }
public string Domain { get; set; }
public string HostingComputer { get; set; }
public CARegistryData CARegistryData { get; set; }
public TypedPrincipal[] EnabledCertTemplates { get; set; }
}
}
1 change: 1 addition & 0 deletions src/CommonLib/OutputTypes/NTAuthStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
{
public class NTAuthStore : OutputBase
{
public string Domain { get; set; }
}
}

0 comments on commit f9b904f

Please sign in to comment.