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