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)";
396 static String getCreateAccountInstancesTableTemplate(CentralRepoPlatforms selectedPlatform) {
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)";
422 static String getCreateDataSourcesTableStatement(CentralRepoPlatforms selectedPlatform) {
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));
630 static String getCreateAccountTypesTableStatement(CentralRepoPlatforms 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)"
648 static String getCreateConfidenceTableStatement(CentralRepoPlatforms selectedPlatform) {
650 return "CREATE TABLE IF NOT EXISTS confidence ("
652 +
"confidence_id integer NOT NULL,"
653 +
"description TEXT,"
654 +
"CONSTRAINT level_unique UNIQUE (confidence_id)"
664 static String getCreateExaminersTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
680 static String getCreatePersonaStatusTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
697 static String getCreateAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
714 static String getCreatePersonasTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
737 static String getCreatePersonaAliasTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
759 static String getCreatePersonaMetadataTableStatement(CentralRepoPlatforms selectedPlatform) {
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)"
783 static String getCreatePersonaAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
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()) {
813 for (Confidence confidence : Persona.Confidence.values()) {
814 String sqlString =
"INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevelId() +
", '" + confidence.toString() +
"')"
816 stmt.execute(sqlString);
820 for (PersonaStatus status : Persona.PersonaStatus.values()) {
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) {
878 typeId = CorrelationAttributeInstance.EMAIL_TYPE_ID;
879 }
else if (accountType == Account.Type.PHONE) {
880 typeId = CorrelationAttributeInstance.PHONE_TYPE_ID;
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 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
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)