#NEWLINE# def parse_session_info( server_handshake_bytes , client_handshake_bytes ) : #NEWLINE# #INDENT# '\n    Parse the TLS handshake from the client to the server to extract information\n    including the cipher suite selected, if compression is enabled, the\n    session id and if a new or reused session ticket exists.\n\n    :param server_handshake_bytes:\n        A byte string of the handshake data received from the server\n\n    :param client_handshake_bytes:\n        A byte string of the handshake data sent to the server\n\n    :return:\n        A dict with the following keys:\n         - "protocol": unicode string\n         - "cipher_suite": unicode string\n         - "compression": boolean\n         - "session_id": "new", "reused" or None\n         - "session_ticket: "new", "reused" or None\n    ' #NEWLINE# protocol = None #NEWLINE# cipher_suite = None #NEWLINE# compression = False #NEWLINE# session_id = None #NEWLINE# session_ticket = None #NEWLINE# server_session_id = None #NEWLINE# client_session_id = None #NEWLINE# for ( record_type , _ , record_data ) in _parse_tls_records ( server_handshake_bytes ) : #NEWLINE# #INDENT# if ( record_type != b'\x16' ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# for ( message_type , message_data ) in _parse_handshake_messages ( record_data ) : #NEWLINE# #INDENT# if ( message_type != b'\x02' ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# protocol = { #NEWLINE# #INDENT# b'\x03\x00' : 'SSLv3' , #NEWLINE# b'\x03\x01' : 'TLSv1' , #NEWLINE# b'\x03\x02' : 'TLSv1.1' , #NEWLINE# b'\x03\x03' : 'TLSv1.2' , #NEWLINE# b'\x03\x04' : 'TLSv1.3' , #NEWLINE# #UNINDENT# } [ message_data [ 0 : 2 ] ] #NEWLINE# session_id_length = int_from_bytes ( message_data [ 34 : 35 ] ) #NEWLINE# if ( session_id_length > 0 ) : #NEWLINE# #INDENT# server_session_id = message_data [ 35 : ( 35 + session_id_length ) ] #NEWLINE# #UNINDENT# cipher_suite_start = ( 35 + session_id_length ) #NEWLINE# cipher_suite_bytes = message_data [ cipher_suite_start : ( cipher_suite_start + 2 ) ] #NEWLINE# cipher_suite = CIPHER_SUITE_MAP [ cipher_suite_bytes ] #NEWLINE# compression_start = ( cipher_suite_start + 2 ) #NEWLINE# compression = ( message_data [ compression_start : ( compression_start + 1 ) ] != b'\x00' ) #NEWLINE# extensions_length_start = ( compression_start + 1 ) #NEWLINE# extensions_data = message_data [ extensions_data : ] #NEWLINE# for ( extension_type , extension_data ) in _parse_hello_extensions ( extensions_data ) : #NEWLINE# #INDENT# if ( extension_type == 35 ) : #NEWLINE# #INDENT# session_ticket = 'new' #NEWLINE# break #NEWLINE# #UNINDENT# #UNINDENT# break #NEWLINE# #UNINDENT# #UNINDENT# for ( record_type , _ , record_data ) in _parse_tls_records ( client_handshake_bytes ) : #NEWLINE# #INDENT# if ( record_type != b'\x16' ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# for ( message_type , message_data ) in _parse_handshake_messages ( record_data ) : #NEWLINE# #INDENT# if ( message_type != b'\x02' ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# session_id_length = int_from_bytes ( message_data [ 34 : 35 ] ) #NEWLINE# if ( session_id_length > 0 ) : #NEWLINE# #INDENT# client_session_id = message_data [ 35 : ( 35 + session_id_length ) ] #NEWLINE# #UNINDENT# cipher_suite_start = ( 35 + session_id_length ) #NEWLINE# cipher_suite_length = int_from_bytes ( message_data [ cipher_suite_start : ( cipher_suite_start + 2 ) ] ) #NEWLINE# compression_start = ( ( cipher_suite_start + 2 ) + cipher_suite_length ) #NEWLINE# compression_length = int_from_bytes ( message_data [ compression_start : ( compression_start + 1 ) ] ) #NEWLINE# if ( ( server_session_id is None ) and ( session_ticket is None ) ) : #NEWLINE# #INDENT# extensions_length_start = ( ( compression_start + 1 ) + compression_length ) #NEWLINE# extensions_data = message_data [ extensions_length_start : ] #NEWLINE# for ( extension_type , extension_data ) in _parse_hello_extensions ( extensions_data ) : #NEWLINE# #INDENT# if ( extension_type == 35 ) : #NEWLINE# #INDENT# session_ticket = 'reused' #NEWLINE# break #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# break #NEWLINE# #UNINDENT# #UNINDENT# if ( server_session_id is not None ) : #NEWLINE# #INDENT# if ( client_session_id is None ) : #NEWLINE# #INDENT# session_id = 'new' #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( client_session_id != server_session_id ) : #NEWLINE# #INDENT# session_id = 'new' #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# session_id = 'reused' #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# return { #NEWLINE# #INDENT# 'protocol' : protocol , #NEWLINE# 'cipher_suite' : cipher_suite , #NEWLINE# 'compression' : compression , #NEWLINE# 'session_id' : session_id , #NEWLINE# 'session_ticket' : session_ticket , #NEWLINE# #UNINDENT# }