19 package com.basistech.df.cybertriage.autopsy.malwarescan;
31 import java.security.MessageDigest;
32 import java.security.NoSuchAlgorithmException;
33 import java.text.MessageFormat;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HexFormat;
38 import java.util.List;
40 import java.util.Optional;
42 import java.util.logging.Level;
43 import java.util.stream.Collectors;
44 import java.util.stream.Stream;
45 import org.apache.commons.collections4.CollectionUtils;
46 import org.apache.commons.collections4.MapUtils;
47 import org.apache.commons.lang3.StringUtils;
48 import org.apache.curator.shaded.com.google.common.collect.Lists;
49 import org.openide.util.NbBundle.Messages;
73 class MalwareScanIngestModule
implements FileIngestModule {
75 private static final SharedProcessing sharedProcessing =
new SharedProcessing();
76 private boolean uploadFiles;
77 private boolean queryFiles;
79 MalwareScanIngestModule(MalwareScanIngestSettings settings) {
80 uploadFiles = settings.shouldUploadFiles();
81 queryFiles = settings.shouldQueryFiles();
85 public void startUp(IngestJobContext context)
throws IngestModuleException {
86 sharedProcessing.startUp(context, uploadFiles);
90 public ProcessResult process(AbstractFile af) {
91 return sharedProcessing.process(af);
95 public void shutDown() {
96 sharedProcessing.shutDown();
125 "application/x-dosexec",
126 "application/vnd.microsoft.portable-executable",
127 "application/x-msdownload",
130 "application/dos-exe",
132 "application/x-winexe",
133 "application/msdos-windows",
134 "application/x-msdos-program"
135 ).collect(Collectors.toSet());
141 private final BatchProcessor<FileRecord>
batchProcessor =
new BatchProcessor<FileRecord>(
152 "MalwareScanIngestModule_malwareTypeDisplayName=Malware",
153 "MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License",
154 "MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled.",
155 "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups",
156 "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Malware scanning will be disabled.",
157 "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title=Hash Lookups Low",
158 "# {0} - remainingLookups",
159 "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc=This license only has {0} lookups remaining.",
160 "MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads",
161 "MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled.",
162 "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low",
163 "# {0} - remainingUploads",
164 "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",})
167 if (ingestJobState != null) {
173 }
catch (Exception ex) {
174 ingestJobState = IngestJobState.DISABLED;
175 throw new IngestModuleException(
"An exception occurred on MalwareScanIngestModule startup", ex);
189 Optional<LicenseInfo> licenseInfoOpt = ctSettingsPersistence.
loadLicenseInfo();
190 if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) {
192 Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(),
193 Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(),
196 return IngestJobState.DISABLED;
204 if (lookupsRemaining <= 0) {
206 Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(),
207 Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(),
210 return IngestJobState.DISABLED;
211 }
else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) {
213 Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(),
214 Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc(lookupsRemaining),
221 if (uploadsRemaining <= 0) {
223 Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title(),
224 Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc(),
227 }
else if (lookupsRemaining < LOW_UPLOADS_REMAINING) {
229 Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title(),
230 Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc(lookupsRemaining),
237 return new IngestJobState(
240 new PathNormalizer(tskCase),
242 licenseInfoOpt.get(),
243 BlackboardArtifact.Type.TSK_MALWARE,
257 limit = limit == null ? 0 : limit;
258 used = used == null ? 0 : used;
271 if (StringUtils.isNotBlank(af.getMd5Hash())) {
272 return af.getMd5Hash();
276 if (StringUtils.isNotBlank(af.getSha256Hash())) {
277 return af.getSha256Hash();
282 List<HashResult> hashResults = HashUtility.calculateHashes(af, Collections.singletonList(hashType));
283 if (CollectionUtils.isNotEmpty(hashResults)) {
284 for (HashResult hashResult : hashResults) {
285 if (hashResult.getType() == hashType) {
286 return hashResult.getValue();
290 }
catch (TskCoreException ex) {
291 logger.log(Level.WARNING,
292 MessageFormat.format(
"An error occurred while processing hash for file name: {0} and obj id: {1} and hash type {2}.",
328 private static String
getOrCalcSha1(AbstractFile af)
throws NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException {
329 if (StringUtils.isNotBlank(af.getSha1Hash())) {
330 return af.getSha1Hash();
333 MessageDigest digest = MessageDigest.getInstance(
"SHA-1");
334 ReadContentInputStream afStream =
new ReadContentInputStream(af);
336 byte[] buffer =
new byte[8192];
338 n = afStream.read(buffer);
340 digest.update(buffer, 0, n);
343 byte[] hashBytes = digest.digest();
344 String hashString = HexFormat.of().formatHex(hashBytes);
358 "MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout",
359 "MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out"
363 if (ingestJobState != null
364 && ingestJobState.isDoFileLookups()
365 && !ingestJobState.getIngestJobContext().fileIngestIsCancelled()
366 && af.getKnown() != TskData.FileKnown.KNOWN
367 && EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(ingestJobState.getFileTypeDetector().getMIMEType(af)).trim().toLowerCase())
368 && CollectionUtils.isEmpty(af.getAnalysisResults(ingestJobState.getMalwareType()))) {
371 if (StringUtils.isNotBlank(md5)) {
372 batchProcessor.add(
new FileRecord(af.getId(), md5));
375 return ProcessResult.OK;
376 }
catch (TskCoreException ex) {
378 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
379 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
381 return IngestModule.ProcessResult.ERROR;
382 }
catch (InterruptedException ex) {
384 Bundle.MalwareScanIngestModule_ShareProcessing_batchTimeout_title(),
385 Bundle.MalwareScanIngestModule_ShareProcessing_batchTimeout_desc(),
387 return IngestModule.ProcessResult.ERROR;
399 "MalwareScanIngestModule_SharedProcessing_authTokenResponseError_title=Authentication API error",
400 "# {0} - errorResponse",
401 "MalwareScanIngestModule_SharedProcessing_authTokenResponseError_desc=Received error: ''{0}'' when fetching the API authentication token for the license",
402 "MalwareScanIngestModule_SharedProcessing_repServicenResponseError_title=Lookup API error",
403 "# {0} - errorResponse",
404 "MalwareScanIngestModule_SharedProcessing_repServicenResponseError_desc=Received error: ''{0}'' when fetching hash lookup results",
405 "MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title=Hash Lookups Exhausted",
406 "MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted",
407 "MalwareScanIngestModule_SharedProcessing_generalProcessingError_title=Hash Lookup Error",
408 "MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results",})
409 private void handleBatch(IngestJobState ingestJobState, List<FileRecord> fileRecords) {
410 if (ingestJobState == null
411 || !ingestJobState.isDoFileLookups()
412 || ingestJobState.getIngestJobContext().fileIngestIsCancelled()
413 || fileRecords == null
414 || fileRecords.isEmpty()) {
419 Map<String, List<Long>> md5ToObjId =
new HashMap<>();
421 for (FileRecord fr : fileRecords) {
422 if (fr == null || StringUtils.isBlank(fr.getMd5hash()) || fr.getObjId() <= 0) {
428 .computeIfAbsent(sanitizedMd5, (k) ->
new ArrayList<>())
432 List<String> md5Hashes =
new ArrayList<>(md5ToObjId.keySet());
434 if (md5Hashes.isEmpty()) {
441 }
catch (Exception ex) {
443 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
444 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
460 "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Lookup Limits Exceeded",
461 "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Not all files were processed because hash lookup limits were exceeded. Please try again when your limits reset.",})
462 private void handleLookupResults(IngestJobState ingestJobState, Map<String, List<Long>> md5ToObjId, List<CTCloudBean> repResult)
throws Blackboard.BlackboardException, TskCoreException, TskCoreException,
CTCloudException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException {
463 if (CollectionUtils.isEmpty(repResult)) {
467 Map<Status, List<CTCloudBean>> statusGroupings = repResult.stream()
468 .filter(bean -> bean.getMalwareResult() != null)
469 .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus()));
472 List<CTCloudBean> found = statusGroupings.get(
Status.
FOUND);
482 if (CollectionUtils.isNotEmpty(statusGroupings.get(
Status.
ERROR))) {
484 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
485 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
492 Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title(),
493 Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc(),
509 private void handleNonFoundResults(IngestJobState ingestJobState, Map<String, List<Long>> md5ToObjId, List<CTCloudBean> results,
boolean performFileUpload)
throws CTCloudException, TskCoreException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException {
510 if (CollectionUtils.isNotEmpty(results)
511 && ingestJobState.isDoFileLookups()
512 && ((performFileUpload && ingestJobState.isUploadUnknownFiles()) || (!performFileUpload && ingestJobState.isQueryForMissing()))) {
514 for (
CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) {
516 String sanitizedMd5 =
normalizedMd5(beingScanned.getMd5HashValue());
517 if (StringUtils.isBlank(sanitizedMd5)) {
520 List<Long> correspondingObjIds = md5ToObjId.get(sanitizedMd5);
521 if (CollectionUtils.isEmpty(correspondingObjIds)) {
525 if (performFileUpload) {
526 uploadFile(ingestJobState, sanitizedMd5, correspondingObjIds.get(0));
529 ingestJobState.getUnidentifiedHashes().put(sanitizedMd5, correspondingObjIds);
544 private List<CTCloudBean>
getHashLookupResults(IngestJobState ingestJobState, List<String> md5Hashes)
throws CTCloudException {
545 if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
546 return Collections.emptyList();
554 if (remainingScans <= 0) {
555 ingestJobState.disableDoFileLookups();
557 Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(),
558 Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(),
560 return Collections.emptyList();
561 }
else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
562 return Collections.emptyList();
566 if (ingestJobState.isUploadUnknownFiles()) {
568 if (remainingUploads <= 0) {
569 ingestJobState.disableUploadUnknownFiles();
571 Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(),
572 Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(),
591 return StringUtils.defaultString(orig).trim().toLowerCase();
602 long size = af.getSize();
616 "MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload",
618 "MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}).",
619 "MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining File Uploads",
620 "MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc=There are no more file uploads on this license at this time. File uploads will be disabled for remaining uploads.",})
621 private boolean uploadFile(IngestJobState ingestJobState, String md5,
long objId)
throws CTCloudException, TskCoreException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException {
622 if (!ingestJobState.isUploadUnknownFiles() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
626 AbstractFile af = ingestJobState.getTskCase().getAbstractFileById(objId);
633 Bundle.MalwareScanIngestModule_uploadFile_notUploadable_title(),
634 Bundle.MalwareScanIngestModule_uploadFile_notUploadable_desc(objId),
642 throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR);
645 ingestJobState.disableUploadUnknownFiles();
647 Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(),
648 Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(),
652 }
else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
657 ReadContentInputStream fileInputStream =
new ReadContentInputStream(af);
660 .setContentLength(af.getSize())
661 .setFileInputStream(fileInputStream)
669 .setFilePath(ingestJobState.getPathNormalizer().normalizePath(af.getUniquePath()))
690 "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results",
691 "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Waiting for all uploaded files to complete scanning.",
692 "MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout",
693 "MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later.",})
694 private void longPollForNotFound(IngestJobState ingestJobState)
throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException {
695 if (!ingestJobState.isDoFileLookups()
696 || !ingestJobState.isQueryForMissing()
697 || MapUtils.isEmpty(ingestJobState.getUnidentifiedHashes())
698 || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
703 Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title(),
704 Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc()
706 logger.log(Level.INFO,
"Begin polling for malware status of file uploads.");
708 Map<String, List<Long>>
remaining =
new HashMap<>(ingestJobState.getUnidentifiedHashes());
711 List<List<String>> md5Batches = Lists.partition(
new ArrayList<>(remaining.keySet()), BATCH_SIZE);
712 for (List<String> batch : md5Batches) {
714 if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
720 Map<Status, List<CTCloudBean>> statusGroupings = repResult.stream()
721 .filter(bean -> bean.getMalwareResult() != null)
722 .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus()));
725 List<CTCloudBean> found = statusGroupings.get(
Status.
FOUND);
730 for (
CTCloudBean foundItem : CollectionUtils.emptyIfNull(found)) {
732 remaining.remove(normalizedMd5);
736 if (remaining.isEmpty()) {
741 long waitMultiplier = ((long) Math.pow(2, retry));
743 logger.log(Level.INFO, MessageFormat.format(
"Waiting {0} milliseconds before polling again for malware status of file uploads.", (waitMultiplier * FILE_UPLOAD_RETRY_SLEEP_MILLIS)));
745 for (
int i = 0; i < waitMultiplier; i++) {
746 if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) {
750 Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS);
755 Bundle.MalwareScanIngestModule_longPollForNotFound_timeout_title(),
756 Bundle.MalwareScanIngestModule_longPollForNotFound_timeout_desc(),
772 private void createAnalysisResults(IngestJobState ingestJobState, List<CTCloudBean> repResult, Map<String, List<Long>> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException {
773 if (CollectionUtils.isEmpty(repResult)) {
777 List<BlackboardArtifact> createdArtifacts =
new ArrayList<>();
778 SleuthkitCase.CaseDbTransaction trans = null;
780 trans = ingestJobState.getTskCase().beginTransaction();
782 String sanitizedMd5 =
normalizedMd5(result.getMd5HashValue());
783 List<Long> objIds = md5ToObjId.remove(sanitizedMd5);
784 if (CollectionUtils.isEmpty(objIds)) {
788 for (Long objId : objIds) {
792 Score score = res.getScore();
793 if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) {
794 createdArtifacts.add(res);
805 createdArtifacts.clear();
810 if (!CollectionUtils.isEmpty(createdArtifacts)) {
811 ingestJobState.getTskCase().getBlackboard().postArtifacts(
813 Bundle.MalwareScanIngestModuleFactory_displayName(),
814 ingestJobState.getIngestJobId()
832 "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES",
833 "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO"
835 private AnalysisResult
createAnalysisResult(IngestJobState ingestJobState, SleuthkitCase.CaseDbTransaction trans,
CTCloudBean cloudBean, Long objId)
throws Blackboard.BlackboardException {
837 logger.log(Level.WARNING, MessageFormat.format(
"Attempting to create analysis result with invalid parameters [objId: {0}, cloud bean status: {1}]",
849 ? Score.SCORE_UNKNOWN
852 String conclusion = score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE
853 ? Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes()
854 : Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No();
858 return ingestJobState.getTskCase().getBlackboard().newAnalysisResult(
859 ingestJobState.getMalwareType(),
861 ingestJobState.getDsId(),
866 Collections.emptyList(),
867 trans).getAnalysisResult();
874 "MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout",
875 "MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing"
877 synchronized void shutDown() {
879 if (ingestJobState == null) {
885 batchProcessor.flushAndReset();
887 }
catch (InterruptedException ex) {
889 Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_title(),
890 Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_desc(),
892 }
catch (Exception ex) {
894 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(),
895 Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(),
899 ingestJobState = null;
911 private static void notifyWarning(String title, String message, Exception ex) {
913 logger.log(Level.WARNING, message, ex);
918 private final long objId;
919 private final String md5hash;
921 FileRecord(
long objId, String md5hash) {
923 this.md5hash = md5hash;
930 String getMd5hash() {
946 static class IngestJobState {
948 static final IngestJobState DISABLED =
new IngestJobState(
959 private final SleuthkitCase tskCase;
960 private final FileTypeDetector fileTypeDetector;
961 private final LicenseInfo licenseInfo;
962 private final BlackboardArtifact.Type malwareType;
963 private final long dsId;
964 private final long ingestJobId;
965 private final boolean queryForMissing;
966 private final Map<String, List<Long>> unidentifiedHashes =
new HashMap<>();
969 private boolean uploadUnknownFiles;
970 private boolean doFileLookups;
971 private final IngestJobContext ingestJobContext;
972 private final PathNormalizer pathNormalizer;
974 IngestJobState(IngestJobContext ingestJobContext, SleuthkitCase tskCase, PathNormalizer pathNormalizer, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType,
boolean uploadUnknownFiles,
boolean doFileLookups) {
975 this.tskCase = tskCase;
976 this.fileTypeDetector = fileTypeDetector;
977 this.pathNormalizer = pathNormalizer;
978 this.licenseInfo = licenseInfo;
979 this.malwareType = malwareType;
980 this.dsId = ingestJobContext == null ? 0L : ingestJobContext.getDataSource().getId();
981 this.ingestJobId = ingestJobContext == null ? 0L : ingestJobContext.getJobId();
982 this.ingestJobContext = ingestJobContext;
984 this.queryForMissing = uploadUnknownFiles && doFileLookups;
985 this.uploadUnknownFiles = uploadUnknownFiles;
986 this.doFileLookups = doFileLookups;
989 SleuthkitCase getTskCase() {
993 IngestJobContext getIngestJobContext() {
994 return ingestJobContext;
997 FileTypeDetector getFileTypeDetector() {
998 return fileTypeDetector;
1001 LicenseInfo getLicenseInfo() {
1005 BlackboardArtifact.Type getMalwareType() {
1013 long getIngestJobId() {
1017 Map<String, List<Long>> getUnidentifiedHashes() {
1018 return unidentifiedHashes;
1021 boolean isQueryForMissing() {
1022 return queryForMissing;
1025 boolean isUploadUnknownFiles() {
1026 return uploadUnknownFiles;
1029 void disableUploadUnknownFiles() {
1030 this.uploadUnknownFiles =
false;
1033 boolean isDoFileLookups() {
1034 return doFileLookups;
1037 void disableDoFileLookups() {
1038 this.doFileLookups =
false;
1041 public PathNormalizer getPathNormalizer() {
1042 return pathNormalizer;
static final long LOW_UPLOADS_REMAINING
Long getFileUploadLimit()
static final Set< String > EXECUTABLE_MIME_TYPES
static long remaining(Long limit, Long used)
void longPollForNotFound(IngestJobState ingestJobState)
String getFileUploadUrl()
static final int NUM_FILE_UPLOAD_RETRIES
Long getFileUploadCount()
String getStatusDescription()
static CTApiDAO getInstance()
static String getOrCalcMd5(AbstractFile af)
AnalysisResult createAnalysisResult(IngestJobState ingestJobState, SleuthkitCase.CaseDbTransaction trans, CTCloudBean cloudBean, Long objId)
final BatchProcessor< FileRecord > batchProcessor
MalwareResultBean getMalwareResult()
void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest)
void handleNonFoundResults(IngestJobState ingestJobState, Map< String, List< Long >> md5ToObjId, List< CTCloudBean > results, boolean performFileUpload)
static void notifyWarning(String title, String message, Exception ex)
synchronized Optional< LicenseInfo > loadLicenseInfo()
static void info(String title, String message)
List< CTCloudBean > getReputationResults(AuthenticatedRequestData authenticatedRequestData, List< String > md5Hashes)
boolean uploadFile(IngestJobState ingestJobState, String md5, long objId)
void createAnalysisResults(IngestJobState ingestJobState, List< CTCloudBean > repResult, Map< String, List< Long >> md5ToObjId)
void handleBatch(IngestJobState ingestJobState, List< FileRecord > fileRecords)
static CTLicensePersistence getInstance()
static boolean isUploadable(AbstractFile af)
static final Logger logger
void uploadFile(FileUploadRequest fileUploadRequest)
static final long MIN_UPLOAD_SIZE
static final long FLUSH_SECS_TIMEOUT
Long getHashLookupLimit()
static final long LOW_LOOKUPS_REMAINING
static final int BATCH_SIZE
Long getHashLookupCount()
SleuthkitCase getSleuthkitCase()
AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted)
IngestJobState ingestJobState
FileUploadRequest setFileName(String fileName)
static final long MAX_UPLOAD_SIZE
static String getOrCalcSha1(AbstractFile af)
void handleLookupResults(IngestJobState ingestJobState, Map< String, List< Long >> md5ToObjId, List< CTCloudBean > repResult)
final CTLicensePersistence ctSettingsPersistence
static String getOrCalcHash(AbstractFile af, HashType hashType)
synchronized static Logger getLogger(String name)
static final String MALWARE_CONFIG
static Case getCurrentCaseThrows()
IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles)
static String getOrCalcSha256(AbstractFile af)
static String normalizedMd5(String orig)
List< CTCloudBean > getHashLookupResults(IngestJobState ingestJobState, List< String > md5Hashes)
static void warn(String title, String message)
static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS