001
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.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.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.StringPool;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.security.auth.AuthException;
030 import com.liferay.portal.security.auth.HttpPrincipal;
031 import com.liferay.portal.security.auth.PrincipalException;
032 import com.liferay.portal.util.PropsValues;
033 import com.liferay.util.Encryptor;
034
035 import java.io.EOFException;
036 import java.io.IOException;
037 import java.io.ObjectInputStream;
038 import java.io.ObjectOutputStream;
039
040 import java.net.HttpURLConnection;
041 import java.net.URL;
042
043 import java.security.Key;
044
045 import javax.crypto.spec.SecretKeySpec;
046
047 import javax.net.ssl.HostnameVerifier;
048 import javax.net.ssl.HttpsURLConnection;
049 import javax.net.ssl.SSLSession;
050
051 import javax.servlet.http.HttpServletRequest;
052
053 import org.apache.commons.codec.DecoderException;
054 import org.apache.commons.codec.binary.Hex;
055
056
059 public class TunnelUtil {
060
061 public static Key getSharedSecretKey() throws AuthException {
062 String sharedSecret = PropsValues.TUNNELING_SERVLET_SHARED_SECRET;
063 boolean sharedSecretHex =
064 PropsValues.TUNNELING_SERVLET_SHARED_SECRET_HEX;
065
066 if (Validator.isNull(sharedSecret)) {
067 AuthException authException = new AuthException();
068
069 authException.setType(AuthException.NO_SHARED_SECRET);
070
071 throw authException;
072 }
073
074 byte[] key = null;
075
076 if (sharedSecretHex) {
077 try {
078 key = Hex.decodeHex(sharedSecret.toCharArray());
079 }
080 catch (DecoderException e) {
081 if (_log.isWarnEnabled()) {
082 _log.warn(e, e);
083 }
084
085 AuthException authException = new AuthException();
086
087 authException.setType(AuthException.INVALID_SHARED_SECRET);
088
089 throw authException;
090 }
091 }
092 else {
093 key = sharedSecret.getBytes();
094 }
095
096 if (key.length < 8) {
097 AuthException authException = new AuthException();
098
099 authException.setType(AuthException.INVALID_SHARED_SECRET);
100
101 throw authException;
102 }
103
104 return new SecretKeySpec(
105 key, PropsValues.TUNNELING_SERVLET_ENCRYPTION_ALGORITHM);
106 }
107
108 public static Object invoke(
109 HttpPrincipal httpPrincipal, MethodHandler methodHandler)
110 throws Exception {
111
112 String password = Encryptor.encrypt(
113 getSharedSecretKey(), httpPrincipal.getLogin());
114
115 httpPrincipal.setPassword(password);
116
117 HttpURLConnection httpURLConnection = _getConnection(httpPrincipal);
118
119 try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(
120 httpURLConnection.getOutputStream())) {
121
122 objectOutputStream.writeObject(
123 new ObjectValuePair<HttpPrincipal, MethodHandler>(
124 httpPrincipal, methodHandler));
125 }
126
127 Object returnObject = null;
128
129 try (ObjectInputStream objectInputStream = new ObjectInputStream(
130 httpURLConnection.getInputStream())) {
131
132 returnObject = objectInputStream.readObject();
133 }
134 catch (EOFException eofe) {
135 if (_log.isDebugEnabled()) {
136 _log.debug("Unable to read object", eofe);
137 }
138 }
139 catch (IOException ioe) {
140 String ioeMessage = ioe.getMessage();
141
142 if ((ioeMessage != null) &&
143 ioeMessage.contains("HTTP response code: 401")) {
144
145 throw new PrincipalException(ioeMessage);
146 }
147 else {
148 throw ioe;
149 }
150 }
151
152 if ((returnObject != null) && returnObject instanceof Exception) {
153 throw (Exception)returnObject;
154 }
155
156 return returnObject;
157 }
158
159 private static HttpURLConnection _getConnection(HttpPrincipal httpPrincipal)
160 throws IOException {
161
162 if ((httpPrincipal == null) || (httpPrincipal.getUrl() == null)) {
163 return null;
164 }
165
166 URL url = new URL(httpPrincipal.getUrl() + "/api/liferay/do");
167
168 HttpURLConnection httpURLConnection =
169 (HttpURLConnection)url.openConnection();
170
171 httpURLConnection.setDoInput(true);
172 httpURLConnection.setDoOutput(true);
173
174 if (!_VERIFY_SSL_HOSTNAME &&
175 (httpURLConnection instanceof HttpsURLConnection)) {
176
177 HttpsURLConnection httpsURLConnection =
178 (HttpsURLConnection)httpURLConnection;
179
180 httpsURLConnection.setHostnameVerifier(
181 new HostnameVerifier() {
182
183 @Override
184 public boolean verify(String hostname, SSLSession session) {
185 return true;
186 }
187
188 }
189 );
190 }
191
192 httpURLConnection.setRequestProperty(
193 HttpHeaders.CONTENT_TYPE,
194 ContentTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT);
195 httpURLConnection.setUseCaches(false);
196
197 httpURLConnection.setRequestMethod(HttpMethods.POST);
198
199 if (Validator.isNotNull(httpPrincipal.getLogin()) &&
200 Validator.isNotNull(httpPrincipal.getPassword())) {
201
202 String userNameAndPassword =
203 httpPrincipal.getLogin() + StringPool.COLON +
204 httpPrincipal.getPassword();
205
206 httpURLConnection.setRequestProperty(
207 HttpHeaders.AUTHORIZATION,
208 HttpServletRequest.BASIC_AUTH + StringPool.SPACE +
209 Base64.encode(userNameAndPassword.getBytes()));
210 }
211
212 return httpURLConnection;
213 }
214
215 private static final boolean _VERIFY_SSL_HOSTNAME = GetterUtil.getBoolean(
216 PropsUtil.get(TunnelUtil.class.getName() + ".verify.ssl.hostname"));
217
218 private static final Log _log = LogFactoryUtil.getLog(TunnelUtil.class);
219
220 }