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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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 public TrustedApplicationsFilter(TrustedApplicationsManager appManager, UserResolver resolver, AuthenticationController authenticationController, AuthenticationListener authenticationListener)
63 {
64 this(new CertificateServerImpl(appManager), new TrustedApplicationFilterAuthenticator(appManager, resolver, authenticationController), authenticationController, authenticationListener);
65 }
66
67 protected TrustedApplicationsFilter(CertificateServer certificateServer, Authenticator authenticator, AuthenticationController authenticationController, AuthenticationListener authenticationListener)
68 {
69 Null.not("certificateServer", certificateServer);
70 Null.not("authenticator", authenticator);
71 Null.not("authenticationController", authenticationController);
72 Null.not("authenticationListener", authenticationListener);
73
74 this.certificateServer = certificateServer;
75 this.authenticator = authenticator;
76 this.authenticationController = authenticationController;
77 this.authenticationListener = authenticationListener;
78 }
79
80 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
81 {
82
83 final HttpServletRequest request = (HttpServletRequest) req;
84 final HttpServletResponse response = (HttpServletResponse) res;
85
86 if (getPathInfo(request).endsWith(TrustedApplicationUtils.Constant.CERTIFICATE_URL_PATH))
87 {
88 response.setContentType("text/plain");
89 final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(response.getOutputStream());
90 certificateServer.writeCertificate(outputStreamWriter);
91 outputStreamWriter.flush();
92 return;
93 }
94
95 final boolean isTrustedAppCall = authenticate(request, response);
96 try
97 {
98 chain.doFilter(request, res);
99 }
100 finally
101 {
102 if (isTrustedAppCall && request.getSession(false) != null)
103 {
104 request.getSession().invalidate();
105 }
106 }
107 }
108
109 boolean authenticate(HttpServletRequest request, HttpServletResponse response)
110 {
111 if (authenticationController.shouldAttemptAuthentication(request))
112 {
113 final Authenticator.Result result = authenticator.authenticate(request, response);
114
115 if (result.getStatus() == Authenticator.Result.Status.SUCCESS)
116 {
117 authenticationListener.authenticationSuccess(result, request, response);
118 response.setHeader(TrustedApplicationUtils.Header.Response.STATUS, Status.OK);
119 return true;
120 }
121
122 if (result.getStatus() == Authenticator.Result.Status.FAILED)
123 {
124 authenticationListener.authenticationFailure(result, request, response);
125 }
126 else
127 {
128 authenticationListener.authenticationError(result, request, response);
129 }
130 }
131 else
132 {
133 authenticationListener.authenticationNotAttempted(request, response);
134 }
135 return false;
136 }
137
138 protected String getPathInfo(HttpServletRequest request)
139 {
140 String context = request.getContextPath();
141 String uri = request.getRequestURI();
142 if (context != null && context.length() > 0)
143 {
144 return uri.substring(context.length());
145 }
146 else
147 {
148 return uri;
149 }
150 }
151
152 public void init(FilterConfig config)
153 {
154 this.filterConfig = config;
155 }
156
157 public void destroy()
158 {
159 filterConfig = null;
160 }
161
162
163
164
165 public FilterConfig getFilterConfig()
166 {
167 return filterConfig;
168 }
169
170
171
172
173 public void setFilterConfig(FilterConfig filterConfig)
174 {
175 if (filterConfig != null)
176 {
177 init(filterConfig);
178 }
179 }
180
181
182
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 public CertificateServerImpl(TrustedApplicationsManager appManager)
194 {
195 this.appManager = appManager;
196 }
197
198 public void writeCertificate(Writer writer) throws IOException
199 {
200 CurrentApplication currentApplication = appManager.getCurrentApplication();
201 PublicKey publicKey = currentApplication.getPublicKey();
202
203 try
204 {
205 writer.write(currentApplication.getID());
206 writer.write("\n");
207
208 byte[] key = publicKey.getEncoded();
209 writer.write(new String(Base64.encode(key), TrustedApplicationUtils.Constant.CHARSET_NAME));
210 writer.write("\n");
211 writer.write(TrustedApplicationUtils.Constant.VERSION.toString());
212 writer.write("\n");
213 writer.write(TrustedApplicationUtils.Constant.MAGIC);
214 writer.flush();
215 }
216 catch (UnsupportedEncodingException ex)
217 {
218 throw new AssertionError(ex);
219 }
220 catch (IOException e)
221 {
222 throw new RuntimeException(e);
223 }
224 }
225 }
226 }