1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package waffle.servlet.spi;
25
26 import com.sun.jna.platform.win32.Win32Exception;
27
28 import jakarta.servlet.http.HttpServletRequest;
29 import jakarta.servlet.http.HttpServletResponse;
30
31 import java.io.IOException;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.InvocationTargetException;
34 import java.util.ArrayList;
35 import java.util.List;
36
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import waffle.util.AuthorizationHeader;
41 import waffle.windows.auth.IWindowsAuthProvider;
42 import waffle.windows.auth.IWindowsIdentity;
43
44
45
46
47 public class SecurityFilterProviderCollection {
48
49
50 private static final Logger LOGGER = LoggerFactory.getLogger(SecurityFilterProviderCollection.class);
51
52
53 private final List<SecurityFilterProvider> providers = new ArrayList<>();
54
55
56
57
58
59
60
61 public SecurityFilterProviderCollection(final SecurityFilterProvider[] providerArray) {
62 for (final SecurityFilterProvider provider : providerArray) {
63 SecurityFilterProviderCollection.LOGGER.info("using '{}'", provider.getClass().getName());
64 this.providers.add(provider);
65 }
66 }
67
68
69
70
71
72
73
74
75
76 @SuppressWarnings("unchecked")
77 public SecurityFilterProviderCollection(final String[] providerNames, final IWindowsAuthProvider auth) {
78 Class<SecurityFilterProvider> providerClass;
79 Constructor<SecurityFilterProvider> providerConstructor;
80 for (String providerName : providerNames) {
81 providerName = providerName.trim();
82 SecurityFilterProviderCollection.LOGGER.info("loading '{}'", providerName);
83 try {
84 providerClass = (Class<SecurityFilterProvider>) Class.forName(providerName);
85 providerConstructor = providerClass.getConstructor(IWindowsAuthProvider.class);
86 final SecurityFilterProvider provider = providerConstructor.newInstance(auth);
87 this.providers.add(provider);
88 } catch (final ClassNotFoundException e) {
89 throw new RuntimeException(e);
90 } catch (final SecurityException | NoSuchMethodException | IllegalArgumentException | InstantiationException
91 | IllegalAccessException | InvocationTargetException e) {
92 SecurityFilterProviderCollection.LOGGER.error("error loading '{}': {}", providerName, e.getMessage());
93 SecurityFilterProviderCollection.LOGGER.trace("", e);
94 }
95 }
96 }
97
98
99
100
101
102
103
104 public SecurityFilterProviderCollection(final IWindowsAuthProvider auth) {
105 this.providers.add(new NegotiateSecurityFilterProvider(auth));
106 this.providers.add(new BasicSecurityFilterProvider(auth));
107 }
108
109
110
111
112
113
114
115
116
117 public boolean isSecurityPackageSupported(final String securityPackage) {
118 return this.get(securityPackage) != null;
119 }
120
121
122
123
124
125
126
127
128
129 private SecurityFilterProvider get(final String securityPackage) {
130 for (final SecurityFilterProvider provider : this.providers) {
131 if (provider.isSecurityPackageSupported(securityPackage)) {
132 return provider;
133 }
134 }
135 return null;
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 public IWindowsIdentity doFilter(final HttpServletRequest request, final HttpServletResponse response)
152 throws IOException {
153 final AuthorizationHeader authorizationHeader = new AuthorizationHeader(request);
154 final SecurityFilterProvider provider = this.get(authorizationHeader.getSecurityPackage());
155 if (provider == null) {
156 throw new RuntimeException("Unsupported security package: " + authorizationHeader.getSecurityPackage());
157 }
158 try {
159 return provider.doFilter(request, response);
160 } catch (final Win32Exception e) {
161 throw new IOException(e);
162 }
163 }
164
165
166
167
168
169
170
171
172
173 public boolean isPrincipalException(final HttpServletRequest request) {
174 for (final SecurityFilterProvider provider : this.providers) {
175 if (provider.isPrincipalException(request)) {
176 return true;
177 }
178 }
179 return false;
180 }
181
182
183
184
185
186
187
188 public void sendUnauthorized(final HttpServletResponse response) {
189 for (final SecurityFilterProvider provider : this.providers) {
190 provider.sendUnauthorized(response);
191 }
192 }
193
194
195
196
197
198
199 public int size() {
200 return this.providers.size();
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214 public SecurityFilterProvider getByClassName(final String name) throws ClassNotFoundException {
215 for (final SecurityFilterProvider provider : this.providers) {
216 if (provider.getClass().getName().equals(name)) {
217 return provider;
218 }
219 }
220 throw new ClassNotFoundException(name);
221 }
222 }