atomicshop 2.16.29__py3-none-any.whl → 2.16.31__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.16.29'
4
+ __version__ = '2.16.31'
atomicshop/http_parse.py CHANGED
@@ -2,6 +2,7 @@ from http.server import BaseHTTPRequestHandler
2
2
  from http.client import HTTPResponse
3
3
  import http
4
4
  from io import BytesIO
5
+ import socket
5
6
 
6
7
 
7
8
  class HTTPRequestParse(BaseHTTPRequestHandler):
@@ -50,38 +51,25 @@ class HTTPRequestParse(BaseHTTPRequestHandler):
50
51
 
51
52
  # noinspection PyMissingConstructor
52
53
  def __init__(self, request_text):
53
- self.rfile = BytesIO(request_text)
54
- self.raw_requestline = self.rfile.readline()
55
- self.error_code = self.error_message = None
56
- self.parse_request()
54
+ self.request_text = request_text
57
55
 
58
- # Check if ".path" attribute exists after HTTP request parsing
59
- if not hasattr(self, 'path'):
60
- # noinspection PyTypeChecker
61
- self.path = None
56
+ # noinspection PyTypeChecker
57
+ self.rfile = None
58
+ self.raw_requestline = None
59
+ self.error_code = None
60
+ self.error_message = None
62
61
 
63
62
  self.content_length = None
64
63
  self.body = None
65
-
66
- # Before checking for body, we need to make sure that ".headers" property exists, if not, return empty values.
67
- if hasattr(self, 'headers'):
68
- # The "body" of request is in the 'Content-Length' key. If it exists in "headers" - get the body
69
- if 'Content-Length' in self.headers.keys():
70
- # "self.headers.get('Content-Length')" returns number in string format, "int" converts it to integer
71
- self.content_length = int(self.headers.get('Content-Length'))
72
- self.body = self.rfile.read(self.content_length)
73
-
74
- # Examples:
75
- # Getting path: self.path
76
- # Getting Request Version: self.request_version
77
- # Getting specific header: self.headers['host']
64
+ # noinspection PyTypeChecker
65
+ self.path = None
78
66
 
79
67
  # noinspection PyMethodOverriding
80
68
  def send_error(self, code, message):
81
69
  self.error_code = code
82
70
  self.error_message = message
83
71
 
84
- def check_if_http(self):
72
+ def parse(self):
85
73
  """
86
74
  Function to check if parsed object is HTTP request or not.
87
75
  'reason' will be populated with parsing status and errors.
@@ -116,7 +104,26 @@ class HTTPRequestParse(BaseHTTPRequestHandler):
116
104
  client_message.request_raw_decoded = request_decoded
117
105
  """
118
106
 
119
- error: bool = False
107
+ error: str = str()
108
+ info: str = str()
109
+
110
+ self.rfile = BytesIO(self.request_text)
111
+ self.raw_requestline = self.rfile.readline()
112
+ self.error_code = self.error_message = None
113
+ self.parse_request()
114
+
115
+ # Before checking for body, we need to make sure that ".headers" property exists, if not, return empty values.
116
+ if hasattr(self, 'headers'):
117
+ # The "body" of request is in the 'Content-Length' key. If it exists in "headers" - get the body
118
+ if 'Content-Length' in self.headers.keys():
119
+ # "self.headers.get('Content-Length')" returns number in string format, "int" converts it to integer
120
+ self.content_length = int(self.headers.get('Content-Length'))
121
+ self.body = self.rfile.read(self.content_length)
122
+
123
+ # Examples:
124
+ # Getting path: self.path
125
+ # Getting Request Version: self.request_version
126
+ # Getting specific header: self.headers['host']
120
127
 
121
128
  # If there's any error in HTTP parsing
122
129
  if self.error_message:
@@ -125,67 +132,82 @@ class HTTPRequestParse(BaseHTTPRequestHandler):
125
132
  # If it's 'Bad request' this is not HTTP request, so we can
126
133
  # continue the execution and parse the code as NON-HTTP Request.
127
134
  # Currently, seen 'Bad request syntax' and 'Bad request version'.
128
- reason = f"HTTP Request Parsing: Not HTTP request: {self.error_message}"
129
- function_result = False
130
- error: False
135
+ error = f"HTTP Request Parsing: Not HTTP request: {self.error_message}"
136
+ is_http = False
131
137
  else:
132
- reason = f"HTTP Request Parsing: HTTP Request with Script Undocumented ERROR: {self.error_message}"
133
- function_result = True
134
- error = True
138
+ error = f"HTTP Request Parsing: HTTP Request with Script Undocumented ERROR: {self.error_message}"
139
+ is_http = False
135
140
  # If there's no error at all in HTTP Parsing, then it's fine HTTP Request
136
141
  else:
