Skip to content

Commit b3e0c7e

Browse files
authored
Merge pull request #110 from dgnuff/dhcp-buffer-overflow
Fix for issue #108 - Make sure the buffer is large enough before ever…
2 parents f683e3c + a22a887 commit b3e0c7e

File tree

1 file changed

+75
-76
lines changed

1 file changed

+75
-76
lines changed

adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py

Lines changed: 75 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@
8585
_LEASE_TIME = 51
8686
_OPT_END = 255
8787

88-
# Packet buffer
89-
_BUFF = bytearray(318)
88+
# Packet buffer size
89+
_BUFF_SIZE = const(318)
9090

9191

9292
class DHCP:
@@ -166,95 +166,95 @@ def send_dhcp_message(
166166
:param float time_elapsed: Number of seconds elapsed since DHCP process started
167167
:param bool renew: Set True for renew and rebind, defaults to False
168168
"""
169-
_BUFF[:] = b"\x00" * len(_BUFF)
169+
buff = bytearray(_BUFF_SIZE)
170170
# OP
171-
_BUFF[0] = _DHCP_BOOT_REQUEST
171+
buff[0] = _DHCP_BOOT_REQUEST
172172
# HTYPE
173-
_BUFF[1] = _DHCP_HTYPE10MB
173+
buff[1] = _DHCP_HTYPE10MB
174174
# HLEN
175-
_BUFF[2] = _DHCP_HLENETHERNET
175+
buff[2] = _DHCP_HLENETHERNET
176176
# HOPS
177-
_BUFF[3] = _DHCP_HOPS
177+
buff[3] = _DHCP_HOPS
178178

179179
# Transaction ID (xid)
180180
self._initial_xid = htonl(self._transaction_id)
181181
self._initial_xid = self._initial_xid.to_bytes(4, "big")
182-
_BUFF[4:8] = self._initial_xid
182+
buff[4:8] = self._initial_xid
183183

184184
# seconds elapsed
185-
_BUFF[8] = (int(time_elapsed) & 0xFF00) >> 8
186-
_BUFF[9] = int(time_elapsed) & 0x00FF
185+
buff[8] = (int(time_elapsed) & 0xFF00) >> 8
186+
buff[9] = int(time_elapsed) & 0x00FF
187187

188188
# flags
189189
flags = htons(0x8000)
190190
flags = flags.to_bytes(2, "big")
191-
_BUFF[10] = flags[1]
192-
_BUFF[11] = flags[0]
191+
buff[10] = flags[1]
192+
buff[11] = flags[0]
193193

194194
# NOTE: Skipping ciaddr/yiaddr/siaddr/giaddr
195195
# as they're already set to 0.0.0.0
196196
# Except when renewing, then fill in ciaddr
197197
if renew:
198-
_BUFF[12:16] = bytes(self.local_ip)
198+
buff[12:16] = bytes(self.local_ip)
199199

200200
# chaddr
201-
_BUFF[28:34] = self._mac_address
201+
buff[28:34] = self._mac_address
202202

203203
# NOTE: 192 octets of 0's, BOOTP legacy
204204

205205
# Magic Cookie
206-
_BUFF[236:240] = _MAGIC_COOKIE
206+
buff[236:240] = _MAGIC_COOKIE
207207

208208
# Option - DHCP Message Type
209-
_BUFF[240] = 53
210-
_BUFF[241] = 0x01
211-
_BUFF[242] = state
209+
buff[240] = 53
210+
buff[241] = 0x01
211+
buff[242] = state
212212

213213
# Option - Client Identifier
214-
_BUFF[243] = 61
214+
buff[243] = 61
215215
# Length
216-
_BUFF[244] = 0x07
216+
buff[244] = 0x07
217217
# HW Type - ETH
218-
_BUFF[245] = 0x01
218+
buff[245] = 0x01
219219
# Client MAC Address
220220
for mac, val in enumerate(self._mac_address):
221-
_BUFF[246 + mac] = val
221+
buff[246 + mac] = val
222222

223223
# Option - Host Name
224-
_BUFF[252] = 12
224+
buff[252] = 12
225225
hostname_len = len(self._hostname)
226226
after_hostname = 254 + hostname_len
227-
_BUFF[253] = hostname_len
228-
_BUFF[254:after_hostname] = self._hostname
227+
buff[253] = hostname_len
228+
buff[254:after_hostname] = self._hostname
229229

230230
if state == _DHCP_REQUEST and not renew:
231231
# Set the parsed local IP addr
232-
_BUFF[after_hostname] = 50
233-
_BUFF[after_hostname + 1] = 0x04
234-
_BUFF[after_hostname + 2 : after_hostname + 6] = bytes(self.local_ip)
232+
buff[after_hostname] = 50
233+
buff[after_hostname + 1] = 0x04
234+
buff[after_hostname + 2 : after_hostname + 6] = bytes(self.local_ip)
235235
# Set the parsed dhcp server ip addr
236-
_BUFF[after_hostname + 6] = 54
237-
_BUFF[after_hostname + 7] = 0x04
238-
_BUFF[after_hostname + 8 : after_hostname + 12] = bytes(self.dhcp_server_ip)
236+
buff[after_hostname + 6] = 54
237+
buff[after_hostname + 7] = 0x04
238+
buff[after_hostname + 8 : after_hostname + 12] = bytes(self.dhcp_server_ip)
239239

240-
_BUFF[after_hostname + 12] = 55
241-
_BUFF[after_hostname + 13] = 0x06
240+
buff[after_hostname + 12] = 55
241+
buff[after_hostname + 13] = 0x06
242242
# subnet mask
243-
_BUFF[after_hostname + 14] = 1
243+
buff[after_hostname + 14] = 1
244244
# routers on subnet
245-
_BUFF[after_hostname + 15] = 3
245+
buff[after_hostname + 15] = 3
246246
# DNS
247-
_BUFF[after_hostname + 16] = 6
247+
buff[after_hostname + 16] = 6
248248
# domain name
249-
_BUFF[after_hostname + 17] = 15
249+
buff[after_hostname + 17] = 15
250250
# renewal (T1) value
251-
_BUFF[after_hostname + 18] = 58
251+
buff[after_hostname + 18] = 58
252252
# rebinding (T2) value
253-
_BUFF[after_hostname + 19] = 59
254-
_BUFF[after_hostname + 20] = 255
253+
buff[after_hostname + 19] = 59
254+
buff[after_hostname + 20] = 255
255255

256256
# Send DHCP packet
257-
self._sock.send(_BUFF)
257+
self._sock.send(buff)
258258

259259
# pylint: disable=too-many-branches, too-many-statements
260260
def parse_dhcp_response(
@@ -264,89 +264,88 @@ def parse_dhcp_response(
264264
265265
:return Tuple[int, bytearray]: DHCP packet type and ID.
266266
"""
267-
global _BUFF # pylint: disable=global-statement
268267
# store packet in buffer
269-
_BUFF = bytearray(self._sock.recv(len(_BUFF)))
268+
buff = bytearray(self._sock.recv(_BUFF_SIZE))
270269
if self._debug:
271-
print("DHCP Response: ", _BUFF)
270+
print("DHCP Response: ", buff)
272271

273272
# -- Parse Packet, FIXED -- #
274273
# Validate OP
275-
if _BUFF[0] != _DHCP_BOOT_REPLY:
274+
if buff[0] != _DHCP_BOOT_REPLY:
276275
raise RuntimeError(
277276
"Malformed Packet - \
278277
DHCP message OP is not expected BOOT Reply."
279278
)
280279

281-
xid = _BUFF[4:8]
280+
xid = buff[4:8]
282281
if bytes(xid) != self._initial_xid:
283282
raise ValueError("DHCP response ID mismatch.")
284283

285-
self.local_ip = tuple(_BUFF[16:20])
284+
self.local_ip = tuple(buff[16:20])
286285
# Check that there is a server ID.
287-
if _BUFF[28:34] == b"\x00\x00\x00\x00\x00\x00":
286+
if buff[28:34] == b"\x00\x00\x00\x00\x00\x00":
288287
raise ValueError("No DHCP server ID in the response.")
289288

290-
if _BUFF[236:240] != _MAGIC_COOKIE:
289+
if buff[236:240] != _MAGIC_COOKIE:
291290
raise ValueError("No DHCP Magic Cookie in the response.")
292291

293292
# -- Parse Packet, VARIABLE -- #
294293
ptr = 240
295-
while _BUFF[ptr] != _OPT_END:
296-
if _BUFF[ptr] == _MSG_TYPE:
294+
while buff[ptr] != _OPT_END:
295+
if buff[ptr] == _MSG_TYPE:
297296
ptr += 1
298-
opt_len = _BUFF[ptr]
297+
opt_len = buff[ptr]
299298
ptr += opt_len
300-
msg_type = _BUFF[ptr]
299+
msg_type = buff[ptr]
301300
ptr += 1
302-
elif _BUFF[ptr] == _SUBNET_MASK:
301+
elif buff[ptr] == _SUBNET_MASK:
303302
ptr += 1
304-
opt_len = _BUFF[ptr]
303+
opt_len = buff[ptr]
305304
ptr += 1
306-
self.subnet_mask = tuple(_BUFF[ptr : ptr + opt_len])
305+
self.subnet_mask = tuple(buff[ptr : ptr + opt_len])
307306
ptr += opt_len
308-
elif _BUFF[ptr] == _DHCP_SERVER_ID:
307+
elif buff[ptr] == _DHCP_SERVER_ID:
309308
ptr += 1
310-
opt_len = _BUFF[ptr]
309+
opt_len = buff[ptr]
311310
ptr += 1
312-
self.dhcp_server_ip = tuple(_BUFF[ptr : ptr + opt_len])
311+
self.dhcp_server_ip = tuple(buff[ptr : ptr + opt_len])
313312
ptr += opt_len
314-
elif _BUFF[ptr] == _LEASE_TIME:
313+
elif buff[ptr] == _LEASE_TIME:
315314
ptr += 1
316-
opt_len = _BUFF[ptr]
315+
opt_len = buff[ptr]
317316
ptr += 1
318-
self._lease_time = int.from_bytes(_BUFF[ptr : ptr + opt_len], "big")
317+
self._lease_time = int.from_bytes(buff[ptr : ptr + opt_len], "big")
319318
ptr += opt_len
320-
elif _BUFF[ptr] == _ROUTERS_ON_SUBNET:
319+
elif buff[ptr] == _ROUTERS_ON_SUBNET:
321320
ptr += 1
322-
opt_len = _BUFF[ptr]
321+
opt_len = buff[ptr]
323322
ptr += 1
324-
self.gateway_ip = tuple(_BUFF[ptr : ptr + 4])
323+
self.gateway_ip = tuple(buff[ptr : ptr + 4])
325324
ptr += opt_len
326-
elif _BUFF[ptr] == _DNS_SERVERS:
325+
elif buff[ptr] == _DNS_SERVERS:
327326
ptr += 1
328-
opt_len = _BUFF[ptr]
327+
opt_len = buff[ptr]
329328
ptr += 1
330-
self.dns_server_ip = tuple(_BUFF[ptr : ptr + 4])
329+
self.dns_server_ip = tuple(buff[ptr : ptr + 4])
331330
ptr += opt_len # still increment even though we only read 1 addr.
332-
elif _BUFF[ptr] == _T1_VAL:
331+
elif buff[ptr] == _T1_VAL:
333332
ptr += 1
334-
opt_len = _BUFF[ptr]
333+
opt_len = buff[ptr]
335334
ptr += 1
336-
self._t1 = int.from_bytes(_BUFF[ptr : ptr + opt_len], "big")
335+
self._t1 = int.from_bytes(buff[ptr : ptr + opt_len], "big")
337336
ptr += opt_len
338-
elif _BUFF[ptr] == _T2_VAL:
337+
elif buff[ptr] == _T2_VAL:
339338
ptr += 1
340-
opt_len = _BUFF[ptr]
339+
opt_len = buff[ptr]
341340
ptr += 1
342-
self._t2 = int.from_bytes(_BUFF[ptr : ptr + opt_len], "big")
341+
self._t2 = int.from_bytes(buff[ptr : ptr + opt_len], "big")
343342
ptr += opt_len
344-
elif _BUFF[ptr] == 0:
343+
elif buff[ptr] == 0:
345344
break
346345
else:
347346
# We're not interested in this option
348347
ptr += 1
349-
opt_len = _BUFF[ptr]
348+
opt_len = buff[ptr]
350349
ptr += 1
351350
# no-op
352351
ptr += opt_len

0 commit comments

Comments
 (0)