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 ObjectOutputStream objectOutputStream = new ObjectOutputStream(
120 httpURLConnection.getOutputStream());
121
122 objectOutputStream.writeObject(
123 new ObjectValuePair<HttpPrincipal, MethodHandler>(
124 httpPrincipal, methodHandler));
125
126 objectOutputStream.flush();
127
128 objectOutputStream.close();
129
130 Object returnObject = null;
131
132 try {
133 ObjectInputStream objectInputStream = new ObjectInputStream(
134 httpURLConnection.getInputStream());
135
136 returnObject = objectInputStream.readObject();
137
138 objectInputStream.close();
139 }
140 catch (EOFException eofe) {
141 if (_log.isDebugEnabled()) {
142 _log.debug("Unable to read object", eofe);
143 }
144 }
145 catch (IOException ioe) {
146 String ioeMessage = ioe.getMessage();
147
148 if ((ioeMessage != null) &&
149 ioeMessage.contains("HTTP response code: 401")) {
150
151 throw new PrincipalException(ioeMessage);
152 }
153 else {
154 throw ioe;
155 }
156 }
157
158 if ((returnObject != null) && returnObject instanceof Exception) {
159 throw (Exception)returnObject;
160 }
161
162 return returnObject;
163 }
164
165 private static HttpURLConnection _getConnection(HttpPrincipal httpPrincipal)
166 throws IOException {
167
168 if ((httpPrincipal == null) || (httpPrincipal.getUrl() == null)) {
169 return null;
170 }
171
172 URL url = new URL(httpPrincipal.getUrl() + "/api/liferay/do");
173
174 HttpURLConnection httpURLConnection =
175 (HttpURLConnection)url.openConnection();
176
177 httpURLConnection.setDoInput(true);
178 httpURLConnection.setDoOutput(true);
179
180 if (!_VERIFY_SSL_HOSTNAME &&
181 (httpURLConnection instanceof HttpsURLConnection)) {
182
183 HttpsURLConnection httpsURLConnection =
184 (HttpsURLConnection)httpURLConnection;
185
186 httpsURLConnection.setHostnameVerifier(
187 new HostnameVerifier() {
188
189 @Override
190 public boolean verify(String hostname, SSLSession session) {
191 return true;
192 }
193
194 }
195 );
196 }
197
198 httpURLConnection.setRequestProperty(
199 HttpHeaders.CONTENT_TYPE,
200 ContentTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT);
201 httpURLConnection.setUseCaches(false);
202
203 httpURLConnection.setRequestMethod(HttpMethods.POST);
204
205 if (Validator.isNotNull(httpPrincipal.getLogin()) &&
206 Validator.isNotNull(httpPrincipal.getPassword())) {
207
208 String userNameAndPassword =
209 httpPrincipal.getLogin() + StringPool.COLON +
210 httpPrincipal.getPassword();
211
212 httpURLConnection.setRequestProperty(
213 HttpHeaders.AUTHORIZATION,
214 HttpServletRequest.BASIC_AUTH + StringPool.SPACE +
215 Base64.encode(userNameAndPassword.getBytes()));
216 }
217
218 return httpURLConnection;
219 }
220
221 private static final boolean _VERIFY_SSL_HOSTNAME = GetterUtil.getBoolean(
222 PropsUtil.get(TunnelUtil.class.getName() + ".verify.ssl.hostname"));
223
224 private static Log _log = LogFactoryUtil.getLog(TunnelUtil.class);
225
226 }