137
- reason = "HTTP Request Parsing: Valid HTTP request"
138
- function_result = True
139
- error = False
142
+ is_http = True
143
+ info = "HTTP Request Parsing: Valid HTTP request"
140
144
 
141
- return function_result, reason, error
145
+ return self, is_http, info, error
142
146
 
143
147
 
144
148
  class FakeSocket:
145
149
  """
146
- FakeSocket is needed to parse HTTP Response. Socket object is needed for HTTPResponse class input.
150
+ FakeSocket mimics a socket object for parsing HTTP responses.
147
151
  """
148
152
  def __init__(self, response_bytes):
149
153
  self._file = BytesIO(response_bytes)
150
154
 
151
- def makefile(self, *args, **kwargs):
155
+ def makefile(self, mode='rb', buffering=-1) -> BytesIO:
156
+ """
157
+ Mimics the socket's makefile method, returning the BytesIO object.
158
+ """
152
159
  return self._file
153
160
 
161
+ def fileno(self) -> int:
162
+ """
163
+ Provide a dummy file descriptor, as some code might call this.
164
+ """
165
+ raise OSError("File descriptor not available in FakeSocket")
166
+
154
167
 
155
168
  class HTTPResponseParse:
156
169
  def __init__(self, response_raw_bytes: bytes):
157
- self.error = None
158
170
  self.response_raw_bytes: bytes = response_raw_bytes
171
+
172
+ self.error = None
173
+ self.source = None
174
+ self.response_raw_decoded = None
175
+ self.is_http: bool = False
176
+
177
+ def parse(self):
159
178
  # Assigning FakeSocket with response_raw_bytes.
160
179
  self.source = FakeSocket(self.response_raw_bytes)
161
180
 
162
181
  # Initializing HTTPResponse class with the FakeSocket with response_raw_bytes as input.
182
+ # noinspection PyTypeChecker
163
183
  self.response_raw_decoded = HTTPResponse(self.source)
164
184
 
165
185
  # Try to parse HTTP Response.
166
186
  try:
167
187
  self.response_raw_decoded.begin()
188
+ self.is_http = True
168
189
  # If there were problems with the status line.
169
190
  except http.client.BadStatusLine:
170
191
  self.error = "HTTP Response Parsing: Not a valid HTTP Response: Bad Status Line."
171
- pass
172
-
173
- try:
174
- # If no exception was thrown, but there are some problems with headers.
175
- if self.response_raw_decoded.headers.defects:
176
- self.error = f"HTTP Response Parsing: Not a valid HTTP Response: Some defects in headers: " \
177
- f"{self.response_raw_decoded.headers.defects}"
178
- # If the attribute of defects doesn't exist, probably the response wasn't parsed at all by the library,
179
- # Meaning, that the exception was already handled.
180
- except AttributeError:
181
- pass
182
-
183
- # Before checking for body, we need to make sure that ".headers" property exists, if not, return empty values
184
- self.response_raw_decoded.content_length = None
185
- self.response_raw_decoded.body = None
186
- if hasattr(self.response_raw_decoded, 'headers') and self.response_raw_decoded is not None:
187
- # The "body" of response is in the 'Content-Length' key. If it exists in "headers" - get the body.
188
- if 'Content-Length' in self.response_raw_decoded.headers.keys():
192
+ self.is_http = False
193
+
194
+ header_exists: bool = False
195
+ if (self.response_raw_decoded is not None and hasattr(self.response_raw_decoded, 'headers') and
196
+ self.response_raw_decoded.headers is not None):
197
+ header_exists = True
198
+
199
+ if header_exists and self.response_raw_decoded.headers.defects:
200
+ self.error = f"HTTP Response Parsing: Not a valid HTTP Response: Some defects in headers: " \
201
+ f"{self.response_raw_decoded.headers.defects}"
202
+ self.is_http = False
203
+
204
+ if self.is_http:
205
+ # Before checking for body, we need to make sure that ".headers" property exists,
206
+ # if not, return empty values.
207
+ self.response_raw_decoded.content_length = None
208
+ self.response_raw_decoded.body = None
209
+ if header_exists and 'Content-Length' in self.response_raw_decoded.headers.keys():
210
+ # The "body" of response is in the 'Content-Length' key. If it exists in "headers" - get the body.
189
211
  # "self.response_raw_decoded.headers.get('Content-Length')" returns number in string format,
190
212
  # "int" converts it to integer.
191
213
  self.response_raw_decoded.content_length = int(self.response_raw_decoded.headers.get('Content-Length'))
@@ -193,6 +215,5 @@ class HTTPResponseParse:
193
215
  # of the response that we received.
194
216
  # self.response_raw_bytes[-23:]
195
217
  self.response_raw_decoded.body = self.response_raw_bytes[-self.response_raw_decoded.content_length:]
