예제 #1
0
        private async Task AddOrUpdateCertificate(IFormFile certificateFile)
        {
            var bytes = await certificateFile.ReadAsBytesAsync();

            X509Certificate2 cert = null;

            try
            {
                cert = new X509Certificate2(bytes);
            }
            catch { }

            if (cert == null)
            {
                ModelState.AddModelError("Input.CertificateFile", "Not a valid certificate");
                return;
            }

            var existingDomainCert = await _dataContext.DomainCertificates
                                     .FirstOrDefaultAsync(x => x.Thumbprint == cert.Thumbprint);

            if (existingDomainCert != null)
            {
                ModelState.AddModelError("Input.CertificateFile", "Certificate already exists");
            }
            else
            {
                var domainCert = DomainCertificate.FromX509Certificate2(cert, CertificateSource.Uploaded);
                _dataContext.DomainCertificates.Add(domainCert);
                await _dataContext.SaveChangesAsync();

                StatusMessage = "New certificate added";
            }
        }
예제 #2
0
        public DomainScan Scan()
        {
            return(NamedLocker.RunWithLock(_domain.Uri, () =>
            {
                _logger.LogInformation($"Scanning domain {_domain.Uri}");
                var uri = new Uri(_domain.Uri);
                var hostEntry = _lookupClient.GetHostEntry(uri.Host);
                if (hostEntry != null && hostEntry.AddressList.Any())
                {
                    var msg = $"{uri.Host} resolved to the following IP addresses: " +
                              $"{string.Join(", ", hostEntry.AddressList.Select(x => x))}";
                    _messages.Add(msg);

                    _logger.LogDebug(msg);

                    var ip = hostEntry.AddressList.First();
                    OpenSslConnection(uri.Host, ip, uri.Port);
                }
                var domainCert = DomainCertificate.FromX509Certificate2(_certificate, CertificateSource.TrackedDomain);
                _certificate?.Dispose();

                var domainScan = new DomainScan
                {
                    DateScan = DateTime.UtcNow,
                    DomainCertificate = domainCert,
                    ScanResult = string.Join("\r\n", _messages),
                    ScanSuccess = domainCert != null,
                    ScanStatus = _scanStatus
                };
                _logger.LogInformation($"Domain scan finished {(domainScan.ScanSuccess ? "successfully" : "unsuccessfully")} " +
                                       $"for {_domain.Uri}");

                return domainScan;
            }));
        }
예제 #3
0
        public static TrackedCertificate FromDomainCertificate(DomainCertificate domainCertificate)
        {
            var verifyResult = domainCertificate.Certificate.Verify();

            return(new TrackedCertificate
            {
                Id = domainCertificate.DomainCertificateId,
                CertId = domainCertificate.DomainCertificateId,
                Order = int.MaxValue,
                DaysRemaining = (int)Math.Floor(domainCertificate.ValidNotAfter.Subtract(DateTime.Now).TotalDays),
                Subject = domainCertificate.Subject,
                RegistrableDomain = domainCertificate.RegistrableDomain,
                Issuer = domainCertificate?.IssuerName,
                DateModified = domainCertificate.DateCreated.ToLocalTime(),
                ValidFrom = domainCertificate.ValidNotBefore,
                ValidTo = domainCertificate.ValidNotAfter,
                IsValid = verifyResult,
                VerificationResult = verifyResult ? CertificateValidationResult.Valid : CertificateValidationResult.VerificationFailure,
                Thumbprint = domainCertificate.Thumbprint,
                Source = CertificateSource.Uploaded,
                PublicKeyHash = domainCertificate.Certificate.PublicKeyPinningHash()
            });
        }
        public async Task CreateCertificate()
        {
            var mockRequestExecutor = new MockedStringRequestExecutor(string.Empty);
            var client = new TestableOktaClient(mockRequestExecutor);

            var privateKeyMock = @"-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5cyk6x63iBJSW-----END PRIVATE KEY-----";

            var certificateMock = @"-----BEGIN CERTIFICATE-----MIIFNzCCBB+gAwIBAgISBAXomJWRama3ypu8TIxdA9wzMA0GCSqGSIb3DQEBCwUA-----END CERTIFICATE-----";

            var domainsClient     = client.Domains;
            var domainCertificate = new DomainCertificate
            {
                PrivateKey  = privateKeyMock,
                Certificate = certificateMock,
                Type        = DomainCertificateType.Pem,
            };
            await domainsClient.CreateCertificateAsync(domainCertificate, "domainId");

            mockRequestExecutor.ReceivedHref.Should().Be("/api/v1/domains/domainId/certificate");
            var expectedBody = $"{{\"privateKey\":\"{privateKeyMock}\",\"certificate\":\"{certificateMock}\",\"type\":\"{domainCertificate.Type}\"}}";

            mockRequestExecutor.ReceivedBody.Should().Be(expectedBody);
        }
