def test_component_sorting(self):

        md1 = Component()
        md1.version = '1.2.3'
        md2 = Component()
        md2.version = '1.2.4'
        self.assertTrue(md1 < md2)
        self.assertFalse(md2 < md1)
        self.assertTrue(md2 > md1)
        self.assertFalse(md1 > md2)
Ejemplo n.º 2
0
        for md in fw.mds:
            if not md.blob:
                continue
            if self._require_test_for_md(md):
                _run_intelme_on_blob(self, test, md)
        db.session.commit()


# run with PYTHONPATH=. ./.env3/bin/python3 plugins/intelme/__init__.py ./firmware.bin
if __name__ == '__main__':
    import sys
    from lvfs.models import Firmware, Component, Protocol, Category

    plugin = Plugin()
    _test = Test('intelme')
    _fw = Firmware()
    _md = Component()
    _md.protocol = Protocol('org.uefi.capsule')
    _md.category = Category('X-ManagementEngine')
    _fw.mds.append(_md)

    with open(sys.argv[1], 'rb') as f:
        _md.blob = f.read()
    plugin.run_test_on_fw(_test, _fw)
    for attribute in _test.attributes:
        print(attribute)
    for _shard in _md.shards:
        if not _shard.checksums:
            continue
        print(_shard.info.guid, _shard.checksums[0])
Ejemplo n.º 3
0
        else:
            test.add_pass('Size', '{}x{}'.format(im.width, im.height))

        # save to download directory
        basename = 'img-{}.png'.format(hashlib.sha256(r.content).hexdigest())
        fn = os.path.join(app.config['DOWNLOAD_DIR'], basename)
        if not os.path.isfile(fn):
            im.save(fn, "PNG")

        # set the safe URL
        settings = _get_settings('firmware')
        md.screenshot_url_safe = os.path.join(settings['firmware_baseuri_cdn'],
                                              basename)


# run with PYTHONPATH=. ./env/bin/python3 plugins/cdn-mirror/__init__.py
if __name__ == '__main__':
    import sys
    from lvfs.models import Firmware, Component

    plugin = Plugin()
    _test = Test(plugin_id=plugin.id)
    _fw = Firmware()
    _md = Component()
    _md.screenshot_url = 'https://github.com/fwupd/8bitdo-firmware/raw/master/screenshots/FC30.png'
    _fw.mds.append(_md)
    plugin.run_test_on_md(_test, _md)
    print('new URL', _md.screenshot_url_safe)
    for attribute in _test.attributes:
        print(attribute)