196
- else:
197
- self.response_raw_decoded.content_length = None
198
- self.response_raw_decoded.body = None
218
+
219
+ return self.response_raw_decoded, self.is_http, self.error
@@ -82,29 +82,22 @@ def thread_worker_main(
82
82
  def parse_http():
83
83
  nonlocal error_message
84
84
  # Parsing the raw bytes as HTTP.
85
- request_decoded = HTTPRequestParse(client_message.request_raw_bytes)
86
- # Getting the status of http parsing
87
- request_is_http, http_parsing_reason, http_parsing_error = request_decoded.check_if_http()
85
+ request_decoded, is_http_request, request_parsing_info, request_parsing_error = (
86
+ HTTPRequestParse(client_message.request_raw_bytes).parse())
88
87
 
89
- # Currently, we don't care if it's HTTP. If there was no error we can continue. Just log the reason.
90
- if not http_parsing_error:
91
- print_api(http_parsing_reason, logger=network_logger, logger_method='info')
92
- # If there was error - the request is really HTTP, but there's a problem with its structure.
93
- else:
94
- client_message.error = http_parsing_reason
95
- error_message = (
96
- f'HTTP Parse Request Error: '
97
- f'The request is HTTP protocol, but there was a problem with its structure: '
98
- f'{http_parsing_error}')
99
- print_api(error_message, logger=network_logger, logger_method='error', color='yellow')
100
- statistics_error_list.append(error_message)
101
-
102
- # If the request is HTTP protocol.
103
- if request_is_http:
88
+ if is_http_request:
104
89
  client_message.protocol = 'HTTP'
90
+ client_message.request_raw_decoded = request_decoded
91
+ print_api(request_parsing_info, logger=network_logger, logger_method='info')
105
92
  network_logger.info(f"Method: {request_decoded.command}")
106
93
  network_logger.info(f"Path: {request_decoded.path}")
107
- client_message.request_raw_decoded = request_decoded
94
+ # If there was error - the request is really HTTP, but there's a problem with its structure.
95
+ else:
96
+ # client_message.error = request_parsing_error
97
+ print_api(request_parsing_error, logger=network_logger, logger_method='error', color='yellow')
98
+ # It doesn't matter if we have HTTP Parsing error, since the request may not be really HTTP, so it is OK
99
+ # not to log it into statistics.
100
+ # statistics_error_list.append(error_message)
108
101
 
109
102
  def finish_thread():
110
103
  # At this stage there could be several times that the same socket was used to the service server - we need to
@@ -184,6 +177,8 @@ def thread_worker_main(
184
177
  client_message.destination_port = destination_port
185
178
  client_message.process_name = process_commandline
186
179
  client_message.server_name = server_name
180
+ # Getting current time of message received from client.
181
+ client_message.request_time_received = datetime.now()
187
182
 
188
183
  network_logger.info(f"Initializing Receiver on cycle: {str(cycle_count+1)}")
189
184
  # Getting message from the client over the socket using specific class.
@@ -196,10 +191,10 @@ def thread_worker_main(
196
191
  if client_received_raw_data:
197
192
  # Putting the received message to the aggregating message class.
198
193
  client_message.request_raw_bytes = client_received_raw_data
199
- # Getting current time of message received from client.
200
- client_message.request_time_received = datetime.now()
201
194
 
202
195
  parse_http()
196
+ if client_message.protocol != 'HTTP':
197
+ pass
203
198
 
204
199
  # Custom parser, should parse HTTP body or the whole message if not HTTP.
205
200
  parser_instance = parser(client_message)
@@ -268,8 +263,13 @@ def thread_worker_main(
268
263
  client_message.response_list_of_raw_decoded = list()
269
264
  # Make HTTP Response parsing only if there was response at all.
270
265
  if response_raw_bytes:
271
- response_raw_decoded = HTTPResponseParse(response_raw_bytes).response_raw_decoded
272
- client_message.response_list_of_raw_decoded.append(response_raw_decoded)
266
+ response_raw_decoded, is_http_response, response_parsing_error = (
267
+ HTTPResponseParse(response_raw_bytes).parse())
268
+
269
+ if is_http_response:
270
+ client_message.response_list_of_raw_decoded.append(response_raw_decoded)
271
+ else:
272
+ client_message.response_list_of_raw_decoded.append(None)
273
273
 
274
274
  # So if the socket was closed and there was an error we can break the loop
275
275
  if not service_ssl_socket:
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  from datetime import datetime
3
+ import json
3
4
 
4
5
  from ...shared_functions import build_module_names, create_custom_logger, get_json
5
6
  from ... import message, recs_files
@@ -87,10 +88,13 @@ class RecorderParent:
87
88
  # Convert the requests and responses to hex.
88
89
  self.convert_messages()
89
90
  # Get the message in dict / JSON format
90
- record_message = get_json(self.class_client_message)
91
+ # record_message = get_json(self.class_client_message)
92
+ record_message_dict: dict = dict(self.class_client_message)
93
+ recorded_message_json_string = json.dumps(record_message_dict)
91
94
 
92
95
  # Since we already dumped the object to dictionary string, we'll just save the object to regular file.
93
- file_io.write_file(record_message, self.record_file_path, enable_long_file_path=True, **{'logger': self.logger})
96
+ file_io.write_file(
97
+ recorded_message_json_string, self.record_file_path, enable_long_file_path=True, **{'logger': self.logger})
94
98
 
95
99
  self.logger.info(f"Recorded to file: {self.record_file_path}")
96
100
 
@@ -1,15 +1,21 @@
1
+ from datetime import datetime
2
+ from typing import Union
3
+
4
+ from .. import http_parse
5
+ from ..basics import dicts
6
+
7
+
1
8
  class ClientMessage:
2
9
  """ A class that will store all the message details from the client """
3
10
  def __init__(self):
4
11
  self.request_raw_bytes: bytearray = bytearray()
5
- self.request_time_received = None
6
- self.request_raw_decoded = None
12
+ # noinspection PyTypeChecker
13
+ self.request_time_received: datetime = None
14
+ self.request_raw_decoded: Union[http_parse.HTTPRequestParse, any] = None
7
15
  self.request_body_parsed = None
8
16
  self.request_raw_hex: hex = None
9
- # self.response_raw_bytes: bytearray = bytearray()
10
17
  self.response_list_of_raw_bytes: list = list()
11
18
  self.response_list_of_raw_decoded: list = list()
12
- # self.response_raw_hex: hex = None
13
19
  self.response_list_of_raw_hex: list = list()
14
20
  self.server_name: str = str()
15
21
  self.server_ip: str = str()
@@ -22,3 +28,23 @@ class ClientMessage:
22
28
  self.error: str = str()
23
29
  self.protocol: str = str()
24
30
  self.recorded_file_path: str = str()
31
+
32
+ def __iter__(self):
33
+ # __dict__ returns a dictionary containing the instance's attributes
34
+ for key, value in self.__dict__.items():
35
+ if key == 'request_raw_bytes':
36
+ value = str(value)
37
+ elif key == 'request_time_received':
38
+ value = value.strftime('%Y-%m-%d-%H:%M:%S.%f')
39
+ elif key == 'request_raw_decoded':
40
+ if isinstance(value, http_parse.HTTPRequestParse):
41
+ value = dicts.convert_complex_object_to_dict(value)
42
+ else:
43
+ value = str(value)
44
+ elif key == 'request_body_parsed':
45
+ value = dicts.convert_complex_object_to_dict(value)
46
+ elif key == 'response_list_of_raw_bytes':
47
+ value = [str(bytes_response) for bytes_response in value]
48
+ elif key == 'response_list_of_raw_decoded':
49
+ value = [dicts.convert_complex_object_to_dict(complex_response) for complex_response in value]
50
+ yield key, value
@@ -38,9 +38,11 @@ def exit_cleanup():
38
38
  dns.set_connection_dns_gateway_dynamic(use_default_connection=True)
39
39
  print_api.print_api("Returned default DNS gateway...", color='blue')
40
40
 
41
- print_api.print_api(RECS_PROCESS_INSTANCE.is_alive())
42
- RECS_PROCESS_INSTANCE.terminate()
43
- RECS_PROCESS_INSTANCE.join()
41
+ # The process will not be executed if there was an exception in the beginning.
42
+ if RECS_PROCESS_INSTANCE is not None:
43
+ print_api.print_api(RECS_PROCESS_INSTANCE.is_alive())
44
+ RECS_PROCESS_INSTANCE.terminate()
45
+ RECS_PROCESS_INSTANCE.join()
44
46
 
45
47
 
46
48
  def mitm_server(config_file_path: str):
@@ -392,8 +394,8 @@ def mitm_server_main(config_file_path: str):
392
394
  exit_cleanup()
393
395
  return 0
394
396
  except Exception as e:
395
- RECS_PROCESS_INSTANCE.terminate()
396
-
397
- MITM_ERROR_LOGGER.write(e)
397
+ # The error logger will not be initiated if there will be a problem with configuration file or checks.
398
+ if MITM_ERROR_LOGGER is not None:
399
+ MITM_ERROR_LOGGER.write(e)
398
400
  exit_cleanup()
399
401
  return 1
@@ -589,7 +589,7 @@ class DnsServer:
589
589
  google_dns_ipv4_socket.recvfrom(self.buffer_size_receive)
590
590
  except TimeoutError as function_exception_object:
591
591
  print_api(function_exception_object, logger=self.logger, logger_method='error',
592
- traceback_string=True)
592
+ traceback_string=True, oneline=True)
593
593
  google_dns_ipv4_socket.close()
594
594
  counter += 1
595
595
  # Pass the exception.
@@ -6,6 +6,8 @@ from ...print_api import print_api
6
6
  from ..loggingw import loggingw
7
7
  from ...basics import tracebacks
8
8
 
9
+ from . import base, ssl_base
10
+
9
11
 
10
12
  class Sender:
11
13
  def __init__(
@@ -66,22 +68,32 @@ class Sender:
66
68
 
67
69
  # At this point the sending loop finished successfully
68
70
  self.logger.info(f"Sent the message to destination.")
69
- except ConnectionResetError as e:
70
- error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
71
- exception_error = tracebacks.get_as_string(one_line=True)
72
- error_message = (f"Socket Send: Error, Couldn't reach the server - Connection was reset | "
73
- f"{error_class_type}: {exception_error}")
74
- except (ssl.SSLEOFError, ssl.SSLZeroReturnError, ssl.SSLWantWriteError, TimeoutError) as e:
75
- error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
76
- exception_error = tracebacks.get_as_string(one_line=True)
77
- error_message = f"Socket Send: {error_class_type}: {exception_error}"
78
71
  except Exception as e:
72
+ source_tuple, destination_tuple = base.get_source_destination(self.ssl_socket)
73
+ source_address, source_port = source_tuple
74
+ destination_address, destination_port = destination_tuple
75
+ if self.ssl_socket.server_hostname:
76
+ destination_address = self.ssl_socket.server_hostname
77
+ destination: str = f'[{source_address}:{source_port}<->{destination_address}:{destination_port}]'
78
+
79
79
  error_class_type = str(type(e)).replace("<class '", '').replace("'>", '')
80
80
  exception_error = tracebacks.get_as_string(one_line=True)
81
+
81
82
  if 'ssl' in error_class_type.lower():
82
- error_message = f"Socket Send: SSL UNDOCUMENTED Exception: {error_class_type}{exception_error}"
83
+ if error_class_type in ['ssl.SSLEOFError', 'ssl.SSLZeroReturnError', 'ssl.SSLWantWriteError']:
84
+ error_message = f"Socket Send: {destination}: {error_class_type}: {exception_error}"
85
+ else:
86
+ error_message = (f"Socket Send: {destination}: "
87
+ f"SSL UNDOCUMENTED Exception: {error_class_type}{exception_error}")
83
88
  else:
84
- error_message = f"Socket Send: Error, UNDOCUMENTED Exception: {error_class_type}{exception_error}"
89
+ if error_class_type == 'ConnectionResetError':
90
+ error_message = (f"Socket Send: {destination}: "
91
+ f"Error, Couldn't reach the server - Connection was reset | "
92
+ f"{error_class_type}: {exception_error}")
93
+ elif error_class_type in ['TimeoutError']:
94
+ error_message = f"Socket Send: {destination}: {error_class_type}: {exception_error}"
95
+ else:
96
+ raise e
85
97
 
86
98
  if error_message:
87
99
  print_api(error_message, logger=self.logger, logger_method='error')
@@ -1,10 +1,12 @@
1
1
  import ssl
2
2
  from dataclasses import dataclass
3
3
 
4
- from . import certificator, creator
4
+ from ..loggingw import loggingw
5
5
  from ...domains import get_domain_without_first_subdomain_if_no_subdomain_return_as_is
6
6
  from ...print_api import print_api
7
7
 
8
+ from . import certificator, creator
9
+
8
10
 
9
11
  @dataclass
10
12
  class SNIReceivedParameters:
@@ -43,7 +45,8 @@ class SNISetup:
43
45
  forwarding_dns_service_ipv4_list___only_for_localhost: list,
44
46
  tls: bool,
45
47
  domain_from_dns_server: str = None,
46
- skip_extension_id_list: list = None
48
+ skip_extension_id_list: list = None,
49
+ exceptions_logger: loggingw.ExceptionCsvLogger = None
47
50
  ):
48
51
  self.ca_certificate_name = ca_certificate_name
49
52
  self.ca_certificate_filepath = ca_certificate_filepath
@@ -68,6 +71,7 @@ class SNISetup:
68
71
  self.domain_from_dns_server: str = domain_from_dns_server
69
72
  self.skip_extension_id_list = skip_extension_id_list
70
73
  self.tls = tls
74
+ self.exceptions_logger = exceptions_logger
71
75
 
72
76
  self.certificator_instance = None
73
77
 
@@ -154,7 +158,8 @@ class SNISetup:
154
158
  sni_create_server_certificate_for_each_domain=self.sni_create_server_certificate_for_each_domain,
155
159
  certificator_instance=self.certificator_instance,
156
160
  domain_from_dns_server=self.domain_from_dns_server,
157
- default_certificate_domain_list=self.default_certificate_domain_list
161
+ default_certificate_domain_list=self.default_certificate_domain_list,
162
+ exceptions_logger=self.exceptions_logger
158
163
  )
159
164
  ssl_context.set_servername_callback(
160
165
  sni_handler_instance.setup_sni_callback(print_kwargs=print_kwargs))
@@ -172,7 +177,8 @@ class SNIHandler:
172
177
  sni_create_server_certificate_for_each_domain: bool,
173
178
  certificator_instance: certificator.Certificator,
174
179
  domain_from_dns_server: str,
175
- default_certificate_domain_list: list
180
+ default_certificate_domain_list: list,
181
+ exceptions_logger: loggingw.ExceptionCsvLogger
176
182
  ):
177
183
  self.sni_use_default_callback_function_extended = sni_use_default_callback_function_extended
178
184
  self.sni_add_new_domains_to_default_server_certificate = sni_add_new_domains_to_default_server_certificate
@@ -180,6 +186,7 @@ class SNIHandler:
180
186
  self.certificator_instance = certificator_instance
181
187
  self.domain_from_dns_server: str = domain_from_dns_server
182
188
  self.default_certificate_domain_list = default_certificate_domain_list
189
+ self.exceptions_logger = exceptions_logger
183
190
 
184
191
  # noinspection PyTypeChecker
185
192
  self.sni_received_parameters: SNIReceivedParameters = None
@@ -202,18 +209,22 @@ class SNIHandler:
202
209
  sni_ssl_socket: ssl.SSLSocket,
203
210
  sni_destination_name: str,
204
211
  sni_ssl_context: ssl.SSLContext):
