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