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));
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);
207 }
catch (SQLException ex) {
208 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in CR tables."), ex);
222 return "CREATE TABLE db_info ("
224 +
"name TEXT UNIQUE NOT NULL,"
225 +
"value TEXT NOT NULL "
243 return "CREATE TABLE IF NOT EXISTS organizations ("
245 +
"org_name text NOT NULL,"
246 +
"poc_name text NOT NULL,"
247 +
"poc_email text NOT NULL,"
248 +
"poc_phone text NOT NULL,"
249 +
"CONSTRAINT org_name_unique UNIQUE (org_name)"
262 return (
"CREATE TABLE IF NOT EXISTS cases (")
264 +
"case_uid text NOT NULL,"
266 +
"case_name text NOT NULL,"
267 +
"creation_date text NOT NULL,"
268 +
"case_number text,"
269 +
"examiner_name text,"
270 +
"examiner_email text,"
271 +
"examiner_phone text,"
273 +
"foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,"
279 return "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
283 return "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
288 return "CREATE TABLE IF NOT EXISTS reference_sets ("
290 +
"org_id integer NOT NULL,"
291 +
"set_name text NOT NULL,"
292 +
"version text NOT NULL,"
293 +
"known_status integer NOT NULL,"
294 +
"read_only boolean NOT NULL,"
295 +
"type integer NOT NULL,"
296 +
"import_date text NOT NULL,"
297 +
"foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,"
298 +
"CONSTRAINT hash_set_unique UNIQUE (set_name, version)"
308 return "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
321 return "CREATE TABLE IF NOT EXISTS %s ("
323 +
"reference_set_id integer,"
324 +
"value text NOT NULL,"
325 +
"known_status integer NOT NULL,"
328 +
"foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL"
337 return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
345 return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
357 return "CREATE TABLE IF NOT EXISTS correlation_types ("
359 +
"display_name text NOT NULL,"
360 +
"db_table_name text NOT NULL,"
361 +
"supported integer NOT NULL,"
362 +
"enabled integer NOT NULL,"
363 +
"CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)"
376 return "CREATE TABLE IF NOT EXISTS %s ("
378 +
"case_id integer NOT NULL,"
379 +
"data_source_id integer NOT NULL,"
380 +
"value text NOT NULL,"
381 +
"file_path text NOT NULL,"
382 +
"known_status integer NOT NULL,"
384 +
"file_obj_id " + getBigIntType(selectedPlatform) +
" ,"
385 +
"CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" +
getOnConflictIgnoreClause(selectedPlatform) +
","
386 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
387 +
"foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
397 static String getCreateAccountInstancesTableTemplate(CentralRepoPlatforms selectedPlatform) {
400 return "CREATE TABLE IF NOT EXISTS %s ("
402 +
"case_id integer NOT NULL,"
403 +
"data_source_id integer NOT NULL,"
404 +
"account_id " + getBigIntType(selectedPlatform) +
" DEFAULT NULL,"
405 +
"value text NOT NULL,"
406 +
"file_path text NOT NULL,"
407 +
"known_status integer NOT NULL,"
409 +
"file_obj_id " + getBigIntType(selectedPlatform) +
" ,"
410 +
"CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" +
getOnConflictIgnoreClause(selectedPlatform) +
","
411 +
"foreign key (account_id) references accounts(id),"
412 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
413 +
"foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
423 static String getCreateDataSourcesTableStatement(CentralRepoPlatforms selectedPlatform) {
424 return "CREATE TABLE IF NOT EXISTS data_sources ("
426 +
"case_id integer NOT NULL,"
427 +
"device_id text NOT NULL,"
428 +
"name text NOT NULL,"
429 +
"datasource_obj_id " + getBigIntType(selectedPlatform) +
" ,"
430 +
"md5 text DEFAULT NULL,"
431 +
"sha1 text DEFAULT NULL,"
432 +
"sha256 text DEFAULT NULL,"
433 +
"foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
434 +
"CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
445 static String getAddCaseIdIndexTemplate() {
447 return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
458 static String getAddDataSourceIdIndexTemplate() {
460 return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
471 static String getAddValueIndexTemplate() {
473 return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
484 static String getAddKnownStatusIndexTemplate() {
486 return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
497 static String getAddObjectIdIndexTemplate() {
499 return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
509 static String getAddDataSourcesNameIndexStatement() {
510 return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
520 static String getAddDataSourcesObjectIdIndexStatement() {
521 return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
534 switch (selectedPlatform) {
536 return String.format(
" %s SERIAL PRIMARY KEY, ", pkName);
538 return String.format(
" %s integer primary key autoincrement NOT NULL ,", pkName);
552 switch (selectedPlatform) {
556 return " ON CONFLICT IGNORE ";
569 switch (selectedPlatform) {
580 switch (selectedPlatform) {
582 return "ON CONFLICT DO NOTHING";
595 switch (selectedPlatform) {
597 return this.postgresCentralRepoSettings.getEphemeralConnection(
false);
599 return this.sqliteCentralRepoSettings.getEphemeralConnection();
612 stmt.execute(getCreateConfidenceTableStatement(selectedPlatform));
613 stmt.execute(getCreateExaminersTableStatement(selectedPlatform));
614 stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform));
616 stmt.execute(getCreatePersonasTableStatement(selectedPlatform));
617 stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform));
618 stmt.execute(getCreatePersonaMetadataTableStatement(selectedPlatform));
619 stmt.execute(getCreatePersonaAccountsTableStatement(selectedPlatform));
633 return "CREATE TABLE IF NOT EXISTS account_types ("
635 +
"type_name TEXT NOT NULL,"
636 +
"display_name TEXT NOT NULL,"
637 +
"correlation_type_id " + getBigIntType(selectedPlatform) +
" ,"
638 +
"CONSTRAINT type_name_unique UNIQUE (type_name),"
639 +
"FOREIGN KEY (correlation_type_id) REFERENCES correlation_types(id)"
649 static String getCreateConfidenceTableStatement(CentralRepoPlatforms selectedPlatform) {
651 return "CREATE TABLE IF NOT EXISTS confidence ("
653 +
"confidence_id integer NOT NULL,"
654 +
"description TEXT,"
655 +
"CONSTRAINT level_unique UNIQUE (confidence_id)"
665 static String getCreateExaminersTableStatement(CentralRepoPlatforms selectedPlatform) {
667 return "CREATE TABLE IF NOT EXISTS examiners ("
669 +
"login_name TEXT NOT NULL,"
670 +
"display_name TEXT,"
671 +
"CONSTRAINT login_name_unique UNIQUE(login_name)"
681 static String getCreatePersonaStatusTableStatement(CentralRepoPlatforms selectedPlatform) {
683 return "CREATE TABLE IF NOT EXISTS persona_status ("
685 +
"status_id integer NOT NULL,"
686 +
"status TEXT NOT NULL,"
687 +
"CONSTRAINT status_unique UNIQUE(status_id)"
698 static String getCreateAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
700 return "CREATE TABLE IF NOT EXISTS accounts ("
702 +
"account_type_id integer NOT NULL,"
703 +
"account_unique_identifier TEXT NOT NULL,"
704 +
"CONSTRAINT account_unique UNIQUE(account_type_id, account_unique_identifier),"
705 +
"FOREIGN KEY (account_type_id) REFERENCES account_types(id)"
715 static String getCreatePersonasTableStatement(CentralRepoPlatforms selectedPlatform) {
717 return "CREATE TABLE IF NOT EXISTS personas ("
719 +
"uuid TEXT NOT NULL,"
720 +
"comment TEXT NOT NULL,"
721 +
"name TEXT NOT NULL,"
722 +
"created_date " + getBigIntType(selectedPlatform) +
" ,"
723 +
"modified_date " + getBigIntType(selectedPlatform) +
" ,"
724 +
"status_id integer NOT NULL,"
725 +
"examiner_id integer NOT NULL,"
726 +
"CONSTRAINT uuid_unique UNIQUE(uuid),"
727 +
"FOREIGN KEY (status_id) REFERENCES persona_status(status_id), "
728 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
738 static String getCreatePersonaAliasTableStatement(CentralRepoPlatforms selectedPlatform) {
740 return "CREATE TABLE IF NOT EXISTS persona_alias ("
742 +
"persona_id " + getBigIntType(selectedPlatform) +
" ,"
743 +
"alias TEXT NOT NULL, "
744 +
"justification TEXT NOT NULL,"
745 +
"confidence_id integer NOT NULL,"
746 +
"date_added " + getBigIntType(selectedPlatform) +
" ,"
747 +
"examiner_id integer NOT NULL,"
748 +
"FOREIGN KEY (persona_id) REFERENCES personas(id),"
749 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
750 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
760 static String getCreatePersonaMetadataTableStatement(CentralRepoPlatforms selectedPlatform) {
762 return "CREATE TABLE IF NOT EXISTS persona_metadata ("
764 +
"persona_id " + getBigIntType(selectedPlatform) +
" ,"
765 +
"name TEXT NOT NULL,"
766 +
"value TEXT NOT NULL,"
767 +
"justification TEXT NOT NULL,"
768 +
"confidence_id integer NOT NULL,"
769 +
"date_added " + getBigIntType(selectedPlatform) +
" ,"
770 +
"examiner_id integer NOT NULL,"
771 +
"CONSTRAINT unique_metadata UNIQUE(persona_id, name),"
772 +
"FOREIGN KEY (persona_id) REFERENCES personas(id),"
773 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
774 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
784 static String getCreatePersonaAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
786 return "CREATE TABLE IF NOT EXISTS persona_accounts ("
788 +
"persona_id " + getBigIntType(selectedPlatform) +
" ,"
789 +
"account_id " + getBigIntType(selectedPlatform) +
" ,"
790 +
"justification TEXT NOT NULL,"
791 +
"confidence_id integer NOT NULL,"
792 +
"date_added " + getBigIntType(selectedPlatform) +
" ,"
793 +
"examiner_id integer NOT NULL,"
794 +
"FOREIGN KEY (persona_id) REFERENCES personas(id),"
795 +
"FOREIGN KEY (account_id) REFERENCES accounts(id),"
796 +
"FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
797 +
"FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
812 try (Statement stmt = conn.createStatement()) {
815 String sqlString =
"INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevel() +
", '" + confidence.toString() +
"')"
817 stmt.execute(sqlString);
822 String sqlString =
"INSERT INTO persona_status (status_id, status) VALUES ( " + status.getStatus() +
", '" + status.toString() +
"')"
824 stmt.execute(sqlString);
827 }
catch (SQLException ex) {
828 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in Persona tables."), ex);
842 static boolean insertDefaultAccountsTablesContent(Connection conn,
CentralRepoPlatforms selectedPlatform) {
844 try (Statement stmt = conn.createStatement();) {
847 for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) {
848 if (type != Account.Type.DEVICE) {
849 int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type);
850 if (correlationTypeId > 0) {
851 String sqlString = String.format(
"INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" +
getOnConflictDoNothingClause(selectedPlatform),
852 type.getTypeName(), type.getDisplayName(), correlationTypeId);
853 stmt.execute(sqlString);
858 }
catch (SQLException ex) {
859 LOGGER.log(Level.SEVERE, String.format(
"Failed to populate default data in account_types table."), ex);
875 static int getCorrelationTypeIdForAccountType(Connection conn, Account.Type accountType) {
878 if (accountType == Account.Type.EMAIL) {
879 typeId = CorrelationAttributeInstance.EMAIL_TYPE_ID;
880 }
else if (accountType == Account.Type.PHONE) {
881 typeId = CorrelationAttributeInstance.PHONE_TYPE_ID;
883 String querySql =
"SELECT * FROM correlation_types WHERE display_name=?";
884 try ( PreparedStatement preparedStatementQuery = conn.prepareStatement(querySql)) {
885 preparedStatementQuery.setString(1, accountType.getDisplayName());
886 try (ResultSet resultSet = preparedStatementQuery.executeQuery();) {
887 if (resultSet.next()) {
888 typeId = resultSet.getInt(
"id");
891 }
catch (SQLException ex) {
892 LOGGER.log(Level.SEVERE, String.format(
"Failed to get correlation typeId for account type %s.", accountType.getTypeName()), ex);
static String getReferenceTypeValueIndexTemplate()
boolean insertDefaultDatabaseContent()
Confidence(int level, String name)
static boolean insertDefaultPersonaTablesContent(Connection conn, CentralRepoPlatforms selectedPlatform)
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)
PersonaStatus(int status, String description)
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 createPersonaTables(Statement stmt)
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)