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.HttpPrincipal;
030 import com.liferay.portal.security.auth.PrincipalException;
031 import com.liferay.portal.util.PropsValues;
032 import com.liferay.util.Encryptor;
033
034 import java.io.EOFException;
035 import java.io.IOException;
036 import java.io.ObjectInputStream;
037 import java.io.ObjectOutputStream;
038
039 import java.net.HttpURLConnection;
040 import java.net.URL;
041
042 import java.security.InvalidKeyException;
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
056 public class TunnelUtil {
057
058 public static Key getSharedSecretKey() throws InvalidKeyException {
059 String sharedSecret = PropsValues.TUNNELING_SERVLET_SHARED_SECRET;
060
061 if (Validator.isNull(sharedSecret)) {
062 throw new InvalidKeyException(
063 "The tunneling servlet shared secret is not set");
064 }
065
066 if ((sharedSecret.length() != 16) && (sharedSecret.length() != 32) &&
067 (sharedSecret.length() != 64)) {
068
069 throw new InvalidKeyException(
070 "The tunneling servlet shared secret must be 16, 32 or 64 " +
071 "characters long");
072 }
073
074 return new SecretKeySpec(
075 sharedSecret.getBytes(), _TUNNEL_ENCRYPTION_ALGORITHM);
076 }
077
078 public static Object invoke(
079 HttpPrincipal httpPrincipal, MethodHandler methodHandler)
080 throws Exception {
081
082 String password = Encryptor.encrypt(
083 getSharedSecretKey(), httpPrincipal.getLogin());
084
085 httpPrincipal.setPassword(password);
086
087 HttpURLConnection httpURLConnection = _getConnection(httpPrincipal);
088
089 ObjectOutputStream objectOutputStream = new ObjectOutputStream(
090 httpURLConnection.getOutputStream());
091
092 objectOutputStream.writeObject(
093 new ObjectValuePair<HttpPrincipal, MethodHandler>(
094 httpPrincipal, methodHandler));
095
096 objectOutputStream.flush();
097
098 objectOutputStream.close();
099
100 Object returnObject = null;
101
102 try {
103 ObjectInputStream objectInputStream = new ObjectInputStream(
104 httpURLConnection.getInputStream());
105
106 returnObject = objectInputStream.readObject();
107
108 objectInputStream.close();
109 }
110 catch (EOFException eofe) {
111 if (_log.isDebugEnabled()) {
112 _log.debug("Unable to read object", eofe);
113 }
114 }
115 catch (IOException ioe) {
116 String ioeMessage = ioe.getMessage();
117
118 if ((ioeMessage != null) &&
119 ioeMessage.contains("HTTP response code: 401")) {
120
121 throw new PrincipalException(ioeMessage);
122 }
123 else {
124 throw ioe;
125 }
126 }
127
128 if ((returnObject != null) && returnObject instanceof Exception) {
129 throw (Exception)returnObject;
130 }
131
132 return returnObject;
133 }
134
135 private static HttpURLConnection _getConnection(HttpPrincipal httpPrincipal)
136 throws IOException {
137
138 if ((httpPrincipal == null) || (httpPrincipal.getUrl() == null)) {
139 return null;
140 }
141
142 URL url = new URL(httpPrincipal.getUrl() + "/api/liferay/do");
143
144 HttpURLConnection httpURLConnection =
145 (HttpURLConnection)url.openConnection();
146
147 httpURLConnection.setDoInput(true);
148 httpURLConnection.setDoOutput(true);
149
150 if (!_VERIFY_SSL_HOSTNAME &&
151 (httpURLConnection instanceof HttpsURLConnection)) {
152
153 HttpsURLConnection httpsURLConnection =
154 (HttpsURLConnection)httpURLConnection;
155
156 httpsURLConnection.setHostnameVerifier(
157 new HostnameVerifier() {
158
159 @Override
160 public boolean verify(String hostname, SSLSession session) {
161 return true;
162 }
163
164 }
165 );
166 }
167
168 httpURLConnection.setRequestProperty(
169 HttpHeaders.CONTENT_TYPE,
170 ContentTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT);
171 httpURLConnection.setUseCaches(false);
172
173 httpURLConnection.setRequestMethod(HttpMethods.POST);
174
175 if (Validator.isNotNull(httpPrincipal.getLogin()) &&
176 Validator.isNotNull(httpPrincipal.getPassword())) {
177
178 String userNameAndPassword =
179 httpPrincipal.getLogin() + StringPool.COLON +
180 httpPrincipal.getPassword();
181
182 httpURLConnection.setRequestProperty(
183 HttpHeaders.AUTHORIZATION,
184 HttpServletRequest.BASIC_AUTH + StringPool.SPACE +
185 Base64.encode(userNameAndPassword.getBytes()));
186 }
187
188 return httpURLConnection;
189 }
190
191 private static final String _TUNNEL_ENCRYPTION_ALGORITHM = "AES";
192
193 private static final boolean _VERIFY_SSL_HOSTNAME = GetterUtil.getBoolean(
194 PropsUtil.get(TunnelUtil.class.getName() + ".verify.ssl.hostname"));
195
196 private static Log _log = LogFactoryUtil.getLog(TunnelUtil.class);
197
198 }