205
- # Set 'server_hostname' for the socket.
206
- sni_ssl_socket.server_hostname = sni_destination_name
207
-
208
- # If 'sni_execute_extended' was set to True.
209
- if self.sni_use_default_callback_function_extended:
210
- self.sni_received_parameters = SNIReceivedParameters(
211
- ssl_socket=sni_ssl_socket,
212
- destination_name=sni_destination_name,
213
- ssl_context=sni_ssl_context
214
- )
215
-
216
- self.sni_handle_extended(print_kwargs=print_kwargs)
212
+
213
+ try:
214
+ # Set 'server_hostname' for the socket.
215
+ sni_ssl_socket.server_hostname = sni_destination_name
216
+
217
+ # If 'sni_execute_extended' was set to True.
218
+ if self.sni_use_default_callback_function_extended:
219
+ self.sni_received_parameters = SNIReceivedParameters(
220
+ ssl_socket=sni_ssl_socket,
221
+ destination_name=sni_destination_name,
222
+ ssl_context=sni_ssl_context
223
+ )
224
+
225
+ self.sni_handle_extended(print_kwargs=print_kwargs)
226
+ except Exception as e:
227
+ self.exceptions_logger.write(e)
217
228
 
218
229
  return sni_handle
219
230
 
@@ -426,7 +426,6 @@ class SocketWrapper:
426
426
  listening_socket_list = self.listening_sockets
