//[DataRow("_acme-challenge.www2.candell.org", "IpualE-HBtD8bxr60LoyuLw8FxMPOIUgg2XQTR6mSvw")]
        //[DataRow("_acme-challenge.www2.candell.org", "I2F57jex1qSMXprwPy0crWFSUe2n5AowLitxU0q_WKM")]
        //[DataRow("_acme-challenge.wouter.tinus.online", "DHrsG3LudqI9S0jvitp25tDofK1Jf58J08s3c5rIY3k")]
        //[DataRow("_acme-challenge.www7.candell.org", "xxx")]
        public void Should_recursively_follow_cnames(string challengeUri, string expectedToken)
        {
            //var client = _dnsClient.DefaultClient();
            var client = _dnsClient.GetClients(challengeUri).Result.First();
            var tokens = client.GetTextRecordValues(challengeUri, 0).Result;

            Assert.IsTrue(tokens.Contains(expectedToken));
        }
        //[DataRow("_acme-challenge.www2.candell.org", "IpualE-HBtD8bxr60LoyuLw8FxMPOIUgg2XQTR6mSvw")]
        //[DataRow("_acme-challenge.www2.candell.org", "I2F57jex1qSMXprwPy0crWFSUe2n5AowLitxU0q_WKM")]
        //[DataRow("_acme-challenge.wouter.tinus.online", "DHrsG3LudqI9S0jvitp25tDofK1Jf58J08s3c5rIY3k")]
        //[DataRow("_acme-challenge.www7.candell.org", "xxx")]
        public void Should_recursively_follow_cnames(string challengeUri, string expectedToken)
        {
            //var client = _dnsClient.DefaultClient();
            var client = _dnsClient.GetClients(challengeUri).Result.First();

            var(tokens, cname) = client.GetTextRecordValues(challengeUri, 0).Result;
            Assert.IsTrue(tokens.Contains(expectedToken));
            Assert.AreEqual(cname, "_acme-challenge.logs.hourstrackercloud.com");
        }
Exemplo n.º 3
0
        protected async Task <bool> PreValidate(int attempt)
        {
            try
            {
                var dnsClients = await _dnsClientProvider.GetClients(Challenge.DnsRecordName, attempt);

                foreach (var client in dnsClients)
                {
                    _log.Debug("Preliminary validation will now check name server {ip}", client.IpAddress);
                    var answers = await client.GetTextRecordValues(Challenge.DnsRecordName, attempt);

                    if (!answers.Any())
                    {
                        _log.Warning("Preliminary validation at {address} failed: no TXT records found", client.IpAddress);
                        return(false);
                    }
                    if (!answers.Contains(Challenge.DnsRecordValue))
                    {
                        _log.Warning("Preliminary validation at {address} failed: {ExpectedTxtRecord} not found in {TxtRecords}",
                                     client.IpAddress,
                                     Challenge.DnsRecordValue,
                                     string.Join(", ", answers));
                        return(false);
                    }
                    _log.Debug("Preliminary validation at {address} looks good!", client.IpAddress);
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Preliminary validation failed");
                return(false);
            }
            _log.Information("Preliminary validation succeeded");
            return(true);
        }
Exemplo n.º 4
0
        protected async Task <bool> PreValidate(int attempt)
        {
            try
            {
                var dnsClients = await _dnsClientProvider.GetClients(_challenge.DnsRecordName, attempt);

                _log.Debug("Preliminary validation will now check name servers: {address}",
                           string.Join(", ", dnsClients.Select(x => x.IpAddress)));

                // Parallel queries
                var answers = await Task.WhenAll(dnsClients.Select(client => client.GetTextRecordValues(_challenge.DnsRecordName, attempt)));

                // Loop through results
                for (var i = 0; i < dnsClients.Count(); i++)
                {
                    var currentClient = dnsClients[i];
                    var currentResult = answers[i];
                    if (!currentResult.Any())
                    {
                        _log.Warning("Preliminary validation for {address} failed: no TXT records found", currentClient.IpAddress);
                        return(false);
                    }
                    if (!currentResult.Contains(_challenge.DnsRecordValue))
                    {
                        _log.Warning("Preliminary validation for {address} failed: {ExpectedTxtRecord} not found in {TxtRecords}",
                                     currentClient.IpAddress,
                                     _challenge.DnsRecordValue,
                                     string.Join(", ", currentResult));
                        return(false);
                    }
                    _log.Debug("Preliminary validation for {address} looks good!", currentClient.IpAddress);
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Preliminary validation failed");
                return(false);
            }
            _log.Information("Preliminary validation succeeded");
            return(true);
        }
Exemplo n.º 5
0
        public override async Task PrepareChallenge()
        {
            // Check for substitute domains
            if (_settings.Validation.AllowDnsSubstitution)
            {
                try
                {
                    // Resolve CNAME in DNS
                    var client = await _dnsClient.GetClients(Challenge.DnsRecordName);

                    var(_, cname) = await client.First().GetTextRecordValues(Challenge.DnsRecordName, 0);

                    // Normalize CNAME
                    var idn = new IdnMapping();
                    cname = cname.ToLower().Trim().TrimEnd('.');
                    cname = idn.GetAscii(cname);

                    // Substitute
                    if (cname != Challenge.DnsRecordName)
                    {
                        _log.Information("Detected that {DnsRecordName} is a CNAME that leads to {cname}", Challenge.DnsRecordName, cname);
                        _recordName = cname;
                    }
                }
                catch (Exception ex)
                {
                    _log.Debug("Error checking for substitute domains: {ex}", ex.Message);
                }
            }

            // Create record
            await CreateRecord(_recordName ?? Challenge.DnsRecordName, Challenge.DnsRecordValue);

            _log.Information("Answer should now be available at {answerUri}", _recordName);

            // Verify that the record was created succesfully and wait for possible
            // propagation/caching/TTL issues to resolve themselves naturally
            var retry        = 0;
            var maxRetries   = _settings.Validation.PreValidateDnsRetryCount;
            var retrySeconds = _settings.Validation.PreValidateDnsRetryInterval;

            while (_settings.Validation.PreValidateDns)
            {
                if (await PreValidate(retry))
                {
                    break;
                }
                else
                {
                    retry += 1;
                    if (retry > maxRetries)
                    {
                        _log.Information("It looks like validation is going to fail, but we will try now anyway...");
                        break;
                    }
                    else
                    {
                        _log.Information("Will retry in {s} seconds (retry {i}/{j})...", retrySeconds, retry, maxRetries);
                        Thread.Sleep(retrySeconds * 1000);
                    }
                }
            }
        }