dissect.target 3.14.dev28__py3-none-any.whl → 3.15__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. dissect/target/containers/ewf.py +1 -1
  2. dissect/target/containers/vhd.py +5 -2
  3. dissect/target/filesystem.py +36 -18
  4. dissect/target/filesystems/dir.py +10 -4
  5. dissect/target/filesystems/jffs.py +122 -0
  6. dissect/target/helpers/compat/path_310.py +506 -0
  7. dissect/target/helpers/compat/path_311.py +539 -0
  8. dissect/target/helpers/compat/path_312.py +443 -0
  9. dissect/target/helpers/compat/path_39.py +545 -0
  10. dissect/target/helpers/compat/path_common.py +223 -0
  11. dissect/target/helpers/cyber.py +512 -0
  12. dissect/target/helpers/fsutil.py +128 -666
  13. dissect/target/helpers/hashutil.py +17 -57
  14. dissect/target/helpers/keychain.py +9 -3
  15. dissect/target/helpers/loaderutil.py +1 -1
  16. dissect/target/helpers/mount.py +47 -4
  17. dissect/target/helpers/polypath.py +73 -0
  18. dissect/target/helpers/record_modifier.py +100 -0
  19. dissect/target/loader.py +2 -1
  20. dissect/target/loaders/asdf.py +2 -0
  21. dissect/target/loaders/cyber.py +37 -0
  22. dissect/target/loaders/log.py +14 -3
  23. dissect/target/loaders/raw.py +2 -0
  24. dissect/target/loaders/remote.py +12 -0
  25. dissect/target/loaders/tar.py +13 -0
  26. dissect/target/loaders/targetd.py +2 -0
  27. dissect/target/loaders/velociraptor.py +12 -3
  28. dissect/target/loaders/vmwarevm.py +2 -0
  29. dissect/target/plugin.py +272 -143
  30. dissect/target/plugins/apps/ssh/openssh.py +11 -54
  31. dissect/target/plugins/apps/ssh/opensshd.py +4 -3
  32. dissect/target/plugins/apps/ssh/putty.py +236 -0
  33. dissect/target/plugins/apps/ssh/ssh.py +58 -0
  34. dissect/target/plugins/apps/vpn/openvpn.py +6 -0
  35. dissect/target/plugins/apps/webserver/apache.py +309 -95
  36. dissect/target/plugins/apps/webserver/caddy.py +5 -2
  37. dissect/target/plugins/apps/webserver/citrix.py +82 -0
  38. dissect/target/plugins/apps/webserver/iis.py +9 -12
  39. dissect/target/plugins/apps/webserver/nginx.py +5 -2
  40. dissect/target/plugins/apps/webserver/webserver.py +25 -41
  41. dissect/target/plugins/child/wsl.py +1 -1
  42. dissect/target/plugins/filesystem/ntfs/mft.py +10 -0
  43. dissect/target/plugins/filesystem/ntfs/mft_timeline.py +10 -0
  44. dissect/target/plugins/filesystem/ntfs/usnjrnl.py +10 -0
  45. dissect/target/plugins/filesystem/ntfs/utils.py +28 -5
  46. dissect/target/plugins/filesystem/resolver.py +6 -4
  47. dissect/target/plugins/general/default.py +0 -2
  48. dissect/target/plugins/general/example.py +0 -1
  49. dissect/target/plugins/general/loaders.py +3 -5
  50. dissect/target/plugins/os/unix/_os.py +3 -3
  51. dissect/target/plugins/os/unix/bsd/citrix/_os.py +68 -28
  52. dissect/target/plugins/os/unix/bsd/citrix/history.py +130 -0
  53. dissect/target/plugins/os/unix/generic.py +17 -10
  54. dissect/target/plugins/os/unix/linux/fortios/__init__.py +0 -0
  55. dissect/target/plugins/os/unix/linux/fortios/_os.py +534 -0
  56. dissect/target/plugins/os/unix/linux/fortios/generic.py +30 -0
  57. dissect/target/plugins/os/unix/linux/fortios/locale.py +109 -0
  58. dissect/target/plugins/os/windows/log/evt.py +1 -1
  59. dissect/target/plugins/os/windows/log/schedlgu.py +155 -0
  60. dissect/target/plugins/os/windows/regf/firewall.py +1 -1
  61. dissect/target/plugins/os/windows/regf/shimcache.py +1 -1
  62. dissect/target/plugins/os/windows/regf/trusteddocs.py +1 -1
  63. dissect/target/plugins/os/windows/registry.py +1 -1
  64. dissect/target/plugins/os/windows/sam.py +3 -0
  65. dissect/target/plugins/os/windows/sru.py +41 -28
  66. dissect/target/plugins/os/windows/tasks.py +5 -2
  67. dissect/target/target.py +7 -3
  68. dissect/target/tools/dd.py +7 -1
  69. dissect/target/tools/fs.py +8 -1
  70. dissect/target/tools/info.py +22 -15
  71. dissect/target/tools/mount.py +28 -3
  72. dissect/target/tools/query.py +146 -117
  73. dissect/target/tools/reg.py +21 -16
  74. dissect/target/tools/shell.py +30 -6
  75. dissect/target/tools/utils.py +28 -0
  76. dissect/target/volumes/bde.py +14 -10
  77. dissect/target/volumes/luks.py +18 -10
  78. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/METADATA +4 -3
  79. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/RECORD +85 -67
  80. dissect/target/plugins/os/unix/linux/fortigate/_os.py +0 -175
  81. /dissect/target/{plugins/os/unix/linux/fortigate → helpers/compat}/__init__.py +0 -0
  82. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/COPYRIGHT +0 -0
  83. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/LICENSE +0 -0
  84. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/WHEEL +0 -0
  85. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/entry_points.txt +0 -0
  86. {dissect.target-3.14.dev28.dist-info → dissect.target-3.15.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,223 @@
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ import posixpath
5
+ import stat
6
+ from typing import IO, TYPE_CHECKING, Iterator, Literal, Optional
7
+
8
+ if TYPE_CHECKING:
9
+ from dissect.target.helpers.fsutil import TargetPath
10
+ from dissect.target.filesystem import Filesystem, FilesystemEntry
11
+
12
+ from dissect.target.exceptions import FilesystemError, SymlinkRecursionError
13
+ from dissect.target.helpers.polypath import abspath, normalize
14
+
15
+ try:
16
+ # Up until CPython 3.12, pathlib._PathParents requires subclassing to inject the filesystem and flavour
17
+ # into each parent path component. Since CPython 3.12, this is no longer necessary.
18
+ # In CPython 3.13, _PathParents was moved to a different file, so this will result in an import error.
19
+ # Since we no longer need it in CPython 3.13, we can just ignore the error.
20
+ from pathlib import _PathParents
21
+
22
+ class _DissectPathParents(_PathParents):
23
+ __slots__ = ("_fs", "_flavour")
24
+
25
+ def __init__(self, path: TargetPath):
26
+ super().__init__(path)
27
+ self._fs = path._fs
28
+ self._flavour = path._flavour
29
+
30
+ def __getitem__(self, idx: int) -> TargetPath:
31
+ result = super().__getitem__(idx)
32
+ result._fs = self._fs
33
+ result._flavour = self._flavour
34
+ return result
35
+
36
+ except ImportError:
37
+ pass
38
+
39
+
40
+ class _DissectScandirIterator:
41
+ """This class implements a ScandirIterator for dissect's scandir()
42
+
43
+ The _DissectScandirIterator provides a context manager, so scandir can be called as:
44
+
45
+ ```
46
+ with scandir(path) as it:
47
+ for entry in it
48
+ print(entry.name)
49
+ ```
50
+
51
+ similar to os.scandir() behaviour since Python 3.6.
52
+ """
53
+
54
+ def __init__(self, iterator: Iterator[FilesystemEntry]):
55
+ self._iterator = iterator
56
+
57
+ def __del__(self) -> None:
58
+ self.close()
59
+
60
+ def __enter__(self) -> Iterator[FilesystemEntry]:
61
+ return self._iterator
62
+
63
+ def __exit__(self, *args, **kwargs) -> Literal[False]:
64
+ return False
65
+
66
+ def __iter__(self) -> Iterator[FilesystemEntry]:
67
+ return self._iterator
68
+
69
+ def __next__(self, *args) -> FilesystemEntry:
70
+ return next(self._iterator, *args)
71
+
72
+ def close(self):
73
+ # close() is not defined in the various filesystem implementations. The
74
+ # python ScandirIterator does define the interface however.
75
+ pass
76
+
77
+
78
+ def scandir(path: TargetPath) -> _DissectScandirIterator:
79
+ return _DissectScandirIterator(path.get().scandir())
80
+
81
+
82
+ def realpath(path: TargetPath, *, strict: bool = False) -> str:
83
+ """Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path."""
84
+ filename = str(path)
85
+ path, _ = _joinrealpath(path._fs, filename[:0], filename, strict, {})
86
+ return abspath(path)
87
+
88
+
89
+ def isjunction(path: TargetPath) -> bool:
90
+ """Return True if the path is a junction."""
91
+ try:
92
+ from dissect.target.filesystems.ntfs import NtfsFilesystemEntry
93
+ except ImportError:
94
+ return False
95
+
96
+ entry = path.get()
97
+ # Python's ntpath isjunction() only checks for mount point reparse tags
98
+ return isinstance(entry, NtfsFilesystemEntry) and entry.dereference().is_mount_point()
99
+
100
+
101
+ # Join two paths, normalizing and eliminating any symbolic links
102
+ # encountered in the second path.
103
+ # NOTE: This is a copy of posixpath._joinrealpath with some small tweaks
104
+ def _joinrealpath(fs: Filesystem, path: str, rest: str, strict: bool, seen: dict[str, str]) -> tuple[str, bool]:
105
+ if posixpath.isabs(rest):
106
+ rest = rest[1:]
107
+ path = "/"
108
+
109
+ while rest:
110
+ name, _, rest = rest.partition("/")
111
+ if not name or name == ".":
112
+ # current dir
113
+ continue
114
+ if name == "..":
115
+ # parent dir
116
+ if path:
117
+ path, name = posixpath.split(path)
118
+ if name == "..":
119
+ path = posixpath.join(path, "..", "..")
120
+ else:
121
+ path = ".."
122
+ continue
123
+ newpath = posixpath.join(path, name)
124
+ try:
125
+ st = fs.get(newpath).lstat()
126
+ except FilesystemError:
127
+ if strict:
128
+ raise
129
+ is_link = False
130
+ else:
131
+ is_link = stat.S_ISLNK(st.st_mode)
132
+ if not is_link:
133
+ path = newpath
134
+ continue
135
+ # Resolve the symbolic link
136
+ if newpath in seen:
137
+ # Already seen this path
138
+ path = seen[newpath]
139
+ if path is not None:
140
+ # use cached value
141
+ continue
142
+ # The symlink is not resolved, so we must have a symlink loop.
143
+ if strict:
144
+ # Raise OSError(errno.ELOOP)
145
+ raise SymlinkRecursionError(newpath)
146
+ else:
147
+ # Return already resolved part + rest of the path unchanged.
148
+ return posixpath.join(newpath, rest), False
149
+ seen[newpath] = None # not resolved symlink
150
+ path, ok = _joinrealpath(fs, path, normalize(fs.readlink(newpath)), strict, seen)
151
+ if not ok:
152
+ return posixpath.join(path, rest), False
153
+ seen[newpath] = path # resolved symlink
154
+
155
+ return path, True
156
+
157
+
158
+ def io_open(
159
+ path: TargetPath,
160
+ mode: str = "rb",
161
+ buffering: int = 0,
162
+ encoding: Optional[str] = None,
163
+ errors: Optional[str] = None,
164
+ newline: Optional[str] = None,
165
+ ) -> IO:
166
+ """Open file and return a stream.
167
+
168
+ Supports a subset of features of the real pathlib.open/io.open.
169
+
170
+ Note: in contrast to regular Python, the mode is binary by default. Text mode
171
+ has to be explicitly specified. Buffering is also disabled by default.
172
+ """
173
+ modes = set(mode)
174
+ if modes - set("rbt") or len(mode) > len(modes):
175
+ raise ValueError("invalid mode: %r" % mode)
176
+
177
+ reading = "r" in modes
178
+ binary = "b" in modes
179
+ text = "t" in modes or "b" not in modes
180
+
181
+ if "b" not in mode:
182
+ encoding = encoding or "UTF-8"
183
+ # CPython >= 3.10
184
+ if hasattr(io, "text_encoding"):
185
+ # Vermin linting needs to be skipped for this line as this is
186
+ # guarded by an explicit check for availability.
187
+ # novermin
188
+ encoding = io.text_encoding(encoding)
189
+
190
+ if not reading:
191
+ raise ValueError("must be reading mode")
192
+ if text and binary:
193
+ raise ValueError("can't have text and binary mode at once")
194
+ if binary and encoding is not None:
195
+ raise ValueError("binary mode doesn't take an encoding argument")
196
+ if binary and errors is not None:
197
+ raise ValueError("binary mode doesn't take an errors argument")
198
+ if binary and newline is not None:
199
+ raise ValueError("binary mode doesn't take a newline argument")
200
+
201
+ raw = path.get().open()
202
+ result = raw
203
+
204
+ line_buffering = False
205
+ if buffering == 1 or buffering < 0 and raw.isatty():
206
+ buffering = -1
207
+ line_buffering = True
208
+ if buffering < 0 or text and buffering == 0:
209
+ buffering = io.DEFAULT_BUFFER_SIZE
210
+ if buffering == 0:
211
+ if binary:
212
+ return result
213
+ raise ValueError("can't have unbuffered text I/O")
214
+
215
+ buffer = io.BufferedReader(raw, buffering)
216
+ result = buffer
217
+ if binary:
218
+ return result
219
+
220
+ result = io.TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
221
+ result.mode = mode
222
+
223
+ return result