427
427
 
428
428
  while True:
429
- # noinspection PyBroadException
430
429
  try:
431
430
  # Using "select.select" which is currently the only API function that works on all
432
431
  # operating system types: Windows / Linux / BSD.
@@ -503,7 +502,8 @@ class SocketWrapper:
503
502
  domain_from_dns_server=domain_from_dns_server,
504
503
  forwarding_dns_service_ipv4_list___only_for_localhost=(
505
504
  self.forwarding_dns_service_ipv4_list___only_for_localhost),
506
- tls=is_tls
505
+ tls=is_tls,
506
+ exceptions_logger=self.exceptions_logger
507
507
  )
508
508
 
509
509
  ssl_client_socket, accept_error_message = \
@@ -538,7 +538,7 @@ class SocketWrapper:
538
538
  if not pass_function_reference_to_thread:
539
539
  before_socket_thread_worker(
540
540
  callable_function=reference_function_name, thread_args=thread_args,
541
- exception_logger=self.exceptions_logger)
541
+ exceptions_logger=self.exceptions_logger)
542
542
  # If 'pass_function_reference_to_thread' was set to 'True', execute the callable function reference
543
543
  # in a new thread.
544
544
  else:
@@ -552,11 +552,8 @@ class SocketWrapper:
552
552
  error_message=accept_error_message,
