public void subqueryDelete(Connection dConn, Connection gConn) { // leverage the join tables to get colocation info int[] joinTables = SQLPrms.getJoinTables(); int subquery = joinTables[rand.nextInt(joinTables.length)]; // get random table to perform dml sql.subqueryStatements.SubqueryStmtIF subqueryStmt = new ColocatedSubqueryStmtsFactory().createQueryStmt(subquery); // dmlStmt of a table // perform the opeartions subqueryStmt.subqueryDelete(dConn, gConn); }
@SuppressWarnings("unchecked") public class AuthorizationDDLStmt implements DDLStmtIF { // static int totalAccessorThreads = TestConfig.tab().intAt(SQLPrms.totalAccessorThreads); // static int totalStoreThreads = TestConfig.tab().intAt(SQLPrms.totalStoreThreads); private static String[] tableNames = SQLPrms.getTableNames(); private static HashMap<String, List<String>> tableCols = new HashMap<String, List<String>>(); protected static ArrayList<String> procedureNames = null; protected static ArrayList<String> functionNames = null; protected static boolean usePublic = TestConfig.tab().booleanAt(SQLPrms.usePublicAsGrantees, false); static { tableCols.putAll( (Map) SQLBB.getBB().getSharedMap().get("tableCols")); // need to invoke setTable first } private static String[] tablePriv = { "delete", "insert", "trigger", "References ", /*"References ", only ddl thread could create reference */ "select", "update", }; String[] action = {"grant ", "revoke "}; String withGrantOption = " WITH GRANT OPTION "; // with grant is not supported yet private static boolean hasRoutine = TestConfig.tab().booleanAt(SQLPrms.hasRoutineInSecurityTest, false); public void doDDLOp(Connection dConn, Connection gConn) { boolean success = false; int maxNumOfTries = 1; ArrayList<SQLException> exList = new ArrayList<SQLException>(); String tableName = tableNames[SQLTest.random.nextInt(tableNames.length)]; String routineName = (hasRoutine) ? getRoutineNames(dConn, gConn) : null; StringBuffer aStr = new StringBuffer(); // grant or revoke String act = action[SQLTest.random.nextInt(action.length)]; aStr.append(act); // rest of the authorization stmt if (routineName == null) aStr.append(getAuthForTables(tableName, act)); else aStr.append( SQLTest.random.nextBoolean() ? getAuthForTables(tableName, act) : getAuthForRoutines(routineName, act)); if (dConn != null) { try { success = applySecurityToDerby(dConn, aStr.toString(), exList); // insert to derby table int count = 0; while (!success) { if (count >= maxNumOfTries) { Log.getLogWriter() .info("Could not get the lock to finish grant/revoke stmt, abort this operation"); return; } exList.clear(); success = applySecurityToDerby( dConn, aStr.toString(), exList); // retry insert to derby table count++; } applySecurityToGFE(gConn, aStr.toString(), exList); // insert to gfe table SQLHelper.handleMissedSQLException(exList); gConn.commit(); dConn.commit(); } catch (SQLException se) { SQLHelper.printSQLException(se); throw new TestException("execute security statement fails " + TestHelper.getStackTrace(se)); } // for verification } else { try { applySecurityToGFE(gConn, aStr.toString()); // insert to gfe table gConn.commit(); } catch (SQLException se) { SQLHelper.printSQLException(se); throw new TestException("execute security statement fails " + TestHelper.getStackTrace(se)); } } // no verification } public void assignSelectToMe(Connection dConn, Connection gConn, int tid) { boolean success = false; int maxNumOfTries = 1; ArrayList<SQLException> exList = new ArrayList<SQLException>(); // for load test String sql = "grant select on trade.buyorders to thr_" + tid; if (dConn != null) { try { success = applySecurityToDerby(dConn, sql, exList); // insert to derby table int count = 0; while (!success) { if (count >= maxNumOfTries) { Log.getLogWriter() .info("Could not get the lock to finish grant/revoke stmt, abort this operation"); return; } exList.clear(); success = applySecurityToDerby(dConn, sql, exList); // retry insert to derby table count++; } applySecurityToGFE(gConn, sql, exList); // insert to gfe table SQLHelper.handleMissedSQLException(exList); gConn.commit(); dConn.commit(); } catch (SQLException se) { SQLHelper.printSQLException(se); throw new TestException("execute security statement fails " + TestHelper.getStackTrace(se)); } // for verification } else { try { applySecurityToGFE(gConn, sql); // insert to gfe table gConn.commit(); } catch (SQLException se) { SQLHelper.printSQLException(se); throw new TestException("execute security statement fails " + TestHelper.getStackTrace(se)); } } // no verification } public void createDDLs(Connection dConn, Connection gConn) { // TODO Auto-generated method stub } protected String getRoutineNames(Connection dConn, Connection gConn) { int n = 10; if (SQLTest.random.nextInt(n) == 0) return "function " + getFunctionName(dConn, gConn); else return "procedure " + getProcedureName(dConn, gConn); } protected synchronized String getProcedureName(Connection dConn, Connection gConn) { /// avoid #42569 ResultSet rs = null; try { rs = gConn.getMetaData().getProcedures(null, null, null); List procNames = ResultSetHelper.asList(rs, false); Log.getLogWriter().info("procedure names are " + ResultSetHelper.listToString(procNames)); rs.close(); } catch (SQLException se) { SQLHelper.handleSQLException(se); } try { rs = gConn.getMetaData().getFunctions(null, null, null); } catch (SQLException se) { SQLHelper.handleSQLException(se); } List funcNames = ResultSetHelper.asList(rs, false); Log.getLogWriter().info("function names are " + ResultSetHelper.listToString(funcNames)); if (procedureNames == null) { ArrayList<String> procs = new ArrayList<String>(); procs.addAll(ProcedureDDLStmt.modifyProcNameList); procs.addAll(ProcedureDDLStmt.nonModifyProcNameList); procedureNames = new ArrayList<String>(procs); } return procedureNames.get(SQLTest.random.nextInt(procedureNames.size())); } protected String getFunctionName(Connection dConn, Connection gConn) { if (functionNames == null) functionNames = new ArrayList<String>(FunctionDDLStmt.functionNameList); return functionNames.get(SQLTest.random.nextInt(functionNames.size())); } // All privileges or priviege list for a table private String getAuthForTables(String tableName, String act) { StringBuffer aStr = new StringBuffer(); // privilege type if (SQLTest.random.nextBoolean()) { aStr.append("ALL PRIVILEGES "); } else { String privList = getPrivilegeLists(tableName); if (privList.equals(" ")) { Log.getLogWriter().info("did not get the privilege list"); aStr.append("ALL PRIVILEGES "); } else { aStr.append(privList); } } // type // on table tablename to if (act.contains("grant ")) aStr.append(" on " + tableName + " to "); else aStr.append(" on " + tableName + " from "); // grantees int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = null; if (usePublic) { grantees = (SQLTest.random.nextInt(100) == 0) ? getGrantees(num) : " public "; } else { grantees = getGrantees(num); } aStr.append((grantees.equals(" ")) ? "thr_0" : grantees); return aStr.toString(); } // return optionally any insert, delete, trigger, select [col list], update [col list] private String getPrivilegeLists(String tableName) { StringBuffer aStr = new StringBuffer(" "); for (int i = 0; i < tablePriv.length; i++) { if (SQLTest.random.nextBoolean()) { aStr.append(tablePriv[i]); // insert delete etc if (i > 2) { aStr.append(getColumnLists(tableName)); // column list for the table } // may include column list aStr.append(", "); } } if (aStr.charAt(aStr.length() - 2) == ',') { aStr.deleteCharAt(aStr.length() - 2); } aStr.deleteCharAt(0); // delete the leading space return aStr.toString(); } // returns column list: column-id, column-id ... private String getColumnLists(String tableName) { List<String> colNames = (List<String>) tableCols.get(tableName); StringBuffer aStr = new StringBuffer(" "); for (int i = 0; i < colNames.size(); i++) { if (SQLTest.random.nextBoolean()) { aStr.append(colNames.get(i) + ", "); } } if (aStr.charAt(aStr.length() - 2) == ',') { aStr.deleteCharAt(aStr.length() - 2); } aStr.deleteCharAt(0); // delete the leading space if (aStr.length() != 1) { aStr.insert(1, '('); aStr.append(')'); } // has column return aStr.toString(); } private String getAuthForRoutines(String routineName, String act) { StringBuffer aStr = new StringBuffer(); // privilege type aStr.append("EXECUTE ON "); if (act.contains("grant ")) aStr.append(routineName + " to "); else aStr.append(routineName + " from "); // grantees int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = null; if (usePublic) { grantees = (SQLTest.random.nextInt() == 0) ? getGrantees(num) : " public "; } else { grantees = getGrantees(num); } aStr.append((grantees.equals(" ")) ? "thr_0" : grantees); if (act.contains("revoke ")) aStr.append(" restrict "); // revoke privilege for routine must have restrict keyword return aStr.toString(); } protected boolean applySecurityToDerby( Connection dConn, String sql, ArrayList<SQLException> exList) { Log.getLogWriter().info("execute authorization statement in derby"); Log.getLogWriter().info("security statement is: " + sql); try { Statement stmt = dConn.createStatement(); stmt.execute(sql); // execute authorization stmt on derby } catch (SQLException se) { if (!SQLHelper.checkDerbyException(dConn, se)) { // handles the deadlock of aborting Log.getLogWriter().info("detected the deadlock, will try it again"); return false; } else { SQLHelper.handleDerbySQLException(se, exList); } } return true; } protected void applySecurityToGFE(Connection gConn, String sql, ArrayList<SQLException> exList) { Log.getLogWriter().info("execute authorization statement in GFE"); Log.getLogWriter().info("security statement is: " + sql); try { Statement stmt = gConn.createStatement(); stmt.execute(sql); // execute authorization stmt } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exList); } } protected void applySecurityToGFE(Connection gConn, String sql) { Log.getLogWriter().info("execute authorization statement in GFE"); Log.getLogWriter().info("security statement is: " + sql); try { Statement stmt = gConn.createStatement(); stmt.execute(sql); // execute authorization } catch (SQLException se) { if (se.getSQLState().equals("42506") && SQLTest.testSecurity) Log.getLogWriter() .info("Got the expected exception for authorization," + " continuing tests"); else if (se.getSQLState().equals("42509") && SQLTest.testSecurity) Log.getLogWriter() .info( "Got the expected grant or revoke operation " + "is not allowed exception for authorization," + " continuing tests"); else if (se.getSQLState().equals("42Y03") && hasRoutine) Log.getLogWriter() .info( "Got the expected not recognized as " + "a function or procedure exception for authorization," + " continuing tests"); else SQLHelper.handleSQLException(se); } } public static void turnOnAuthorization(Connection dConn, Connection gConn) { String sql = "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( " + "'derby.database.sqlAuthorization', 'true')"; ArrayList<SQLException> exList = new ArrayList<SQLException>(); if (dConn != null) { turnOnDerbyAuthorization(dConn, sql, exList); turnOnGFEAuthorization(gConn, sql, exList); SQLHelper.handleMissedSQLException(exList); } else turnOnGFEAuthorization(gConn, sql); } public static void turnOnDerbyAuthorization( Connection conn, String sql, ArrayList<SQLException> exList) { Log.getLogWriter().info("turn on authorization statement in derby"); try { Statement stmt = conn.createStatement(); stmt.executeUpdate(sql); conn.commit(); ResultSet rs = stmt.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.sqlAuthorization')"); rs.next(); Log.getLogWriter().info("Value of sqlAuthorization is " + rs.getString(1)); rs = stmt.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.defaultConnectionMode')"); rs.next(); Log.getLogWriter().info("Value of defaultConnectionMode is " + rs.getString(1)); rs.close(); } catch (SQLException se) { SQLHelper.handleDerbySQLException(se, exList); } } public static void turnOnGFEAuthorization( Connection conn, String sql, ArrayList<SQLException> exList) { Log.getLogWriter().info("turn on authorization statement in GFE"); try { Statement stmt = conn.createStatement(); stmt.executeUpdate(sql); conn.commit(); } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exList); } } public static void turnOnGFEAuthorization(Connection conn, String sql) { Log.getLogWriter().info("turn on authorization statement in GFE"); try { Statement stmt = conn.createStatement(); stmt.executeUpdate(sql); conn.commit(); } catch (SQLException se) { SQLHelper.handleSQLException(se); } } public void provideAllPrivToAll(Connection dConn, Connection gConn) { ArrayList<SQLException> exList = new ArrayList<SQLException>(); for (int i = 0; i < tableNames.length; i++) { StringBuffer sql = new StringBuffer(); sql.append("grant all privileges on " + tableNames[i] + " to " + getAllGrantees()); Log.getLogWriter().info("security statement is " + sql.toString()); if (dConn != null) { try { Statement stmt = dConn.createStatement(); stmt.execute(sql.toString()); // execute authorization dConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleDerbySQLException(se, exList); } try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exList); } } else { try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleSQLException(se); } } } } // "with grant option" not supported in derby yet public void delegateGrantOption(Connection dConn, Connection gConn) { if (dConn != null) { for (int i = 0; i < tableNames.length; i++) { delegateGrantOption(dConn, gConn, tableNames[i]); } } else { for (int i = 0; i < tableNames.length; i++) { delegateGrantOption(gConn, tableNames[i]); } } } private void delegateGrantOption(Connection dConn, Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = getGrantees(num); ArrayList<SQLException> exceptionList = new ArrayList<SQLException>(); StringBuffer sql = new StringBuffer(); int whichPriv = SQLTest.random.nextInt(tablePriv.length); sql.append( "grant " + tablePriv[whichPriv] + " on " + tableName + " to " + grantees + withGrantOption); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = dConn.createStatement(); stmt.execute(sql.toString()); // execute authorization dConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleDerbySQLException(se, exceptionList); } try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exceptionList); } SQLHelper.handleMissedSQLException(exceptionList); } private void delegateGrantOption(Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = getGrantees(num); StringBuffer sql = new StringBuffer(); int whichPriv = SQLTest.random.nextInt(tablePriv.length); sql.append( "grant " + tablePriv[whichPriv] + " on " + tableName + " to " + grantees + withGrantOption); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { if (se.getSQLState().equals("42X01")) { Log.getLogWriter() .info( "Got expected exception as WITH GRANT OPTION " + "is not supported yet, continuing test"); } else { SQLHelper.handleSQLException(se); } } } /* currently only the object owner/or system owner has the right to grant/revoke * once With GRANT OPTION is supported, all connections with privileges could grant * or revoke the privileges */ public void useDelegatedPrivilege(Connection dConn, Connection gConn) { if (dConn != null) { for (int i = 0; i < tableNames.length; i++) { useDelegatedPrivilege(dConn, gConn, tableNames[i]); } } else { for (int i = 0; i < tableNames.length; i++) { useDelegatedPrivilege(gConn, tableNames[i]); } } } private void useDelegatedPrivilege(Connection dConn, Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = getGrantees(num); ArrayList<SQLException> exceptionList = new ArrayList<SQLException>(); StringBuffer sql = new StringBuffer(); int whichPriv = SQLTest.random.nextInt(tablePriv.length); sql.append("grant " + tablePriv[whichPriv] + " on " + tableName + " to " + grantees); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = dConn.createStatement(); stmt.execute(sql.toString()); // execute authorization dConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleDerbySQLException(se, exceptionList); } try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exceptionList); } SQLHelper.handleMissedSQLException(exceptionList); } private void useDelegatedPrivilege(Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = getGrantees(num); StringBuffer sql = new StringBuffer(); int whichPriv = SQLTest.random.nextInt(tablePriv.length); sql.append("grant " + tablePriv[whichPriv] + " on " + tableName + " to " + grantees); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleSQLException(se); } } public void revokeDelegatedPrivilege(Connection dConn, Connection gConn) { if (dConn != null) { for (int i = 0; i < tableNames.length; i++) { revokeDelegatedPrivilege(dConn, gConn, tableNames[i]); } } else { for (int i = 0; i < tableNames.length; i++) { revokeDelegatedPrivilege(gConn, tableNames[i]); } } } private void revokeDelegatedPrivilege(Connection dConn, Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; ArrayList<SQLException> exceptionList = new ArrayList<SQLException>(); String grantees = getGrantees(num); StringBuffer sql = new StringBuffer(); int whichPriv = SQLTest.random.nextInt(tablePriv.length); sql.append("revoke " + tablePriv[whichPriv] + " on " + tableName + " from " + grantees); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = dConn.createStatement(); stmt.execute(sql.toString()); // execute authorization dConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleDerbySQLException(se, exceptionList); } try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleGFGFXDException(se, exceptionList); } } private void revokeDelegatedPrivilege(Connection gConn, String tableName) { int num = SQLTest.random.nextInt(SQLTest.numOfWorkers) + 1; String grantees = getGrantees(num); int whichPriv = SQLTest.random.nextInt(tablePriv.length); StringBuffer sql = new StringBuffer(); sql.append("revoke " + tablePriv[whichPriv] + " on " + tableName + " from " + grantees); Log.getLogWriter().info("security statement is " + sql.toString()); try { Statement stmt = gConn.createStatement(); stmt.execute(sql.toString()); // execute authorization gConn.commit(); stmt.close(); } catch (SQLException se) { SQLHelper.handleSQLException(se); } } // return all grantees: thr_0, thr_1, thr_2 ..., excluding itself private static String getAllGrantees() { StringBuffer aStr = new StringBuffer(" "); Map<String, String> userPasswd = (Map<String, String>) SQLBB.getBB().getSharedMap().get(SQLSecurityTest.userPasswdMap); for (Map.Entry<String, String> e : userPasswd.entrySet()) { if (!e.getKey().equalsIgnoreCase("thr_" + RemoteTestModule.getCurrentThread().getThreadId())) aStr.append(e.getKey() + ", "); } if (aStr.charAt(aStr.length() - 2) == ',') { aStr.deleteCharAt(aStr.length() - 2); } aStr.deleteCharAt(0); // delete the leading space return aStr.toString(); } // any number of users excluding itself private static String getGrantees(int num) { StringBuffer aStr = new StringBuffer(" "); Map<String, String> userPasswd = (Map<String, String>) SQLBB.getBB().getSharedMap().get(SQLSecurityTest.userPasswdMap); userPasswd.remove("thr_" + RemoteTestModule.getCurrentThread().getThreadId()); String[] users = new String[userPasswd.size()]; userPasswd.keySet().toArray(users); int i = 0; while (i < num) { int x = SQLTest.random.nextInt(users.length); aStr.append(users[x] + ", "); i++; } if (aStr.charAt(aStr.length() - 2) == ',') { aStr.deleteCharAt(aStr.length() - 2); } aStr.deleteCharAt(0); // delete the leading space return aStr.toString(); } private static String getGrantee() { return getGrantees(1); } }