Ejemplo n.º 4
0
    def _parse_component(self, component):

        # get priority
        md = Component()
        md.priority = int(component.get('priority', '0'))

        # check type
        if component.get('type') != 'firmware':
            raise MetadataInvalid('<component type="firmware"> required')

        # get <id>
        try:
            md.appstream_id = _node_validate_text(component.xpath('id')[0],
                                                  minlen=10,
                                                  maxlen=256)
            if not md.appstream_id:
                raise MetadataInvalid('<id> value invalid')
            for char in md.appstream_id:
                if char.isspace():
                    raise MetadataInvalid('<id> Cannot contain spaces')
                if char in ['/', '\\']:
                    raise MetadataInvalid('<id> Cannot contain slashes')
                if char not in ['-', '_', '.'] and not char.isalnum():
                    raise MetadataInvalid(
                        '<id> Cannot contain {}'.format(char))
            if len(md.appstream_id.split('.')) < 4:
                raise MetadataInvalid(
                    '<id> Should contain at least 4 sections to identify the model'
                )
        except IndexError as _:
            raise MetadataInvalid('<id> tag missing')

        # get <developer_name>
        try:
            md.developer_name = _node_validate_text(
                component.xpath('developer_name')[0],
                minlen=3,
                maxlen=50,
                nourl=True)
            if md.developer_name == 'LenovoLtd.':
                md.developer_name = 'Lenovo Ltd.'
            md.add_keywords_from_string(md.developer_name, priority=10)
        except IndexError as _:
            raise MetadataInvalid('<developer_name> tag missing')
        if md.developer_name.find('@') != -1 or md.developer_name.find(
                '_at_') != -1:
            raise MetadataInvalid(
                '<developer_name> cannot contain an email address')

        # get <name>
        try:
            md.name = _node_validate_text(component.xpath('name')[0],
                                          minlen=3,
                                          maxlen=500)
            md.add_keywords_from_string(md.name, priority=3)

            # use categories instead
            if self.is_strict:
                category = {
                    'system': 'X-System',
                    'device': 'X-Device',
                    'bios': 'X-System',
                    'me': 'X-ManagementEngine',
                    'embedded': 'X-EmbeddedController',
                    'controller': 'X-EmbeddedController',
                }
                words = [word.lower() for word in md.name.split(' ')]
                for search in category:
                    if search in words:
                        raise MetadataInvalid('<name> tag should not contain {}, use '
                                              '<categories><category>{}'
                                              '</category></categories> instead'.\
                                              format(search, category[search]))

                # tokens banned outright
                for search in ['firmware', 'update', '(r)', '(c)']:
                    if search in words:
                        raise MetadataInvalid('<name> tag should not contain '
                                              'the word "{}"'.format(search))

                # should not include the vendor in the name
                if md.developer_name_display:
                    if md.developer_name_display.lower() in words:
                        raise MetadataInvalid('<name> tag should not contain '
                                              'the vendor name "{}"'.format(
                                                  md.developer_name_display))
        except IndexError as _:
            raise MetadataInvalid('<name> tag missing')

        # get <summary>
        try:
            md.summary = _node_validate_text(component.xpath('summary')[0],
                                             minlen=10,
                                             maxlen=500)
            md.add_keywords_from_string(md.summary, priority=1)
        except IndexError as _:
            raise MetadataInvalid('<summary> tag missing')

        # get optional <name_variant_suffix>
        try:
            md.name_variant_suffix = _node_validate_text(
                component.xpath('name_variant_suffix')[0],
                minlen=2,
                maxlen=500)
        except IndexError as _:
            pass

        # get optional <description}
        try:
            md.description = _node_validate_text(
                component.xpath('description')[0],
                minlen=25,
                maxlen=1000,
                nourl=True)
        except IndexError as _:
            pass

        # get <metadata_license>
        if self.is_strict:
            try:
                md.metadata_license = _node_validate_text(
                    component.xpath('metadata_license')[0])
                if md.metadata_license not in [
                        'CC0-1.0', 'FSFAP', 'CC-BY-3.0', 'CC-BY-SA-3.0',
                        'CC-BY-4.0', 'CC-BY-SA-4.0', 'GFDL-1.1', 'GFDL-1.2',
                        'GFDL-1.3'
                ]:
                    raise MetadataInvalid(
                        'Invalid <metadata_license> tag of {}'.format(
                            md.metadata_license))
            except AttributeError as _:
                raise MetadataInvalid('<metadata_license> tag')
            except IndexError as _:
                raise MetadataInvalid('<metadata_license> tag missing')

        # get <project_license>
        try:
            md.project_license = _node_validate_text(
                component.xpath('project_license')[0],
                minlen=4,
                maxlen=50,
                nourl=True)
        except IndexError as _:
            raise MetadataInvalid('<project_license> tag missing')
        if not md.project_license:
            raise MetadataInvalid('<project_license> value invalid')

        # get <url type="homepage">
        try:
            md.url_homepage = _node_validate_text(
                component.xpath('url[@type="homepage"]')[0],
                minlen=7,
                maxlen=1000)
        except IndexError as _:
            raise MetadataInvalid('<url type="homepage"> tag missing')
        if not md.url_homepage:
            raise MetadataInvalid('<url type="homepage"> value invalid')

        # add manually added keywords
        for keyword in component.xpath('keywords/keyword'):
            text = _node_validate_text(keyword,
                                       minlen=3,
                                       maxlen=50,
                                       nourl=True)
            if text.find(' ') != -1:
                raise MetadataInvalid('<keywords> cannot contain spaces')
            md.add_keywords_from_string(text, priority=5)

        # add provides
        for prov in component.xpath('provides/firmware[@type="flashed"]'):
            text = _node_validate_text(prov, minlen=5, maxlen=1000)
            if not _validate_guid(text):
                raise MetadataInvalid('The GUID {} was invalid.'.format(text))
            if text in [
                    '230c8b18-8d9b-53ec-838b-6cfc0383493a',  # main-system-firmware
                    'f15aa55c-9cd5-5942-85ae-a6bf8740b96c',  # MST-panamera
                    'd6072785-6fc0-5f83-9d49-11376e7f48b1',  # MST-leaf
                    '49ec4eb4-c02b-58fc-8935-b1ee182405c7'
            ]:  # MST-tesla
                raise MetadataInvalid(
                    'The GUID {} is too generic'.format(text))
            md.guids.append(Guid(md.component_id, text))
        if not md.guids:
            raise MetadataInvalid(
                'The metadata file did not provide any GUID.')

        # check the file didn't try to add it's own <require> on vendor-id
        # to work around the vendor-id security checks in fwupd
        if component.xpath('requires/firmware[text()="vendor-id"]'):
            raise MetadataInvalid('Firmware cannot specify vendor-id')

        # check only recognised requirements are added
        for req in component.xpath('requires/*'):
            if req.tag == 'firmware':
                text = _node_validate_text(req,
                                           minlen=3,
                                           maxlen=1000,
                                           allow_none=True)
                rq = Requirement(kind=req.tag,
                                 value=text,
                                 compare=req.get('compare'),
                                 version=req.get('version'),
                                 depth=req.get('depth', None))
                md.requirements.append(rq)
            elif req.tag == 'id':
                text = _node_validate_text(req, minlen=3, maxlen=1000)
                rq = Requirement(kind=req.tag,
                                 value=text,
                                 compare=req.get('compare'),
                                 version=req.get('version'))
                md.requirements.append(rq)
                if text == 'org.freedesktop.fwupd':
                    self.fwupd_min_version = req.get('version')
            elif req.tag == 'hardware':
                text = _node_validate_text(req, minlen=3, maxlen=1000)
                for req_value in text.split('|'):
                    rq = Requirement(kind=req.tag,
                                     value=req_value,
                                     compare=req.get('compare'),
                                     version=req.get('version'))
                    md.requirements.append(rq)
            else:
                raise MetadataInvalid('<{}> requirement was invalid'.format(
                    req.tag))

        # from the first screenshot
        try:
            md.screenshot_caption = _node_validate_text(
                component.xpath('screenshots/screenshot/caption')[0],
                minlen=8,
                maxlen=1000,
                nourl=True)
        except IndexError as _:
            pass
        try:
            md.screenshot_url = _node_validate_text(
                component.xpath('screenshots/screenshot/image')[0],
                minlen=8,
                maxlen=1000)
        except IndexError as _:
            pass

        # allows OEM to hide the direct download link on the LVFS
        if component.xpath('custom/value[@key="LVFS::InhibitDownload"]'):
            md.inhibit_download = True

        # allows OEM to disable ignore all kinds of statistics on this firmware
        if component.xpath('custom/value[@key="LVFS::DoNotTrack"]'):
            md.fw.do_not_track = True

        # allows OEM to change the triplet (AA.BB.CCDD) to quad (AA.BB.CC.DD)
        try:
            version_format = _node_validate_text(
                component.xpath('custom/value[@key="LVFS::VersionFormat"]')[0])
            if not self.version_formats:
                raise MetadataInvalid(
                    'Valid version formats have not been added')
            if version_format not in self.version_formats:
                raise MetadataInvalid('LVFS::VersionFormat can only be {}'.\
                                      format(','.join(self.version_formats.keys())))
            md.verfmt = self.version_formats[version_format]
        except IndexError as _:
            pass

        # enforce the VersionFormat if the version is an integer
        if self.is_strict and md.version:
            if md.version.isdigit() and not md.version_format:
                raise MetadataInvalid(
                    'LVFS::VersionFormat is required for integer version')

        # allows OEM to specify protocol
        try:
            text = _node_validate_text(
                component.xpath('custom/value[@key="LVFS::UpdateProtocol"]')
                [0])
            if text not in self.protocol_map:
                raise MetadataInvalid(
                    'No valid UpdateProtocol {} found'.format(text))
            md.protocol_id = self.protocol_map[text]
        except IndexError as _:
            pass

        # allows OEM to set banned country codes
        try:
            text = _node_validate_text(component.xpath(
                'custom/value[@key="LVFS::BannedCountryCodes"]')[0],
                                       minlen=2,
                                       maxlen=1000,
                                       nourl=True)
            self.fw.banned_country_codes = text
        except IndexError as _:
            pass

        # should we parse the .inf file?
        try:
            text = _node_validate_text(component.xpath(
                'custom/value[@key="LVFS::EnableInfParsing"]')[0],
                                       minlen=2,
                                       maxlen=10,
                                       nourl=True)
            if text == 'true':
                self.enable_inf_parsing = True
            elif text == 'false':
                self.enable_inf_parsing = False
            else:
                raise MetadataInvalid(
                    'LVFS::EnableInfParsing only allowed true or false, got {}'
                    .format(text))
        except IndexError as _:
            pass

        # allows OEM to specify category
        for category in component.xpath('categories/category'):
            text = _node_validate_text(category,
                                       minlen=8,
                                       maxlen=50,
                                       nourl=True)
            if text in self.category_map:
                md.category_id = self.category_map[text]
                break

        # parse the default (first) release
        try:
            default_release = component.xpath('releases/release')[0]
        except IndexError as _:
            raise MetadataInvalid(
                'The metadata file did not provide any releases')
        self._parse_release(md, default_release)

        # ensure the update description does not refer to a file in the archive
        if md.release_description:
            for word in md.release_description.split(' '):
                if word.find('.') == -1:  # any word without a dot is not a fn
                    continue
                if word in self.cabarchive_upload:
                    raise MetadataInvalid(
                        'The release description should not reference other files.'
                    )

        # check the inf file matches up with the .xml file
        if self._version_inf and self._version_inf != md.version:
            raise MetadataInvalid(
                'The inf Firmware_AddReg[HKR->FirmwareVersion] '
                '%s did not match the metainfo.xml value %s.' %
                (self._version_inf, md.version))

        # success
        return md