553
553
  host=domain_from_dns_server,
554
554
  process_name=process_name)
555
- except Exception:
556
- print_api("Undocumented exception in while loop of listening sockets.", error_type=True,
557
- logger_method="error", traceback_string=True, logger=self.logger)
558
- pass
559
- continue
555
+ except Exception as e:
556
+ self.exceptions_logger.write(e)
560
557
 
561
558
  def _send_accepted_socket_to_thread(self, thread_function_name, reference_args=()):
562
559
  # Creating thread for each socket
@@ -575,17 +572,17 @@ class SocketWrapper:
575
572
  def before_socket_thread_worker(
576
573
  callable_function: callable,
577
574
  thread_args: tuple,
578
- exception_logger: loggingw.ExceptionCsvLogger = None
575
+ exceptions_logger: loggingw.ExceptionCsvLogger = None
579
576
  ):
580
577
  """
581
578
  Function that will be executed before the thread is started.
582
579
  :param callable_function: callable, function that will be executed in the thread.
583
580
  :param thread_args: tuple, arguments that will be passed to the function.
584
- :param exception_logger: loggingw.ExceptionCsvLogger, logger object that will be used to log exceptions.
581
+ :param exceptions_logger: loggingw.ExceptionCsvLogger, logger object that will be used to log exceptions.
585
582
  :return:
586
583
  """
