/* * Copyright (C) 2015 The Pennsylvania State University and the University of Wisconsin * Systems and Internet Infrastructure Security Laboratory * * Author: Damien Octeau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package edu.psu.cse.siis.ic3.db; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import edu.psu.cse.siis.ic3.manifest.ManifestComponent; import edu.psu.cse.siis.ic3.manifest.ManifestData; import edu.psu.cse.siis.ic3.manifest.ManifestIntentFilter; import edu.psu.cse.siis.ic3.manifest.ManifestProviderComponent; public class SQLConnection { protected static ApplicationTable applicationTable = new ApplicationTable(); protected static IntentTable intentTable = new IntentTable(); protected static IntentFilterTable intentFilterTable = new IntentFilterTable(); protected static IntentMimeTypeTable intentMimeTypeTable = new IntentMimeTypeTable(); protected static IntentActionTable intentActionTable = new IntentActionTable(); protected static FilterActionTable filterActionTable = new FilterActionTable(); protected static IntentCategoryTable intentCategoryTable = new IntentCategoryTable(); protected static FilterCategoryTable filterCategoryTable = new FilterCategoryTable(); protected static IntentDataTable intentDataTable = new IntentDataTable(); protected static FilterDataTable filterDataTable = new FilterDataTable(); protected static IntentClassTable intentClassTable = new IntentClassTable(); protected static IntentPackageTable intentPackageTable = new IntentPackageTable(); protected static StringTable actionStringTable = new StringTable("ActionStrings"); protected static StringTable categoryStringTable = new StringTable("CategoryStrings"); protected static StringTable permissionStringTable = new StringTable("PermissionStrings"); protected static UsesPermissionTable usesPermissionTable = new UsesPermissionTable(); protected static IntentPermissionTable intentPermissionTable = new IntentPermissionTable(); protected static ClassTable classTable = new ClassTable(); protected static IntentExtraTable intentExtraTable = new IntentExtraTable(); protected static ComponentTable componentTable = new ComponentTable(); protected static ComponentExtraTable componentExtraTable = new ComponentExtraTable(); protected static ExitPointTable exitPointTable = new ExitPointTable(); protected static ExitPointComponentTable exitPointComponentTable = new ExitPointComponentTable(); protected static PermissionTable permissionTable = new PermissionTable(); protected static UriDataTable uriDataTable = new UriDataTable(); protected static UriTable uriTable = new UriTable(); protected static ProviderTable providerTable = new ProviderTable(); protected static ProviderAuthorityTable providerAuthorityTable = new ProviderAuthorityTable(); protected static int appId = Constants.NOT_FOUND; public static void init(String dbName, String dbPropertiesPath, String sshPropertiesPath, int localDbPort) { Table.init(dbName, dbPropertiesPath, sshPropertiesPath, localDbPort); } public static void closeConnection() { Table.closeConnection(); } public static Map<String, Integer> insert(String app, int version, List<ManifestComponent> intentFilters, Set<String> usesPermissions, Map<String, String> permissions, boolean skipEntryPoints) { try { if (appId == Constants.NOT_FOUND) { appId = applicationTable.insert(app, version); } if (usesPermissions != null && !insertUsesPermissions(usesPermissions)) { return null; } if (permissions != null && !insertPermissions(permissions)) { return null; } if (skipEntryPoints) { return Collections.emptyMap(); } else { return insertIntentFilters(intentFilters); } } catch (SQLException e) { e.printStackTrace(); return null; } } protected static boolean insertUsesPermissions(Set<String> usesPermissions) throws SQLException { if (usesPermissions == null) { return true; } Set<Integer> permissionIds = permissionStringTable.batchInsert(usesPermissions, null); for (int permissionId : permissionIds) { usesPermissionTable.insert(appId, permissionId); } return true; } protected static boolean insertPermissions(Map<String, String> permissions) throws SQLException { for (Map.Entry<String, String> entry : permissions.entrySet()) { int permissionId = permissionStringTable.insert(entry.getKey()); permissionTable.insert(permissionId, entry.getValue()); } return true; } /** * Figure out if a permission is a signature or signatureOrSystem one. * * @param permission The permission to look for. * @return True if the permission is found and it is has a signature or signatureOrSystem * protection level. Note that this returns false if the permission is not found, even if * it is in fact a signature or signatureOrSystem permission. * @throws SQLException */ public static boolean isSignatureOrSystem(String permission) throws SQLException { return permissionTable.isSignatureOrSystem(permission); } public static Map<String, Integer> insertIntentFilters(List<ManifestComponent> components) throws SQLException { if (appId == Constants.NOT_FOUND) { throw new RuntimeException("appId has not been set"); } Map<String, Integer> componentIds = new HashMap<String, Integer>(); for (ManifestComponent component : components) { int componentId; if (component instanceof ManifestProviderComponent) { componentId = insertProvider((ManifestProviderComponent) component); componentIds.put(component.getName(), componentId); continue; } componentId = insertComponent(component.getName(), component.getType(), component.isExported(), component.getPermission(), component.missingIntentFilters()); componentIds.put(component.getName(), componentId); Set<ManifestIntentFilter> intentFilters = component.getIntentFilters(); // System.out.println("Inserting " + intentFilters); if (intentFilters != null) { for (ManifestIntentFilter intentFilter : component.getIntentFilters()) { List<Integer> actionIds = new ArrayList<Integer>(); List<Integer> categoryIds = new ArrayList<Integer>(); // System.out.println(intentFilter.getActions()); insertStrings(actionStringTable, intentFilter.getActions(), actionIds); insertStrings(categoryStringTable, intentFilter.getCategories(), categoryIds); // if (find) { // find = // (intentFilterTable.find(componentId, actionIds, categoryIds, // intentFilter.getMimeTypes(), intentFilter.isAlias()) != Constants.NOT_FOUND); // } // if (find) { // // System.out.println("Found"); // continue; // } int filterId = intentFilterTable.forceInsert(componentId, intentFilter.isAlias()); // System.out.println("Inserting actions " + actionIds); filterActionTable.batchForceInsert(filterId, actionIds); // for (int actionId : actionIds) { // filterActionTable.forceInsert(filterId, actionId); // } filterCategoryTable.batchForceInsert(filterId, categoryIds); // for (int categoryId : categoryIds) { // filterCategoryTable.forceInsert(filterId, categoryId); // } insertFilterData(filterId, intentFilter); } } } return componentIds; } protected static int insertProvider(ManifestProviderComponent component) throws SQLException { int componentId = insertComponent(component.getName(), component.getType(), component.isExported(), null, null); int providerId = providerTable.insert(componentId, component.getGrantUriPermissions(), component.getReadPermission(), component.getWritePermission()); Set<String> authorities = component.getAuthorities(); if (authorities != null) { for (String authority : authorities) { providerAuthorityTable.insert(providerId, authority); } } return componentId; } protected static void insertFilterData(Integer filterId, ManifestIntentFilter intentFilter) throws SQLException { List<ManifestData> data = intentFilter.getData(); if (data != null) { for (ManifestData manifestData : data) { String type = null; String subtype = null; String mimeType = manifestData.getMimeType(); if (mimeType != null) { String[] typeParts = null; if (mimeType.equals(Constants.ANY_STRING)) { type = "*"; subtype = "*"; } else { typeParts = mimeType.split("/"); if (typeParts.length != 2) { type = null; subtype = null; } else { type = typeParts[0]; subtype = typeParts[1]; } } } filterDataTable.insert(filterId, manifestData.getScheme(), manifestData.getHost(), manifestData.getPort(), manifestData.getPath(), type, subtype); } } } protected static boolean insertStrings(StringTable table, Set<String> strings, List<Integer> output) throws SQLException { boolean[] allThere = new boolean[] { false }; output.addAll(table.batchInsert(strings, allThere)); if (strings != null) { for (String string : strings) { if (string != null) { int stringId = table.find(string); if (stringId == Constants.NOT_FOUND) { throw new RuntimeException("error: string '" + string + "' not found in table."); } else { output.add(stringId); } } } } return allThere[0]; } protected static boolean findStrings(StringTable table, Set<String> strings, List<Integer> output) throws SQLException { if (strings == null) { return true; } // if (strings.contains(ConnectedComponents.ANY_STRING) // || strings.contains(ConnectedComponents.ANY_CLASS)) { // output.add(Constants.NOT_FOUND); // return true; // } for (String string : strings) { if (string != null) { if (string.equals(Constants.ANY_STRING) || string.equals(Constants.ANY_CLASS)) { output.add(Constants.NOT_FOUND); } int stringId = table.find(string); if (stringId == Constants.NOT_FOUND) { return false; } else { output.add(stringId); } } } return true; } // protected static boolean insertAndSplitStrings(StringTable table, Set<String> strings, // List<Integer[]> output) throws SQLException { // if (strings == null) { // return true; // } // boolean allThere = true; // for (String string : strings) { // if (string != null) { // String[] typeParts; // if (string.equals(Constants.ANY_STRING)) { // typeParts = new String[] {"*", "*"}; // } else { // typeParts = string.split("/"); // if (typeParts.length != 2) { // System.err.println("Wrong MIME type format: " + string); // } // } // int part1 = table.find(typeParts[0]); // if (part1 == Constants.NOT_FOUND) { // allThere = false; // part1 = table.forceInsert(typeParts[0]); // } // int part2 = table.find(typeParts[1]); // if (part2 == Constants.NOT_FOUND) { // allThere = false; // part2 = table.forceInsert(typeParts[1]); // } // output.add(new Integer[] { part1, part2 }); // } // } // return allThere; // } // // protected static boolean findAndSplitStrings(StringTable table, Set<String> strings, // List<Integer[]> output) throws SQLException { // if (strings == null) { // return true; // } // if (strings.contains(Constants.ANY_STRING)) { // output.add(null); // return true; // } // for (String string : strings) { // if (string != null) { // String[] typeParts; // if (string.equals(Constants.ANY_STRING)) { // typeParts = new String[] {"*", "*"}; // } else { // typeParts = string.split("/"); // if (typeParts.length != 2) { // System.err.println("Wrong MIME type format: " + string); // } // } // int part1 = table.find(typeParts[0]); // if (part1 == Constants.NOT_FOUND) { // return false; // } // int part2 = table.find(typeParts[1]); // if (part2 == Constants.NOT_FOUND) { // return false; // } // output.add(new Integer[] { part1, part2 }); // } // } // return true; // } public static int insertComponent(String name, String type, boolean exported, String permission, Integer missingIntentFilters) throws SQLException { int classId = insertClass(name); int permissionId = (permission == null) ? Constants.NOT_FOUND : permissionStringTable.insert(permission); return componentTable.insert(classId, type, exported, permissionId, missingIntentFilters); } protected static int insertClass(String clazz) throws SQLException { return classTable.insert(appId, clazz); } protected static boolean insertIntentPermission(int exitPointId, String intentPermission) throws SQLException { int permissionId = permissionStringTable.insert(intentPermission); intentPermissionTable.insert(exitPointId, permissionId); return true; } protected static int insertExitPoint(String className, String method, int instruction, String exit_kind, Integer missingIntentFilters) throws SQLException { int classId = insertClass(className); return exitPointTable.insert(classId, method, instruction, exit_kind, missingIntentFilters); } }