atomicshop 3.3.16__py3-none-any.whl → 3.3.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/mitm/import_config.py +9 -1
- atomicshop/mitm/mitm_main.py +9 -1
- atomicshop/mitm/statistic_analyzer.py +7 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +44 -4
- atomicshop/wrappers/socketw/creator.py +56 -5
- atomicshop/wrappers/socketw/exception_wrapper.py +20 -15
- atomicshop/wrappers/socketw/sni.py +10 -4
- atomicshop/wrappers/socketw/socket_wrapper.py +8 -1
- {atomicshop-3.3.16.dist-info → atomicshop-3.3.18.dist-info}/METADATA +1 -1
- {atomicshop-3.3.16.dist-info → atomicshop-3.3.18.dist-info}/RECORD +14 -14
- {atomicshop-3.3.16.dist-info → atomicshop-3.3.18.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.16.dist-info → atomicshop-3.3.18.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.16.dist-info → atomicshop-3.3.18.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/mitm/import_config.py
CHANGED
|
@@ -116,7 +116,15 @@ def import_engines_configs(print_kwargs: dict) -> int:
|
|
|
116
116
|
return result_code
|
|
117
117
|
|
|
118
118
|
# Assigning all the engines domains to all time domains, that will be responsible for adding new domains.
|
|
119
|
-
|
|
119
|
+
domains_all_times_with_ports: list[str] = list(domains_engine_list_full)
|
|
120
|
+
|
|
121
|
+
domains_all_times: list[str] = list()
|
|
122
|
+
for domain_and_port in domains_all_times_with_ports:
|
|
123
|
+
domain: str = domain_and_port.split(':')[0]
|
|
124
|
+
if domain not in domains_engine_list_full:
|
|
125
|
+
domains_all_times.append(domain)
|
|
126
|
+
|
|
127
|
+
config_static.Certificates.domains_all_times = domains_all_times
|
|
120
128
|
|
|
121
129
|
config_static.ENGINES_LIST = engines_list
|
|
122
130
|
config_static.REFERENCE_MODULE = reference_module
|
atomicshop/mitm/mitm_main.py
CHANGED
|
@@ -20,6 +20,14 @@ from .connection_thread_worker import thread_worker_main
|
|
|
20
20
|
from . import config_static, recs_files
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
# If you have 'pip-system-certs' package installed, this section overrides this behavior, since it injects
|
|
24
|
+
# the ssl default behavior, which we don't need when using ssl and sockets.
|
|
25
|
+
import ssl, importlib
|
|
26
|
+
if getattr(ssl.SSLContext.wrap_socket, "__module__", "").startswith("pip._vendor.truststore"):
|
|
27
|
+
# Truststore injection is active; restore stdlib ssl
|
|
28
|
+
importlib.reload(ssl)
|
|
29
|
+
|
|
30
|
+
|
|
23
31
|
class NetworkSettings:
|
|
24
32
|
"""
|
|
25
33
|
Class to store network settings.
|
|
@@ -162,7 +170,7 @@ def startup_output(system_logger, script_version: str):
|
|
|
162
170
|
f"Default server certificate usage enabled, if no SNI available: "
|
|
163
171
|
f"{config_static.MainConfig.default_server_certificate_filepath}")
|
|
164
172
|
|
|
165
|
-
if config_static.Certificates.
|
|
173
|
+
if config_static.Certificates.sni_create_server_certificate_for_each_domain:
|
|
166
174
|
system_logger.info(
|
|
167
175
|
f"SNI function certificates creation enabled. Certificates cache: "
|
|
168
176
|
f"{config_static.Certificates.sni_server_certificates_cache_directory}")
|
|
@@ -352,6 +352,7 @@ def deviation_calculator_by_moving_average(
|
|
|
352
352
|
moving_average_window_days: int = 5,
|
|
353
353
|
top_bottom_deviation_percentage: float = 0.25,
|
|
354
354
|
get_deviation_for_last_day_only: bool = False,
|
|
355
|
+
get_deviation_for_date: str = None,
|
|
355
356
|
summary: bool = False,
|
|
356
357
|
output_file_path: str = None,
|
|
357
358
|
output_file_type: Literal['json', 'csv'] = 'json',
|
|
@@ -386,6 +387,8 @@ def deviation_calculator_by_moving_average(
|
|
|
386
387
|
Files 01 to 05 will be used for moving average and the file 06 for deviation.
|
|
387
388
|
Meaning the average calculated for 2021-01-06 will be compared to the values moving average of 2021-01-01
|
|
388
389
|
to 2021-01-05.
|
|
390
|
+
:param get_deviation_for_date: string, if specified, only the specified date will be analyzed.
|
|
391
|
+
The date must be in the format of 'YYYY-MM-DD'. Example: '2021-01-06'.
|
|
389
392
|
:param summary: bool, if True, Only the summary will be generated without all the numbers that were used
|
|
390
393
|
to calculate the averages and the moving average data.
|
|
391
394
|
:param output_file_path: string, if None, no file will be written.
|
|
@@ -437,6 +440,9 @@ def deviation_calculator_by_moving_average(
|
|
|
437
440
|
if by_type not in ['host', 'url']:
|
|
438
441
|
raise ValueError(f'by_type must be "host" or "url", not [{by_type}]')
|
|
439
442
|
|
|
443
|
+
if get_deviation_for_last_day_only and get_deviation_for_date:
|
|
444
|
+
raise ValueError('Either [get_deviation_for_last_day_only] or [get_deviation_for_date] can be provided, not both.')
|
|
445
|
+
|
|
440
446
|
if statistics_file_directory:
|
|
441
447
|
statistics_file_path: str | None = f'{statistics_file_directory}{os.sep}{STATISTICS_FILE_NAME}'
|
|
442
448
|
else:
|
|
@@ -449,6 +455,7 @@ def deviation_calculator_by_moving_average(
|
|
|
449
455
|
moving_average_window_days,
|
|
450
456
|
top_bottom_deviation_percentage,
|
|
451
457
|
get_deviation_for_last_day_only,
|
|
458
|
+
get_deviation_for_date,
|
|
452
459
|
skip_total_count_less_than
|
|
453
460
|
)
|
|
454
461
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import statistics
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Literal
|
|
4
|
+
import datetime
|
|
4
5
|
|
|
5
6
|
from ...print_api import print_api
|
|
6
7
|
from ...wrappers.loggingw import reading, consts
|
|
@@ -15,6 +16,7 @@ def calculate_moving_average(
|
|
|
15
16
|
moving_average_window_days: int = 5,
|
|
16
17
|
top_bottom_deviation_percentage: float = 0.25,
|
|
17
18
|
get_deviation_for_last_day_only: bool = False,
|
|
19
|
+
get_deviation_for_date: str = None,
|
|
18
20
|
skip_total_count_less_than: int = None,
|
|
19
21
|
print_kwargs: dict = None
|
|
20
22
|
) -> list:
|
|
@@ -29,6 +31,7 @@ def calculate_moving_average(
|
|
|
29
31
|
:param top_bottom_deviation_percentage: float, the percentage of deviation from the moving average to the top or
|
|
30
32
|
bottom.
|
|
31
33
|
:param get_deviation_for_last_day_only: bool, check the 'get_all_files_content' function.
|
|
34
|
+
:param get_deviation_for_date: str, check the 'get_all_files_content' function.
|
|
32
35
|
:param skip_total_count_less_than: integer, if the total count is less than this number, skip the deviation.
|
|
33
36
|
:param print_kwargs: dict, the print_api arguments.
|
|
34
37
|
"""
|
|
@@ -38,10 +41,15 @@ def calculate_moving_average(
|
|
|
38
41
|
if file_path and statistics_content:
|
|
39
42
|
raise ValueError('Only one of file_path or statistics_content must be provided.')
|
|
40
43
|
|
|
44
|
+
if get_deviation_for_last_day_only and get_deviation_for_date:
|
|
45
|
+
raise ValueError('Only one of get_deviation_for_last_day_only or get_deviation_for_date can be set.')
|
|
46
|
+
|
|
41
47
|
if not statistics_content:
|
|
42
48
|
statistics_content: dict = get_all_files_content(
|
|
43
49
|
file_path=file_path, moving_average_window_days=moving_average_window_days,
|
|
44
|
-
get_deviation_for_last_day_only=get_deviation_for_last_day_only,
|
|
50
|
+
get_deviation_for_last_day_only=get_deviation_for_last_day_only,
|
|
51
|
+
get_deviation_for_date=get_deviation_for_date,
|
|
52
|
+
print_kwargs=print_kwargs)
|
|
45
53
|
|
|
46
54
|
for date_string, day_dict in statistics_content.items():
|
|
47
55
|
day_dict['content_no_useless'] = get_content_without_useless(day_dict['content'])
|
|
@@ -73,6 +81,7 @@ def get_all_files_content(
|
|
|
73
81
|
file_path: str,
|
|
74
82
|
moving_average_window_days: int,
|
|
75
83
|
get_deviation_for_last_day_only: bool = False,
|
|
84
|
+
get_deviation_for_date: str = None,
|
|
76
85
|
print_kwargs: dict = None
|
|
77
86
|
) -> dict:
|
|
78
87
|
"""
|
|
@@ -83,7 +92,7 @@ def get_all_files_content(
|
|
|
83
92
|
:param get_deviation_for_last_day_only: bool, if True, only the last day will be analyzed.
|
|
84
93
|
Example: With 'moving_average_window_days=5', the last 6 days will be analyzed.
|
|
85
94
|
5 days for moving average and the last day for deviation.
|
|
86
|
-
File names example:
|
|
95
|
+
File names example the last day is 2021-01-06:
|
|
87
96
|
statistics_2021-01-01.csv
|
|
88
97
|
statistics_2021-01-02.csv
|
|
89
98
|
statistics_2021-01-03.csv
|
|
@@ -93,12 +102,24 @@ def get_all_files_content(
|
|
|
93
102
|
Files 01 to 05 will be used for moving average and the file 06 for deviation.
|
|
94
103
|
Meaning the average calculated for 2021-01-06 will be compared to the values moving average of 2021-01-01
|
|
95
104
|
to 2021-01-05.
|
|
105
|
+
:param get_deviation_for_date: str, if set, the last day is considered the date that you set here.
|
|
106
|
+
The format should be the same as in the file names, e.g. 'YYYY-MM-DD'.
|
|
96
107
|
:param print_kwargs: dict, the print_api arguments.
|
|
97
108
|
:return:
|
|
98
109
|
"""
|
|
99
110
|
|
|
111
|
+
if get_deviation_for_last_day_only and get_deviation_for_date:
|
|
112
|
+
raise ValueError('Only one of get_deviation_for_last_day_only or get_deviation_for_date can be set.')
|
|
113
|
+
|
|
100
114
|
date_format: str = consts.DEFAULT_ROTATING_SUFFIXES_FROM_WHEN['midnight']
|
|
101
115
|
|
|
116
|
+
def is_valid_date(date_str: str) -> bool:
|
|
117
|
+
try:
|
|
118
|
+
datetime.datetime.strptime(date_str, date_format)
|
|
119
|
+
return True
|
|
120
|
+
except ValueError:
|
|
121
|
+
return False
|
|
122
|
+
|
|
102
123
|
# Get all the file paths and their midnight rotations.
|
|
103
124
|
logs_paths: list[filesystem.AtomicPath] = reading.get_logs_paths(
|
|
104
125
|
log_file_path=file_path,
|
|
@@ -109,6 +130,24 @@ def get_all_files_content(
|
|
|
109
130
|
days_back_to_analyze: int = moving_average_window_days + 1
|
|
110
131
|
logs_paths = logs_paths[-days_back_to_analyze:]
|
|
111
132
|
|
|
133
|
+
if get_deviation_for_date:
|
|
134
|
+
# Check if the date format is correct.
|
|
135
|
+
if not is_valid_date(get_deviation_for_date):
|
|
136
|
+
raise ValueError(f'Date [{get_deviation_for_date}] is not in the correct format: {date_format}')
|
|
137
|
+
|
|
138
|
+
# Find the index of the date in the logs_paths list.
|
|
139
|
+
date_index: int | None = None
|
|
140
|
+
for index, log_atomic_path in enumerate(logs_paths):
|
|
141
|
+
if log_atomic_path.datetime_string == get_deviation_for_date:
|
|
142
|
+
date_index = index
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
if date_index is None:
|
|
146
|
+
raise ValueError(f'Date {get_deviation_for_date} not found in the log files.')
|
|
147
|
+
|
|
148
|
+
start_index: int = max(0, date_index - moving_average_window_days)
|
|
149
|
+
logs_paths = logs_paths[start_index:date_index + 1]
|
|
150
|
+
|
|
112
151
|
statistics_content: dict = {}
|
|
113
152
|
# Read each file to its day.
|
|
114
153
|
for log_atomic_path in logs_paths:
|
|
@@ -260,7 +299,7 @@ def compute_moving_averages_from_average_statistics(
|
|
|
260
299
|
|
|
261
300
|
# Create list of the last 'moving_average_window_days' days, including the current day.
|
|
262
301
|
last_x_window_days_content_list = (
|
|
263
|
-
list(average_statistics_dict.values()))[current_day-moving_average_window_days:current_day]
|
|
302
|
+
list(average_statistics_dict.values()))[current_day - moving_average_window_days:current_day]
|
|
264
303
|
|
|
265
304
|
# Compute the moving averages.
|
|
266
305
|
moving_average[day] = compute_average_for_current_day_from_past_x_days(
|
|
@@ -443,7 +482,8 @@ def find_deviation_from_moving_average(
|
|
|
443
482
|
if day_index == 0:
|
|
444
483
|
previous_day_moving_average_dict = {}
|
|
445
484
|
else:
|
|
446
|
-
previous_day_moving_average_dict = list(statistics_content.values())[day_index-1].get('moving_average',
|
|
485
|
+
previous_day_moving_average_dict = list(statistics_content.values())[day_index - 1].get('moving_average',
|
|
486
|
+
{})
|
|
447
487
|
|
|
448
488
|
# If there is no moving average for previous day continue to the next day.
|
|
449
489
|
if not previous_day_moving_average_dict:
|
|
@@ -25,20 +25,36 @@ def add_reusable_address_option(socket_instance):
|
|
|
25
25
|
socket_instance.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def create_ssl_context_for_server() -> ssl.SSLContext:
|
|
28
|
+
def create_ssl_context_for_server(allow_legacy=False) -> ssl.SSLContext:
|
|
29
29
|
# Creating context with SSL certificate and the private key before the socket
|
|
30
30
|
# https://docs.python.org/3/library/ssl.html
|
|
31
31
|
# Creating context for SSL wrapper, specifying "PROTOCOL_TLS_SERVER" will pick the best TLS version protocol for
|
|
32
32
|
# the server.
|
|
33
33
|
|
|
34
|
-
ssl_context: ssl.SSLContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
34
|
+
# ssl_context: ssl.SSLContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
35
35
|
|
|
36
36
|
# # Enforce the use of TLS 1.2 only (disable TLS 1.0, TLS 1.1, and TLS 1.3)
|
|
37
37
|
# ssl_context.options |= ssl.OP_NO_TLSv1 # Disable TLS 1.0
|
|
38
38
|
# ssl_context.options |= ssl.OP_NO_TLSv1_1 # Disable TLS 1.1
|
|
39
39
|
# ssl_context.options |= ssl.OP_NO_TLSv1_3 # Disable TLS 1.3
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# Correct factory for servers
|
|
42
|
+
ssl_context: ssl.SSLContext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
|
43
|
+
|
|
44
|
+
# Modern default; relax only if you must
|
|
45
|
+
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
|
|
46
|
+
|
|
47
|
+
# Don't verify client certificates.
|
|
48
|
+
ssl_context.verify_mode = ssl.CERT_NONE
|
|
49
|
+
ssl_context.check_hostname = False
|
|
50
|
+
|
|
51
|
+
# If you must support old clients that only offer TLS_RSA_* suites under OpenSSL 3:
|
|
52
|
+
if allow_legacy:
|
|
53
|
+
# This enables RSA key exchange and other legacy bits at security level 1
|
|
54
|
+
ssl_context.set_ciphers('DEFAULT:@SECLEVEL=1')
|
|
55
|
+
# If you truly have TLS 1.0/1.1 clients, uncomment the next line (not recommended):
|
|
56
|
+
ssl_context.minimum_version = ssl.TLSVersion.TLSv1
|
|
57
|
+
|
|
42
58
|
return ssl_context
|
|
43
59
|
|
|
44
60
|
|
|
@@ -138,9 +154,44 @@ def load_certificate_and_key_into_server_ssl_context(
|
|
|
138
154
|
print_api(message, error_type=True, logger_method="critical", **print_kwargs)
|
|
139
155
|
|
|
140
156
|
|
|
141
|
-
def
|
|
157
|
+
def copy_server_ctx_settings(src: ssl.SSLContext, dst: ssl.SSLContext) -> None:
|
|
158
|
+
# Versions & options
|
|
159
|
+
try: dst.minimum_version = src.minimum_version
|
|
160
|
+
except Exception: pass
|
|
161
|
+
try: dst.maximum_version = src.maximum_version
|
|
162
|
+
except Exception: pass
|
|
163
|
+
try: dst.options = src.options
|
|
164
|
+
except Exception: pass
|
|
165
|
+
|
|
166
|
+
# Verification knobs (server usually CERT_NONE unless you do mTLS)
|
|
167
|
+
try: dst.verify_mode = src.verify_mode
|
|
168
|
+
except Exception: pass
|
|
169
|
+
try: dst.check_hostname = src.check_hostname
|
|
170
|
+
except Exception: pass
|
|
171
|
+
|
|
172
|
+
# Cipher policy – replicate current enabled list
|
|
173
|
+
try:
|
|
174
|
+
cipher_names = ':'.join(c['name'] for c in src.get_ciphers())
|
|
175
|
+
if cipher_names:
|
|
176
|
+
dst.set_ciphers(cipher_names)
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
# (ALPN/curves/etc. don’t have public getters; set them the same way you set them on src, if applicable)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def create_server_ssl_context___load_certificate_and_key(
|
|
184
|
+
certificate_file_path: str,
|
|
185
|
+
key_file_path: str | None,
|
|
186
|
+
inherit_from: ssl.SSLContext | None = None
|
|
187
|
+
) -> ssl.SSLContext:
|
|
142
188
|
# Create and set ssl context for server.
|
|
143
|
-
ssl_context: ssl.SSLContext = create_ssl_context_for_server()
|
|
189
|
+
ssl_context: ssl.SSLContext = create_ssl_context_for_server(True)
|
|
190
|
+
|
|
191
|
+
# If you replaced contexts during SNI, copy policy from the old one
|
|
192
|
+
if inherit_from is not None:
|
|
193
|
+
copy_server_ctx_settings(inherit_from, ssl_context)
|
|
194
|
+
|
|
144
195
|
# Load certificate into context.
|
|
145
196
|
load_certificate_and_key_into_server_ssl_context(ssl_context, certificate_file_path, key_file_path)
|
|
146
197
|
# Return ssl context only.
|
|
@@ -75,18 +75,25 @@ def connection_exception_decorator(function_name):
|
|
|
75
75
|
pass
|
|
76
76
|
pass
|
|
77
77
|
except ssl.SSLError as exception_object:
|
|
78
|
-
|
|
79
|
-
if exception_object
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
excepted: bool = False
|
|
79
|
+
if getattr(exception_object, "reason", None):
|
|
80
|
+
# Getting the exact reason of "ssl.SSLError"
|
|
81
|
+
if exception_object.reason == "HTTP_REQUEST":
|
|
82
|
+
message = f"Socket Accept: HTTP Request on SSL Socket: " \
|
|
83
|
+
f"{base.get_source_destination(kwargs['socket_object'])}"
|
|
84
|
+
wrapper_handle_connection_exceptions.message = message
|
|
85
|
+
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
86
|
+
|
|
87
|
+
excepted = True
|
|
88
|
+
elif exception_object.reason == "TSV1_ALERT_UNKNOWN_CA":
|
|
89
|
+
message = f"Socket Accept: Check CA certificate on the client " \
|
|
90
|
+
f"{base.get_source_destination(kwargs['socket_object'])}"
|
|
91
|
+
wrapper_handle_connection_exceptions.message = message
|
|
92
|
+
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
93
|
+
|
|
94
|
+
excepted = True
|
|
95
|
+
|
|
96
|
+
if not excepted:
|
|
90
97
|
# Not all requests have the server name passed through Client Hello.
|
|
91
98
|
# If it is not passed an error of undefined variable will be raised.
|
|
92
99
|
# So, we'll check if the variable as a string is in the "locals()" variable pool.
|
|
@@ -102,21 +109,19 @@ def connection_exception_decorator(function_name):
|
|
|
102
109
|
f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
103
110
|
wrapper_handle_connection_exceptions.message = message
|
|
104
111
|
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
105
|
-
|
|
112
|
+
|
|
106
113
|
except FileNotFoundError:
|
|
107
114
|
message = "'SSLSocket.accept()' crashed: 'FileNotFoundError'. Some problem with SSL during Handshake - " \
|
|
108
115
|
"Could be certificate, client, or server."
|
|
109
116
|
message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
110
117
|
wrapper_handle_connection_exceptions.message = message
|
|
111
118
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
112
|
-
pass
|
|
113
119
|
except Exception as e:
|
|
114
120
|
_ = e
|
|
115
121
|
message = "Undocumented exception on accept."
|
|
116
122
|
message = f"Socket Accept: {domain_from_dns_server}:{port}: {message}"
|
|
117
123
|
wrapper_handle_connection_exceptions.message = message
|
|
118
124
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
119
|
-
pass
|
|
120
125
|
|
|
121
126
|
wrapper_handle_connection_exceptions.message = None
|
|
122
127
|
return wrapper_handle_connection_exceptions
|
|
@@ -82,7 +82,7 @@ class SNISetup:
|
|
|
82
82
|
):
|
|
83
83
|
|
|
84
84
|
# Create SSL Socket to wrap the raw socket with.
|
|
85
|
-
ssl_context: ssl.SSLContext = creator.create_ssl_context_for_server()
|
|
85
|
+
ssl_context: ssl.SSLContext = creator.create_ssl_context_for_server(True)
|
|
86
86
|
|
|
87
87
|
self.certificator_instance = certificator.Certificator(
|
|
88
88
|
ca_certificate_name=self.ca_certificate_name,
|
|
@@ -149,7 +149,8 @@ class SNISetup:
|
|
|
149
149
|
# The function is actually called at "accept()" method of the "ssl.SSLSocket"
|
|
150
150
|
# This needs to be set only once on the listening socket
|
|
151
151
|
if self.sni_custom_callback_function:
|
|
152
|
-
ssl_context.sni_callback = self.sni_custom_callback_function
|
|
152
|
+
# ssl_context.sni_callback = self.sni_custom_callback_function
|
|
153
|
+
ssl_context.set_servername_callback(self.sni_custom_callback_function)
|
|
153
154
|
|
|
154
155
|
if self.sni_use_default_callback_function:
|
|
155
156
|
sni_handler_instance = SNIHandler(
|
|
@@ -320,8 +321,13 @@ class SNIHandler:
|
|
|
320
321
|
# Since new default certificate was created we need to create new SSLContext and add the certificate.
|
|
321
322
|
# You need to build new context and exchange the context that being inherited from the main socket,
|
|
322
323
|
# or else the context will receive previous certificate each time.
|
|
323
|
-
self.sni_received_parameters.ssl_socket.context =
|
|
324
|
-
creator.create_server_ssl_context___load_certificate_and_key(
|
|
324
|
+
self.sni_received_parameters.ssl_socket.context = (
|
|
325
|
+
creator.create_server_ssl_context___load_certificate_and_key(
|
|
326
|
+
default_server_certificate_path,
|
|
327
|
+
None,
|
|
328
|
+
inherit_from=self.sni_received_parameters.ssl_socket.context
|
|
329
|
+
)
|
|
330
|
+
)
|
|
325
331
|
else:
|
|
326
332
|
message = f"Couldn't create / overwrite Default Server Certificate: {default_server_certificate_path}"
|
|
327
333
|
raise SNIDefaultCertificateCreationError(message)
|
|
@@ -378,7 +378,8 @@ class SocketWrapper:
|
|
|
378
378
|
|
|
379
379
|
os.makedirs(self.sni_server_certificates_cache_directory, exist_ok=True)
|
|
380
380
|
print_api("Removed cached server certificates.", logger=self.logger)
|
|
381
|
-
|
|
381
|
+
else:
|
|
382
|
+
os.makedirs(self.sni_server_certificates_cache_directory, exist_ok=True)
|
|
382
383
|
|
|
383
384
|
if self.install_ca_certificate_to_root_store:
|
|
384
385
|
if not self.ca_certificate_filepath:
|
|
@@ -613,6 +614,12 @@ class SocketWrapper:
|
|
|
613
614
|
print_kwargs={'logger': self.logger}
|
|
614
615
|
)
|
|
615
616
|
|
|
617
|
+
if ssl_client_socket:
|
|
618
|
+
# Handshake is done at this point, so version/cipher are available
|
|
619
|
+
self.logger.info(
|
|
620
|
+
f"TLS version={ssl_client_socket.version()} cipher={ssl_client_socket.cipher()}"
|
|
621
|
+
)
|
|
622
|
+
|
|
616
623
|
if accept_error_message:
|
|
617
624
|
# Write statistics after wrap is there was an error.
|
|
618
625
|
self.statistics_writer.write_accept_error(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=ZZgIypIAzAvhlg6GcAfDfISP0Pv6PTd2kCCEgIKx420,123
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -128,13 +128,13 @@ atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
128
128
|
atomicshop/mitm/config_static.py,sha256=KzO8DjZjRHfkQMYSIGTkW4jLNPzMR8visTqs1H6ZQ-U,8926
|
|
129
129
|
atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
|
|
130
130
|
atomicshop/mitm/connection_thread_worker.py,sha256=p-93_zdq3HzWpR7NF-gIq0JvvX0L8jz3_TSD3tBhV4o,33255
|
|
131
|
-
atomicshop/mitm/import_config.py,sha256=
|
|
131
|
+
atomicshop/mitm/import_config.py,sha256=7aLfKqflc3ZnzKc2_Y4T0eenzQpKG94M0r-PaVwF99M,18881
|
|
132
132
|
atomicshop/mitm/initialize_engines.py,sha256=qzz5jzh_lKC03bI1w5ebngVXo1K-RV3poAyW-nObyqo,11042
|
|
133
133
|
atomicshop/mitm/message.py,sha256=CDhhm4BTuZE7oNZCjvIZ4BuPOW4MuIzQLOg91hJaxDI,3065
|
|
134
|
-
atomicshop/mitm/mitm_main.py,sha256=
|
|
134
|
+
atomicshop/mitm/mitm_main.py,sha256=u9q4BYIhScw9W9M7AS4h217gKQXkuppOFxvprEBVPGE,39366
|
|
135
135
|
atomicshop/mitm/recs_files.py,sha256=tv8XFhYZMkBv4DauvpiAdPgvSo0Bcm1CghnmwO7dx8M,5018
|
|
136
136
|
atomicshop/mitm/shared_functions.py,sha256=0lzeyINd44sVEfFbahJxQmz6KAMWbYrW5ou3UYfItvw,1777
|
|
137
|
-
atomicshop/mitm/statistic_analyzer.py,sha256=
|
|
137
|
+
atomicshop/mitm/statistic_analyzer.py,sha256=EC9g21ocOsFzNfntV-nZHSGtrS1-Kxb0QDSGWS5FuNA,28942
|
|
138
138
|
atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
139
|
atomicshop/mitm/engines/create_module_template.py,sha256=PHE2pVC9JNgaIh2o7M5dFMrkdOkmIyHLoO2mdzE5BdM,5938
|
|
140
140
|
atomicshop/mitm/engines/create_module_template_main_example.py,sha256=LeQ44Rp2Gi_KbIDY_4OMS0odkSK3zFZWra_oAka5eJY,243
|
|
@@ -150,7 +150,7 @@ atomicshop/mitm/engines/__reference_general/requester___reference_general.py,sha
|
|
|
150
150
|
atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=5XSmvF0d6d9mPkPOGw7f9T-Cr-YoUiUTVYgBIjiKh7s,10615
|
|
151
151
|
atomicshop/mitm/statistic_analyzer_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
152
152
|
atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py,sha256=pk6L1t1ea1kvlBoR9QEJptOmaX-mumhwLsP2GCKukbk,5920
|
|
153
|
-
atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=
|
|
153
|
+
atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=j_0_8p-6ExVbbhILMeY7RuQ3PTNjs-mB6y0wr2ie34U,23501
|
|
154
154
|
atomicshop/monitor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
155
|
atomicshop/monitor/change_monitor.py,sha256=K5NlVp99XIDDPnQQMdru4BDmua_DtcDIhVAzkTOvD5s,7673
|
|
156
156
|
atomicshop/monitor/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -301,23 +301,23 @@ atomicshop/wrappers/socketw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
|
301
301
|
atomicshop/wrappers/socketw/accepter.py,sha256=4I9ORugRDvwaqSzm_gWSjZnRwQGY8hDTlCdsYHwH_ZE,2377
|
|
302
302
|
atomicshop/wrappers/socketw/base.py,sha256=EcosGkD8VzgBY3GeIHDSG29ThQfXwg3-GQPmBTAqTdw,3048
|
|
303
303
|
atomicshop/wrappers/socketw/certificator.py,sha256=mtWPJ_ew3OSwt0-1W4jaoco1VIY4NRCrMv3mDUxb_Cc,12418
|
|
304
|
-
atomicshop/wrappers/socketw/creator.py,sha256=
|
|
304
|
+
atomicshop/wrappers/socketw/creator.py,sha256=8cRX8mfU36rDCZ6eUPqPw1_GVX6inr4x4LEuWoV-esE,15866
|
|
305
305
|
atomicshop/wrappers/socketw/dns_server.py,sha256=GOYMvHvS6Fx7s-DRygGqO7_o8_Qt9on3HmKxgOSznRE,55956
|
|
306
|
-
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=
|
|
306
|
+
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=_p98OdOaKYSMqJ23pHLXBUA7NkbVmpgqcSJAdWr6wwc,7560
|
|
307
307
|
atomicshop/wrappers/socketw/get_process.py,sha256=aJC-_qFUv3NgWCSUzDI72E4z8_-VTZE9NVZ0CwUoNlM,5698
|
|
308
308
|
atomicshop/wrappers/socketw/receiver.py,sha256=9B3MvcDqr4C3x2fsnjG5SQognd1wRqsBgikxZa0wXG8,8243
|
|
309
309
|
atomicshop/wrappers/socketw/sender.py,sha256=aX_K8l_rHjd5AWb8bi5mt8-YTkMYVRDB6DnPqK_XDUE,4754
|
|
310
|
-
atomicshop/wrappers/socketw/sni.py,sha256=
|
|
310
|
+
atomicshop/wrappers/socketw/sni.py,sha256=uj6KKYKmSrzXcKBhVLaHQhYn1wNfIUpdnmcvn21V9iE,18176
|
|
311
311
|
atomicshop/wrappers/socketw/socket_client.py,sha256=WWIiCxUX9irN9aWzJ6-1xrXNB_iv_diq3ha1yrWsNGU,22671
|
|
312
312
|
atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
|
|
313
|
-
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=
|
|
313
|
+
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=8tRoccWvnDNXaK2iYsT68RyxHHjILdPjw2R7SxPC6go,41621
|
|
314
314
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=62-hPm7zla1rh3m_WvDnXqKH-sDUTdiRptD8STCkgdk,2313
|
|
315
315
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=_gA8bMX6Sw_UCXKi2y9wNAwlqifgExgDGfQIa9pFxQA,5543
|
|
316
316
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
317
317
|
atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
|
|
318
318
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
|
|
319
|
-
atomicshop-3.3.
|
|
320
|
-
atomicshop-3.3.
|
|
321
|
-
atomicshop-3.3.
|
|
322
|
-
atomicshop-3.3.
|
|
323
|
-
atomicshop-3.3.
|
|
319
|
+
atomicshop-3.3.18.dist-info/licenses/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
320
|
+
atomicshop-3.3.18.dist-info/METADATA,sha256=9i69mSa_kRBTR5_2RN1F5-rAJm7myfH7dBjI3gXBrsA,9345
|
|
321
|
+
atomicshop-3.3.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
322
|
+
atomicshop-3.3.18.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
323
|
+
atomicshop-3.3.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|