using DnsClient; using DnsClient.Protocol; using PKISharp.WACS.Services; using Serilog.Context; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Threading.Tasks; namespace PKISharp.WACS.Clients.DNS { public class LookupClientWrapper { private readonly ILogService _log; private readonly LookupClientProvider _provider; private readonly IPAddress? _ipAddress; private ILookupClient _lookupClient { get; set; } public string IpAddress => _ipAddress?.ToString() ?? "[System]"; public LookupClientWrapper(ILogService logService, IPAddress? ipAddress, LookupClientProvider provider) { _ipAddress = ipAddress; var clientOptions = _ipAddress != null ? new LookupClientOptions(new[] { _ipAddress }) : new LookupClientOptions(); clientOptions.UseCache = true; _lookupClient = new LookupClient(clientOptions); _log = logService; _provider = provider; } public async Task?> GetNameServers(string host, int round) { host = host.TrimEnd('.'); _log.Debug("Querying name servers for {part}", host); var nsResponse = await _lookupClient.QueryAsync(host, QueryType.NS); var nsRecords = nsResponse.Answers.NsRecords(); var cnameRecords = nsResponse.Answers.CnameRecords(); if (!nsRecords.Any() && !cnameRecords.Any()) { nsRecords = nsResponse.Authorities.OfType(); } if (nsRecords.Any()) { return GetIpAddresses(nsRecords.Select(n => n.NSDName.Value), round); } //if (cnameRecords.Any()) //{ // var client = await _provider.GetClients(cnameRecords.First().CanonicalName.Value); // return await _provider.GetAuthoritativeNameServersForDomain(cnameRecords.First().CanonicalName.Value, round); //} return null; } private IEnumerable GetIpAddresses(IEnumerable hosts, int round) { foreach (var nsRecord in hosts) { using (LogContext.PushProperty("NameServer", nsRecord)) { _log.Verbose("Querying IP for name server"); var aResponse = _provider.GetDefaultClient(round)._lookupClient.Query(nsRecord, QueryType.A); var nameServerIp = aResponse.Answers.ARecords().FirstOrDefault()?.Address; if (nameServerIp != null) { _log.Verbose("Name server IP {NameServerIpAddress} identified", nameServerIp); yield return nameServerIp; } } } } public async Task> GetTxtRecords(string host) { var txtResult = await _lookupClient.QueryAsync(host, QueryType.TXT); return txtResult.Answers.TxtRecords(). SelectMany(txtRecord => txtRecord?.EscapedText). Where(txtRecord => txtRecord != null). OfType(). ToList(); } public async Task GetCname(string host) { var cnames = await _lookupClient.QueryAsync(host, QueryType.CNAME); var cnameRecords = cnames.Answers.CnameRecords(); if (cnameRecords.Any()) { var canonicalName = cnameRecords.First().CanonicalName.Value; var idn = new IdnMapping(); canonicalName = canonicalName.ToLower().Trim().TrimEnd('.'); canonicalName = idn.GetAscii(canonicalName); return canonicalName; } return null; } } }