001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.pacl.dao.jdbc;
016    
017    import com.liferay.portal.kernel.util.ProxyUtil;
018    import com.liferay.portal.security.lang.DoPrivilegedFactory;
019    import com.liferay.portal.security.pacl.PACLPolicy;
020    
021    import java.lang.reflect.InvocationHandler;
022    import java.lang.reflect.InvocationTargetException;
023    import java.lang.reflect.Method;
024    
025    import java.security.AccessController;
026    import java.security.PrivilegedAction;
027    
028    import java.sql.CallableStatement;
029    import java.sql.Connection;
030    import java.sql.PreparedStatement;
031    import java.sql.Statement;
032    
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    /**
037     * @author Brian Wing Shun Chan
038     */
039    public class PACLConnectionHandler implements InvocationHandler {
040    
041            public PACLConnectionHandler(Connection connection, PACLPolicy paclPolicy) {
042                    _connection = connection;
043                    _paclPolicy = paclPolicy;
044            }
045    
046            public Object invoke(Object proxy, Method method, Object[] arguments)
047                    throws Throwable {
048    
049                    try {
050                            String methodName = method.getName();
051    
052                            if (methodName.equals("equals")) {
053                                    if (proxy == arguments[0]) {
054                                            return true;
055                                    }
056                                    else {
057                                            return false;
058                                    }
059                            }
060                            else if (methodName.equals("hashCode")) {
061                                    return System.identityHashCode(proxy);
062                            }
063                            else if (methodName.equals("prepareCall") ||
064                                             methodName.equals("prepareStatement")) {
065    
066                                    String sql = (String)arguments[0];
067    
068                                    if (!_paclPolicy.hasSQL(sql)) {
069                                            throw new SecurityException(
070                                                    "Attempted to execute unapproved SQL " + sql);
071                                    }
072                            }
073    
074                            Object returnValue = method.invoke(_connection, arguments);
075    
076                            if (methodName.equals("createStatement") ||
077                                    methodName.equals("prepareCall") ||
078                                    methodName.equals("prepareStatement")) {
079    
080                                    Statement statement = (Statement)returnValue;
081    
082                                    statement = DoPrivilegedFactory.wrap(statement);
083    
084                                    return AccessController.doPrivileged(
085                                            new StatementPrivilegedAction(statement, returnValue));
086                            }
087    
088                            return returnValue;
089                    }
090                    catch (InvocationTargetException ite) {
091                            throw ite.getTargetException();
092                    }
093            }
094    
095            protected Class<?>[] getInterfaces(Class<?> returnType) {
096                    List<Class<?>> interfaceClasses = new ArrayList<Class<?>>();
097    
098                    interfaceClasses.add(Statement.class);
099    
100                    if (!CallableStatement.class.isAssignableFrom(returnType)) {
101                            interfaceClasses.add(CallableStatement.class);
102                    }
103                    else if (!PreparedStatement.class.isAssignableFrom(returnType)) {
104                            interfaceClasses.add(PreparedStatement.class);
105                    }
106    
107                    return interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]);
108            }
109    
110            private Connection _connection;
111            private PACLPolicy _paclPolicy;
112    
113            private class StatementPrivilegedAction
114                    implements PrivilegedAction<Statement> {
115    
116                    public StatementPrivilegedAction(
117                            Statement statement, Object returnValue) {
118    
119                            _statement = statement;
120                            _returnValue = returnValue;
121                    }
122    
123                    public Statement run() {
124                            return (Statement)ProxyUtil.newProxyInstance(
125                                    _paclPolicy.getClassLoader(),
126                                    getInterfaces(_returnValue.getClass()),
127                                    new PACLStatementHandler(_statement, _paclPolicy));
128                    }
129    
130                    private Object _returnValue;
131                    private Statement _statement;
132    
133            }
134    
135    }