[virt-tools-list] [PATCH RFC virtio-win-pkg-scripts v2 1/2] add parser for driver catalog files

Roman Kagan rkagan at virtuozzo.com
Fri Jan 22 15:05:02 UTC 2016


This script parses ASN.1 structure of the Windows driver catalog files,
and extracts information about what architecture and windows flavor the
driver is suitable for.

Signed-off-by: Roman Kagan <rkagan at virtuozzo.com>
---
changes since v1:
 - fix pep8 warnings

 util/parsecat.py | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 util/parsecat.py

diff --git a/util/parsecat.py b/util/parsecat.py
new file mode 100644
index 0000000..5d8e391
--- /dev/null
+++ b/util/parsecat.py
@@ -0,0 +1,188 @@
+#!/usr/bin/python
+#
+# Copyright 2016 Parallels IP Holdings GmbH
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+"""
+Parse relevant items in the ASN.1 structure of a Windows driver catalog file
+"""
+
+import sys
+import pprint
+from pyasn1_modules import rfc2315
+from pyasn1.type import tag, namedtype, namedval, univ, char, useful
+from pyasn1.codec.der import decoder
+
+
+class CatalogList(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('oid', univ.ObjectIdentifier())
+    )
+
+
+class CatalogListMemberId(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('oid', univ.ObjectIdentifier()),
+        namedtype.NamedType('null', univ.Null())
+    )
+
+
+class CatalogNameValue(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('name', char.BMPString()),
+        namedtype.NamedType('someInt', univ.Integer()),
+        namedtype.NamedType('value', univ.OctetString(encoding='utf-16-le'))
+    )
+
+
+class SpcKind(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('oid', univ.ObjectIdentifier()),
+        namedtype.NamedType('someTh', univ.Any())
+    )
+
+
+class SpcIndirectData(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('spcKind', SpcKind()),
+        namedtype.NamedType('digest', rfc2315.DigestInfo())
+    )
+
+
+class MemberAttributeContent(univ.SetOf):
+    componentType = univ.Any()
+
+
+class MemberAttribute(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('oid', univ.ObjectIdentifier()),
+        namedtype.NamedType('content', MemberAttributeContent())
+    )
+
+
+class MemberAttributes(univ.SetOf):
+    componentType = MemberAttribute()
+
+
+class CatalogListMember(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('referenceTag', univ.OctetString()),
+        namedtype.NamedType('attributes', MemberAttributes())
+    )
+
+
+class CatalogMembers(univ.SequenceOf):
+    componentType = CatalogListMember()
+
+
+class CatalogAttribute(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('oid', univ.ObjectIdentifier()),
+        namedtype.NamedType('content', univ.OctetString())
+    )
+
+
+class CatalogAttributes(univ.SequenceOf):
+    componentType = CatalogAttribute()
+    tagSet = univ.SequenceOf.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext,
+                                                  tag.tagFormatConstructed, 0))
+
+
+class CertTrustList(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('catalogList', CatalogList()),
+        namedtype.NamedType('someStr0', univ.OctetString()),
+        namedtype.NamedType('utcTime', useful.UTCTime()),
+        namedtype.NamedType('catalogListMemberId', CatalogListMemberId()),
+        namedtype.NamedType('members', CatalogMembers()),
+        namedtype.OptionalNamedType('attributes', CatalogAttributes())
+    )
+
+
+def parseNameValue(attr):
+    nv, _ = decoder.decode(attr, asn1Spec=CatalogNameValue())
+    strtype = type(u'')    # python2/3 compat
+    name, value = str(strtype(nv['name'])), str(strtype(nv['value']))
+    assert value[-1] == '\x00'
+    return name, value[:-1]
+
+
+spcKindMap = {
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.2.1.15'): 'spcPEImageData',
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.2.1.25'): 'spcLink',
+}
+
+
+digestAlgoMap = {
+    univ.ObjectIdentifier('1.3.14.3.2.26'): 'sha1',
+    univ.ObjectIdentifier('2.16.840.1.101.3.4.2.1'): 'sha256',
+}
+
+
+def parseSpcIndirectData(attr):
+    sid, _ = decoder.decode(attr, asn1Spec=SpcIndirectData())
+    spcKind, digest = sid['spcKind'], sid['digest']
+    algo = digestAlgoMap[digest['digestAlgorithm']['algorithm']]
+    return 'signature', {
+        'kind': spcKindMap[spcKind['oid']],
+        'digestAlgorithm': algo,
+        'digest': digest['digest'].asOctets()
+    }
+
+
+memberAttrMap = {
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.12.2.1'): parseNameValue,
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.12.2.2'): None,
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.12.2.3'): None,
+    univ.ObjectIdentifier('1.3.6.1.4.1.311.2.1.4'): parseSpcIndirectData,
+}
+
+
+def parseCatMember(member):
+    for attr in member['attributes']:
+        meth = memberAttrMap[attr['oid']]
+        if meth:
+            yield meth(attr['content'][0])
+
+
+contentInfoMap = {
+    rfc2315.data: rfc2315.Data(),
+    rfc2315.signedData: rfc2315.SignedData(),
+    rfc2315.envelopedData: rfc2315.EnvelopedData(),
+    rfc2315.signedAndEnvelopedData: rfc2315.SignedAndEnvelopedData(),
+    rfc2315.digestedData: rfc2315.DigestedData(),
+    rfc2315.encryptedData: rfc2315.EncryptedData()
+}
+
+
+def parseNameValueObj(nameValue):
+    assert nameValue['oid'] == univ.ObjectIdentifier('1.3.6.1.4.1.311.12.2.1')
+    return parseNameValue(nameValue['content'])
+
+
+def parseCat(fname):
+    cat = open(fname, "rb").read()
+    contentInfo, _ = decoder.decode(cat, asn1Spec=rfc2315.ContentInfo())
+    contentType = contentInfo['contentType']
+
+    content, _ = decoder.decode(contentInfo['content'],
+                                asn1Spec=contentInfoMap[contentType])
+    contentInfo = content['contentInfo']
+    contentType = contentInfo['contentType']
+    assert contentType == univ.ObjectIdentifier('1.3.6.1.4.1.311.10.1')
+
+    ctl, _ = decoder.decode(contentInfo['content'], asn1Spec=CertTrustList())
+    assert (ctl['catalogList']['oid'] ==
+            univ.ObjectIdentifier('1.3.6.1.4.1.311.12.1.1'))
+    assert (ctl['catalogListMemberId']['oid'] in (
+        univ.ObjectIdentifier('1.3.6.1.4.1.311.12.1.2'),
+        univ.ObjectIdentifier('1.3.6.1.4.1.311.12.1.3')
+        ))
+
+    members = [dict(parseCatMember(member)) for member in ctl['members']]
+    attributes = dict(parseNameValueObj(attr) for attr in ctl['attributes'])
+    return attributes, members
+
+if __name__ == "__main__":
+    pprint.pprint(parseCat(sys.argv[1]))
-- 
2.5.0




More information about the virt-tools-list mailing list