Ejemplo n.º 5
0
            try:
                self.rules = yara.compile(filepaths=filepaths)
            except yara.SyntaxError as e:
                test.add_fail('YARA',
                              'Failed to compile rules: {}'.format(str(e)))
                return

        # run analysis on the component and any shards
        for md in fw.mds:
            if md.blob:
                _run_on_blob(self, test, md, md.filename_contents, md.blob)
            for shard in md.shards:
                if shard.blob:
                    _run_on_blob(self, test, md, shard.name, shard.blob)


# run with PYTHONPATH=. ./env/bin/python3 plugins/blocklist/__init__.py
if __name__ == '__main__':
    import sys
    from lvfs.models import Firmware, Component

    plugin = Plugin('blocklist')
    _test = Test(plugin.id)
    _fw = Firmware()
    _md = Component()
    _md.blob = b'CN=DO NOT TRUST - AMI Test PK'
    _fw.mds.append(_md)
    plugin.run_test_on_fw(_test, _fw)
    for attribute in _test.attributes:
        print(attribute)
Ejemplo n.º 6
0
# pylint: disable=protected-access,wrong-import-position

import os
import sys

# allows us to run this from the project root
sys.path.append(os.path.realpath('.'))

from lvfs.models import Test, Firmware, Component, Protocol, Category
from plugins.intelme import Plugin

