dissect.database 0.1.dev5__tar.gz → 0.1.dev6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/PKG-INFO +1 -1
  2. dissect_database-0.1.dev6/dissect/database/ese/tools/certlog.py +157 -0
  3. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect.database.egg-info/PKG-INFO +1 -1
  4. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect.database.egg-info/SOURCES.txt +3 -0
  5. dissect_database-0.1.dev6/tests/_data/ese/tools/CertLog.edb.gz +0 -0
  6. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/conftest.py +5 -0
  7. dissect_database-0.1.dev6/tests/ese/tools/test_certlog.py +14 -0
  8. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/.gitattributes +0 -0
  9. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/COPYRIGHT +0 -0
  10. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/LICENSE +0 -0
  11. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/MANIFEST.in +0 -0
  12. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/README.md +0 -0
  13. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/__init__.py +0 -0
  14. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/__init__.py +0 -0
  15. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/c_db.py +0 -0
  16. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/c_db.pyi +0 -0
  17. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/db.py +0 -0
  18. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/tools/__init__.py +0 -0
  19. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/tools/c_rpm.py +0 -0
  20. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/tools/c_rpm.pyi +0 -0
  21. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/bsd/tools/rpm.py +0 -0
  22. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/__init__.py +0 -0
  23. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/btree.py +0 -0
  24. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/c_ese.py +0 -0
  25. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/c_ese.pyi +0 -0
  26. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/compression.py +0 -0
  27. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/cursor.py +0 -0
  28. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/ese.py +0 -0
  29. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/exception.py +0 -0
  30. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/index.py +0 -0
  31. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/lcmapstring.py +0 -0
  32. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/page.py +0 -0
  33. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/record.py +0 -0
  34. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/sorting_table.py +0 -0
  35. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/table.py +0 -0
  36. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/tools/__init__.py +0 -0
  37. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/tools/impacket.py +0 -0
  38. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/tools/sru.py +0 -0
  39. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/tools/ual.py +0 -0
  40. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/ese/util.py +0 -0
  41. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/exception.py +0 -0
  42. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/__init__.py +0 -0
  43. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/c_sqlite3.py +0 -0
  44. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/c_sqlite3.pyi +0 -0
  45. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/exception.py +0 -0
  46. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/sqlite3.py +0 -0
  47. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect/database/sqlite3/util.py +0 -0
  48. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect.database.egg-info/dependency_links.txt +0 -0
  49. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect.database.egg-info/requires.txt +0 -0
  50. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/dissect.database.egg-info/top_level.txt +0 -0
  51. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/pyproject.toml +0 -0
  52. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/setup.cfg +0 -0
  53. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/__init__.py +0 -0
  54. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/bsd/btree.db.gz +0 -0
  55. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/bsd/hash.db.gz +0 -0
  56. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/bsd/recno.db.gz +0 -0
  57. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/bsd/rpm/Packages.gz +0 -0
  58. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/Windows.edb.gz +0 -0
  59. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/basic.edb.gz +0 -0
  60. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/binary.edb.gz +0 -0
  61. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/default.edb.gz +0 -0
  62. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/index.edb.gz +0 -0
  63. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/large.edb.gz +0 -0
  64. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/multi.edb.gz +0 -0
  65. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/text.edb.gz +0 -0
  66. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/tools/Current.mdb.gz +0 -0
  67. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/ese/tools/SRUDB.dat.gz +0 -0
  68. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/sqlite3/empty.sqlite +0 -0
  69. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_data/sqlite3/test.sqlite +0 -0
  70. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_docs/Makefile +0 -0
  71. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_docs/conf.py +0 -0
  72. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_docs/index.rst +0 -0
  73. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/_util.py +0 -0
  74. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/bsd/__init__.py +0 -0
  75. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/bsd/conftest.py +0 -0
  76. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/bsd/test_db.py +0 -0
  77. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/bsd/test_rpm.py +0 -0
  78. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/__init__.py +0 -0
  79. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_cursor.py +0 -0
  80. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_ese.py +0 -0
  81. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_index.py +0 -0
  82. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_page.py +0 -0
  83. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_record.py +0 -0
  84. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/test_table.py +0 -0
  85. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/tools/__init__.py +0 -0
  86. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/tools/test_sru.py +0 -0
  87. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/ese/tools/test_ual.py +0 -0
  88. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/__init__.py +0 -0
  89. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/conftest.py +0 -0
  90. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/test_default_values.py +0 -0
  91. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/test_row.py +0 -0
  92. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/test_sqlite3.py +0 -0
  93. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tests/sqlite3/test_util.py +0 -0
  94. {dissect_database-0.1.dev5 → dissect_database-0.1.dev6}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.database
