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