Clover Coverage Report - Atlassian Trusted Apps(Aggregated)
Coverage timestamp: Tue Jun 9 2009 19:34:44 CDT
58   226   22   5.27
14   167   0.38   2.75
11     2  
4    
 
 
  TrustedApplicationsFilter       Line # 46 43 18 95.5% 0.95454544
  TrustedApplicationsFilter.Status       Line # 48 0 0 - -1.0
  TrustedApplicationsFilter.CertificateServer       Line # 184 0 0 - -1.0
  TrustedApplicationsFilter.CertificateServerImpl       Line # 189 15 4 94.1% 0.9411765
 
  (22)
 
1    package com.atlassian.security.auth.trustedapps.filter;
2   
3    import com.atlassian.security.auth.trustedapps.CurrentApplication;
4    import com.atlassian.security.auth.trustedapps.Null;
5    import com.atlassian.security.auth.trustedapps.TrustedApplicationUtils;
6    import com.atlassian.security.auth.trustedapps.TrustedApplicationsManager;
7    import com.atlassian.security.auth.trustedapps.UserResolver;
8    import org.bouncycastle.util.encoders.Base64;
9   
10    import javax.servlet.Filter;
11    import javax.servlet.FilterChain;
12    import javax.servlet.FilterConfig;
13    import javax.servlet.ServletException;
14    import javax.servlet.ServletRequest;
15    import javax.servlet.ServletResponse;
16    import javax.servlet.http.HttpServletRequest;
17    import javax.servlet.http.HttpServletResponse;
18    import java.io.IOException;
19    import java.io.OutputStreamWriter;
20    import java.io.UnsupportedEncodingException;
21    import java.io.Writer;
22    import java.security.PublicKey;
23   
24    /**
25    * This filter serves two purposes:
26    * <ol>
27    * <li>Authenticates requests from trusted applications if the right certificate is
28    * present in the request.</li>
29    * <li>Returns the UID and public key of this application upon request so other servers can
30    * establish trusted relationship with this application as a client.</li>
31    * </ol>
32    * <p/>
33    * For the first purpose, the filter will intercept any calls to a page '/admin/appTrustCertificate'. Directory
34    * structure of the request will be ignored. The returned page will contain 2 lines:
35    * <ul>
36    * <li> ID </li>
37    * <li> public key BASE64 encoded </li>
38    * </ul>
39    * <p/>
40    * For the second purpose the following header parameters must be present and valid:
41    * {@link CurrentApplication#HEADER_TRUSTED_APP_CERT} {@link CurrentApplication#HEADER_TRUSTED_APP_ID}
42    * <p/>
43    * If the authentication should fail a message will be set in the response header:
44    * {@link CurrentApplication#HEADER_TRUSTED_APP_ERROR}
45    */
 
