1
2
3
4
5
6
7
8
9
10
11
12
13
14 package waffle.apache;
15
16 import java.io.IOException;
17 import java.security.Principal;
18 import java.util.Arrays;
19 import java.util.LinkedHashSet;
20 import java.util.Locale;
21 import java.util.Set;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletResponse;
25
26 import org.apache.catalina.authenticator.AuthenticatorBase;
27 import org.apache.catalina.connector.Request;
28 import org.slf4j.Logger;
29
30 import waffle.windows.auth.IWindowsAuthProvider;
31 import waffle.windows.auth.IWindowsIdentity;
32 import waffle.windows.auth.PrincipalFormat;
33 import waffle.windows.auth.impl.WindowsAuthProviderImpl;
34
35
36
37
38
39
40 abstract class WaffleAuthenticatorBase extends AuthenticatorBase {
41
42
43 private static final Set<String> SUPPORTED_PROTOCOLS = new LinkedHashSet<String>(Arrays.asList("Negotiate", "NTLM"));
44
45
46 protected String info;
47
48
49 protected Logger log;
50
51
52 protected PrincipalFormat principalFormat = PrincipalFormat.FQN;
53
54
55 protected PrincipalFormat roleFormat = PrincipalFormat.FQN;
56
57
58 protected boolean allowGuestLogin = true;
59
60
61 protected Set<String> protocols = WaffleAuthenticatorBase.SUPPORTED_PROTOCOLS;
62
63
64 protected IWindowsAuthProvider auth = new WindowsAuthProviderImpl();
65
66
67
68
69
70
71 public IWindowsAuthProvider getAuth() {
72 return this.auth;
73 }
74
75
76
77
78
79
80
81 public void setAuth(final IWindowsAuthProvider provider) {
82 this.auth = provider;
83 }
84
85
86
87
88 @Override
89 public String getInfo() {
90 return this.info;
91 }
92
93
94
95
96
97
98
99 public void setPrincipalFormat(final String format) {
100 this.principalFormat = PrincipalFormat.valueOf(format.toUpperCase(Locale.ENGLISH));
101 this.log.debug("principal format: {}", this.principalFormat);
102 }
103
104
105
106
107
108
109 public PrincipalFormat getPrincipalFormat() {
110 return this.principalFormat;
111 }
112
113
114
115
116
117
118
119 public void setRoleFormat(final String format) {
120 this.roleFormat = PrincipalFormat.valueOf(format.toUpperCase(Locale.ENGLISH));
121 this.log.debug("role format: {}", this.roleFormat);
122 }
123
124
125
126
127
128
129 public PrincipalFormat getRoleFormat() {
130 return this.roleFormat;
131 }
132
133
134
135
136
137
138 public boolean isAllowGuestLogin() {
139 return this.allowGuestLogin;
140 }
141
142
143
144
145
146
147
148
149 public void setAllowGuestLogin(final boolean value) {
150 this.allowGuestLogin = value;
151 }
152
153
154
155
156
157
158
159 public void setProtocols(final String value) {
160 this.protocols = new LinkedHashSet<String>();
161 final String[] protocolNames = value.split(",");
162 for (String protocolName : protocolNames) {
163 protocolName = protocolName.trim();
164 if (!protocolName.isEmpty()) {
165 this.log.debug("init protocol: {}", protocolName);
166 if (WaffleAuthenticatorBase.SUPPORTED_PROTOCOLS.contains(protocolName)) {
167 this.protocols.add(protocolName);
168 } else {
169 this.log.error("unsupported protocol: {}", protocolName);
170 throw new RuntimeException("Unsupported protocol: " + protocolName);
171 }
172 }
173 }
174 }
175
176
177
178
179
180
181
182 protected void sendUnauthorized(final HttpServletResponse response) {
183 try {
184 for (final String protocol : this.protocols) {
185 response.addHeader("WWW-Authenticate", protocol);
186 }
187 response.setHeader("Connection", "close");
188 response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
189 response.flushBuffer();
190 } catch (final IOException e) {
191 throw new RuntimeException(e);
192 }
193 }
194
195
196
197
198
199
200
201
202
203 protected void sendError(final HttpServletResponse response, final int code) {
204 try {
205 response.sendError(code);
206 } catch (final IOException e) {
207 this.log.error(e.getMessage());
208 this.log.trace("{}", e);
209 throw new RuntimeException(e);
210 }
211 }
212
213
214
215
216 @Override
217 protected String getAuthMethod() {
218 return null;
219 }
220
221
222
223
224 @Override
225 protected Principal doLogin(final Request request, final String username, final String password)
226 throws ServletException {
227 this.log.debug("logging in: {}", username);
228 IWindowsIdentity windowsIdentity;
229 try {
230 windowsIdentity = this.auth.logonUser(username, password);
231 } catch (final Exception e) {
232 this.log.error(e.getMessage());
233 this.log.trace("{}", e);
234 return super.doLogin(request, username, password);
235 }
236
237 if (!this.allowGuestLogin && windowsIdentity.isGuest()) {
238 this.log.warn("guest login disabled: {}", windowsIdentity.getFqn());
239 return super.doLogin(request, username, password);
240 }
241 try {
242 this.log.debug("successfully logged in {} ({})", username, windowsIdentity.getSidString());
243 final GenericWindowsPrincipal windowsPrincipal = new GenericWindowsPrincipal(windowsIdentity,
244 this.principalFormat, this.roleFormat);
245 this.log.debug("roles: {}", windowsPrincipal.getRolesString());
246 return windowsPrincipal;
247 } finally {
248 windowsIdentity.dispose();
249 }
250 }
251
252 }