1 package com.atlassian.seraph.filter;
2
3 import com.atlassian.seraph.SecurityService;
4 import com.atlassian.seraph.auth.AuthType;
5 import com.atlassian.seraph.auth.AuthenticationContext;
6 import com.atlassian.seraph.auth.Authenticator;
7 import com.atlassian.seraph.config.SecurityConfig;
8 import com.atlassian.seraph.config.SecurityConfigFactory;
9 import com.atlassian.seraph.util.RedirectUtils;
10 import com.atlassian.seraph.util.SecurityUtils;
11 import org.apache.log4j.Category;
12
13 import javax.servlet.*;
14 import javax.servlet.http.Cookie;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17 import java.io.IOException;
18 import java.security.Principal;
19 import java.util.HashSet;
20 import java.util.Set;
21
22
23
24
25
26
27 public class SecurityFilter implements Filter
28 {
29 private FilterConfig config = null;
30 private SecurityConfig securityConfig = null;
31
32 private static final Category log = Category.getInstance(SecurityFilter.class);
33 static final String ALREADY_FILTERED = "os_securityfilter_already_filtered";
34 public static final String ORIGINAL_URL = "atlassian.core.seraph.original.url";
35
36 public void init(final FilterConfig config)
37 {
38 log.debug("SecurityFilter.init");
39 this.config = config;
40
41 String configFileLocation = null;
42
43 if (config.getInitParameter("config.file") != null)
44 {
45 configFileLocation = config.getInitParameter("config.file");
46 log.debug("Security config file location: " + configFileLocation);
47 }
48
49 securityConfig = SecurityConfigFactory.getInstance(configFileLocation);
50 config.getServletContext().setAttribute(SecurityConfig.STORAGE_KEY, securityConfig);
51 log.debug("SecurityFilter.init completed successfully.");
52 }
53
54 public void destroy()
55 {
56 log.debug("SecurityFilter.destroy");
57
58 if (securityConfig == null)
59 {
60 log.warn("Trying to destroy a SecurityFilter with null securityConfig.");
61 }
62 else
63 {
64
65 securityConfig.destroy();
66 securityConfig = null;
67 }
68 config = null;
69 }
70
71 public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException
72 {
73 if ((req.getAttribute(ALREADY_FILTERED) != null) || !getSecurityConfig().getController().isSecurityEnabled())
74 {
75 chain.doFilter(req, res);
76 return;
77 }
78 else
79 {
80 req.setAttribute(ALREADY_FILTERED, Boolean.TRUE);
81 }
82
83 final String METHOD = "doFilter : ";
84 final boolean dbg = log.isDebugEnabled();
85
86
87
88 if (!SecurityUtils.isSeraphFilteringDisabled(req))
89 {
90 log.warn(METHOD + "LoginFilter not yet applied to this request - terminating filter chain");
91 return;
92 }
93
94 final HttpServletRequest httpServletRequest = (HttpServletRequest) req;
95 final HttpServletResponse httpServletResponse = (HttpServletResponse) res;
96
97 final String originalURL = httpServletRequest.getServletPath() + (httpServletRequest.getPathInfo() == null ? "" : httpServletRequest.getPathInfo()) + (httpServletRequest.getQueryString() == null ? "" : "?" + httpServletRequest.getQueryString());
98
99
100 httpServletRequest.setAttribute(SecurityFilter.ORIGINAL_URL, originalURL);
101 if (dbg)
102 {
103 log.debug(METHOD + "Storing the originally requested URL (" + SecurityFilter.ORIGINAL_URL + "=" + originalURL + ")");
104 }
105
106 final Set<String> requiredRoles = new HashSet<String>();
107
108
109 for (final SecurityService service : getSecurityConfig().getServices())
110 {
111 final Set<String> serviceRoles = service.getRequiredRoles(httpServletRequest);
112 requiredRoles.addAll(serviceRoles);
113 }
114
115 if (dbg)
116 {
117 log.debug(METHOD + "requiredRoles = " + requiredRoles);
118 }
119
120
121 boolean needAuth = false;
122
123
124 final Authenticator authenticator = getSecurityConfig().getAuthenticator();
125 final Principal user = authenticator.getUser(httpServletRequest, httpServletResponse);
126
127 if (user == null)
128 {
129 AuthType authType = AuthType.getAuthTypeInformation(httpServletRequest, getSecurityConfig());
130
131
132
133 if (RedirectUtils.isBasicAuthentication(httpServletRequest, getSecurityConfig().getAuthType()))
134 {
135
136 return;
137 }
138 else if (authType == AuthType.COOKIE && httpServletRequest.getSession(false) == null)
139 {
140 httpServletResponse.sendError(401, "os_authType was 'cookie' but no valid cookie was sent.");
141 return;
142 }
143 else if (authType == AuthType.ANY)
144 {
145
146
147 if (hasJSessionCookie(httpServletRequest.getCookies()) && httpServletRequest.getSession(false) == null)
148 {
149 httpServletResponse.sendError(401, "os_authType was 'any' and an invalid cookie was sent.");
150 return;
151 }
152 }
153 }
154
155
156 if (dbg)
157 {
158 log.debug(METHOD + "Setting Auth Context to be '" + (user == null ? "anonymous " : user.getName()) + "'");
159 }
160
161 final AuthenticationContext authenticationContext = getAuthenticationContext();
162 authenticationContext.setUser(user);
163
164
165
166 for (final Object element : requiredRoles)
167 {
168 final String role = (String) element;
169
170
171
172 if (!getSecurityConfig().getRoleMapper().hasRole(user, httpServletRequest, role))
173 {
174 log.info(METHOD + "'" + user + "' needs (and lacks) role '" + role + "' to access " + originalURL);
175 needAuth = true;
176 }
177 }
178
179
180 if ((httpServletRequest.getServletPath() != null) && httpServletRequest.getServletPath().equals(getSecurityConfig().getLoginURL()))
181 {
182 if (dbg)
183 {
184 log.debug(METHOD + "Login page requested so no additional authorization required.");
185 }
186 needAuth = false;
187 }
188
189
190 if (needAuth)
191 {
192 if (dbg)
193 {
194 log.debug(METHOD + "Need Authentication: Redirecting to: " + getSecurityConfig().getLoginURL() + " from: " + originalURL);
195 }
196
197 httpServletRequest.getSession().setAttribute(getSecurityConfig().getOriginalURLKey(), originalURL);
198
199 if (!httpServletResponse.isCommitted())
200 {
201 httpServletResponse.sendRedirect(RedirectUtils.getLoginUrl(httpServletRequest));
202 }
203
204
205 return;
206 }
207 else
208 {
209 try
210 {
211 chain.doFilter(req, res);
212 }
213 finally
214 {
215
216 authenticationContext.clearUser();
217 }
218 }
219 }
220
221 private boolean hasJSessionCookie(final Cookie[] cookies)
222 {
223 if (cookies == null)
224 {
225 return false;
226 }
227
228 for (Cookie cookie : cookies)
229 {
230 if (cookie.getName().equals("JSESSIONID"))
231 {
232 return true;
233 }
234 }
235
236 return false;
237 }
238
239 protected SecurityConfig getSecurityConfig()
240 {
241
242 if (securityConfig == null)
243 {
244 securityConfig = (SecurityConfig) config.getServletContext().getAttribute(SecurityConfig.STORAGE_KEY);
245 }
246 return securityConfig;
247 }
248
249 protected AuthenticationContext getAuthenticationContext()
250 {
251 return getSecurityConfig().getAuthenticationContext();
252 }
253
254 }