1
2
3
4
5
6
7 """Wrapper of TLS RecordLayer providing message-level abstraction"""
8
9 from .recordlayer import RecordLayer
10 from .constants import ContentType
11 from .messages import RecordHeader3, Message
12 from .utils.codec import Parser
13
15
16 """TLS Record Layer socket that provides Message level abstraction
17
18 Because the record layer has a hard size limit on sent messages, they need
19 to be fragmented before sending. Similarly, a single record layer record
20 can include multiple handshake protocol messages (very common with
21 ServerHello, Certificate and ServerHelloDone), as such, the user of
22 RecordLayer needs to fragment those records into multiple messages.
23 Unfortunately, fragmentation of messages requires some degree of
24 knowledge about the messages passed and as such is outside scope of pure
25 record layer implementation.
26
27 This class tries to provide a useful abstraction for handling Handshake
28 protocol messages.
29
30 @type recordSize: int
31 @ivar recordSize: maximum size of records sent through socket. Messages
32 bigger than this size will be fragmented to smaller chunks. Setting it
33 to higher value than the default 2^14 will make the implementation
34 non RFC compliant and likely not interoperable with other peers.
35
36 @type defragmenter: L{Defragmenter}
37 @ivar defragmenter: defragmenter used for read records
38
39 @type unfragmentedDataTypes: tuple
40 @ivar unfragmentedDataTypes: data types which will be passed as-read,
41 TLS application_data by default
42 """
43
45 """Apply TLS Record Layer abstraction to raw network socket.
46
47 @type sock: L{socket.socket}
48 @param sock: network socket to wrap
49 @type defragmenter: L{Defragmenter}
50 @param defragmenter: defragmenter to apply on the records read
51 """
52 super(MessageSocket, self).__init__(sock)
53
54 self.defragmenter = defragmenter
55 self.unfragmentedDataTypes = tuple((ContentType.application_data, ))
56 self._lastRecordVersion = (0, 0)
57
58 self._sendBuffer = bytearray(0)
59 self._sendBufferType = None
60
61 self.recordSize = 2**14
62
64 """
65 Read next message in queue
66
67 will return a 0 or 1 if the read is blocking, a tuple of
68 L{RecordHeader3} and L{Parser} in case a message was received.
69
70 @rtype: generator
71 """
72 while True:
73 while True:
74 ret = self.defragmenter.getMessage()
75 if ret is None:
76 break
77 header = RecordHeader3().create(self._lastRecordVersion,
78 ret[0],
79 0)
80 yield header, Parser(ret[1])
81
82 for ret in self.recvRecord():
83 if ret in (0, 1):
84 yield ret
85 else:
86 break
87
88 header, parser = ret
89 if header.type in self.unfragmentedDataTypes:
90 yield ret
91
92 if header.ssl2:
93 yield ret
94
95 self.defragmenter.addData(header.type, parser.bytes)
96 self._lastRecordVersion = header.version
97
99 """Blocking variant of L{recvMessage}"""
100 for res in self.recvMessage():
101 if res in (0, 1):
102 pass
103 else:
104 return res
105
107 """
108 Empty the queue of messages to write
109
110 Will fragment the messages and write them in as little records as
111 possible.
112
113 @rtype: generator
114 """
115 while len(self._sendBuffer) > 0:
116 recordPayload = self._sendBuffer[:self.recordSize]
117 self._sendBuffer = self._sendBuffer[self.recordSize:]
118 msg = Message(self._sendBufferType, recordPayload)
119 for res in self.sendRecord(msg):
120 yield res
121
122 assert len(self._sendBuffer) == 0
123 self._sendBufferType = None
124
126 """Blocking variant of L{flush}"""
127 for _ in self.flush():
128 pass
129
131 """
132 Queue message for sending
133
134 If the message is of same type as messages in queue, the message is
135 just added to queue.
136
137 If the message is of different type as messages in queue, the queue is
138 flushed and then the message is queued.
139
140 @rtype: generator
141 """
142 if self._sendBufferType is None:
143 self._sendBufferType = msg.contentType
144
145 if msg.contentType == self._sendBufferType:
146 self._sendBuffer += msg.write()
147 return
148
149 for res in self.flush():
150 yield res
151
152 assert self._sendBufferType is None
153 self._sendBufferType = msg.contentType
154 self._sendBuffer += msg.write()
155
157 """Blocking variant of L{queueMessage}"""
158 for _ in self.queueMessage(msg):
159 pass
160
162 """
163 Fragment and send a message.
164
165 If a messages already of same type reside in queue, the message if
166 first added to it and then the queue is flushed.
167
168 If the message is of different type than the queue, the queue is
169 flushed, the message is added to queue and the queue is flushed again.
170
171 Use the sendRecord() message if you want to send a message outside
172 the queue, or a message of zero size.
173
174 @rtype: generator
175 """
176 for res in self.queueMessage(msg):
177 yield res
178
179 for res in self.flush():
180 yield res
181
183 """Blocking variant of L{sendMessage}"""
184 for _ in self.sendMessage(msg):
185 pass
186