3
- Version: 0.1.dev5
3
+ Version: 0.1.dev6
4
4
  Summary: A Dissect module implementing parsers for various database formats, including Berkeley DB, Microsofts Extensible Storage Engine (ESE) and SQLite3
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: Apache-2.0
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import datetime
5
+ import json
6
+ import typing
7
+ from pathlib import Path
8
+ from typing import BinaryIO
9
+
10
+ from dissect.util.ts import wintimestamp
11
+
12
+ from dissect.database.ese import ESE
13
+ from dissect.database.ese.c_ese import JET_coltyp
14
+ from dissect.database.ese.util import RecordValue
15
+
16
+ if typing.TYPE_CHECKING:
17
+ from collections.abc import Iterator
18
+
19
+ from dissect.database.ese.table import Table
20
+
21
+ CertLogValue = RecordValue | datetime.datetime
22
+
23
+ SKIP_TABLES = [
24
+ "MSysObjects",
25
+ "MSysObjectsShadow",
26
+ "MSysObjids",
27
+ "MSysLocales",
28
+ ]
29
+
30
+ # Value from certutil -view -restrict "RequestID=XX"
31
+ REQUEST_TYPE = {0x100: "PKCS10", 0x40100: "PKCS10, Full Response"}
32
+ REQUEST_DISPOSITION = {0x14: "Issued", 0x1F: "Denied", 0xF: "Ca cert"}
33
+
34
+ REQUEST_STATUS_CODE = {
35
+ 0x0: "The operation completed successfully",
36
+ 0x80094001: "CERTSRV_E_BAD_REQUESTSUBJECT",
37
+ 0x80094002: "CERTSRV_E_NO_REQUEST",
38
+ 0x80094003: "CERTSRV_E_BAD_REQUESTSTATUS",
39
+ 0x80094004: "CERTSRV_E_PROPERTY_EMPTY",
40
+ 0x80094005: "CERTSRV_E_INVALID_CA_CERTIFICATE",
41
+ 0x80094006: "CERTSRV_E_SERVER_SUSPENDED",
42
+ 0x80094007: "CERTSRV_E_ENCODING_LENGTH",
43
+ 0x80094008: "CERTSRV_E_ROLECONFLICT",
44
+ 0x80094009: "CERTSRV_E_RESTRICTEDOFFICER",
45
+ 0x8009400A: "CERTSRV_E_KEY_ARCHIVAL_NOT_CONFIGURED",
46
+ 0x8009400B: "CERTSRV_E_NO_VALID_KRA",
47
+ 0x8009400C: "CERTSRV_E_BAD_REQUEST_KEY_ARCHIVAL",
48
+ 0x8009400D: "CERTSRV_E_NO_CAADMIN_DEFINED",
49
+ 0x8009400E: "CERTSRV_E_BAD_RENEWAL_CERT_ATTRIBUTE",
50
+ 0x8009400F: "CERTSRV_E_NO_DB_SESSIONS",
51
+ 0x80094010: "CERTSRV_E_ALIGNMENT_FAULT",
52
+ 0x80094011: "CERTSRV_E_ENROLL_DENIED",
53
+ 0x80094012: "CERTSRV_E_TEMPLATE_DENIED",
54
+ 0x80094013: "CERTSRV_E_DOWNLEVEL_DC_SSL_OR_UPGRADE",
55
+ 0x80094014: "CERTSRV_E_ADMIN_DENIED_REQUEST",
56
+ 0x80094015: "CERTSRV_E_NO_POLICY_SERVER",
57
+ 0x80094016: "CERTSRV_E_WEAK_SIGNATURE_OR_KEY",
58
+ 0x80094017: "CERTSRV_E_KEY_ATTESTATION_NOT_SUPPORTED",
59
+ 0x80094018: "CERTSRV_E_ENCRYPTION_CERT_REQUIRED",
60
+ 0x80094800: "CERTSRV_E_UNSUPPORTED_CERT_TYPE",
61
+ 0x80094801: "CERTSRV_E_NO_CERT_TYPE",
62
+ 0x80094802: "CERTSRV_E_TEMPLATE_CONFLICT",
63
+ 0x80094803: "CERTSRV_E_SUBJECT_ALT_NAME_REQUIRED",
64
+ 0x80094804: "CERTSRV_E_ARCHIVED_KEY_REQUIRED",
65
+ 0x80094805: "CERTSRV_E_SMIME_REQUIRED",
66
+ 0x80094806: "CERTSRV_E_BAD_RENEWAL_SUBJECT",
67
+ 0x80094807: "CERTSRV_E_BAD_TEMPLATE_VERSION",
68
+ 0x80094808: "CERTSRV_E_TEMPLATE_POLICY_REQUIRED",
69
+ 0x80094809: "CERTSRV_E_SIGNATURE_POLICY_REQUIRED",
70
+ 0x8009480A: "CERTSRV_E_SIGNATURE_COUNT",
71
+ 0x8009480B: "CERTSRV_E_SIGNATURE_REJECTED",
72
+ 0x8009480C: "CERTSRV_E_ISSUANCE_POLICY_REQUIRED",
73
+ 0x8009480D: "CERTSRV_E_SUBJECT_UPN_REQUIRED",
74
+ 0x8009480E: "CERTSRV_E_SUBJECT_DIRECTORY_GUID_REQUIRED",
75
+ 0x8009480F: "CERTSRV_E_SUBJECT_DNS_REQUIRED",
76
+ 0x80094810: "CERTSRV_E_ARCHIVED_KEY_UNEXPECTED",
77
+ 0x80094811: "CERTSRV_E_KEY_LENGTH",
78
+ 0x80094812: "CERTSRV_E_SUBJECT_EMAIL_REQUIRED",
79
+ 0x80094813: "CERTSRV_E_UNKNOWN_CERT_TYPE",
80
+ 0x80094814: "CERTSRV_E_CERT_TYPE_OVERLAP",
81
+ 0x80094815: "CERTSRV_E_TOO_MANY_SIGNATURES",
82
+ 0x80094816: "CERTSRV_E_RENEWAL_BAD_PUBLIC_KEY",
83
+ 0x80094817: "CERTSRV_E_INVALID_EK",
84
+ 0x80094818: "CERTSRV_E_INVALID_IDBINDING",
85
+ 0x80094819: "CERTSRV_E_INVALID_ATTESTATION",
86
+ 0x8009481A: "CERTSRV_E_KEY_ATTESTATION",
87
+ 0x8009481B: "CERTSRV_E_CORRUPT_KEY_ATTESTATION",
88
+ 0x8009481C: "CERTSRV_E_EXPIRED_CHALLENGE",
89
+ 0x8009481D: "CERTSRV_E_INVALID_RESPONSE",
90
+ 0x8009481E: "CERTSRV_E_INVALID_REQUESTID",
91
+ 0x8009481F: "CERTSRV_E_REQUEST_PRECERTIFICATE_MISMATCH",
92
+ 0x80094820: "CERTSRV_E_PENDING_CLIENT_RESPONSE",
93
+ 0x80094821: "CERTSRV_E_SEC_EXT_DIRECTORY_SID_REQUIRED",
94
+ }
95
+
96
+
97
+ class CertLog:
98
+ def __init__(self, fh: BinaryIO):
99
+ self.db = ESE(fh)
100
+
101
+ def tables(self) -> list[Table]:
102
+ return [table for table in self.db.tables() if table.name not in SKIP_TABLES]
103
+
104
+ def records(self, table_name: str) -> Iterator[dict[str, CertLogValue]]:
105
+ try:
106
+ table = self.db.table(table_name)
107
+ except KeyError:
108
+ return None
109
+
110
+ for record in table.records():
111
+ record_data = {"TableName": table.name}
112
+
113
+ for column in table.columns:
114
+ value = record.get(column.name)
115
+
116
+ if column.type == JET_coltyp.DateTime and value:
117
+ value = wintimestamp(value)
118
+
119
+ if table.name == "Requests":
120
+ if column.name == "StatusCode":
121
+ value = REQUEST_STATUS_CODE.get(value & 0xFFFFFFFF, value & 0xFFFFFFFF)
122
+ if column.name == "Disposition":
123
+ value = REQUEST_DISPOSITION.get(value, value)
124
+ if column.name == "RequestType":
125
+ value = REQUEST_TYPE.get(value, value)
126
+
127
+ record_data[column.name] = value
128
+
129
+ yield record_data
130
+
131
+ def entries(self) -> Iterator[dict[str, CertLogValue]]:
132
+ for table in self.tables():
133
+ yield from self.records(table.name)
134
+
135
+
136
+ def main() -> None:
137
+ parser = argparse.ArgumentParser(description="dissect.database.ese Certlog parser")
138
+ parser.add_argument("input", help="certlog database to read")
139
+ parser.add_argument("-t", "--table", metavar="TABLE", help="show only content of TABLE (case sensitive)")
140
+ parser.add_argument("-j", "--json", help="output in JSON format", action="store_true", default=False)
141
+ args = parser.parse_args()
142
+
143
+ with Path(args.input).open("rb") as fh:
144
+ parser = CertLog(fh)
145
+
146
+ for table in parser.tables():
147
+ if args.table and table.name != args.table:
148
+ continue
149
+ for record in parser.records(table.name):
150
+ if args.json:
151
+ print(json.dumps(record, default=str))
152
+ else:
153
+ print(record)
154
+
155
+
156
+ if __name__ == "__main__":
157
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.database
3
- Version: 0.1.dev5
3
+ Version: 0.1.dev6
4
4
  Summary: A Dissect module implementing parsers for various database formats, including Berkeley DB, Microsofts Extensible Storage Engine (ESE) and SQLite3
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: Apache-2.0
@@ -36,6 +36,7 @@ dissect/database/ese/sorting_table.py
36
36
  dissect/database/ese/table.py
