public DirResult ClassifyDir(string dir) { BlockingMq Mq = BlockingMq.GetMq(); DirResult dirResult = new DirResult() { DirPath = dir, Triage = ClassifierRule.Triage, ScanDir = true, }; // check if it matches TextClassifier textClassifier = new TextClassifier(ClassifierRule); TextResult textResult = textClassifier.TextMatch(dir); if (textResult != null) { // if it does, see what we're gonna do with it switch (ClassifierRule.MatchAction) { case MatchAction.Discard: dirResult.ScanDir = false; return(dirResult); case MatchAction.Snaffle: dirResult.Triage = ClassifierRule.Triage; Mq.DirResult(dirResult); return(dirResult); default: Mq.Error("You've got a misconfigured file ClassifierRule named " + ClassifierRule.RuleName + "."); return(null); } } return(dirResult); }
public bool ClassifyShare(string share) { BlockingMq Mq = BlockingMq.GetMq(); // check if the share has a matching classifier TextClassifier textClassifier = new TextClassifier(ClassifierRule); TextResult textResult = textClassifier.TextMatch(share); if (textResult != null) { // if it does, see what we're gonna do with it switch (ClassifierRule.MatchAction) { case MatchAction.Discard: return(true); case MatchAction.Snaffle: // in this context snaffle means 'send a report up the queue, and scan the share further' if (IsShareReadable(share)) { ShareResult shareResult = new ShareResult() { Triage = ClassifierRule.Triage, Listable = true, SharePath = share }; Mq.ShareResult(shareResult); } return(false); default: Mq.Error("You've got a misconfigured share ClassifierRule named " + ClassifierRule.RuleName + "."); return(false); } } return(false); }
public bool ClassifyFile(FileInfo fileInfo) { BlockingMq Mq = BlockingMq.GetMq(); // figure out what part we gonna look at string stringToMatch = null; switch (ClassifierRule.MatchLocation) { case MatchLoc.FileExtension: stringToMatch = fileInfo.Extension; // special handling to treat files named like 'thing.kdbx.bak' if (stringToMatch == ".bak") { // strip off .bak string subName = fileInfo.Name.Replace(".bak", ""); stringToMatch = Path.GetExtension(subName); // if this results in no file extension, put it back. if (stringToMatch == "") { stringToMatch = ".bak"; } } // this is insane that i have to do this but apparently files with no extension return // this bullshit if (stringToMatch == "") { return(false); } break; case MatchLoc.FileName: stringToMatch = fileInfo.Name; break; case MatchLoc.FilePath: stringToMatch = fileInfo.FullName; break; case MatchLoc.FileLength: if (!SizeMatch(fileInfo)) { return(false); } else { break; } default: Mq.Error("You've got a misconfigured file classifier rule named " + ClassifierRule.RuleName + "."); return(false); } TextResult textResult = null; if (!String.IsNullOrEmpty(stringToMatch)) { TextClassifier textClassifier = new TextClassifier(ClassifierRule); // check if it matches textResult = textClassifier.TextMatch(stringToMatch); if (textResult == null) { // if it doesn't we just bail now. return(false); } } FileResult fileResult; // if it matches, see what we're gonna do with it switch (ClassifierRule.MatchAction) { case MatchAction.Discard: // chuck it. return(true); case MatchAction.Snaffle: // snaffle that bad boy fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule, TextResult = textResult }; // if the file was list-only, don't bother sending a result back to the user. if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return(false); } ; Mq.FileResult(fileResult); return(false); case MatchAction.CheckForKeys: // do a special x509 dance List <string> x509MatchReason = x509Match(fileInfo); if (x509MatchReason.Count >= 0) { // if there were any matchreasons, cat them together... string matchContext = String.Join(",", x509MatchReason); // and sling the results on the queue fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule, TextResult = new TextResult() { MatchContext = matchContext, MatchedStrings = new List <string>() { "" } } }; if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return(false); } ; Mq.FileResult(fileResult); } return(false); case MatchAction.Relay: // bounce it on to the next ClassifierRule try { bool fLoggedContentSizeWarning = false; foreach (string relayTarget in ClassifierRule.RelayTargets) { ClassifierRule nextRule = MyOptions.ClassifierRules.First(thing => thing.RuleName == relayTarget); if (nextRule.EnumerationScope == EnumerationScope.ContentsEnumeration) { if (fileInfo.Length > MyOptions.MaxSizeToGrep) { if (!fLoggedContentSizeWarning) { // Just log once per relay rule, no need to fill up the log with one for each relay target Mq.Trace("The following file was bigger than the MaxSizeToGrep config parameter:" + fileInfo.FullName); fLoggedContentSizeWarning = true; } continue; } ContentClassifier nextContentClassifier = new ContentClassifier(nextRule); nextContentClassifier.ClassifyContent(fileInfo); } else if (nextRule.EnumerationScope == EnumerationScope.FileEnumeration) { FileClassifier nextFileClassifier = new FileClassifier(nextRule); nextFileClassifier.ClassifyFile(fileInfo); } else { Mq.Error("You've got a misconfigured file ClassifierRule named " + ClassifierRule.RuleName + "."); } } return(false); } catch (IOException e) { Mq.Trace(e.ToString()); } catch (Exception e) { Mq.Error("You've got a misconfigured file ClassifierRule named " + ClassifierRule.RuleName + "."); Mq.Trace(e.ToString()); } return(false); case MatchAction.EnterArchive: // do a special looking inside archive files dance using // https://github.com/adamhathcock/sharpcompress // TODO FUUUUUCK throw new NotImplementedException("Haven't implemented walking dir structures inside archives."); default: Mq.Error("You've got a misconfigured file ClassifierRule named " + ClassifierRule.RuleName + "."); return(false); } }
public void ClassifyContent(FileInfo fileInfo) { BlockingMq Mq = BlockingMq.GetMq(); FileResult fileResult; try { if (MyOptions.MaxSizeToGrep >= fileInfo.Length) { // figure out if we need to look at the content as bytes or as string. switch (ClassifierRule.MatchLocation) { case MatchLoc.FileContentAsBytes: byte[] fileBytes = File.ReadAllBytes(fileInfo.FullName); if (ByteMatch(fileBytes)) { fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule }; // if the file was list-only, don't bother sending a result back to the user. if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return; } ; Mq.FileResult(fileResult); } return; case MatchLoc.FileContentAsString: try { string fileString; #if ULTRASNAFFLER // if it's an office doc or a PDF or something, parse it to a string first i guess? List <string> parsedExtensions = new List <string>() { ".doc", ".docx", ".xls", ".xlsx", ".eml", ".msg", ".pdf", ".ppt", ".pptx", ".rtf", ".docm", ".xlsm", ".pptm", ".dot", ".dotx", ".dotm", ".xlt", ".xlsm", ".xltm" }; if (parsedExtensions.Contains(fileInfo.Extension)) { fileString = ParseFileToString(fileInfo); } else { fileString = File.ReadAllText(fileInfo.FullName); } #else fileString = File.ReadAllText(fileInfo.FullName); #endif TextClassifier textClassifier = new TextClassifier(ClassifierRule); TextResult textResult = textClassifier.TextMatch(fileString); if (textResult != null) { fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule, TextResult = textResult }; // if the file was list-only, don't bother sending a result back to the user. if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return; } ; Mq.FileResult(fileResult); } } catch (UnauthorizedAccessException) { return; } catch (IOException) { return; } return; case MatchLoc.FileLength: bool lengthResult = SizeMatch(fileInfo); if (lengthResult) { fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule }; // if the file was list-only, don't bother sending a result back to the user. if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return; } ; Mq.FileResult(fileResult); } return; case MatchLoc.FileMD5: bool Md5Result = MD5Match(fileInfo); if (Md5Result) { fileResult = new FileResult(fileInfo) { MatchedRule = ClassifierRule }; // if the file was list-only, don't bother sending a result back to the user. if (!fileResult.RwStatus.CanRead && !fileResult.RwStatus.CanModify && !fileResult.RwStatus.CanWrite) { return; } ; Mq.FileResult(fileResult); } return; default: Mq.Error("You've got a misconfigured file ClassifierRule named " + ClassifierRule.RuleName + "."); return; } } else { Mq.Trace("The following file was bigger than the MaxSizeToGrep config parameter:" + fileInfo.FullName); } } catch (UnauthorizedAccessException) { Mq.Error($"Not authorized to access file: {fileInfo.FullName}"); return; } catch (IOException e) { Mq.Error($"IO Exception on file: {fileInfo.FullName}. {e.Message}"); return; } catch (Exception e) { Mq.Error(e.ToString()); return; } }