47ad1ffc4c86c5a697aa7240c0219aa74bc6f193
[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.*;
53 import java.net.MalformedURLException;
54 import java.net.URL;
55 import java.util.*;
56 import javax.servlet.*;
57 import javax.servlet.http.*;
58 import javax.naming.*;
59 import javax.naming.directory.*;
60 import org.opensaml.*;
61 import org.w3c.dom.*;
62 import edu.internet2.middleware.shibboleth.*;
63 import edu.internet2.middleware.shibboleth.aa.arp.AAPrincipal;
64 import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
65 import edu.internet2.middleware.shibboleth.aa.arp.ArpException;
66 import edu.internet2.middleware.shibboleth.common.*;
67 import edu.internet2.middleware.shibboleth.hs.*;
68 import edu.internet2.middleware.eduPerson.*;
69 import org.apache.log4j.Logger;
70 import org.apache.log4j.MDC;
71
72 /**
73  *  Attribute Authority & Release Policy
74  *  Handles Initialization and incoming requests to AA
75  *
76  * @author     Parviz Dousti (dousti@cmu.edu)
77  * @created    June, 2002
78  */
79
80 public class AAServlet extends HttpServlet {
81
82     AAResponder responder;
83     HandleRepositoryFactory hrf;
84     protected Properties configuration;
85     private static Logger log = Logger.getLogger(AAServlet.class.getName());    
86     
87         public void init() throws ServletException {
88
89                 MDC.put("serviceId", "[AA Core]");
90                 log.info("Initializing Attribute Authority.");
91
92                 try {
93
94                         configuration = loadConfiguration();
95
96                         ArpEngine arpEngine = new ArpEngine(configuration);
97                         edu.internet2.middleware.eduPerson.Init.init();
98                         hrf = getHandleRepository();
99
100                         log.info(
101                                 "Using JNDI context ("
102                                         + configuration.getProperty("java.naming.factory.initial")
103                                         + ") for attribute retrieval.");
104
105                         DirContext ctx = new InitialDirContext(configuration);
106
107                         responder =
108                                 new AAResponder(
109                                         arpEngine,
110                                         ctx,
111                                         configuration.getProperty(
112                                                 "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName"));
113
114                         log.info("Attribute Authority initialization complete.");
115
116                 } catch (NamingException ne) {
117                         log.fatal("AA init failed: " + ne);
118                         throw new ServletException("Init failed: " + ne);
119                 } catch (ArpException ae) {
120                         log.fatal(
121                                 "Attribute Authority could not be initialized due to a problem with the ARP Engine configuration: "
122                                         + ae);
123                         throw new UnavailableException("Attribute Authority failed to initialize.");
124                 } catch (AAException ae) {
125                         log.fatal("AA init failed: " + ae);
126                         throw new ServletException("Init failed: " + ae);
127                 } catch (HandleException he) {
128                         log.fatal("AA init failed: " + he);
129                         throw new ServletException("Init failed: " + he);
130                 }
131         }
132         protected Properties loadConfiguration() throws AAException {
133
134                 //Set defaults
135                 Properties defaultProps = new Properties();
136                 defaultProps.setProperty(
137                         "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path",
138                         getServletContext().getRealPath("/WEB-INF/conf/arps/"));
139                 defaultProps.setProperty(
140                         "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
141                         "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository");
142                 defaultProps.setProperty(
143                         "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName",
144                         "shib2.internet2.edu");
145                 defaultProps.setProperty("edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase", "uid=");
146                 defaultProps.setProperty(
147                         "java.naming.factory.initial",
148                         "edu.internet2.middleware.shibboleth.aaLocal.EchoCtxFactory");
149
150                 //Load from file
151                 Properties properties = new Properties(defaultProps);
152                 String propertiesFileLocation = getInitParameter("OriginPropertiesFile");
153                 if (propertiesFileLocation == null) {
154                         propertiesFileLocation = "/WEB-INF/conf/origin.properties";
155                 }
156                 try {
157                         log.debug("Loading Configuration from (" + propertiesFileLocation + ").");
158                         properties.load(getServletContext().getResourceAsStream(propertiesFileLocation));
159                 } catch (IOException e) {
160                         log.error("Could not load AA servlet configuration: " + e);
161                         throw new AAException("Could not load AA servlet configuration.");
162                 }
163
164                 if (log.isDebugEnabled()) {
165                         PrintStream debugStream = new PrintStream(new ByteArrayOutputStream());
166                         properties.list(debugStream);
167                         log.debug(
168                                 "Runtime configuration parameters: "
169                                         + System.getProperty("line.separator")
170                                         + debugStream.toString());
171                 }
172
173                 return properties;
174         }
175
176         public void doPost(HttpServletRequest req, HttpServletResponse resp)
177                 throws ServletException, IOException {
178
179                 log.debug("Recieved a request.");
180                 MDC.put("serviceId", new SAMLIdentifier().toString());
181                 MDC.put("remoteAddr", req.getRemoteAddr());
182                 log.info("Handling request.");
183
184                 List attrs = null;
185                 SAMLException ourSE = null;
186                 AASaml saml = null;
187                 String userName = null;
188
189                 try {
190                         saml =
191                                 new AASaml(
192                                         configuration.getProperty(
193                                                 "edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName"));
194                         saml.receive(req);
195
196                         URL resource = null;
197                         try {
198                                 resource = new URL(saml.getResource());
199                         } catch (MalformedURLException mue) {
200                                 log.error(
201                                         "Request contained an improperly formatted resource identifier.  Attempting to "
202                                                 + "handle request without one.");
203                         }
204
205                         String shar = saml.getShar();
206                         log.info("AA: shar:" + shar);
207                         String handle = saml.getHandle();
208                         log.info("AA: handle:" + handle);
209                         if (handle.equalsIgnoreCase("foo")) {
210                                 // for testing only
211                                 userName = "dummy";
212                         } else {
213                                 if (hrf == null) {
214                                         throw new HandleException("No HandleRepository found! Has HS initialized?");
215                                 } else {
216                                         HandleEntry he = hrf.getHandleEntry(handle);
217                                         userName = he.getUsername();
218                                         if (userName == null)
219                                                 throw new HandleException("HandleServer returns null for user name!");
220                                 }
221                         }
222
223                         attrs =
224                                 Arrays.asList(
225                                         responder.getReleaseAttributes(
226                                                 new AAPrincipal(userName),
227                                                 configuration.getProperty(
228                                                         "edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase"),
229                                                 shar,
230                                                 resource));
231                         log.info("Got " + attrs.size() + " attributes for " + userName);
232                         saml.respond(resp, attrs, null);
233                         log.info("Successfully responded about " + userName);
234
235                 } catch (org.opensaml.SAMLException se) {
236                         log.error("AA failed for " + userName + " because of: " + se);
237                         try {
238                                 saml.fail(resp, se);
239                         } catch (Exception ee) {
240                                 throw new ServletException(
241                                         "AA failed to even make a SAML Failure message because "
242                                                 + ee
243                                                 + "  Origianl problem: "
244                                                 + se);
245                         }
246                 } catch (HandleException he) {
247                         log.error("AA failed for " + userName + " because of: " + he);
248                         try {
249                                 QName[] codes = new QName[2];
250                                 codes[0] = SAMLException.REQUESTER;
251                                 codes[1] = new QName(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS, "InvalidHandle");
252                                 saml.fail(resp, new SAMLException(Arrays.asList(codes), "AA got a HandleException: " + he));
253                         } catch (Exception ee) {
254                                 throw new ServletException(
255                                         "AA failed to even make a SAML Failure message because "
256                                                 + ee
257                                                 + "  Original problem: "
258                                                 + he);
259                         }
260                 } catch (Exception e) {
261                         e.printStackTrace();
262                         log.error(
263                                 "Attribute Authority Error for principal ("
264                                         + userName
265                                         + ") : "
266                                         + e.getClass().getName()
267                                         + " : "
268                                         + e.getMessage());
269                         try {
270                                 saml.fail(
271                                         resp,
272                                         new SAMLException(
273                                                 SAMLException.RESPONDER,
274                                                 "Attribute Authority Error: " + e.getMessage()));
275                         } catch (Exception ee) {
276                                 throw new ServletException(
277                                         "AA failed to even make a SAML Failure message because "
278                                                 + ee
279                                                 + "  Original problem: "
280                                                 + e);
281                         }
282
283                 }
284         }
285
286
287     private synchronized HandleRepositoryFactory getHandleRepository()
288         throws HandleException, AAException{
289
290         ServletConfig sc = getServletConfig();
291         ServletContext sctx = sc.getServletContext(); 
292         HandleRepositoryFactory hrf = (HandleRepositoryFactory)sctx.getAttribute("HandleRepository");
293
294         log.debug("Context attribute for HandleRepository: "+hrf);
295             
296             
297         if(hrf == null){
298             // make one
299             String repositoryType = this.getServletContext().getInitParameter("repository");
300             if(repositoryType == null)
301                 throw new AAException("repository parameter not set. Unknown Handle repository type");
302             hrf = HandleRepositoryFactory.getInstance(                                                Constants.POLICY_CLUBSHIB, 
303                                                                                                       repositoryType,
304                                                                                                       this );
305             sctx.setAttribute("HandleRepository", hrf);
306             log.info("A new HandleRepository created by AA: "+hrf);
307             
308         }
309         return hrf;
310     }
311
312
313 }