37
37
  dissect/database/ese/util.py
38
38
  dissect/database/ese/tools/__init__.py
39
+ dissect/database/ese/tools/certlog.py
39
40
  dissect/database/ese/tools/impacket.py
40
41
  dissect/database/ese/tools/sru.py
41
42
  dissect/database/ese/tools/ual.py
@@ -59,6 +60,7 @@ tests/_data/ese/index.edb.gz
59
60
  tests/_data/ese/large.edb.gz
60
61
  tests/_data/ese/multi.edb.gz
61
62
  tests/_data/ese/text.edb.gz
63
+ tests/_data/ese/tools/CertLog.edb.gz
62
64
  tests/_data/ese/tools/Current.mdb.gz
63
65
  tests/_data/ese/tools/SRUDB.dat.gz
64
66
  tests/_data/sqlite3/empty.sqlite
@@ -79,6 +81,7 @@ tests/ese/test_page.py
79
81
  tests/ese/test_record.py
80
82
  tests/ese/test_table.py
81
83
  tests/ese/tools/__init__.py
84
+ tests/ese/tools/test_certlog.py
82
85
  tests/ese/tools/test_sru.py
83
86
  tests/ese/tools/test_ual.py
84
87
  tests/sqlite3/__init__.py
@@ -58,3 +58,8 @@ def sru_db() -> Iterator[BinaryIO]:
58
58
  @pytest.fixture
59
59
  def ual_db() -> Iterator[BinaryIO]:
60
60
  yield from open_file_gz("_data/ese/tools/Current.mdb.gz")
61
+
62
+
63
+ @pytest.fixture
64
+ def certlog_db() -> Iterator[BinaryIO]:
65
+ yield from open_file_gz("_data/ese/tools/CertLog.edb.gz")
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import BinaryIO
4
+
5
+ from dissect.database.ese.tools.certlog import CertLog
6
+
7
+
8
+ def test_certlog(certlog_db: BinaryIO) -> None:
9
+ db = CertLog(certlog_db)
10
+ assert len(list(db.records("Certificates"))) == 11
11
+ assert len(list(db.records("Requests"))) == 11
12
+ assert len(list(db.records("RequestAttributes"))) == 26
13
+ assert len(list(db.records("CertificateExtensions"))) == 92
14
+ assert len(list(db.records("CRLs"))) == 2