def from_stream(body): """Parse a Client Hello record from body. Body should start with the byte representation of an RFC 5246 struct ClientHello Returns a ClientHello and the number of bytes read from body Throws a struct.error or IndexError if there is not enough data to parse properly. """ version, index = Version.from_stream(body) random, read_amt = Random.from_stream(body[index:]) index += read_amt sessionid_length = struct.unpack_from("B", body, index)[0] index += 1 session_id, read_amt = ( parse.parse_tls_list( body[index:], sessionid_length, parse.parse_opaque)) index += read_amt cipher_length = struct.unpack_from("!H", body, index)[0] index += 2 ciphers, read_amt = ( parse.parse_tls_list( body[index:], cipher_length, Cipher.from_stream)) index += read_amt compression_length = struct.unpack_from("B", body, index)[0] index += 1 compression_methods, read_amt = ( parse.parse_tls_list( body[index:], compression_length, CompressionMethod.from_stream)) index += read_amt extensions = [] # Check if there are extensions present if index != len(body): extensions_length = struct.unpack_from("!H", body, index)[0] index += 2 extensions, read_amt = ( parse.parse_tls_list( body[index:], extensions_length, Extension.from_stream)) index += read_amt return ClientHello( version, random, session_id, ciphers, compression_methods, extensions), index
def from_stream(body): """Parse a Client Hello record from body. Body should start with the byte representation of an RFC 5246 struct ClientHello Returns a ClientHello and the number of bytes read from body Throws a struct.error or IndexError if there is not enough data to parse properly. """ version, index = Version.from_stream(body) random, read_amt = Random.from_stream(body[index:]) index += read_amt sessionid_length = struct.unpack_from("B", body, index)[0] index += 1 session_id, read_amt = (parse.parse_tls_list(body[index:], sessionid_length, parse.parse_opaque)) index += read_amt cipher_length = struct.unpack_from("!H", body, index)[0] index += 2 ciphers, read_amt = (parse.parse_tls_list(body[index:], cipher_length, Cipher.from_stream)) index += read_amt compression_length = struct.unpack_from("B", body, index)[0] index += 1 compression_methods, read_amt = (parse.parse_tls_list( body[index:], compression_length, CompressionMethod.from_stream)) index += read_amt extensions = [] # Check if there are extensions present if index != len(body): extensions_length = struct.unpack_from("!H", body, index)[0] index += 2 extensions, read_amt = (parse.parse_tls_list( body[index:], extensions_length, Extension.from_stream)) index += read_amt return ClientHello(version, random, session_id, ciphers, compression_methods, extensions), index
def from_stream(body): """Parse a SSLv2 Client Hello record from body. Body should start with the byte representation struct ClientHello starting at the version field. See http://tools.ietf.org/html/rfc5246#appendix-E.2 Returns a ClientHello and the number of bytes read from body Throws a struct.error or IndexError if there is not enough data to parse properly. """ version, index = Version.from_stream(body) ciphers_length, sessionid_length, random_length = struct.unpack_from( "!HHH", body, index) index += 6; if ciphers_length % 3 != 0: raise ValueError("Cipher spec list length not a multiple of 3") if ciphers_length + sessionid_length + random_length \ != len(body) - index: raise ValueError("Not enough data or too much data") if random_length < 16 or random_length > 32: raise ValueError("Random challenge too short or too long") ciphers, read_amt = ( parse.parse_tls_list( body[index:], ciphers_length, Cipher.from_stream)) index += read_amt session_id, read_amt = ( parse.parse_tls_list( body[index:], sessionid_length, parse.parse_opaque)) index += read_amt random = body[index:index + random_length] index += random_length return ClientHello( version, random, session_id, ciphers), index
def parse_data(type, data): data = "".join(data) # currently only parsing SNI if type != 0: return data if len(data) == 0: return "" # parse out the SNI list size = struct.unpack_from("!H", data, 0)[0] snis = parse.parse_tls_list(data[2:], size, _parse_sni)[0] for sni in snis: if sni[0] == 0: return sni[1] # Didn't parse out a server name? return ""
def parse_data(type, data): data = "".join(data) # currently only parsing SNI if type != 0: return data if len(data) == 0: return "" # parse out the SNI list size = struct.unpack_from("!H", data, 0)[0] snis = parse.parse_tls_list(data[2:], size, _parse_sni)[0] for sni in snis: if sni[0] == 0: return sni[1] # Didn't parse out a server name? return ""
def from_stream(body): """Parse a SSLv2 Client Hello record from body. Body should start with the byte representation struct ClientHello starting at the version field. See http://tools.ietf.org/html/rfc5246#appendix-E.2 Returns a ClientHello and the number of bytes read from body Throws a struct.error or IndexError if there is not enough data to parse properly. """ version, index = Version.from_stream(body) ciphers_length, sessionid_length, random_length = struct.unpack_from( "!HHH", body, index) index += 6 if ciphers_length % 3 != 0: raise ValueError("Cipher spec list length not a multiple of 3") if ciphers_length + sessionid_length + random_length \ != len(body) - index: raise ValueError("Not enough data or too much data") if random_length < 16 or random_length > 32: raise ValueError("Random challenge too short or too long") ciphers, read_amt = (parse.parse_tls_list(body[index:], ciphers_length, Cipher.from_stream)) index += read_amt session_id, read_amt = (parse.parse_tls_list(body[index:], sessionid_length, parse.parse_opaque)) index += read_amt random = body[index:index + random_length] index += random_length return ClientHello(version, random, session_id, ciphers), index
def from_stream(body): extension_type = struct.unpack_from("!H", body, 0)[0] data_length = struct.unpack_from("!H", body, 2)[0] extension_data, read_amt = parse.parse_tls_list( body[4:], data_length, parse.parse_opaque) return Extension(extension_type, list(extension_data)), 4 + read_amt
def _parse_sni(data): type = struct.unpack_from("B", data, 0)[0] size = struct.unpack_from("!H", data, 1)[0] name = parse.parse_tls_list(data[3:], size, parse.parse_opaque)[0] return (type, "".join(name)), size + 3
def from_stream(body): # length is 24 bits, pad so struct will parse it as an int num_certificates = struct.unpack_from("!I", "\x00" + body[:3])[0] certificates, read_amt = parse.parse_tls_list(body[3:], num_certificates, Certificate._parse_certificate) return Certificate(certificates), read_amt + 3
def _parse_sni(data): type = struct.unpack_from("B", data, 0)[0] size = struct.unpack_from("!H", data, 1)[0] name = parse.parse_tls_list(data[3:], size, parse.parse_opaque)[0] return (type, "".join(name)), size + 3
def from_stream(body): extension_type = struct.unpack_from("!H", body, 0)[0] data_length = struct.unpack_from("!H", body, 2)[0] extension_data, read_amt = parse.parse_tls_list( body[4:], data_length, parse.parse_opaque) return Extension(extension_type, list(extension_data)), 4 + read_amt
def from_stream(body): # length is 24 bits, pad so struct will parse it as an int num_certificates = struct.unpack_from("!I", "\x00" + body[:3])[0] certificates, read_amt = parse.parse_tls_list( body[3:], num_certificates, Certificate._parse_certificate) return Certificate(certificates), read_amt + 3