1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.internet2.middleware.shibboleth.wayf;
18
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.lang.reflect.Constructor;
22 import java.util.ArrayList;
23 import java.util.Hashtable;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import javax.servlet.GenericServlet;
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServlet;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32 import javax.xml.namespace.QName;
33
34 import org.opensaml.DefaultBootstrap;
35 import org.opensaml.xml.Configuration;
36 import org.opensaml.xml.parse.BasicParserPool;
37 import org.opensaml.xml.util.DatatypeHelper;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.NodeList;
43
44 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
45 import edu.internet2.middleware.shibboleth.wayf.plugins.Plugin;
46
47
48
49
50
51
52
53 public class WayfService extends HttpServlet {
54
55
56 private static final long serialVersionUID = 5244503011625804940L;
57
58
59 private static final Logger LOG = LoggerFactory.getLogger(WayfService.class.getName());
60
61
62 private String wayfConfigFileLocation;
63
64
65 private LogbackLoggingService logService;
66
67
68 private List <DiscoveryServiceHandler> discoveryServices = new ArrayList <DiscoveryServiceHandler>();
69
70
71
72
73
74
75
76
77 public void init() throws ServletException {
78
79 super.init();
80
81 wayfConfigFileLocation = getServletContext().getInitParameter("WAYFConfigFileLocation");
82 if (wayfConfigFileLocation == null) {
83 wayfConfigFileLocation = getServletConfig().getInitParameter("WAYFConfigFileLocation");
84 }
85 if (wayfConfigFileLocation == null) {
86 wayfConfigFileLocation = "/wayfconfig.xml";
87 }
88
89
90 try {
91
92
93
94 String wayfLogfile = getServletContext().getInitParameter("WAYFLogConfig");
95 if (null == wayfLogfile) {
96 wayfLogfile = getServletConfig().getInitParameter("WAYFLogConfig");
97 }
98 long pollingFrequency = 1000*60*5;
99
100 String wayfLogfilePollFrequency = getServletContext().getInitParameter("WAYFLogConfigPollFrequency");
101 if (null == wayfLogfilePollFrequency) {
102 wayfLogfilePollFrequency = getServletConfig().getInitParameter("WAYFLogConfigPollFrequency");
103 }
104 if(!DatatypeHelper.isEmpty(wayfLogfilePollFrequency)){
105 pollingFrequency = Long.parseLong(wayfLogfilePollFrequency);
106 }
107 if (wayfLogfile != null) {
108 logService = new LogbackLoggingService(wayfLogfile, pollingFrequency);
109 }
110
111 LOG.info("Logging initiated");
112
113
114
115
116 DefaultBootstrap.bootstrap();
117
118 BasicParserPool parser = new BasicParserPool();
119 parser.setNamespaceAware(true);
120 Document doc;
121 try {
122 doc = parser.parse(new FileInputStream(wayfConfigFileLocation));
123 } catch (FileNotFoundException e) {
124 LOG.error("Could not parse " + wayfConfigFileLocation, e);
125 throw new ShibbolethConfigurationException("Could not parse " + wayfConfigFileLocation, e);
126 }
127 NodeList itemElements = doc.getDocumentElement().getElementsByTagNameNS(XMLConstants.CONFIG_NS,
128 "Default");
129
130 HandlerConfig defaultHandlerConfig;
131
132 if (itemElements.getLength() == 1) {
133
134 Element element = (Element) itemElements.item(0);
135 String attribute = element.getAttribute("location");
136
137 if (attribute != null && !attribute.equals("")) {
138
139 LOG.error("<Default> element cannot contain a location attribute");
140 throw new ShibbolethConfigurationException("<Default> element cannot contain a location attribute");
141
142 }
143
144 attribute = element.getAttribute("default");
145
146 if (attribute != null && !attribute.equals("")) {
147
148 LOG.error("<Default> element cannot contain a default attribute");
149 throw new ShibbolethConfigurationException("<Default> element cannot contain a default attribute");
150
151 }
152
153 itemElements = element.getElementsByTagName("Federation");
154
155 if (itemElements.getLength() != 0) {
156
157 LOG.error("<Default> element cannot contain <Federation> elements");
158 throw new ShibbolethConfigurationException("<Default> element cannot contain <Federation> elements");
159
160 }
161
162 defaultHandlerConfig = new HandlerConfig(element, new HandlerConfig());
163
164 } else if (itemElements.getLength() == 0) {
165
166 defaultHandlerConfig = new HandlerConfig();
167
168 } else {
169 LOG.error("Must specify exactly one <Default> element");
170 throw new ShibbolethConfigurationException("Must specify exactly one <Default> element");
171 }
172
173
174
175 QName response = new QName(DiscoveryResponseImpl.METADATA_NS, DiscoveryResponseImpl.DEFAULT_ELEMENT_LOCAL_NAME);
176
177 Configuration.getUnmarshallerFactory().registerUnmarshaller(response, new DiscoveryResponseUnmarshaller());
178 Configuration.getBuilderFactory().registerBuilder(response, new DiscoveryResponseBuilder());
179
180
181
182
183 Hashtable <String, IdPSiteSet> siteSets = new Hashtable <String, IdPSiteSet>();
184
185 itemElements = doc.getDocumentElement().getElementsByTagNameNS(XMLConstants.CONFIG_NS,
186 "MetadataProvider");
187
188 for (int i = 0; i < itemElements.getLength(); i++) {
189
190 Element element = (Element) itemElements.item(i);
191
192 IdPSiteSet siteset = new IdPSiteSet(element, parser, defaultHandlerConfig.getWarnOnBadBinding());
193
194 siteSets.put(siteset.getIdentifier(), siteset);
195 }
196 if (siteSets.size() < 1) {
197 LOG.error("No Metadata Provider metadata loaded.");
198 throw new ShibbolethConfigurationException("Could not load SAML metadata.");
199 }
200
201
202
203
204 Hashtable <String, Plugin> plugins = new Hashtable <String, Plugin>();
205
206 itemElements = doc.getDocumentElement().getElementsByTagNameNS(XMLConstants.CONFIG_NS,
207 "Plugin");
208
209 for (int i = 0; i < itemElements.getLength(); i++) {
210
211 Plugin plugin;
212
213 Element element = (Element) itemElements.item(i);
214
215 String identifier = element.getAttribute("identifier");
216
217 if (null == identifier || identifier.equals("")) {
218 LOG.error("Could not load plugin with no identifier");
219 continue;
220 }
221
222 String className = element.getAttribute("type");
223 if (null == className || className.equals("")) {
224 LOG.error("Plugin " + identifier + " did not have a valid type");
225 }
226
227
228
229 try {
230 Class<Plugin> pluginClass = (Class<Plugin>) Class.forName(className);
231 Class[] classParams = {Element.class};
232 Constructor<Plugin> pluginConstructor = pluginClass.getConstructor(classParams);
233 Object[] constructorParams = {element};
234
235 plugin = pluginConstructor.newInstance(constructorParams);
236
237 } catch (Exception e) {
238 LOG.error("Plugin " + identifier + " could not be loaded ", e);
239 continue;
240 }
241
242 plugins.put(identifier, plugin);
243 }
244
245
246
247
248
249 itemElements = doc.getDocumentElement().getElementsByTagNameNS(XMLConstants.CONFIG_NS,
250 "DiscoveryServiceHandler");
251
252 for (int i = 0; i < itemElements.getLength(); i++) {
253
254 discoveryServices.add(new DiscoveryServiceHandler((Element)itemElements.item(i),
255 siteSets,
256 plugins,
257 defaultHandlerConfig));
258
259 }
260
261 } catch (Exception e) {
262
263
264
265 if (LOG != null) {
266 LOG.error("Error parsing DS configuration file.", e);
267 }
268 throw new ServletException("Error parsing DS configuration file.", e);
269 }
270
271 LOG.info("DS initialization completed.");
272 }
273
274
275
276
277
278
279
280 public void doGet(HttpServletRequest req, HttpServletResponse res) {
281
282 LOG.info("Handling DS request.");
283
284 res.setHeader("Cache-Control", "no-cache");
285 res.setHeader("Pragma", "no-cache");
286 res.setDateHeader("Expires", 0);
287
288 DiscoveryServiceHandler serviceHandler = lookupServiceHandler(req);
289
290 serviceHandler.doGet(req, res);
291
292 }
293
294
295
296
297
298
299 private DiscoveryServiceHandler lookupServiceHandler(HttpServletRequest req) {
300
301 Iterator<DiscoveryServiceHandler> it = discoveryServices.iterator();
302 String requestURL = req.getRequestURL().toString();
303 DiscoveryServiceHandler defaultHandler = null;
304
305 while (it.hasNext()) {
306 DiscoveryServiceHandler handler = it.next();
307
308 if (requestURL.matches(handler.getLocation())) {
309 return handler;
310 }
311 if (defaultHandler == null || handler.isDefault()) {
312 defaultHandler = handler;
313 }
314 }
315 LOG.warn("Could not find Discovery service Handler for " + requestURL);
316 return defaultHandler;
317 }
318 }