diff options
author | Victor Stinner <vstinner@python.org> | 2020-03-17 17:36:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-17 17:36:44 (GMT) |
commit | ebf6bb9f5ef032d1646b418ebbb645ea0b217da6 (patch) | |
tree | d6573ddced3ee130edab9765eb87a4283bfd1a1a /Lib/uuid.py | |
parent | 5b1ef200d31a74a9b478d0217d73ed0a659a8a06 (diff) | |
download | cpython-ebf6bb9f5ef032d1646b418ebbb645ea0b217da6.zip cpython-ebf6bb9f5ef032d1646b418ebbb645ea0b217da6.tar.gz cpython-ebf6bb9f5ef032d1646b418ebbb645ea0b217da6.tar.bz2 |
bpo-39991: Enhance uuid parser for MAC address (GH-19045)
Reject valid IPv6 addresses which doesn't contain "::" but have
a length of 17 characters.
Diffstat (limited to 'Lib/uuid.py')
-rw-r--r-- | Lib/uuid.py | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/Lib/uuid.py b/Lib/uuid.py index 3b3abc2..2799c75 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -434,6 +434,34 @@ def _find_mac_near_keyword(command, args, keywords, get_word_index): return first_local_mac or None +def _parse_mac(word): + # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'), + # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8'). + # + # Virtual interfaces, such as those provided by VPNs, do not have a + # colon-delimited MAC address as expected, but a 16-byte HWAddr separated + # by dashes. These should be ignored in favor of a real MAC address + parts = word.split(_MAC_DELIM) + if len(parts) != 6: + return + if _MAC_OMITS_LEADING_ZEROES: + # (Only) on AIX the macaddr value given is not prefixed by 0, e.g. + # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0 + # not + # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0 + if not all(1 <= len(part) <= 2 for part in parts): + return + hexstr = b''.join(part.rjust(2, b'0') for part in parts) + else: + if not all(len(part) == 2 for part in parts): + return + hexstr = b''.join(parts) + try: + return int(hexstr, 16) + except ValueError: + return + + def _find_mac_under_heading(command, args, heading): """Looks for a MAC address under a heading in a command's output. @@ -453,39 +481,21 @@ def _find_mac_under_heading(command, args, heading): first_local_mac = None for line in stdout: + words = line.rstrip().split() try: - words = line.rstrip().split() word = words[column_index] - # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'), - # but reject IPv6 address (ex: 'fe80::5054:ff:fe9') detected - # by '::' pattern. - if len(word) == 17 and b'::' not in word: - mac = int(word.replace(_MAC_DELIM, b''), 16) - elif _MAC_OMITS_LEADING_ZEROES: - # (Only) on AIX the macaddr value given is not prefixed by 0, e.g. - # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0 - # not - # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0 - parts = word.split(_MAC_DELIM) - if len(parts) == 6 and all(0 < len(p) <= 2 for p in parts): - hexstr = b''.join(p.rjust(2, b'0') for p in parts) - mac = int(hexstr, 16) - else: - continue - else: - continue - except (ValueError, IndexError): - # Virtual interfaces, such as those provided by - # VPNs, do not have a colon-delimited MAC address - # as expected, but a 16-byte HWAddr separated by - # dashes. These should be ignored in favor of a - # real MAC address - pass - else: - if _is_universal(mac): - return mac - first_local_mac = first_local_mac or mac - return first_local_mac or None + except IndexError: + continue + + mac = _parse_mac(word) + if mac is None: + continue + if _is_universal(mac): + return mac + if first_local_mac is None: + first_local_mac = mac + + return first_local_mac # The following functions call external programs to 'get' a macaddr value to |