1 package com.atlassian.seraph.config;
2
3 import com.atlassian.seraph.util.RedirectUtils;
4
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.util.Map;
8
9 import javax.servlet.http.HttpServletRequest;
10
11 public class DefaultRedirectPolicy implements RedirectPolicy
12 {
13 private boolean allowAnyUrl = false;
14
15 public void init(final Map<String, String> params, final SecurityConfig config)
16 {
17 // params is never allowed to be null.
18 if (params == null)
19 {
20 throw new IllegalArgumentException("params is not allowed to be null");
21 }
22 // Allow applications to set allow.any.redirect.url=true for legacy behaviour
23 allowAnyUrl = "true".equals(params.get("allow.any.redirect.url"));
24 }
25
26 /**
27 * Returns true if we allow redirect to any URL at all.
28 * By default this is false, however it may be configured to true in the Seraph config file to allow legacy behaviour.
29 *
30 * @return true if we allow redirect to any URL at all.
31 */
32 public boolean isAllowAnyUrl()
33 {
34 return allowAnyUrl;
35 }
36
37 /**
38 * Checks if the given redirectURL is permitted.
39 * <p/>
40 * Uses the configured redirect rules to see if we are allowed to redirect to the given URL.
41 * By default, the following is allowed:
42 * <ul>
43 * <li>Any relative URL</li>
44 * <li>An absolute URL to the same context path as the current incoming request</li>
45 * </ul>
46 * You can configure this "security-policy" in the Seraph XML config file.
47 * eg:
48 * <pre>
49 * <redirect-policy class="com.atlassian.seraph.config.SimpleRedirectPolicy">
50 * <init-param>
51 * <param-name>allow.any.redirect.url</param-name>
52 * <param-value>true</param-value>
53 * </init-param>
54 * </redirect-policy>
55 * </pre>
56 * <p/>
57 *
58 * @param redirectUrl Requested redirect URL to be verified.
59 * @param request The current incoming request.
60 * @return <code>true</code> if this redirectURL is allowed.
61 */
62 public boolean allowedRedirectDestination(final String redirectUrl, final HttpServletRequest request)
63 {
64 // Test for total trust
65 if (allowAnyUrl)
66 {
67 return true;
68 }
69 // Otherwise we use default behaviour: allow valid redirects to the same context.
70 URI uri;
71 try
72 {
73 // Attempt to parse the URI
74 uri = new URI(redirectUrl);
75 }
76 catch (final URISyntaxException e)
77 {
78 // Invalid URI - not allowed. This stops possible header injection attacks (see SER-127)
79 // but it is also good in general that if we can't parse a URI, then we can't trust it.
80 return false;
81 }
82 // The URI is valid - if it is absolute, then check that it is to the same context
83 return !uri.isAbsolute() || RedirectUtils.sameContext(redirectUrl, request);
84 }
85 }