atomicshop 2.16.13__py3-none-any.whl → 2.16.15__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/certificates.py +146 -51
- atomicshop/mitm/config_static.py +15 -2
- atomicshop/mitm/import_config.py +8 -0
- atomicshop/mitm/initialize_engines.py +4 -1
- atomicshop/mitm/mitm_main.py +13 -7
- atomicshop/wrappers/cryptographyw.py +3 -1
- atomicshop/wrappers/loggingw/handlers.py +16 -4
- atomicshop/wrappers/loggingw/loggingw.py +5 -1
- atomicshop/wrappers/pywin32w/cert_store.py +89 -0
- atomicshop/wrappers/socketw/dns_server.py +6 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +71 -2
- atomicshop/wrappers/socketw/ssl_base.py +1 -1
- atomicshop/wrappers/socketw/statistics_csv.py +0 -1
- {atomicshop-2.16.13.dist-info → atomicshop-2.16.15.dist-info}/METADATA +1 -1
- {atomicshop-2.16.13.dist-info → atomicshop-2.16.15.dist-info}/RECORD +19 -18
- {atomicshop-2.16.13.dist-info → atomicshop-2.16.15.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.13.dist-info → atomicshop-2.16.15.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.13.dist-info → atomicshop-2.16.15.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/certificates.py
CHANGED
|
@@ -5,8 +5,10 @@ https://oidref.com/1.3.6.1.5.5.7.3.1
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import ssl
|
|
8
|
+
from typing import Literal
|
|
8
9
|
|
|
9
10
|
from .wrappers import cryptographyw
|
|
11
|
+
from .wrappers.pywin32w import cert_store
|
|
10
12
|
from .print_api import print_api
|
|
11
13
|
|
|
12
14
|
|
|
@@ -16,72 +18,165 @@ from .print_api import print_api
|
|
|
16
18
|
SECONDS_NOT_AFTER_3_YEARS = 3 * 365 * 24 * 60 * 60
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
def
|
|
21
|
+
def get_pem_certificate_from_string(certificate: str) -> str:
|
|
20
22
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
:param certificate:
|
|
24
|
-
:
|
|
25
|
-
The problem that the issuer common name is not unique, so it can be installed multiple times.
|
|
26
|
-
:param thumbprint_only: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
27
|
-
The problem that searching by the thumbprint will not tell you if there are multiple certificates with the same
|
|
28
|
-
issuer name.
|
|
29
|
-
:return: bool, True if certificate is installed, False if not.
|
|
23
|
+
Some PEM certificates can contain a private key. This function will return only the certificate part.
|
|
24
|
+
|
|
25
|
+
:param certificate: string, PEM certificate.
|
|
26
|
+
:return: string, certificate part.
|
|
30
27
|
"""
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
certificate_lines = certificate.split('\n')
|
|
30
|
+
certificate_part = ''
|
|
31
|
+
start = False
|
|
32
|
+
for line in certificate_lines:
|
|
33
|
+
if 'BEGIN CERTIFICATE' in line:
|
|
34
|
+
start = True
|
|
35
|
+
if start:
|
|
36
|
+
certificate_part += line + '\n'
|
|
37
|
+
if 'END CERTIFICATE' in line:
|
|
38
|
+
break
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
for cert, encoding, trust in ssl.enum_certificates("ROOT"):
|
|
40
|
-
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
41
|
-
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
42
|
-
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
43
|
-
|
|
44
|
-
if issuer_only:
|
|
45
|
-
if store_issuer_common_name == issuer_common_name:
|
|
46
|
-
return True, certificate
|
|
47
|
-
elif thumbprint_only:
|
|
48
|
-
if store_thumbprint == thumbprint:
|
|
49
|
-
return True, certificate
|
|
50
|
-
elif not issuer_only and not thumbprint_only:
|
|
51
|
-
if store_thumbprint == thumbprint and store_issuer_common_name == issuer_common_name:
|
|
52
|
-
return True, certificate
|
|
40
|
+
return certificate_part
|
|
53
41
|
|
|
54
42
|
|
|
55
|
-
def
|
|
43
|
+
def write_crt_certificate_file_in_pem_format_from_pem_file(
|
|
44
|
+
pem_file_path: str,
|
|
45
|
+
crt_file_path: str
|
|
46
|
+
):
|
|
56
47
|
"""
|
|
57
|
-
The function will
|
|
48
|
+
The function will read the PEM certificate file and write it to the CRT file in PEM format.
|
|
49
|
+
The function is used to convert the PEM certificate file to the CRT file.
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
Basically the point here is that the CRT file is the same as the PEM file, but the extension is different,
|
|
52
|
+
and it doesn't support integrated private key.
|
|
61
53
|
|
|
62
|
-
:
|
|
54
|
+
:param pem_file_path: string, path to the PEM certificate file.
|
|
55
|
+
:param crt_file_path: string, path to the CRT certificate file.
|
|
63
56
|
"""
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
with open(pem_file_path, 'r') as f:
|
|
59
|
+
certificate_string = f.read()
|
|
60
|
+
|
|
61
|
+
certificate_pem = get_pem_certificate_from_string(certificate_string)
|
|
62
|
+
|
|
63
|
+
with open(crt_file_path, 'w') as f:
|
|
64
|
+
f.write(certificate_pem)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def is_certificate_in_store(
|
|
68
|
+
certificate: any = None,
|
|
69
|
+
by_cert_issuer: bool = True,
|
|
70
|
+
by_cert_thumbprint: bool = True,
|
|
71
|
+
issuer_name: str = None,
|
|
72
|
+
store_location: str = "ROOT"
|
|
73
|
+
) -> tuple[bool, list]:
|
|
74
|
+
"""
|
|
75
|
+
The function will check if the CA certificate is installed in the Windows certificate Trusted Root store.
|
|
76
|
+
NO ADMIN RIGHTS NEEDED.
|
|
77
|
+
|
|
78
|
+
:param certificate: x509 object, certificate to check. You can search by certificate or by issuer name.
|
|
79
|
+
Supported types:
|
|
80
|
+
string that is path to file will be imported as bytes object abd converted to x509.Certificate
|
|
81
|
+
After check if it's PEM or DER format.
|
|
82
|
+
string that is PEM certificate will be converted to bytes, then x509.Certificate
|
|
83
|
+
bytes of PEM or DER will be converted to x509.Certificate.
|
|
84
|
+
x509.Certificate will be returned as is.
|
|
85
|
+
:param by_cert_issuer: bool, if True, will check only by the certificate issuer common name is installed in the store.
|
|
86
|
+
The problem if the search will be by issuer alone, that the issuer common name is not unique,
|
|
87
|
+
so it can be installed multiple times.
|
|
88
|
+
:param by_cert_thumbprint: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
89
|
+
The problem that searching by the thumbprint alone will not tell you if there are multiple
|
|
90
|
+
certificates with the same issuer name.
|
|
91
|
+
:param issuer_name: string, issuer name to search for. You can search by certificate or by issuer name.
|
|
92
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
93
|
+
:return: tuple(bool - True if certificate is installed and False if not, list of certificates found)
|
|
94
|
+
"""
|
|
67
95
|
|
|
68
|
-
|
|
96
|
+
if not by_cert_issuer and not by_cert_thumbprint:
|
|
97
|
+
raise ValueError('At least one of the parameters "by_issuer" or "by_thumbprint" must be True.')
|
|
98
|
+
|
|
99
|
+
if not certificate and not issuer_name:
|
|
100
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
101
|
+
elif certificate and issuer_name:
|
|
102
|
+
raise ValueError('Only one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
103
|
+
|
|
104
|
+
if certificate:
|
|
105
|
+
# Make sure the certificate is x509.Certificate object.
|
|
106
|
+
certificate_x509 = cryptographyw.convert_object_to_x509(certificate)
|
|
107
|
+
# Get the certificate thumbprint.
|
|
108
|
+
provided_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(certificate_x509)
|
|
109
|
+
provided_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(certificate_x509)
|
|
110
|
+
elif issuer_name:
|
|
111
|
+
provided_thumbprint = None
|
|
112
|
+
provided_issuer_common_name = issuer_name
|
|
113
|
+
else:
|
|
114
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
69
115
|
|
|
70
|
-
|
|
116
|
+
# Iterate over all certificates in the store specifically in the ROOT.
|
|
117
|
+
# for store in ["CA", "ROOT", "MY"]:
|
|
118
|
+
result_found_list: list = []
|
|
119
|
+
found: bool = False
|
|
120
|
+
for cert, encoding, trust in ssl.enum_certificates(store_location):
|
|
71
121
|
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
72
122
|
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
123
|
+
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
73
124
|
|
|
74
|
-
if
|
|
75
|
-
|
|
125
|
+
if certificate:
|
|
126
|
+
if by_cert_issuer and not by_cert_thumbprint:
|
|
127
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
128
|
+
result_found_list.append(store_certificate)
|
|
129
|
+
found = True
|
|
130
|
+
elif by_cert_thumbprint and not by_cert_issuer:
|
|
131
|
+
if store_thumbprint == provided_thumbprint:
|
|
132
|
+
result_found_list.append(store_certificate)
|
|
133
|
+
found = True
|
|
134
|
+
elif by_cert_issuer and by_cert_thumbprint:
|
|
135
|
+
if store_thumbprint == provided_thumbprint and store_issuer_common_name == provided_issuer_common_name:
|
|
136
|
+
result_found_list.append(store_certificate)
|
|
137
|
+
found = True
|
|
138
|
+
elif issuer_name:
|
|
139
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
140
|
+
result_found_list.append(store_certificate)
|
|
141
|
+
found = True
|
|
142
|
+
|
|
143
|
+
return found, result_found_list
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def delete_certificate_by_issuer_name(
|
|
147
|
+
issuer_name: str,
|
|
148
|
+
store_location: Literal[
|
|
149
|
+
"ROOT",
|
|
150
|
+
"CA",
|
|
151
|
+
"MY"] = "ROOT",
|
|
152
|
+
print_kwargs: dict = None
|
|
153
|
+
):
|
|
154
|
+
"""
|
|
155
|
+
NEED ADMIN RIGHTS.
|
|
156
|
+
The function will remove all certificates with the specified issuer name.
|
|
157
|
+
There can be several certificates with this name.
|
|
76
158
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
159
|
+
:param issuer_name: string, issuer name to search for.
|
|
160
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
161
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
cert_store.delete_certificate_by_issuer_name(issuer_name, store_location, print_kwargs)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def install_certificate_file(
|
|
168
|
+
file_path: str,
|
|
169
|
+
store_location: Literal[
|
|
170
|
+
"ROOT", "CA", "MY"] = "ROOT",
|
|
171
|
+
print_kwargs: dict = None
|
|
172
|
+
):
|
|
173
|
+
"""
|
|
174
|
+
The function will install the certificate from the file to the specified store location.
|
|
175
|
+
NEED ADMIN RIGHTS.
|
|
176
|
+
|
|
177
|
+
:param file_path: string, full file path to the certificate file.
|
|
178
|
+
:param store_location: string, store location to install the certificate. Default is "ROOT".
|
|
179
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
180
|
+
"""
|
|
86
181
|
|
|
87
|
-
|
|
182
|
+
cert_store.install_certificate_file(file_path, store_location, print_kwargs)
|
atomicshop/mitm/config_static.py
CHANGED
|
@@ -4,7 +4,10 @@ from dataclasses import dataclass
|
|
|
4
4
|
from . import import_config
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
SCRIPT_VERSION: str = '1.7.
|
|
7
|
+
SCRIPT_VERSION: str = '1.7.6'
|
|
8
|
+
"""
|
|
9
|
+
added ca cert check and installation
|
|
10
|
+
"""
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
# CONFIG = None
|
|
@@ -20,6 +23,8 @@ LIST_OF_BOOLEANS: list = [
|
|
|
20
23
|
('tcp', 'engines_usage'),
|
|
21
24
|
('tcp', 'server_response_mode'),
|
|
22
25
|
('logrec', 'enable_request_response_recordings_in_logs'),
|
|
26
|
+
('certificates', 'install_ca_certificate_to_root_store'),
|
|
27
|
+
('certificates', 'uninstall_unused_ca_certificates_with_mitm_ca_name'),
|
|
23
28
|
('certificates', 'default_server_certificate_usage'),
|
|
24
29
|
('certificates', 'sni_add_new_domains_to_default_server_certificate'),
|
|
25
30
|
('certificates', 'custom_server_certificate_usage'),
|
|
@@ -52,8 +57,11 @@ class MainConfig:
|
|
|
52
57
|
# Certificates.
|
|
53
58
|
default_server_certificate_name: str = 'default'
|
|
54
59
|
ca_certificate_name: str = 'ElaborateCA'
|
|
60
|
+
ca_certificate_pem_filename: str = f'{ca_certificate_name}.pem'
|
|
61
|
+
ca_certificate_crt_filename: str = f'{ca_certificate_name}_for_manual_installation_not_used_by_script.crt'
|
|
55
62
|
# CA Certificate name and file name without extension.
|
|
56
63
|
ca_certificate_filepath: str = None
|
|
64
|
+
ca_certificate_crt_filepath: str = None
|
|
57
65
|
# Default server certificate file name and path.
|
|
58
66
|
default_server_certificate_filename = f'{default_server_certificate_name}.pem'
|
|
59
67
|
default_server_certificate_filepath: str = None
|
|
@@ -62,7 +70,8 @@ class MainConfig:
|
|
|
62
70
|
def update(cls):
|
|
63
71
|
# This runs after the dataclass is initialized
|
|
64
72
|
cls.ENGINES_DIRECTORY_PATH = cls.SCRIPT_DIRECTORY + os.sep + cls.ENGINES_DIRECTORY_NAME
|
|
65
|
-
cls.ca_certificate_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.
|
|
73
|
+
cls.ca_certificate_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.ca_certificate_pem_filename}'
|
|
74
|
+
cls.ca_certificate_crt_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.ca_certificate_crt_filename}'
|
|
66
75
|
cls.default_server_certificate_filepath = \
|
|
67
76
|
f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.default_server_certificate_filename}'
|
|
68
77
|
|
|
@@ -105,12 +114,16 @@ class LogRec:
|
|
|
105
114
|
logs_path: str
|
|
106
115
|
recordings_path: str
|
|
107
116
|
enable_request_response_recordings_in_logs: bool
|
|
117
|
+
store_logs_for_x_days: int
|
|
108
118
|
|
|
109
119
|
recordings_directory_name: str = 'recs'
|
|
110
120
|
|
|
111
121
|
|
|
112
122
|
@dataclass
|
|
113
123
|
class Certificates:
|
|
124
|
+
install_ca_certificate_to_root_store: bool
|
|
125
|
+
uninstall_unused_ca_certificates_with_mitm_ca_name: bool
|
|
126
|
+
|
|
114
127
|
default_server_certificate_usage: bool
|
|
115
128
|
sni_add_new_domains_to_default_server_certificate: bool
|
|
116
129
|
|
atomicshop/mitm/import_config.py
CHANGED
|
@@ -117,6 +117,14 @@ def check_configurations() -> int:
|
|
|
117
117
|
print_api(message, color='red')
|
|
118
118
|
return 1
|
|
119
119
|
|
|
120
|
+
# This is checked directly in the SocketWrapper.
|
|
121
|
+
# if (config_static.Certificates.install_ca_certificate_to_root_store and not is_admin) or \
|
|
122
|
+
# (config_static.Certificates.uninstall_unused_ca_certificates_with_mitm_ca_name and not is_admin):
|
|
123
|
+
# message: str = \
|
|
124
|
+
# "Need to run the script with administrative rights to install or uninstall CA certificate.\nExiting..."
|
|
125
|
+
# print_api(message, color='red')
|
|
126
|
+
# return 1
|
|
127
|
+
|
|
120
128
|
return 0
|
|
121
129
|
|
|
122
130
|
|
|
@@ -9,6 +9,8 @@ from ..wrappers.loggingw import loggingw
|
|
|
9
9
|
from .engines.__reference_general import parser___reference_general, responder___reference_general, \
|
|
10
10
|
recorder___reference_general
|
|
11
11
|
|
|
12
|
+
from . import config_static
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
class ModuleCategory:
|
|
14
16
|
def __init__(self, script_directory: str):
|
|
@@ -89,7 +91,8 @@ class ModuleCategory:
|
|
|
89
91
|
add_stream=True,
|
|
90
92
|
add_timedfile=True,
|
|
91
93
|
formatter_streamhandler='DEFAULT',
|
|
92
|
-
formatter_filehandler='DEFAULT'
|
|
94
|
+
formatter_filehandler='DEFAULT',
|
|
95
|
+
backupCount=config_static.LogRec.store_logs_for_x_days
|
|
93
96
|
)
|
|
94
97
|
|
|
95
98
|
|
atomicshop/mitm/mitm_main.py
CHANGED
|
@@ -65,7 +65,8 @@ def mitm_server_main(config_file_path: str):
|
|
|
65
65
|
add_stream=True,
|
|
66
66
|
add_timedfile=True,
|
|
67
67
|
formatter_streamhandler='DEFAULT',
|
|
68
|
-
formatter_filehandler='DEFAULT'
|
|
68
|
+
formatter_filehandler='DEFAULT',
|
|
69
|
+
backupCount=config_static.LogRec.store_logs_for_x_days
|
|
69
70
|
)
|
|
70
71
|
|
|
71
72
|
# Writing first log.
|
|
@@ -208,7 +209,8 @@ def mitm_server_main(config_file_path: str):
|
|
|
208
209
|
add_stream=True,
|
|
209
210
|
add_timedfile=True,
|
|
210
211
|
formatter_streamhandler='DEFAULT',
|
|
211
|
-
formatter_filehandler='DEFAULT'
|
|
212
|
+
formatter_filehandler='DEFAULT',
|
|
213
|
+
backupCount=config_static.LogRec.store_logs_for_x_days
|
|
212
214
|
)
|
|
213
215
|
system_logger.info(f"Loaded network logger: {network_logger}")
|
|
214
216
|
|
|
@@ -227,12 +229,13 @@ def mitm_server_main(config_file_path: str):
|
|
|
227
229
|
dns_server_instance = dns_server.DnsServer(
|
|
228
230
|
listening_interface=config_static.DNSServer.listening_interface,
|
|
229
231
|
listening_port=config_static.DNSServer.listening_port,
|
|
232
|
+
log_directory_path=config_static.LogRec.logs_path,
|
|
233
|
+
backupCount_log_files_x_days=config_static.LogRec.store_logs_for_x_days,
|
|
230
234
|
forwarding_dns_service_ipv4=config_static.DNSServer.forwarding_dns_service_ipv4,
|
|
231
235
|
tcp_target_server_ipv4=config_static.DNSServer.target_tcp_server_ipv4,
|
|
232
236
|
# Passing the engine domain list to DNS server to work with.
|
|
233
237
|
# 'list' function re-initializes the current list, or else it will be the same instance object.
|
|
234
238
|
tcp_resolve_domain_list=list(config_static.Certificates.domains_all_times),
|
|
235
|
-
log_directory_path=config_static.LogRec.logs_path,
|
|
236
239
|
offline_mode=config_static.DNSServer.offline_mode,
|
|
237
240
|
resolve_to_tcp_server_only_tcp_resolve_domains=(
|
|
238
241
|
config_static.DNSServer.resolve_to_tcp_server_only_engine_domains),
|
|
@@ -260,6 +263,10 @@ def mitm_server_main(config_file_path: str):
|
|
|
260
263
|
listening_port_list=config_static.TCPServer.listening_port_list,
|
|
261
264
|
ca_certificate_name=config_static.MainConfig.ca_certificate_name,
|
|
262
265
|
ca_certificate_filepath=config_static.MainConfig.ca_certificate_filepath,
|
|
266
|
+
ca_certificate_crt_filepath=config_static.MainConfig.ca_certificate_crt_filepath,
|
|
267
|
+
install_ca_certificate_to_root_store=config_static.Certificates.install_ca_certificate_to_root_store,
|
|
268
|
+
uninstall_unused_ca_certificates_with_ca_certificate_name=(
|
|
269
|
+
config_static.Certificates.uninstall_unused_ca_certificates_with_mitm_ca_name),
|
|
263
270
|
default_server_certificate_usage=config_static.Certificates.default_server_certificate_usage,
|
|
264
271
|
default_server_certificate_name=config_static.MainConfig.default_server_certificate_name,
|
|
265
272
|
default_certificate_domain_list=config_static.Certificates.domains_all_times,
|
|
@@ -313,11 +320,10 @@ def mitm_server_main(config_file_path: str):
|
|
|
313
320
|
dns_gateway_server_list = [base.DEFAULT_IPV4]
|
|
314
321
|
set_dns_gateway = True
|
|
315
322
|
|
|
323
|
+
# Get current network interface state.
|
|
324
|
+
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
325
|
+
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
316
326
|
if set_dns_gateway:
|
|
317
|
-
# Get current network interface state.
|
|
318
|
-
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
319
|
-
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
320
|
-
|
|
321
327
|
# Set the DNS gateway to the specified one only if the DNS gateway is dynamic or it is static but different
|
|
322
328
|
# from the one specified in the configuration file.
|
|
323
329
|
if (NETWORK_INTERFACE_IS_DYNAMIC or (not NETWORK_INTERFACE_IS_DYNAMIC and
|
|
@@ -36,7 +36,9 @@ def convert_object_to_x509(certificate):
|
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
38
|
# Check if 'certificate' is a string and a path.
|
|
39
|
-
if isinstance(certificate, str)
|
|
39
|
+
if isinstance(certificate, str):
|
|
40
|
+
if not os.path.isfile(certificate):
|
|
41
|
+
raise FileNotFoundError(f'File not found: {certificate}')
|
|
40
42
|
# Import the certificate from the path.
|
|
41
43
|
certificate = file_io.read_file(certificate, file_mode='rb')
|
|
42
44
|
|
|
@@ -124,6 +124,7 @@ def _wrap_do_rollover(handler, header):
|
|
|
124
124
|
handler.doRollover = new_do_rollover
|
|
125
125
|
|
|
126
126
|
|
|
127
|
+
# noinspection PyPep8Naming
|
|
127
128
|
def add_timedfilehandler_with_queuehandler(
|
|
128
129
|
logger: logging.Logger,
|
|
129
130
|
file_path: str,
|
|
@@ -144,6 +145,7 @@ def add_timedfilehandler_with_queuehandler(
|
|
|
144
145
|
when: str = 'midnight',
|
|
145
146
|
interval: int = 1,
|
|
146
147
|
delay: bool = True,
|
|
148
|
+
backupCount: int = 0,
|
|
147
149
|
encoding=None,
|
|
148
150
|
header: str = None
|
|
149
151
|
):
|
|
@@ -164,15 +166,16 @@ def add_timedfilehandler_with_queuehandler(
|
|
|
164
166
|
filesystem.create_directory(os.path.dirname(file_path))
|
|
165
167
|
|
|
166
168
|
file_handler = get_timed_rotating_file_handler(
|
|
167
|
-
file_path, when=when, interval=interval, delay=delay, encoding=encoding)
|
|
169
|
+
file_path, when=when, interval=interval, delay=delay, backupCount=backupCount, encoding=encoding)
|
|
168
170
|
|
|
169
171
|
loggers.set_logging_level(file_handler, logging_level)
|
|
170
172
|
|
|
171
173
|
formatter = _process_formatter_attribute(formatter, file_type=file_type)
|
|
172
174
|
|
|
173
175
|
# If formatter was passed to the function we'll add it to handler.
|
|
176
|
+
# noinspection GrazieInspection
|
|
174
177
|
if formatter:
|
|
175
|
-
# Convert string to Formatter object. Moved to newer styling of python 3: style='{'
|
|
178
|
+
# Convert string to Formatter object. Moved to newer styling of python 3: style='{'.
|
|
176
179
|
logging_formatter = formatters.get_logging_formatter_from_string(
|
|
177
180
|
formatter=formatter, use_nanoseconds=formatter_use_nanoseconds)
|
|
178
181
|
# Setting the formatter in file handler.
|
|
@@ -240,8 +243,14 @@ def get_stream_handler() -> logging.StreamHandler:
|
|
|
240
243
|
return logging.StreamHandler()
|
|
241
244
|
|
|
242
245
|
|
|
246
|
+
# noinspection PyPep8Naming
|
|
243
247
|
def get_timed_rotating_file_handler(
|
|
244
|
-
log_file_path: str,
|
|
248
|
+
log_file_path: str,
|
|
249
|
+
when: str = "midnight",
|
|
250
|
+
interval: int = 1,
|
|
251
|
+
backupCount: int = 0,
|
|
252
|
+
delay: bool = False,
|
|
253
|
+
encoding=None
|
|
245
254
|
) -> TimedRotatingFileHandler:
|
|
246
255
|
"""
|
|
247
256
|
Function to get a TimedRotatingFileHandler.
|
|
@@ -255,13 +264,16 @@ def get_timed_rotating_file_handler(
|
|
|
255
264
|
"D" - Days
|
|
256
265
|
"midnight" - Roll over at midnight
|
|
257
266
|
:param interval: Interval to rotate the log file.
|
|
267
|
+
:param backupCount: int, Number of backup files to keep. Default is 0.
|
|
268
|
+
If backupCount is > 0, when rollover is done, no more than backupCount files are kept, the oldest are deleted.
|
|
269
|
+
If backupCount is == 0, all the backup files will be kept.
|
|
258
270
|
:param delay: bool, If set to True, the log file will be created only if there's something to write.
|
|
259
271
|
:param encoding: Encoding to use for the log file. Same as for the TimeRotatingFileHandler, which uses Default None.
|
|
260
272
|
:return: TimedRotatingFileHandler.
|
|
261
273
|
"""
|
|
262
274
|
|
|
263
275
|
return TimedRotatingFileHandler(
|
|
264
|
-
filename=log_file_path, when=when, interval=interval, delay=delay, encoding=encoding)
|
|
276
|
+
filename=log_file_path, when=when, interval=interval, backupCount=backupCount, delay=delay, encoding=encoding)
|
|
265
277
|
|
|
266
278
|
|
|
267
279
|
def start_queue_listener_for_file_handler(
|
|
@@ -32,6 +32,7 @@ def create_logger(
|
|
|
32
32
|
filehandler_rotation_use_default_namer_function: bool = True,
|
|
33
33
|
when: str = "midnight",
|
|
34
34
|
interval: int = 1,
|
|
35
|
+
backupCount: int = 0,
|
|
35
36
|
delay: bool = False,
|
|
36
37
|
encoding=None,
|
|
37
38
|
header: str = None
|
|
@@ -95,6 +96,9 @@ def create_logger(
|
|
|
95
96
|
:param interval: int, Interval to rotate the log file. Default is 1.
|
|
96
97
|
If 'when="midnight"' and 'interval=1', then the log file will be rotated every midnight.
|
|
97
98
|
If 'when="midnight"' and 'interval=2', then the log file will be rotated every 2nd midnights.
|
|
99
|
+
:param backupCount: int, Number of backup files to keep. Default is 0.
|
|
100
|
+
If backupCount is > 0, when rollover is done, no more than backupCount files are kept, the oldest are deleted.
|
|
101
|
+
If backupCount is == 0, all the backup files will be kept.
|
|
98
102
|
:param delay: bool, If set to True, the log file will be created only if there's something to write.
|
|
99
103
|
:param encoding: string, Encoding to use for the log file. Default is None.
|
|
100
104
|
:param header: string, Header to write to the log file.
|
|
@@ -181,7 +185,7 @@ def create_logger(
|
|
|
181
185
|
rotation_date_format=filehandler_rotation_date_format,
|
|
182
186
|
rotation_callback_namer_function=filehandler_rotation_callback_namer_function,
|
|
183
187
|
rotation_use_default_callback_namer_function=filehandler_rotation_use_default_namer_function,
|
|
184
|
-
when=when, interval=interval, delay=delay, encoding=encoding, header=header)
|
|
188
|
+
when=when, interval=interval, delay=delay, backupCount=backupCount, encoding=encoding, header=header)
|
|
185
189
|
|
|
186
190
|
return logger
|
|
187
191
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
import win32crypt as wcrypt
|
|
3
|
+
|
|
4
|
+
from ...print_api import print_api
|
|
5
|
+
from ... import certificates
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# lpszStoreProvider
|
|
9
|
+
CERT_STORE_PROV_SYSTEM = 0x0000000A
|
|
10
|
+
# dwFlags
|
|
11
|
+
CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
|
|
12
|
+
CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
|
|
13
|
+
CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001
|
|
14
|
+
CRYPT_STRING_BASE64HEADER = 0x00000000
|
|
15
|
+
X509_ASN_ENCODING = 0x00000001
|
|
16
|
+
CERT_STORE_ADD_REPLACE_EXISTING = 3
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
STORE_LOCATION_TO_CERT_SYSTEM_STORE: dict = {
|
|
20
|
+
"ROOT": CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
21
|
+
"CA": CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
22
|
+
"MY": CERT_SYSTEM_STORE_CURRENT_USER
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def delete_certificate_by_issuer_name(
|
|
27
|
+
issuer_name: str,
|
|
28
|
+
store_location: Literal[
|
|
29
|
+
"ROOT",
|
|
30
|
+
"CA",
|
|
31
|
+
"MY"] = "ROOT",
|
|
32
|
+
print_kwargs: dict = None
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
NEED ADMIN RIGHTS.
|
|
36
|
+
The function will remove all certificates with the specified issuer name.
|
|
37
|
+
There can be several certificates with this name.
|
|
38
|
+
|
|
39
|
+
:param issuer_name: string, issuer name to search for.
|
|
40
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
41
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
store = wcrypt.CertOpenStore(
|
|
45
|
+
CERT_STORE_PROV_SYSTEM, 0, None, STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location], store_location)
|
|
46
|
+
|
|
47
|
+
for cert in store.CertEnumCertificatesInStore():
|
|
48
|
+
# Certificate properties.
|
|
49
|
+
# cert.CertEnumCertificateContextProperties()
|
|
50
|
+
subject_string: str = wcrypt.CertNameToStr(cert.Subject)
|
|
51
|
+
if subject_string == issuer_name:
|
|
52
|
+
# Remove the certificate.
|
|
53
|
+
cert.CertDeleteCertificateFromStore()
|
|
54
|
+
print_api(f"Removed the Certificate with issuer: {issuer_name}", **(print_kwargs or {}))
|
|
55
|
+
|
|
56
|
+
# There is an exception about store close.
|
|
57
|
+
# store.CertCloseStore()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def install_certificate_file(
|
|
61
|
+
file_path: str,
|
|
62
|
+
store_location: Literal[
|
|
63
|
+
"ROOT", "CA", "MY"] = "ROOT",
|
|
64
|
+
print_kwargs: dict = None
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
NEED ADMIN RIGHTS.
|
|
68
|
+
The function will install the certificate from the file to the specified store location.
|
|
69
|
+
|
|
70
|
+
:param file_path: string, full file path to the certificate file.
|
|
71
|
+
:param store_location: string, store location to install the certificate. Default is "ROOT".
|
|
72
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
with open(file_path, 'r') as f:
|
|
76
|
+
certificate_string = f.read()
|
|
77
|
+
|
|
78
|
+
certificate_pem = certificates.get_pem_certificate_from_string(certificate_string)
|
|
79
|
+
|
|
80
|
+
certificate_bytes = wcrypt.CryptStringToBinary(certificate_pem, CRYPT_STRING_BASE64HEADER)[0]
|
|
81
|
+
|
|
82
|
+
store = wcrypt.CertOpenStore(
|
|
83
|
+
CERT_STORE_PROV_SYSTEM, 0, None, STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location], store_location)
|
|
84
|
+
|
|
85
|
+
store.CertAddEncodedCertificateToStore(X509_ASN_ENCODING, certificate_bytes, CERT_STORE_ADD_REPLACE_EXISTING)
|
|
86
|
+
store.CertCloseStore(CERT_CLOSE_STORE_FORCE_FLAG)
|
|
87
|
+
|
|
88
|
+
message = f"Certificate installed to the store: [{store_location}] from file: [{file_path}]"
|
|
89
|
+
print_api(message, **(print_kwargs or {}))
|
|
@@ -35,6 +35,7 @@ class DnsServer:
|
|
|
35
35
|
listening_interface: str,
|
|
36
36
|
listening_port: int,
|
|
37
37
|
log_directory_path: str,
|
|
38
|
+
backupCount_log_files_x_days: int = 0,
|
|
38
39
|
forwarding_dns_service_ipv4: str = '8.8.8.8',
|
|
39
40
|
forwarding_dns_service_port: int = 53,
|
|
40
41
|
resolve_to_tcp_server_only_tcp_resolve_domains: bool = False,
|
|
@@ -56,6 +57,9 @@ class DnsServer:
|
|
|
56
57
|
Example: '0.0.0.0'. For all interfaces.
|
|
57
58
|
:param listening_port: int: Port number that the DNS Server will listen on.
|
|
58
59
|
:param log_directory_path: str: Path to the directory where the logs will be saved.
|
|
60
|
+
:param backupCount_log_files_x_days: int: How many days the log files will be kept.
|
|
61
|
+
Default is 0, which means that the log files will be kept indefinitely.
|
|
62
|
+
More than 0 means that the log files will be deleted after the specified days.
|
|
59
63
|
:param forwarding_dns_service_ipv4: str: IPv4 address of the DNS Service that will be used for resolving.
|
|
60
64
|
Example: '8.8.8.8'. For Google DNS Service.
|
|
61
65
|
:param forwarding_dns_service_port: int: Port number of the DNS Service that will be used for resolving.
|
|
@@ -126,7 +130,8 @@ class DnsServer:
|
|
|
126
130
|
logger_name="dns",
|
|
127
131
|
directory_path=self.log_directory_path,
|
|
128
132
|
add_timedfile=True,
|
|
129
|
-
formatter_filehandler='DEFAULT'
|
|
133
|
+
formatter_filehandler='DEFAULT',
|
|
134
|
+
backupCount=backupCount_log_files_x_days
|
|
130
135
|
)
|
|
131
136
|
|
|
132
137
|
self.test_config()
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
import select
|
|
3
3
|
from typing import Literal, Union
|
|
4
|
+
from pathlib import Path
|
|
4
5
|
|
|
5
6
|
from ..psutilw import networks
|
|
7
|
+
from ..certauthw import certauthw
|
|
6
8
|
from ...script_as_string_processor import ScriptAsStringProcessor
|
|
7
|
-
from ... import
|
|
9
|
+
from ...permissions import permissions
|
|
10
|
+
from ... import queues, filesystem, certificates
|
|
8
11
|
from ...basics import booleans
|
|
9
12
|
from ...print_api import print_api
|
|
10
13
|
|
|
@@ -30,6 +33,9 @@ class SocketWrapper:
|
|
|
30
33
|
forwarding_dns_service_ipv4_list___only_for_localhost: list = None,
|
|
31
34
|
ca_certificate_name: str = None,
|
|
32
35
|
ca_certificate_filepath: str = None,
|
|
36
|
+
ca_certificate_crt_filepath: str = None,
|
|
37
|
+
install_ca_certificate_to_root_store: bool = False,
|
|
38
|
+
uninstall_unused_ca_certificates_with_ca_certificate_name: bool = False,
|
|
33
39
|
default_server_certificate_usage: bool = False,
|
|
34
40
|
default_server_certificate_name: str = None,
|
|
35
41
|
default_certificate_domain_list: list = None,
|
|
@@ -68,7 +74,13 @@ class SocketWrapper:
|
|
|
68
74
|
Example: '0.0.0.0'. For all interfaces.
|
|
69
75
|
:param listening_port_list: list, of ports that will be listened on.
|
|
70
76
|
:param ca_certificate_name: CA certificate name.
|
|
71
|
-
:param ca_certificate_filepath: CA certificate file path.
|
|
77
|
+
:param ca_certificate_filepath: CA certificate file path with '.pem' extension.
|
|
78
|
+
:param ca_certificate_crt_filepath: CA certificate file path with '.crt' extension.
|
|
79
|
+
This file will be created from the PEM file 'ca_certificate_filepath' for manual installation.
|
|
80
|
+
:param install_ca_certificate_to_root_store: boolean, if True, CA certificate will be installed
|
|
81
|
+
to the root store.
|
|
82
|
+
:param uninstall_unused_ca_certificates_with_ca_certificate_name: boolean, if True, unused CA certificates
|
|
83
|
+
with provided 'ca_certificate_name' will be uninstalled.
|
|
72
84
|
:param default_server_certificate_usage: boolean, if True, default server certificate will be used
|
|
73
85
|
for each incoming socket.
|
|
74
86
|
:param sni_custom_callback_function: callable, custom callback function that will be executed when
|
|
@@ -150,6 +162,10 @@ class SocketWrapper:
|
|
|
150
162
|
self.listening_port_list: list[int] = listening_port_list
|
|
151
163
|
self.ca_certificate_name: str = ca_certificate_name
|
|
152
164
|
self.ca_certificate_filepath: str = ca_certificate_filepath
|
|
165
|
+
self.ca_certificate_crt_filepath: str = ca_certificate_crt_filepath
|
|
166
|
+
self.install_ca_certificate_to_root_store: bool = install_ca_certificate_to_root_store
|
|
167
|
+
self.uninstall_unused_ca_certificates_with_ca_certificate_name: bool = \
|
|
168
|
+
uninstall_unused_ca_certificates_with_ca_certificate_name
|
|
153
169
|
self.default_server_certificate_usage: bool = default_server_certificate_usage
|
|
154
170
|
self.default_server_certificate_name: str = default_server_certificate_name
|
|
155
171
|
self.default_certificate_domain_list: list = default_certificate_domain_list
|
|
@@ -270,6 +286,59 @@ class SocketWrapper:
|
|
|
270
286
|
error_messages.append(f"Port [{port}] is already in use by process: {process_info}")
|
|
271
287
|
raise SocketWrapperPortInUseError("\n".join(error_messages))
|
|
272
288
|
|
|
289
|
+
if not filesystem.is_file_exists(file_path=self.ca_certificate_filepath):
|
|
290
|
+
# Initialize CertAuthWrapper.
|
|
291
|
+
ca_certificate_directory: str = str(Path(self.ca_certificate_filepath).parent)
|
|
292
|
+
certauth_wrapper = certauthw.CertAuthWrapper(
|
|
293
|
+
ca_certificate_name=self.ca_certificate_name,
|
|
294
|
+
ca_certificate_filepath=self.ca_certificate_filepath,
|
|
295
|
+
server_certificate_directory=ca_certificate_directory
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Create CA certificate if it doesn't exist.
|
|
299
|
+
certauth_wrapper.create_use_ca_certificate()
|
|
300
|
+
|
|
301
|
+
certificates.write_crt_certificate_file_in_pem_format_from_pem_file(
|
|
302
|
+
pem_file_path=self.ca_certificate_filepath,
|
|
303
|
+
crt_file_path=self.ca_certificate_crt_filepath)
|
|
304
|
+
|
|
305
|
+
if self.install_ca_certificate_to_root_store:
|
|
306
|
+
if not self.ca_certificate_filepath:
|
|
307
|
+
message = "You set [install_ca_certificate_to_root_store = True],\n" \
|
|
308
|
+
"But you didn't set [ca_certificate_filepath]."
|
|
309
|
+
raise SocketWrapperConfigurationValuesError(message)
|
|
310
|
+
|
|
311
|
+
# Before installation check if there are any unused certificates with the same name.
|
|
312
|
+
if self.uninstall_unused_ca_certificates_with_ca_certificate_name:
|
|
313
|
+
# Check how many certificates with our ca certificate name are installed.
|
|
314
|
+
is_installed_by_name, certificate_list_by_name = certificates.is_certificate_in_store(
|
|
315
|
+
issuer_name=self.ca_certificate_name)
|
|
316
|
+
# If there is more than one certificate with the same name, delete them all.
|
|
317
|
+
if is_installed_by_name and len(certificate_list_by_name) > 1:
|
|
318
|
+
certificates.delete_certificate_by_issuer_name(self.ca_certificate_name)
|
|
319
|
+
# If there is only one certificate with the same name, check if it is the same certificate.
|
|
320
|
+
elif is_installed_by_name and len(certificate_list_by_name) == 1:
|
|
321
|
+
is_installed_by_file, certificate_list_by_file = certificates.is_certificate_in_store(
|
|
322
|
+
certificate=self.ca_certificate_filepath, by_cert_thumbprint=True, by_cert_issuer=True)
|
|
323
|
+
# If the certificate is not the same, delete it.
|
|
324
|
+
if not is_installed_by_file:
|
|
325
|
+
if not permissions.is_admin():
|
|
326
|
+
raise SocketWrapperConfigurationValuesError(
|
|
327
|
+
"You need to run the script with admin rights to uninstall the unused certificates.")
|
|
328
|
+
certificates.delete_certificate_by_issuer_name(
|
|
329
|
+
self.ca_certificate_name, store_location="ROOT", print_kwargs={'logger': self.logger})
|
|
330
|
+
|
|
331
|
+
if self.install_ca_certificate_to_root_store:
|
|
332
|
+
# Install CA certificate to the root store if it is not installed.
|
|
333
|
+
is_installed_by_file, certificate_list_by_file = certificates.is_certificate_in_store(
|
|
334
|
+
certificate=self.ca_certificate_filepath, by_cert_thumbprint=True, by_cert_issuer=True)
|
|
335
|
+
if not is_installed_by_file:
|
|
336
|
+
if not permissions.is_admin():
|
|
337
|
+
raise SocketWrapperConfigurationValuesError(
|
|
338
|
+
"You need to run the script with admin rights to install the CA certificate.")
|
|
339
|
+
certificates.install_certificate_file(
|
|
340
|
+
self.ca_certificate_filepath, store_location="ROOT", print_kwargs={'logger': self.logger})
|
|
341
|
+
|
|
273
342
|
# Creating listening sockets.
|
|
274
343
|
def create_socket_ipv4_tcp(self, ip_address: str, port: int):
|
|
275
344
|
self.sni_execute_extended = True
|
|
@@ -60,7 +60,7 @@ def is_tls(client_socket) -> Optional[Tuple[str, str]]:
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
# Get the tuple of the type and version as strings.
|
|
63
|
-
tls_content_and_version_tuple: tuple
|
|
63
|
+
tls_content_and_version_tuple: tuple = \
|
|
64
64
|
content_type_map.get(content_type), version_map.get((version_major, version_minor))
|
|
65
65
|
|
|
66
66
|
# If both parts of the tuple are not None, return the protocol type.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=UzNeZyRkmLnYywv5edPjB0_p7zEgYfoGzcusp1FpodI,124
|
|
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
|
|
5
5
|
atomicshop/appointment_management.py,sha256=BsYH_PClTGLVazcuNjt30--hpXKYjSmHp1R1iQbM4Hc,7330
|
|
6
|
-
atomicshop/certificates.py,sha256=
|
|
6
|
+
atomicshop/certificates.py,sha256=ssOTD1uN4OaB9TU7mI0Dg_sSGFb6Xxw28A7TtyKmMMY,7637
|
|
7
7
|
atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9tRM-_YXrQ,1038
|
|
8
8
|
atomicshop/config_init.py,sha256=BSxc2FhytQPv06g5z9wbAXuA6oYCAsAJLxu_mTExhwI,2491
|
|
9
9
|
atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
|
|
@@ -122,13 +122,13 @@ atomicshop/file_io/tomls.py,sha256=ol8EvQPf9sryTmZUf1v55BYSUQ6ml7HVVBHpNKbsIlA,9
|
|
|
122
122
|
atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
|
|
123
123
|
atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,2104
|
|
124
124
|
atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
125
|
-
atomicshop/mitm/config_static.py,sha256=
|
|
125
|
+
atomicshop/mitm/config_static.py,sha256=UNvRTb3ZuFVGZpF33fvaIf0xw_VGyml2ExIwqW_uYcg,7777
|
|
126
126
|
atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
|
|
127
127
|
atomicshop/mitm/connection_thread_worker.py,sha256=1MBpRoLpzWJMvxqQKizo6IVQ4XYsbKGsjxianNQLUlE,20051
|
|
128
|
-
atomicshop/mitm/import_config.py,sha256=
|
|
129
|
-
atomicshop/mitm/initialize_engines.py,sha256=
|
|
128
|
+
atomicshop/mitm/import_config.py,sha256=_nu8mgA-M4s6dZ8_QWx3x0aVb75upvsCuX_PIUg4X2w,8345
|
|
129
|
+
atomicshop/mitm/initialize_engines.py,sha256=kBG8TBnyFuwlJ1uKaWDzc5AiZNpwdvouq2pr-PYrdEA,8349
|
|
130
130
|
atomicshop/mitm/message.py,sha256=d_sm3O_aoZf87dDQP44xOMNEG-uZBN1ZecQgMCacbZs,1814
|
|
131
|
-
atomicshop/mitm/mitm_main.py,sha256=
|
|
131
|
+
atomicshop/mitm/mitm_main.py,sha256=CdCv4nYt_jwd23AI14v6lC2H8SZeIZqsXjFhwq61UtM,21285
|
|
132
132
|
atomicshop/mitm/recs_files.py,sha256=btOuYQca4DuBOAKp9OY21HGjeEVOx9r_k-AnZOqs3Dk,3007
|
|
133
133
|
atomicshop/mitm/shared_functions.py,sha256=hplm98tz8pgJ4WHUVI9sf_oVqUM2KJ1Y2pD6EFSb8P0,1879
|
|
134
134
|
atomicshop/mitm/statistic_analyzer.py,sha256=AzL9rQhg0tLJj33gZfxdwWghmbXGLh_HyMBDpzuBmsQ,24709
|
|
@@ -178,7 +178,7 @@ atomicshop/wrappers/_process_wrapper_curl.py,sha256=XkZZXYl7D0Q6UfdWqy-18AvpU0yV
|
|
|
178
178
|
atomicshop/wrappers/_process_wrapper_tar.py,sha256=WUMZFKNrlG4nJP9tWZ51W7BR1j_pIjsjgyAStmWjRGs,655
|
|
179
179
|
atomicshop/wrappers/astw.py,sha256=VkYfkfyc_PJLIOxByT6L7B8uUmKY6-I8XGZl4t_z828,4239
|
|
180
180
|
atomicshop/wrappers/configparserw.py,sha256=JwDTPjZoSrv44YKwIRcjyUnpN-FjgXVfMqMK_tJuSgU,22800
|
|
181
|
-
atomicshop/wrappers/cryptographyw.py,sha256=
|
|
181
|
+
atomicshop/wrappers/cryptographyw.py,sha256=LfzTnwvJE03G6WZryOOf43VKhhnyMakzHpn8DPPCoy4,13252
|
|
182
182
|
atomicshop/wrappers/ffmpegw.py,sha256=wcq0ZnAe0yajBOuTKZCCaKI7CDBjkq7FAgdW5IsKcVE,6031
|
|
183
183
|
atomicshop/wrappers/githubw.py,sha256=AQcFuT5mvDUNT_cI31MwkJ7srdhMtttF8FyXS8vs5cU,12270
|
|
184
184
|
atomicshop/wrappers/msiw.py,sha256=GQLqud72nfex3kvO1bJSruNriCYTYX1_G1gSf1MPkIA,6118
|
|
@@ -247,9 +247,9 @@ atomicshop/wrappers/fibratusw/install.py,sha256=PLVymDe0HuOvU0r2lje8BkQAgtiOWEeR
|
|
|
247
247
|
atomicshop/wrappers/loggingw/consts.py,sha256=JWiUJEydjhwatBxtIJsGTmDUSTLbmIRidtR6qRLMaIY,1608
|
|
248
248
|
atomicshop/wrappers/loggingw/filters.py,sha256=CMs5PAMb68zxJgBcQobaOFDG5kLJBOVYnoBHjDgksO8,2859
|
|
249
249
|
atomicshop/wrappers/loggingw/formatters.py,sha256=7XUJvlB0CK4DCkEp8NTL0S0dkyrZD0UTADgEwkStKOY,5483
|
|
250
|
-
atomicshop/wrappers/loggingw/handlers.py,sha256=
|
|
250
|
+
atomicshop/wrappers/loggingw/handlers.py,sha256=_69ZtmZRUsdgL8Q1rh2X-a0ComDU9gg9v101ngbJcac,17436
|
|
251
251
|
atomicshop/wrappers/loggingw/loggers.py,sha256=DHOOTAtqkwn1xgvLHSkOiBm6yFGNuQy1kvbhG-TDog8,2374
|
|
252
|
-
atomicshop/wrappers/loggingw/loggingw.py,sha256=
|
|
252
|
+
atomicshop/wrappers/loggingw/loggingw.py,sha256=BBQe_2i8otcbe0cZcAKd3tZ2D5XL3SPb_IWTXCepSxw,11595
|
|
253
253
|
atomicshop/wrappers/loggingw/reading.py,sha256=tplnJlQ7RMxWv2s782tWGOo1C7WNemk2SRTZCCgD9J0,16474
|
|
254
254
|
atomicshop/wrappers/mongodbw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
255
255
|
atomicshop/wrappers/mongodbw/infrastructure.py,sha256=tHqtt__yKGtj24CT5AIk0V0k9t1p_PjezFExXRmmmcA,1517
|
|
@@ -278,6 +278,7 @@ atomicshop/wrappers/pycharmw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
278
278
|
atomicshop/wrappers/pycharmw/ubuntu.py,sha256=l2_9SXrw7ApSvFOROGZdPZa5ylZBKofk4sYqf4IugQs,1223
|
|
279
279
|
atomicshop/wrappers/pycharmw/win.py,sha256=jdnTkUqZX_BrMW8AmW-xGtxdV-wmmNr_NMA2jB6JHsQ,2725
|
|
280
280
|
atomicshop/wrappers/pywin32w/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
281
|
+
atomicshop/wrappers/pywin32w/cert_store.py,sha256=bpFm5nH9j6I9eJdLjPnSvo-g4OyJO7Sb5VddzVE9-UM,3156
|
|
281
282
|
atomicshop/wrappers/pywin32w/console.py,sha256=LstHajPLgXp9qQxFNR44QfH10nOnNp3bCJquxaTquns,1175
|
|
282
283
|
atomicshop/wrappers/pywin32w/winshell.py,sha256=i2bKiMldPU7_azsD5xGQDdMwjaM7suKJd3k0Szmcs6c,723
|
|
283
284
|
atomicshop/wrappers/pywin32w/win_event_log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -295,7 +296,7 @@ atomicshop/wrappers/socketw/accepter.py,sha256=hZZKVYlF3LOHQJsSIEKXZUf6QXXWm-Atq
|
|
|
295
296
|
atomicshop/wrappers/socketw/base.py,sha256=evoOIxg5Xff3THJnrVX00D5HobaOpDp6_e_gso7TJmA,2191
|
|
296
297
|
atomicshop/wrappers/socketw/certificator.py,sha256=3CpQKtcW68FSbH6LVSEZTqWBS6Yg_-3K0x4nFkId4UY,12236
|
|
297
298
|
atomicshop/wrappers/socketw/creator.py,sha256=3_OraDkw2DAWZfoSdY3svCGMOIxpjLEEY7NxWd7M5P4,9873
|
|
298
|
-
atomicshop/wrappers/socketw/dns_server.py,sha256=
|
|
299
|
+
atomicshop/wrappers/socketw/dns_server.py,sha256=53S52lkA9RWetNlee-mjt000OJW4Mi7Ktcru0WXrMZE,45504
|
|
299
300
|
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=B-X5SHLSUIWToihH2MKnOB1F4A81_X0DpLLfnYKYbEc,7067
|
|
300
301
|
atomicshop/wrappers/socketw/get_process.py,sha256=_YMVxYhVlzjJpeOR36tphZ5QWeKYwk03Ilw0muCxDbg,5950
|
|
301
302
|
atomicshop/wrappers/socketw/receiver.py,sha256=G3hDTacm7nwwUNHEbKZpxO0c8rHcl0NeKpZy7Xc6zpA,9008
|
|
@@ -303,13 +304,13 @@ atomicshop/wrappers/socketw/sender.py,sha256=d7YQFlCBMFTYtkGxbS-8cm5rh5WWFeBVvrE
|
|
|
303
304
|
atomicshop/wrappers/socketw/sni.py,sha256=fVwyh3h9IqfLMnf4__bMIzcF4c-Kk9mlbDWMRXKN-ow,17155
|
|
304
305
|
atomicshop/wrappers/socketw/socket_client.py,sha256=FNmTt94YvjZP0X4RPb7icO3xD_nBHQ_XynnObdWFiAU,19682
|
|
305
306
|
atomicshop/wrappers/socketw/socket_server_tester.py,sha256=wAwyst8YdVyVfZfERav1A9_OnMJAiVBy-4uY0RpNqkU,6339
|
|
306
|
-
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=
|
|
307
|
-
atomicshop/wrappers/socketw/ssl_base.py,sha256=
|
|
308
|
-
atomicshop/wrappers/socketw/statistics_csv.py,sha256=
|
|
307
|
+
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=DiDzg9OlgahxpqAsnOkCKHNcE-H-YAY3ndVMeU-oCjw,33363
|
|
308
|
+
atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0LxIwBA4iVvU,2275
|
|
309
|
+
atomicshop/wrappers/socketw/statistics_csv.py,sha256=V_m1D0KpizQox3IEWp2AUcncwWy5kG25hbFrc-mBSJE,3029
|
|
309
310
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
310
311
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
|
|
311
|
-
atomicshop-2.16.
|
|
312
|
-
atomicshop-2.16.
|
|
313
|
-
atomicshop-2.16.
|
|
314
|
-
atomicshop-2.16.
|
|
315
|
-
atomicshop-2.16.
|
|
312
|
+
atomicshop-2.16.15.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
313
|
+
atomicshop-2.16.15.dist-info/METADATA,sha256=i5Xgtqpn2TfPbeSQ_L3nAryipoFyy2Z6whmJsDFQyD4,10503
|
|
314
|
+
atomicshop-2.16.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
315
|
+
atomicshop-2.16.15.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
316
|
+
atomicshop-2.16.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|