sonic-buildimage/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py
Mai Bui 4963c1cc97 [device/juniper] Mitigation for security vulnerability (#11838)
Signed-off-by: maipbui maibui@microsoft.com
Dependency: [https://github.com/sonic-net/sonic-buildimage/pull/12065](https://github.com/sonic-net/sonic-buildimage/pull/12065)
#### Why I did it
`commands` module is not secure
command injection in `getstatusoutput` being used without a static string
#### How I did it
Eliminate `commands` module, use `subprocess` module only
Convert Python 2 to Python 3
2022-12-10 10:33:21 +08:00

336 lines
12 KiB
Python

#!/usr/bin/env python3
#
# Name: juniper_qfx5210_eepromconv.py version: 1.0
#
# Description: This file contains the code to store the contents of Board EEPROM in file
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
import binascii
import subprocess
from sonic_eeprom import eeprom_tlvinfo
def main():
eeprom_qfx5210 = Eeprom()
FANTYPE_PATH = '/sys/bus/i2c/devices/17-0068/fan1_direction'
isPlatformAFO = False
try:
fan_type_file = open(FANTYPE_PATH)
except IOError as e:
print("Error: unable to open file: %s" % str(e))
fan_type = -1
else:
fan_type = fan_type_file.read()
fan_type_file.close()
if (int(fan_type) == -1 or int(fan_type) == 0):
if (int(fan_type) == -1):
print("unable to open sys file for fan handling, defaulting it to AFO")
isPlatformAFO = True
else:
isPlatformAFO = False
# creating the "/var/run/eeprom" file and storing values of CPU board EEPROM in this file.
eeprom_file = open("/var/run/eeprom", "a+")
eeprom_file.write("\n")
if isPlatformAFO == True:
eeprom_file.write("Fan Type=AFO\r\n")
else:
eeprom_file.write("Fan Type=AFI\r\n")
eeprom_file.write("\n")
# Write the contents of CPU Board EEPROM to file
eeprom_file.write("CPU Board EEPROM (0x56)\r\n")
eeprom_file.write("===============================\r\n")
eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5210.modelstr())
eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5210.part_number_str())
eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5210.serial_number_str())
eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5210.base_mac_address())
eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5210.manuDate_str())
eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5210.platform_str())
eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5210.MACsize_str())
eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5210.vendor_name_str())
eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5210.manufacture_name_str())
CPUeepromFileCmd = ['cat', '/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom']
# Write the contents of CPU EEPROM to file
out_file = '/etc/init.d/eeprom_qfx5210_ascii'
try:
with open(out_file, 'w') as file:
subprocess.call(CPUeepromFileCmd, universal_newlines=True, stdout=file)
except OSError:
print('Error: Execution of "%s" failed', CPUeepromFileCmd)
return False
eeprom_ascii = '/etc/init.d/eeprom_qfx5210_ascii'
# Read file contents in Hex format
with open(eeprom_ascii, 'rb') as Hexformat:
content = Hexformat.read()
Hexformatoutput = binascii.hexlify(content)
eeprom_hex = '/etc/init.d/eeprom_qfx5210_hex'
with open(eeprom_hex, 'wb+') as Hexfile:
Hexfile.write(Hexformatoutput)
# Write contents of CPU EEPROM to new file in hexa format
with open(eeprom_hex, 'rb') as eeprom_hexfile:
eeprom_hexfile.seek(350, 0)
vendorext_read = eeprom_hexfile.read(124)
vendorext = ""
vendorext += "0x" + vendorext_read[0:2]
for i in range(2, 124, 2):
vendorext += " 0x" + vendorext_read[i:i+2]
eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext))
eeprom_hexfile.seek(350, 0)
IANA_read = eeprom_hexfile.read(8)
IANAName = binascii.unhexlify(IANA_read)
eeprom_file.write("IANA=%s\r\n" % str(IANAName))
eeprom_hexfile.seek(358, 0)
ASMpartrev_read = eeprom_hexfile.read(4)
ASMpartrev = binascii.unhexlify(ASMpartrev_read)
eeprom_file.write("Assembly Part Number Rev=%s\r\n" % str(ASMpartrev))
eeprom_hexfile.seek(374, 0)
ASMpartnum_read = eeprom_hexfile.read(20)
ASMpartnum_read = binascii.unhexlify(ASMpartnum_read)
eeprom_file.write("Assembly Part Number=%s\r\n" % str(ASMpartnum_read))
eeprom_hexfile.seek(402, 0)
ASMID_read = eeprom_hexfile.read(4)
ASMID_read_upper = ASMID_read.upper()
eeprom_file.write("Assembly ID=0x%s\r\n" % str(ASMID_read_upper))
ASMHWMajRev_position = eeprom_hexfile.seek(410, 0)
ASMHWMajRev_read = eeprom_hexfile.read(2)
eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(ASMHWMajRev_read))
eeprom_hexfile.seek(416, 0)
ASMHWMinRev_read = eeprom_hexfile.read(2)
eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(ASMHWMinRev_read))
eeprom_hexfile.seek(422, 0)
Deviation_read = eeprom_hexfile.read(28)
Deviation_read_upper = Deviation_read.upper()
eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read_upper))
eeprom_hexfile.seek(450, 0)
CLEI_read = eeprom_hexfile.read(20)
CLEI_name = binascii.unhexlify(CLEI_read)
eeprom_file.write("CLEI code=%s\r\n" % str(CLEI_name))
eeprom_dict = eeprom_qfx5210.system_eeprom_info()
key = '0x29'
if key in list(eeprom_dict.keys()):
onie_version_str = eeprom_dict.get('0x29', None)
else:
onie_version_str = "N/A"
eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str)
crc_str = eeprom_dict.get('0xFE', None)
eeprom_file.write("CRC=%s\r\n" % crc_str)
eeprom_file.close()
return True
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ ord(eeprom[tlv_index + 1])]
code = "0x%02X" % (ord(tlv[0]))
if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT:
value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) |
(ord(tlv[4]) << 8) | ord(tlv[5]))
value += str(tlv[6:6 + ord(tlv[1])])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32:
break
tlv_index += ord(eeprom[tlv_index+1]) + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def base_mac_address(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2]
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2]
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2]
def manuDate_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MANUF_DATE)
if not is_valid:
return "N/A"
return results[2]
def platform_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME)
if not is_valid:
return "N/A"
return results[2]
def MACsize_str(self):
(is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE)
if not is_valid:
return "N/A"
return str((ord(t[2][0]) << 8) | ord(t[2][1]))
def vendor_name_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_VENDOR_NAME)
if not is_valid:
return "N/A"
return results[2]
def manufacture_name_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MANUF_NAME)
if not is_valid:
return "N/A"
return results[2]
def onie_version_str(self):
value = ""
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_ONIE_VERSION)
if not is_valid:
return "N/A"
for c in results[2:2 + ord(results[1])]:
value += "0x%02X " % (ord(c),)
return value
def vendor_ext_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_VENDOR_EXT)
if not is_valid:
return "N/A"
vendor_value_formatted = ''.join([" 0x" + "%02X " % ord(x) for x in results[2]]).strip()
vendor_value_hexvalue = ''.join(["%02X" % ord(x) for x in results[2]]).strip()
return vendor_value_formatted, vendor_value_hexvalue
def crc_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_CRC_32)
if not is_valid:
return "N/A"
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict
if __name__ == "__main__":
main()