19 package org.sleuthkit.autopsy.centralrepository.datamodel;
21 import java.sql.Connection;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26 import java.util.List;
27 import java.util.logging.Level;
60 this.sqliteCentralRepoSettings = repoSettings;
61 this.postgresCentralRepoSettings = null;
67 this.postgresCentralRepoSettings = repoSettings;
68 this.sqliteCentralRepoSettings = null;
85 String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate(selectedPlatform);
86 String createAccountInstancesTableTemplate = getCreateAccountInstancesTableTemplate(selectedPlatform);
88 String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
89 String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
90 String instancesValueIdx = getAddValueIndexTemplate();
91 String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
92 String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
99 LOGGER.log(Level.SEVERE,
"Cannot initialize CR database, don't have a valid connection.");
103 try (Statement stmt = conn.createStatement();) {
107 stmt.execute(PRAGMA_JOURNAL_WAL);
108 stmt.execute(PRAGMA_SYNC_OFF);
109 stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE);
110 stmt.execute(PRAGMA_ENCODING_UTF8);
111 stmt.execute(PRAGMA_PAGE_SIZE_4096);
112 stmt.execute(PRAGMA_FOREIGN_KEYS_ON);
123 stmt.execute(getCreateDataSourcesTableStatement(selectedPlatform));
124 stmt.execute(getAddDataSourcesNameIndexStatement());
125 stmt.execute(getAddDataSourcesObjectIdIndexStatement());
133 stmt.execute(
"INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY +
"', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() +
"')");
134 stmt.execute(
"INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY +
"', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() +
"')");
135 stmt.execute(
"INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY +
"', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() +
"')");
136 stmt.execute(
"INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY +
"', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() +
"')");
139 stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform));
140 stmt.execute(getCreateAccountsTableStatement(selectedPlatform));
145 String reference_type_dbname;
146 String instance_type_dbname;
152 String createTableTemplate = (
CentralRepoDbUtil.correlationAttribHasAnAccount(type))
153 ? createAccountInstancesTableTemplate
154 : createArtifactInstancesTableTemplate;
156 stmt.execute(String.format(createTableTemplate, instance_type_dbname, instance_type_dbname));
158 stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
159 stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
160 stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
161 stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
162 stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
172 createPersonaTables(stmt, selectedPlatform);
173 }
catch (SQLException ex) {
174 LOGGER.log(Level.SEVERE,
"Error initializing db schema.", ex);
177 LOGGER.log(Level.SEVERE,
"Error getting default correlation types. Likely due to one or more Type's with an invalid db table name.");
180 }
catch (SQLException ex) {
181 LOGGER.log(Level.SEVERE,
"Error connecting to database.", ex);
204 && insertDefaultPersonaTablesContent(conn, selectedPlatform);
206 }
catch (SQLException ex) {
207 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in CR tables."), ex);
221 return "CREATE TABLE db_info (" 223 +
"name TEXT UNIQUE NOT NULL," 224 +
"value TEXT NOT NULL " 242 return "CREATE TABLE IF NOT EXISTS organizations (" 244 +
"org_name text NOT NULL," 245 +
"poc_name text NOT NULL," 246 +
"poc_email text NOT NULL," 247 +
"poc_phone text NOT NULL," 248 +
"CONSTRAINT org_name_unique UNIQUE (org_name)" 261 return (
"CREATE TABLE IF NOT EXISTS cases (")
263 +
"case_uid text NOT NULL," 265 +
"case_name text NOT NULL," 266 +
"creation_date text NOT NULL," 267 +
"case_number text," 268 +
"examiner_name text," 269 +
"examiner_email text," 270 +
"examiner_phone text," 272 +
"foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL," 278 return "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
282 return "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
287 return "CREATE TABLE IF NOT EXISTS reference_sets (" 289 +
"org_id integer NOT NULL," 290 +
"set_name text NOT NULL," 291 +
"version text NOT NULL," 292 +
"known_status integer NOT NULL," 293 +
"read_only boolean NOT NULL," 294 +
"type integer NOT NULL," 295 +
"import_date text NOT NULL," 296 +
"foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL," 297 +
"CONSTRAINT hash_set_unique UNIQUE (set_name, version)" 307 return "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
320 return "CREATE TABLE IF NOT EXISTS %s (" 322 +
"reference_set_id integer," 323 +
"value text NOT NULL," 324 +
"known_status integer NOT NULL," 327 +
"foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL" 336 return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
344 return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
356 return "CREATE TABLE IF NOT EXISTS correlation_types (" 358 +
"display_name text NOT NULL," 359 +
"db_table_name text NOT NULL," 360 +
"supported integer NOT NULL," 361 +
"enabled integer NOT NULL," 362 +
"CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)" 375 return "CREATE TABLE IF NOT EXISTS %s (" 377 +
"case_id integer NOT NULL," 378 +
"data_source_id integer NOT NULL," 379 +
"value text NOT NULL," 380 +
"file_path text NOT NULL," 381 +
"known_status integer NOT NULL," 383 +
"file_obj_id " + getBigIntType(selectedPlatform) +
" ," 384 +
"CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" +
getOnConflictIgnoreClause(selectedPlatform) +
"," 385 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL," 386 +
"foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
399 return "CREATE TABLE IF NOT EXISTS %s (" 401 +
"case_id integer NOT NULL," 402 +
"data_source_id integer NOT NULL," 403 +
"account_id " + getBigIntType(selectedPlatform) +
" DEFAULT NULL," 404 +
"value text NOT NULL," 405 +
"file_path text NOT NULL," 406 +
"known_status integer NOT NULL," 408 +
"file_obj_id " + getBigIntType(selectedPlatform) +
" ," 409 +
"CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" +
getOnConflictIgnoreClause(selectedPlatform) +
"," 410 +
"foreign key (account_id) references accounts(id)," 411 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL," 412 +
"foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
423 return "CREATE TABLE IF NOT EXISTS data_sources (" 425 +
"case_id integer NOT NULL," 426 +
"device_id text NOT NULL," 427 +
"name text NOT NULL," 428 +
"datasource_obj_id " + getBigIntType(selectedPlatform) +
" ," 429 +
"md5 text DEFAULT NULL," 430 +
"sha1 text DEFAULT NULL," 431 +
"sha256 text DEFAULT NULL," 432 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL," 433 +
"CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
444 static String getAddCaseIdIndexTemplate() {
446 return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
457 static String getAddDataSourceIdIndexTemplate() {
459 return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
470 static String getAddValueIndexTemplate() {
472 return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
483 static String getAddKnownStatusIndexTemplate() {
485 return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
496 static String getAddObjectIdIndexTemplate() {
498 return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
508 static String getAddDataSourcesNameIndexStatement() {
509 return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
519 static String getAddDataSourcesObjectIdIndexStatement() {
520 return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
533 switch (selectedPlatform) {
535 return String.format(
" %s SERIAL PRIMARY KEY, ", pkName);
537 return String.format(
" %s integer primary key autoincrement NOT NULL ,", pkName);
551 switch (selectedPlatform) {
555 return " ON CONFLICT IGNORE ";
568 switch (selectedPlatform) {
579 switch (selectedPlatform) {
581 return "ON CONFLICT DO NOTHING";
594 switch (selectedPlatform) {
596 return this.postgresCentralRepoSettings.getEphemeralConnection(
false);
598 return this.sqliteCentralRepoSettings.getEphemeralConnection();
609 static boolean createPersonaTables(Statement stmt,
CentralRepoPlatforms selectedPlatform)
throws SQLException {
611 stmt.execute(getCreateConfidenceTableStatement(selectedPlatform));
612 stmt.execute(getCreateExaminersTableStatement(selectedPlatform));
613 stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform));
615 stmt.execute(getCreatePersonasTableStatement(selectedPlatform));
616 stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform));
617 stmt.execute(getCreatePersonaMetadataTableStatement(selectedPlatform));
618 stmt.execute(getCreatePersonaAccountsTableStatement(selectedPlatform));
632 return "CREATE TABLE IF NOT EXISTS account_types (" 634 +
"type_name TEXT NOT NULL," 635 +
"display_name TEXT NOT NULL," 636 +
"correlation_type_id " + getBigIntType(selectedPlatform) +
" ," 637 +
"CONSTRAINT type_name_unique UNIQUE (type_name)," 638 +
"FOREIGN KEY (correlation_type_id) REFERENCES correlation_types(id)" 650 return "CREATE TABLE IF NOT EXISTS confidence (" 652 +
"confidence_id integer NOT NULL," 653 +
"description TEXT," 654 +
"CONSTRAINT level_unique UNIQUE (confidence_id)" 666 return "CREATE TABLE IF NOT EXISTS examiners (" 668 +
"login_name TEXT NOT NULL," 669 +
"display_name TEXT," 670 +
"CONSTRAINT login_name_unique UNIQUE(login_name)" 682 return "CREATE TABLE IF NOT EXISTS persona_status (" 684 +
"status_id integer NOT NULL," 685 +
"status TEXT NOT NULL," 686 +
"CONSTRAINT status_unique UNIQUE(status_id)" 699 return "CREATE TABLE IF NOT EXISTS accounts (" 701 +
"account_type_id integer NOT NULL," 702 +
"account_unique_identifier TEXT NOT NULL," 703 +
"CONSTRAINT account_unique UNIQUE(account_type_id, account_unique_identifier)," 704 +
"FOREIGN KEY (account_type_id) REFERENCES account_types(id)" 716 return "CREATE TABLE IF NOT EXISTS personas (" 718 +
"uuid TEXT NOT NULL," 719 +
"comment TEXT NOT NULL," 720 +
"name TEXT NOT NULL," 721 +
"created_date " + getBigIntType(selectedPlatform) +
" ," 722 +
"modified_date " + getBigIntType(selectedPlatform) +
" ," 723 +
"status_id integer NOT NULL," 724 +
"examiner_id integer NOT NULL," 725 +
"CONSTRAINT uuid_unique UNIQUE(uuid)," 726 +
"FOREIGN KEY (status_id) REFERENCES persona_status(status_id), " 727 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)" 739 return "CREATE TABLE IF NOT EXISTS persona_alias (" 741 +
"persona_id " + getBigIntType(selectedPlatform) +
" ," 742 +
"alias TEXT NOT NULL, " 743 +
"justification TEXT NOT NULL," 744 +
"confidence_id integer NOT NULL," 745 +
"date_added " + getBigIntType(selectedPlatform) +
" ," 746 +
"examiner_id integer NOT NULL," 747 +
"FOREIGN KEY (persona_id) REFERENCES personas(id)," 748 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," 749 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)" 761 return "CREATE TABLE IF NOT EXISTS persona_metadata (" 763 +
"persona_id " + getBigIntType(selectedPlatform) +
" ," 764 +
"name TEXT NOT NULL," 765 +
"value TEXT NOT NULL," 766 +
"justification TEXT NOT NULL," 767 +
"confidence_id integer NOT NULL," 768 +
"date_added " + getBigIntType(selectedPlatform) +
" ," 769 +
"examiner_id integer NOT NULL," 770 +
"CONSTRAINT unique_metadata UNIQUE(persona_id, name)," 771 +
"FOREIGN KEY (persona_id) REFERENCES personas(id)," 772 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," 773 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)" 785 return "CREATE TABLE IF NOT EXISTS persona_accounts (" 787 +
"persona_id " + getBigIntType(selectedPlatform) +
" ," 788 +
"account_id " + getBigIntType(selectedPlatform) +
" ," 789 +
"justification TEXT NOT NULL," 790 +
"confidence_id integer NOT NULL," 791 +
"date_added " + getBigIntType(selectedPlatform) +
" ," 792 +
"examiner_id integer NOT NULL," 793 +
"FOREIGN KEY (persona_id) REFERENCES personas(id)," 794 +
"FOREIGN KEY (account_id) REFERENCES accounts(id)," 795 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," 796 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)" 809 static boolean insertDefaultPersonaTablesContent(Connection conn,
CentralRepoPlatforms selectedPlatform) {
811 try (Statement stmt = conn.createStatement()) {
814 String sqlString =
"INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevelId() +
", '" + confidence.toString() +
"')" 816 stmt.execute(sqlString);
821 String sqlString =
"INSERT INTO persona_status (status_id, status) VALUES ( " + status.getStatusId() +
", '" + status.toString() +
"')" 823 stmt.execute(sqlString);
826 }
catch (SQLException ex) {
827 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in Persona tables."), ex);
841 static boolean insertDefaultAccountsTablesContent(Connection conn,
CentralRepoPlatforms selectedPlatform) {
843 try (Statement stmt = conn.createStatement();) {
846 for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) {
847 if (type != Account.Type.DEVICE) {
848 int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type);
849 if (correlationTypeId > 0) {
850 String sqlString = String.format(
"INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" +
getOnConflictDoNothingClause(selectedPlatform),
851 type.getTypeName(), type.getDisplayName(), correlationTypeId);
852 stmt.execute(sqlString);
857 }
catch (SQLException ex) {
858 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in account_types table."), ex);
874 static int getCorrelationTypeIdForAccountType(Connection conn, Account.Type accountType) {
877 if (accountType == Account.Type.EMAIL) {
879 }
else if (accountType == Account.Type.PHONE) {
882 String querySql =
"SELECT * FROM correlation_types WHERE display_name=?";
883 try ( PreparedStatement preparedStatementQuery = conn.prepareStatement(querySql)) {
884 preparedStatementQuery.setString(1, accountType.getDisplayName());
885 try (ResultSet resultSet = preparedStatementQuery.executeQuery();) {
886 if (resultSet.next()) {
887 typeId = resultSet.getInt(
"id");
890 }
catch (SQLException ex) {
891 LOGGER.log(Level.SEVERE, String.format(
"Failed to get correlation typeId for account type %s.", accountType.getTypeName()), ex);
static final int EMAIL_TYPE_ID
static String getReferenceTypeValueIndexTemplate()
boolean insertDefaultDatabaseContent()
static String correlationTypeToReferenceTableName(CorrelationAttributeInstance.Type type)
static String getCreateCasesTableStatement(CentralRepoPlatforms selectedPlatform)
static List< CorrelationAttributeInstance.Type > getDefaultCorrelationTypes()
static final String PRAGMA_ENCODING_UTF8
final CentralRepoPlatforms selectedPlatform
static String getCreateReferenceSetsTableStatement(CentralRepoPlatforms selectedPlatform)
static String getCasesCaseUidIndexStatement()
static final String PRAGMA_SYNC_OFF
Connection getEphemeralConnection()
static String getCreateCorrelationTypesTableStatement(CentralRepoPlatforms selectedPlatform)
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static String getNumericPrimaryKeyClause(String pkName, CentralRepoPlatforms selectedPlatform)
final PostgresCentralRepoSettings postgresCentralRepoSettings
RdbmsCentralRepoFactory(CentralRepoPlatforms selectedPlatform, PostgresCentralRepoSettings repoSettings)
RdbmsCentralRepoFactory(CentralRepoPlatforms selectedPlatform, SqliteCentralRepoSettings repoSettings)
static final String PRAGMA_FOREIGN_KEYS_ON
static final int PHONE_TYPE_ID
final SqliteCentralRepoSettings sqliteCentralRepoSettings
static final String PRAGMA_JOURNAL_WAL
static String getCreateDbInfoTableStatement(CentralRepoPlatforms selectedPlatform)
static String getCasesOrgIdIndexStatement()
synchronized static Logger getLogger(String name)
static boolean insertDefaultCorrelationTypes(Connection conn)
boolean initializeDatabaseSchema()
static String getReferenceSetsOrgIdIndexTemplate()
static String getOnConflictIgnoreClause(CentralRepoPlatforms selectedPlatform)
static String getReferenceTypesTableTemplate(CentralRepoPlatforms selectedPlatform)
static final String PRAGMA_READ_UNCOMMITTED_TRUE
static final Logger LOGGER
static String getReferenceTypeValueKnownstatusIndexTemplate()
static String getOnConflictDoNothingClause(CentralRepoPlatforms selectedPlatform)
static final int FILES_TYPE_ID
static final String PRAGMA_PAGE_SIZE_4096
static String getCreateOrganizationsTableStatement(CentralRepoPlatforms selectedPlatform)