;;;;;; Copyright 2013 Apple Inc. All rights reserved.
;;;;;;
;;;;;; Sandbox profile for CloudDocs's bird on OS X.
;;;;;;
(version 1)
(deny default)
(import "system.sb")
(import "opendirectory.sb")
(import "com.apple.corefoundation.sb")
(corefoundation)
(allow lsopen)
(allow mach-per-user-lookup)
(allow distributed-notification-post)
(allow user-preference*
       (preference-domain "com.apple.bird")
       (preference-domain "com.apple.fileproviderd")
       (preference-domain "com.apple.iclouddrive.features")
       (preference-domain "com.apple.security.revocation") ;; <rdar:
       (preference-domain "com.apple.bird.containers.notifications")
)
(allow user-preference-read ;; <rdar:
       (preference-domain "com.apple.security")
       (preference-domain "com.apple.Security")
       (preference-domain "com.apple.Preferences")
)
;; Homedir-relative path filters
(define (home-regex home-relative-regex)
       (regex (string-append "^" (regex-quote (param "_HOME")) home-relative-regex)))
(define (home-subpath home-relative-subpath)
       (subpath (string-append (param "_HOME") home-relative-subpath)))
(define (home-literal home-relative-literal)
       (literal (string-append (param "_HOME") home-relative-literal)))
;; AppSupport-related path filters
(define (appsupport-subpath appsupport-relative-subpath)
       (subpath (string-append (param "_APP_SUPPORT") appsupport-relative-subpath)))
