19 package org.sleuthkit.datamodel;
22 import java.io.UnsupportedEncodingException;
23 import java.net.URLEncoder;
24 import java.sql.Connection;
25 import java.sql.DriverManager;
26 import java.sql.SQLException;
27 import java.sql.Statement;
28 import java.util.Properties;
29 import java.util.logging.Logger;
30 import java.util.logging.Level;
37 class CaseDatabaseFactory {
39 private static final Logger logger = Logger.getLogger(CaseDatabaseFactory.class.getName());
40 private final SQLHelper dbQueryHelper;
41 private final DbCreationHelper dbCreationHelper;
47 final static String SSL_NONVERIFY_URL =
"?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require";
52 final static String SSL_VERIFY_DEFAULT_URL =
"?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca";
70 static String getCustomPostrgesSslVerificationUrl(String customSslValidationClassName) {
71 return "?ssl=true&sslfactory=" + customSslValidationClassName +
"&sslmode=verify-ca";
79 CaseDatabaseFactory(String dbPath) {
80 this.dbQueryHelper =
new SQLiteHelper();
81 this.dbCreationHelper =
new SQLiteDbCreationHelper(dbPath);
94 CaseDatabaseFactory(String caseName, CaseDbConnectionInfo info) {
95 this.dbQueryHelper =
new PostgreSQLHelper();
96 this.dbCreationHelper =
new PostgreSQLDbCreationHelper(caseName, info);
105 void createCaseDatabase() throws TskCoreException {
115 private void createDatabase() throws TskCoreException {
116 dbCreationHelper.createDatabase();
124 private void initializeSchema() throws TskCoreException {
125 try (Connection conn = dbCreationHelper.getConnection()) {
127 dbCreationHelper.performPreInitialization(conn);
134 dbCreationHelper.performPostTableInitialization(conn);
138 }
catch (SQLException ex) {
139 throw new TskCoreException(
"Error initializing case database", ex);
150 private void addDbInfo(Connection conn)
throws TskCoreException {
151 CaseDbSchemaVersionNumber version = SleuthkitCase.CURRENT_DB_SCHEMA_VERSION;
152 long tskVersionNum = SleuthkitJNI.getSleuthkitVersion();
154 try (Statement stmt = conn.createStatement()) {
155 stmt.execute(
"CREATE TABLE tsk_db_info (schema_ver INTEGER, tsk_ver INTEGER, schema_minor_ver INTEGER)");
156 stmt.execute(
"INSERT INTO tsk_db_info (schema_ver, tsk_ver, schema_minor_ver) VALUES (" +
157 version.getMajor() +
", " + tskVersionNum +
", " + version.getMinor() +
");");
159 stmt.execute(
"CREATE TABLE tsk_db_info_extended (name TEXT PRIMARY KEY, value TEXT NOT NULL);");
160 stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('TSK_VERSION', '" + tskVersionNum +
"');");
161 stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('SCHEMA_MAJOR_VERSION', '" + version.getMajor() +
"');");
162 stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('SCHEMA_MINOR_VERSION', '" + version.getMinor() +
"');");
163 stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MAJOR_VERSION', '" + version.getMajor() +
"');");
164 stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MINOR_VERSION', '" + version.getMinor() +
"');");
165 }
catch (SQLException ex) {
166 throw new TskCoreException(
"Error initializing db_info tables", ex);
177 private void addTables(Connection conn)
throws TskCoreException {
178 try (Statement stmt = conn.createStatement()) {
179 createTskObjects(stmt);
180 createHostTables(stmt);
181 createAccountTables(stmt);
182 createFileTables(stmt);
183 createArtifactTables(stmt);
184 createAnalysisResultsTables(stmt);
185 createTagTables(stmt);
186 createIngestTables(stmt);
187 createEventTables(stmt);
188 createAttributeTables(stmt);
189 createAccountInstancesAndArtifacts(stmt);
190 }
catch (SQLException ex) {
191 throw new TskCoreException(
"Error initializing tables", ex);
196 private void createTskObjects(Statement stmt)
throws SQLException {
198 stmt.execute(
"CREATE TABLE tsk_objects (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, par_obj_id " + dbQueryHelper.getBigIntType()
199 +
", type INTEGER NOT NULL, UNIQUE (obj_id), FOREIGN KEY (par_obj_id) REFERENCES tsk_objects (obj_id) ON DELETE CASCADE)");
202 private void createFileTables(Statement stmt)
throws SQLException {
204 stmt.execute(
"CREATE TABLE tsk_image_info (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, type INTEGER, ssize INTEGER, "
205 +
"tzone TEXT, size " + dbQueryHelper.getBigIntType() +
", md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, "
206 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
208 stmt.execute(
"CREATE TABLE tsk_image_names (obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, name TEXT NOT NULL, "
209 +
"sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
211 stmt.execute(
"CREATE TABLE tsk_vs_info (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, vs_type INTEGER NOT NULL, "
212 +
"img_offset " + dbQueryHelper.getBigIntType() +
" NOT NULL, block_size " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
213 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
215 stmt.execute(
"CREATE TABLE tsk_vs_parts (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
216 +
"addr " + dbQueryHelper.getBigIntType() +
" NOT NULL, start " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
217 +
"length " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
218 + dbQueryHelper.getVSDescColName() +
" TEXT, "
219 +
"flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
221 stmt.execute(
"CREATE TABLE tsk_pool_info (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
222 +
"pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
224 stmt.execute(
"CREATE TABLE data_source_info (obj_id " + dbQueryHelper.getBigIntType() +
" PRIMARY KEY, device_id TEXT NOT NULL, "
225 +
"time_zone TEXT NOT NULL, acquisition_details TEXT, added_date_time "+ dbQueryHelper.getBigIntType() +
", "
226 +
"acquisition_tool_settings TEXT, acquisition_tool_name TEXT, acquisition_tool_version TEXT, "
227 +
"host_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
228 +
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id), "
229 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
231 stmt.execute(
"CREATE TABLE tsk_fs_info (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
232 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
233 +
"img_offset " + dbQueryHelper.getBigIntType() +
" NOT NULL, fs_type INTEGER NOT NULL, "
234 +
"block_size " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
235 +
"block_count " + dbQueryHelper.getBigIntType() +
" NOT NULL, root_inum " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
236 +
"first_inum " + dbQueryHelper.getBigIntType() +
" NOT NULL, last_inum " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
237 +
"display_name TEXT, "
238 +
"FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, "
239 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
241 stmt.execute(
"CREATE TABLE file_collection_status_types (collection_status_type INTEGER PRIMARY KEY, name TEXT NOT NULL)");
243 stmt.execute(
"CREATE TABLE tsk_files (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
244 +
"fs_obj_id " + dbQueryHelper.getBigIntType() +
", data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
245 +
"attr_type INTEGER, attr_id INTEGER, "
246 +
"name TEXT NOT NULL, meta_addr " + dbQueryHelper.getBigIntType() +
", meta_seq " + dbQueryHelper.getBigIntType() +
", "
247 +
"type INTEGER, has_layout INTEGER, has_path INTEGER, "
248 +
"dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size " + dbQueryHelper.getBigIntType() +
", "
249 +
"ctime " + dbQueryHelper.getBigIntType() +
", "
250 +
"crtime " + dbQueryHelper.getBigIntType() +
", atime " + dbQueryHelper.getBigIntType() +
", "
251 +
"mtime " + dbQueryHelper.getBigIntType() +
", mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, sha256 TEXT, sha1 TEXT,"
253 +
"parent_path TEXT, mime_type TEXT, extension TEXT, "
254 +
"owner_uid TEXT DEFAULT NULL, "
255 +
"os_account_obj_id " + dbQueryHelper.getBigIntType() +
" DEFAULT NULL, "
256 +
"collected INTEGER NOT NULL, "
257 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
258 +
"FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, "
259 +
"FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, "
260 +
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL, "
261 +
"FOREIGN KEY(collected) REFERENCES file_collection_status_types (collection_status_type))" );
263 stmt.execute(
"CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)");
265 stmt.execute(
"CREATE TABLE tsk_files_path (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, path TEXT NOT NULL, "
266 +
"encoding_type INTEGER NOT NULL, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), "
267 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
269 stmt.execute(
"CREATE TABLE tsk_files_derived (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
270 +
"derived_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, rederive TEXT, "
271 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
273 stmt.execute(
"CREATE TABLE tsk_files_derived_method (derived_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
274 +
"tool_name TEXT NOT NULL, tool_version TEXT NOT NULL, other TEXT)");
276 stmt.execute(
"CREATE TABLE tsk_file_layout (obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
277 +
"byte_start " + dbQueryHelper.getBigIntType() +
" NOT NULL, byte_len " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
278 +
"sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
280 stmt.execute(
"CREATE TABLE reports (obj_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, path TEXT NOT NULL, "
281 +
"crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, "
282 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
285 private void createArtifactTables(Statement stmt)
throws SQLException {
286 stmt.execute(
"CREATE TABLE blackboard_artifact_types (artifact_type_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
287 +
"type_name TEXT NOT NULL, display_name TEXT,"
288 +
"category_type INTEGER DEFAULT 0)");
290 stmt.execute(
"CREATE TABLE blackboard_attribute_types (attribute_type_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
291 +
"type_name TEXT NOT NULL, display_name TEXT, value_type INTEGER NOT NULL)");
293 stmt.execute(
"CREATE TABLE review_statuses (review_status_id INTEGER PRIMARY KEY, "
294 +
"review_status_name TEXT NOT NULL, "
295 +
"display_name TEXT NOT NULL)");
297 stmt.execute(
"CREATE TABLE blackboard_artifacts (artifact_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
298 +
"obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
299 +
"artifact_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
300 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
", "
301 +
"artifact_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
302 +
"review_status_id INTEGER NOT NULL, "
303 +
"UNIQUE (artifact_obj_id),"
304 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
305 +
"FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
306 +
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
307 +
"FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), "
308 +
"FOREIGN KEY(review_status_id) REFERENCES review_statuses(review_status_id))");
314 stmt.execute(
"CREATE TABLE blackboard_attributes (artifact_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
315 +
"artifact_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
316 +
"source TEXT, context TEXT, attribute_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
317 +
"value_type INTEGER NOT NULL, value_byte " + dbQueryHelper.getBlobType() +
", "
318 +
"value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() +
", value_double NUMERIC(20, 10), "
319 +
"FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, "
320 +
"FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), "
321 +
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
324 private void createAnalysisResultsTables(Statement stmt)
throws SQLException {
325 stmt.execute(
"CREATE TABLE tsk_analysis_results (artifact_obj_id " + dbQueryHelper.getBigIntType() +
" PRIMARY KEY, "
326 +
"conclusion TEXT, "
327 +
"significance INTEGER NOT NULL, "
328 +
"priority INTEGER NOT NULL, "
329 +
"configuration TEXT, justification TEXT, "
330 +
"ignore_score INTEGER DEFAULT 0, "
331 +
"FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE"
334 stmt.execute(
"CREATE TABLE tsk_aggregate_score( obj_id " + dbQueryHelper.getBigIntType() +
" PRIMARY KEY, "
335 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
", "
336 +
"significance INTEGER NOT NULL, "
337 +
"priority INTEGER NOT NULL, "
339 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
340 +
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE "
344 private void createTagTables(Statement stmt)
throws SQLException {
345 stmt.execute(
"CREATE TABLE tsk_tag_sets (tag_set_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, name TEXT UNIQUE)");
346 stmt.execute(
"CREATE TABLE tag_names (tag_name_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, display_name TEXT UNIQUE, "
347 +
"description TEXT NOT NULL, color TEXT NOT NULL, knownStatus INTEGER NOT NULL,"
348 +
" tag_set_id " + dbQueryHelper.getBigIntType() +
", rank INTEGER, FOREIGN KEY(tag_set_id) REFERENCES tsk_tag_sets(tag_set_id) ON DELETE SET NULL)");
350 stmt.execute(
"CREATE TABLE tsk_examiners (examiner_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
351 +
"login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))");
353 stmt.execute(
"CREATE TABLE content_tags (tag_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
354 +
"obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
355 +
"comment TEXT NOT NULL, begin_byte_offset " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
356 +
"end_byte_offset " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
357 +
"examiner_id " + dbQueryHelper.getBigIntType() +
", "
358 +
"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, "
359 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
360 +
"FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)");
362 stmt.execute(
"CREATE TABLE blackboard_artifact_tags (tag_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
363 +
"artifact_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
364 +
"comment TEXT NOT NULL, examiner_id " + dbQueryHelper.getBigIntType() +
", "
365 +
"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, "
366 +
"FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, "
367 +
"FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)");
376 private void addIndexes(Connection conn)
throws TskCoreException {
377 try (Statement stmt = conn.createStatement()) {
379 stmt.execute(
"CREATE INDEX parObjId ON tsk_objects(par_obj_id)");
382 stmt.execute(
"CREATE INDEX layout_objID ON tsk_file_layout(obj_id)");
385 stmt.execute(
"CREATE INDEX artifact_objID ON blackboard_artifacts(obj_id)");
386 stmt.execute(
"CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)");
387 stmt.execute(
"CREATE INDEX artifact_typeID ON blackboard_artifacts(artifact_type_id)");
388 stmt.execute(
"CREATE INDEX attrsArtifactID ON blackboard_attributes(artifact_id)");
391 stmt.execute(
"CREATE INDEX mime_type ON tsk_files(dir_type,mime_type,type)");
392 stmt.execute(
"CREATE INDEX file_extension ON tsk_files(extension)");
395 stmt.execute(
"CREATE INDEX relationships_account1 ON account_relationships(account1_id)");
396 stmt.execute(
"CREATE INDEX relationships_account2 ON account_relationships(account2_id)");
397 stmt.execute(
"CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)");
398 stmt.execute(
"CREATE INDEX relationships_date_time ON account_relationships(date_time)");
399 stmt.execute(
"CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)");
400 stmt.execute(
"CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)");
403 stmt.execute(
"CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id)");
404 stmt.execute(
"CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id)");
405 stmt.execute(
"CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id)");
406 stmt.execute(
"CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time)");
407 stmt.execute(
"CREATE INDEX events_time ON tsk_events(time)");
410 stmt.execute(
"CREATE INDEX score_significance_priority ON tsk_aggregate_score(significance, priority)");
411 stmt.execute(
"CREATE INDEX score_datasource_obj_id ON tsk_aggregate_score(data_source_obj_id)");
413 stmt.execute(
"CREATE INDEX tsk_file_attributes_obj_id ON tsk_file_attributes(obj_id)");
416 }
catch (SQLException ex) {
417 throw new TskCoreException(
"Error initializing db_info tables", ex);
421 private void createIngestTables(Statement stmt)
throws SQLException {
422 stmt.execute(
"CREATE TABLE ingest_module_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)");
424 stmt.execute(
"CREATE TABLE ingest_job_status_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)");
426 stmt.execute(
"CREATE TABLE ingest_modules (ingest_module_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
427 +
"display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, "
428 +
"version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id) ON DELETE CASCADE);");
430 stmt.execute(
"CREATE TABLE ingest_jobs (ingest_job_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
431 +
"obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, host_name TEXT NOT NULL, "
432 +
"start_date_time " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
433 +
"end_date_time " + dbQueryHelper.getBigIntType() +
" NOT NULL, status_id INTEGER NOT NULL, "
434 +
"settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
435 +
"FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id) ON DELETE CASCADE);");
437 stmt.execute(
"CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, "
438 +
"pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), "
439 +
"FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id) ON DELETE CASCADE, "
440 +
"FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id) ON DELETE CASCADE);");
443 private void createHostTables(Statement stmt)
throws SQLException {
445 stmt.execute(
"CREATE TABLE tsk_persons (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
446 +
"name TEXT NOT NULL, "
450 stmt.execute(
"CREATE TABLE tsk_hosts (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
451 +
"name TEXT NOT NULL, "
452 +
"db_status INTEGER DEFAULT 0, "
453 +
"person_id INTEGER, "
454 +
"merged_into " + dbQueryHelper.getBigIntType() +
", "
455 +
"FOREIGN KEY(person_id) REFERENCES tsk_persons(id) ON DELETE SET NULL, "
456 +
"FOREIGN KEY(merged_into) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
459 stmt.execute(
"CREATE TABLE tsk_host_addresses (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
460 +
"address_type INTEGER NOT NULL, "
461 +
"address TEXT NOT NULL, "
462 +
"UNIQUE(address_type, address)) ");
464 stmt.execute(
"CREATE TABLE tsk_host_address_map (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
465 +
"host_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
466 +
"addr_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
467 +
"source_obj_id " + dbQueryHelper.getBigIntType() +
", "
468 +
"time " + dbQueryHelper.getBigIntType() +
", "
469 +
"UNIQUE(host_id, addr_obj_id, time), "
470 +
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
471 +
"FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id), "
472 +
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
475 stmt.execute(
"CREATE TABLE tsk_host_address_dns_ip_map (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
476 +
"dns_address_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
477 +
"ip_address_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
478 +
"source_obj_id " + dbQueryHelper.getBigIntType() +
", "
479 +
"time " + dbQueryHelper.getBigIntType() +
", "
480 +
"UNIQUE(dns_address_id, ip_address_id, time), "
481 +
"FOREIGN KEY(dns_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, "
482 +
"FOREIGN KEY(ip_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE,"
483 +
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
486 stmt.execute(
"CREATE TABLE tsk_host_address_usage (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
487 +
"addr_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
488 +
"obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
489 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
490 +
"UNIQUE(addr_obj_id, obj_id), "
491 +
"FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, "
492 +
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
493 +
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE )");
497 private void createAccountTables(Statement stmt)
throws SQLException {
498 stmt.execute(
"CREATE TABLE account_types (account_type_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
499 +
"type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
502 stmt.execute(
"CREATE TABLE accounts (account_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
503 +
"account_type_id INTEGER NOT NULL, account_unique_identifier TEXT NOT NULL, "
504 +
"UNIQUE(account_type_id, account_unique_identifier), "
505 +
"FOREIGN KEY(account_type_id) REFERENCES account_types(account_type_id))");
508 stmt.execute(
"CREATE TABLE account_relationships (relationship_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
509 +
"account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, "
510 +
"relationship_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
511 +
"date_time " + dbQueryHelper.getBigIntType() +
", relationship_type INTEGER NOT NULL, "
512 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
513 +
"UNIQUE(account1_id, account2_id, relationship_source_obj_id), "
514 +
"FOREIGN KEY(account1_id) REFERENCES accounts(account_id), "
515 +
"FOREIGN KEY(account2_id) REFERENCES accounts(account_id), "
516 +
"FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
517 +
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
520 stmt.execute(
"CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
521 +
"realm_name TEXT DEFAULT NULL, "
522 +
"realm_addr TEXT DEFAULT NULL, "
523 +
"realm_signature TEXT NOT NULL, "
524 +
"scope_host_id " + dbQueryHelper.getBigIntType() +
" DEFAULT NULL, "
525 +
"scope_confidence INTEGER, "
526 +
"db_status INTEGER DEFAULT 0, "
527 +
"merged_into " + dbQueryHelper.getBigIntType() +
" DEFAULT NULL, "
528 +
"UNIQUE(realm_signature), "
529 +
"FOREIGN KEY(scope_host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE,"
530 +
"FOREIGN KEY(merged_into) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE )");
533 stmt.execute(
"CREATE TABLE tsk_os_accounts (os_account_obj_id " + dbQueryHelper.getBigIntType() +
" PRIMARY KEY, "
534 +
"login_name TEXT DEFAULT NULL, "
535 +
"full_name TEXT DEFAULT NULL, "
536 +
"realm_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
537 +
"addr TEXT DEFAULT NULL, "
538 +
"signature TEXT NOT NULL, "
541 +
"created_date " + dbQueryHelper.getBigIntType() +
" DEFAULT NULL, "
542 +
"db_status INTEGER DEFAULT 0, "
543 +
"merged_into " + dbQueryHelper.getBigIntType() +
" DEFAULT NULL, "
544 +
"UNIQUE(signature, realm_id), "
545 +
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
546 +
"FOREIGN KEY(realm_id) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE,"
547 +
"FOREIGN KEY(merged_into) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE )");
551 private void createAccountInstancesAndArtifacts(Statement stmt)
throws SQLException {
554 stmt.execute(
"CREATE TABLE tsk_os_account_attributes (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
555 +
"os_account_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
556 +
"host_id " + dbQueryHelper.getBigIntType() +
", "
557 +
"source_obj_id " + dbQueryHelper.getBigIntType() +
", "
558 +
"attribute_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
559 +
"value_type INTEGER NOT NULL, "
560 +
"value_byte " + dbQueryHelper.getBlobType() +
", "
561 +
"value_text TEXT, "
562 +
"value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() +
", "
563 +
"value_double NUMERIC(20, 10), "
564 +
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "
565 +
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
566 +
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL, "
567 +
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
570 stmt.execute(
"CREATE TABLE tsk_os_account_instances (id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
571 +
"os_account_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
572 +
"data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
573 +
"instance_type INTEGER NOT NULL, "
574 +
"UNIQUE(os_account_obj_id, data_source_obj_id, instance_type), "
575 +
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "
576 +
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE ) ");
579 stmt.execute(
"CREATE TABLE tsk_data_artifacts ( "
580 +
"artifact_obj_id " + dbQueryHelper.getBigIntType() +
" PRIMARY KEY, "
581 +
"os_account_obj_id " + dbQueryHelper.getBigIntType() +
", "
582 +
"FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, "
583 +
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL) ");
586 private void createEventTables(Statement stmt)
throws SQLException {
587 stmt.execute(
"CREATE TABLE tsk_event_types ("
588 +
" event_type_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY,"
589 +
" display_name TEXT UNIQUE NOT NULL , "
590 +
" super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
605 "CREATE TABLE tsk_event_descriptions ( "
606 +
" event_description_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
607 +
" full_description TEXT NOT NULL, "
608 +
" med_description TEXT, "
609 +
" short_description TEXT,"
610 +
" data_source_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
611 +
" content_obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
612 +
" artifact_id " + dbQueryHelper.getBigIntType() +
", "
613 +
" hash_hit INTEGER NOT NULL, "
614 +
" tagged INTEGER NOT NULL, "
615 +
" FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, "
616 +
" FOREIGN KEY(content_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
617 +
" FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE,"
618 +
" UNIQUE (full_description, content_obj_id, artifact_id))");
621 "CREATE TABLE tsk_events ("
622 +
" event_id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
623 +
" event_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
624 +
" event_description_id " + dbQueryHelper.getBigIntType() +
" NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ON DELETE CASCADE ,"
625 +
" time " + dbQueryHelper.getBigIntType() +
" NOT NULL , "
626 +
" UNIQUE (event_type_id, event_description_id, time))");
629 private void createAttributeTables(Statement stmt)
throws SQLException {
635 stmt.execute(
"CREATE TABLE tsk_file_attributes ( id " + dbQueryHelper.getPrimaryKey() +
" PRIMARY KEY, "
636 +
"obj_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
637 +
"attribute_type_id " + dbQueryHelper.getBigIntType() +
" NOT NULL, "
638 +
"value_type INTEGER NOT NULL, value_byte " + dbQueryHelper.getBlobType() +
", "
639 +
"value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() +
", value_double NUMERIC(20, 10), "
640 +
"FOREIGN KEY(obj_id) REFERENCES tsk_files(obj_id) ON DELETE CASCADE, "
641 +
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
647 private abstract class DbCreationHelper {
654 abstract void createDatabase() throws TskCoreException;
661 abstract Connection getConnection() throws TskCoreException;
671 abstract
void performPreInitialization(Connection conn) throws TskCoreException;
679 abstract
void performPostTableInitialization(Connection conn) throws TskCoreException;
685 private class PostgreSQLDbCreationHelper extends DbCreationHelper {
687 private final static String JDBC_BASE_URI =
"jdbc:postgresql://";
688 private final static String JDBC_DRIVER =
"org.postgresql.Driver";
690 final private String caseName;
691 final private CaseDbConnectionInfo info;
693 PostgreSQLDbCreationHelper(String caseName, CaseDbConnectionInfo info) {
694 this.caseName = caseName;
699 void createDatabase() throws TskCoreException{
700 try(Connection conn = getPostgresConnection();
701 Statement stmt = conn.createStatement()) {
702 stmt.execute(
"CREATE DATABASE \"" + caseName +
"\" WITH ENCODING='UTF8'");
703 }
catch (SQLException ex) {
704 throw new TskCoreException(
"Error creating PostgreSQL case " + caseName, ex);
709 Connection getConnection() throws TskCoreException {
710 return getConnection(caseName);
718 Connection getPostgresConnection() throws TskCoreException {
719 return getConnection(
"postgres");
729 Connection getConnection(String databaseName)
throws TskCoreException {
730 String encodedDbName;
732 encodedDbName = URLEncoder.encode(databaseName,
"UTF-8");
733 }
catch (UnsupportedEncodingException ex) {
735 logger.log(Level.WARNING,
"Error encoding database name " + databaseName, ex);
736 encodedDbName = databaseName;
739 StringBuilder url =
new StringBuilder();
740 url.append(JDBC_BASE_URI)
741 .append(info.getHost())
743 .append(info.getPort())
745 .append(encodedDbName);
747 if (info.isSslEnabled()) {
748 if (info.isSslVerify()) {
749 if (info.getCustomSslValidationClassName().isBlank()) {
750 url.append(SSL_VERIFY_DEFAULT_URL);
753 url.append(getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName()));
756 url.append(SSL_NONVERIFY_URL);
762 Properties props =
new Properties();
763 props.setProperty(
"user", info.getUserName());
764 props.setProperty(
"password", info.getPassword());
766 Class.forName(JDBC_DRIVER);
767 conn = DriverManager.getConnection(url.toString(), props);
768 }
catch (ClassNotFoundException | SQLException ex) {
769 throw new TskCoreException(
"Failed to acquire ephemeral connection to PostgreSQL database " + databaseName, ex);
775 void performPreInitialization(Connection conn)
throws TskCoreException {
780 void performPostTableInitialization(Connection conn)
throws TskCoreException {
781 try (Statement stmt = conn.createStatement()) {
782 stmt.execute(
"ALTER SEQUENCE blackboard_artifacts_artifact_id_seq minvalue -9223372036854775808 restart with -9223372036854775808");
783 }
catch (SQLException ex) {
784 throw new TskCoreException(
"Error altering artifact ID sequence", ex);
792 private class SQLiteDbCreationHelper
extends DbCreationHelper {
794 private final static String PRAGMA_SYNC_OFF =
"PRAGMA synchronous = OFF";
795 private final static String PRAGMA_READ_UNCOMMITTED_TRUE =
"PRAGMA read_uncommitted = True";
796 private final static String PRAGMA_ENCODING_UTF8 =
"PRAGMA encoding = 'UTF-8'";
797 private final static String PRAGMA_PAGE_SIZE_4096 =
"PRAGMA page_size = 4096";
798 private final static String PRAGMA_FOREIGN_KEYS_ON =
"PRAGMA foreign_keys = ON";
800 private final static String JDBC_DRIVER =
"org.sqlite.JDBC";
801 private final static String JDBC_BASE_URI =
"jdbc:sqlite:";
805 SQLiteDbCreationHelper(String dbPath) {
806 this.dbPath = dbPath;
810 void createDatabase() throws TskCoreException {
813 File dbFile =
new File(dbPath);
814 if (dbFile.exists()) {
815 throw new TskCoreException(
"Case database already exists : " + dbPath);
818 if (dbFile.getParentFile() != null && !dbFile.getParentFile().exists()) {
819 throw new TskCoreException(
"Case database folder does not exist : " + dbFile.getParent());
824 Connection getConnection() throws TskCoreException {
826 StringBuilder url =
new StringBuilder();
827 url.append(JDBC_BASE_URI)
832 Class.forName(JDBC_DRIVER);
833 conn = DriverManager.getConnection(url.toString());
834 }
catch (ClassNotFoundException | SQLException ex) {
835 throw new TskCoreException(
"Failed to acquire ephemeral connection SQLite database " + dbPath, ex);
841 void performPreInitialization(Connection conn)
throws TskCoreException {
842 try (Statement stmt = conn.createStatement()) {
843 stmt.execute(PRAGMA_SYNC_OFF);
844 stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE);
845 stmt.execute(PRAGMA_ENCODING_UTF8);
846 stmt.execute(PRAGMA_PAGE_SIZE_4096);
847 stmt.execute(PRAGMA_FOREIGN_KEYS_ON);
848 }
catch (SQLException ex) {
849 throw new TskCoreException(
"Error setting pragmas", ex);
854 void performPostTableInitialization(Connection conn)
throws TskCoreException {