diff --git a/src/main/java/com/adyen/terminal/security/TerminalCommonNameValidator.java b/src/main/java/com/adyen/terminal/security/TerminalCommonNameValidator.java index e78ef4b89..97aa33c2e 100644 --- a/src/main/java/com/adyen/terminal/security/TerminalCommonNameValidator.java +++ b/src/main/java/com/adyen/terminal/security/TerminalCommonNameValidator.java @@ -26,36 +26,63 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** Validates the Common Name of a terminal API certificate. */ public final class TerminalCommonNameValidator { - private static final String ENVIRONMENT_WILDCARD = "{ENVIRONMENT}"; - private static final String TERMINAL_API_CN_REGEX = - "[a-zA-Z0-9]{3,}-[0-9]{9,15}\\." + ENVIRONMENT_WILDCARD + "\\.terminal\\.adyen\\.com"; - private static final String TERMINAL_API_LEGACY_CN = - "legacy-terminal-certificate." + ENVIRONMENT_WILDCARD + ".terminal.adyen.com"; + // Precompiled regex for Terminal API CN format + private static final Pattern TERMINAL_API_CN_TEST = + Pattern.compile("[a-zA-Z0-9]{3,}-[a-zA-Z0-9]{9,15}\\.test\\.terminal\\.adyen\\.com"); + private static final Pattern TERMINAL_API_CN_LIVE = + Pattern.compile("[a-zA-Z0-9]{3,}-[a-zA-Z0-9]{9,15}\\.live\\.terminal\\.adyen\\.com"); + + // Exact strings for legacy format (no regex needed) + private static final String TERMINAL_API_LEGACY_TEST = + "legacy-terminal-certificate.test.terminal.adyen.com"; + private static final String TERMINAL_API_LEGACY_LIVE = + "legacy-terminal-certificate.live.terminal.adyen.com"; + + // Regex to extract CN from subject string + private static final Pattern SUBJECT_ATTRIBUTE_PATTERN = + Pattern.compile("(?:^|,\\s?)([A-Z]+)=((?:\"[^\"]+\")|[^,]+)"); private TerminalCommonNameValidator() {} + /** + * Validates the Common Name of the given {@link X509Certificate} for the given {@link + * Environment}. + * + * @param certificate the {@link X509Certificate} to validate. + * @param environment the {@link Environment}. + * @return true if the Common Name is valid, false otherwise. + */ public static boolean validateCertificate(X509Certificate certificate, Environment environment) { - String environmentName = environment.name().toLowerCase(); String name = certificate.getSubjectX500Principal().getName(); - String patternRegex = "(?:^|,\\s?)(?:([A-Z]+)=(\"(?:[^\"]|\"\")+\"|[^,]+))+"; - Pattern pattern = Pattern.compile(patternRegex); - Matcher matcher = pattern.matcher(name); - boolean valid = false; - while (matcher.find() && !valid) { + Matcher matcher = SUBJECT_ATTRIBUTE_PATTERN.matcher(name); + + while (matcher.find()) { String groupName = matcher.group(1); if ("CN".equals(groupName)) { String commonName = matcher.group(2); - valid = - commonName != null - && (commonName.matches( - TERMINAL_API_CN_REGEX.replace(ENVIRONMENT_WILDCARD, environmentName)) - || commonName.equals( - TERMINAL_API_LEGACY_CN.replace(ENVIRONMENT_WILDCARD, environmentName))); + return isValidCommonName(commonName, environment); } } + return false; + } - return valid; + private static boolean isValidCommonName(String commonName, Environment environment) { + if (commonName == null) { + return false; + } + + switch (environment) { + case LIVE: + return TERMINAL_API_CN_LIVE.matcher(commonName).matches() + || TERMINAL_API_LEGACY_LIVE.equals(commonName); + case TEST: + return TERMINAL_API_CN_TEST.matcher(commonName).matches() + || TERMINAL_API_LEGACY_TEST.equals(commonName); + default: + return false; + } } } diff --git a/src/test/java/com/adyen/terminal/security/TerminalCommonNameValidatorTest.java b/src/test/java/com/adyen/terminal/security/TerminalCommonNameValidatorTest.java index 1e6bc7a07..84e86bd38 100644 --- a/src/test/java/com/adyen/terminal/security/TerminalCommonNameValidatorTest.java +++ b/src/test/java/com/adyen/terminal/security/TerminalCommonNameValidatorTest.java @@ -45,6 +45,11 @@ public static Collection data() { return Arrays.asList( new Object[][] { // Valid CNs and environment + { + "EMAILADDRESS=mock@adyen.com, CN=TG300-G10M257M70004.test.terminal.adyen.com, OU=Mock, O=Mock, L=Mock, ST=MO, C=MO", + Environment.TEST, + true + }, { "EMAILADDRESS=mock@adyen.com, CN=legacy-terminal-certificate.test.terminal.adyen.com, OU=Mock, O=Mock, L=Mock, ST=MO, C=MO", Environment.TEST,