package dbProcs;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Used to create database connections using the FileInputProperties.readfile method to gather
* property information Initiated by Getter.java, Setter.java
*
* This file is part of the Security Shepherd Project.
*
*
The Security Shepherd project is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
*
The Security Shepherd project is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
*
You should have received a copy of the GNU General Public License along with the Security
* Shepherd project. If not, see .
*
* @author Mark
*/
public class Database {
private static final Logger log = LogManager.getLogger(Database.class);
/**
* This method is used by the application to open an connection to the database
*
* @param conn The connection to close
* @throws SQLException
*/
public static Connection getConnection(
String driverType,
String connectionURL,
String dbOptions,
String dbUsername,
String dbPassword)
throws SQLException {
try {
Class.forName(driverType).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
if (dbOptions.length() > 0) {
connectionURL += "?" + dbOptions;
}
Connection conn = DriverManager.getConnection(connectionURL, dbUsername, dbPassword);
return conn;
}
/**
* This method is used by the application to close an open connection to a database server
*
* @param conn The connection to close
*/
public static void closeConnection(Connection conn) {
// log.debug("Closing database connection");
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* This method is used by the application to get a connection to the secure database sever based
* on the input path to a specific properties file.
*
* @param ApplicationRoot The running context of the application.
* @param path The path to the properties file to use for this connection. this is filtered for
* path traversal attacks
* @return A connection to the secure database server
* @throws IOException
* @throws FileNotFoundException
* @throws SQLException
*/
public static Connection getChallengeConnection(String ApplicationRoot, String path)
throws SQLException {
// Some over paranoid input validation never hurts.
path = path.replaceAll("\\.", "").replaceAll("/", "");
log.debug("Path = " + path);
Connection conn = null;
Properties prop = new Properties();
// Pull Driver and DB URL out of database.properties
String mysql_props = Constants.MYSQL_DB_PROP;
try (InputStream mysql_input = new FileInputStream(mysql_props)) {
prop.load(mysql_input);
} catch (IOException e) {
log.error("Could not load properties file: " + e.toString());
throw new RuntimeException(e);
}
String errorBase = "Missing property :";
String connectionURL = prop.getProperty("databaseConnectionURL");
if (connectionURL == null) {
String message = errorBase + "connectionURL";
log.fatal(message);
throw new RuntimeException(message);
}
if (connectionURL.contains("?")) {
// Check for old-style challenge properties files that put options in connection url
String message = "Connection URL cannot contain options!";
log.fatal(message);
throw new RuntimeException(message);
}
String driverType = prop.getProperty("DriverType");
if (driverType == null) {
String message = errorBase + "DriverType";
log.fatal(message);
throw new RuntimeException(message);
}
// Pull DB Schema, Schema User name and Schema Password from level specific
// properties File
String challenge_props =
new File(Database.class.getResource("/challenges/" + path + ".properties").getFile())
.getAbsolutePath();
log.debug("Level Properties File = " + path + ".properties");
try (InputStream mysql_input = new FileInputStream(challenge_props)) {
prop.load(mysql_input);
} catch (IOException e) {
log.error("Could not load properties file: " + e.toString());
throw new RuntimeException(e);
}
String challenge_connectionURL = prop.getProperty("databaseConnectionURL");
if (challenge_connectionURL == null) {
throw new RuntimeException(errorBase + "connectionURL");
}
String dbOptions = prop.getProperty("databaseOptions");
if (dbOptions == null) {
log.debug(
"Did not find database options, defaulting to"
+ " useUnicode=true&character_set_server=utf8mb4");
dbOptions = "useUnicode=true&character_set_server=utf8mb4";
}
String username = prop.getProperty("databaseUsername");
if (username == null) {
throw new RuntimeException(errorBase + "databaseUsername");
}
String password = prop.getProperty("databasePassword");
if (password == null) {
throw new RuntimeException(errorBase + "databasePassword");
}
connectionURL += challenge_connectionURL;
conn = getConnection(driverType, connectionURL, dbOptions, username, password);
return conn;
}
public static Connection getCoreConnection() throws SQLException, IOException {
Connection conn = getCoreConnection("");
return conn;
}
/**
* @param ApplicationRoot @return Connection to core schema with admin privileges @throws
* FileNotFoundException @throws SQLException @throws
* @throws IOException Returns connection to core schema in database
* @throws FileNotFoundException
* @throws SQLException
* @throws RuntimeException
*/
public static Connection getCoreConnection(String ApplicationRoot) throws SQLException {
Connection conn = null;
Properties prop = new Properties();
// Pull Driver and DB URL out of database.properties
String mysql_props = Constants.MYSQL_DB_PROP;
try (InputStream mysql_input = new FileInputStream(mysql_props)) {
prop.load(mysql_input);
} catch (IOException e) {
log.error("Could not load properties file: " + e.toString());
throw new RuntimeException(e);
}
String errorBase = "Missing property :";
String connectionURL = prop.getProperty("databaseConnectionURL");
if (connectionURL == null) {
throw new RuntimeException(errorBase + "connectionURL");
}
String databaseSchema = prop.getProperty("databaseSchema");
if (databaseSchema == null) {
throw new RuntimeException(errorBase + "databaseSchema");
}
String dbOptions = prop.getProperty("databaseOptions");
if (dbOptions == null) {
throw new RuntimeException(errorBase + "databaseOptions");
}
String driverType = prop.getProperty("DriverType");
if (driverType == null) {
throw new RuntimeException(errorBase + "DriverType");
}
String username = prop.getProperty("databaseUsername");
if (username == null) {
throw new RuntimeException(errorBase + "databaseUsername");
}
String password = prop.getProperty("databasePassword");
if (password == null) {
throw new RuntimeException(errorBase + "databasePassword");
}
connectionURL += databaseSchema;
conn = getConnection(driverType, connectionURL, dbOptions, username, password);
return conn;
}
public static Connection getDatabaseConnection(String ApplicationRoot)
throws SQLException, IOException {
return getDatabaseConnection(ApplicationRoot, false);
}
/**
* This method is used by the application to get a connection to the secure database sever
*
* @param ApplicationRoot The running context of the application.
* @return A connection to the secure database server
* @throws SQLException
* @throws IOException
* @throws RuntimeException
*/
public static Connection getDatabaseConnection(String ApplicationRoot, boolean allowMulti)
throws SQLException, IOException {
Connection conn = null;
Properties prop = new Properties();
// Pull Driver and DB URL out of database.properties
String mysql_props = Constants.MYSQL_DB_PROP;
try (InputStream mysql_input = new FileInputStream(mysql_props)) {
prop.load(mysql_input);
}
String errorBase = "Missing property :";
String connectionURL = prop.getProperty("databaseConnectionURL");
if (connectionURL == null) {
throw new RuntimeException(errorBase + "connectionURL");
}
String dbOptions = prop.getProperty("databaseOptions");
if (dbOptions == null) {
throw new RuntimeException(errorBase + "databaseOptions");
}
String driverType = prop.getProperty("DriverType");
if (driverType == null) {
throw new RuntimeException(errorBase + "DriverType");
}
String username = prop.getProperty("databaseUsername");
if (username == null) {
throw new RuntimeException(errorBase + "databaseUsername");
}
String password = prop.getProperty("databasePassword");
if (password == null) {
throw new RuntimeException(errorBase + "databasePassword");
}
if (allowMulti) {
if (dbOptions.length() > 0) {
dbOptions += "&";
}
dbOptions += "allowMultiQueries=true";
}
conn = getConnection(driverType, connectionURL, dbOptions, username, password);
return conn;
}
/**
* This method is used by the application to get a connection to the secure database sever's SQL
* injection Lesson schema
*
* @param ApplicationRoot The running context of the application.
* @return A connection to the secure database server
* @throws SQLException
* @throws IOException
*/
public static Connection getSqlInjLessonConnection(String ApplicationRoot)
throws SQLException, IOException {
Connection conn = null;
Properties prop = new Properties();
String mysql_props = Constants.MYSQL_DB_PROP;
try (InputStream mysql_input = new FileInputStream(mysql_props)) {
prop.load(mysql_input);
}
String errorBase = "Missing property :";
String connectionURL = prop.getProperty("databaseConnectionURL");
if (connectionURL == null) {
throw new RuntimeException(errorBase + "connectionURL");
}
String dbOptions = prop.getProperty("databaseOptions");
if (dbOptions == null) {
throw new RuntimeException(errorBase + "databaseOptions");
}
String driverType = prop.getProperty("DriverType");
if (driverType == null) {
throw new RuntimeException(errorBase + "DriverType");
}
// Pull Schema, User name and Password from SqlInjLesson.properties
String sql_inj_props = ApplicationRoot + "/WEB-INF/classes/lessons/SqlInjLesson.properties";
try (InputStream sql_inj_input = new FileInputStream(sql_inj_props)) {
prop.load(sql_inj_input);
}
String injection_URL = prop.getProperty("databaseConnectionURL");
if (injection_URL == null) {
throw new RuntimeException(errorBase + "SQL injection connectionURL");
}
String username = prop.getProperty("databaseUsername");
if (username == null) {
throw new RuntimeException(errorBase + "SQL injection databaseUsername");
}
String password = prop.getProperty("databasePassword");
if (password == null) {
throw new RuntimeException(errorBase + "SQL injection databasePassword");
}
conn = getConnection(driverType, connectionURL + injection_URL, dbOptions, username, password);
return conn;
}
}