+
+ simpleFeature("root_only", ^{
+ UnixError::check(::chmod(dbPath(), S_IRUSR | S_IWUSR));
+ });
+
+ simpleFeature("notarized_apps", ^{
+
+ // Insert a set of notarization requirements for notarized applications and installers, with a priority that will be higher than developer id priorities
+ // so they are guaranteed to match first.
+ SQLite::Statement addNotarizedExecutables(*this,
+ "INSERT INTO authority (type, allow, flags, priority, label, requirement) VALUES (1, 1, 2, 5.0, 'Notarized Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized')");
+ addNotarizedExecutables.execute();
+
+ SQLite::Statement addNotarizedInstallers(*this,
+ "INSERT INTO authority (type, allow, flags, priority, label, requirement) VALUES (2, 1, 2, 5.0, 'Notarized Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and notarized')");
+ addNotarizedInstallers.execute();
+
+ // Bump the priority on apple system, apple installer, and mac app store entries so they are evaluated before Developer ID variants.
+ // This is important because notarized variants meet the requirement of the Developer ID variant and would could match that too.
+ SQLite::Statement bumpAppleSystemPriority(*this,
+ "UPDATE authority SET priority = 20.0 WHERE label = 'Apple System'");
+ bumpAppleSystemPriority.execute();
+
+ SQLite::Statement bumpAppleInstallerPriority(*this,
+ "UPDATE authority SET priority = 20.0 WHERE label = 'Apple Installer'");
+ bumpAppleInstallerPriority.execute();
+
+ SQLite::Statement bumpMacAppStorePriority(*this,
+ "UPDATE authority SET priority = 10.0 WHERE label = 'Mac App Store'");
+ bumpMacAppStorePriority.execute();
+ });
+
+ {
+ SQLite::Transaction devIdRequirementUpgrades(*this);
+
+ simpleFeatureNoTransaction("legacy_devid", ^{
+ auto migrateReq = [](auto db, int type, string req) {
+ const string legacy =
+ " and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] absent or "
+ "certificate leaf[timestamp.1.2.840.113635.100.6.1.33] < timestamp \"20190408000000Z\")";
+
+ const string unnotarized =
+ " and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] exists and "
+ "certificate leaf[timestamp.1.2.840.113635.100.6.1.33] >= timestamp \"20190408000000Z\")";
+
+ SQLite::Statement update(*db, "UPDATE OR IGNORE authority "
+ "SET requirement = :newreq "
+ "WHERE requirement = :oldreq "
+ " AND type = :type "
+ " AND label = 'Developer ID'");
+ update.bind(":oldreq") = req;
+ update.bind(":type") = type;
+ update.bind(":newreq") = req + legacy;
+ update.execute();
+
+ SQLite::Statement insert(*db, "INSERT OR IGNORE INTO authority "
+ "(type, requirement, allow, priority, label) "
+ "VALUES "
+ "(:type, :req, 0, 4.0, "
+ "'Unnotarized Developer ID')");
+ insert.bind(":type") = type;
+ insert.bind(":req") = req + unnotarized;
+ insert.execute();
+ };
+
+ migrateReq(this, 1, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists");
+ migrateReq(this, 2, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])");
+ migrateReq(this, 3, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists");
+ });
+
+ // Add simpleFeatureNoTransaction for going from the requirements create above, to add secure timestamps in requirements, here before the commit
+
+ devIdRequirementUpgrades.commit();
+ }