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