|
7 | 7 | """ |
8 | 8 |
|
9 | 9 | from pathlib import Path |
| 10 | +from multiprocessing import Pool |
| 11 | +from functools import partial |
10 | 12 | import linksiren.pure_functions |
| 13 | +from tqdm import tqdm |
11 | 14 |
|
12 | 15 |
|
13 | 16 | def write_payload_local(payload_name, payload_contents): |
@@ -75,60 +78,91 @@ def read_targets(targets_file): |
75 | 78 | return linksiren.pure_functions.process_targets(target_unc_paths) |
76 | 79 |
|
77 | 80 |
|
| 81 | +def get_rankings_for_target( |
| 82 | + target, domain, username, password, active_threshold_date, max_depth, go_fast |
| 83 | +): |
| 84 | + folder_rankings = {} |
| 85 | + |
| 86 | + if target.connection is None: |
| 87 | + try: |
| 88 | + target.connect(user=username, password=password, domain=domain) |
| 89 | + except Exception as e: |
| 90 | + print(f"Error connecting to {target.host}: {e}") |
| 91 | + return folder_rankings |
| 92 | + |
| 93 | + # Expand any empty paths for the target |
| 94 | + # An empty path indicates all shares on the host should be targeted |
| 95 | + try: |
| 96 | + target.expand_paths() |
| 97 | + except Exception as e: |
| 98 | + print(f"Error expanding paths on {target.host}: {e}") |
| 99 | + return folder_rankings |
| 100 | + |
| 101 | + try: |
| 102 | + # Call the appropriate review function based on the fast argument |
| 103 | + folder_rankings = target.review_all_folders( |
| 104 | + folder_rankings, active_threshold_date, max_depth, go_fast |
| 105 | + ) |
| 106 | + except Exception as e: |
| 107 | + print(f"Error connecting to shares on {target.host}: {e}") |
| 108 | + |
| 109 | + return folder_rankings |
| 110 | + |
| 111 | + |
78 | 112 | # Eventually we should just pass the whole parsed arguments structure to different functions |
79 | 113 | # And then modify behaviors by checking options for things like active_threshold_date, max_depth |
80 | 114 | # creds/ntlm hash, go_fast, etc. |
81 | 115 | def get_rankings( |
82 | 116 | targets, domain, username, password, active_threshold_date, max_depth, go_fast |
83 | 117 | ): |
84 | 118 | """ |
85 | | - get_sorted_rankings(targets, active_threshold, max_depth, go_fast) |
| 119 | + get_rankings(targets, domain, username, password, active_threshold_date, max_depth, go_fast) |
86 | 120 |
|
87 | | - :param list targets: List of UNC paths to shares and base directories to review. |
88 | | - :param int active_threshold: Number of days within which file access constitutes a file being |
89 | | - active |
| 121 | + :param str domain: Domain for authentication. |
| 122 | + :param str username: Username for authentication. |
| 123 | + :param str password: Password for authentication. |
| 124 | + :param datetime active_threshold_date: Date threshold to determine if a file is active. |
| 125 | + dictionary of UNC paths and associated rankings. Catches exceptions for failed smb connections |
90 | 126 | :param int max_depth: Number of layers of folders to search. 1 searches only the specified |
91 | 127 | target UNC paths and none of their subfolders. |
92 | 128 | :param bool go_fast: If True, folders will be marked as active as soon as a single file is |
93 | 129 | meeting the active_threshold criteria is found. A rank of 1 will be assigned to all active |
94 | 130 | folders. |
95 | 131 |
|
96 | | - :return: A dictionary in the format {<folder UNC path>: <ranking>} sorted by ranking |
| 132 | + :return: A dictionary in the format {<folder UNC path>: <ranking>} |
97 | 133 |
|
98 | | - Accepts a list of UNC paths to file shares and base directories. Gets the ranking associated |
99 | | - with each folder based on the number of files active within the active_threshold number of days. |
| 134 | + Accepts a list of UNC target objects. Gets rankings associated with each path associated with |
| 135 | + each target based on the number of files active within the active_threshold number of days. |
100 | 136 | Recursively assigns ranking to subfolders up to max_depth. If go_fast is enabled, assigns the |
101 | 137 | rank of 1 to all folders with a single active file and moves on to the next folder. Returns a |
102 | 138 | dirctionary of UNC paths and associated rankings. Catches exceptions for failed smb connections |
103 | 139 | and prints a message describing the error. |
104 | 140 | """ |
105 | 141 | # Track rankings for each folder, which are (counterintuitively) scores corresponding to the |
106 | | - # number of active files in a folder. {<folder UNC path>: <ranking>} |
| 142 | + # number of active files in a folder. So a higher ranking is a better target. |
| 143 | + # {<folder UNC path>: <ranking>} |
107 | 144 | folder_rankings = {} |
108 | 145 |
|
109 | | - for target in targets: |
110 | | - if target.connection is None: |
111 | | - try: |
112 | | - target.connect(user=username, password=password, domain=domain) |
113 | | - except Exception as e: |
114 | | - print(f"Error connecting to {target.host}: {e}") |
115 | | - return folder_rankings |
| 146 | + worker_partial = partial( |
| 147 | + get_rankings_for_target, |
| 148 | + domain=domain, |
| 149 | + username=username, |
| 150 | + password=password, |
| 151 | + active_threshold_date=active_threshold_date, |
| 152 | + max_depth=max_depth, |
| 153 | + go_fast=go_fast, |
| 154 | + ) |
116 | 155 |
|
117 | | - # Expand any empty paths for the target |
118 | | - # An empty path indicates all shares on the host should be targeted |
119 | | - try: |
120 | | - target.expand_paths() |
121 | | - except Exception as e: |
122 | | - print(f"Error expanding paths on {target.host}: {e}") |
123 | | - return folder_rankings |
| 156 | + with Pool(processes=2) as pool: |
| 157 | + for result in tqdm( |
| 158 | + pool.imap_unordered(func=worker_partial, iterable=targets), |
| 159 | + total=len(targets), |
| 160 | + ): |
| 161 | + if result is not None: |
| 162 | + folder_rankings.update(result) |
124 | 163 |
|
125 | | - try: |
126 | | - # Call the appropriate review function based on the fast argument |
127 | | - folder_rankings = target.review_all_folders( |
128 | | - folder_rankings, active_threshold_date, max_depth, go_fast |
129 | | - ) |
130 | | - except Exception as e: |
131 | | - print(f"Error connecting to shares on {target.host}: {e}") |
| 164 | + pool.close() |
| 165 | + pool.join() |
132 | 166 |
|
133 | 167 | return folder_rankings |
134 | 168 |
|
|
0 commit comments