Sin descripción

util.py 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. # IRIS Source Code
  2. # Copyright (C) 2022 - DFIR IRIS Team
  3. # contact@dfir-iris.org
  4. # Copyright (C) 2021 - Airbus CyberSecurity (SAS)
  5. # ir@cyberactionlab.net
  6. #
  7. # This program is free software; you can redistribute it and/or
  8. # modify it under the terms of the GNU Lesser General Public
  9. # License as published by the Free Software Foundation; either
  10. # version 3 of the License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. # Lesser General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Lesser General Public License
  18. # along with this program; if not, write to the Free Software Foundation,
  19. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. # TODO should probably dispatch the methods provided in this file in the different namespaces
  21. import base64
  22. import datetime
  23. import hashlib
  24. import logging as log
  25. import marshmallow
  26. import shutil
  27. import weakref
  28. from cryptography.exceptions import InvalidSignature
  29. from cryptography.hazmat.primitives import hashes
  30. from cryptography.hazmat.primitives import hmac
  31. from flask_login import current_user
  32. from pathlib import Path
  33. from pyunpack import Archive
  34. from sqlalchemy.orm.attributes import flag_modified
  35. from app import app
  36. from app import db
  37. class FileRemover(object):
  38. def __init__(self):
  39. self.weak_references = dict() # weak_ref -> filepath to remove
  40. def cleanup_once_done(self, response_d, filepath):
  41. wr = weakref.ref(response_d, self._do_cleanup)
  42. self.weak_references[wr] = filepath
  43. def _do_cleanup(self, wr):
  44. filepath = self.weak_references[wr]
  45. shutil.rmtree(filepath, ignore_errors=True)
  46. def decompress_7z(filename: Path, output_dir):
  47. """
  48. Decompress a 7z file in specified output directory
  49. :param filename: Filename to decompress
  50. :param output_dir: Target output dir
  51. :return: True if uncompress
  52. """
  53. try:
  54. a = Archive(filename=filename)
  55. a.extractall(directory=output_dir, auto_create_dir=True)
  56. except Exception as e:
  57. log.warning(e)
  58. return False
  59. return True
  60. def add_obj_history_entry(obj, action, commit=False):
  61. if hasattr(obj, 'modification_history'):
  62. if isinstance(obj.modification_history, dict):
  63. obj.modification_history.update({
  64. datetime.datetime.now().timestamp(): {
  65. 'user': current_user.user,
  66. 'user_id': current_user.id,
  67. 'action': action
  68. }
  69. })
  70. else:
  71. obj.modification_history = {
  72. datetime.datetime.now().timestamp(): {
  73. 'user': current_user.user,
  74. 'user_id': current_user.id,
  75. 'action': action
  76. }
  77. }
  78. flag_modified(obj, "modification_history")
  79. if commit:
  80. db.session.commit()
  81. return obj
  82. def file_sha256sum(file_path):
  83. if not Path(file_path).is_file():
  84. return None
  85. sha256_hash = hashlib.sha256()
  86. with open(file_path, "rb") as f:
  87. # Read and update hash string value in blocks of 4K
  88. for byte_block in iter(lambda: f.read(4096), b""):
  89. sha256_hash.update(byte_block)
  90. return sha256_hash.hexdigest().upper()
  91. def stream_sha256sum(stream):
  92. return hashlib.sha256(stream).hexdigest().upper()
  93. @app.template_filter()
  94. def format_datetime(value, frmt):
  95. return datetime.datetime.fromtimestamp(float(value)).strftime(frmt)
  96. def hmac_sign(data):
  97. key = bytes(app.config.get("SECRET_KEY"), "utf-8")
  98. h = hmac.HMAC(key, hashes.SHA256())
  99. h.update(data)
  100. signature = base64.b64encode(h.finalize())
  101. return signature
  102. def hmac_verify(signature_enc, data):
  103. signature = base64.b64decode(signature_enc)
  104. key = bytes(app.config.get("SECRET_KEY"), "utf-8")
  105. h = hmac.HMAC(key, hashes.SHA256())
  106. h.update(data)
  107. try:
  108. h.verify(signature)
  109. return True
  110. except InvalidSignature:
  111. return False
  112. def str_to_bool(value):
  113. if value is None:
  114. return False
  115. if isinstance(value, bool):
  116. return value
  117. if isinstance(value, int):
  118. return bool(value)
  119. return value.lower() in ['true', '1', 'yes', 'y', 't']
  120. def assert_type_mml(input_var: any, field_name: str, type: type, allow_none: bool = False,
  121. max_len: int = None, max_val: int = None, min_val: int = None):
  122. if input_var is None:
  123. if allow_none is False:
  124. raise marshmallow.ValidationError("Invalid data - non null expected",
  125. field_name=field_name if field_name else "type")
  126. else:
  127. return True
  128. if isinstance(input_var, type):
  129. if max_len:
  130. if len(input_var) > max_len:
  131. raise marshmallow.ValidationError("Invalid data - max length exceeded",
  132. field_name=field_name if field_name else "type")
  133. if max_val:
  134. if input_var > max_val:
  135. raise marshmallow.ValidationError("Invalid data - max value exceeded",
  136. field_name=field_name if field_name else "type")
  137. if min_val:
  138. if input_var < min_val:
  139. raise marshmallow.ValidationError("Invalid data - min value exceeded",
  140. field_name=field_name if field_name else "type")
  141. return True
  142. try:
  143. if isinstance(type(input_var), type):
  144. return True
  145. except Exception as e:
  146. log.error(e)
  147. print(e)
  148. raise marshmallow.ValidationError("Invalid data type",
  149. field_name=field_name if field_name else "type")