1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.providers.x509.populator;
17
18 import org.acegisecurity.AcegiMessageSource;
19 import org.acegisecurity.AuthenticationException;
20 import org.acegisecurity.BadCredentialsException;
21 import org.acegisecurity.AuthenticationServiceException;
22
23 import org.acegisecurity.providers.x509.X509AuthoritiesPopulator;
24
25 import org.acegisecurity.userdetails.UserDetails;
26 import org.acegisecurity.userdetails.UserDetailsService;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.oro.text.regex.MalformedPatternException;
32 import org.apache.oro.text.regex.MatchResult;
33 import org.apache.oro.text.regex.Pattern;
34 import org.apache.oro.text.regex.PatternMatcher;
35 import org.apache.oro.text.regex.Perl5Compiler;
36 import org.apache.oro.text.regex.Perl5Matcher;
37
38 import org.springframework.beans.factory.InitializingBean;
39
40 import org.springframework.context.MessageSource;
41 import org.springframework.context.MessageSourceAware;
42 import org.springframework.context.support.MessageSourceAccessor;
43
44 import org.springframework.util.Assert;
45
46 import java.security.cert.X509Certificate;
47
48
49
50
51
52
53
54
55 public class DaoX509AuthoritiesPopulator implements X509AuthoritiesPopulator, InitializingBean, MessageSourceAware {
56
57
58 private static final Log logger = LogFactory.getLog(DaoX509AuthoritiesPopulator.class);
59
60
61
62 protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
63 private Pattern subjectDNPattern;
64 private String subjectDNRegex = "CN=(.*?),";
65 private UserDetailsService userDetailsService;
66
67
68
69 public void afterPropertiesSet() throws Exception {
70 Assert.notNull(userDetailsService, "An authenticationDao must be set");
71 Assert.notNull(this.messages, "A message source must be set");
72
73 Perl5Compiler compiler = new Perl5Compiler();
74
75 try {
76 subjectDNPattern = compiler.compile(subjectDNRegex,
77 Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK);
78 } catch (MalformedPatternException mpe) {
79 throw new IllegalArgumentException("Malformed regular expression: " + subjectDNRegex);
80 }
81 }
82
83 public UserDetails getUserDetails(X509Certificate clientCert) throws AuthenticationException {
84 String subjectDN = clientCert.getSubjectDN().getName();
85 PatternMatcher matcher = new Perl5Matcher();
86
87 if (!matcher.contains(subjectDN, subjectDNPattern)) {
88 throw new BadCredentialsException(messages.getMessage("DaoX509AuthoritiesPopulator.noMatching",
89 new Object[] {subjectDN}, "No matching pattern was found in subjectDN: {0}"));
90 }
91
92 MatchResult match = matcher.getMatch();
93
94 if (match.groups() != 2) {
95 throw new IllegalArgumentException("Regular expression must contain a single group ");
96 }
97
98 String userName = match.group(1);
99
100 UserDetails user = this.userDetailsService.loadUserByUsername(userName);
101
102 if (user == null) {
103 throw new AuthenticationServiceException(
104 "UserDetailsService returned null, which is an interface contract violation");
105 }
106
107 return user;
108 }
109
110 public void setMessageSource(MessageSource messageSource) {
111 this.messages = new MessageSourceAccessor(messageSource);
112 }
113
114
115
116
117
118
119
120
121
122
123
124 public void setSubjectDNRegex(String subjectDNRegex) {
125 this.subjectDNRegex = subjectDNRegex;
126 }
127
128 public void setUserDetailsService(UserDetailsService userDetailsService) {
129 this.userDetailsService = userDetailsService;
130 }
131 }