/* * * (c) Copyright Ascensio System Limited 2010-2018 * * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. * * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html * * You can contact Ascensio System SIA by email at sales@onlyoffice.com * * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. * * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains * relevant author attributions when distributing the software. If the display of the logo in its graphic * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using ARSoft.Tools.Net; using ARSoft.Tools.Net.Dns; namespace ASC.Common.Utils { public class DnsLookup { private readonly IDnsResolver _sDnsResolver; private readonly DnsClient _dnsClient; public DnsLookup() { _dnsClient = DnsClient.Default; _sDnsResolver = new DnsStubResolver(_dnsClient); } /// /// Get domain MX records /// /// domain name /// if domainName is empty /// if domainName is invalid /// list of MxRecord public List GetDomainMxRecords(string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var mxRecords = DnsResolve(domainName, RecordType.Mx); return mxRecords; } /// /// Check existance of MX record in domain DNS /// /// domain name /// MX record value /// if domainName is empty /// if domainName is invalid /// true if exists and vice versa public bool IsDomainMxRecordExists(string domainName, string mxRecord) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); if (string.IsNullOrEmpty(mxRecord)) throw new ArgumentNullException(nameof(mxRecord)); var mxDomain = DomainName.Parse(mxRecord); var records = GetDomainMxRecords(domainName); return records.Any( mx => mx.ExchangeDomainName.Equals(mxDomain)); } /// /// Check domain existance /// /// /// if domainName is empty /// if domainName is invalid /// if DNS request failed /// true if any DNS record exists and vice versa public bool IsDomainExists(string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var dnsMessage = GetDnsMessage(domainName); return dnsMessage.AnswerRecords.Any(); } /// /// Get domain A records /// /// domain name /// if domainName is empty /// if domainName is invalid /// list of ARecord public List GetDomainARecords(string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var aRecords = DnsResolve(domainName, RecordType.A); return aRecords; } /// /// Get domain IP addresses list /// /// domain name /// if domainName is empty /// if domainName is invalid /// list of IPAddress public List GetDomainIPs(string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var addresses = _sDnsResolver.ResolveHost(domainName); return addresses; } /// /// Get domain TXT records /// /// domain name /// if domainName is empty /// if domainName is invalid /// list of TxtRecord public List GetDomainTxtRecords(string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var txtRecords = DnsResolve(domainName, RecordType.Txt); return txtRecords; } /// /// Check existance of TXT record in domain DNS /// /// domain name /// TXT record value /// if domainName is empty /// if domainName is invalid /// true if exists and vice versa public bool IsDomainTxtRecordExists(string domainName, string recordValue) { var txtRecords = GetDomainTxtRecords(domainName); return txtRecords.Any( txtRecord => txtRecord.TextData.Trim('\"').Equals(recordValue, StringComparison.InvariantCultureIgnoreCase)); } /// /// Check existance of DKIM record in domain DNS /// /// domain name /// DKIM selector (example is "dkim") /// DKIM record value /// if domainName is empty /// if domainName is invalid /// true if exists and vice versa public bool IsDomainDkimRecordExists(string domainName, string dkimSelector, string dkimValue) { var dkimRecordName = dkimSelector + "._domainkey." + domainName; var txtRecords = GetDomainTxtRecords(dkimRecordName); return txtRecords.Any(txtRecord => txtRecord.TextData.Trim('\"').Equals(dkimValue)); } /// /// Check existance Domain in PTR record /// /// IP address for PTR check /// PTR domain name /// if domainName or ipAddress is empty/null /// if domainName is invalid /// true if exists and vice versa public bool IsDomainPtrRecordExists(IPAddress ipAddress, string domainName) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); if (ipAddress == null) throw new ArgumentNullException(nameof(ipAddress)); var domain = DomainName.Parse(domainName); var ptrDomain = _sDnsResolver.ResolvePtr(ipAddress); return ptrDomain.Equals(domain); } /// /// Check existance Domain in PTR record /// /// IP address for PTR check /// PTR domain name /// if domainName or ipAddress is empty/null /// if domainName is invalid /// if ipAddress is invalid /// true if exists and vice versa public bool IsDomainPtrRecordExists(string ipAddress, string domainName) { return IsDomainPtrRecordExists(IPAddress.Parse(ipAddress), domainName); } private DnsMessage GetDnsMessage(string domainName, RecordType? type = null) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var domain = DomainName.Parse(domainName); var dnsMessage = type.HasValue ? _dnsClient.Resolve(domain, type.Value) : _dnsClient.Resolve(domain); if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain))) { throw new SystemException(); // DNS request failed } return dnsMessage; } private List DnsResolve(string domainName, RecordType type) { if (string.IsNullOrEmpty(domainName)) throw new ArgumentNullException(nameof(domainName)); var dnsMessage = GetDnsMessage(domainName, type); return dnsMessage.AnswerRecords.Where(r => r.RecordType == type).Cast().ToList(); } } }