;; UUID pattern matching stolen from AppSandbox/application.sb
;;; <rdar:
;;; UUID of the form: XXXXXXXX-XXXX-XXXX--XXXX-XXXXXXXXXXXX
;;; That's 8X-4X-4X-4X-12X; where X = "[0-9A-F]", length(X) = 8
;;; Return a regex string which matches capital hex digit patterns
;;; pattern descriptor is an list of integers where the element specifies the repeat
;;; count of the hex digit; 0 means insert a dash
;;; You can paste these functions into: https:
(define (HEX-pattern-match-generator pattern-descriptor)
    (letrec ((pattern-string ""))
        (for-each (lambda (repeat-count)
            (if (zero? repeat-count)
                (set! pattern-string (string-append pattern-string "-"))
                (let appender ((count repeat-count))
                    (if (> count 0)
                        (begin
                            (set! pattern-string (string-append pattern-string "[0-9A-F]"))
                            (appender (- count 1)))))))
        pattern-descriptor)
    pattern-string)
)
;; return a regex pattern matching string for 8-4-4-4-12 UUIDs:
(define (uuid-HEX-pattern-match-string)
(HEX-pattern-match-generator '(8 0 4 0 4 0 4 0 12)))
;; global to hold the computed UUID matching pattern.
(define *uuid-pattern* "")
(define (uuid-regex-string)
       (if (zero? (string-length *uuid-pattern*))
              (set! *uuid-pattern* (uuid-HEX-pattern-match-string)))
       *uuid-pattern*
)
;; root when running in enterprise persona context
(define (enterprise-context-root)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Daemon Containers/" (uuid-regex-string) #"(/|$)"))
)
(define (enterprise-context-tmp)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Daemon Containers/" (uuid-regex-string) #"/tmp/com.apple.bird(/|$)"))
)
(define (enterprise-context-library)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Daemon Containers/" (uuid-regex-string) #"/Data/Library/Application Support/CloudDocs(/|$)"))
)
(define (enterprise-cloudkit-cache)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Caches/CloudKit/com.apple.bird/"))
)
(define (legacy-enterprise-provided-files)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Group Containers/group.com.apple.CloudDocs/File Provider Storage(/|$)"))
)
(define (fpfs-enterprise-provided-files)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Group Containers/group.com.apple.iCloudDrive/File Provider Storage(/|$)"))
)
(define (fpfs-primary-provided-files)
       (home-regex "/Library/Group Containers/group.com.apple.iCloudDrive/File Provider Storage(/|$)")
)
(define (fpfs-enterprise-provided-files-secondary)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Daemon Containers/" (uuid-regex-string) #"/Data/Library/Mobile Documents(/|$)"))
)
;; allow files in the FP wharf if we have an extension for them
(define (fileprovider-wharf)
    (require-all
       (home-regex (string-append "/Library/Application Support/FileProvider/" (uuid-regex-string) #"/wharf/wharf/propagate(/|$)"))
       (extension "com.apple.app-sandbox.read-write"))
)
;; allow files in the enterprise FP wharf if we have an extension for them
(define (fileprovider-enterprise-wharf)
    (require-all
       (regex (string-append "^/Volumes/"
           (uuid-regex-string) #"/Library/Daemon Containers/"
           (uuid-regex-string) #"/Library/Application Support/FileProvider/"
           (uuid-regex-string) #"/wharf/wharf/propagate(/|$)"))
       (extension "com.apple.app-sandbox.read-write"))
)
(define (enterprise-clouddocs-subpath appsupport-relative-subpath)
       (regex (string-append "^/Volumes/" (uuid-regex-string) #"/Library/Daemon Containers/" (uuid-regex-string) #"/Data/Library/Application Support/CloudDocs/" appsupport-relative-subpath))
)
;;; Networking for Config Plist
(system-network)
(allow network-outbound
        (literal "/private/var/run/mDNSResponder")
        (remote tcp)
)
(allow ipc-posix-shm-read-data
 (ipc-posix-name "FNetwork.defaultStorageSession")
 (ipc-posix-name "apple.shm.notification_center")
 (ipc-posix-name-regex #"^/tmp/com\.apple\.csseed\.[0-9]+$")
)
(allow ipc-posix-shm-read-data ipc-posix-shm-write-data
 (ipc-posix-name "com.apple.AppleDatabaseChanged")
)
(allow file-read*
 (subpath "/AppleInternal/Library/Preferences/Logging") ;; rdar:
 (subpath "/private/var/db/mds")
 (subpath "/Library/QuickLook")
 (home-subpath "/Library/QuickLook")
 (home-literal "/.CFUserTextEncoding")
 ;; IconServices rdar:
 (regex #"^/private/var/folders/[^/]+/[^/]+/[^/]+/com\.apple\.iconservices/store\.index")
 (subpath "/Library/Caches/com.apple.iconservices.store")
 ;; App lookup rdar:
 (regex #"^/.*/Pages.app")
 (regex #"^/.*/Keynote.app")
 (regex #"^/.*/Numbers.app")
 ;; DiagnosticMessagesClient check (stat ==> file-read-metadata)
 (literal "/Library/Caches/com.apple.DiagnosticReporting.HasBeenAppleInternal")
)
(deny file-write-setugid)
(allow file-read* file-write*
       (regex #"^/private/var/folders/[^/]+/[^/]+/[^/]+/com\.apple\.bird/mds($|/)")
       (mount-relative-regex #"^/\.TemporaryItems(/|$)") ;;; Safe Saves use .TemporaryItems, see e.g. <rdar:
       (appsupport-subpath "/CloudDocs")
       (appsupport-subpath "/Ubiquity")
       (subpath (param "_CACHE"))
       (subpath (param "_ROOT"))
       (regex (string-append "^" (regex-quote (param "_ROOT")) #"\.")) ;; <rdar:
       (subpath (param "_TMP"))
       (subpath (param "_CS_DARWIN_USER_DIR"))
       (subpath (param "_CS_DARWIN_USER_CACHE_DIR"))
       (home-literal "/Library/Caches") ;; <rdar:
       (home-literal "/Library/Caches/CloudKit") ;; <rdar:
       (home-subpath "/Library/Caches/CloudKit/com.apple.clouddocs")
       (home-subpath "/Library/Caches/CloudKit/com.apple.bird")
       (home-subpath "/Library/Caches/com.apple.ubd")
       (home-subpath "/Library/Containers/com.apple.bird")
       (home-subpath "/Library/Logs/Ubiquity")
       ;; Workaround for <rdar:
       (home-subpath "/Library/Caches/CloudKit/com.apple.cloudd")
       ;; <rdar:
       (home-subpath "/Library/Caches/com.apple.nsurlsessiond/Downloads/com.apple.bird")
       (home-subpath "/Desktop")
       (home-subpath "/Documents")
       (fpfs-primary-provided-files)
       ;; Enterprise Data Separation rules
       (enterprise-context-tmp)
       (enterprise-context-root)
       (enterprise-context-library)
       (enterprise-cloudkit-cache)
       (legacy-enterprise-provided-files)
       (fpfs-enterprise-provided-files)
       (fpfs-enterprise-provided-files-secondary)
       (extension "com.apple.sandbox.container")
       (fileprovider-wharf)
       (fileprovider-enterprise-wharf)
       ;; Access group containers with extension from containermanagerd
       (extension "com.apple.sandbox.application-group")
)
;;; Revisiond client (stolen from iOS, should go to GS framework.sb eventually)
(define (revisiond-client)
    (allow mach-lookup (global-name "com.apple.revisiond"))
    ;; Individual revisions vended by revisiond (read-only access).
    (allow file-read* (require-all
        (vnode-type REGULAR-FILE DIRECTORY SYMLINK)
        (mount-relative-regex #"^/\.DocumentRevisions-V100/(AllUIDs|PerUID)/")
        (extension "com.apple.revisiond.revision"
                   "com.apple.app-sandbox.read")
    ))
    ;; Access to revisiond's staging area for adding new document revisiond (read-write access).
    (allow file-read* file-write* (require-all
         (vnode-type REGULAR-FILE DIRECTORY SYMLINK)
         (mount-relative-regex #"^/\.DocumentRevisions-V100/staging/")
         (extension "com.apple.revisiond.staging"
                    "com.apple.app-sandbox.read-write")
    ))
)
(revisiond-client)
;;; Extensions to ubiquity containers
(allow file-issue-extension (require-all
       (require-any
           (subpath (param "_ROOT"))
           (legacy-enterprise-provided-files)
           (fpfs-enterprise-provided-files)
           (fpfs-enterprise-provided-files-secondary)
           (home-subpath "/Desktop")
           (home-subpath "/Documents")
           (appsupport-subpath "/CloudDocs/session/r")
           (appsupport-subpath "/CloudDocs/session/containers")
           (appsupport-subpath "/CloudDocs/session/telemetry-db")
           (enterprise-clouddocs-subpath "session/r")
           (enterprise-clouddocs-subpath "session/containers")
           (enterprise-clouddocs-subpath "session/telemetry-db")
           (home-subpath "/Library/Caches/com.apple.bird"))
       (require-any
           (extension-class "com.apple.librarian.ubiquity-container")
           (extension-class "com.apple.app-sandbox.read")
           (extension-class "com.apple.app-sandbox.read-write"))
))
;; Preferences access
(define (preference-read domain)
    (allow file-read*
      (home-literal (string-append "/Library/Preferences/" domain ".plist"))
      (home-regex (string-append #"/Library/Preferences/ByHost/" (regex-quote domain) #"\.[^/]*\.plist$")))
      (allow user-preference-read (preference-domain domain)))
(define (preference-rw domain)
    (allow file-read* file-write*
        (home-literal (string-append "/Library/Preferences/" domain ".plist"))
        (home-regex (string-append #"/Library/Preferences/ByHost/" (regex-quote domain) #"\.[^/]*\.plist$")))
        (allow user-preference-read (preference-domain domain))
        (allow user-preference-write (preference-domain domain)))
(preference-read ".GlobalPreferences")
(preference-read "com.apple.bird")
(preference-read "com.apple.mmcs")
(preference-read "com.apple.CloudKit.BehaviorOptions")
(preference-read "com.apple.DebugSymbols")
(preference-read "com.apple.security.revocation")
(preference-read "com.apple.cache_delete")
(preference-rw "MobileMeAccounts") ;; Get rid of this as soon as we can adopt Account.framework
(preference-rw "com.apple.fileproviderd")
(allow file-read-metadata
       (literal (param "_HOME"))
       (literal "/AppleInternal")
)
;; FIXME get rid of this, this is needed for fsevents because they realpath()
;; <rdar:
(allow file-read-metadata (subpath "/"))
(allow file-read*
       (literal "/")
       (literal "/Library/Preferences/.GlobalPreferences.plist")
       (literal "/Library/Preferences/com.apple.security.plist")
       (literal "/Library/Preferences/SystemConfiguration/preferences.plist")
       (literal "/Library/Preferences/com.apple.AOSKit.plist")
       (literal "/Library/Application Support/CrashReporter/SubmitDiagInfo.domains")
       (literal "/Library/Application Support/CrashReporter/DiagnosticMessagesHistory.plist")
)
(allow mach-lookup
       (global-name "com.apple.FSEvents")
       (global-name "com.apple.FileCoordination")
       (global-name "com.apple.metadata.mds")
       (global-name "com.apple.windowserver.active")
       (global-name "com.apple.UNCUserNotification")
       (global-name "com.apple.usernotifications.listener")
       (global-name "com.apple.coreservices.quarantine-resolver")
       (global-name "com.apple.DiskArbitration.diskarbitrationd")
       (global-name "com.apple.cache_delete")
       (global-name "com.apple.analyticsd")
       (global-name "com.apple.rtcreportingd")
;; IOPMConnectionGetSystemCapabilities
       (global-name "com.apple.PowerManagement.control")
;; CloudKit
       (global-name "com.apple.cloudd")
;; AOS
        (global-name "com.apple.icloudusernotification.agent")
;; CoreSymbolication for our logs
       (global-name "com.apple.coresymbolicationd")
;; NSProgress
       (global-name "com.apple.ProgressReporting")
;; OS X only: QuickLook for thumbnails
       (global-name "com.apple.quicklook")
       (global-name "com.apple.quicklook.ThumbnailsAgent")
;; OS X only: NSURL bookmarkDataWithOptions calls LaunchServices which calls IconServices rdar:
 (global-name "com.apple.iconservices")
 (global-name "com.apple.iconservices.store")
;; OS X only: LaunchServices brings lsd to OS X (see 19378357)
       (global-name "com.apple.lsd.mapdb")
;; aps
       (global-name "com.apple.apsd")
;; Quick Look logging
       (global-name "com.apple.decalog4.incoming")
;; TCC
       (global-name "com.apple.tccd")
;; Config plist
       (global-name "com.apple.cookied")
       (global-name "com.apple.SecurityServer")
       (global-name "com.apple.ocspd")
       (global-name "com.apple.nsurlsessiond")
       (global-name "com.apple.securityd.xpc")
       (global-name "com.apple.accountsd.accountmanager")
       (global-name "com.apple.usernoted.client")
;; SFL <rdar:
        (global-name "com.apple.coreservices.sharedfilelistd.xpc")
        (global-name "com.apple.coreservices.sharedfilelistd.mig")
        (global-name "com.apple.coreservices.sharedfilelistd.async-mig")
;; LS Register App <rdar:
        (global-name "com.apple.lsd.modifydb")
        (global-name "com.apple.DesktopServicesHelper")
;; Used by sharing acceptation flow to select file in Finder (25639025)
        (global-name "com.apple.coreservices.launchservicesd")
        (global-name "com.apple.coreservices.appleevents")
;; fileproviderd
        (global-name "com.apple.FileProvider")
;; AutoBugCapture
        (global-name "com.apple.symptom_diagnostics")
;; Anisette (see rdar:
        (global-name "com.apple.ak.anisette.xpc")
;; EDS
        (global-name "com.apple.mobile.keybagd.xpc")
        (global-name "com.apple.containermanagerd")
        (global-name "com.apple.mobile.usermanagerd.xpc")
        (global-name "com.apple.mobile.keybagd.UserManager.xpc")
;; Reveal in Finder
        (global-name "com.apple.pbs.fetch_services")
        (global-name "com.apple.pasteboard.1")
        (global-name "com.apple.siri.VoiceShortcuts.xpc")
        (global-name "com.apple.finder.ServiceProvider")
;; DE
        (global-name "com.apple.pluginkit.pkd")
;; TTR
        (global-name "com.apple.TapToRadarKit.service")
;; Telemetry
        (global-name "com.apple.ak.auth.xpc")
        (global-name "com.apple.tccd.system")
;; BGST
        (global-name "com.apple.duetactivityscheduler")
;; MobileSoftwareUpdate daemon
        (global-name "com.apple.mobile.softwareupdated")
)
(allow user-preference-read (preference-domain "com.apple.CloudKit"))
(allow user-preference-read (preference-domain "pbs"))
;; Allow read-only access to necessary folders in $HOME/Library/Trial
(allow file-read*
    (home-subpath "/Library/Trial/NamespaceDescriptors"))
(allow file-read*
    (home-subpath "/Library/Trial/Treatments/255"))
;; Used by sharing acceptation flow to select file in Finder (25639025)
(allow appleevent-send)
;; from application.sb
(allow system-fsctl
       (fsctl-command (_IO "J" 2)) ;; APFSIOC_MAINTAIN_DIR_STATS
       (fsctl-command (_IO "J" 32)) ;; APFSIOC_GET_DIR_STATS_EXT
       (fsctl-command (_IO "h" 24))
       (fsctl-command (_IO "h" 30))
       (fsctl-command (_IO "h" 31))
       (fsctl-command (_IO "h" 32))
       (fsctl-command (_IO "z" 12))
       (fsctl-command (_IO "z" 19))
       (fsctl-command (_IO "z" 23))
       (fsctl-command APFSIOC_DOC_ID_TO_FILE_ID)
)
;; allow F_PATHPKG_CHECK (23424418)
(if (defined? 'system-package-check)
(allow system-package-check))
;; remove sync root bits when necessary
(allow system-fsctl
    (fsctl-command
        APFSIOC_SYNC_ROOT_SET_FLAG
    )
)
;; rules for Sandbox extensions
(with-filter (extension "com.apple.app-sandbox.read")
  (allow file-read*)
  (allow file-issue-extension (extension-class "com.apple.app-sandbox.read")))
(with-filter (extension "com.apple.app-sandbox.read-write")
  (allow file-read* file-write*)
  (allow file-issue-extension (extension-class "com.apple.app-sandbox.read" "com.apple.app-sandbox.read-write")))
;; rules for uploading thumbnails.
(allow file-issue-extension
    (require-all
        (require-any
            (appsupport-subpath "/CloudDocs/session/i")
            (appsupport-subpath "/CloudDocs/session/u")
            (enterprise-clouddocs-subpath "session/i")
            (enterprise-clouddocs-subpath "session/u"))
        (require-any
            (extension-class "com.apple.app-sandbox.read")
            (extension-class "com.apple.quicklook.readonly"))))
;; rules for giving write access to write thumbnails after moving to QLThumbnailGenerationRequest
(allow file-issue-extension
    (require-all
        (require-any
            (appsupport-subpath "/CloudDocs/session/t")
            (enterprise-clouddocs-subpath "session/t"))
        (require-any
            (extension-class "com.apple.app-sandbox.read-write"))))
;;; Allow generating thumbnail using quicklook for upload v2 (reading the file)
(allow file-issue-extension
       (require-all
           (require-any
               (require-all
                   (appsupport-subpath "/CloudDocs/session/se/jobs/")
                   (regex (string-append #"/session/se/jobs/" (uuid-regex-string))))
               (require-all
                   (enterprise-clouddocs-subpath "session/se/jobs/")
                   (regex (string-append #"/session/se/jobs/" (uuid-regex-string))))
           )
           (require-any
               (extension-class "com.apple.app-sandbox.read")
               (extension-class "com.apple.quicklook.readonly"))))
;;; Allow generating thumbnail using quicklook for upload v2 (Saving the thumbnail)
(allow file-issue-extension
    (require-all
        (extension-class "com.apple.app-sandbox.read-write")
        (require-any
            (require-all
                (appsupport-subpath "/CloudDocs/session/se/jobs/")
                (regex (string-append #"/session/se/jobs/" (uuid-regex-string) #"/thumbnail.jpg")))
            (require-all
                (enterprise-clouddocs-subpath "session/se/jobs/")
                (regex (string-append #"/session/se/jobs/" (uuid-regex-string) #"/thumbnail.jpg"))))))
