Skip to content

Commit

Permalink
Fix JSON serialization in Python 2; fixes #246
Browse files Browse the repository at this point in the history
  • Loading branch information
nabla-c0d3 committed Oct 15, 2017
1 parent f0610b7 commit 39923bb
Showing 1 changed file with 31 additions and 21 deletions.
52 changes: 31 additions & 21 deletions sslyze/cli/json_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def __init__(self, file_to):
'sslyze_url': PROJECT_URL}

def command_line_parsed(self, available_plugins, args_command_list):
self._json_dict.update({'network_timeout': str(args_command_list.timeout),
'network_max_retries': str(args_command_list.nb_retries),
self._json_dict.update({'network_timeout': args_command_list.timeout,
'network_max_retries': args_command_list.nb_retries,
'invalid_targets': [],
'accepted_targets': []})

Expand All @@ -40,7 +40,9 @@ def scans_started(self):

def server_scan_completed(self, server_scan_result):
# type: (CompletedServerScan) -> None
server_scan_dict = {'server_info': server_scan_result.server_info.__dict__}
server_scan_dict = {'server_info': server_scan_result.server_info.__dict__.copy()}
for key, value in server_scan_dict['server_info'].items():
server_scan_dict['server_info'][key] = _object_to_json_dict(value)

dict_command_result = {}
for plugin_result in server_scan_result.plugin_result_list:
Expand All @@ -53,6 +55,10 @@ def server_scan_completed(self, server_scan_result):

if scan_command.get_cli_argument() in dict_command_result.keys():
raise ValueError('Received duplicate result for command {}'.format(scan_command))

for key, value in dict_result.items():
dict_result[key] = _object_to_json_dict(value)

dict_command_result[scan_command.get_cli_argument()] = dict_result

server_scan_dict['commands_results'] = dict_command_result
Expand All @@ -61,34 +67,38 @@ def server_scan_completed(self, server_scan_result):
def scans_completed(self, total_scan_time):
# type: (float) -> None
self._json_dict['total_scan_time'] = total_scan_time
json_out = json.dumps(self._json_dict, default=self._object_to_json_dict, sort_keys=True, indent=4,
json_out = json.dumps(self._json_dict, default=_object_to_json_dict, sort_keys=True, indent=4,
ensure_ascii=True)
if IS_PYTHON_2:
json_out = unicode(json_out)
self._file_to.write(json_out)

@staticmethod
def _object_to_json_dict(obj):
"""Convert an object to a dictionary suitable for the JSON output.
"""
if isinstance(obj, Enum):
# Properly serialize Enums (such as OpenSslVersionEnum)
result = obj.name
elif isinstance(obj, x509._Certificate):
# Properly serialize certificates; only return the PEM string
result = {'as_pem': obj.public_bytes(Encoding.PEM).decode('ascii'),
'hpkp_pin': CertificateUtils.get_hpkp_pin(obj),
'subject_name': CertificateUtils.get_name_as_short_text(obj.subject)}
elif isinstance(obj, object):

def _object_to_json_dict(obj):
"""Convert an object to a dictionary suitable for the JSON output.
"""
if isinstance(obj, Enum):
# Properly serialize Enums (such as OpenSslVersionEnum)
result = obj.name
elif isinstance(obj, x509._Certificate):
# Properly serialize certificates; only return the PEM string
result = {'as_pem': obj.public_bytes(Encoding.PEM).decode('ascii'),
'hpkp_pin': CertificateUtils.get_hpkp_pin(obj),
'subject_name': CertificateUtils.get_name_as_short_text(obj.subject)}
elif isinstance(obj, object):
if hasattr(obj, '__dict__'):
result = {}
for key, value in obj.__dict__.items():
# Remove private attributes
if key.startswith('_'):
continue

result[key] = value

result[key] = _object_to_json_dict(value)
else:
raise TypeError('Unknown type: {}'.format(repr(obj)))
# Simple object like a string
result = obj

else:
raise TypeError('Unknown type: {}'.format(repr(obj)))

return result
return result

0 comments on commit 39923bb

Please sign in to comment.