예제 #5
0
        public async Task <AcmeOrder> Complete()
        {
            if (_acmeOrder.Status != AcmeOrderStatus.Validating)
            {
                return(_acmeOrder);
            }

            foreach (var cc in _authChallengeContainers)
            {
                cc.AuthorizationTask = cc.AuthorizationContext.Resource();
            }

            var attempts = 5;

            do
            {
                // Kick off the authorization tasks for the tasks that haven't been run yet
                await Task.WhenAll(_authChallengeContainers
                                   .Where(x => !x.AuthorizationTask.IsCompleted)
                                   .Select(x => x.AuthorizationTask)
                                   .ToList());

                var incompletes = 0;
                // After running the tasks, find all incomplete authz
                foreach (var cc in _authChallengeContainers)
                {
                    var status    = cc.AuthorizationTask.Result.Status;
                    var completed = status == AuthorizationStatus.Valid ||
                                    status == AuthorizationStatus.Invalid;
                    if (!completed)
                    {
                        incompletes++;

                        // Update the task such that it's a new task and it will be awaited above
                        cc.AuthorizationTask = cc.AuthorizationContext.Resource();
                    }
                    else
                    {
                        cc.Authorization = cc.AuthorizationTask.Result;
                    }
                }

                // Find incomplete ones and try again
                _logger.LogDebug($"{incompletes} incomplete authorizations.");

                if (incompletes == 0)
                {
                    break;
                }

                await Task.Delay(5000);
            } while (attempts-- > 0);

            // All authorizations have completed, save the results
            foreach (var cc in _authChallengeContainers)
            {
                cc.Authorization = cc.AuthorizationTask.Result;
            }

            // At this point, they're all complete and need to see which are valid/invalid
            // and obtain the cert if possible.
            try
            {
                var invalidResp = _authChallengeContainers
                                  .SelectMany(x => x.Authorization.Challenges)
                                  .Where(x => x.Error != null)
                                  .ToList();

                var errors = string.Join("\r\n", invalidResp
                                         .Select(x => $"{x.Error.Status} {x.Error.Type} {x.Error.Detail}"));

                _acmeOrder.RequestCount         = _authChallengeContainers.Count;
                _acmeOrder.InvalidResponseCount = invalidResp.Count;
                _acmeOrder.Errors = errors;
                _acmeOrder.Status = AcmeOrderStatus.Completed;

                if (invalidResp.Count > 0)
                {
                    _acmeOrder.Status = AcmeOrderStatus.Invalid;
                    return(_acmeOrder);
                }

                var cert = await _order.Generate(
                    new CsrInfo
                {
                    CommonName       = _acmeCertificate.CsrCommonName,
                    CountryName      = _acmeCertificate.CsrCountryName,
                    Locality         = _acmeCertificate.CsrLocality,
                    Organization     = _acmeCertificate.CsrOrganization,
                    OrganizationUnit = _acmeCertificate.CsrOrganizationUnit,
                    State            = _acmeCertificate.CsrState
                }, KeyFactory.FromPem(_acmeCertificate.Key.RawData));

                var certBytes = cert.Certificate.ToDer();

                var xCert      = new X509Certificate2(certBytes);
                var domainCert = DomainCertificate.FromX509Certificate2(xCert, CertificateSource.AcmeCertificate);
                xCert.Dispose();

                _acmeOrder.RawDataPem        = cert.ToPem();
                _acmeOrder.DomainCertificate = domainCert;

                return(_acmeOrder);
            }
            catch (AcmeRequestException e)
            {
                _acmeOrder.Status = AcmeOrderStatus.Error;
                _acmeOrder.Errors = $"{e.Error.Status} {e.Error.Type} {e.Error.Detail}";
            }
            catch (Exception)
            {
                _acmeOrder.Status = AcmeOrderStatus.Error;
                _acmeOrder.Errors = "Unknown Error";
            }
            return(_acmeOrder);
        }
예제 #6
0
    public UserCertificate(ulong id, string username, DomainCertificate domainCertificate, DateTime issueDate,
                           DateTime expireDate, HashFunctionType hashFunction = HashFunctionType.SHA1, uint ip = 0, byte[] ip6 = null)
        : base(id, issueDate, expireDate, hashFunction)
    {
        // assign type
        var cr = new BinaryList();

        //id
        cr.AddUInt64(id);

        // ip
        this.ip  = ip;
        this.ip6 = ip6;

        cr.AddUInt32(ip);


        if (ip6?.Length == 16)
        {
            cr.AddUInt8Array(ip6);
        }
        else
        {
            cr.AddUInt8Array(new byte[16]);
        }


        // dates
        this.issueDate  = DateTime.UtcNow;
        this.expireDate = expireDate;

        cr.AddDateTime(issueDate)
        .AddDateTime(expireDate);


        // domain
        this.domainId = domainCertificate.Id;
        cr.AddUInt64(domainCertificate.Id);
        this.domain = domainCertificate.Domain;
        cr.AddUInt8((byte)domainCertificate.Domain.Length)
        .AddUInt8Array(Encoding.ASCII.GetBytes(domainCertificate.Domain));


        // username
        this.username = username;

        cr.AddUInt8((byte)(username.Length))
        .AddUInt8Array(Encoding.ASCII.GetBytes(username));

        // hash function (SHA1)
        cr.AddUInt8((byte)((byte)hashFunction << 4));// (byte)0x10);

        // public key

        rsa         = RSA.Create();// new RSACryptoServiceProvider(2048);
        rsa.KeySize = 2048;
        // write public certificate file

        var key = rsa.ExportParameters(true);

        publicRawData = new BinaryList().AddUInt8((byte)key.Exponent.Length)
                        .AddUInt8Array(key.Exponent)
                        .AddUInt16((ushort)key.Modulus.Length)
                        .AddUInt8Array(key.Modulus).ToArray();


        // sign it
        this.signature = domainCertificate.Sign(publicRawData);


        // store private info
        privateRawData = DC.Merge(key.D, key.DP, key.DQ, key.InverseQ, key.P, key.Q, signature);
    }