1
2
3
4
5
6
7
8
9
10
11 """Helper class for TLSConnection."""
12 from __future__ import generators
13
14 import io
15 import socket
16
17 from .utils.compat import *
18 from .utils.cryptomath import *
19 from .utils.codec import Parser
20 from .errors import *
21 from .messages import *
22 from .mathtls import *
23 from .constants import *
24 from .recordlayer import RecordLayer
25 from .defragmenter import Defragmenter
26 from .handshakehashes import HandshakeHashes
27 from .bufferedsocket import BufferedSocket
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
464
465
466
467 - def makefile(self, mode='r', bufsize=-1):
468 """Create a file object for the TLS connection (socket emulation).
469
470 @rtype: L{socket._fileobject}
471 """
472 self._refCount += 1
473
474
475
476
477
478
479
480
481
482
483
484
485
486 if 'w' in mode and bufsize <= 0:
487 bufsize = 2**14
488
489 if sys.version_info < (3,):
490 return socket._fileobject(self, mode, bufsize, close=True)
491 else:
492 if 'w' in mode:
493 return io.BufferedWriter(socket.SocketIO(self, mode), bufsize)
494 else:
495 return socket.SocketIO(self, mode)
496
497
499 """Return the socket's own address (socket emulation)."""
500 return self.sock.getsockname()
501
503 """Return the remote address to which the socket is connected
504 (socket emulation)."""
505 return self.sock.getpeername()
506
508 """Set a timeout on blocking socket operations (socket emulation)."""
509 return self.sock.settimeout(value)
510
512 """Return the timeout associated with socket operations (socket
513 emulation)."""
514 return self.sock.gettimeout()
515
517 """Set the value of the given socket option (socket emulation)."""
518 return self.sock.setsockopt(level, optname, value)
519
521 """Shutdown the underlying socket."""
522 return self.sock.shutdown(how)
523
525 """Not implement in TLS Lite."""
526 raise NotImplementedError()
527
528
529
530
531
532
534 self._recordLayer.shutdown()
535 self.version = (0,0)
536 self.closed = True
537 if self.closeSocket:
538 self.sock.close()
539
540
541 if not resumable and self.session:
542 self.session.resumable = False
543
544
545 - def _sendError(self, alertDescription, errorStr=None):
554
556
557 self.sock.buffer_writes = True
558 randomizeFirstBlock = True
559 for msg in msgs:
560 for result in self._sendMsg(msg, randomizeFirstBlock):
561 yield result
562 randomizeFirstBlock = True
563 self.sock.flush()
564 self.sock.buffer_writes = False
565
566 - def _sendMsg(self, msg, randomizeFirstBlock = True):
567 """Fragment and send message through socket"""
568
569
570
571
572 if randomizeFirstBlock and self.version <= (3, 1) \
573 and self._recordLayer.isCBCMode() \
574 and msg.contentType == ContentType.application_data:
575 msgFirstByte = msg.splitFirstByte()
576 for result in self._sendMsgThroughSocket(msgFirstByte):
577 yield result
578 if len(msg.write()) == 0:
579 return
580
581 buf = msg.write()
582 contentType = msg.contentType
583
584 if contentType == ContentType.handshake:
585 self._handshake_hash.update(buf)
586
587
588 while len(buf) > self.recordSize:
589 newB = buf[:self.recordSize]
590 buf = buf[self.recordSize:]
591
592 msgFragment = Message(contentType, newB)
593 for result in self._sendMsgThroughSocket(msgFragment):
594 yield result
595
596 msgFragment = Message(contentType, buf)
597 for result in self._sendMsgThroughSocket(msgFragment):
598 yield result
599
601 """Send message, handle errors"""
602
603 try:
604 for result in self._recordLayer.sendRecord(msg):
605 if result in (0, 1):
606 yield result
607 except socket.error:
608
609
610
611
612
613
614
615
616
617
618 if msg.contentType == ContentType.handshake:
619
620
621
622 for result in self._getNextRecord():
623 if result in (0, 1):
624 yield result
625 else:
626 break
627
628
629 self._shutdown(False)
630
631
632 recordHeader, p = result
633 if recordHeader.type == ContentType.alert:
634 alert = Alert().parse(p)
635 raise TLSRemoteAlert(alert)
636 else:
637
638
639
640 raise
641
642 - def _getMsg(self, expectedType, secondaryType=None, constructorType=None):
643 try:
644 if not isinstance(expectedType, tuple):
645 expectedType = (expectedType,)
646
647
648
649
650
651
652 while 1:
653 for result in self._getNextRecord():
654 if result in (0,1):
655 yield result
656 else:
657 break
658 recordHeader, p = result
659
660
661 if recordHeader.type == ContentType.application_data:
662 if p.index == len(p.bytes):
663 continue
664
665
666 if recordHeader.type not in expectedType:
667
668
669 if recordHeader.type == ContentType.alert:
670 alert = Alert().parse(p)
671
672
673
674
675
676
677 if alert.level == AlertLevel.warning or \
678 alert.description == AlertDescription.close_notify:
679
680
681
682
683
684 try:
685 alertMsg = Alert()
686 alertMsg.create(AlertDescription.close_notify,
687 AlertLevel.warning)
688 for result in self._sendMsg(alertMsg):
689 yield result
690 except socket.error:
691 pass
692
693 if alert.description == \
694 AlertDescription.close_notify:
695 self._shutdown(True)
696 elif alert.level == AlertLevel.warning:
697 self._shutdown(False)
698
699 else:
700 self._shutdown(False)
701
702
703 raise TLSRemoteAlert(alert)
704
705
706 if recordHeader.type == ContentType.handshake:
707 subType = p.get(1)
708 reneg = False
709 if self._client:
710 if subType == HandshakeType.hello_request:
711 reneg = True
712 else:
713 if subType == HandshakeType.client_hello:
714 reneg = True
715
716 if reneg:
717 alertMsg = Alert()
718 alertMsg.create(AlertDescription.no_renegotiation,
719 AlertLevel.warning)
720 for result in self._sendMsg(alertMsg):
721 yield result
722 continue
723
724
725
726 for result in self._sendError(\
727 AlertDescription.unexpected_message,
728 "received type=%d" % recordHeader.type):
729 yield result
730
731 break
732
733
734 if recordHeader.type == ContentType.change_cipher_spec:
735 yield ChangeCipherSpec().parse(p)
736 elif recordHeader.type == ContentType.alert:
737 yield Alert().parse(p)
738 elif recordHeader.type == ContentType.application_data:
739 yield ApplicationData().parse(p)
740 elif recordHeader.type == ContentType.handshake:
741
742 if not isinstance(secondaryType, tuple):
743 secondaryType = (secondaryType,)
744
745
746 if recordHeader.ssl2:
747 subType = p.get(1)
748 if subType != HandshakeType.client_hello:
749 for result in self._sendError(\
750 AlertDescription.unexpected_message,
751 "Can only handle SSLv2 ClientHello messages"):
752 yield result
753 if HandshakeType.client_hello not in secondaryType:
754 for result in self._sendError(\
755 AlertDescription.unexpected_message):
756 yield result
757 subType = HandshakeType.client_hello
758 else:
759 subType = p.get(1)
760 if subType not in secondaryType:
761 for result in self._sendError(\
762 AlertDescription.unexpected_message,
763 "Expecting %s, got %s" % (str(secondaryType), subType)):
764 yield result
765
766
767 self._handshake_hash.update(p.bytes)
768
769
770 if subType == HandshakeType.client_hello:
771 yield ClientHello(recordHeader.ssl2).parse(p)
772 elif subType == HandshakeType.server_hello:
773 yield ServerHello().parse(p)
774 elif subType == HandshakeType.certificate:
775 yield Certificate(constructorType).parse(p)
776 elif subType == HandshakeType.certificate_request:
777 yield CertificateRequest(self.version).parse(p)
778 elif subType == HandshakeType.certificate_verify:
779 yield CertificateVerify(self.version).parse(p)
780 elif subType == HandshakeType.server_key_exchange:
781 yield ServerKeyExchange(constructorType,
782 self.version).parse(p)
783 elif subType == HandshakeType.server_hello_done:
784 yield ServerHelloDone().parse(p)
785 elif subType == HandshakeType.client_key_exchange:
786 yield ClientKeyExchange(constructorType, \
787 self.version).parse(p)
788 elif subType == HandshakeType.finished:
789 yield Finished(self.version).parse(p)
790 elif subType == HandshakeType.next_protocol:
791 yield NextProtocol().parse(p)
792 else:
793 raise AssertionError()
794
795
796 except SyntaxError as e:
797 for result in self._sendError(AlertDescription.decode_error,
798 formatExceptionTrace(e)):
799 yield result
800
801
803 """read next message from socket, defragment message"""
804
805 while True:
806
807
808
809
810
811
812
813
814
815 while True:
816
817 ret = self._defragmenter.getMessage()
818 if ret is None:
819 break
820 header = RecordHeader3().create(self.version, ret[0], 0)
821 yield header, Parser(ret[1])
822
823
824 for result in self._getNextRecordFromSocket():
825 if result in (0, 1):
826 yield result
827 else:
828 break
829
830 header, parser = result
831
832
833 if header.type == ContentType.application_data:
834 yield (header, parser)
835
836
837 elif header.ssl2:
838 yield (header, parser)
839 else:
840
841 self._defragmenter.addData(header.type, parser.bytes)
842
889
891 if not self.closed:
892 raise ValueError("Renegotiation disallowed for security reasons")
893 self._client = client
894 self._handshake_hash = HandshakeHashes()
895 self._defragmenter.clearBuffers()
896 self.allegedSrpUsername = None
897 self._refCount = 1
898
900 self.resumed = resumed
901 self.closed = False
902
903 - def _calcPendingStates(self, cipherSuite, masterSecret,
904 clientRandom, serverRandom, implementations):
905 self._recordLayer.calcPendingStates(cipherSuite, masterSecret,
906 clientRandom, serverRandom,
907 implementations)
908
911
914