if __name__ == '__main__':
    for _argv in sys.argv[1:]:
        print('Processing', _argv)
        plugin = Plugin('intelme')
        _test = Test(plugin.id)
        _fw = Firmware()
        _md = Component()
        _md.component_id = 999999
        _md.category = Category('X-ManagementEngine')
        _md.filename_contents = 'filename.bin'
        _md.protocol = Protocol('org.uefi.capsule')
        with open(_argv, 'rb') as _f:
            _md.blob = _f.read()
        _fw.mds.append(_md)
        plugin.run_test_on_fw(_test, _fw)
        for attribute in _test.attributes:
            print(attribute)
        for shard in _md.shards:
            print(shard.info.guid, shard.info.name, shard.checksum)
Ejemplo n.º 7
0
import datetime

# allows us to run this from the project root
sys.path.append(os.path.realpath('.'))

from lvfs.models import Test, Firmware, Component, Protocol, ComponentShard
from plugins.pecheck import Plugin

if __name__ == '__main__':
    for _argv in sys.argv[1:]:
        print('Processing', _argv)
        plugin = Plugin('pecheck')
        _test = Test(plugin.id)
        _fw = Firmware()
        _fw.timestamp = datetime.datetime.utcnow()
        _md = Component()
        _md.protocol = Protocol('org.uefi.capsule')
        _shard = ComponentShard(name=os.path.basename(_argv))
        try:
            with open(_argv, 'rb') as f:
                _shard.set_blob(f.read())
        except IsADirectoryError as _:
            continue
        _md.shards.append(_shard)
        _fw.mds.append(_md)
        plugin.run_test_on_fw(_test, _fw)
        for attribute in _test.attributes:
            print(attribute)
        for cert in _shard.certificates:
            print(cert)