587
584
 
588
585
  try:
589
586
  callable_function(*thread_args)
590
587
  except Exception as e:
591
- exception_logger.write(e)
588
+ exceptions_logger.write(e)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.16.29
3
+ Version: 2.16.31
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=i8HvtTRZFtZFX7kwB4VqwPlkg-1D7OwfyNzJul477ZI,124
1
+ atomicshop/__init__.py,sha256=sCusnYw5eAOy-azyQImMCB9etQnC6WjnQr70CnWZluk,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
@@ -19,7 +19,7 @@ atomicshop/functions.py,sha256=pK8hoCE9z61PtWCxQJsda7YAphrLH1wxU5x-1QJP-sY,499
19
19
  atomicshop/get_process_list.py,sha256=8cxb7gKe9sl4R6H2yMi8J6oe-RkonTvCdKjRFqi-Fs4,6075
20
20
  atomicshop/get_process_name_cmd_dll.py,sha256=CtaSp3mgxxJKCCVW8BLx6BJNx4giCklU_T7USiCEwfc,5162
21
21
  atomicshop/hashing.py,sha256=Le8qGFyt3_wX-zGTeQShz7L2HL_b6nVv9PnawjglyHo,3474
22
- atomicshop/http_parse.py,sha256=wky-d3iRxS9hNoHXcOzXDvrFX0-DLWRSPYQ7DFf-Gs4,9618
22
+ atomicshop/http_parse.py,sha256=bIrJODFmumfI6uSwWkTtjtJWS-o40kn_eg7J9Mmwr20,10002
23
23
  atomicshop/inspect_wrapper.py,sha256=sGRVQhrJovNygHTydqJj0hxES-aB2Eg9KbIk3G31apw,11429
24
24
  atomicshop/ip_addresses.py,sha256=Hvi4TumEFoTEpKWaq5WNF-YzcRzt24IxmNgv-Mgax1s,1190
25
25
  atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
@@ -124,11 +124,11 @@ atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,21
124
124
  atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  atomicshop/mitm/config_static.py,sha256=ROAtbibSWSsF3BraUbhu-QO3MPIFqYY5KUKgsQbiSkk,7813
126
126
  atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
127
- atomicshop/mitm/connection_thread_worker.py,sha256=OIKaaVnewxtIMPEjwrJmQqiaIQWEq-pl2AfmEYTAGlc,16516
127
+ atomicshop/mitm/connection_thread_worker.py,sha256=fybUBcZckgF7TC_P1z2yIYGH6ATX7jQEfsQSBuddt2s,16531
128
128
  atomicshop/mitm/import_config.py,sha256=_nu8mgA-M4s6dZ8_QWx3x0aVb75upvsCuX_PIUg4X2w,8345
129
129
  atomicshop/mitm/initialize_engines.py,sha256=VyJE8QnzlgD3QbX5inz5o6rC3zQ3is9CeTL7-B10g1w,8292
130
- atomicshop/mitm/message.py,sha256=WcKnE102GImbl8N3f4NliCuahHpkqMB4e4XlD2BOrOY,1035
131
- atomicshop/mitm/mitm_main.py,sha256=nBSAibYOkRozrl4X1SBnof4eKs6LkjImAAhFF-UaOm8,22193
130
+ atomicshop/mitm/message.py,sha256=URR5JKSuAT8XmGIkyprEjlPW2GW4ef_gfUz_GgcFseE,2184
131
+ atomicshop/mitm/mitm_main.py,sha256=wEW0UAqxnn9kI4oO5zyNtG04Glmi3hR-C-0W6SpxVWY,22446
132
132
  atomicshop/mitm/recs_files.py,sha256=VjgtJF7vy365mBjctwB2bpDYoLMkEeogzF8kbb01dAk,2977
133
133
  atomicshop/mitm/shared_functions.py,sha256=jjCDZVQCwQ8hf9QNMe3T8W3ISkfZo4Mm2HtXOJLZYgI,1999
134
134
  atomicshop/mitm/statistic_analyzer.py,sha256=mBmwEe68WAjnIskGndQTRldnsAsDHuaOW0O7UXlM3Pc,26702
@@ -137,7 +137,7 @@ atomicshop/mitm/engines/create_module_template.py,sha256=tRjVSm1sD6FzML71Qbuwvit
137
137
  atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
