AA init cleanups.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / AAServlet.java
1 /* 
2  * The Shibboleth License, Version 1. 
3  * Copyright (c) 2002 
4  * University Corporation for Advanced Internet Development, Inc. 
5  * All rights reserved
6  * 
7  * 
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions are met:
10  * 
11  * Redistributions of source code must retain the above copyright notice, this 
12  * list of conditions and the following disclaimer.
13  * 
14  * Redistributions in binary form must reproduce the above copyright notice, 
15  * this list of conditions and the following disclaimer in the documentation 
16  * and/or other materials provided with the distribution, if any, must include 
17  * the following acknowledgment: "This product includes software developed by 
18  * the University Corporation for Advanced Internet Development 
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
20  * may appear in the software itself, if and wherever such third-party 
21  * acknowledgments normally appear.
22  * 
23  * Neither the name of Shibboleth nor the names of its contributors, nor 
24  * Internet2, nor the University Corporation for Advanced Internet Development, 
25  * Inc., nor UCAID may be used to endorse or promote products derived from this 
26  * software without specific prior written permission. For written permission, 
27  * please contact shibboleth@shibboleth.org
28  * 
29  * Products derived from this software may not be called Shibboleth, Internet2, 
30  * UCAID, or the University Corporation for Advanced Internet Development, nor 
31  * may Shibboleth appear in their name, without prior written permission of the 
32  * University Corporation for Advanced Internet Development.
33  * 
34  * 
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 package edu.internet2.middleware.shibboleth.aa;
51
52 import java.io.ByteArrayOutputStream;
53 import java.io.IOException;
54 import java.io.PrintStream;
55 import java.net.MalformedURLException;
56 import java.net.URL;
57 import java.util.Arrays;
58 import java.util.List;
59 import java.util.Properties;
60
61 import javax.naming.NamingException;
62 import javax.naming.directory.DirContext;
63 import javax.naming.directory.InitialDirContext;
64 import javax.servlet.ServletConfig;
65 import javax.servlet.ServletContext;
66 import javax.servlet.ServletException;
67 import javax.servlet.UnavailableException;
68 import javax.servlet.http.HttpServlet;
69 import javax.servlet.http.HttpServletRequest;
70 import javax.servlet.http.HttpServletResponse;
71
72 import org.apache.log4j.Logger;
73 import org.apache.log4j.MDC;
74 import org.opensaml.QName;
75 import org.opensaml.SAMLException;
76 import org.opensaml.SAMLIdentifier;
77
78 import edu.internet2.middleware.eduPerson.Init;
79 import edu.internet2.middleware.shibboleth.aa.arp.AAPrincipal;
80 import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
81 import edu.internet2.middleware.shibboleth.aa.arp.ArpException;
82 import edu.internet2.middleware.shibboleth.common.Constants;
83 import edu.internet2.middleware.shibboleth.hs.HandleEntry;
84 import edu.internet2.middleware.shibboleth.hs.HandleException;
85 import edu.internet2.middleware.shibboleth.hs.HandleRepositoryFactory;
86
87 /**
88  *  Attribute Authority & Release Policy
89  *  Handles Initialization and incoming requests to AA
90  *
91  * @author     Parviz Dousti (dousti@cmu.edu)
92  * @created    June, 2002
93  */
94
95 public class AAServlet extends HttpServlet {
96
97     protected AAResponder responder;
98     protected HandleRepositoryFactory hrf;
99     protected Properties configuration;
100     private static Logger log = Logger.getLogger(AAServlet.class.getName());    
101     
102         public void init() throws ServletException {
103
104                 MDC.put("serviceId", "[AA Core]");
105                 log.info("Initializing Attribute Authority.");
106
107                 try {
108
109                         configuration = loadConfiguration();
110
111                         ArpEngine arpEngine = new ArpEngine(configuration);
112                         
113                         hrf = getHandleRepository();
114
115                         log.info(
116                                 "Using JNDI context ("
117                                         + configuration.getProperty("java.naming.factory.initial")
118                                         + ") for attribute retrieval.");
119
120                         DirContext ctx = new InitialDirContext(configuration);
121                         Init.init();
122                         responder =
123                                 new AAResponder(
124                                         arpEngine,
125                                         ctx,
126                                         configuration.getProperty(
127                                                 "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName"));
128
129                         log.info("Attribute Authority initialization complete.");
130
131                 } catch (NamingException ne) {
132                         log.fatal(
133                                 "The AA could not be initialized due to a problem with the JNDI context configuration: "
134                                         + ne);
135                         throw new UnavailableException("Attribute Authority failed to initialize.");
136                 } catch (ArpException ae) {
137                         log.fatal(
138                                 "The AA could not be initialized due to a problem with the ARP Engine configuration: " + ae);
139                         throw new UnavailableException("Attribute Authority failed to initialize.");
140                 } catch (AAException ae) {
141                         log.fatal("The AA could not be initialized: " + ae);
142                         throw new UnavailableException("Attribute Authority failed to initialize.");
143                 } catch (HandleException he) {
144                         log.fatal(
145                                 "The AA could not be initialized due to a problem with the Handle Repository configuration: "
146                                         + he);
147                         throw new UnavailableException("Attribute Authority failed to initialize.");
148                 }
149         }
150         protected Properties loadConfiguration() throws AAException {
151
152                 //Set defaults
153                 Properties defaultProps = new Properties();
154                 defaultProps.setProperty(
155                         "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path",
156                         getServletContext().getRealPath("/WEB-INF/conf/arps/"));
157                 defaultProps.setProperty(
158                         "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
159                         "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository");
160                 defaultProps.setProperty(
161                         "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName",
162                         "shib2.internet2.edu");
163                 defaultProps.setProperty("edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase", "uid=");
164                 defaultProps.setProperty(
165                         "java.naming.factory.initial",
166                         "edu.internet2.middleware.shibboleth.aaLocal.EchoCtxFactory");
167
168                 //Load from file
169                 Properties properties = new Properties(defaultProps);
170                 String propertiesFileLocation = getInitParameter("OriginPropertiesFile");
171                 if (propertiesFileLocation == null) {
172                         propertiesFileLocation = "/WEB-INF/conf/origin.properties";
173                 }
174                 try {
175                         log.debug("Loading Configuration from (" + propertiesFileLocation + ").");
176                         properties.load(getServletContext().getResourceAsStream(propertiesFileLocation));
177                 } catch (IOException e) {
178                         log.error("Could not load AA servlet configuration: " + e);
179                         throw new AAException("Could not load AA servlet configuration.");
180                 }
181
182                 if (log.isDebugEnabled()) {
183                         PrintStream debugStream = new PrintStream(new ByteArrayOutputStream());
184                         properties.list(debugStream);
185                         log.debug(
186                                 "Runtime configuration parameters: "
187                                         + System.getProperty("line.separator")
188                                         + debugStream.toString());
189                 }
190
191                 return properties;
192         }
193
194         public void doPost(HttpServletRequest req, HttpServletResponse resp)
195                 throws ServletException, IOException {
196
197                 log.debug("Recieved a request.");
198                 MDC.put("serviceId", new SAMLIdentifier().toString());
199                 MDC.put("remoteAddr", req.getRemoteAddr());
200                 log.info("Handling request.");
201
202                 List attrs = null;
203                 SAMLException ourSE = null;
204                 AASaml saml = null;
205                 String userName = null;
206
207                 try {
208                         saml =
209                                 new AASaml(
210                                         configuration.getProperty(
211                                                 "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName"));
212                         saml.receive(req);
213
214                         URL resource = null;
215                         try {
216                                 resource = new URL(saml.getResource());
217                         } catch (MalformedURLException mue) {
218                                 log.error(
219                                         "Request contained an improperly formatted resource identifier.  Attempting to "
220                                                 + "handle request without one.");
221                         }
222
223                         String shar = saml.getShar();
224                         log.info("AA: shar:" + shar);
225                         String handle = saml.getHandle();
226                         log.info("AA: handle:" + handle);
227                         if (handle.equalsIgnoreCase("foo")) {
228                                 // for testing only
229                                 userName = "dummy";
230                         } else {
231                                 if (hrf == null) {
232                                         throw new HandleException("No HandleRepository found! Has HS initialized?");
233                                 } else {
234                                         HandleEntry he = hrf.getHandleEntry(handle);
235                                         userName = he.getUsername();
236                                         if (userName == null)
237                                                 throw new HandleException("HandleServer returns null for user name!");
238                                 }
239                         }
240
241                         attrs =
242                                 Arrays.asList(
243                                         responder.getReleaseAttributes(
244                                                 new AAPrincipal(userName),
245                                                 configuration.getProperty(
246                                                         "edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase"),
247                                                 shar,
248                                                 resource));
249                         log.info("Got " + attrs.size() + " attributes for " + userName);
250                         saml.respond(resp, attrs, null);
251                         log.info("Successfully responded about " + userName);
252
253                 } catch (org.opensaml.SAMLException se) {
254                         log.error("AA failed for " + userName + " because of: " + se);
255                         try {
256                                 saml.fail(resp, se);
257                         } catch (Exception ee) {
258                                 throw new ServletException(
259                                         "AA failed to even make a SAML Failure message because "
260                                                 + ee
261                                                 + "  Origianl problem: "
262                                                 + se);
263                         }
264                 } catch (HandleException he) {
265                         log.error("AA failed for " + userName + " because of: " + he);
266                         try {
267                                 QName[] codes = new QName[2];
268                                 codes[0] = SAMLException.REQUESTER;
269                                 codes[1] = new QName(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS, "InvalidHandle");
270                                 saml.fail(resp, new SAMLException(Arrays.asList(codes), "AA got a HandleException: " + he));
271                         } catch (Exception ee) {
272                                 throw new ServletException(
273                                         "AA failed to even make a SAML Failure message because "
274                                                 + ee
275                                                 + "  Original problem: "
276                                                 + he);
277                         }
278                 } catch (Exception e) {
279                         e.printStackTrace();
280                         log.error(
281                                 "Attribute Authority Error for principal ("
282                                         + userName
283                                         + ") : "
284                                         + e.getClass().getName()
285                                         + " : "
286                                         + e.getMessage());
287                         try {
288                                 saml.fail(
289                                         resp,
290                                         new SAMLException(
291                                                 SAMLException.RESPONDER,
292                                                 "Attribute Authority Error: " + e.getMessage()));
293                         } catch (Exception ee) {
294                                 throw new ServletException(
295                                         "AA failed to even make a SAML Failure message because "
296                                                 + ee
297                                                 + "  Original problem: "
298                                                 + e);
299                         }
300
301                 }
302         }
303
304
305     private synchronized HandleRepositoryFactory getHandleRepository()
306         throws HandleException, AAException{
307
308         ServletConfig sc = getServletConfig();
309         ServletContext sctx = sc.getServletContext(); 
310         HandleRepositoryFactory hrf = (HandleRepositoryFactory)sctx.getAttribute("HandleRepository");
311
312         log.debug("Context attribute for HandleRepository: "+hrf);
313             
314             
315         if(hrf == null){
316             // make one
317             String repositoryType = this.getServletContext().getInitParameter("repository");
318             if(repositoryType == null)
319                 throw new AAException("repository parameter not set. Unknown Handle repository type");
320             hrf = HandleRepositoryFactory.getInstance(                                                Constants.POLICY_CLUBSHIB, 
321                                                                                                       repositoryType,
322                                                                                                       this );
323             sctx.setAttribute("HandleRepository", hrf);
324             log.info("A new HandleRepository created by AA: "+hrf);
325             
326         }
327         return hrf;
328     }
329
330
331 }