Ejemplo n.º 8
0
# pylint: disable=protected-access,wrong-import-position

import os
import sys

# allows us to run this from the project root
sys.path.append(os.path.realpath('.'))

from lvfs.models import Test, Firmware, Component, Protocol, Category
from plugins.amdpsp import Plugin

if __name__ == '__main__':
    for _argv in sys.argv[1:]:
        print('Processing', _argv)
        plugin = Plugin('amdpsp')
        _test = Test(plugin.id)
        _fw = Firmware()
        _md = Component()
        _md.component_id = 999999
        _md.category = Category('X-PlatformSecurityProcessor')
        _md.filename_contents = 'filename.bin'
        _md.protocol = Protocol('org.uefi.capsule')
        with open(_argv, 'rb') as _f:
            _md.blob = _f.read()
        _fw.mds.append(_md)
        plugin.run_test_on_fw(_test, _fw)
        for attribute in _test.attributes:
            print(attribute)
        for shard in _md.shards:
            print(shard.guid, shard.name, shard.checksum, len(shard.blob))
Ejemplo n.º 9
0
#
# pylint: disable=protected-access,wrong-import-position

import os
import sys

# allows us to run this from the project root
sys.path.append(os.path.realpath('.'))

from lvfs.models import Test, Firmware, Component, Protocol
from plugins.chipsec import Plugin

if __name__ == '__main__':
    for _argv in sys.argv[1:]:
        print('Processing', _argv)
        plugin = Plugin('chipsec')
        _test = Test(plugin.id)
        _fw = Firmware()
        _md = Component()
        _md.component_id = 999999
        _md.filename_contents = 'filename.bin'
        _md.protocol = Protocol('org.uefi.capsule')
        with open(_argv, 'rb') as _f:
            _md.blob = _f.read()
        _fw.mds.append(_md)
        plugin.run_test_on_fw(_test, _fw)
        for attribute in _test.attributes:
            print(attribute)
        for shard in _md.shards:
            print(shard.guid, shard.name, shard.checksum)
Ejemplo n.º 10
0
        # run analysis on the component and any shards
        for shard in md.shards:
            if shard.guid in self.infos_by_guid:
                info = self.infos_by_guid[shard.guid]
                md.add_claim(info.claim)
            if shard.checksum in self.claims_by_csum:
                shard_claim = self.claims_by_csum[shard.checksum]
                md.add_claim(shard_claim.claim)


# run with PYTHONPATH=. ./env/bin/python3 plugins/shard-claim/__init__.py
if __name__ == '__main__':
    import sys
    from lvfs.models import Firmware, Component

    plugin = Plugin('shard-claim')
    _test = Test(plugin_id=plugin.id)
    _fw = Firmware()
    _md = Component()
    _shard = ComponentShard(guid='f114faa8-4fd5-4b95-8bc3-bc5cb5454966')
    _shard.checksums.append(ComponentShardChecksum(kind='SHA256',
                                                   value='fd14d82dd6f4f6fdc3263c25c681b11ef8'\
                                                         'daccd169efcab451cbb32c5f45ef8a'))
    _md.shards.append(_shard)
    _fw.mds.append(_md)
    plugin.run_test_on_fw(_test, _fw)
    plugin.run_test_on_md(_test, _md)
    for _claim in _md.claims:
        print(_claim)