mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-04-21 16:30:27 +00:00
Merge branch '7.0.x' into 7.1.x
This commit is contained in:
commit
d96926a375
@ -17,9 +17,11 @@
|
||||
package org.springframework.security.web.authentication.preauth.x509;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@ -47,14 +49,13 @@ public final class SubjectX500PrincipalExtractor implements X509PrincipalExtract
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private static final Pattern EMAIL_SUBJECT_DN_PATTERN = Pattern.compile("OID.1.2.840.113549.1.9.1=(.*?)(?:,|$)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static final String EMAIL_SUBJECT_DN_TYPE = "OID.1.2.840.113549.1.9.1";
|
||||
|
||||
private static final Pattern CN_SUBJECT_DN_PATTERN = Pattern.compile("CN=(.*?)(?:,|$)", Pattern.CASE_INSENSITIVE);
|
||||
private static final String CN_SUBJECT_DN_TYPE = "CN";
|
||||
|
||||
private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
|
||||
private Pattern subjectDnPattern = CN_SUBJECT_DN_PATTERN;
|
||||
private String subjectDnType = CN_SUBJECT_DN_TYPE;
|
||||
|
||||
private String x500PrincipalFormat = X500Principal.RFC2253;
|
||||
|
||||
@ -64,16 +65,31 @@ public final class SubjectX500PrincipalExtractor implements X509PrincipalExtract
|
||||
X500Principal principal = clientCert.getSubjectX500Principal();
|
||||
String subjectDN = principal.getName(this.x500PrincipalFormat);
|
||||
this.logger.debug(LogMessage.format("Subject DN is '%s'", subjectDN));
|
||||
Matcher matcher = this.subjectDnPattern.matcher(subjectDN);
|
||||
if (!matcher.find()) {
|
||||
throw new BadCredentialsException(this.messages.getMessage("SubjectX500PrincipalExtractor.noMatching",
|
||||
new Object[] { subjectDN }, "No matching pattern was found in subject DN: {0}"));
|
||||
}
|
||||
String principalName = matcher.group(1);
|
||||
String principalName = getSubject(subjectDN);
|
||||
this.logger.debug(LogMessage.format("Extracted Principal name is '%s'", principalName));
|
||||
return principalName;
|
||||
}
|
||||
|
||||
private List<Rdn> getDns(String subjectDn) {
|
||||
try {
|
||||
return new LdapName(subjectDn).getRdns();
|
||||
}
|
||||
catch (InvalidNameException ex) {
|
||||
throw new BadCredentialsException("Failed to parse client certificate", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private String getSubject(String subjectDn) {
|
||||
for (Rdn rdn : getDns(subjectDn)) {
|
||||
String type = rdn.getType();
|
||||
if (this.subjectDnType.equals(type)) {
|
||||
return String.valueOf(rdn.getValue());
|
||||
}
|
||||
}
|
||||
throw new BadCredentialsException(this.messages.getMessage("SubjectX500PrincipalExtractor.noMatching",
|
||||
new Object[] { subjectDn }, "No matching pattern was found in subject DN: {0}"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessageSource(MessageSource messageSource) {
|
||||
Assert.notNull(messageSource, "messageSource cannot be null");
|
||||
@ -104,11 +120,11 @@ public final class SubjectX500PrincipalExtractor implements X509PrincipalExtract
|
||||
*/
|
||||
public void setExtractPrincipalNameFromEmail(boolean extractPrincipalNameFromEmail) {
|
||||
if (extractPrincipalNameFromEmail) {
|
||||
this.subjectDnPattern = EMAIL_SUBJECT_DN_PATTERN;
|
||||
this.subjectDnType = EMAIL_SUBJECT_DN_TYPE;
|
||||
this.x500PrincipalFormat = X500Principal.RFC1779;
|
||||
}
|
||||
else {
|
||||
this.subjectDnPattern = CN_SUBJECT_DN_PATTERN;
|
||||
this.subjectDnType = CN_SUBJECT_DN_TYPE;
|
||||
this.x500PrincipalFormat = X500Principal.RFC2253;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,22 @@ public class SubjectX500PrincipalExtractorTests {
|
||||
assertThat(principal).isEqualTo("Duke");
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractWhenDnEmbeddedInCnThenExtractsPrincipalName() throws Exception {
|
||||
Object principal = this.extractor.extractPrincipal(X509TestUtils.buildTestCertficateWithEmbeddedDn());
|
||||
|
||||
assertThat(principal).isEqualTo("luke");
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractWhenEmailDnEmbeddedInCnThenExtractsEmail() throws Exception {
|
||||
this.extractor.setExtractPrincipalNameFromEmail(true);
|
||||
|
||||
Object principal = this.extractor.extractPrincipal(X509TestUtils.buildTestCertficateWithEmbeddedEmailDn());
|
||||
|
||||
assertThat(principal).isEqualTo("luke@monkeymachine");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setMessageSourceWhenNullThenThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.extractor.setMessageSource(null));
|
||||
|
||||
@ -135,4 +135,54 @@ public final class X509TestUtils {
|
||||
return (X509Certificate) cf.generateCertificate(in);
|
||||
}
|
||||
|
||||
public static X509Certificate buildTestCertficateWithEmbeddedDn() throws Exception {
|
||||
String cert = "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIDDTCCAfWgAwIBAgIJANSyvk4gJhqPMA0GCSqGSIb3DQEBCwUAMEYxDTALBgNV\n"
|
||||
+ "BAMMBGx1a2UxETAPBgNVBAsMCENOPWR1a2UsMRUwEwYDVQQKDAxFeGFtcGxlIENv\n"
|
||||
+ "cnAxCzAJBgNVBAYTAlVTMB4XDTI2MDEwNDE5MjY0N1oXDTI3MDEwNTE5MjY0N1ow\n"
|
||||
+ "RjENMAsGA1UEAwwEbHVrZTERMA8GA1UECwwIQ049ZHVrZSwxFTATBgNVBAoMDEV4\n"
|
||||
+ "YW1wbGUgQ29ycDELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n"
|
||||
+ "ggEKAoIBAQDU9fY74nEFbBKfIef7CK02J/BJb42sIF9kD8eHN5OvEwLQBeTh30it\n"
|
||||
+ "E7LLalXyOXeUFkPe1N1ZhGdVak9udsIqULSvQaWqTbN+IrAGklZAxuXYTC1GbhMF\n"
|
||||
+ "AkGWWM55J2SNqVGQaHzZUn6VPxWaDft6nZR0DxuvXMYM5kVG6VErdB3ygGUv8cjQ\n"
|
||||
+ "QBKAYpsZeRldnauRPt2dImmGTagvSuJVyr8X/AioE2Rl0guii456AKw+QSvRiZ+g\n"
|
||||
+ "w08Y8C9nDyzQmurqpdYYkp0X+4yqm1iVowMX+tSPvHnlqJdvVzaW2b0yRzrrT6ao\n"
|
||||
+ "UCgw25slR1P1IcyzqPKWQIoQRnYIaX1bAgMBAAEwDQYJKoZIhvcNAQELBQADggEB\n"
|
||||
+ "AIos+nr8DFM6bAt9AI/79O/12hcN7gVv4F3P4Vz6NRRkkvsb9WMN8fLLDEsEJ/BQ\n"
|
||||
+ "eQkAVnhlmAe++vrqy8OTHoQ7F5C3K0zrr19NLNoyNFTkXkFgnm4ZhYinSbusuIb7\n"
|
||||
+ "LPYoyCnEEiMdl0VMWWSWcOvZpipbvTtH3CiVxTqXLjFFNraEAyUN50kXjo/zuHpK\n"
|
||||
+ "HzTS1BAu0li9GdV3Da2ELdDx90zaUym7dDIejY4YUlXYIJ5UUYS61fqtgOHGLLdb\n"
|
||||
+ "UXGAr5gqEe7OrQ9D4ebg9w5ciTb7g1H2CmirjTf/rkii8AojmsGFKIfGVe3gY6EB\n" + "o9eF5FV9V9leo5yLo25ev08=\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(cert.getBytes());
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
return (X509Certificate) cf.generateCertificate(in);
|
||||
}
|
||||
|
||||
public static X509Certificate buildTestCertficateWithEmbeddedEmailDn() throws Exception {
|
||||
String cert = "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIDfDCCAmSgAwIBAgIIXHoOUFeZ29MwDQYJKoZIhvcNAQELBQAwfjEhMB8GCSqG\n"
|
||||
+ "SIb3DQEJARYSbHVrZUBtb25rZXltYWNoaW5lMTUwMwYDVQQLDCxPSUQuMS4yLjg0\n"
|
||||
+ "MC4xMTM1NDkuMS45LjE9ZHVrZUBnb3JpbGxhZ2FkZ2V0LDEVMBMGA1UECgwMRXhh\n"
|
||||
+ "bXBsZSBDb3JwMQswCQYDVQQGEwJVUzAeFw0yNjAxMDQxOTMxMDhaFw0yNzAxMDUx\n"
|
||||
+ "OTMxMDhaMH4xITAfBgkqhkiG9w0BCQEWEmx1a2VAbW9ua2V5bWFjaGluZTE1MDMG\n"
|
||||
+ "A1UECwwsT0lELjEuMi44NDAuMTEzNTQ5LjEuOS4xPWR1a2VAZ29yaWxsYWdhZGdl\n"
|
||||
+ "dCwxFTATBgNVBAoMDEV4YW1wbGUgQ29ycDELMAkGA1UEBhMCVVMwggEiMA0GCSqG\n"
|
||||
+ "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBuIQWnj+uvvG+4ZIyFMs4dSbiBavubCmC\n"
|
||||
+ "hudrHr93hP19QbPulbHRTVCUqEi8efvq+J9jmMdPd7tziuDX02PeG9uljp9+c5Ir\n"
|
||||
+ "pw9/oMoTRkF7K4PK1JxLN4tcgxjxVA4QkS+MjKLPeHrYyGCjKspcHbi+zBiQ9Xqp\n"
|
||||
+ "yHWq6N5XPd6mEj2gh0zamnsJCeUCOX4SJbcp3MFtcYzhguHAeVhy9Jv+EAMJejDn\n"
|
||||
+ "YIZmMUdP6Ykf2zTzs/4L3bRZb0oS5WvfeRdJB6SKg8mNO/jdGX87krSio//cRdDy\n"
|
||||
+ "TGQK+YCVDf8GyLLavYZW56AJbZxL3MWgHYilQjj4p+Kw/PWpaBVvAgMBAAEwDQYJ\n"
|
||||
+ "KoZIhvcNAQELBQADggEBAKVTMIo8JO0H0HRrpsEDP17E2pnfMJV4g70BwClUMMek\n"
|
||||
+ "wNIWZn+6XPR8oObzzjnVWXjrovMkmmyFk0vWIpF68MPyiQ++5fwdzOZiQtUP177n\n"
|
||||
+ "9ulAtLoIJld3olGeL9VsCZGp3J2PqiDe613zd+bkSUG1lQYC2awozWqJEdvwJJtf\n"
|
||||
+ "j9nlhyMsARKEEu3tFGJsCHST3XhbhFKOraf/GZ21xW650R7ap0ZNaEiB16M2a5Oe\n"
|
||||
+ "WXasgUukIo82Z8+yK4IITeCcr0aA1fJxwhU8J6qfYWloaoirSYj487HRnPPv3X/b\n"
|
||||
+ "RxZynIjtGKygT6T1dRaWennmoitqfprJnEO2tlhLwP0=\n" + "-----END CERTIFICATE-----";
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(cert.getBytes());
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
return (X509Certificate) cf.generateCertificate(in);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user