atomicshop 2.15.13__py3-none-any.whl → 2.16.1__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/a_installs/ubuntu/pycharm.py +7 -0
- atomicshop/a_installs/win/pycharm.py +2 -2
- atomicshop/{addons/mains/install_wsl_ubuntu_lts_admin.py → a_installs/win/wsl_ubuntu_lts.py} +1 -0
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/basics/booleans.py +14 -5
- atomicshop/dns.py +104 -0
- atomicshop/file_io/docxs.py +8 -0
- atomicshop/file_io/tomls.py +133 -0
- atomicshop/filesystem.py +5 -4
- atomicshop/get_process_list.py +3 -3
- atomicshop/mitm/config_static.py +195 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +54 -90
- atomicshop/mitm/import_config.py +148 -139
- atomicshop/mitm/initialize_engines.py +7 -2
- atomicshop/mitm/initialize_mitm_server.py +162 -107
- atomicshop/mitm/shared_functions.py +0 -1
- atomicshop/mitm/statistic_analyzer.py +13 -1
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +54 -14
- atomicshop/permissions/__init__.py +0 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/{permissions.py → permissions/ubuntu_permissions.py} +4 -54
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/script_as_string_processor.py +5 -1
- atomicshop/wrappers/cryptographyw.py +3 -3
- atomicshop/wrappers/dockerw/install_docker.py +6 -5
- atomicshop/wrappers/elasticsearchw/install_elastic.py +2 -1
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -4
- atomicshop/wrappers/mongodbw/install_mongodb.py +2 -1
- atomicshop/wrappers/msiw.py +2 -3
- atomicshop/wrappers/psutilw/networks.py +25 -1
- atomicshop/wrappers/pycharmw/__init__.py +0 -0
- atomicshop/wrappers/pycharmw/ubuntu.py +38 -0
- atomicshop/wrappers/{pycharmw.py → pycharmw/win.py} +2 -2
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/helpers.py +127 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +167 -0
- atomicshop/wrappers/socketw/accepter.py +8 -8
- atomicshop/wrappers/socketw/base.py +13 -0
- atomicshop/wrappers/socketw/certificator.py +202 -149
- atomicshop/wrappers/socketw/creator.py +15 -35
- atomicshop/wrappers/socketw/dns_server.py +155 -102
- atomicshop/wrappers/socketw/exception_wrapper.py +8 -27
- atomicshop/wrappers/socketw/get_process.py +115 -95
- atomicshop/wrappers/socketw/sni.py +298 -164
- atomicshop/wrappers/socketw/socket_client.py +5 -12
- atomicshop/wrappers/socketw/socket_server_tester.py +1 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +328 -72
- atomicshop/wrappers/socketw/statistics_csv.py +94 -16
- atomicshop/wrappers/ubuntu_terminal.py +6 -6
- atomicshop/wrappers/wslw.py +1 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/METADATA +1 -1
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/RECORD +63 -54
- atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc +0 -0
- atomicshop/addons/mains/__pycache__/msi_unpacker.cpython-312.pyc +0 -0
- atomicshop/mitm/config_editor.py +0 -37
- /atomicshop/{addons/mains/install_docker_rootless_ubuntu.py → a_installs/ubuntu/docker_rootless.py} +0 -0
- /atomicshop/{addons/mains/install_docker_ubuntu_main_sudo.py → a_installs/ubuntu/docker_sudo.py} +0 -0
- /atomicshop/{addons/mains/install_elastic_search_and_kibana_ubuntu.py → a_installs/ubuntu/elastic_search_and_kibana.py} +0 -0
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
import win32com.client
|
|
4
|
+
|
|
5
|
+
from . import helpers
|
|
6
|
+
from ...psutilw import networks
|
|
7
|
+
from ....print_api import print_api
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NetworkAdapterNotFoundError(Exception):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def list_network_adapters() -> list:
|
|
15
|
+
# Initialize the WMI client
|
|
16
|
+
wmi = win32com.client.Dispatch('WbemScripting.SWbemLocator')
|
|
17
|
+
wmi_service = wmi.ConnectServer('.', 'root\\cimv2')
|
|
18
|
+
|
|
19
|
+
# Query all network adapters
|
|
20
|
+
adapters = wmi_service.ExecQuery("SELECT * FROM Win32_NetworkAdapter")
|
|
21
|
+
|
|
22
|
+
# Print adapter descriptions
|
|
23
|
+
# for adapter in adapters:
|
|
24
|
+
# print(f"Description: {adapter.Description}, IPEnabled: {adapter.IPEnabled}")
|
|
25
|
+
return list(adapters)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_default_network_adapter():
|
|
29
|
+
"""
|
|
30
|
+
Get the default network adapter.
|
|
31
|
+
:return:
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
default_connection_name_dict: dict = networks.get_default_connection_name()
|
|
35
|
+
# Get the first key from the dictionary.
|
|
36
|
+
default_connection_name: str = list(default_connection_name_dict.keys())[0]
|
|
37
|
+
adapters = list_network_adapters()
|
|
38
|
+
|
|
39
|
+
for adapter in adapters:
|
|
40
|
+
if default_connection_name == adapter.NetConnectionID:
|
|
41
|
+
return adapter
|
|
42
|
+
|
|
43
|
+
raise NetworkAdapterNotFoundError("Default network adapter not found.")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_wmi_network_configuration(
|
|
47
|
+
use_default_interface: bool = False,
|
|
48
|
+
connection_name: str = None,
|
|
49
|
+
mac_address: str = None
|
|
50
|
+
) -> tuple:
|
|
51
|
+
"""
|
|
52
|
+
Get the WMI network configuration for a network adapter.
|
|
53
|
+
:param use_default_interface: bool, if True, the default network interface will be used.
|
|
54
|
+
This is the adapter that your internet is being used from.
|
|
55
|
+
:param connection_name: string, adapter name as shown in the network settings.
|
|
56
|
+
:param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
|
|
57
|
+
:return: tuple(Win32_NetworkAdapterConfiguration, Win32_NetworkAdapter)
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
if use_default_interface and connection_name:
|
|
61
|
+
raise ValueError("Only one of 'use_default_interface' or 'connection_name' must be provided.")
|
|
62
|
+
elif not use_default_interface and not connection_name:
|
|
63
|
+
raise ValueError("Either 'use_default_interface' or 'connection_name' must be provided.")
|
|
64
|
+
|
|
65
|
+
adapters = list_network_adapters()
|
|
66
|
+
|
|
67
|
+
current_adapter = None
|
|
68
|
+
if use_default_interface:
|
|
69
|
+
default_connection_name_dict: dict = networks.get_default_connection_name()
|
|
70
|
+
# Get the first key from the dictionary.
|
|
71
|
+
connection_name: str = list(default_connection_name_dict.keys())[0]
|
|
72
|
+
|
|
73
|
+
if connection_name is None and mac_address is None:
|
|
74
|
+
raise ValueError("Either 'connection_name' or 'mac_address' must be provided.")
|
|
75
|
+
elif connection_name and mac_address:
|
|
76
|
+
raise ValueError("Only one of 'connection_name' or 'mac_address' must be provided.")
|
|
77
|
+
|
|
78
|
+
if connection_name:
|
|
79
|
+
for adapter in adapters:
|
|
80
|
+
if connection_name == adapter.NetConnectionID:
|
|
81
|
+
current_adapter = adapter
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
if not current_adapter:
|
|
85
|
+
raise NetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
|
|
86
|
+
elif mac_address:
|
|
87
|
+
for adapter in adapters:
|
|
88
|
+
if mac_address == adapter.MACAddress:
|
|
89
|
+
current_adapter = adapter
|
|
90
|
+
break
|
|
91
|
+
|
|
92
|
+
if current_adapter is None:
|
|
93
|
+
raise NetworkAdapterNotFoundError(f"Adapter with MAC address '{mac_address}' not found.")
|
|
94
|
+
|
|
95
|
+
# Initialize the WMI client
|
|
96
|
+
wmi = win32com.client.Dispatch('WbemScripting.SWbemLocator')
|
|
97
|
+
wmi_service = wmi.ConnectServer('.', 'root\\cimv2')
|
|
98
|
+
|
|
99
|
+
# Query the network adapter configurations
|
|
100
|
+
query = f"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index='{current_adapter.DeviceID}'"
|
|
101
|
+
adapter_configs = wmi_service.ExecQuery(query)
|
|
102
|
+
|
|
103
|
+
# Check if the adapter exists
|
|
104
|
+
if len(adapter_configs) == 0:
|
|
105
|
+
raise NetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
|
|
106
|
+
|
|
107
|
+
return adapter_configs[0], current_adapter
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def set_dns_server(
|
|
111
|
+
dns_servers: Union[list[str], None],
|
|
112
|
+
use_default_interface: bool = False,
|
|
113
|
+
connection_name: str = None,
|
|
114
|
+
mac_address: str = None
|
|
115
|
+
):
|
|
116
|
+
"""
|
|
117
|
+
Set the DNS servers for a network adapter.
|
|
118
|
+
:param dns_servers: list of strings, DNS server IPv4 addresses.
|
|
119
|
+
None, if you want to remove the DNS servers and make the interface to obtain them automatically from DHCP.
|
|
120
|
+
list[str], if you want to set the DNS servers manually to the list of strings.
|
|
121
|
+
:param use_default_interface: bool, if True, the default network interface will be used.
|
|
122
|
+
This is the adapter that your internet is being used from.
|
|
123
|
+
:param connection_name: string, adapter name as shown in the network settings.
|
|
124
|
+
:param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
|
|
125
|
+
:return:
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
adapter_config, current_adapter = get_wmi_network_configuration(
|
|
129
|
+
use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
|
|
130
|
+
|
|
131
|
+
print_api(f"Adapter [{current_adapter.Description}], Connection name [{current_adapter.NetConnectionID}]\n"
|
|
132
|
+
f"Setting DNS servers to {dns_servers}", color='blue')
|
|
133
|
+
|
|
134
|
+
# Set DNS servers
|
|
135
|
+
helpers.call_method(adapter_config, 'SetDNSServerSearchOrder', dns_servers)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def is_adapter_dns_gateway_from_dhcp(
|
|
139
|
+
use_default_interface: bool = False,
|
|
140
|
+
connection_name: str = None,
|
|
141
|
+
mac_address: str = None
|
|
142
|
+
) -> bool:
|
|
143
|
+
"""
|
|
144
|
+
Check if the adapter is set to obtain the DNS servers automatically from DHCP.
|
|
145
|
+
:param use_default_interface: bool, if True, the default network interface will be used.
|
|
146
|
+
This is the adapter that your internet is being used from.
|
|
147
|
+
:param connection_name: string, adapter name as shown in the network settings.
|
|
148
|
+
:param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
|
|
149
|
+
:return: bool, True if DHCP is enabled, False otherwise.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
adapter_config, current_adapter = get_wmi_network_configuration(
|
|
153
|
+
use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
|
|
154
|
+
|
|
155
|
+
# If DHCP is not enabled.
|
|
156
|
+
if not adapter_config.DHCPEnabled:
|
|
157
|
+
# Then it is obvious that DNS Gateway is also Statis.
|
|
158
|
+
return False
|
|
159
|
+
# If DHCP is enabled.
|
|
160
|
+
else:
|
|
161
|
+
# Then we need to check if Default IP gateway is the same as DNS Gateway, if so.
|
|
162
|
+
if adapter_config.DefaultIPGateway == adapter_config.DNSServerSearchOrder:
|
|
163
|
+
# Then it is set dynamically from DHCP.
|
|
164
|
+
return True
|
|
165
|
+
else:
|
|
166
|
+
# If not, so it is static.
|
|
167
|
+
return False
|
|
@@ -2,17 +2,12 @@ from . import exception_wrapper
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
@exception_wrapper.connection_exception_decorator
|
|
5
|
-
def accept_connection(socket_object,
|
|
5
|
+
def accept_connection(socket_object, domain_from_dns_server, print_kwargs: dict = None):
|
|
6
6
|
"""
|
|
7
7
|
Accept connection from client.
|
|
8
8
|
This function is wrapped with exception wrapper.
|
|
9
9
|
After you execute the function, you can get the error message if there was any with:
|
|
10
10
|
error_message = accept_connection.message
|
|
11
|
-
|
|
12
|
-
:param socket_object:
|
|
13
|
-
:param dns_domain:
|
|
14
|
-
:param print_kwargs:
|
|
15
|
-
:return:
|
|
16
11
|
"""
|
|
17
12
|
|
|
18
13
|
client_socket = None
|
|
@@ -33,8 +28,13 @@ def accept_connection(socket_object, dns_domain, print_kwargs: dict = None):
|
|
|
33
28
|
return client_socket, client_address_tuple
|
|
34
29
|
|
|
35
30
|
|
|
36
|
-
def accept_connection_with_error(
|
|
37
|
-
|
|
31
|
+
def accept_connection_with_error(
|
|
32
|
+
socket_object,
|
|
33
|
+
domain_from_dns_server,
|
|
34
|
+
print_kwargs: dict = None
|
|
35
|
+
):
|
|
36
|
+
client_socket, client_address_tuple = accept_connection(
|
|
37
|
+
socket_object, domain_from_dns_server, print_kwargs=print_kwargs)
|
|
38
38
|
error_message = accept_connection.message
|
|
39
39
|
|
|
40
40
|
return client_socket, client_address_tuple, error_message
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import socket
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
LOCALHOST_IPV4: str = '127.0.0.1'
|
|
5
|
+
DEFAULT_IPV4: str = socket.gethostbyname(socket.gethostname())
|
|
6
|
+
THIS_DEVICE_IP_LIST: list = [LOCALHOST_IPV4, DEFAULT_IPV4]
|
|
7
|
+
|
|
8
|
+
|
|
4
9
|
def get_local_network_interfaces_ip_address(family_type: str = None, ip_only: bool = False) -> list:
|
|
5
10
|
"""
|
|
6
11
|
Return list of IP addresses of local network interfaces.
|
|
@@ -57,3 +62,11 @@ def get_source_destination(socket_object):
|
|
|
57
62
|
def set_socket_timeout(socket_object, seconds: int = 1):
|
|
58
63
|
# Setting timeout on the socket before "accept()" drastically slows down connections.
|
|
59
64
|
socket_object.settimeout(seconds)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_default_ip_address() -> str:
|
|
68
|
+
"""
|
|
69
|
+
Get the default IP address of the system.
|
|
70
|
+
:return: string.
|
|
71
|
+
"""
|
|
72
|
+
return socket.gethostbyname(socket.gethostname())
|
|
@@ -1,169 +1,222 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
|
|
4
|
+
from cryptography import x509
|
|
5
|
+
|
|
4
6
|
from . import creator, base, socket_client
|
|
5
7
|
from .. import pyopensslw, cryptographyw
|
|
6
8
|
from ..certauthw.certauthw import CertAuthWrapper
|
|
7
9
|
from ...print_api import print_api
|
|
10
|
+
from ... import filesystem
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Certificator:
|
|
14
|
+
"""
|
|
15
|
+
Certificator class is used to create and manage certificates, wrapping ssl contexts and sockets.
|
|
16
|
+
"""
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
ca_certificate_name: str,
|
|
20
|
+
ca_certificate_filepath: str,
|
|
21
|
+
default_server_certificate_usage: bool,
|
|
22
|
+
default_server_certificate_name: str,
|
|
23
|
+
default_server_certificate_directory: str,
|
|
24
|
+
default_certificate_domain_list: list,
|
|
25
|
+
sni_server_certificates_cache_directory: str,
|
|
26
|
+
sni_get_server_certificate_from_server_socket: bool,
|
|
27
|
+
sni_server_certificate_from_server_socket_download_directory: str,
|
|
28
|
+
custom_server_certificate_usage: bool,
|
|
29
|
+
custom_server_certificate_path: str,
|
|
30
|
+
custom_private_key_path: str,
|
|
31
|
+
forwarding_dns_service_ipv4_list___only_for_localhost: list,
|
|
32
|
+
skip_extension_id_list: list,
|
|
33
|
+
tls: bool
|
|
34
|
+
):
|
|
35
|
+
self.ca_certificate_name = ca_certificate_name
|
|
36
|
+
self.ca_certificate_filepath = ca_certificate_filepath
|
|
37
|
+
self.default_server_certificate_usage = default_server_certificate_usage
|
|
38
|
+
self.default_server_certificate_name = default_server_certificate_name
|
|
39
|
+
self.default_server_certificate_directory = default_server_certificate_directory
|
|
40
|
+
self.default_certificate_domain_list = default_certificate_domain_list
|
|
41
|
+
self.sni_server_certificates_cache_directory = sni_server_certificates_cache_directory
|
|
42
|
+
self.sni_get_server_certificate_from_server_socket = sni_get_server_certificate_from_server_socket
|
|
43
|
+
self.sni_server_certificate_from_server_socket_download_directory = (
|
|
44
|
+
sni_server_certificate_from_server_socket_download_directory)
|
|
45
|
+
self.custom_server_certificate_usage = custom_server_certificate_usage
|
|
46
|
+
self.custom_server_certificate_path = custom_server_certificate_path
|
|
47
|
+
self.custom_private_key_path = custom_private_key_path
|
|
48
|
+
self.forwarding_dns_service_ipv4_list___only_for_localhost = (
|
|
49
|
+
forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
50
|
+
self.skip_extension_id_list = skip_extension_id_list
|
|
51
|
+
self.tls = tls
|
|
52
|
+
|
|
53
|
+
# noinspection PyTypeChecker
|
|
54
|
+
self.certauth_wrapper: CertAuthWrapper = None
|
|
55
|
+
|
|
56
|
+
def initialize_certauth_create_use_ca_certificate(self, server_certificate_directory: str):
|
|
57
|
+
"""
|
|
58
|
+
Initialize CertAuthWrapper and create CA certificate if it doesn't exist.
|
|
59
|
+
:return:
|
|
60
|
+
"""
|
|
61
|
+
# Initialize CertAuthWrapper.
|
|
62
|
+
certauth_wrapper = CertAuthWrapper(
|
|
63
|
+
ca_certificate_name=self.ca_certificate_name,
|
|
64
|
+
ca_certificate_filepath=self.ca_certificate_filepath,
|
|
65
|
+
server_certificate_directory=server_certificate_directory
|
|
66
|
+
)
|
|
8
67
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# Check if default certificate was created.
|
|
46
|
-
if server_certificate_file_path:
|
|
47
|
-
message = f"Default Server Certificate was created / overwritten: {server_certificate_file_path}"
|
|
48
|
-
print_api(message, **print_kwargs)
|
|
49
|
-
|
|
50
|
-
message = \
|
|
51
|
-
f"Default Server Certificate current 'Subject Alternative Names': {default_server_certificate_san}"
|
|
52
|
-
print_api(message, **print_kwargs)
|
|
53
|
-
else:
|
|
54
|
-
message = f"Couldn't create / overwrite Default Server Certificate: {server_certificate_file_path}"
|
|
55
|
-
print_api(message, error_type=True, logger_method='critical', **print_kwargs)
|
|
56
|
-
sys.exit()
|
|
68
|
+
# Create CA certificate if it doesn't exist.
|
|
69
|
+
certauth_wrapper.create_use_ca_certificate()
|
|
70
|
+
|
|
71
|
+
return certauth_wrapper
|
|
72
|
+
|
|
73
|
+
# noinspection PyTypeChecker
|
|
74
|
+
def select_server_ssl_context_certificate(
|
|
75
|
+
self,
|
|
76
|
+
print_kwargs: dict = None
|
|
77
|
+
):
|
|
78
|
+
"""
|
|
79
|
+
This function selects between the default certificate and custom certificate for the sll context.
|
|
80
|
+
Returns the selected certificate file path and the private key file path.
|
|
81
|
+
"""
|
|
82
|
+
# We need to nullify the variable, since we have several checks if the variable was set or not.
|
|
83
|
+
server_certificate_file_path: str = None
|
|
84
|
+
server_private_key_file_path: str = None
|
|
85
|
+
|
|
86
|
+
# Creating if non-existent/overwriting default server certificate.
|
|
87
|
+
if self.default_server_certificate_usage:
|
|
88
|
+
# Creating if non-existent/overwriting default server certificate.
|
|
89
|
+
server_certificate_file_path, default_server_certificate_san = \
|
|
90
|
+
self.create_overwrite_default_server_certificate_ca_signed()
|
|
91
|
+
|
|
92
|
+
# Check if default certificate was created.
|
|
93
|
+
if server_certificate_file_path:
|
|
94
|
+
message = f"Default Server Certificate was created / overwritten: {server_certificate_file_path}"
|
|
95
|
+
print_api(message, **(print_kwargs or {}))
|
|
96
|
+
|
|
97
|
+
message = \
|
|
98
|
+
f"Default Server Certificate current 'Subject Alternative Names': {default_server_certificate_san}"
|
|
99
|
+
print_api(message, **(print_kwargs or {}))
|
|
100
|
+
else:
|
|
101
|
+
message = f"Couldn't create / overwrite Default Server Certificate: {server_certificate_file_path}"
|
|
102
|
+
print_api(message, error_type=True, logger_method='critical', **(print_kwargs or {}))
|
|
103
|
+
sys.exit()
|
|
57
104
|
|
|
58
105
|
# Assigning 'certificate_path' to 'custom_certificate_path' if usage was set.
|
|
59
|
-
if
|
|
60
|
-
server_certificate_file_path =
|
|
106
|
+
if self.custom_server_certificate_usage:
|
|
107
|
+
server_certificate_file_path = self.custom_server_certificate_path
|
|
61
108
|
# Since 'ssl_context.load_cert_chain' uses 'keypath' as 'None' if certificate contains private key.
|
|
62
109
|
# We'd like to leave it that way and don't fetch empty string from 'config'.
|
|
63
|
-
if
|
|
64
|
-
server_private_key_file_path =
|
|
65
|
-
|
|
66
|
-
return server_certificate_file_path, server_private_key_file_path
|
|
110
|
+
if self.custom_private_key_path:
|
|
111
|
+
server_private_key_file_path = self.custom_private_key_path
|
|
67
112
|
|
|
113
|
+
return server_certificate_file_path, server_private_key_file_path
|
|
68
114
|
|
|
69
|
-
def create_overwrite_default_server_certificate_ca_signed(
|
|
70
|
-
|
|
71
|
-
|
|
115
|
+
def create_overwrite_default_server_certificate_ca_signed(self):
|
|
116
|
+
"""
|
|
117
|
+
Create or overwrite default server certificate.
|
|
118
|
+
:return:
|
|
119
|
+
"""
|
|
72
120
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
server_certificate_file_path, default_server_certificate_san = \
|
|
77
|
-
CERTAUTH_WRAPPER.create_overwrite_server_certificate_ca_signed_return_path_and_san(
|
|
78
|
-
domain_list=domain_list,
|
|
79
|
-
server_certificate_file_name_no_extension=server_certificate_file_name_no_extension
|
|
121
|
+
self.certauth_wrapper = self.initialize_certauth_create_use_ca_certificate(
|
|
122
|
+
server_certificate_directory=self.default_server_certificate_directory
|
|
80
123
|
)
|
|
81
124
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def create_use_sni_server_certificate_ca_signed(sni_received_dict: dict, config: dict, print_kwargs: dict = None):
|
|
86
|
-
global CERTAUTH_WRAPPER
|
|
87
|
-
|
|
88
|
-
# === Connect to the domain and get the certificate. ===========================================================
|
|
89
|
-
certificate_from_socket_x509 = None
|
|
90
|
-
if config['certificates']['sni_get_server_certificate_from_server_socket']:
|
|
91
|
-
# Generate PEM certificate file path string for downloaded certificates. Signed certificates will go to the
|
|
92
|
-
# 'certs' folder.
|
|
93
|
-
certificate_from_socket_file_path: str = \
|
|
94
|
-
config['certificates']['sni_server_certificate_from_server_socket_download_directory'] + \
|
|
95
|
-
os.sep + sni_received_dict['destination_name'] + ".pem"
|
|
96
|
-
# Get client ip.
|
|
97
|
-
client_ip = base.get_source_address_from_socket(sni_received_dict['ssl_socket'])[0]
|
|
98
|
-
|
|
99
|
-
# If we're on localhost, then use external services list in order to resolve the domain:
|
|
100
|
-
if client_ip == "127.0.0.1":
|
|
101
|
-
service_client = socket_client.SocketClient(
|
|
102
|
-
service_name=sni_received_dict['destination_name'],
|
|
103
|
-
service_port=base.get_destination_address_from_socket(sni_received_dict['ssl_socket'])[1],
|
|
104
|
-
dns_servers_list=config['tcp']['forwarding_dns_service_ipv4_list___only_for_localhost'])
|
|
105
|
-
# If we're not on localhost, then connect to domain directly.
|
|
106
|
-
else:
|
|
107
|
-
service_client = socket_client.SocketClient(
|
|
108
|
-
service_name=sni_received_dict['destination_name'],
|
|
109
|
-
service_port=base.get_destination_address_from_socket(sni_received_dict['ssl_socket'])[1])
|
|
110
|
-
|
|
111
|
-
# Get certificate from socket and convert to X509 cryptography module object.
|
|
112
|
-
certificate_from_socket_x509_cryptography_object = service_client.get_certificate_from_server(
|
|
113
|
-
save_as_file=True, cert_file_path=certificate_from_socket_file_path, cert_output_type='cryptography'
|
|
114
|
-
)
|
|
125
|
+
server_certificate_file_name_no_extension = self.default_server_certificate_name
|
|
115
126
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
server_certificate_file_path, default_server_certificate_san = \
|
|
128
|
+
self.certauth_wrapper.create_overwrite_server_certificate_ca_signed_return_path_and_san(
|
|
129
|
+
domain_list=self.default_certificate_domain_list,
|
|
130
|
+
server_certificate_file_name_no_extension=server_certificate_file_name_no_extension
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return server_certificate_file_path, default_server_certificate_san
|
|
134
|
+
|
|
135
|
+
def create_use_sni_server_certificate_ca_signed(
|
|
136
|
+
self,
|
|
137
|
+
sni_received_parameters,
|
|
138
|
+
print_kwargs: dict = None
|
|
139
|
+
):
|
|
140
|
+
# === Connect to the domain and get the certificate. ===========================================================
|
|
141
|
+
certificate_from_socket_x509 = None
|
|
142
|
+
if self.sni_get_server_certificate_from_server_socket:
|
|
143
|
+
# Generate PEM certificate file path string for downloaded certificates. Signed certificates will go to the
|
|
144
|
+
# 'certs' folder.
|
|
145
|
+
certificate_from_socket_file_path: str = \
|
|
146
|
+
self.sni_server_certificate_from_server_socket_download_directory + \
|
|
147
|
+
os.sep + sni_received_parameters.destination_name + ".pem"
|
|
148
|
+
# Get client ip.
|
|
149
|
+
client_ip = base.get_source_address_from_socket(sni_received_parameters.ssl_socket)[0]
|
|
150
|
+
|
|
151
|
+
# If we're on localhost, then use external services list in order to resolve the domain:
|
|
152
|
+
if client_ip in base.THIS_DEVICE_IP_LIST:
|
|
153
|
+
service_client = socket_client.SocketClient(
|
|
154
|
+
service_name=sni_received_parameters.destination_name,
|
|
155
|
+
service_port=base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
|
|
156
|
+
tls=self.tls,
|
|
157
|
+
dns_servers_list=self.forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
158
|
+
# If we're not on localhost, then connect to domain directly.
|
|
159
|
+
else:
|
|
160
|
+
service_client = socket_client.SocketClient(
|
|
161
|
+
service_name=sni_received_parameters.destination_name,
|
|
162
|
+
service_port=base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
|
|
163
|
+
tls=self.tls
|
|
127
164
|
)
|
|
128
165
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
#
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
# If certificate from socket exists, then we don't need to get it from the socket and write to file.
|
|
167
|
+
# and we will return None, since no certificate was fetched.
|
|
168
|
+
# noinspection PyTypeChecker
|
|
169
|
+
certificate_from_socket_x509_cryptography_object: x509.Certificate = None
|
|
170
|
+
if not filesystem.is_file_exists(certificate_from_socket_file_path):
|
|
171
|
+
print_api("Certificate from socket doesn't exist, fetching.", **(print_kwargs or {}))
|
|
172
|
+
# Get certificate from socket and convert to X509 cryptography module object.
|
|
173
|
+
certificate_from_socket_x509_cryptography_object: x509.Certificate = (
|
|
174
|
+
service_client.get_certificate_from_server(
|
|
175
|
+
save_as_file=True, cert_file_path=certificate_from_socket_file_path,
|
|
176
|
+
cert_output_type='cryptography')
|
|
177
|
+
)
|
|
178
|
+
else:
|
|
179
|
+
print_api("The Certificate from socket already exists, not fetching", **(print_kwargs or {}))
|
|
180
|
+
certificate_from_socket_x509_cryptography_object: x509.Certificate = (
|
|
181
|
+
cryptographyw.convert_object_to_x509(certificate_from_socket_file_path))
|
|
182
|
+
|
|
183
|
+
# skip_extensions = ['1.3.6.1.5.5.7.3.2', '2.5.29.31', '1.3.6.1.5.5.7.1.1']
|
|
184
|
+
|
|
185
|
+
# If certificate was downloaded successfully, then remove extensions if they were provided.
|
|
186
|
+
# If certificate was downloaded successfully and no extensions to skip were provided, then use it as is.
|
|
187
|
+
if certificate_from_socket_x509_cryptography_object and self.skip_extension_id_list:
|
|
188
|
+
# Copy extensions from old certificate to new certificate, without specified extensions.
|
|
189
|
+
certificate_from_socket_x509_cryptography_object, _ = \
|
|
190
|
+
cryptographyw.copy_extensions_from_old_cert_to_new_cert(
|
|
191
|
+
certificate_from_socket_x509_cryptography_object,
|
|
192
|
+
skip_extensions=self.skip_extension_id_list,
|
|
193
|
+
print_kwargs=print_kwargs
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# If certificate was downloaded successfully, then convert it to pyopenssl object.
|
|
197
|
+
if certificate_from_socket_x509_cryptography_object:
|
|
198
|
+
# Convert X509 cryptography module object to pyopenssl, since certauth uses pyopenssl.
|
|
199
|
+
certificate_from_socket_x509 = \
|
|
200
|
+
pyopensslw.convert_cryptography_object_to_pyopenssl(
|
|
201
|
+
certificate_from_socket_x509_cryptography_object)
|
|
202
|
+
|
|
203
|
+
# === EOF Get certificate from the domain. =====================================================================
|
|
204
|
+
|
|
205
|
+
# If CertAuthWrapper wasn't initialized yet, it means that CA wasn't created/loaded yet.
|
|
206
|
+
if not self.certauth_wrapper:
|
|
207
|
+
self.certauth_wrapper = self.initialize_certauth_create_use_ca_certificate(
|
|
208
|
+
server_certificate_directory=self.sni_server_certificates_cache_directory)
|
|
209
|
+
# try:
|
|
210
|
+
# Create if non-existent / read existing server certificate.
|
|
211
|
+
sni_server_certificate_file_path = self.certauth_wrapper.create_read_server_certificate_ca_signed(
|
|
212
|
+
sni_received_parameters.destination_name, certificate_from_socket_x509)
|
|
213
|
+
|
|
214
|
+
message = f"SNI Handler: port " \
|
|
215
|
+
f"{base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1]}: " \
|
|
216
|
+
f"Using certificate: {sni_server_certificate_file_path}"
|
|
217
|
+
print_api(message, **print_kwargs)
|
|
218
|
+
|
|
219
|
+
# You need to build new context and exchange the context that being inherited from the main socket,
|
|
220
|
+
# or else the context will receive previous certificate each time.
|
|
221
|
+
sni_received_parameters.ssl_socket.context = \
|
|
222
|
+
creator.create_server_ssl_context___load_certificate_and_key(sni_server_certificate_file_path, None)
|