138
138
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
139
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=RK2wviepP0oeq7zuLpgkvqvTJtc0r0a7hDGWdV0dGc4,657
140
- atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=gUQF1OFMBKLbvd5JhqLPURjD8j7NvQyg5SSmmLdFfWQ,4493
140
+ atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=xPc_5BGDubPfgNa4z8qBtm8MacDlas_yQNkfNsji46k,4677
141
141
  atomicshop/mitm/engines/__parent/responder___parent.py,sha256=7WQeR3UmMnN74bDwn-0nz2OfhXJ3-ClXpNGUFZ7wJUE,12004
142
142
  atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
143
  atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=57MEPZMAjTO6xBDZ-yt6lgGJyqRrP0Do5Gk_cgCiPns,2998
@@ -296,21 +296,21 @@ atomicshop/wrappers/socketw/accepter.py,sha256=hZZKVYlF3LOHQJsSIEKXZUf6QXXWm-Atq
296
296
  atomicshop/wrappers/socketw/base.py,sha256=evoOIxg5Xff3THJnrVX00D5HobaOpDp6_e_gso7TJmA,2191
297
297
  atomicshop/wrappers/socketw/certificator.py,sha256=3CpQKtcW68FSbH6LVSEZTqWBS6Yg_-3K0x4nFkId4UY,12236
298
298
  atomicshop/wrappers/socketw/creator.py,sha256=3_OraDkw2DAWZfoSdY3svCGMOIxpjLEEY7NxWd7M5P4,9873
299
- atomicshop/wrappers/socketw/dns_server.py,sha256=GhotsER4NfZ0k_jP5Fgzv1zzS9TSkmDQ71Sx6lBZ1xA,48953
299
+ atomicshop/wrappers/socketw/dns_server.py,sha256=F-t2ZOrMAS0hZ5AaoTsIEbe7jj0tUathp8gs4CTNDqM,48967
300
300
  atomicshop/wrappers/socketw/exception_wrapper.py,sha256=B-X5SHLSUIWToihH2MKnOB1F4A81_X0DpLLfnYKYbEc,7067
301
301
  atomicshop/wrappers/socketw/get_process.py,sha256=zKEqh98cB9UDLFhtxVpperfXsCjyIMNANHilDD06p0U,6094
302
302
  atomicshop/wrappers/socketw/receiver.py,sha256=XVvWOoeCo3vA0O5p19ryi-hcDIyx382WNG7WzMNVeYk,9322
303
- atomicshop/wrappers/socketw/sender.py,sha256=PBCUk7k2mjJaLRpB2ANjvWs_wR-Yqv_AjBQaeJ5KMKE,4521
304
- atomicshop/wrappers/socketw/sni.py,sha256=fVwyh3h9IqfLMnf4__bMIzcF4c-Kk9mlbDWMRXKN-ow,17155
303
+ atomicshop/wrappers/socketw/sender.py,sha256=5HPrgTS2pA1g-jbG1TUtR7drHT1Z_8UevlRCTwW7dgY,5007
304
+ atomicshop/wrappers/socketw/sni.py,sha256=J1kPnQ77XwKN1pO5aOI1c_VfhuivCm95OOaQxMpPuZ0,17627
305
305
  atomicshop/wrappers/socketw/socket_client.py,sha256=XC-YaqA1wu0rvWQ9Q99DWLxcycKPkPc72pSnflzalfo,20320
306
306
  atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
307
- atomicshop/wrappers/socketw/socket_wrapper.py,sha256=V9X_tK2w-roE9GF6rgmz1rDc54D3EZmLXLcNW2StEno,35614
307
+ atomicshop/wrappers/socketw/socket_wrapper.py,sha256=jOIux6eedupRtiEKQeaPSBt7xJbJixpBbK1zNcQUDqU,35451
308
308
  atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0LxIwBA4iVvU,2275
309
309
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=w1AH-zf4mBuT4euf28UKij9ihM-b1BRU9Qfby0QDdqI,2957
310
310
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
311
  atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
312
- atomicshop-2.16.29.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
313
- atomicshop-2.16.29.dist-info/METADATA,sha256=PIQz6ksXLRjwULJweIFjOJIeCSN-ej1dB48nyC5b17M,10473
314
- atomicshop-2.16.29.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
315
- atomicshop-2.16.29.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
316
- atomicshop-2.16.29.dist-info/RECORD,,
312
+ atomicshop-2.16.31.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
313
+ atomicshop-2.16.31.dist-info/METADATA,sha256=qf8gXgqyW9JhWKob2yEkM118Kt1OcfQyVeqTrz9nj-0,10473
314
+ atomicshop-2.16.31.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
315
+ atomicshop-2.16.31.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
316
+ atomicshop-2.16.31.dist-info/RECORD,,