Package dpkt :: Module ssl
[hide private]
[frames] | no frames]

Source Code for Module dpkt.ssl

  1  # $Id: ssl.py 90 2014-04-02 22:06:23Z andrewflnr@gmail.com $ 
  2  # Portion Copyright 2012 Google Inc. All rights reserved. 
  3  # -*- coding: utf-8 -*- 
  4  """Secure Sockets Layer / Transport Layer Security.""" 
  5  from __future__ import absolute_import 
  6   
  7  import struct 
  8  import binascii 
  9   
 10  from . import dpkt 
 11  from . import ssl_ciphersuites 
12 13 # 14 # Note from April 2011: cde...@gmail.com added code that parses SSL3/TLS messages more in depth. 15 # 16 # Jul 2012: afleenor@google.com modified and extended SSL support further. 17 # 18 19 # SSL 2.0 is deprecated in RFC 6176 20 -class SSL2(dpkt.Packet):
21 __hdr__ = ( 22 ('len', 'H', 0), 23 ('msg', 's', ''), 24 ('pad', 's', ''), 25 ) 26
27 - def unpack(self, buf):
28 dpkt.Packet.unpack(self, buf) 29 if self.len & 0x8000: 30 n = self.len = self.len & 0x7FFF 31 self.msg, self.data = self.data[:n], self.data[n:] 32 else: 33 n = self.len = self.len & 0x3FFF 34 padlen = ord(self.data[0]) 35 self.msg = self.data[1:1 + n] 36 self.pad = self.data[1 + n:1 + n + padlen] 37 self.data = self.data[1 + n + padlen:]
38
39 40 # SSL 3.0 is deprecated in RFC 7568 41 # Use class TLS for >= SSL 3.0 42 -class TLS(dpkt.Packet):
43 __hdr__ = ( 44 ('type', 'B', ''), 45 ('version', 'H', ''), 46 ('len', 'H', ''), 47 ) 48
49 - def __init__(self, *args, **kwargs):
50 self.records = [] 51 dpkt.Packet.__init__(self, *args, **kwargs)
52 53
54 - def unpack(self, buf):
55 dpkt.Packet.unpack(self, buf) 56 pointer = 0 57 while len(self.data[pointer:]) > 0: 58 end = pointer + 5 + struct.unpack("!H", buf[pointer+3:pointer+5])[0] 59 self.records.append(TLSRecord(buf[pointer:end])) 60 pointer = end 61 self.data = self.data[pointer:]
62 63 64 # SSLv3/TLS versions 65 SSL3_V = 0x0300 66 TLS1_V = 0x0301 67 TLS11_V = 0x0302 68 TLS12_V = 0x0303 69 70 ssl3_versions_str = { 71 SSL3_V: 'SSL3', 72 TLS1_V: 'TLS 1.0', 73 TLS11_V: 'TLS 1.1', 74 TLS12_V: 'TLS 1.2' 75 } 76 77 SSL3_VERSION_BYTES = set((b'\x03\x00', b'\x03\x01', b'\x03\x02', b'\x03\x03')) 78 79 80 # Alert levels 81 SSL3_AD_WARNING = 1 82 SSL3_AD_FATAL = 2 83 alert_level_str = { 84 SSL3_AD_WARNING: 'SSL3_AD_WARNING', 85 SSL3_AD_FATAL: 'SSL3_AD_FATAL' 86 } 87 88 # SSL3 alert descriptions 89 SSL3_AD_CLOSE_NOTIFY = 0 90 SSL3_AD_UNEXPECTED_MESSAGE = 10 # fatal 91 SSL3_AD_BAD_RECORD_MAC = 20 # fatal 92 SSL3_AD_DECOMPRESSION_FAILURE = 30 # fatal 93 SSL3_AD_HANDSHAKE_FAILURE = 40 # fatal 94 SSL3_AD_NO_CERTIFICATE = 41 95 SSL3_AD_BAD_CERTIFICATE = 42 96 SSL3_AD_UNSUPPORTED_CERTIFICATE = 43 97 SSL3_AD_CERTIFICATE_REVOKED = 44 98 SSL3_AD_CERTIFICATE_EXPIRED = 45 99 SSL3_AD_CERTIFICATE_UNKNOWN = 46 100 SSL3_AD_ILLEGAL_PARAMETER = 47 # fatal 101 102 # TLS1 alert descriptions 103 TLS1_AD_DECRYPTION_FAILED = 21 104 TLS1_AD_RECORD_OVERFLOW = 22 105 TLS1_AD_UNKNOWN_CA = 48 # fatal 106 TLS1_AD_ACCESS_DENIED = 49 # fatal 107 TLS1_AD_DECODE_ERROR = 50 # fatal 108 TLS1_AD_DECRYPT_ERROR = 51 109 TLS1_AD_EXPORT_RESTRICTION = 60 # fatal 110 TLS1_AD_PROTOCOL_VERSION = 70 # fatal 111 TLS1_AD_INSUFFICIENT_SECURITY = 71 # fatal 112 TLS1_AD_INTERNAL_ERROR = 80 # fatal 113 TLS1_AD_USER_CANCELLED = 90 114 TLS1_AD_NO_RENEGOTIATION = 100 115 # /* codes 110-114 are from RFC3546 */ 116 TLS1_AD_UNSUPPORTED_EXTENSION = 110 117 TLS1_AD_CERTIFICATE_UNOBTAINABLE = 111 118 TLS1_AD_UNRECOGNIZED_NAME = 112 119 TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE = 113 120 TLS1_AD_BAD_CERTIFICATE_HASH_VALUE = 114 121 TLS1_AD_UNKNOWN_PSK_IDENTITY = 115 # fatal 122 123 124 # Mapping alert types to strings 125 alert_description_str = { 126 SSL3_AD_CLOSE_NOTIFY: 'SSL3_AD_CLOSE_NOTIFY', 127 SSL3_AD_UNEXPECTED_MESSAGE: 'SSL3_AD_UNEXPECTED_MESSAGE', 128 SSL3_AD_BAD_RECORD_MAC: 'SSL3_AD_BAD_RECORD_MAC', 129 SSL3_AD_DECOMPRESSION_FAILURE: 'SSL3_AD_DECOMPRESSION_FAILURE', 130 SSL3_AD_HANDSHAKE_FAILURE: 'SSL3_AD_HANDSHAKE_FAILURE', 131 SSL3_AD_NO_CERTIFICATE: 'SSL3_AD_NO_CERTIFICATE', 132 SSL3_AD_BAD_CERTIFICATE: 'SSL3_AD_BAD_CERTIFICATE', 133 SSL3_AD_UNSUPPORTED_CERTIFICATE: 'SSL3_AD_UNSUPPORTED_CERTIFICATE', 134 SSL3_AD_CERTIFICATE_REVOKED: 'SSL3_AD_CERTIFICATE_REVOKED', 135 SSL3_AD_CERTIFICATE_EXPIRED: 'SSL3_AD_CERTIFICATE_EXPIRED', 136 SSL3_AD_CERTIFICATE_UNKNOWN: 'SSL3_AD_CERTIFICATE_UNKNOWN', 137 SSL3_AD_ILLEGAL_PARAMETER: 'SSL3_AD_ILLEGAL_PARAMETER', 138 TLS1_AD_DECRYPTION_FAILED: 'TLS1_AD_DECRYPTION_FAILED', 139 TLS1_AD_RECORD_OVERFLOW: 'TLS1_AD_RECORD_OVERFLOW', 140 TLS1_AD_UNKNOWN_CA: 'TLS1_AD_UNKNOWN_CA', 141 TLS1_AD_ACCESS_DENIED: 'TLS1_AD_ACCESS_DENIED', 142 TLS1_AD_DECODE_ERROR: 'TLS1_AD_DECODE_ERROR', 143 TLS1_AD_DECRYPT_ERROR: 'TLS1_AD_DECRYPT_ERROR', 144 TLS1_AD_EXPORT_RESTRICTION: 'TLS1_AD_EXPORT_RESTRICTION', 145 TLS1_AD_PROTOCOL_VERSION: 'TLS1_AD_PROTOCOL_VERSION', 146 TLS1_AD_INSUFFICIENT_SECURITY: 'TLS1_AD_INSUFFICIENT_SECURITY', 147 TLS1_AD_INTERNAL_ERROR: 'TLS1_AD_INTERNAL_ERROR', 148 TLS1_AD_USER_CANCELLED: 'TLS1_AD_USER_CANCELLED', 149 TLS1_AD_NO_RENEGOTIATION: 'TLS1_AD_NO_RENEGOTIATION', 150 TLS1_AD_UNSUPPORTED_EXTENSION: 'TLS1_AD_UNSUPPORTED_EXTENSION', 151 TLS1_AD_CERTIFICATE_UNOBTAINABLE: 'TLS1_AD_CERTIFICATE_UNOBTAINABLE', 152 TLS1_AD_UNRECOGNIZED_NAME: 'TLS1_AD_UNRECOGNIZED_NAME', 153 TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: 'TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE', 154 TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: 'TLS1_AD_BAD_CERTIFICATE_HASH_VALUE', 155 TLS1_AD_UNKNOWN_PSK_IDENTITY: 'TLS1_AD_UNKNOWN_PSK_IDENTITY' 156 } 157 158 159 # struct format strings for parsing buffer lengths 160 # don't forget, you have to pad a 3-byte value with \x00 161 _SIZE_FORMATS = ['!B', '!H', '!I', '!I']
162 163 164 -def parse_variable_array(buf, lenbytes):
165 """ 166 Parse an array described using the 'Type name<x..y>' syntax from the spec 167 Read a length at the start of buf, and returns that many bytes 168 after, in a tuple with the TOTAL bytes consumed (including the size). This 169 does not check that the array is the right length for any given datatype. 170 """ 171 # first have to figure out how to parse length 172 assert lenbytes <= 4 # pretty sure 4 is impossible, too 173 size_format = _SIZE_FORMATS[lenbytes - 1] 174 padding = b'\x00' if lenbytes == 3 else b'' 175 # read off the length 176 size = struct.unpack(size_format, padding + buf[:lenbytes])[0] 177 # read the actual data 178 data = buf[lenbytes:lenbytes + size] 179 # if len(data) != size: insufficient data 180 return data, size + lenbytes
181
182 183 -def parse_extensions(buf):
184 """ 185 Parse TLS extensions in passed buf. Returns an ordered list of extension tuples with 186 ordinal extension type as first value and extension data as second value. 187 Passed buf must start with the 2-byte extensions length TLV. 188 http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml 189 """ 190 extensions_length = struct.unpack('!H', buf[:2])[0] 191 extensions = [] 192 193 pointer = 2 194 while pointer < extensions_length: 195 ext_type = struct.unpack('!H', buf[pointer:pointer+2])[0] 196 pointer += 2 197 ext_data, parsed = parse_variable_array(buf[pointer:], 2) 198 extensions.append((ext_type, ext_data)) 199 pointer += parsed 200 return extensions
201
202 203 -class SSL3Exception(Exception):
204 pass
205
206 207 -class TLSRecord(dpkt.Packet):
208 209 """ 210 SSLv3 or TLSv1+ packet. 211 212 In addition to the fields specified in the header, there are 213 compressed and decrypted fields, indicating whether, in the language 214 of the spec, this is a TLSPlaintext, TLSCompressed, or 215 TLSCiphertext. The application will have to figure out when it's 216 appropriate to change these values. 217 """ 218 219 __hdr__ = ( 220 ('type', 'B', 0), 221 ('version', 'H', 0), 222 ('length', 'H', 0), 223 ) 224
225 - def __init__(self, *args, **kwargs):
226 # assume plaintext unless specified otherwise in arguments 227 self.compressed = kwargs.pop('compressed', False) 228 self.encrypted = kwargs.pop('encrypted', False) 229 # parent constructor 230 dpkt.Packet.__init__(self, *args, **kwargs) 231 # make sure length and data are consistent 232 self.length = len(self.data)
233
234 - def unpack(self, buf):
235 dpkt.Packet.unpack(self, buf) 236 header_length = self.__hdr_len__ 237 self.data = buf[header_length:header_length + self.length] 238 # make sure buffer was long enough 239 if len(self.data) != self.length: 240 raise dpkt.NeedData('TLSRecord data was too short.') 241 # assume compressed and encrypted when it's been parsed from 242 # raw data 243 self.compressed = True 244 self.encrypted = True
245
246 247 -class TLSChangeCipherSpec(dpkt.Packet):
248 249 """ 250 ChangeCipherSpec message is just a single byte with value 1 251 """ 252 253 __hdr__ = (('type', 'B', 1),)
254
255 256 -class TLSAppData(str):
257 258 """ 259 As far as TLSRecord is concerned, AppData is just an opaque blob. 260 """ 261 262 pass
263
264 265 -class TLSAlert(dpkt.Packet):
266 __hdr__ = ( 267 ('level', 'B', 1), 268 ('description', 'B', 0), 269 )
270
271 272 -class TLSHelloRequest(dpkt.Packet):
273 __hdr__ = tuple()
274
275 276 -class TLSClientHello(dpkt.Packet):
277 __hdr__ = ( 278 ('version', 'H', 0x0301), 279 ('random', '32s', '\x00' * 32), 280 ) # the rest is variable-length and has to be done manually 281
282 - def unpack(self, buf):
283 dpkt.Packet.unpack(self, buf) 284 # now session, cipher suites, extensions are in self.data 285 self.session_id, pointer = parse_variable_array(self.data, 1) 286 # print 'pointer',pointer 287 # handle ciphersuites 288 ciphersuites, parsed = parse_variable_array(self.data[pointer:], 2) 289 pointer += parsed 290 self.num_ciphersuites = len(ciphersuites) / 2 291 # check len(ciphersuites) % 2 == 0 ? 292 # compression methods 293 compression_methods, parsed = parse_variable_array( 294 self.data[pointer:], 1) 295 pointer += parsed 296 self.num_compression_methods = parsed - 1 297 self.compression_methods = map(ord, compression_methods) 298 # Parse extensions if present 299 if len(self.data[pointer:]) >= 6: 300 self.extensions = parse_extensions(self.data[pointer:])
301
302 303 -class TLSServerHello(dpkt.Packet):
304 __hdr__ = ( 305 ('version', 'H', '0x0301'), 306 ('random', '32s', '\x00' * 32), 307 ) # session is variable, forcing rest to be manual 308
309 - def unpack(self, buf):
310 try: 311 dpkt.Packet.unpack(self, buf) 312 self.session_id, pointer = parse_variable_array(self.data, 1) 313 # single cipher suite 314 self.cipher_suite = struct.unpack('!H', self.data[pointer:pointer + 2])[0] 315 pointer += 2 316 # single compression method 317 self.compression = struct.unpack('!B', self.data[pointer:pointer + 1])[0] 318 pointer += 1 319 # Parse extensions if present 320 if len(self.data[pointer:]) >= 6: 321 self.extensions = parse_extensions(self.data[pointer:]) 322 except struct.error: 323 # probably data too short 324 raise dpkt.NeedData
325
326 327 -class TLSCertificate(dpkt.Packet):
328 __hdr__ = tuple() 329
330 - def unpack(self, buf):
331 try: 332 dpkt.Packet.unpack(self, buf) 333 all_certs, all_certs_len = parse_variable_array(self.data, 3) 334 self.certificates = [] 335 pointer = 3 336 while pointer < all_certs_len: 337 cert, parsed = parse_variable_array(self.data[pointer:], 3) 338 self.certificates.append((cert)) 339 pointer += parsed 340 except struct.error: 341 raise dpkt.NeedData
342
343 344 -class TLSUnknownHandshake(dpkt.Packet):
345 __hdr__ = tuple()
346 347 348 TLSServerKeyExchange = TLSUnknownHandshake 349 TLSCertificateRequest = TLSUnknownHandshake 350 TLSServerHelloDone = TLSUnknownHandshake 351 TLSCertificateVerify = TLSUnknownHandshake 352 TLSClientKeyExchange = TLSUnknownHandshake 353 TLSFinished = TLSUnknownHandshake 354 355 356 # mapping of handshake type ids to their names 357 # and the classes that implement them 358 HANDSHAKE_TYPES = { 359 0: ('HelloRequest', TLSHelloRequest), 360 1: ('ClientHello', TLSClientHello), 361 2: ('ServerHello', TLSServerHello), 362 11: ('Certificate', TLSCertificate), 363 12: ('ServerKeyExchange', TLSServerKeyExchange), 364 13: ('CertificateRequest', TLSCertificateRequest), 365 14: ('ServerHelloDone', TLSServerHelloDone), 366 15: ('CertificateVerify', TLSCertificateVerify), 367 16: ('ClientKeyExchange', TLSClientKeyExchange), 368 20: ('Finished', TLSFinished), 369 }
370 371 372 -class TLSHandshake(dpkt.Packet):
373 374 """ 375 A TLS Handshake message 376 377 This goes for all messages encapsulated in the Record layer, but especially 378 important for handshakes and app data: A message may be spread across a 379 number of TLSRecords, in addition to the possibility of there being more 380 than one in a given Record. You have to put together the contents of 381 TLSRecord's yourself. 382 """ 383 384 # struct.unpack can't handle the 3-byte int, so we parse it as bytes 385 # (and store it as bytes so dpkt doesn't get confused), and turn it into 386 # an int in a user-facing property 387 __hdr__ = ( 388 ('type', 'B', 0), 389 ('length_bytes', '3s', 0), 390 ) 391
392 - def unpack(self, buf):
393 dpkt.Packet.unpack(self, buf) 394 # Wait, might there be more than one message of self.type? 395 embedded_type = HANDSHAKE_TYPES.get(self.type, None) 396 if embedded_type is None: 397 raise SSL3Exception('Unknown or invalid handshake type %d' % 398 self.type) 399 # only take the right number of bytes 400 self.data = self.data[:self.length] 401 if len(self.data) != self.length: 402 raise dpkt.NeedData 403 # get class out of embedded_type tuple 404 self.data = embedded_type[1](self.data)
405 406 @property
407 - def length(self):
408 return struct.unpack('!I', b'\x00' + self.length_bytes)[0]
409 410 411 RECORD_TYPES = { 412 20: TLSChangeCipherSpec, 413 21: TLSAlert, 414 22: TLSHandshake, 415 23: TLSAppData, 416 }
417 418 419 -class SSLFactory(object):
420 - def __new__(cls, buf):
421 v = buf[1:3] 422 if v in SSL3_VERSION_BYTES: 423 return TLSRecord(buf) 424 # SSL2 has no characteristic header or magic bytes, so we just assume 425 # that the msg is an SSL2 msg if it is not detected as SSL3+ 426 return SSL2(buf)
427
428 429 -def tls_multi_factory(buf):
430 """ 431 Attempt to parse one or more TLSRecord's out of buf 432 433 Args: 434 buf: string containing SSL/TLS messages. May have an incomplete record 435 on the end 436 437 Returns: 438 [TLSRecord] 439 int, total bytes consumed, != len(buf) if an incomplete record was left at 440 the end. 441 442 Raises SSL3Exception. 443 """ 444 i, n = 0, len(buf) 445 msgs = [] 446 while i < n: 447 v = buf[i + 1:i + 3] 448 if v in SSL3_VERSION_BYTES: 449 try: 450 msg = TLSRecord(buf[i:]) 451 msgs.append(msg) 452 except dpkt.NeedData: 453 break 454 else: 455 raise SSL3Exception('Bad TLS version in buf: %r' % buf[i:i + 5]) 456 i += len(msg) 457 return msgs, i
458 459 _hexdecode = binascii.a2b_hex
460 461 462 -class TestTLS(object):
463 464 """ 465 Test basic TLS functionality. 466 Test that each TLSRecord is correctly discovered and added to TLS.records 467 """ 468 469 @classmethod
470 - def setup_class(cls):
471 cls.p = TLS(_hexdecode('1603000206010002020303585c2ff72a6599498771f59514f10af68c68f9ef30d0dadc9e1af64d1091476a000084c02bc02cc086c087c009c023c00ac024c072c073c008c007c02fc030c08ac08bc013c027c014c028c076c077c012c011009c009dc07ac07b002f003c0035003d004100ba008400c0000a00050004009e009fc07cc07d003300670039006b004500be008800c4001600a200a3c080c081003200400038006a004400bd008700c3001300660100015500050005010000000000000011000f00000c7777772e69616e612e6f7267ff0100010000230000000a000c000a00130015001700180019000b00020100000d001c001a0401040204030501050306010603030103020303020102020203001500f400f20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
472
473 - def test_records_length(self):
474 assert (len(self.p.records) == 1)
475
476 - def test_record_type(self):
477 assert (self.p.records[0].type == 22)
478
479 - def test_record_version(self):
480 assert (self.p.records[0].version == 768)
481
482 483 -class TestTLSRecord(object):
484 485 """ 486 Test basic TLSRecord functionality 487 For this test, the contents of the record doesn't matter, since we're not parsing the next layer. 488 """ 489 490 @classmethod
491 - def setup_class(cls):
492 # add some extra data, to make sure length is parsed correctly 493 cls.p = TLSRecord(b'\x17\x03\x01\x00\x08abcdefghzzzzzzzzzzz')
494
495 - def test_content_type(self):
496 assert (self.p.type == 23)
497
498 - def test_version(self):
499 assert (self.p.version == 0x0301)
500
501 - def test_length(self):
502 assert (self.p.length == 8)
503
504 - def test_data(self):
505 assert (self.p.data == b'abcdefgh')
506
507 - def test_initial_flags(self):
508 assert (self.p.compressed == True) 509 assert (self.p.encrypted == True)
510
511 - def test_repack(self):
512 p2 = TLSRecord(type=23, version=0x0301, data=b'abcdefgh') 513 assert (p2.type == 23) 514 assert (p2.version == 0x0301) 515 assert (p2.length == 8) 516 assert (p2.data == b'abcdefgh') 517 assert (p2.pack() == self.p.pack())
518
519 - def test_total_length(self):
520 # that len(p) includes header 521 assert (len(self.p) == 13)
522
524 import pytest 525 pytest.raises(dpkt.NeedData, TLSRecord, b'\x16\x03\x01\x00\x10abc')
526
527 528 -class TestTLSChangeCipherSpec(object):
529 530 """It's just a byte. This will be quick, I promise""" 531 532 @classmethod
533 - def setup_class(cls):
534 cls.p = TLSChangeCipherSpec(b'\x01')
535
536 - def test_parses(self):
537 assert (self.p.type == 1)
538
539 - def test_total_length(self):
540 assert (len(self.p) == 1)
541
542 543 -class TestTLSAppData(object):
544 545 """AppData is basically just a string""" 546
547 - def test_value(self):
548 d = TLSAppData('abcdefgh') 549 assert (d == 'abcdefgh')
550
551 552 -class TestTLSHandshake(object):
553 @classmethod
554 - def setup_class(cls):
555 cls.h = TLSHandshake(b'\x00\x00\x00\x01\xff')
556
558 assert (isinstance(self.h.data, TLSHelloRequest) == True)
559
560 - def test_length(self):
561 assert (self.h.length == 0x01)
562
563 - def test_raises_need_data(self):
564 import pytest 565 pytest.raises(dpkt.NeedData, TLSHandshake, b'\x00\x00\x01\x01')
566
567 568 -class TestClientHello(object):
569 570 """This data is extracted from and verified by Wireshark""" 571 572 @classmethod
573 - def setup_class(cls):
574 cls.data = _hexdecode( 575 b"01000199" # handshake header 576 b"0301" # version 577 b"5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d" # rand 578 b"2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1" # session id 579 # cipher suites 580 b"005400ffc00ac0140088008700390038c00fc00500840035c007c009c011c0130045004400330032c00cc00ec002c0040096004100050004002fc008c01200160013c00dc003feff000ac006c010c00bc00100020001" 581 b"0100" # compresssion methods 582 # extensions 583 b"00fc0000000e000c0000096c6f63616c686f7374000a00080006001700180019000b00020100002300d0a50b2e9f618a9ea9bf493ef49b421835cd2f6b05bbe1179d8edf70d58c33d656e8696d36d7e7e0b9d3ecc0e4de339552fa06c64c0fcb550a334bc43944e2739ca342d15a9ebbe981ac87a0d38160507d47af09bdc16c5f0ee4cdceea551539382333226048a026d3a90a0535f4a64236467db8fee22b041af986ad0f253bc369137cd8d8cd061925461d7f4d7895ca9a4181ab554dad50360ac31860e971483877c9335ac1300c5e78f3e56f3b8e0fc16358fcaceefd5c8d8aaae7b35be116f8832856ca61144fcdd95e071b94d0cf7233740000" 584 b"FFFFFFFFFFFFFFFF") # random garbage 585 cls.p = TLSHandshake(cls.data)
586
588 """Make sure the correct class was constructed""" 589 # print self.p 590 assert (isinstance(self.p.data, TLSClientHello) == True)
591 592 # def testClientDateCorrect(self): 593 # self.assertEqual(self.p.random_unixtime, 1342710284) 594
596 assert (self.p.data.random == _hexdecode(b'5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d'))
597
598 - def test_cipher_suite_length(self):
599 # we won't bother testing the identity of each cipher suite in the list. 600 assert (self.p.data.num_ciphersuites == 42)
601 # self.assertEqual(len(self.p.ciphersuites), 42) 602
603 - def test_session_id(self):
604 assert (self.p.data.session_id == _hexdecode(b'09bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1'))
605
606 - def test_compression_methods(self):
607 assert (self.p.data.num_compression_methods == 1)
608
609 - def test_total_length(self):
610 assert (len(self.p) == 413)
611
612 613 -class TestServerHello(object):
614 615 """Again, from Wireshark""" 616 617 @classmethod
618 - def setup_class(cls):
619 cls.data = _hexdecode( 620 b'0200004d03015008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed10002000005ff01000100') 621 cls.p = TLSHandshake(cls.data)
622
623 - def test_constructed(self):
624 assert (isinstance(self.p.data, TLSServerHello) == True)
625 626 # def testDateCorrect(self): 627 # self.assertEqual(self.p.random_unixtime, 1342710284) 628
629 - def test_random_correct(self):
630 assert (self.p.data.random == _hexdecode(b'5008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd'))
631
632 - def test_cipher_suite(self):
633 assert (ssl_ciphersuites.BY_CODE[self.p.data.cipher_suite].name == 'TLS_RSA_WITH_NULL_SHA')
634
635 - def test_total_length(self):
636 assert (len(self.p) == 81)
637
638 639 -class TestTLSCertificate(object):
640 641 """We use a 2016 certificate record from iana.org as test data.""" 642 643 @classmethod
644 - def setup_class(cls):
645 cls.p = TLSHandshake(_hexdecode('0b000b45000b42000687308206833082056ba003020102021009cabbe2191c8f569dd4b6dd250f21d8300d06092a864886f70d01010b05003070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e636520536572766572204341301e170d3134313032373030303030305a170d3138303130333132303030305a3081a3310b3009060355040613025553311330110603550408130a43616c69666f726e6961311430120603550407130b4c6f7320416e67656c6573313c303a060355040a1333496e7465726e657420436f72706f726174696f6e20666f722041737369676e6564204e616d657320616e64204e756d6265727331163014060355040b130d4954204f7065726174696f6e733113301106035504030c0a2a2e69616e612e6f726730820222300d06092a864886f70d01010105000382020f003082020a02820201009dbdfddeb5cae53a559747e2fda63728e4aba60f18b79a69f03310bf0164e5ee7db6b15bf56df23fddbae6a1bb38449b8c883f18102bbd8bb655ac0e2dac2ee3ed5cf4315868d2c598068284854b24894dcd4bd37811f0ad3a282cd4b4e599ffd07d8d2d3f2478554f81020b320ee12f44948e2ea1edbc990b830ca5cca6b4a839fb27b51850c9847eac74f26609eb24365b9751fb1c3208f56913bacbcae49201347c78b7e54a9d99979404c37f00fb65db849fd75e3a68770c30f2abe65b33256fb59b450050b00d8139d4d80d36f7bc46daf303e48f0f0791b2fdd72ec60b2cb3ad533c3f288c9c194e49337a69c496731f086d4f1f9825900713e2a551d05cb6057567850d91e6001c4ce27176f0957873a95b880acbec19e7bd9bcf1286d0452b73789c41905dd470971cd73aea52c77b080cd779af58234f337225c26f87a8c13e2a65e9dd4e03a5b41d7e06b3353f38129b2327a531ec9627a21dc423733aa029d4989448ba3322891c1a5690ddf2d25c8ec8aaa894b14aa92130c6b6d969a21ff671b60c4c923a94a93ea1dd0492c93393ca6edd61f33ca77e9208d01d6bd15107662ec088733df4c876a7e1608b82973a0f7592e84ed15579d181e79024ae8a7e4b9f0078eb2005b23f9d09a1df1bbc7de2a5a6085a3646d9fadb0e9da273a5f403cdd42831ce6f0ca46889585602bb8bc36bb3be861ff6d1a62e350203010001a38201e3308201df301f0603551d230418301680145168ff90af0207753cccd9656462a212b859723b301d0603551d0e04160414c7d0acef898b20e4b914668933032394f6bf3a61301f0603551d1104183016820a2a2e69616e612e6f7267820869616e612e6f7267300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230750603551d1f046e306c3034a032a030862e687474703a2f2f63726c332e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c3034a032a030862e687474703a2f2f63726c342e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c30420603551d20043b3039303706096086480186fd6c0101302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f43505330818306082b0601050507010104773075302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304d06082b060105050730028641687474703a2f2f636163657274732e64696769636572742e636f6d2f446967694365727453484132486967684173737572616e636553657276657243412e637274300c0603551d130101ff04023000300d06092a864886f70d01010b0500038201010070314c38e7c02fd80810500b9df6dae85de9b23e29fbd68bfdb5f23411c89acfaf9ae05af9123a8aa6bce6954a4e68dc7cfc480a65d76f229c4bd5f5674b0c9ac6d06a37a1a1c145c3956120b8efe67c887ab4ff7d6aa950ff3698f27c4a19d59d93a39aca5a7b6d6c75e34974e50f5a590005b3cb665ddbd7074f9fcbcbf9c50228d5e25596b64ada160b48f77a93aaced22617bfe005e00fe20a532a0adcb818c878dc5d6649277777ca1a814e21d0b53308af4078be4554715e4ce4828b012f25ffa13a6ceb30d20a75deba8a344e41d627fa638feff38a3063a0187519b39b053f7134d9cd83e6091accf5d2e3a05edfa1dfbe181a87ad86ba24fe6b97fe0004b5308204b130820399a003020102021004e1e7a4dc5cf2f36dc02b42b85d159f300d06092a864886f70d01010b0500306c310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312b30290603550403132244696769436572742048696768204173737572616e636520455620526f6f74204341301e170d3133313032323132303030305a170d3238313032323132303030305a3070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e63652053657276657220434130820122300d06092a864886f70d01010105000382010f003082010a0282010100b6e02fc22406c86d045fd7ef0a6406b27d22266516ae42409bcedc9f9f76073ec330558719b94f940e5a941f5556b4c2022aafd098ee0b40d7c4d03b72c8149eef90b111a9aed2c8b8433ad90b0bd5d595f540afc81ded4d9c5f57b786506899f58adad2c7051fa897c9dca4b182842dc6ada59cc71982a6850f5e44582a378ffd35f10b0827325af5bb8b9ea4bd51d027e2dd3b4233a30528c4bb28cc9aac2b230d78c67be65e71b74a3e08fb81b71616a19d23124de5d79208ac75a49cbacd17b21e4435657f532539d11c0a9a631b199274680a37c2c25248cb395aa2b6e15dc1dda020b821a293266f144a2141c7ed6d9bf2482ff303f5a26892532f5ee30203010001a38201493082014530120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b06010505070302303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304b0603551d1f044430423040a03ea03c863a687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274486967684173737572616e63654556526f6f7443412e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e041604145168ff90af0207753cccd9656462a212b859723b301f0603551d23041830168014b13ec36903f8bf4701d498261a0802ef63642bc3300d06092a864886f70d01010b05000382010100188a958903e66ddf5cfc1d68ea4a8f83d6512f8d6b44169eac63f5d26e6c84998baa8171845bed344eb0b7799229cc2d806af08e20e179a4fe034713eaf586ca59717df404966bd359583dfed331255c183884a3e69f82fd8c5b98314ecd789e1afd85cb49aaf2278b9972fc3eaad5410bdad536a1bf1c6e47497f5ed9487c03d9fd8b49a098264240ebd69211a4640a5754c4f51dd6025e6baceec4809a1272fa5693d7ffbf30850630bf0b7f4eff57059d24ed85c32bfba675a8ac2d16ef7d7927b2ebc29d0b07eaaa85d301a3202841594328d281e3aaf6ec7b3b77b640628005414501ef17063edec0339b67d3612e7287e469fc120057401e70f51ec9b4'))
646
647 - def test_num_certs(self):
648 assert (len(self.p.data.certificates) == 2)
649
650 651 -class TestTLSMultiFactory(object):
652 653 """Made up test data""" 654 655 @classmethod
656 - def setup_class(cls):
657 cls.data = _hexdecode(b'1703010010' # header 1 658 b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' # data 1 659 b'1703010010' # header 2 660 b'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB' # data 2 661 b'1703010010' # header 3 662 b'CCCCCCCC') # data 3 (incomplete) 663 cls.msgs, cls.bytes_parsed = tls_multi_factory(cls.data)
664
665 - def test_num_messages(self):
666 # only complete messages should be parsed, incomplete ones left 667 # in buffer 668 assert (len(self.msgs) == 2)
669
670 - def test_bytes_parsed(self):
671 assert (self.bytes_parsed == (5 + 16) * 2)
672
673 - def test_first_msg_data(self):
674 assert (self.msgs[0].data == _hexdecode(b'AA' * 16))
675
676 - def test_second_msg_data(self):
677 assert (self.msgs[1].data == _hexdecode(b'BB' * 16))
678