1
2
3
4
5
6
7
8
9
10
11 """Helper class for TLSConnection."""
12 from __future__ import generators
13
14 from .utils.compat import *
15 from .utils.cryptomath import *
16 from .utils.codec import Parser
17 from .errors import *
18 from .messages import *
19 from .mathtls import *
20 from .constants import *
21 from .recordlayer import RecordLayer
22 from .defragmenter import Defragmenter
23 from .handshakehashes import HandshakeHashes
24 from .bufferedsocket import BufferedSocket
25
26 import socket
27 import traceback
30 """
31 This class handles data transmission for a TLS connection.
32
33 Its only subclass is L{tlslite.TLSConnection.TLSConnection}. We've
34 separated the code in this class from TLSConnection to make things
35 more readable.
36
37
38 @type sock: socket.socket
39 @ivar sock: The underlying socket object.
40
41 @type session: L{tlslite.Session.Session}
42 @ivar session: The session corresponding to this connection.
43
44 Due to TLS session resumption, multiple connections can correspond
45 to the same underlying session.
46
47 @type version: tuple
48 @ivar version: The TLS version being used for this connection.
49
50 (3,0) means SSL 3.0, and (3,1) means TLS 1.0.
51
52 @type closed: bool
53 @ivar closed: If this connection is closed.
54
55 @type resumed: bool
56 @ivar resumed: If this connection is based on a resumed session.
57
58 @type allegedSrpUsername: str or None
59 @ivar allegedSrpUsername: This is set to the SRP username
60 asserted by the client, whether the handshake succeeded or not.
61 If the handshake fails, this can be inspected to determine
62 if a guessing attack is in progress against a particular user
63 account.
64
65 @type closeSocket: bool
66 @ivar closeSocket: If the socket should be closed when the
67 connection is closed, defaults to True (writable).
68
69 If you set this to True, TLS Lite will assume the responsibility of
70 closing the socket when the TLS Connection is shutdown (either
71 through an error or through the user calling close()). The default
72 is False.
73
74 @type ignoreAbruptClose: bool
75 @ivar ignoreAbruptClose: If an abrupt close of the socket should
76 raise an error (writable).
77
78 If you set this to True, TLS Lite will not raise a
79 L{tlslite.errors.TLSAbruptCloseError} exception if the underlying
80 socket is unexpectedly closed. Such an unexpected closure could be
81 caused by an attacker. However, it also occurs with some incorrect
82 TLS implementations.
83
84 You should set this to True only if you're not worried about an
85 attacker truncating the connection, and only if necessary to avoid
86 spurious errors. The default is False.
87
88 @type encryptThenMAC: bool
89 @ivar encryptThenMAC: Whether the connection uses the encrypt-then-MAC
90 construct for CBC cipher suites, will be False also if connection uses
91 RC4 or AEAD.
92
93 @type recordSize: int
94 @ivar recordSize: maimum size of data to be sent in a single record layer
95 message. Note that after encryption is established (generally after
96 handshake protocol has finished) the actual amount of data written to
97 network socket will be larger because of the record layer header, padding
98 or encryption overhead. It can be set to low value (so that there is no
99 fragmentation on Ethernet, IP and TCP level) at the beginning of
100 connection to reduce latency and set to protocol max (2**14) to maximise
101 throughput after sending few kiB of data. Setting to values greater than
102 2**14 will cause the connection to be dropped by RFC compliant peers.
103
104 @sort: __init__, read, readAsync, write, writeAsync, close, closeAsync,
105 getCipherImplementation, getCipherName
106 """
107
149
150 @property
152 """Boolean stating if the endpoint acts as a client"""
153 return self._recordLayer.client
154
155 @_client.setter
157 """Set the endpoint to act as a client or not"""
158 self._recordLayer.client = value
159
160 @property
162 """Get the SSL protocol version of connection"""
163 return self._recordLayer.version
164
165 @version.setter
167 """
168 Set the SSL protocol version of connection
169
170 The setter is a public method only for backwards compatibility.
171 Don't use it! See at HandshakeSettings for options to set desired
172 protocol version.
173 """
174 self._recordLayer.version = value
175
176 @property
178 """Whether the connection uses Encrypt Then MAC (RFC 7366)"""
179 return self._recordLayer.encryptThenMAC
180
182 self._readBuffer = b''
183
185 self._send_writer = None
186
187
188
189
190
191
192 - def read(self, max=None, min=1):
193 """Read some data from the TLS connection.
194
195 This function will block until at least 'min' bytes are
196 available (or the connection is closed).
197
198 If an exception is raised, the connection will have been
199 automatically closed.
200
201 @type max: int
202 @param max: The maximum number of bytes to return.
203
204 @type min: int
205 @param min: The minimum number of bytes to return
206
207 @rtype: str
208 @return: A string of no more than 'max' bytes, and no fewer
209 than 'min' (unless the connection has been closed, in which
210 case fewer than 'min' bytes may be returned).
211
212 @raise socket.error: If a socket error occurs.
213 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
214 without a preceding alert.
215 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
216 """
217 for result in self.readAsync(max, min):
218 pass
219 return result
220
222 """Start a read operation on the TLS connection.
223
224 This function returns a generator which behaves similarly to
225 read(). Successive invocations of the generator will return 0
226 if it is waiting to read from the socket, 1 if it is waiting
227 to write to the socket, or a string if the read operation has
228 completed.
229
230 @rtype: iterable
231 @return: A generator; see above for details.
232 """
233 try:
234 while len(self._readBuffer)<min and not self.closed:
235 try:
236 for result in self._getMsg(ContentType.application_data):
237 if result in (0,1):
238 yield result
239 applicationData = result
240 self._readBuffer += applicationData.write()
241 except TLSRemoteAlert as alert:
242 if alert.description != AlertDescription.close_notify:
243 raise
244 except TLSAbruptCloseError:
245 if not self.ignoreAbruptClose:
246 raise
247 else:
248 self._shutdown(True)
249
250 if max == None:
251 max = len(self._readBuffer)
252
253 returnBytes = self._readBuffer[:max]
254 self._readBuffer = self._readBuffer[max:]
255 yield bytes(returnBytes)
256 except GeneratorExit:
257 raise
258 except:
259 self._shutdown(False)
260 raise
261
263 """Add bytes to the front of the socket read buffer for future
264 reading. Be careful using this in the context of select(...): if you
265 unread the last data from a socket, that won't wake up selected waiters,
266 and those waiters may hang forever.
267 """
268 self._readBuffer = b + self._readBuffer
269
271 """Write some data to the TLS connection.
272
273 This function will block until all the data has been sent.
274
275 If an exception is raised, the connection will have been
276 automatically closed.
277
278 @type s: str
279 @param s: The data to transmit to the other party.
280
281 @raise socket.error: If a socket error occurs.
282 """
283 for result in self.writeAsync(s):
284 pass
285
287 """Start a write operation on the TLS connection.
288
289 This function returns a generator which behaves similarly to
290 write(). Successive invocations of the generator will return
291 1 if it is waiting to write to the socket, or will raise
292 StopIteration if the write operation has completed.
293
294 @rtype: iterable
295 @return: A generator; see above for details.
296 """
297 try:
298 if self.closed:
299 raise TLSClosedConnectionError("attempt to write to closed connection")
300
301 applicationData = ApplicationData().create(bytearray(s))
302 for result in self._sendMsg(applicationData, \
303 randomizeFirstBlock=True):
304 yield result
305 except GeneratorExit:
306 raise
307 except Exception:
308
309
310 self._shutdown(self.ignoreAbruptClose)
311 raise
312
314 """Close the TLS connection.
315
316 This function will block until it has exchanged close_notify
317 alerts with the other party. After doing so, it will shut down the
318 TLS connection. Further attempts to read through this connection
319 will return "". Further attempts to write through this connection
320 will raise ValueError.
321
322 If makefile() has been called on this connection, the connection
323 will be not be closed until the connection object and all file
324 objects have been closed.
325
326 Even if an exception is raised, the connection will have been
327 closed.
328
329 @raise socket.error: If a socket error occurs.
330 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
331 without a preceding alert.
332 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
333 """
334 if not self.closed:
335 for result in self._decrefAsync():
336 pass
337
338
339 _decref_socketios = close
340
342 """Start a close operation on the TLS connection.
343
344 This function returns a generator which behaves similarly to
345 close(). Successive invocations of the generator will return 0
346 if it is waiting to read from the socket, 1 if it is waiting
347 to write to the socket, or will raise StopIteration if the
348 close operation has completed.
349
350 @rtype: iterable
351 @return: A generator; see above for details.
352 """
353 if not self.closed:
354 for result in self._decrefAsync():
355 yield result
356
391
393 """Get the name of this TLS version.
394
395 @rtype: str
396 @return: The name of the TLS version used with this connection.
397 Either None, 'SSL 3.0', 'TLS 1.0', 'TLS 1.1', or 'TLS 1.2'.
398 """
399 if self.version == (3,0):
400 return "SSL 3.0"
401 elif self.version == (3,1):
402 return "TLS 1.0"
403 elif self.version == (3,2):
404 return "TLS 1.1"
405 elif self.version == (3,3):
406 return "TLS 1.2"
407 else:
408 return None
409
411 """Get the name of the cipher used with this connection.
412
413 @rtype: str
414 @return: The name of the cipher used with this connection.
415 Either 'aes128', 'aes256', 'rc4', or '3des'.
416 """
417 return self._recordLayer.getCipherName()
418
420 """Get the name of the cipher implementation used with
421 this connection.
422
423 @rtype: str
424 @return: The name of the cipher implementation used with
425 this connection. Either 'python', 'openssl', or 'pycrypto'.
426 """
427 return self._recordLayer.getCipherImplementation()
428
429
431 """Send data to the TLS connection (socket emulation).
432
433 @raise socket.error: If a socket error occurs.
434 """
435 self.write(s)
436 return len(s)
437
439 """Send data to the TLS connection (socket emulation).
440
441 @raise socket.error: If a socket error occurs.
442 """
443 self.write(s)
444
445 - def recv(self, bufsize):
446 """Get some data from the TLS connection (socket emulation).
447
448 @raise socket.error: If a socket error occurs.
449 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
450 without a preceding alert.
451 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
452 """
453 return self.read(bufsize)
454
456
457 data = self.read(len(b))
458 if not data:
459 return None
460 b[:len(data)] = data
461 return len(data)
462
463 - def makefile(self, mode='r', bufsize=-1):
464 """Create a file object for the TLS connection (socket emulation).
465
466 @rtype: L{socket._fileobject}
467 """
468 self._refCount += 1
469
470
471
472
473
474
475
476
477
478
479
480
481
482 if 'w' in mode and bufsize == 0:
483 bufsize = 2**14
484
485 if sys.version_info < (3,):
486 return socket._fileobject(self, mode, bufsize, close=True)
487 else:
488
489 return socket.SocketIO(self, mode)
490
492 """Return the socket's own address (socket emulation)."""
493 return self.sock.getsockname()
494
496 """Return the remote address to which the socket is connected
497 (socket emulation)."""
498 return self.sock.getpeername()
499
501 """Set a timeout on blocking socket operations (socket emulation)."""
502 return self.sock.settimeout(value)
503
505 """Return the timeout associated with socket operations (socket
506 emulation)."""
507 return self.sock.gettimeout()
508
510 """Set the value of the given socket option (socket emulation)."""
511 return self.sock.setsockopt(level, optname, value)
512
514 """Shutdown the underlying socket."""
515 return self.sock.shutdown(how)
516
518 """Not implement in TLS Lite."""
519 raise NotImplementedError()
520
521
522
523
524
525
527 self._recordLayer.shutdown()
528 self.version = (0,0)
529 self.closed = True
530 if self.closeSocket:
531 self.sock.close()
532
533
534 if not resumable and self.session:
535 self.session.resumable = False
536
537
538 - def _sendError(self, alertDescription, errorStr=None):
547
549
550 self.sock.buffer_writes = True
551 randomizeFirstBlock = True
552 for msg in msgs:
553 for result in self._sendMsg(msg, randomizeFirstBlock):
554 yield result
555 randomizeFirstBlock = True
556 self.sock.flush()
557 self.sock.buffer_writes = False
558
559 - def _sendMsg(self, msg, randomizeFirstBlock = True):
560 """Fragment and send message through socket"""
561
562
563
564
565 if randomizeFirstBlock and self.version <= (3, 1) \
566 and self._recordLayer.isCBCMode() \
567 and msg.contentType == ContentType.application_data:
568 msgFirstByte = msg.splitFirstByte()
569 for result in self._sendMsgThroughSocket(msgFirstByte):
570 yield result
571 if len(msg.write()) == 0:
572 return
573
574 buf = msg.write()
575 contentType = msg.contentType
576
577 if contentType == ContentType.handshake:
578 self._handshake_hash.update(buf)
579
580
581 while len(buf) > self.recordSize:
582 newB = buf[:self.recordSize]
583 buf = buf[self.recordSize:]
584
585 msgFragment = Message(contentType, newB)
586 for result in self._sendMsgThroughSocket(msgFragment):
587 yield result
588
589 msgFragment = Message(contentType, buf)
590 for result in self._sendMsgThroughSocket(msgFragment):
591 yield result
592
594 """Send message, handle errors"""
595
596 try:
597 for result in self._recordLayer.sendRecord(msg):
598 if result in (0, 1):
599 yield result
600 except socket.error:
601
602
603
604
605
606
607
608
609
610
611 if msg.contentType == ContentType.handshake:
612
613
614
615 for result in self._getNextRecord():
616 if result in (0, 1):
617 yield result
618 else:
619 break
620
621
622 self._shutdown(False)
623
624
625 recordHeader, p = result
626 if recordHeader.type == ContentType.alert:
627 alert = Alert().parse(p)
628 raise TLSRemoteAlert(alert)
629 else:
630
631
632
633 raise
634
635 - def _getMsg(self, expectedType, secondaryType=None, constructorType=None):
636 try:
637 if not isinstance(expectedType, tuple):
638 expectedType = (expectedType,)
639
640
641
642
643
644
645 while 1:
646 for result in self._getNextRecord():
647 if result in (0,1):
648 yield result
649 else:
650 break
651 recordHeader, p = result
652
653
654 if recordHeader.type == ContentType.application_data:
655 if p.index == len(p.bytes):
656 continue
657
658
659 if recordHeader.type not in expectedType:
660
661
662 if recordHeader.type == ContentType.alert:
663 alert = Alert().parse(p)
664
665
666
667
668
669
670 if alert.level == AlertLevel.warning or \
671 alert.description == AlertDescription.close_notify:
672
673
674
675
676
677 try:
678 alertMsg = Alert()
679 alertMsg.create(AlertDescription.close_notify,
680 AlertLevel.warning)
681 for result in self._sendMsg(alertMsg):
682 yield result
683 except socket.error:
684 pass
685
686 if alert.description == \
687 AlertDescription.close_notify:
688 self._shutdown(True)
689 elif alert.level == AlertLevel.warning:
690 self._shutdown(False)
691
692 else:
693 self._shutdown(False)
694
695
696 raise TLSRemoteAlert(alert)
697
698
699 if recordHeader.type == ContentType.handshake:
700 subType = p.get(1)
701 reneg = False
702 if self._client:
703 if subType == HandshakeType.hello_request:
704 reneg = True
705 else:
706 if subType == HandshakeType.client_hello:
707 reneg = True
708
709 if reneg:
710 alertMsg = Alert()
711 alertMsg.create(AlertDescription.no_renegotiation,
712 AlertLevel.warning)
713 for result in self._sendMsg(alertMsg):
714 yield result
715 continue
716
717
718
719 for result in self._sendError(\
720 AlertDescription.unexpected_message,
721 "received type=%d" % recordHeader.type):
722 yield result
723
724 break
725
726
727 if recordHeader.type == ContentType.change_cipher_spec:
728 yield ChangeCipherSpec().parse(p)
729 elif recordHeader.type == ContentType.alert:
730 yield Alert().parse(p)
731 elif recordHeader.type == ContentType.application_data:
732 yield ApplicationData().parse(p)
733 elif recordHeader.type == ContentType.handshake:
734
735 if not isinstance(secondaryType, tuple):
736 secondaryType = (secondaryType,)
737
738
739 if recordHeader.ssl2:
740 subType = p.get(1)
741 if subType != HandshakeType.client_hello:
742 for result in self._sendError(\
743 AlertDescription.unexpected_message,
744 "Can only handle SSLv2 ClientHello messages"):
745 yield result
746 if HandshakeType.client_hello not in secondaryType:
747 for result in self._sendError(\
748 AlertDescription.unexpected_message):
749 yield result
750 subType = HandshakeType.client_hello
751 else:
752 subType = p.get(1)
753 if subType not in secondaryType:
754 for result in self._sendError(\
755 AlertDescription.unexpected_message,
756 "Expecting %s, got %s" % (str(secondaryType), subType)):
757 yield result
758
759
760 self._handshake_hash.update(p.bytes)
761
762
763 if subType == HandshakeType.client_hello:
764 yield ClientHello(recordHeader.ssl2).parse(p)
765 elif subType == HandshakeType.server_hello:
766 yield ServerHello().parse(p)
767 elif subType == HandshakeType.certificate:
768 yield Certificate(constructorType).parse(p)
769 elif subType == HandshakeType.certificate_request:
770 yield CertificateRequest(self.version).parse(p)
771 elif subType == HandshakeType.certificate_verify:
772 yield CertificateVerify(self.version).parse(p)
773 elif subType == HandshakeType.server_key_exchange:
774 yield ServerKeyExchange(constructorType,
775 self.version).parse(p)
776 elif subType == HandshakeType.server_hello_done:
777 yield ServerHelloDone().parse(p)
778 elif subType == HandshakeType.client_key_exchange:
779 yield ClientKeyExchange(constructorType, \
780 self.version).parse(p)
781 elif subType == HandshakeType.finished:
782 yield Finished(self.version).parse(p)
783 elif subType == HandshakeType.next_protocol:
784 yield NextProtocol().parse(p)
785 else:
786 raise AssertionError()
787
788
789 except SyntaxError as e:
790 for result in self._sendError(AlertDescription.decode_error,
791 formatExceptionTrace(e)):
792 yield result
793
794
796 """read next message from socket, defragment message"""
797
798 while True:
799
800
801
802
803
804
805
806
807
808 while True:
809
810 ret = self._defragmenter.getMessage()
811 if ret is None:
812 break
813 header = RecordHeader3().create(self.version, ret[0], 0)
814 yield header, Parser(ret[1])
815
816
817 for result in self._getNextRecordFromSocket():
818 if result in (0, 1):
819 yield result
820 else:
821 break
822
823 header, parser = result
824
825
826 if header.type == ContentType.application_data:
827 yield (header, parser)
828
829
830 elif header.ssl2:
831 yield (header, parser)
832 else:
833
834 self._defragmenter.addData(header.type, parser.bytes)
835
882
884 if not self.closed:
885 raise ValueError("Renegotiation disallowed for security reasons")
886 self._client = client
887 self._handshake_hash = HandshakeHashes()
888 self._defragmenter.clearBuffers()
889 self.allegedSrpUsername = None
890 self._refCount = 1
891
893 self.resumed = resumed
894 self.closed = False
895
896 - def _calcPendingStates(self, cipherSuite, masterSecret,
897 clientRandom, serverRandom, implementations):
898 self._recordLayer.calcPendingStates(cipherSuite, masterSecret,
899 clientRandom, serverRandom,
900 implementations)
901
904
907