diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index b7bac8c..dd78226 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,6 @@ == Changelog for the TameMyCerts Policy Module -=== 1.1.x.y (unreleased) +=== 1.1.432.1215 (Mar 10, 2022) * Change logic for allowed and disallowed patterns on SubjectRule directives. Now, for each defined "field" it is possible to specify how the expression will get treated (regular expression or CIDR notation), which allows for IP addresses to get verified if they are present in fields other that the iPAddress alternative name field. Existing policy files must be adjusted to the new logic. * Implement support for applying rules on process names used to create certificate requests for both online and offline certificate templates. diff --git a/TameMyCerts/AutoVersionIncrement.cs b/TameMyCerts/AutoVersionIncrement.cs index 90908d6..a77b2ab 100644 --- a/TameMyCerts/AutoVersionIncrement.cs +++ b/TameMyCerts/AutoVersionIncrement.cs @@ -9,5 +9,5 @@ // Build Number // Revision -[assembly: AssemblyVersion("1.1.413.979")] -[assembly: AssemblyFileVersion("1.1.413.979")] +[assembly: AssemblyVersion("1.1.432.1215")] +[assembly: AssemblyFileVersion("1.1.432.1215")] diff --git a/TameMyCerts/CertificateRequestValidator.cs b/TameMyCerts/CertificateRequestValidator.cs index ec518e0..9d833f1 100644 --- a/TameMyCerts/CertificateRequestValidator.cs +++ b/TameMyCerts/CertificateRequestValidator.cs @@ -568,7 +568,7 @@ private static CertificateRequestVerificationResult VerifySubject( if (VerifyPattern(subjectItem.Value, pattern)) { matchFound = true; - break; + break; } } @@ -587,11 +587,11 @@ private static CertificateRequestVerificationResult VerifySubject( foreach (var pattern in policyItem.Patterns.Where(x => x.Action.Equals("Deny"))) { - if (VerifyPattern(subjectItem.Value, pattern)) + if (VerifyPattern(subjectItem.Value, pattern, true)) { result.Success = false; - result.Description.Add(string.Format(LocalizedStrings.ReqVal_Disallow_Match, subjectItem.Value, - subjectItem.Key)); + result.Description.Add(string.Format(LocalizedStrings.ReqVal_Disallow_Match, + subjectItem.Value, pattern.Expression, subjectItem.Key)); return result; } @@ -604,7 +604,7 @@ private static CertificateRequestVerificationResult VerifySubject( return result; } - private static bool VerifyPattern (string term, Pattern pattern) + private static bool VerifyPattern(string term, Pattern pattern, bool matchOnError = false) { try { @@ -633,7 +633,11 @@ private static bool VerifyPattern (string term, Pattern pattern) } catch { - // + // This ensures that failing to interpret the pattern will result in matching as a denied one + if (matchOnError) + { + return true; + } } return false; diff --git a/TameMyCerts/LocalizedStrings.Designer.cs b/TameMyCerts/LocalizedStrings.Designer.cs index f9bb99d..47f8400 100644 --- a/TameMyCerts/LocalizedStrings.Designer.cs +++ b/TameMyCerts/LocalizedStrings.Designer.cs @@ -210,7 +210,7 @@ internal static string ReqVal_Crypto_Provider_Unknown { } /// - /// Looks up a localized string similar to The value "{0}" does match a pattern that is disallowed for the {1} field.. + /// Looks up a localized string similar to The value "{0}" does match expression "{1}" which is disallowed for the {2} field.. /// internal static string ReqVal_Disallow_Match { get { diff --git a/TameMyCerts/LocalizedStrings.resx b/TameMyCerts/LocalizedStrings.resx index 8f1df9c..b039038 100644 --- a/TameMyCerts/LocalizedStrings.resx +++ b/TameMyCerts/LocalizedStrings.resx @@ -204,7 +204,7 @@ The value "{0}" does not match any of the allowed patterns for the {1} field. - The value "{0}" does match a pattern that is disallowed for the {1} field. + The value "{0}" does match expression "{1}" which is disallowed for the {2} field. unknown diff --git a/TameMyCerts/Policy.cs b/TameMyCerts/Policy.cs index d726c73..f161115 100644 --- a/TameMyCerts/Policy.cs +++ b/TameMyCerts/Policy.cs @@ -162,8 +162,7 @@ public int VerifyRequest(string strConfig, int context, int bNewRequest, int fla // Set custom start date if requested and permitted if ((_editFlags & CertSrv.EDITF_ATTRIBUTEENDDATE) == CertSrv.EDITF_ATTRIBUTEENDDATE) { - if (requestAttributeList != null && - requestAttributeList.Any( + if (requestAttributeList.Any( x => x.Key.Equals("StartDate", StringComparison.InvariantCultureIgnoreCase))) { if (DateTimeOffset.TryParseExact( diff --git a/TameMyCerts/make_release.cmd b/TameMyCerts/make_release.cmd index 2979e3e..c07ddb4 100644 --- a/TameMyCerts/make_release.cmd +++ b/TameMyCerts/make_release.cmd @@ -18,7 +18,7 @@ TameMyCerts.csproj ^ /p:TransformOutOfDateOnly=false copy install.ps1 bin\Release\ -copy Sample_*.xml bin\Debug\ +copy Sample_*.xml bin\Release\ copy ..\CHANGELOG.adoc bin\Release\ copy ..\README.adoc bin\Release\ copy ..\LICENSE bin\Release\ diff --git a/UnitTests/RequestValidatorTests.cs b/UnitTests/RequestValidatorTests.cs index e5630a3..3338454 100644 --- a/UnitTests/RequestValidatorTests.cs +++ b/UnitTests/RequestValidatorTests.cs @@ -853,6 +853,52 @@ public void Test_RSA_ValidCommonName_InvalidSan4() Assert.IsFalse(validationResult.Success); } + [TestMethod] + public void Test_RSA_ValidCommonName_InvalidSan5() + { + // 2048 Bit RSA Key + // CN=intranet.adcslabor.de + // dnsName=web1.adcslabor.de,web2.adcslabor.de,web3.adcslabor.de,web4.adcslabor.de,web5.adcslabor.de,web6.adcslabor.de,web7.pkilabor.de,web8.adcslabor.de,web9.adcslabor.de,web10.adcslabor.de + // Should fail because unallowed domain in web7 request + const string request = + "-----BEGIN NEW CERTIFICATE REQUEST-----\n" + + "MIIFQTCCA6kCAQAwIDEeMBwGA1UEAxMVaW50cmFuZXQuYWRjc2xhYm9yLmRlMIIB\n" + + "ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArXgJYDmOKoK+GJ5AhPzYqBgi\n" + + "ROXPhhxnriC/ImMF+FrQeTwAyVPS5zEAtuxYxFR9Kg/W7ob0qW6zoyKWkNxjzimp\n" + + "DrJGX2M/g8PSyNnbExFFz6FiSZu0hM976oWRdzO3bBDyaWnuef8SM0YS9EWAzhOd\n" + + "Yi16eboyRdAmi2nbwpVSG+idAz4R5LNAyGvl71PHHE0U+T3SccZdY81grGENXtNO\n" + + "UOZ8Mb+5b5tNZLxIPsBdR24bvu3eNjQQmfzJcTjab0In091QRagX3cV7XOWN7C3f\n" + + "kL0g0PePwJ3ILI6olqS1FpCKGb3PDKW/MCI/ekzBUItA+n4Kp+T+fZK//OmKBJpK\n" + + "XI+bUjSKBcJIeAyvziceD/SgjQwRrH17L9ETcaM1Vs22cKLmdFrl0bCi8EEfyzzr\n" + + "vBCJUKB9zEUYp5oK2kUmQIq+HBeLA1lyPz52fVb2+SeX0BWl6D6VZzf+mNdrDRq2\n" + + "mMHzjBoU0wbLMtYVX8bH7c573aq2rLTWw4ILvtFdAgMBAAGgggHaMBwGCisGAQQB\n" + + "gjcNAgMxDhYMMTAuMC4xOTA0NC4yMD4GCSsGAQQBgjcVFDExMC8CAQUMCkxBUFRP\n" + + "UC1VV0UMDkxBUFRPUC1VV0VcdXdlDA5wb3dlcnNoZWxsLmV4ZTBmBgorBgEEAYI3\n" + + "DQICMVgwVgIBAB5OAE0AaQBjAHIAbwBzAG8AZgB0ACAAUwBvAGYAdAB3AGEAcgBl\n" + + "ACAASwBlAHkAIABTAHQAbwByAGEAZwBlACAAUAByAG8AdgBpAGQAZQByAwEAMIIB\n" + + "EAYJKoZIhvcNAQkOMYIBATCB/jAOBgNVHQ8BAf8EBAMCB4AwgcwGA1UdEQEB/wSB\n" + + "wTCBvoIRd2ViMS5hZGNzbGFib3IuZGWCEXdlYjIuYWRjc2xhYm9yLmRlghF3ZWIz\n" + + "LmFkY3NsYWJvci5kZYIRd2ViNC5hZGNzbGFib3IuZGWCEXdlYjUuYWRjc2xhYm9y\n" + + "LmRlghF3ZWI2LmFkY3NsYWJvci5kZYIQd2ViNy5wa2lsYWJvci5kZYIRd2ViOC5h\n" + + "ZGNzbGFib3IuZGWCEXdlYjkuYWRjc2xhYm9yLmRlghJ3ZWIxMC5hZGNzbGFib3Iu\n" + + "ZGUwHQYDVR0OBBYEFLHzMISFNmmMU/xchafRVXOY1GnwMA0GCSqGSIb3DQEBCwUA\n" + + "A4IBgQBAX2dAWlfNd+9KRS06QvNFLKfaRrRiYIPVVe5K+wevkgNquV5Sf6quVX64\n" + + "xkHpAUU9GWB4CFrwXE0KbouBozLhKvamjg1Ndl7ZxGolnCGfPqReVVpKJ9WViGrY\n" + + "SxqMMvX+jJY1L/Res5SwnboiNIRYS3z/hoQiMs9dqvzR1gs92ygIHxhDNroYd1O8\n" + + "9gIZ7TGnV07r4WWut6GLA9ljDPPsx6nj1kOB4yQFNHCfrrzcUXpThXdhL1nrOIJY\n" + + "2px38RuAPHh47AKP17uTwEvkdIX5hh0g8mEdyTqzoTpJfkl49Q4eCRWhJYvSvWqm\n" + + "vWvQWzxyN7rFyonbOya6uU8M4uhLm4hKkfscC4KUtukfIli3X6KxPupEEmbFUXZZ\n" + + "2GZLqPeJ1xiOtsglTQ+uYNvwelQk+B8fPgX0ouvduEeJldQ48I8+T4Ni9wUmtm9H\n" + + "B5takWnKYdzvkFi5cEPGpK+Qe08vN5Lg7w9QK0/8vJfk6hvc/mk2qnECvOsJQuug\n" + + "gIECro4=\n" + + "-----END NEW CERTIFICATE REQUEST-----"; + + var validationResult = _requestValidator.VerifyRequest(request, _requestPolicyRsa, _templateInfo); + Console.WriteLine(string.Join("\n", validationResult.Description)); + + Assert.IsFalse(validationResult.Success); + } + [TestMethod] public void Test_RSA_InvalidCommonName_noSan1() {