1717package org .springframework .security .web .authentication .preauth .x509 ;
1818
1919import java .security .cert .X509Certificate ;
20- import java .util .regex .Matcher ;
21- import java .util .regex .Pattern ;
20+ import java .util .List ;
2221
22+ import javax .naming .InvalidNameException ;
23+ import javax .naming .ldap .LdapName ;
24+ import javax .naming .ldap .Rdn ;
2325import javax .security .auth .x500 .X500Principal ;
2426
2527import org .apache .commons .logging .Log ;
@@ -47,14 +49,13 @@ public final class SubjectX500PrincipalExtractor implements X509PrincipalExtract
4749
4850 private final Log logger = LogFactory .getLog (getClass ());
4951
50- private static final Pattern EMAIL_SUBJECT_DN_PATTERN = Pattern .compile ("OID.1.2.840.113549.1.9.1=(.*?)(?:,|$)" ,
51- Pattern .CASE_INSENSITIVE );
52+ private static final String EMAIL_SUBJECT_DN_TYPE = "OID.1.2.840.113549.1.9.1" ;
5253
53- private static final Pattern CN_SUBJECT_DN_PATTERN = Pattern . compile ( "CN=(.*?)(?:,|$)" , Pattern . CASE_INSENSITIVE ) ;
54+ private static final String CN_SUBJECT_DN_TYPE = "CN" ;
5455
5556 private MessageSourceAccessor messages = SpringSecurityMessageSource .getAccessor ();
5657
57- private Pattern subjectDnPattern = CN_SUBJECT_DN_PATTERN ;
58+ private String subjectDnType = CN_SUBJECT_DN_TYPE ;
5859
5960 private String x500PrincipalFormat = X500Principal .RFC2253 ;
6061
@@ -64,16 +65,31 @@ public Object extractPrincipal(X509Certificate clientCert) {
6465 X500Principal principal = clientCert .getSubjectX500Principal ();
6566 String subjectDN = principal .getName (this .x500PrincipalFormat );
6667 this .logger .debug (LogMessage .format ("Subject DN is '%s'" , subjectDN ));
67- Matcher matcher = this .subjectDnPattern .matcher (subjectDN );
68- if (!matcher .find ()) {
69- throw new BadCredentialsException (this .messages .getMessage ("SubjectX500PrincipalExtractor.noMatching" ,
70- new Object [] { subjectDN }, "No matching pattern was found in subject DN: {0}" ));
71- }
72- String principalName = matcher .group (1 );
68+ String principalName = getSubject (subjectDN );
7369 this .logger .debug (LogMessage .format ("Extracted Principal name is '%s'" , principalName ));
7470 return principalName ;
7571 }
7672
73+ private List <Rdn > getDns (String subjectDn ) {
74+ try {
75+ return new LdapName (subjectDn ).getRdns ();
76+ }
77+ catch (InvalidNameException ex ) {
78+ throw new BadCredentialsException ("Failed to parse client certificate" , ex );
79+ }
80+ }
81+
82+ private String getSubject (String subjectDn ) {
83+ for (Rdn rdn : getDns (subjectDn )) {
84+ String type = rdn .getType ();
85+ if (this .subjectDnType .equals (type )) {
86+ return String .valueOf (rdn .getValue ());
87+ }
88+ }
89+ throw new BadCredentialsException (this .messages .getMessage ("SubjectX500PrincipalExtractor.noMatching" ,
90+ new Object [] { subjectDn }, "No matching pattern was found in subject DN: {0}" ));
91+ }
92+
7793 @ Override
7894 public void setMessageSource (MessageSource messageSource ) {
7995 Assert .notNull (messageSource , "messageSource cannot be null" );
@@ -104,11 +120,11 @@ public void setMessageSource(MessageSource messageSource) {
104120 */
105121 public void setExtractPrincipalNameFromEmail (boolean extractPrincipalNameFromEmail ) {
106122 if (extractPrincipalNameFromEmail ) {
107- this .subjectDnPattern = EMAIL_SUBJECT_DN_PATTERN ;
123+ this .subjectDnType = EMAIL_SUBJECT_DN_TYPE ;
108124 this .x500PrincipalFormat = X500Principal .RFC1779 ;
109125 }
110126 else {
111- this .subjectDnPattern = CN_SUBJECT_DN_PATTERN ;
127+ this .subjectDnType = CN_SUBJECT_DN_TYPE ;
112128 this .x500PrincipalFormat = X500Principal .RFC2253 ;
113129 }
114130 }
0 commit comments