46    public class TrustedApplicationsFilter implements Filter
47    {
 
48    static final class Status
49    {
50    static final String ERROR = "ERROR";
51    static final String OK = "OK";
52    }
53   
54    private final CertificateServer certificateServer;
55    private final Authenticator authenticator;
56   
57    private FilterConfig filterConfig = null;
58   
59    private final AuthenticationController authenticationController;
60    private final AuthenticationListener authenticationListener;
61   
 
62  10 toggle public TrustedApplicationsFilter(TrustedApplicationsManager appManager, UserResolver resolver, AuthenticationController authenticationController, AuthenticationListener authenticationListener)
63    {
64  10 this(new CertificateServerImpl(appManager), new TrustedApplicationFilterAuthenticator(appManager, resolver, authenticationController), authenticationController, authenticationListener);
65    }
66   
 
67  20 toggle protected TrustedApplicationsFilter(CertificateServer certificateServer, Authenticator authenticator, AuthenticationController authenticationController, AuthenticationListener authenticationListener)
68    {
69  20 Null.not("certificateServer", certificateServer);
70  20 Null.not("authenticator", authenticator);
71  20 Null.not("authenticationController", authenticationController);
72  20 Null.not("authenticationListener", authenticationListener);
73   
74  20 this.certificateServer = certificateServer;
75  20 this.authenticator = authenticator;
76  20 this.authenticationController = authenticationController;
77  20 this.authenticationListener = authenticationListener;
78    }
79   
 
80  7 toggle public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
81    {
82    // if this is a certificate request serve the certificate back and return
83  7 final HttpServletRequest request = (HttpServletRequest) req;
84  7 final HttpServletResponse response = (HttpServletResponse) res;
85   
86  7 if (getPathInfo(request).endsWith(TrustedApplicationUtils.Constant.CERTIFICATE_URL_PATH))
87    {
88  1 response.setContentType("text/plain");
89  1 final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(response.getOutputStream());
90  1 certificateServer.writeCertificate(outputStreamWriter);
91  1 outputStreamWriter.flush();
92  1 return;
93    }
94   
95  6 final boolean isTrustedAppCall = authenticate(request, response);
96  2 try
97    {
98  2 chain.doFilter(request, res);
99    }
100    finally
101    {
102  2 if (isTrustedAppCall && request.getSession(false) != null)
103    {
104  2 request.getSession().invalidate();
105    }
106    }
107    }
108   
 
109  16 toggle boolean authenticate(HttpServletRequest request, HttpServletResponse response)
110    {
111  16 if (authenticationController.shouldAttemptAuthentication(request))
112    {
113  16 final Authenticator.Result result = authenticator.authenticate(request, response);
114   
115  12 if (result.getStatus() == Authenticator.Result.Status.SUCCESS)
116    {
117  4 authenticationListener.authenticationSuccess(result, request, response);
118  4 response.setHeader(TrustedApplicationUtils.Header.Response.STATUS, Status.OK);
119  4 return true;
120    }
121   
122  8 if (result.getStatus() == Authenticator.Result.Status.FAILED)
123    {
124  1 authenticationListener.authenticationFailure(result, request, response);
125    }
126    else
127    {
128  7 authenticationListener.authenticationError(result, request, response);
129    }
130    }
131    else
132    {
133  0 authenticationListener.authenticationNotAttempted(request, response);
134    }
135  8 return false;
136    }
137   
 
138  9 toggle protected String getPathInfo(HttpServletRequest request)
139    {
140  9 String context = request.getContextPath();
141  9 String uri = request.getRequestURI();
142  9 if (context != null && context.length() > 0)
143    {
144  8 return uri.substring(context.length());
145    }
146    else
147    {
148  1 return uri;
149    }
150    }
151   
 
152  2 toggle public void init(FilterConfig config)
153    {
154  2 this.filterConfig = config;
155    }
156   
 
157  1 toggle public void destroy()
158    {
159  1 filterConfig = null;
160    }
161   
162    /**
163    * @deprecated Not needed in latest version of Servlet 2.3 API
164    */
 
165  5 toggle public FilterConfig getFilterConfig()
166    {
167  5 return filterConfig;
168    }
169   
170    /**
171    * @deprecated Not needed in latest version of Servlet 2.3 API - replaced by init().
172    */
 
173  2 toggle public void setFilterConfig(FilterConfig filterConfig)
174    {
175  2 if (filterConfig != null) // it seems that Orion 1.5.2 calls this with a null config.
176    {
177  1 init(filterConfig);
178    }
179    }
180   
181    /**
182    * serve the CurrentApplication's certificate
183    */
 
184    public interface CertificateServer
185    {
186    void writeCertificate(Writer writer) throws IOException;
187    }
188   
 
189    public static class CertificateServerImpl implements CertificateServer
190    {
191    final TrustedApplicationsManager appManager;
192   
 
193  12 toggle public CertificateServerImpl(TrustedApplicationsManager appManager)
194    {
195  12 this.appManager = appManager;
196    }
197   
 
198  2 toggle public void writeCertificate(Writer writer) throws IOException
199    {
200  2 CurrentApplication currentApplication = appManager.getCurrentApplication();
201  2 PublicKey publicKey = currentApplication.getPublicKey();
202   
203  2 try
204    {
205  2 writer.write(currentApplication.getID());
206  1 writer.write("\n");
207   
208  1 byte[] key = publicKey.getEncoded();
209  1 writer.write(new String(Base64.encode(key), TrustedApplicationUtils.Constant.CHARSET_NAME));
210  1 writer.write("\n");
211  1 writer.write(TrustedApplicationUtils.Constant.VERSION.toString());
212  1 writer.write("\n");
213  1 writer.write(TrustedApplicationUtils.Constant.MAGIC);
214  1 writer.flush();
215    }
216    catch (UnsupportedEncodingException ex)
217    {
218  0 throw new AssertionError(ex);
219    }
220    catch (IOException e)
221    {
222  1 throw new RuntimeException(e);
223    }
224    }
225    }
226    }