001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.security;
029
030import org.opencms.file.CmsObject;
031import org.opencms.main.A_CmsAuthorizationHandler;
032import org.opencms.main.CmsException;
033import org.opencms.main.CmsHttpAuthenticationSettings;
034import org.opencms.main.OpenCms;
035import org.opencms.util.CmsRequestUtil;
036import org.opencms.workplace.CmsWorkplaceManager;
037
038import java.io.IOException;
039
040import javax.servlet.http.HttpServletRequest;
041import javax.servlet.http.HttpServletResponse;
042
043import org.apache.commons.codec.binary.Base64;
044
045/**
046 * Defines default authorization methods.<p>
047 *
048 * @since 6.5.4
049 */
050public class CmsDefaultAuthorizationHandler extends A_CmsAuthorizationHandler {
051
052    /** Basic authorization prefix constant. */
053    public static final String AUTHORIZATION_BASIC_PREFIX = "BASIC ";
054    /** Authorization header constant. */
055    public static final String HEADER_AUTHORIZATION = "Authorization";
056    /** Credentials separator constant. */
057    public static final String SEPARATOR_CREDENTIALS = ":";
058
059    /**
060     * @see org.opencms.security.I_CmsAuthorizationHandler#getLoginFormURL(java.lang.String, java.lang.String, java.lang.String)
061     */
062    public String getLoginFormURL(String loginFormURL, String params, String callbackURL) {
063
064        if (loginFormURL != null) {
065
066            StringBuffer fullURL = new StringBuffer(loginFormURL);
067            if (callbackURL != null) {
068                fullURL.append("?");
069                fullURL.append(CmsWorkplaceManager.PARAM_LOGIN_REQUESTED_RESOURCE);
070                fullURL.append("=");
071                fullURL.append(callbackURL);
072            }
073            if (params != null) {
074                fullURL.append((callbackURL != null) ? "&" : "?");
075                fullURL.append(params);
076            }
077
078            return fullURL.toString();
079        }
080
081        return null;
082    }
083
084    /**
085     * @see I_CmsAuthorizationHandler#initCmsObject(HttpServletRequest)
086     */
087    public CmsObject initCmsObject(HttpServletRequest request) {
088
089        // check if "basic" authorization data is provided
090        CmsObject cms = checkBasicAuthorization(request);
091        // basic authorization successful?
092        if (cms != null) {
093            try {
094                // register the session into OpenCms and
095                // return successful logged in user
096                return registerSession(request, cms);
097            } catch (CmsException e) {
098                // ignore and threat the whole login process as failed
099            }
100        }
101        // failed
102        return null;
103    }
104
105    /**
106     * @see org.opencms.security.I_CmsAuthorizationHandler#initCmsObject(javax.servlet.http.HttpServletRequest, org.opencms.security.I_CmsAuthorizationHandler.I_PrivilegedLoginAction)
107     */
108    public CmsObject initCmsObject(
109        HttpServletRequest request,
110        I_CmsAuthorizationHandler.I_PrivilegedLoginAction loginAction) {
111
112        return initCmsObject(request);
113    }
114
115    /**
116     * @see I_CmsAuthorizationHandler#initCmsObject(HttpServletRequest, String, String)
117     */
118    public CmsObject initCmsObject(HttpServletRequest request, String userName, String pwd) throws CmsException {
119
120        // first, try to validate the session
121        CmsObject cms = initCmsObjectFromSession(request);
122        if (cms != null) {
123            return cms;
124        }
125        // try to login with the given credentials
126        cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest());
127        // this will throw an exception if login fails
128        cms.loginUser(userName, pwd);
129        // register the session into OpenCms and
130        // return successful logged in user
131        return registerSession(request, cms);
132    }
133
134    /**
135     * This method sends a request to the client to display a login form,
136     * it is needed for HTTP-Authentication.<p>
137     *
138     * @param req the client request
139     * @param res the response
140     * @param loginFormURL the full URL used for form based authentication
141     *
142     * @throws IOException if something goes wrong
143     */
144    public void requestAuthorization(HttpServletRequest req, HttpServletResponse res, String loginFormURL)
145    throws IOException {
146
147        CmsHttpAuthenticationSettings httpAuthenticationSettings = OpenCms.getSystemInfo().getHttpAuthenticationSettings();
148
149        if (loginFormURL == null) {
150            if (httpAuthenticationSettings.useBrowserBasedHttpAuthentication()) {
151                // HTTP basic authentication is used
152                res.setHeader(
153                    CmsRequestUtil.HEADER_WWW_AUTHENTICATE,
154                    "BASIC realm=\"" + OpenCms.getSystemInfo().getOpenCmsContext() + "\"");
155                res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
156                return;
157
158            } else if (httpAuthenticationSettings.getFormBasedHttpAuthenticationUri() != null) {
159                loginFormURL = httpAuthenticationSettings.getFormBasedHttpAuthenticationUri();
160            } else {
161                LOG.error(
162                    Messages.get().getBundle().key(
163                        Messages.ERR_UNSUPPORTED_AUTHENTICATION_MECHANISM_1,
164                        httpAuthenticationSettings.getBrowserBasedAuthenticationMechanism()));
165                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
166                return;
167            }
168        }
169
170        if (LOG.isDebugEnabled()) {
171            LOG.debug(
172                Messages.get().getBundle().key(
173                    Messages.LOG_AUTHENTICATE_PROPERTY_2,
174                    loginFormURL,
175                    req.getRequestURI()));
176        }
177        // finally redirect to the login form
178        res.sendRedirect(loginFormURL);
179    }
180
181    /**
182     * Checks if the current request contains HTTP basic authentication information in
183     * the headers, if so the user is tried to log in with this data, and on success a
184     * session is generated.<p>
185     *
186     * @param req the current HTTP request
187     *
188     * @return the authenticated cms object, or <code>null</code> if failed
189     */
190    protected CmsObject checkBasicAuthorization(HttpServletRequest req) {
191
192        if (LOG.isDebugEnabled()) {
193            LOG.debug("Checking for basic authorization.");
194        }
195        try {
196            CmsObject cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest());
197            if (OpenCms.getSystemInfo().getHttpAuthenticationSettings().getBrowserBasedAuthenticationMechanism() == null) {
198                // browser base authorization is not enabled, return Guest user CmsObject
199                if (LOG.isDebugEnabled()) {
200                    LOG.debug("Browser based authorization not enabled.");
201                }
202                return cms;
203            }
204            // no user identified from the session and basic authentication is enabled
205            String auth = req.getHeader(HEADER_AUTHORIZATION);
206            if ((auth == null) || !auth.toUpperCase().startsWith(AUTHORIZATION_BASIC_PREFIX)) {
207                // no authorization data is available
208                return cms;
209            }
210            // get encoded user and password, following after "BASIC "
211            String base64Token = auth.substring(6);
212
213            // decode it, using base 64 decoder
214            String token = new String(Base64.decodeBase64(base64Token.getBytes()));
215            String username = null;
216            String password = null;
217            int pos = token.indexOf(SEPARATOR_CREDENTIALS);
218            if (pos != -1) {
219                username = token.substring(0, pos);
220                password = token.substring(pos + 1);
221            }
222            // authentication in the DB
223            cms.loginUser(username, password);
224
225            // authorization was successful create a session
226            req.getSession(true);
227            return cms;
228        } catch (CmsException e) {
229            // authorization failed
230            return null;
231        }
232    }
233}