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