Make auto-discovery cross-platform (Windows + Linux)
This commit is contained in:
+147
-26
@@ -1,4 +1,6 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using ADBulkTool.Models;
|
using ADBulkTool.Models;
|
||||||
using DnsClient;
|
using DnsClient;
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ public static class DomainDiscovery
|
|||||||
if (string.IsNullOrWhiteSpace(domain))
|
if (string.IsNullOrWhiteSpace(domain))
|
||||||
{
|
{
|
||||||
return new DiscoveryResult(null, null, null, null, null,
|
return new DiscoveryResult(null, null, null, null, null,
|
||||||
"Could not detect a DNS domain from this machine. Check that you are on a domain-joined network and that /etc/resolv.conf has a search or domain entry.");
|
"Could not detect a DNS domain. Ensure the machine is on a domain network with a proper DNS configuration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
steps.Add($"Detected domain: {domain}");
|
steps.Add($"Detected domain: {domain}");
|
||||||
@@ -27,8 +29,8 @@ public static class DomainDiscovery
|
|||||||
var dnsServers = GetDnsServers();
|
var dnsServers = GetDnsServers();
|
||||||
var dnsServer = dnsServers.FirstOrDefault();
|
var dnsServer = dnsServers.FirstOrDefault();
|
||||||
steps.Add(dnsServer is not null
|
steps.Add(dnsServer is not null
|
||||||
? $"DNS server from /etc/resolv.conf: {dnsServer}"
|
? $"DNS server found: {dnsServer}"
|
||||||
: "No DNS server found in /etc/resolv.conf, using system default.");
|
: "No DNS server found, using system default resolver.");
|
||||||
|
|
||||||
var ldapHost = await FindDomainControllerViaSrvAsync(domain, dnsServer, timeout);
|
var ldapHost = await FindDomainControllerViaSrvAsync(domain, dnsServer, timeout);
|
||||||
|
|
||||||
@@ -62,29 +64,12 @@ public static class DomainDiscovery
|
|||||||
|
|
||||||
public static List<string> GetDnsServers()
|
public static List<string> GetDnsServers()
|
||||||
{
|
{
|
||||||
var servers = new List<string>();
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var lines = File.ReadAllLines("/etc/resolv.conf");
|
|
||||||
foreach (var line in lines)
|
|
||||||
{
|
|
||||||
var trimmed = line.Trim();
|
|
||||||
if (trimmed.StartsWith("nameserver ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var parts = trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
||||||
if (parts.Length >= 2 && IPAddress.TryParse(parts[1], out _))
|
|
||||||
{
|
|
||||||
servers.Add(parts[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
|
return GetDnsServersWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
return servers;
|
return GetDnsServersLinux();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string? DomainToSearchBase(string? domain)
|
public static string? DomainToSearchBase(string? domain)
|
||||||
@@ -109,11 +94,23 @@ public static class DomainDiscovery
|
|||||||
{
|
{
|
||||||
using var cts = new CancellationTokenSource(timeout);
|
using var cts = new CancellationTokenSource(timeout);
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
var resolvDomain = await Task.Run(() => GetDomainFromResolvConf(), cts.Token);
|
var resolvDomain = await Task.Run(() => GetDomainFromResolvConf(), cts.Token);
|
||||||
if (!string.IsNullOrWhiteSpace(resolvDomain))
|
if (!string.IsNullOrWhiteSpace(resolvDomain))
|
||||||
{
|
{
|
||||||
return resolvDomain;
|
return resolvDomain;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
var winDomain = await Task.Run(() => GetDomainFromWindows(), cts.Token);
|
||||||
|
if (!string.IsNullOrWhiteSpace(winDomain))
|
||||||
|
{
|
||||||
|
return winDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var hostDomain = await Task.Run(() => GetDomainFromHostname(), cts.Token);
|
var hostDomain = await Task.Run(() => GetDomainFromHostname(), cts.Token);
|
||||||
if (!string.IsNullOrWhiteSpace(hostDomain))
|
if (!string.IsNullOrWhiteSpace(hostDomain))
|
||||||
@@ -123,8 +120,14 @@ public static class DomainDiscovery
|
|||||||
|
|
||||||
var ipDomain = await Task.Run(() =>
|
var ipDomain = await Task.Run(() =>
|
||||||
{
|
{
|
||||||
try { return System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName; }
|
try
|
||||||
catch { return string.Empty; }
|
{
|
||||||
|
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
}, cts.Token);
|
}, cts.Token);
|
||||||
if (!string.IsNullOrWhiteSpace(ipDomain) && !string.Equals(ipDomain, "localdomain", StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrWhiteSpace(ipDomain) && !string.Equals(ipDomain, "localdomain", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@@ -139,6 +142,68 @@ public static class DomainDiscovery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<string> GetDnsServersWindows()
|
||||||
|
{
|
||||||
|
var servers = new List<string>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||||
|
{
|
||||||
|
if (ni.OperationalStatus != OperationalStatus.Up)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var props = ni.GetIPProperties();
|
||||||
|
if (props is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dns in props.DnsAddresses)
|
||||||
|
{
|
||||||
|
if (dns.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !servers.Contains(dns.ToString()))
|
||||||
|
{
|
||||||
|
servers.Add(dns.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> GetDnsServersLinux()
|
||||||
|
{
|
||||||
|
var servers = new List<string>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var lines = File.ReadAllLines("/etc/resolv.conf");
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
var trimmed = line.Trim();
|
||||||
|
if (trimmed.StartsWith("nameserver ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var parts = trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
if (parts.Length >= 2 && IPAddress.TryParse(parts[1], out _))
|
||||||
|
{
|
||||||
|
servers.Add(parts[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
private static string? GetDomainFromResolvConf()
|
private static string? GetDomainFromResolvConf()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -174,6 +239,62 @@ public static class DomainDiscovery
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string? GetDomainFromWindows()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||||
|
{
|
||||||
|
if (ni.OperationalStatus != OperationalStatus.Up)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var props = ni.GetIPProperties();
|
||||||
|
if (props is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suffix = props.DnsSuffix;
|
||||||
|
if (!string.IsNullOrWhiteSpace(suffix))
|
||||||
|
{
|
||||||
|
return suffix.TrimEnd('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CA1416 // Registry access is guarded by platform check
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
|
||||||
|
@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters");
|
||||||
|
if (key is not null)
|
||||||
|
{
|
||||||
|
var domain = key.GetValue("Domain") as string;
|
||||||
|
if (!string.IsNullOrWhiteSpace(domain))
|
||||||
|
{
|
||||||
|
return domain.TrimEnd('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var dhcpDomain = key.GetValue("DhcpDomain") as string;
|
||||||
|
if (!string.IsNullOrWhiteSpace(dhcpDomain))
|
||||||
|
{
|
||||||
|
return dhcpDomain.TrimEnd('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static string? GetDomainFromHostname()
|
private static string? GetDomainFromHostname()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -192,7 +313,7 @@ public static class DomainDiscovery
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fullHostname = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().HostName;
|
var fullHostname = IPGlobalProperties.GetIPGlobalProperties().HostName;
|
||||||
var dotIndex = fullHostname.IndexOf('.');
|
var dotIndex = fullHostname.IndexOf('.');
|
||||||
if (dotIndex > 0 && dotIndex < fullHostname.Length - 1)
|
if (dotIndex > 0 && dotIndex < fullHostname.Length - 1)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user