001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.sharepoint;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.servlet.HttpHeaders;
020    import com.liferay.portal.kernel.servlet.HttpMethods;
021    import com.liferay.portal.kernel.util.Base64;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.model.Company;
025    import com.liferay.portal.model.CompanyConstants;
026    import com.liferay.portal.model.User;
027    import com.liferay.portal.security.auth.Authenticator;
028    import com.liferay.portal.security.auth.PrincipalException;
029    import com.liferay.portal.security.auth.PrincipalThreadLocal;
030    import com.liferay.portal.security.permission.PermissionChecker;
031    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
032    import com.liferay.portal.security.permission.PermissionThreadLocal;
033    import com.liferay.portal.service.UserLocalServiceUtil;
034    import com.liferay.portal.servlet.filters.BasePortalFilter;
035    import com.liferay.portal.util.PortalUtil;
036    import com.liferay.portal.util.WebKeys;
037    
038    import java.util.HashMap;
039    import java.util.Map;
040    import java.util.StringTokenizer;
041    
042    import javax.servlet.FilterChain;
043    import javax.servlet.http.HttpServletRequest;
044    import javax.servlet.http.HttpServletResponse;
045    import javax.servlet.http.HttpSession;
046    
047    /**
048     * @author Bruno Farache
049     */
050    public class SharepointFilter extends BasePortalFilter {
051    
052            protected boolean isSharepointRequest(String uri) {
053                    if (uri == null) {
054                            return false;
055                    }
056    
057                    if (uri.endsWith("*.asmx")) {
058                            return true;
059                    }
060    
061                    for (String prefix : _PREFIXES) {
062                            if (uri.startsWith(prefix)) {
063                                    return true;
064                            }
065                    }
066    
067                    return false;
068            }
069    
070            protected User login(
071                            HttpServletRequest request, HttpServletResponse response)
072                    throws Exception {
073    
074                    User user = null;
075    
076                    // Get the Authorization header, if one was supplied
077    
078                    String authorization = request.getHeader("Authorization");
079    
080                    if (authorization == null) {
081                            return user;
082                    }
083    
084                    StringTokenizer st = new StringTokenizer(authorization);
085    
086                    if (!st.hasMoreTokens()) {
087                            return user;
088                    }
089    
090                    String basic = st.nextToken();
091    
092                    // We only handle HTTP Basic authentication
093    
094                    if (!basic.equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
095                            return user;
096                    }
097    
098                    String encodedCredentials = st.nextToken();
099    
100                    if (_log.isDebugEnabled()) {
101                            _log.debug("Encoded credentials are " + encodedCredentials);
102                    }
103    
104                    String decodedCredentials = new String(
105                            Base64.decode(encodedCredentials));
106    
107                    if (_log.isDebugEnabled()) {
108                            _log.debug("Decoded credentials are " + decodedCredentials);
109                    }
110    
111                    int pos = decodedCredentials.indexOf(StringPool.COLON);
112    
113                    if (pos == -1) {
114                            return user;
115                    }
116    
117                    Company company = PortalUtil.getCompany(request);
118    
119                    String login = GetterUtil.getString(
120                            decodedCredentials.substring(0, pos));
121                    long userId = GetterUtil.getLong(login);
122                    String password = decodedCredentials.substring(pos + 1);
123    
124                    Map<String, String[]> headerMap = new HashMap<String, String[]>();
125                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
126    
127                    int authResult = Authenticator.FAILURE;
128    
129                    if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
130                            authResult = UserLocalServiceUtil.authenticateByEmailAddress(
131                                    company.getCompanyId(), login, password, headerMap,
132                                    parameterMap);
133    
134                            userId = UserLocalServiceUtil.getUserIdByEmailAddress(
135                                    company.getCompanyId(), login);
136                    }
137                    else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_SN)) {
138                            authResult = UserLocalServiceUtil.authenticateByScreenName(
139                                    company.getCompanyId(), login, password, headerMap,
140                                    parameterMap);
141    
142                            userId = UserLocalServiceUtil.getUserIdByScreenName(
143                                    company.getCompanyId(), login);
144                    }
145                    else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_ID)) {
146                            authResult = UserLocalServiceUtil.authenticateByUserId(
147                                    company.getCompanyId(), userId, password, headerMap,
148                                    parameterMap);
149                    }
150    
151                    if (authResult == Authenticator.SUCCESS) {
152                            user = UserLocalServiceUtil.getUser(userId);
153                    }
154    
155                    return user;
156            }
157    
158            protected void processFilter(
159                            HttpServletRequest request, HttpServletResponse response,
160                            FilterChain filterChain)
161                    throws Exception {
162    
163                    String method = request.getMethod();
164    
165                    String userAgent = GetterUtil.getString(
166                            request.getHeader(HttpHeaders.USER_AGENT));
167    
168                    if ((userAgent.startsWith(
169                                    "Microsoft Data Access Internet Publishing") ||
170                             userAgent.startsWith("Microsoft Office Protocol Discovery")) &&
171                            method.equals(HttpMethods.OPTIONS)) {
172    
173                            setOptionsHeaders(response);
174    
175                            return;
176                    }
177    
178                    if (!isSharepointRequest(request.getRequestURI())) {
179                            processFilter(
180                                    SharepointFilter.class, request, response, filterChain);
181    
182                            return;
183                    }
184    
185                    if (method.equals(HttpMethods.GET) || method.equals(HttpMethods.HEAD)) {
186                            setGetHeaders(response);
187                    }
188                    else if (method.equals(HttpMethods.POST)) {
189                            setPostHeaders(response);
190                    }
191    
192                    HttpSession session = request.getSession();
193    
194                    User user = (User)session.getAttribute(WebKeys.USER);
195    
196                    try {
197                            if (user == null) {
198                                    user = login(request, response);
199    
200                                    if (user == null) {
201                                            throw new PrincipalException("User is null");
202                                    }
203    
204                                    session.setAttribute(WebKeys.USER, user);
205                            }
206    
207                            PrincipalThreadLocal.setName(user.getUserId());
208    
209                            PermissionChecker permissionChecker =
210                                    PermissionCheckerFactoryUtil.create(user, false);
211    
212                            PermissionThreadLocal.setPermissionChecker(permissionChecker);
213    
214                            processFilter(
215                                    SharepointFilter.class, request, response, filterChain);
216                    }
217                    catch (Exception e) {
218                            _log.error(e, e);
219    
220                            response.setHeader("WWW-Authenticate", "BASIC realm=\"Liferay\"");
221    
222                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
223    
224                            response.flushBuffer();
225                    }
226            }
227    
228            protected void setGetHeaders(HttpServletResponse response) {
229                    response.setContentType("text/html");
230    
231                    response.setHeader(
232                            "Public-Extension", "http://schemas.microsoft.com/repl-2");
233                    response.setHeader(
234                            "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
235                    response.setHeader("Cache-Control", "no-cache");
236            }
237    
238            protected void setOptionsHeaders(HttpServletResponse response) {
239                    response.setHeader("MS-Author-Via", "MS-FP/4.0,DAV");
240                    response.setHeader("MicrosoftOfficeWebServer", "5.0_Collab");
241                    response.setHeader(
242                            "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
243                    response.setHeader("DAV", "1,2");
244                    response.setHeader("Accept-Ranges", "none");
245                    response.setHeader("Cache-Control", "no-cache");
246                    response.setHeader(
247                            "Allow",
248                            "COPY, DELETE, GET, GETLIB, HEAD, LOCK, MKCOL, MOVE, OPTIONS, " +
249                                    "POST, PROPFIND, PROPPATCH, PUT, UNLOCK");
250            }
251    
252            protected void setPostHeaders(HttpServletResponse response) {
253                    response.setContentType("application/x-vermeer-rpc");
254    
255                    response.setHeader(
256                            "MicrosoftSharePointTeamServices", SharepointUtil.VERSION);
257                    response.setHeader("Cache-Control", "no-cache");
258                    response.setHeader("Connection", "close");
259            }
260    
261            private static final String[] _PREFIXES =
262                    new String[] {
263                            "/_vti_inf.html", "/_vti_bin", "/sharepoint", "/history",
264                            "/resources"};
265    
266            private static Log _log = LogFactoryUtil.getLog(SharepointFilter.class);
267    
268    }