1 package com.atlassian.security.auth.trustedapps.filter;
2
3 import com.atlassian.security.auth.trustedapps.*;
4 import junit.framework.TestCase;
5
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8 import java.security.KeyPair;
9 import java.security.NoSuchAlgorithmException;
10 import java.security.NoSuchProviderException;
11 import java.security.Principal;
12
13
14
15
16 public class TestTrustedApplicationsFilterAuthenticate extends TestCase
17 {
18
19
20
21
22 private final EncryptionProvider provider = new BouncyCastleEncryptionProvider();
23 private final TrustedApplicationsManager manager = new TrustedApplicationsManager()
24 {
25 final KeyPair pair;
26 final CurrentApplication me;
27
28 {
29 try
30 {
31 pair = provider.generateNewKeyPair();
32 }
33 catch (NoSuchAlgorithmException e)
34 {
35 throw new RuntimeException(e);
36 }
37 catch (NoSuchProviderException e)
38 {
39 throw new RuntimeException(e);
40 }
41 me = new DefaultCurrentApplication(pair.getPublic(), pair.getPrivate(), "me");
42 }
43
44 public CurrentApplication getCurrentApplication()
45 {
46 return me;
47 }
48
49 public TrustedApplication getTrustedApplication(String id)
50 {
51 if (id.equals("me"))
52 {
53 return new DefaultTrustedApplication(provider, pair.getPublic(), "me", RequestConditions.builder().setCertificateTimeout(1000L).build())
54 {
55 @Override
56 protected void checkRequest(HttpServletRequest request) throws InvalidCertificateException
57 {
58 try
59 {
60 if (request.getHeader("ip-mismatch") != null)
61 {
62 throw new InvalidRemoteAddressException(request.getRemoteAddr());
63 }
64 if (request.getHeader("forward-mismatch") != null)
65 {
66 throw new InvalidXForwardedForAddressException(request.getRemoteAddr());
67 }
68 if (request.getHeader("url-mismatch") != null)
69 {
70 throw new InvalidRequestUrlException(request.getPathInfo());
71 }
72 }
73 catch (final InvalidRequestException e)
74 {
75 throw new InvalidCertificateException(e);
76 }
77 }
78 };
79 }
80 return null;
81 }
82 };
83
84 private Principal principal = null;
85 private final UserResolver userResolver = new UserResolver()
86 {
87 public Principal resolve(ApplicationCertificate certificate)
88 {
89 return principal;
90 }
91 };
92 private final TrustedApplicationsFilter filter = new TrustedApplicationsFilter(manager, userResolver, new AuthenticationController()
93 {
94 public boolean canLogin(Principal user, HttpServletRequest request)
95 {
96 return true;
97 }
98
99 public boolean shouldAttemptAuthentication(HttpServletRequest request)
100 {
101 return true;
102 }
103
104 }, new AuthenticationListener()
105 {
106 public void authenticationSuccess(Authenticator.Result result, HttpServletRequest request, HttpServletResponse response)
107 {
108 }
109
110 public void authenticationFailure(Authenticator.Result result, HttpServletRequest request, HttpServletResponse response)
111 {
112 }
113
114 public void authenticationError(Authenticator.Result result, HttpServletRequest request, HttpServletResponse response)
115 {
116 }
117
118 public void authenticationNotAttempted(HttpServletRequest request, HttpServletResponse response)
119 {
120 }
121 })
122 {
123 };
124
125 protected void setUp() throws Exception
126 {
127 principal = null;
128 }
129
130
131
132
133
134 public void testNoTrustedAppAttempt() throws Exception
135 {
136 MockRequest request = new MockRequest("/some/path");
137 MockResponse response = new MockResponse();
138 assertFalse(filter.authenticate(request, response));
139
140 final String error = (String) response.getHeaders().get(TrustedApplicationUtils.Header.Response.ERROR);
141 assertNull(error, error);
142 }
143
144 public void testKnownAppProtocolVersion0() throws Exception
145 {
146 CurrentApplication me = manager.getCurrentApplication();
147 principal = new Principal()
148 {
149 public String getName()
150 {
151 return "blah-de-blah-blah";
152 }
153 };
154 EncryptedCertificate cert = me.encode("blah-de-blah-blah");
155 MockRequest request = new MockTrustedAppRequestV0(cert);
156 MockResponse response = new MockResponse();
157 assertTrue(filter.authenticate(request, response));
158
159 final String error = (String) response.getHeaders().get(TrustedApplicationUtils.Header.Response.ERROR);
160 assertNull(error, error);
161 }
162
163 public void testKnownAppProtocolVersion1() throws Exception
164 {
165 CurrentApplication me = manager.getCurrentApplication();
166 principal = new Principal()
167 {
168 public String getName()
169 {
170 return "blah-de-blah-blah";
171 }
172 };
173 EncryptedCertificate cert = me.encode("blah-de-blah-blah");
174 MockRequest request = new MockTrustedAppRequestV0(cert);
175
176 MockResponse response = new MockResponse();
177 assertTrue(filter.authenticate(request, response));
178
179 final String error = (String) response.getHeaders().get(TrustedApplicationUtils.Header.Response.ERROR);
180 assertNull(error, error);
181 }
182
183 public void testUnknownApp() throws Exception
184 {
185 EncryptedCertificate cert = new EncryptedCertificate()
186 {
187 public String getCertificate()
188 {
189 return "some-cert";
190 }
191
192 public String getID()
193 {
194 return "appId";
195 }
196
197 public String getMagicNumber()
198 {
199 return "dis is majick";
200 }
201
202 public Integer getProtocolVersion()
203 {
204 return new Integer(1);
205 }
206
207 public String getSecretKey()
208 {
209 return "dis-is-a-sekrit";
210 }
211 };
212 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
213 assertFailed("Unknown Application:", request);
214 }
215
216 public void testBadSecretKey() throws Exception
217 {
218 CurrentApplication me = manager.getCurrentApplication();
219 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
220 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
221 request.addHeader(TrustedApplicationUtils.Header.Request.SECRET_KEY, "0123981237123827234842374");
222 assertError("BAD_MAGIC;\tUnable to decrypt certificate {0} for application {1};\t[\"secret key\",\"me\"]", request);
223 }
224
225 public void testBadCertificate() throws Exception
226 {
227 CurrentApplication me = manager.getCurrentApplication();
228 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
229 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
230 request.addHeader(TrustedApplicationUtils.Header.Request.CERTIFICATE, "0123981237123827234842374");
231 assertError("BAD_MAGIC;\tUnable to decrypt certificate {0} for application {1};\t[\"secret key\",\"me\"]", request);
232 }
233
234 public void testBadPublicKey() throws Exception
235 {
236 CurrentApplication me = manager.getCurrentApplication();
237 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
238 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
239 request.addHeader(TrustedApplicationUtils.Header.Request.MAGIC, "123798211233723187217");
240 assertError("BAD_MAGIC;\tUnable to decrypt certificate {0} for application {1};\t[\"public key\",\"me\"]", request);
241 }
242
243 public void testBadRequestIp() throws Exception
244 {
245 CurrentApplication me = manager.getCurrentApplication();
246 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
247 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
248 request.addHeader("ip-mismatch", "true");
249 assertError("BAD_REMOTE_IP;\tRequest not allowed from IP address: {0};\t[\"i.am.a.teapot\"]", request);
250 }
251
252 public void testBadXForwardIp() throws Exception
253 {
254 CurrentApplication me = manager.getCurrentApplication();
255 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
256 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1(cert);
257 request.addHeader("forward-mismatch", "true");
258 assertError("BAD_XFORWARD_IP;\tRequest not allowed from IP address: {0};\t[\"i.am.a.teapot\"]", request);
259 }
260
261 public void testBadRequestUrl() throws Exception
262 {
263 CurrentApplication me = manager.getCurrentApplication();
264 EncryptedCertificate cert = me.encode("blad-de-blah-blah");
265 MockTrustedAppRequestV1 request = new MockTrustedAppRequestV1("/jira/secure/DeleteProject.jspa", cert);
266 request.addHeader("url-mismatch", "true");
267 assertError("BAD_URL;\tRequest not allowed to access URL: {0};\t[\"/jira/secure/DeleteProject.jspa\"]", request);
268 }
269
270
271
272
273
274 private void assertFailed(String msg, MockRequest request)
275 {
276 MockResponse response = new MockResponse();
277
278 assertFalse(filter.authenticate(request, response));
279
280 final String error = (String) response.getHeaders().get(TrustedApplicationUtils.Header.Response.ERROR);
281 System.out.println(error);
282 assertNotNull(error);
283 assertTrue("Expected: '" + msg + "' got:" + error, error.indexOf(msg) >= 0);
284 }
285
286 private void assertError(String msg, MockRequest request)
287 {
288 MockResponse response = new MockResponse();
289
290 assertFalse(filter.authenticate(request, response));
291
292 final String error = (String) response.getHeaders().get(TrustedApplicationUtils.Header.Response.ERROR);
293 System.out.println(error);
294 assertNotNull(error);
295 assertEquals(msg, error);
296
297 }
298 }