diff --git a/Difi.Felles.Utility.Tester/CertificateChainValidatorTests.cs b/Difi.Felles.Utility.Tester/CertificateChainValidatorTests.cs index d2f32e3..242eb5f 100755 --- a/Difi.Felles.Utility.Tester/CertificateChainValidatorTests.cs +++ b/Difi.Felles.Utility.Tester/CertificateChainValidatorTests.cs @@ -1,167 +1,60 @@ -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using Difi.Felles.Utility.Exceptions; -using Difi.Felles.Utility.Utilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Difi.Felles.Utility.Utilities; using Xunit; using Assert = Xunit.Assert; namespace Difi.Felles.Utility.Tester { - + public class CertificateChainValidatorTests { - public class ErGyldigSertifikatkjedeMethod : CertificateChainValidatorTests + public class ValidateCertificateChain : CertificateChainValidatorTests { [Fact] - public void Gyldig_produksjonssertifikat_når_validerer_mot_produksjonskjede() - { - //Arrange - var produksjonssertifikat = SertifikatUtility.GetProduksjonsMottakerSertifikatOppslagstjenesten(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(produksjonssertifikat); - - //Assert - Assert.True(erGyldigResponssertifikat); - } - - [Fact] - public void Gyldig_testsertifikat_når_validerer_mot_testkjede() - { - //Arrange - var testSertifikat = SertifikatUtility.GetFunksjoneltTestmiljøMottakerSertifikatOppslagstjenesten(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(testSertifikat); - - //Assert - Assert.True(erGyldigResponssertifikat); - } - - [Fact] - public void Gyldig_produksjonssertifikat_og_kjedestatus_når_validerer_mot_produksjonskjede() + public void Valid_with_correct_root_and_intermediate() { //Arrange - var produksjonssertifikat = SertifikatUtility.GetProduksjonsMottakerSertifikatOppslagstjenesten(); - X509ChainStatus[] kjedestatus; + var productionCertificate = SertifikatUtility.GetProduksjonsMottakerSertifikatOppslagstjenesten(); + var certificateChainValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(produksjonssertifikat, out kjedestatus); + var result = certificateChainValidator.Validate(productionCertificate); //Assert - const int forventetAntallStatusElementer = 0; - Assert.True(erGyldigResponssertifikat); - Assert.Equal(forventetAntallStatusElementer, kjedestatus.Length); + Assert.Equal(CertificateValidationType.Valid, result.Type); + Assert.Contains("et gyldig sertifikat", result.Message); } [Fact] - public void Gyldig_testsertifikat_og_kjedestatus_når_validerer_mot_testkjede() + public void Fails_with_wrong_root_and_intermediate() { //Arrange - var testSertifikat = SertifikatUtility.GetFunksjoneltTestmiljøMottakerSertifikatOppslagstjenesten(); - X509ChainStatus[] kjedestatus; + var productionCertificate = SertifikatUtility.GetProduksjonsMottakerSertifikatOppslagstjenesten(); //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(testSertifikat, out kjedestatus); + var certificateChainValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); + var result = certificateChainValidator.Validate(productionCertificate); //Assert - Assert.True(erGyldigResponssertifikat); - Assert.True((kjedestatus.Length == 0) || (kjedestatus.ElementAt(0).Status == X509ChainStatusFlags.UntrustedRoot)); - } - - [Fact] - public void Feiler_med_selvsignert_sertifikat_når_validerer_mot_produksjonskjede() - { - //Arrange - var selvsignertSertifikat = SertifikatUtility.GetEnhetstesterSelvsignertSertifikat(); + Assert.Equal(CertificateValidationType.InvalidChain, result.Type); + Assert.Contains("blir hentet fra Certificate Store på Windows", result.Message); - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); - - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(selvsignertSertifikat); - - //Assert - Assert.False(erGyldigResponssertifikat); } [Fact] - public void Feiler_med_selvsignert_sertifikat_når_validerer_mot_testkjede() + public void Fails_with_self_signed_certificate() { //Arrange - var selvsignertSertifikat = SertifikatUtility.GetEnhetstesterSelvsignertSertifikat(); + var selfSignedCertificate = SertifikatUtility.GetEnhetstesterSelvsignertSertifikat(); + var certificateChainValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); - - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(selvsignertSertifikat); + var result = certificateChainValidator.Validate(selfSignedCertificate); //Assert - Assert.False(erGyldigResponssertifikat); - } - - [Fact] - public void Feiler_med_selvsignert_sertifikat_og_kjedestatus_når_validerer_mot_produksjonskjede() - { - //Arrange - var selvsignertSertifikat = SertifikatUtility.GetEnhetstesterSelvsignertSertifikat(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); - - X509ChainStatus[] kjedestatus; - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(selvsignertSertifikat, out kjedestatus); - - //Assert - Assert.False(erGyldigResponssertifikat); - Assert.True(kjedestatus.ElementAt(0).Status == X509ChainStatusFlags.UntrustedRoot); - } - - [Fact] - public void Feiler_med_selvsignert_sertifikat_og_kjedestatus_når_validerer_mot_testkjede() - { - var selvsignertSertifikat = SertifikatUtility.GetEnhetstesterSelvsignertSertifikat(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); - - X509ChainStatus[] kjedestatus; - var erGyldigResponssertifikat = sertifikatValidator.ErGyldigSertifikatkjede(selvsignertSertifikat, out kjedestatus); - - //Assert - Assert.False(erGyldigResponssertifikat); - Assert.True(kjedestatus.ElementAt(0).Status == X509ChainStatusFlags.UntrustedRoot); - } - - [Fact] - public void Feiler_med_produksjonssertifikat_når_validerer_mot_testkjede() - { - //Arrange - var produksjonssertifikat = SertifikatUtility.GetProduksjonsMottakerSertifikatOppslagstjenesten(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.FunksjoneltTestmiljøSertifikater()); - var erGyldigSertifikatkjede = sertifikatValidator.ErGyldigSertifikatkjede(produksjonssertifikat); - - Assert.False(erGyldigSertifikatkjede); - } - - [Fact] - public void Feiler_med_testsertifikat_når_validerer_mot_produksjonskjede() - { - //Arrange - var testsertifikat = SertifikatUtility.GetFunksjoneltTestmiljøMottakerSertifikatOppslagstjenesten(); - - //Act - var sertifikatValidator = new CertificateChainValidator(CertificateChainUtility.ProduksjonsSertifikater()); - var erGyldigSertifikatkjede = sertifikatValidator.ErGyldigSertifikatkjede(testsertifikat); + Assert.Equal(CertificateValidationType.InvalidChain, result.Type); + Assert.Contains("sertifikatet er selvsignert", result.Message); - Assert.False(erGyldigSertifikatkjede); } } } diff --git a/Difi.Felles.Utility.Tester/CertificateValidatorTests.cs b/Difi.Felles.Utility.Tester/CertificateValidatorTests.cs index 8e5e2a5..8b28c4d 100755 --- a/Difi.Felles.Utility.Tester/CertificateValidatorTests.cs +++ b/Difi.Felles.Utility.Tester/CertificateValidatorTests.cs @@ -1,7 +1,4 @@ - - -using ApiClientShared; -using Difi.Felles.Utility.Utilities; +using Difi.Felles.Utility.Utilities; using Xunit; namespace Difi.Felles.Utility.Tester @@ -15,47 +12,41 @@ public class ValidateCertificateAndChain : CertificateValidatorTests public void Returns_fail_if_certificate_error() { //Arrange - var funksjoneltTestmiljøSertifikater = CertificateChainUtility.FunksjoneltTestmiljøSertifikater(); + var funksjoneltTestmiljøSertifikater = CertificateChainUtility.TestCertificates(); //Act - var result = CertificateValidator.ValidateCertificateAndChain( - SertifikatUtility.GetExpiredSelfSignedTestCertificate(), "988015814", funksjoneltTestmiljøSertifikater); + var result = CertificateValidator.ValidateCertificateAndChain(SertifikatUtility.GetExpiredSelfSignedTestCertificate(), "988015814", funksjoneltTestmiljøSertifikater); //Assert - Assert.Equal(SertifikatValideringType.UgyldigSertifikat, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidCertificate, result.Type); + Assert.NotNull(result.Message); } [Fact] public void Returns_fail_if_invalid_certificate_chain() { //Arrange - var funksjoneltTestmiljøSertifikater = CertificateChainUtility.FunksjoneltTestmiljøSertifikater(); + var funksjoneltTestmiljøSertifikater = CertificateChainUtility.TestCertificates(); //Act - var result = CertificateValidator.ValidateCertificateAndChain( - SertifikatUtility.GetValidSelfSignedTestCertificate(), "988015814", funksjoneltTestmiljøSertifikater); + var result = CertificateValidator.ValidateCertificateAndChain(SertifikatUtility.GetValidSelfSignedTestCertificate(), "988015814", funksjoneltTestmiljøSertifikater); //Assert - Assert.Equal(SertifikatValideringType.UgyldigKjede, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidChain, result.Type); } [Fact] public void Returns_ok_if_valid_certificate_and_chain() { //Arrange - var funksjoneltTestmiljøSertifikater = CertificateChainUtility.FunksjoneltTestmiljøSertifikater(); + var funksjoneltTestmiljøSertifikater = CertificateChainUtility.TestCertificates(); //Act - var result = CertificateValidator.ValidateCertificateAndChain( - SertifikatUtility.GetPostenCertificate(), "984661185", funksjoneltTestmiljøSertifikater); + var result = CertificateValidator.ValidateCertificateAndChain(SertifikatUtility.GetPostenCertificate(), "984661185", funksjoneltTestmiljøSertifikater); //Assert - Assert.Equal(SertifikatValideringType.Gyldig, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.Valid, result.Type); } - } public class ValidateCertificateMethod : CertificateValidatorTests @@ -64,69 +55,70 @@ public class ValidateCertificateMethod : CertificateValidatorTests public void Returns_fail_with_null_certificate() { //Arrange + const string organizationNumber = "123456789"; //Act - var result = CertificateValidator.ValidateCertificate(null, "123456789"); + var result = CertificateValidator.ValidateCertificate(null, organizationNumber); //Assert - Assert.Equal(SertifikatValideringType.UgyldigSertifikat, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidCertificate, result.Type); + Assert.Contains("var null", result.Message); } [Fact] public void Returns_fail_if_not_issued_to_organization_number() { //Arrange - var organizationNumber = "123456789"; + const string certificateOrganizationNumber = "123456789"; //Act - var result = CertificateValidator.ValidateCertificate(SertifikatUtility.TestIntegrasjonssertifikat(), organizationNumber); + var result = CertificateValidator.ValidateCertificate(SertifikatUtility.TestIntegrasjonssertifikat(), certificateOrganizationNumber); //Assert - Assert.Equal(SertifikatValideringType.UgyldigSertifikat, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidCertificate, result.Type); + Assert.Contains("ikke utstedt til organisasjonsnummer", result.Message); } [Fact] public void Returns_fail_if_not_activated() { //Arrange - var sertifikatOrganisasjonsnummer = "988015814"; + const string certificateOrganizationNumber = "988015814"; //Act - var result = CertificateValidator.ValidateCertificate(SertifikatUtility.NotActivatedSelfSignedTestCertificate(), sertifikatOrganisasjonsnummer); + var result = CertificateValidator.ValidateCertificate(SertifikatUtility.NotActivatedSelfSignedTestCertificate(), certificateOrganizationNumber); //Assert - Assert.Equal(SertifikatValideringType.UgyldigSertifikat, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidCertificate, result.Type); + Assert.Contains("aktiveres ikke før", result.Message); } [Fact] public void Returns_fail_if_expired() { //Arrange - var sertifikatOrganisasjonsnummer = "988015814"; + const string certificateOrganizationNumber = "988015814"; //Act - var result = CertificateValidator.ValidateCertificate(SertifikatUtility.GetExpiredSelfSignedTestCertificate(), sertifikatOrganisasjonsnummer); + var result = CertificateValidator.ValidateCertificate(SertifikatUtility.GetExpiredSelfSignedTestCertificate(), certificateOrganizationNumber); //Assert - Assert.Equal(SertifikatValideringType.UgyldigSertifikat, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.InvalidCertificate, result.Type); + Assert.Contains("gikk ut",result.Message); } [Fact] public void Returns_ok_if_valid() { //Arrange - var sertifikatOrganisasjonsnummer = "984661185"; + const string certificateOrganizationNumber = "984661185"; //Act - var result = CertificateValidator.ValidateCertificate(SertifikatUtility.GetPostenCertificate(), sertifikatOrganisasjonsnummer); + var result = CertificateValidator.ValidateCertificate(SertifikatUtility.GetPostenCertificate(), certificateOrganizationNumber); //Assert - Assert.Equal(SertifikatValideringType.Gyldig, result.Type); - Assert.NotNull(result.Melding); + Assert.Equal(CertificateValidationType.Valid, result.Type); + Assert.Contains("er et gyldig sertifikat", result.Message); } @@ -138,7 +130,7 @@ public class IsValidCertificateMethod : CertificateValidatorTests public void Returns_false_with_null_certificate() { //Arrange - var certificateOrganizationNumber = "123456789"; + const string certificateOrganizationNumber = "123456789"; //Act var isValid = CertificateValidator.IsValidCertificate(null, certificateOrganizationNumber); @@ -151,10 +143,10 @@ public void Returns_false_with_null_certificate() public void Returns_false_if_not_issued_to_organization_number() { //Arrange - var sertifikatOrganisasjonsnummer = "123456789"; + var certificateOrganizationNumber = "123456789"; //Act - var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.TestIntegrasjonssertifikat(), sertifikatOrganisasjonsnummer); + var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.TestIntegrasjonssertifikat(), certificateOrganizationNumber); //Assert Assert.False(isValid); @@ -164,10 +156,10 @@ public void Returns_false_if_not_issued_to_organization_number() public void Returns_false_if_not_activated() { //Arrange - var sertifikatOrganisasjonsnummer = "123456789"; + var certificateOrganizationNumber = "123456789"; //Act - var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.NotActivatedSelfSignedTestCertificate(), sertifikatOrganisasjonsnummer); + var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.NotActivatedSelfSignedTestCertificate(), certificateOrganizationNumber); //Assert Assert.False(isValid); @@ -177,10 +169,10 @@ public void Returns_false_if_not_activated() public void Returns_false_if_expired() { //Arrange - var sertifikatOrganisasjonsnummer = "123456789"; + var certificateOrganizationNumber = "123456789"; //Act - var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.GetExpiredSelfSignedTestCertificate(), sertifikatOrganisasjonsnummer); + var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.GetExpiredSelfSignedTestCertificate(), certificateOrganizationNumber); //Assert Assert.False(isValid); @@ -190,10 +182,10 @@ public void Returns_false_if_expired() public void Returns_true_for_correct_certificate() { //Arrange - var sertifikatOrganisasjonsnummer = "984661185"; + var certificateOrganizationNumber = "984661185"; //Act - var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.GetPostenCertificate(), sertifikatOrganisasjonsnummer); + var isValid = CertificateValidator.IsValidCertificate(SertifikatUtility.GetPostenCertificate(), certificateOrganizationNumber); //Assert Assert.True(isValid); diff --git a/Difi.Felles.Utility.Tester/Utilities/CertificateChainUtilityTests.cs b/Difi.Felles.Utility.Tester/Utilities/CertificateChainUtilityTests.cs index 6dba02a..0950a38 100755 --- a/Difi.Felles.Utility.Tester/Utilities/CertificateChainUtilityTests.cs +++ b/Difi.Felles.Utility.Tester/Utilities/CertificateChainUtilityTests.cs @@ -14,7 +14,7 @@ public class TestsertifikaterMethod : CertificateChainUtilityTests public void ReturnererFireSertifikaterMedThumbprint() { //Arrange - var sertifikater = CertificateChainUtility.FunksjoneltTestmiljøSertifikater(); + var sertifikater = CertificateChainUtility.TestCertificates(); //Act @@ -33,7 +33,7 @@ public class ProduksjonssertifikaterMethod : CertificateChainUtilityTests public void ReturnererFireSertifikaterMedThumbprint() { //Arrange - var sertifikater = CertificateChainUtility.ProduksjonsSertifikater(); + var sertifikater = CertificateChainUtility.ProductionCertificates(); //Act @@ -52,7 +52,7 @@ public class CertificateChainInfoTests : CertificateChainUtilityTests public void DebugMesages() { int i = 0; - foreach (var certificate in CertificateChainUtility.FunksjoneltTestmiljøSertifikater()) + foreach (var certificate in CertificateChainUtility.TestCertificates()) { Trace.WriteLine($"{i++}: Issuer `{certificate.Issuer}`, thumbprint `{certificate.Thumbprint}`"); } diff --git a/Difi.Felles.Utility/CertificateChainValidator.cs b/Difi.Felles.Utility/CertificateChainValidator.cs index cedac20..e6e5449 100755 --- a/Difi.Felles.Utility/CertificateChainValidator.cs +++ b/Difi.Felles.Utility/CertificateChainValidator.cs @@ -1,74 +1,100 @@ using System; using System.Linq; using System.Security.Cryptography.X509Certificates; -using Difi.Felles.Utility.Exceptions; using Difi.Felles.Utility.Extensions; namespace Difi.Felles.Utility { public class CertificateChainValidator { - public CertificateChainValidator(X509Certificate2Collection sertifikatLager) + public CertificateChainValidator(X509Certificate2Collection certificateStore) { - SertifikatLager = sertifikatLager; + CertificateStore = certificateStore; } - public X509Certificate2Collection SertifikatLager { get; set; } + public X509Certificate2Collection CertificateStore { get; set; } + + [Obsolete("Use CertificateStore instead.")] + public X509Certificate2Collection SertifikatLager => CertificateStore; + + /// + /// Validerer sertifikatkjeden til sertifikatet. Gjør dette ved å validere mot + /// + /// + /// + [Obsolete("Use IsValidChain instead.")] + public bool ErGyldigSertifikatkjede(X509Certificate2 certificate) + { + return IsValidChain(certificate); + } + + /// + /// Validerer sertifikatkjeden til sertifikatet. Gjør dette ved å validere mot + /// + /// + /// + public bool IsValidChain(X509Certificate2 certificate) + { + return Validate(certificate).Type == CertificateValidationType.Valid; + } /// /// Validerer sertifikatkjeden til sertifikatet. Gjør dette ved å validere mot /// - /// + /// + /// Status på kjeden etter validering hvis validering feilet. /// - public bool ErGyldigSertifikatkjede(X509Certificate2 sertifikat) + [Obsolete("Use IsValidChain instead.")] + public bool ErGyldigSertifikatkjede(X509Certificate2 certificate, out string detaljertFeilinformasjon) { - X509ChainStatus[] chainStatuses; - return ErGyldigSertifikatkjede(sertifikat, out chainStatuses); + return IsValidChain(certificate, out detaljertFeilinformasjon); } /// /// Validerer sertifikatkjeden til sertifikatet. Gjør dette ved å validere mot /// - /// + /// /// Status på kjeden etter validering hvis validering feilet. /// - public bool ErGyldigSertifikatkjede(X509Certificate2 sertifikat, out string detaljertFeilinformasjon) + public bool IsValidChain(X509Certificate2 certificate, out string detaljertFeilinformasjon) { - var result = ValidateCertificateChain(sertifikat); - detaljertFeilinformasjon = result.Melding; + var result = Validate(certificate); + detaljertFeilinformasjon = result.Message; - return result.Type == SertifikatValideringType.Gyldig; + return result.Type == CertificateValidationType.Valid; } - public SertifikatValideringsResultat ValidateCertificateChain(X509Certificate2 certificate) + + public CertificateValidationResult Validate(X509Certificate2 certificate) { var chain = BuildCertificateChain(certificate); var onlyUsingValidatorCertificatesResult = ValidateThatUsingOnlyValidatorCertificates(chain, certificate); - return onlyUsingValidatorCertificatesResult.Type != SertifikatValideringType.Gyldig + return onlyUsingValidatorCertificatesResult.Type != CertificateValidationType.Valid ? onlyUsingValidatorCertificatesResult - : ValidateCertificateChain(certificate, chain); + : Validate(certificate, chain); } /// /// Validerer sertifikatkjeden til sertifikatet. Gjør dette ved å validere mot /// - /// - /// Status på kjeden etter validering hvis validering feilet. + /// + /// Status på kjeden etter validering hvis validering feilet. /// - public bool ErGyldigSertifikatkjede(X509Certificate2 sertifikat, out X509ChainStatus[] detaljertFeilinformasjon) + [Obsolete("Use other overloads for validation, as this overload exposes the error of untrusted root certificate. We tolerate this error because it occurs when loading a root certificate from file, which is always done here. We trust the certificates as they are preloaded in library.")] + public bool ErGyldigSertifikatkjede(X509Certificate2 certificate, out X509ChainStatus[] detailedErrorInformation) { - var chain = BuildCertificateChain(sertifikat); - detaljertFeilinformasjon = chain.ChainStatus; + var chain = BuildCertificateChain(certificate); + detailedErrorInformation = chain.ChainStatus; - var onlyUsingValidatorCertificatesResult = ValidateThatUsingOnlyValidatorCertificates(chain,sertifikat); - if (onlyUsingValidatorCertificatesResult.Type != SertifikatValideringType.Gyldig) + var onlyUsingValidatorCertificatesResult = ValidateThatUsingOnlyValidatorCertificates(chain,certificate); + if (onlyUsingValidatorCertificatesResult.Type != CertificateValidationType.Valid) { return false; } - return ValidateCertificateChain(sertifikat, chain).Type == SertifikatValideringType.Gyldig; + return Validate(certificate, chain).Type == CertificateValidationType.Valid; } private X509Chain BuildCertificateChain(X509Certificate2 sertifikat) @@ -81,35 +107,35 @@ private X509Chain BuildCertificateChain(X509Certificate2 sertifikat) return chain; } - private SertifikatValideringsResultat ValidateThatUsingOnlyValidatorCertificates(X509Chain chain, X509Certificate2 sertifikat) + private CertificateValidationResult ValidateThatUsingOnlyValidatorCertificates(X509Chain chain, X509Certificate2 certificate) { foreach (var chainElement in chain.ChainElements) { - var isCertificateToValidate = IsSameCertificate(chainElement.Certificate, sertifikat); + var isCertificateToValidate = IsSameCertificate(chainElement.Certificate, certificate); if (isCertificateToValidate) { continue; } - var isValidatorCertificate = SertifikatLager.Cast().Any(lagerSertifikat => IsSameCertificate(chainElement.Certificate, lagerSertifikat)); + var isValidatorCertificate = CertificateStore.Cast().Any(lagerSertifikat => IsSameCertificate(chainElement.Certificate, lagerSertifikat)); if (isValidatorCertificate) { continue; } var chainAsString = chain.ChainElements .Cast() - .Where(c => c.Certificate.Thumbprint != sertifikat.Thumbprint) + .Where(c => c.Certificate.Thumbprint != certificate.Thumbprint) .Aggregate("",(result, curr) => GetCertificateInfo(result, curr.Certificate)); - var validatorCertificatesAsString = SertifikatLager + var validatorCertificatesAsString = CertificateStore .Cast() .Aggregate("", GetCertificateInfo); - return UsedExternalCertificatesResult(sertifikat, chainAsString, validatorCertificatesAsString); + return UsedExternalCertificatesResult(certificate, chainAsString, validatorCertificatesAsString); } - return new SertifikatValideringsResultat(SertifikatValideringType.Gyldig, ""); + return ValidResult(certificate); } - private static SertifikatValideringsResultat UsedExternalCertificatesResult(X509Certificate2 sertifikat, string chainAsString, string validatorCertificatesAsString) + private static CertificateValidationResult UsedExternalCertificatesResult(X509Certificate2 sertifikat, string chainAsString, string validatorCertificatesAsString) { - return new SertifikatValideringsResultat(SertifikatValideringType.UgyldigKjede, - $"Validering av sertifikat '{sertifikat.Info()}' feilet. {Environment.NewLine}" + + return new CertificateValidationResult(CertificateValidationType.InvalidChain, + $"Validering av '{sertifikat.ToShortString()}' feilet. {Environment.NewLine}" + $"Dette skjer fordi kjeden ble bygd med følgende sertifikater: {Environment.NewLine}{chainAsString}, " + $"men kun følgende er godkjent for å bygge kjeden: {Environment.NewLine}{validatorCertificatesAsString}. Dette skjer som oftest om sertifikater blir hentet fra Certificate Store på Windows, " + "og det tillates ikke under validering. Det er kun gyldig å bygge en kjede med de sertifikatene sendt inn til validatoren."); @@ -132,17 +158,16 @@ public X509ChainPolicy ChainPolicy() RevocationMode = X509RevocationMode.NoCheck }; - policy.ExtraStore.AddRange(SertifikatLager); + policy.ExtraStore.AddRange(CertificateStore); return policy; } - private static SertifikatValideringsResultat ValidateCertificateChain(X509Certificate2 certificate, X509Chain chain) + private static CertificateValidationResult Validate(X509Certificate2 certificate, X509Chain chain) { - const int requiredChainLength = 3; - if (!HasExpectedLength(chain, requiredChainLength)) + if (IsSelfSignedCertificate(chain)) { - return IncorrectChainLengthResult(certificate, requiredChainLength, chain.ChainElements.Count); + return SelfSignedErrorResult(certificate); } var detailedErrorInformation = chain.ChainStatus; @@ -154,30 +179,25 @@ private static SertifikatValideringsResultat ValidateCertificateChain(X509Certif var chainError = detailedErrorInformation.ElementAt(0).Status; return chainError == X509ChainStatusFlags.UntrustedRoot ? ValidResult(certificate) - : InvalidChainResult(certificate, detailedErrorInformation); + : InvalidChainResult(certificate, detailedErrorInformation); //We tolerate this 'UntrustedRoot' because it occurs when loading a root certificate from file, which is always done here. We trust the certificates as they are preloaded in library. default: return InvalidChainResult(certificate, detailedErrorInformation); } } - private static SertifikatValideringsResultat InvalidChainResult(X509Certificate2 certificate, params X509ChainStatus[] x509ChainStatuses) - { - return CreateSertifikatValideringsResultat(certificate, SertifikatValideringType.UgyldigKjede, $"har følgende feil i sertifikatkjeden: {GetPrettyChainErrorStatuses(x509ChainStatuses)}"); - } - - private static SertifikatValideringsResultat ValidResult(X509Certificate2 theCertificate) + private static CertificateValidationResult InvalidChainResult(X509Certificate2 certificate, params X509ChainStatus[] x509ChainStatuses) { - return CreateSertifikatValideringsResultat(theCertificate, SertifikatValideringType.Gyldig, "er et gyldig sertifikat."); + return new CertificateValidationResult(CertificateValidationType.InvalidChain, certificate.ToShortString($"har følgende feil i sertifikatkjeden: {GetPrettyChainErrorStatuses(x509ChainStatuses)}")); } - private static SertifikatValideringsResultat IncorrectChainLengthResult(X509Certificate2 certificate2, int requiredChainLength, int actualChainLength) + private static CertificateValidationResult ValidResult(X509Certificate2 certificate) { - return CreateSertifikatValideringsResultat(certificate2, SertifikatValideringType.UgyldigKjede, $"er ugyldig, fordi lengden på kjeden er {actualChainLength}, men skal være {requiredChainLength}. Dette skjer hvis sertifikatet er utstedt av en ukjent sertifikattilbyder eller er selvsignert."); + return new CertificateValidationResult(CertificateValidationType.Valid, certificate.ToShortString("er et gyldig sertifikat.")); } - private static SertifikatValideringsResultat CreateSertifikatValideringsResultat(X509Certificate2 certificate, SertifikatValideringType sertifikatValideringType, string description) + private static CertificateValidationResult SelfSignedErrorResult(X509Certificate2 certificate) { - return new SertifikatValideringsResultat(sertifikatValideringType, $"Sertifikat '{certificate.Info()}' {description}."); + return new CertificateValidationResult(CertificateValidationType.InvalidChain, certificate.ToShortString("er ugyldig, fordi lengden på kjeden er 1, noe som betyr at sertifikatet er selvsignert. Det må brukes et sertifikat utstedt av en gyldig sertifikatutsteder.")); } private static string GetPrettyChainErrorStatuses(X509ChainStatus[] chainStatuses) @@ -185,9 +205,10 @@ private static string GetPrettyChainErrorStatuses(X509ChainStatus[] chainStatuse return chainStatuses.Aggregate("", (result, curr) => $"{curr.Status}: {curr.StatusInformation}"); } - private static bool HasExpectedLength(X509Chain chain, int chainLength) + private static bool IsSelfSignedCertificate(X509Chain chain) { - return chain.ChainElements.Count == chainLength; + const int selfSignedChainLength = 1; + return chain.ChainElements.Count == selfSignedChainLength; } } } \ No newline at end of file diff --git a/Difi.Felles.Utility/CertificateValidationResult.cs b/Difi.Felles.Utility/CertificateValidationResult.cs new file mode 100755 index 0000000..14b4fdc --- /dev/null +++ b/Difi.Felles.Utility/CertificateValidationResult.cs @@ -0,0 +1,15 @@ +namespace Difi.Felles.Utility +{ + public class CertificateValidationResult + { + public CertificateValidationResult(CertificateValidationType type, string message) + { + Type = type; + Message = message; + } + + public CertificateValidationType Type { get; set; } + + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/Difi.Felles.Utility/CertificateValidationType.cs b/Difi.Felles.Utility/CertificateValidationType.cs new file mode 100755 index 0000000..f9a5ce2 --- /dev/null +++ b/Difi.Felles.Utility/CertificateValidationType.cs @@ -0,0 +1,9 @@ +namespace Difi.Felles.Utility +{ + public enum CertificateValidationType + { + Valid, + InvalidCertificate, + InvalidChain + } +} \ No newline at end of file diff --git a/Difi.Felles.Utility/CertificateValidator.cs b/Difi.Felles.Utility/CertificateValidator.cs index 7d97d9c..26d566b 100755 --- a/Difi.Felles.Utility/CertificateValidator.cs +++ b/Difi.Felles.Utility/CertificateValidator.cs @@ -8,23 +8,23 @@ public class CertificateValidator { public static bool IsValidCertificate(X509Certificate2 certificate, string certificateOrganizationNumber) { - return ValidateCertificate(certificate, certificateOrganizationNumber).Type == SertifikatValideringType.Gyldig; + return ValidateCertificate(certificate, certificateOrganizationNumber).Type == CertificateValidationType.Valid; } - public static SertifikatValideringsResultat ValidateCertificateAndChain(X509Certificate2 certificate, string certificateOrganizationNumber, X509Certificate2Collection chainCertificates) + public static CertificateValidationResult ValidateCertificateAndChain(X509Certificate2 certificate, string certificateOrganizationNumber, X509Certificate2Collection allowedChainCertificates) { var sertifikatValideringsResultat = ValidateCertificate(certificate, certificateOrganizationNumber); - if (sertifikatValideringsResultat.Type != SertifikatValideringType.Gyldig) + if (sertifikatValideringsResultat.Type != CertificateValidationType.Valid) { return sertifikatValideringsResultat; } - var certificateChainValidator = new CertificateChainValidator(chainCertificates); - return certificateChainValidator.ValidateCertificateChain(certificate); + var certificateChainValidator = new CertificateChainValidator(allowedChainCertificates); + return certificateChainValidator.Validate(certificate); } - public static SertifikatValideringsResultat ValidateCertificate(X509Certificate2 certificate, string certificateOrganizationNumber) + public static CertificateValidationResult ValidateCertificate(X509Certificate2 certificate, string certificateOrganizationNumber) { if (certificate == null) { @@ -49,42 +49,37 @@ public static SertifikatValideringsResultat ValidateCertificate(X509Certificate2 return ValidResult(certificate); } - private static SertifikatValideringsResultat NoCertificateResult() + private static CertificateValidationResult NoCertificateResult() { - return new SertifikatValideringsResultat(SertifikatValideringType.UgyldigSertifikat, $"Sertifikat var {null}!"); + return new CertificateValidationResult(CertificateValidationType.InvalidCertificate, "Sertifikat var null! Sjekk at sertifikatet blir lastet korrekt."); } - private static SertifikatValideringsResultat NotIssuedToOrganizationResult(string certificateOrganizationNumber) + private static CertificateValidationResult NotIssuedToOrganizationResult(string certificateOrganizationNumber) { - return new SertifikatValideringsResultat(SertifikatValideringType.UgyldigSertifikat, + return new CertificateValidationResult(CertificateValidationType.InvalidCertificate, $"Sertifikatet er ikke utstedt til organisasjonsnummer '{certificateOrganizationNumber}'. Dette vil skje om sertifikatet er utstedt til en annen virksomhet " + "eller hvis det ikke er et virksomhetssertifikat. Virksomhetssertifikat kan skaffes fra Buypass eller Commfides."); } - private static SertifikatValideringsResultat NotActivatedResult(X509Certificate2 certificate) + private static CertificateValidationResult NotActivatedResult(X509Certificate2 certificate) { - return CreateSertifikatValideringsResultat(certificate, - SertifikatValideringType.UgyldigSertifikat, - $"aktiveres ikke før {certificate.GetEffectiveDateString()}"); + return new CertificateValidationResult( + CertificateValidationType.InvalidCertificate, + certificate.ToShortString($"aktiveres ikke før {certificate.GetEffectiveDateString()}")); } - private static SertifikatValideringsResultat ExpiredResult(X509Certificate2 certificate) + private static CertificateValidationResult ExpiredResult(X509Certificate2 certificate) { - return CreateSertifikatValideringsResultat(certificate, - SertifikatValideringType.UgyldigSertifikat, - $"gikk ut {certificate.GetExpirationDateString()}."); + return new CertificateValidationResult( + CertificateValidationType.InvalidCertificate, + certificate.ToShortString($"gikk ut {certificate.GetExpirationDateString()}.")); } - private static SertifikatValideringsResultat ValidResult(X509Certificate2 certificate) + private static CertificateValidationResult ValidResult(X509Certificate2 certificate) { - return CreateSertifikatValideringsResultat(certificate, SertifikatValideringType.Gyldig, "er et gyldig sertifikat."); - } - - private static SertifikatValideringsResultat CreateSertifikatValideringsResultat(X509Certificate2 certificate, SertifikatValideringType sertifikatValideringType, string description) - { - return new SertifikatValideringsResultat( - sertifikatValideringType, - $"Sertifikat '{certificate.Info()}' {description}."); + return new CertificateValidationResult( + CertificateValidationType.Valid, + certificate.ToShortString("er et gyldig sertifikat.")); } private static bool IsIssuedToOrganizationNumber(X509Certificate certificate, string certificateOrganizationNumber) diff --git a/Difi.Felles.Utility/Difi.Felles.Utility.csproj b/Difi.Felles.Utility/Difi.Felles.Utility.csproj index 290648e..0477c36 100755 --- a/Difi.Felles.Utility/Difi.Felles.Utility.csproj +++ b/Difi.Felles.Utility/Difi.Felles.Utility.csproj @@ -48,8 +48,8 @@ Properties\SharedAssemblyInfo.cs - - + + diff --git a/Difi.Felles.Utility/Extensions/X509Certificate2Extensions.cs b/Difi.Felles.Utility/Extensions/X509Certificate2Extensions.cs index c4e0e0a..2b42d87 100755 --- a/Difi.Felles.Utility/Extensions/X509Certificate2Extensions.cs +++ b/Difi.Felles.Utility/Extensions/X509Certificate2Extensions.cs @@ -4,9 +4,9 @@ namespace Difi.Felles.Utility.Extensions { public static class X509Certificate2Extensions { - public static string Info(this X509Certificate2 certificate) + public static string ToShortString(this X509Certificate2 certificate, string extraInfo = "") { - return $"Subject: {certificate.Subject}, Thumbprint: {certificate.Thumbprint}"; + return $"Sertifikat med Subject '{certificate.Subject}' og Thumbprint '{certificate.Thumbprint}' {extraInfo}"; } } } diff --git a/Difi.Felles.Utility/SertifikatValideringType.cs b/Difi.Felles.Utility/SertifikatValideringType.cs deleted file mode 100755 index 7a02f87..0000000 --- a/Difi.Felles.Utility/SertifikatValideringType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Difi.Felles.Utility -{ - public enum SertifikatValideringType - { - Gyldig, - UgyldigSertifikat, - UgyldigKjede - } -} \ No newline at end of file diff --git a/Difi.Felles.Utility/SertifikatValideringsResultat.cs b/Difi.Felles.Utility/SertifikatValideringsResultat.cs deleted file mode 100755 index 3ecd932..0000000 --- a/Difi.Felles.Utility/SertifikatValideringsResultat.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace Difi.Felles.Utility -{ - public class SertifikatValideringsResultat - { - public SertifikatValideringsResultat(SertifikatValideringType type, string melding) - { - Type = type; - Melding = melding; - } - - public SertifikatValideringType Type { get; set; } - - public string Melding { get; set; } - } -} diff --git a/Difi.Felles.Utility/Utilities/CertificateChainUtility.cs b/Difi.Felles.Utility/Utilities/CertificateChainUtility.cs index 9731227..788f005 100755 --- a/Difi.Felles.Utility/Utilities/CertificateChainUtility.cs +++ b/Difi.Felles.Utility/Utilities/CertificateChainUtility.cs @@ -8,7 +8,7 @@ public static class CertificateChainUtility { private static readonly ResourceUtility ResourceUtility = new ResourceUtility("Difi.Felles.Utility.Resources.Certificates"); - public static X509Certificate2Collection FunksjoneltTestmiljøSertifikater() + public static X509Certificate2Collection TestCertificates() { var difiTestkjedesertifikater = new List { @@ -20,7 +20,7 @@ public static X509Certificate2Collection FunksjoneltTestmiljøSertifikater() return new X509Certificate2Collection(difiTestkjedesertifikater.ToArray()); } - public static X509Certificate2Collection ProduksjonsSertifikater() + public static X509Certificate2Collection ProductionCertificates() { var difiProduksjonssertifikater = new List { diff --git a/difi-felles-utility.sln b/difi-felles-utility.sln index c6c8f9e..d0d3522 100755 --- a/difi-felles-utility.sln +++ b/difi-felles-utility.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Difi.Felles.Utility", "Difi.Felles.Utility\Difi.Felles.Utility.csproj", "{7AB8D858-878F-4184-9557-995BE75DC635}" EndProject