package org.ovirt.engine.core.aaa.filters;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Enumeration;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HeaderElement;
import org.apache.http.conn.util.InetAddressUtils;
import org.apache.http.message.BasicHeaderValueParser;
import org.ovirt.engine.core.aaa.SsoOAuthServiceUtils;
import org.ovirt.engine.core.common.constants.SessionConstants;
import org.ovirt.engine.core.common.interfaces.BackendLocal;
import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.utils.EngineLocalConfig;
public class FiltersHelper {
private static SecureRandom secureRandom;
public static class Constants {
public static final String REQUEST_AUTH_RECORD_KEY = "ovirt_aaa_auth_record";
public static final String REQUEST_SCHEMES_KEY = "ovirt_aaa_schemes";
public static final String REQUEST_PROFILE_KEY = "ovirt_aaa_profile";
public static final String REQUEST_AUTH_TYPE_KEY = "ovirt_aaa_auth_type";
public static final String REQUEST_LOGIN_FILTER_AUTHENTICATION_DONE =
"ovirt_aaa_login_filter_authentication_done";
public static final String HEADER_AUTHORIZATION = "Authorization";
public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
public static final String HEADER_PREFER = "Prefer";
public static final String LOGOUT_INPROGRESS = "LOGOUT_INPROGRESS";
}
public static final int PREFER_NEW_AUTH = 1<<0;
public static final int PREFER_PERSISTENCE_AUTH = 1<<1;
public static BackendLocal getBackend(Context context) {
try {
return (BackendLocal) context.lookup("java:global/engine/bll/Backend!org.ovirt.engine.core.common.interfaces.BackendLocal");
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
public static boolean isAuthenticated(HttpServletRequest request) {
return (request.getSession(false) != null && request.getSession(false)
.getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY) != null)
|| request.getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY) != null;
}
public static boolean isStatusOk(Map<String, Object> response) {
if (response.get("error") != null) {
throw new RuntimeException(String.format("%s: %s", response.get("error_code"), response.get("error")));
}
return true;
}
public static boolean isSessionValid(HttpServletRequest req) {
String engineSessionId = (String) req.getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY);
if (StringUtils.isEmpty(engineSessionId)) {
engineSessionId = (String) req.getSession(true).getAttribute(SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY);
}
return isSessionValid(engineSessionId);
}
public static boolean isSessionValid(String session) {
try {
InitialContext ctx = null;
try {
ctx = new InitialContext();
VdcQueryReturnValue returnValue =
FiltersHelper.getBackend(ctx)
.runPublicQuery(VdcQueryType.ValidateSession,
new VdcQueryParametersBase(session));
return returnValue.getSucceeded();
} finally {
if (ctx != null) {
ctx.close();
}
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static String generateState() throws NoSuchAlgorithmException {
if (secureRandom == null) {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
}
byte[] s = new byte[8];
secureRandom.nextBytes(s);
return new Base64(0, new byte[0], true).encodeToString(s);
}
public static String getEngineUrl(HttpServletRequest request) {
return String.format("%s://%s:%s%s",
request.getScheme(),
FiltersHelper.getRedirectUriServerName(request.getServerName()),
request.getServerPort(),
EngineLocalConfig.getInstance().getProperty("ENGINE_URI"));
}
public static String getEngineSsoUrl(HttpServletRequest request) {
if (EngineLocalConfig.getInstance().getBoolean("ENGINE_SSO_INSTALLED_ON_ENGINE_HOST")) {
return String.format("%s://%s:%s%s",
request.getScheme(),
FiltersHelper.getRedirectUriServerName(request.getServerName()),
request.getServerPort(),
EngineLocalConfig.getInstance().getProperty("ENGINE_SSO_SERVICE_URI"));
}
return EngineLocalConfig.getInstance().getProperty("ENGINE_SSO_AUTH_URL");
}
public static String getRedirectUriServerName(String name) {
return InetAddressUtils.isIPv6Address(name) ? String.format("[%s]", name) : name;
}
public static Map<String, Object> getPayloadForAuthCode(
String authCode,
String scope,
String redirectUri) throws Exception {
Map<String, Object> response = SsoOAuthServiceUtils.getToken("authorization_code", authCode, scope, redirectUri);
FiltersHelper.isStatusOk(response);
return getPayloadForToken((String) response.get("access_token"));
}
public static Map<String, Object> getPayloadForToken(String token) throws Exception {
Map<String, Object> response = SsoOAuthServiceUtils.getTokenInfo(token);
FiltersHelper.isStatusOk(response);
response.put(SessionConstants.SSO_TOKEN_KEY, token);
return response;
}
public static long copy(final InputStream input, final OutputStream output) throws IOException {
final byte[] buffer = new byte[8*1024];
long count = 0;
int n;
while ((n = input.read(buffer)) != -1) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
public static int getPrefer(HttpServletRequest req) {
int ret = 0;
Enumeration<String> headerValues = req.getHeaders(Constants.HEADER_PREFER);
while (headerValues.hasMoreElements()) {
String headerValue = headerValues.nextElement();
HeaderElement[] headerElements = BasicHeaderValueParser.parseElements(headerValue, null);
if (headerElements != null) {
for (HeaderElement headerElement : headerElements) {
String elementName = headerElement.getName();
if ("new-auth".equalsIgnoreCase(elementName)) {
ret |= PREFER_NEW_AUTH;
}
if ("persistent-auth".equalsIgnoreCase(elementName)) {
ret |= PREFER_PERSISTENCE_AUTH;
}
}
}
}
return ret;
}
}