1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.sharepoint;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.servlet.HttpHeaders;
20  import com.liferay.portal.kernel.servlet.HttpMethods;
21  import com.liferay.portal.kernel.util.Base64;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.StringPool;
24  import com.liferay.portal.model.Company;
25  import com.liferay.portal.model.CompanyConstants;
26  import com.liferay.portal.model.User;
27  import com.liferay.portal.security.auth.Authenticator;
28  import com.liferay.portal.security.auth.PrincipalException;
29  import com.liferay.portal.security.auth.PrincipalThreadLocal;
30  import com.liferay.portal.security.permission.PermissionChecker;
31  import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
32  import com.liferay.portal.security.permission.PermissionThreadLocal;
33  import com.liferay.portal.service.UserLocalServiceUtil;
34  import com.liferay.portal.servlet.filters.BasePortalFilter;
35  import com.liferay.portal.util.PortalUtil;
36  import com.liferay.portal.util.WebKeys;
37  
38  import java.util.HashMap;
39  import java.util.Map;
40  import java.util.StringTokenizer;
41  
42  import javax.servlet.FilterChain;
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpServletResponse;
45  import javax.servlet.http.HttpSession;
46  
47  /**
48   * <a href="SharepointFilter.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Bruno Farache
51   */
52  public class SharepointFilter extends BasePortalFilter {
53  
54      protected boolean isSharepointRequest(String uri) {
55          if (uri == null) {
56              return false;
57          }
58  
59          if (uri.endsWith("*.asmx")) {
60              return true;
61          }
62  
63          for (String prefix : _PREFIXES) {
64              if (uri.startsWith(prefix)) {
65                  return true;
66              }
67          }
68  
69          return false;
70      }
71  
72      protected User login(
73              HttpServletRequest request, HttpServletResponse response)
74          throws Exception {
75  
76          User user = null;
77  
78          // Get the Authorization header, if one was supplied
79  
80          String authorization = request.getHeader("Authorization");
81  
82          if (authorization == null) {
83              return user;
84          }
85  
86          StringTokenizer st = new StringTokenizer(authorization);
87  
88          if (!st.hasMoreTokens()) {
89              return user;
90          }
91  
92          String basic = st.nextToken();
93  
94          // We only handle HTTP Basic authentication
95  
96          if (!basic.equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
97              return user;
98          }
99  
100         String encodedCredentials = st.nextToken();
101 
102         if (_log.isDebugEnabled()) {
103             _log.debug("Encoded credentials are " + encodedCredentials);
104         }
105 
106         String decodedCredentials = new String(
107             Base64.decode(encodedCredentials));
108 
109         if (_log.isDebugEnabled()) {
110             _log.debug("Decoded credentials are " + decodedCredentials);
111         }
112 
113         int pos = decodedCredentials.indexOf(StringPool.COLON);
114 
115         if (pos == -1) {
116             return user;
117         }
118 
119         Company company = PortalUtil.getCompany(request);
120 
121         String login = GetterUtil.getString(
122             decodedCredentials.substring(0, pos));
123         long userId = GetterUtil.getLong(login);
124         String password = decodedCredentials.substring(pos + 1);
125 
126         Map<String, String[]> headerMap = new HashMap<String, String[]>();
127         Map<String, String[]> parameterMap = new HashMap<String, String[]>();
128 
129         int authResult = Authenticator.FAILURE;
130 
131         if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
132             authResult = UserLocalServiceUtil.authenticateByEmailAddress(
133                 company.getCompanyId(), login, password, headerMap,
134                 parameterMap);
135 
136             userId = UserLocalServiceUtil.getUserIdByEmailAddress(
137                 company.getCompanyId(), login);
138         }
139         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_SN)) {
140             authResult = UserLocalServiceUtil.authenticateByScreenName(
141                 company.getCompanyId(), login, password, headerMap,
142                 parameterMap);
143 
144             userId = UserLocalServiceUtil.getUserIdByScreenName(
145                 company.getCompanyId(), login);
146         }
147         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_ID)) {
148             authResult = UserLocalServiceUtil.authenticateByUserId(
149                 company.getCompanyId(), userId, password, headerMap,
150                 parameterMap);
151         }
152 
153         if (authResult == Authenticator.SUCCESS) {
154             user = UserLocalServiceUtil.getUser(userId);
155         }
156 
157         return user;
158     }
159 
160     protected void processFilter(
161             HttpServletRequest request, HttpServletResponse response,
162             FilterChain filterChain)
163         throws Exception {
164 
165         String method = request.getMethod();
166 
167         String userAgent = GetterUtil.getString(
168             request.getHeader(HttpHeaders.USER_AGENT));
169 
170         if ((userAgent.startsWith(
171                 "Microsoft Data Access Internet Publishing") ||
172              userAgent.startsWith("Microsoft Office Protocol Discovery")) &&
173             method.equals(HttpMethods.OPTIONS)) {
174 
175             setOptionsHeaders(response);
176 
177             return;
178         }
179 
180         if (!isSharepointRequest(request.getRequestURI())) {
181             processFilter(
182                 SharepointFilter.class, request, response, filterChain);
183 
184             return;
185         }
186 
187         if (method.equals(HttpMethods.GET) || method.equals(HttpMethods.HEAD)) {
188             setGetHeaders(response);
189         }
190         else if (method.equals(HttpMethods.POST)) {
191             setPostHeaders(response);
192         }
193 
194         HttpSession session = request.getSession();
195 
196         User user = (User)session.getAttribute(WebKeys.USER);
197 
198         try {
199             if (user == null) {
200                 user = login(request, response);
201 
202                 if (user == null) {
203                     throw new PrincipalException("User is null");
204                 }
205 
206                 session.setAttribute(WebKeys.USER, user);
207             }
208 
209             PrincipalThreadLocal.setName(user.getUserId());
210 
211             PermissionChecker permissionChecker =
212                 PermissionCheckerFactoryUtil.create(user, false);
213 
214             PermissionThreadLocal.setPermissionChecker(permissionChecker);
215 
216             processFilter(
217                 SharepointFilter.class, request, response, filterChain);
218         }
219         catch (Exception e) {
220             _log.error(e, e);
221 
222             response.setHeader("WWW-Authenticate", "BASIC realm=\"Liferay\"");
223 
224             response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
225 
226             response.flushBuffer();
227         }
228     }
229 
230     protected void setGetHeaders(HttpServletResponse response) {
231         response.setContentType("text/html");
232 
233         response.setHeader(
234             "Public-Extension", "http://schemas.microsoft.com/repl-2");
235         response.setHeader(
236             "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
237         response.setHeader("Cache-Control", "no-cache");
238     }
239 
240     protected void setOptionsHeaders(HttpServletResponse response) {
241         response.setHeader("MS-Author-Via", "MS-FP/4.0,DAV");
242         response.setHeader("MicrosoftOfficeWebServer", "5.0_Collab");
243         response.setHeader(
244             "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
245         response.setHeader("DAV", "1,2");
246         response.setHeader("Accept-Ranges", "none");
247         response.setHeader("Cache-Control", "no-cache");
248         response.setHeader(
249             "Allow",
250             "COPY, DELETE, GET, GETLIB, HEAD, LOCK, MKCOL, MOVE, OPTIONS, " +
251                 "POST, PROPFIND, PROPPATCH, PUT, UNLOCK");
252     }
253 
254     protected void setPostHeaders(HttpServletResponse response) {
255         response.setContentType("application/x-vermeer-rpc");
256 
257         response.setHeader(
258             "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
259         response.setHeader("Cache-Control", "no-cache");
260         response.setHeader("Connection", "close");
261     }
262 
263     private static final String[] _PREFIXES =
264         new String[] {
265             "/_vti_inf.html", "/_vti_bin", "/sharepoint", "/history",
266             "/resources"};
267 
268     private static Log _log = LogFactoryUtil.getLog(SharepointFilter.class);
269 
270 }