001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.CharPool;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.model.Company;
026    import com.liferay.portal.model.CompanyConstants;
027    import com.liferay.portal.model.User;
028    import com.liferay.portal.security.auth.Authenticator;
029    import com.liferay.portal.security.auth.PrincipalException;
030    import com.liferay.portal.security.auth.PrincipalThreadLocal;
031    import com.liferay.portal.security.permission.PermissionChecker;
032    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
033    import com.liferay.portal.security.permission.PermissionThreadLocal;
034    import com.liferay.portal.service.UserLocalServiceUtil;
035    import com.liferay.portal.servlet.filters.BasePortalFilter;
036    import com.liferay.portal.util.PortalUtil;
037    import com.liferay.portal.util.WebKeys;
038    
039    import java.util.HashMap;
040    import java.util.Map;
041    import java.util.StringTokenizer;
042    
043    import javax.servlet.FilterChain;
044    import javax.servlet.http.HttpServletRequest;
045    import javax.servlet.http.HttpServletResponse;
046    import javax.servlet.http.HttpSession;
047    
048    /**
049     * @author Bruno Farache
050     */
051    public class SharepointFilter extends BasePortalFilter {
052    
053            protected boolean isSharepointRequest(String uri) {
054                    if (uri == null) {
055                            return false;
056                    }
057    
058                    if (uri.endsWith("*.asmx")) {
059                            return true;
060                    }
061    
062                    for (String prefix : _PREFIXES) {
063                            if (uri.startsWith(prefix)) {
064                                    return true;
065                            }
066                    }
067    
068                    return false;
069            }
070    
071            protected User login(
072                            HttpServletRequest request, HttpServletResponse response)
073                    throws Exception {
074    
075                    User user = null;
076    
077                    // Get the Authorization header, if one was supplied
078    
079                    String authorization = request.getHeader("Authorization");
080    
081                    if (authorization == null) {
082                            return user;
083                    }
084    
085                    StringTokenizer st = new StringTokenizer(authorization);
086    
087                    if (!st.hasMoreTokens()) {
088                            return user;
089                    }
090    
091                    String basic = st.nextToken();
092    
093                    // We only handle HTTP Basic authentication
094    
095                    if (!basic.equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
096                            return user;
097                    }
098    
099                    String encodedCredentials = st.nextToken();
100    
101                    if (_log.isDebugEnabled()) {
102                            _log.debug("Encoded credentials are " + encodedCredentials);
103                    }
104    
105                    String decodedCredentials = new String(
106                            Base64.decode(encodedCredentials));
107    
108                    if (_log.isDebugEnabled()) {
109                            _log.debug("Decoded credentials are " + decodedCredentials);
110                    }
111    
112                    int pos = decodedCredentials.indexOf(CharPool.COLON);
113    
114                    if (pos == -1) {
115                            return user;
116                    }
117    
118                    Company company = PortalUtil.getCompany(request);
119    
120                    String login = GetterUtil.getString(
121                            decodedCredentials.substring(0, pos));
122                    long userId = GetterUtil.getLong(login);
123                    String password = decodedCredentials.substring(pos + 1);
124    
125                    Map<String, String[]> headerMap = new HashMap<String, String[]>();
126                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
127                    Map<String, Object> resultsMap = new HashMap<String, Object>();
128    
129                    int authResult = Authenticator.FAILURE;
130    
131                    String authType = company.getAuthType();
132    
133                    if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
134                            authResult = UserLocalServiceUtil.authenticateByEmailAddress(
135                                    company.getCompanyId(), login, password, headerMap,
136                                    parameterMap, resultsMap);
137    
138                            userId = MapUtil.getLong(resultsMap, "userId", userId);
139                    }
140                    else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
141                            authResult = UserLocalServiceUtil.authenticateByScreenName(
142                                    company.getCompanyId(), login, password, headerMap,
143                                    parameterMap, resultsMap);
144    
145                            userId = MapUtil.getLong(resultsMap, "userId", userId);
146                    }
147                    else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
148                            authResult = UserLocalServiceUtil.authenticateByUserId(
149                                    company.getCompanyId(), userId, password, headerMap,
150                                    parameterMap, resultsMap);
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    }