001    /**
002     * Copyright (c) 2000-present 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.service.http;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.auth.tunnel.TunnelAuthenticationManagerUtil;
020    import com.liferay.portal.kernel.servlet.HttpHeaders;
021    import com.liferay.portal.kernel.servlet.HttpMethods;
022    import com.liferay.portal.kernel.util.ContentTypes;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.MethodHandler;
025    import com.liferay.portal.kernel.util.ObjectValuePair;
026    import com.liferay.portal.kernel.util.PropsUtil;
027    import com.liferay.portal.kernel.util.ProtectedClassLoaderObjectInputStream;
028    import com.liferay.portal.security.auth.HttpPrincipal;
029    import com.liferay.portal.security.auth.PrincipalException;
030    
031    import java.io.EOFException;
032    import java.io.IOException;
033    import java.io.ObjectInputStream;
034    import java.io.ObjectOutputStream;
035    
036    import java.net.HttpURLConnection;
037    import java.net.URL;
038    
039    import javax.net.ssl.HostnameVerifier;
040    import javax.net.ssl.HttpsURLConnection;
041    import javax.net.ssl.SSLSession;
042    
043    /**
044     * @author Brian Wing Shun Chan
045     */
046    public class TunnelUtil {
047    
048            public static Object invoke(
049                            HttpPrincipal httpPrincipal, MethodHandler methodHandler)
050                    throws Exception {
051    
052                    HttpURLConnection httpURLConnection = _getConnection(httpPrincipal);
053    
054                    TunnelAuthenticationManagerUtil.setCredentials(
055                            httpPrincipal.getLogin(), httpURLConnection);
056    
057                    try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(
058                                    httpURLConnection.getOutputStream())) {
059    
060                            objectOutputStream.writeObject(
061                                    new ObjectValuePair<HttpPrincipal, MethodHandler>(
062                                            httpPrincipal, methodHandler));
063                    }
064    
065                    Object returnObject = null;
066    
067                    Thread thread = Thread.currentThread();
068    
069                    try (ObjectInputStream objectInputStream =
070                                    new ProtectedClassLoaderObjectInputStream(
071                                            httpURLConnection.getInputStream(),
072                                            thread.getContextClassLoader())) {
073    
074                            returnObject = objectInputStream.readObject();
075                    }
076                    catch (EOFException eofe) {
077                            if (_log.isDebugEnabled()) {
078                                    _log.debug("Unable to read object", eofe);
079                            }
080                    }
081                    catch (IOException ioe) {
082                            String ioeMessage = ioe.getMessage();
083    
084                            if ((ioeMessage != null) &&
085                                    ioeMessage.contains("HTTP response code: 401")) {
086    
087                                    throw new PrincipalException.MustBeAuthenticated(
088                                            httpPrincipal.getLogin());
089                            }
090                            else {
091                                    throw ioe;
092                            }
093                    }
094    
095                    if ((returnObject != null) && returnObject instanceof Exception) {
096                            throw (Exception)returnObject;
097                    }
098    
099                    return returnObject;
100            }
101    
102            private static HttpURLConnection _getConnection(HttpPrincipal httpPrincipal)
103                    throws IOException {
104    
105                    if ((httpPrincipal == null) || (httpPrincipal.getUrl() == null)) {
106                            return null;
107                    }
108    
109                    URL url = new URL(httpPrincipal.getUrl() + "/api/liferay/do");
110    
111                    HttpURLConnection httpURLConnection =
112                            (HttpURLConnection)url.openConnection();
113    
114                    httpURLConnection.setDoInput(true);
115                    httpURLConnection.setDoOutput(true);
116    
117                    if (!_VERIFY_SSL_HOSTNAME &&
118                            (httpURLConnection instanceof HttpsURLConnection)) {
119    
120                            HttpsURLConnection httpsURLConnection =
121                                    (HttpsURLConnection)httpURLConnection;
122    
123                            httpsURLConnection.setHostnameVerifier(
124                                    new HostnameVerifier() {
125    
126                                            @Override
127                                            public boolean verify(String hostname, SSLSession session) {
128                                                    return true;
129                                            }
130    
131                                    }
132                            );
133                    }
134    
135                    httpURLConnection.setRequestProperty(
136                            HttpHeaders.CONTENT_TYPE,
137                            ContentTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT);
138                    httpURLConnection.setUseCaches(false);
139    
140                    httpURLConnection.setRequestMethod(HttpMethods.POST);
141    
142                    return httpURLConnection;
143            }
144    
145            private static final boolean _VERIFY_SSL_HOSTNAME = GetterUtil.getBoolean(
146                    PropsUtil.get(TunnelUtil.class.getName() + ".verify.ssl.hostname"));
147    
148            private static final Log _log = LogFactoryUtil.getLog(TunnelUtil.class);
149    
150    }