+//
+// This helper tries to add the (new) subject given to the ACL
+// whose validation is currently proceeding through context.
+// This will succeed if the ACL is in standard form, which means
+// a ThresholdAclSubject.
+// The new subject will be added at the front (so it is checked first
+// from now on), and as a side effect we'll notify the client side to
+// re-encode the object.
+// Returns true if the edit could be done, or false if the ACL wasn't
+// standard enough. May throw if the ACL is malformed or otherwise messed up.
+//
+// This is a self-contained helper that is here merely because it's "about"
+// ACLs and has no better home.
+//
+bool SecurityServerAcl::addToStandardACL(const AclValidationContext &context, AclSubject *subject)
+{
+ if (SecurityServerEnvironment *env = context.environment<SecurityServerEnvironment>())
+ if (ThresholdAclSubject *threshold = env->standardSubject(context)) {
+ unsigned size = threshold->count();
+ if (dynamic_cast<KeychainPromptAclSubject *>(threshold->subject(size-1))) {
+ // looks standard enough
+ secdebug("acl", "adding new subject %p to from of threshold ACL", subject);
+ threshold->add(subject, 0);
+
+ // tell the ACL it's been modified
+ context.acl()->changedAcl();
+
+ // trigger a special notification code on (otherwise successful) return
+ Server::connection().overrideReturn(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT);
+ return true;
+ }
+ }
+ secdebug("acl", "ACL is not standard form; cannot edit");
+ return false;
+}
+
+
+//
+// Look at the ACL whose validation is currently proceeding through context.
+// If it LOOKS like a plausible version of a legacy "dot mac item" ACL.
+// We don't have access to the database attributes of the item up here in the
+// securityd sky, so we have to apply a heuristic based on which applications (by path)
+// are given access to the item.
+// So this is strictly a heuristic. The potential downside is that we may inadvertently
+// give access to new .Mac authorized Apple (only) applications when the user only intended
+// a limited set of extremely popular Apple (only) applications that just happen to all be
+// .Mac authorized today. We can live with that.
+//
+bool SecurityServerAcl::looksLikeLegacyDotMac(const AclValidationContext &context)
+{
+ static const char * const prototypicalDotMacPath[] = {
+ "/Applications/Mail.app",
+ "/Applications/Safari.app",
+ "/Applications/iSync.app",
+ "/Applications/System Preferences.app",
+ "/Applications/iCal.app",
+ "/Applications/iChat.app",
+ "/Applications/iTunes.app",
+ "/Applications/Address Book.app",
+ "/Applications/iSync.app",
+ NULL // sentinel
+ };
+
+ static const unsigned threshold = 6;
+
+ if (SecurityServerEnvironment *env = context.environment<SecurityServerEnvironment>()) {
+ if (ThresholdAclSubject *list = env->standardSubject(context)) {
+ unsigned count = list->count();
+ unsigned matches = 0;
+ for (unsigned n = 0; n < count; ++n) {
+ if (CodeSignatureAclSubject *app = dynamic_cast<CodeSignatureAclSubject *>(list->subject(n))) {
+ for (const char * const *p = prototypicalDotMacPath; *p; p++)
+ if (app->path() == *p)
+ matches++;
+ }
+ }
+ secdebug("codesign", "matched %d of %zd candididates (threshold=%d)",
+ matches, sizeof(prototypicalDotMacPath) / sizeof(char *) - 1, threshold);
+ return matches >= threshold;
+ }
+ }
+ return false;
+}
+
+