Modifying the TCC database

Mountain Lion introduced a new iOS-like feature to allow users to be notified when an application requests access to that user’s contacts:

…and to be able to modify this access later:

Why does Final Cut Pro 7 want to access contacts? Final Cut Pro 7 introduced a feature that uses iChat (which doesn’t even really exist in Mountain Lion), therefore when a user first launches FCP, OS X will ask permission to allow FCP to access that user’s contacts.

It might be nice to be able to pre-allow or -disallow access for applications without user intervention, especially in scenarios where user Library data isn’t persistent across logins in a multi-user environment, where users would otherwise be nagged frequently to access what’s likely an empty Contacts database.

These contacts turn out to be stored in an SQLite3 database, located in the user’s library folder:

~/Library/Application Support/com.apple.TCC/TCC.db

This database is managed by the tccd daemon located at:

/System/Library/PrivateFrameworks/TCC.framework/Resources/tccd

We can query it with the built-in sqlite3 command-line tool:

➜ sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db

SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

sqlite> .tables
access access_overrides access_times admin

There’s some useful information in the access table:

sqlite> .dump access
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE access (service TEXT NOT NULL, client TEXT NOT NULL, client_type INTEGER NOT NULL, allowed INTEGER NOT NULL, prompt_count INTEGER NOT NULL, CONSTRAINT KEY PRIMARY KEY (service, client, client_type));
INSERT INTO "access" VALUES('kTCCServiceAddressBook','com.apple.FinalCutPro',0,1,0);
INSERT INTO "access" VALUES('kTCCServiceAddressBook','com.google.Chrome',0,1,0);
COMMIT;

Here we’ve got FCP and Google Chrome (the latter triggered because we visited GMail). The last three integer columns store the values for client_type, allowed, and prompt_count.

Given this very simple database schema, it’s pretty trivial to update this database ourselves directly. In my experience, when the database gets updated, the Security & Privacy preferences pane responds to the change as soon as its window again receives focus.

I wrote a Python script that allows for ad-hoc changes to the allowed column, given an app bundle id. It should also be usable in scenarios where a user may be brand new and not yet had the TCC database created, so it will handle the initial schema creation of the database if it doesn’t already exist. This is available here. It currently assumes you’ll be running the script as the user whose database will be modified.

However, since I originally wrote this script for a very simple purpose on 10.8, Pierce Darragh and Richard Glaser of the University of Utah Marriott Library have taken these ideas and run with them with the Privacy Services Manager tool, and much further expanded the scope of services upon which it can operate, supporting new-since-10.8 OS X features and changes to the underlying mechanisms that control their behaviour. While I haven’t used this tool, it looks like they have put a lot of work into it, so I’d recommend looking into this if managing these controls is of interest to you.

Tagged , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

31 Comments

  1. Oliver
    Posted November 26, 2012 at 9:48 am | Permalink

    Excellent article. I look forward to giving this a try!

  2. bsdjunkie
    Posted May 13, 2013 at 11:17 am | Permalink

    Any link to the sample plist file?

  3. Allister
    Posted May 31, 2013 at 12:47 am | Permalink

    Thanks for your work, the tool, and the writeup! Just to be super-explicit re: usage steps, this would be activated by a launchagent/loginItem to cover any new users, with something like a dotfile whose absence would trigger tccmanager for the Apps we know we want to suppress this for?
    Allister

    • Posted May 31, 2013 at 1:06 pm | Permalink

      Yes, using a LaunchAgent login script is one way to have this run as the user whose TCC DB you want to update. I use a version of Nate Walck’s scriptRunner to do this, which also conveniently has a built-in mechanism to run something “once” if you want. However, you should be able to pass “–allow ” repeatedly and it will just overwrite the existing data it has for that app bundle.

  4. Mike
    Posted October 27, 2013 at 2:44 pm | Permalink

    Thanks for the post! Modifying your work here, I’ve been able to automate Terminal accessibility access in Mavericks for use in bash provisioning routines that include AppleScript snippets.

    sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db “INSERT or REPLACE INTO access values (‘kTCCServiceAccessibility’, ‘com.apple.Terminal’, 0, 1, 0, NULL);”

  5. Klaus
    Posted November 18, 2013 at 6:49 pm | Permalink

    Great information!
    @mike:
    I’ve read that on another site already, but it doesn’t work for me.
    The quotes are messed up but changing them produced an error at INSERT or REPLACE, wrong options.

    I would like to add an Internet Account for a shared Calendar. Would be cool if I could automate it.
    Is that possible?

  6. Thomas
    Posted December 16, 2013 at 10:51 am | Permalink

    Looks like in Mac10.9 they added a new column to the TCC.db, maybe an update here is needed?

    • Posted December 16, 2013 at 10:54 am | Permalink

      Correct. I haven’t yet had time to do an update.

  7. Posted February 11, 2014 at 7:27 pm | Permalink

    FYI

    There are three valid service names: “kTCCServiceAddressBook” (Contacts), “kTCCServiceAccessibility” (Accessibility), and “kTCCServiceUbiquity” (iCloud). And two locations for the tcc.db, one for current user and the other for host.

    ~/Library/Application Support/com.apple.TCC/TCC.db
    /Library/Application Support/com.apple.TCC/TCC.db

    The “kTCCServiceAccessibility” (Accessibility) service used the /Library TCC.db

    • Posted February 13, 2014 at 5:55 pm | Permalink

      FYI, we have a python script in github that works with the three services in github:

      https://github.com/univ-of-utah-marriott-library-apple/tcc_database_manager

      If anybody is interested in checking it out.

      • Posted March 26, 2014 at 9:48 am | Permalink

        Thanks Richard. I’ve finally updated the original post with a link to yours, since you guys have clearly done more work than I have keeping this up to date.

        • Pierce Darragh
          Posted June 26, 2014 at 7:29 pm | Permalink

          Hi Tim,

          I’ve been the main developer for the script Richard has been referencing, and I’ve stopped supporting it and have moved to a more-complete script that can also handle Location Services requests.

          In short, Location Services is handled in an entirely different manner, so I originally had chosen not to combine it with the tcc_database_manager. Recently I decided to merge them after all, and I’ve since put more work into a more unified privacy_services_manager, available here:

          https://github.com/univ-of-utah-marriott-library-apple/privacy_services_manager

          Would you mind updating the link in this post to point to this page instead? I’ve got redirects on the original in the meantime.

          Thanks again for posting this in the first place!

          • Posted June 30, 2014 at 12:39 pm | Permalink

            Hi Pierce, I’ve just updated the original post. Thanks!

  8. TGB
    Posted May 26, 2014 at 3:26 am | Permalink

    The work you guys have all done on this is awesome, and I ended up using tcc_database_manager to solve my problem much more simply an elegantly than trying to figure out sqlite3. My only feedback with that tool is that it doesn’t gracefully handle attempts to reference the (non-existent) Accessibility table when run on 10.8.

    All this really means is having to wrap it as:
    if [ `sw_vers -productVersion | awk -F. ‘{ print $2 }’` -eq 9 ]; then /sbin/tcc_database_manager add accessibility com.example.app; fi

    It would be nice if tcc_database_manager handled it a little more cleanly than:

    Traceback (most recent call last):
    File “/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py”, line 162, in _run_module_as_main
    File “/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py”, line 72, in _run_code
    File “/sbin/tcc_database_manager/__main__.py”, line 85, in
    File “/sbin/tcc_database_manager/__main__.py”, line 59, in main
    File “/sbin/tcc_database_manager/tcc_edit.py”, line 36, in __init__
    sqlite3.OperationalError: unable to open database file

    But otherwise, great work, very grateful.

    • Posted May 26, 2014 at 9:30 am | Permalink

      Thanks for opening an issue on their repo for this!

    • Posted May 27, 2014 at 2:33 pm | Permalink

      Hello TGB:

      Sorry, about the issue we will do some tests and get back to you once we have replicated the bug.

      Does this happen with any version of OS X 10.8 or other computers running OS X 10.8? Just making sure its not an issue with a specific machine vs a global OS X 10.8 issue.

    • Posted May 28, 2014 at 5:47 pm | Permalink

      We think we’ve got this fixed, as of 9f987b8.

      @TGBX, the issue wasn’t quite what you had thought. The way the script was written previously, it should have just written ‘accessibility’ values to the database regardless of whether or not they would be used without checking. The actual issue was that the root-level TCC database at /Library/Application Support/com.apple.TCC/TCC.db did not exist, and my checks to create the file were not done correctly. The new version (3.2) accommodates for this.

      However, seeing as checking for OS version is useful anyway, we went ahead and included that as part of the update. The script now checks for OS compatibility using the method pointed to by @timsutton (thanks, Tim!).

      I hope this works better for you now! Thanks for liking it and using it!

      To get the latest version of the tcc_database_manager, see the GitHub repo:

      https://github.com/univ-of-utah-marriott-library-apple/tcc_database_manager

      If you have any other feature requests or bugs please let us know.

      • Posted June 27, 2014 at 2:36 pm | Permalink

        FYI:

        We have made a management utility to administrate OS X Location Services, Contacts requests, Accessibility, and iCloud access in enterprise environments.

        It runs on OS X 10.8 & 10.9 and has been tested with OS X 10.10 “Yosemite”.

        Since Mac OS X 10.8 “Mountain Lion”, Apple has introduced systems to handle access to certain features of the computer. Among these are Contacts (AddressBook), iCloud (Ubiquity), Accessibility, and Location Services. The first three are managed through one method (SQLite databases called TCC.db hidden throughout the system), while the latter is handled by the locationd daemon through property list files. Originally I created two separate scripts to accommodate the manual modification of these systems. However, eventually I realized that while the internal workings were different, the desired effect was more or less the same. This Privacy Services Manager is a compilation (and mild reformation) of those two scripts.

        The script is fairly straightforward, though there are some options:

        $ privacy_services_manager.py [-hvn] [-l log] [-u user] [–template] [–language] action service applications

        Options

        Option Purpose
        -h, –help Prints help information.
        -v, –version Prints version information.
        -n, –no-log Redirects logging to stdio.
        –template Modify permissions for Apple’s User Template. Only applies to certain services.
        -l log, –log-dest log Redirect logging to the specified file. (This can be overridden by –no-log.)
        -u user, –user user Modify permissions for user, not yourself. (Requires root privileges.)
        –language lang When changing permissions for the User Template, modify the langtemplate.

        Our two other GitHub repos

        – tcc_database_manager
        – location_services_manager

        Are deprecated and replaced by the more-complete & actively developed and supported Privacy Services Manager

        We also have included a package installer/uninstaller for those using package distribution systems or to ease installation for the busy/less technical.

        If you have any questions, problems or features requests feel free to email me off-list or send email or file a issue via the GitHub repo.

        For more information see the following web page:

        https://github.com/univ-of-utah-marriott-library-apple/privacy_services_manager

  9. Posted July 29, 2014 at 5:49 pm | Permalink

    I downloaded and installed the two scripts from U of Utah. I have the problem of an app always asking for permission to access Contacts on startup. I’m very new to Terminal. Even though I read the instructions on Privacy Services Manager, I can’t work out what to input into Terminal to get to where I need be, and what exactly I should change. Can anyone walk me through it, in baby language?

    • Posted July 30, 2014 at 10:52 am | Permalink

      Hi Ian,

      Since the Utah folks may be less likely to see your comment here, and they don’t seem to document a particular way to contact them for support, perhaps your best bet is to open a GitHub issue.

      But, from looking at where their installers copy the scripts (in /usr/local/bin), you should be able to install the two packages and then simply run the privacy_services_manager.py command directly into the Terminal as they document in their README.

      • Posted July 30, 2014 at 10:59 am | Permalink

        Thank you, Tim. I’m able to run the command in Terminal. But there are parameters I don’t understand, and I only need to do one thing: modify one app so it doesn’t trigger the “would like to access contacts” on startup. This is the information I can’t find at this point.

        • Posted July 30, 2014 at 11:07 am | Permalink

          Have you seen “privacy_services_manager.py –help”? That seems to explain everything.

          I just did “privacy_services_manager.py add contacts /Applications/Chess.app”, and now Chess is listed in applications that can access my contacts.

        • Posted July 30, 2014 at 12:54 pm | Permalink

          Hello Ian:

          What application do you want to add? I can give you the specific command.

          Also, what environment do you want to implement privacy_services_manager? Is this just for a user? Or all users that use a computer?

          privacy_services_manager has the ability to modify Apple or a custom user template folder that can be used to customize privacy services for all users using that user template folder.

          Again, if you can reply back, we are willing to help and give you example code to use.

          • Posted July 31, 2014 at 5:23 pm | Permalink

            Well, I thought I had it working, but a restart seemed to reset the changes. The command I input in Terminal was:
            privacy_services_manager.py add contacts /Applications/SpamSieve.app

            SpamSieve has been asking to access my contacts every time I open Mail. After I input that command, I can quit and restart Mail and it is gone. But on reboot, it is back, and there every time I start mail, until I enter that command.

            So the change is not sticking, as it were.

            Any suggestions? Many thanks

          • Posted July 31, 2014 at 5:47 pm | Permalink

            Hello Ian:

            You should probably use the privacy_services_manager contact options. Either file a issue or email us.

            https://github.com/univ-of-utah-marriott-library-apple/privacy_services_manager#contact

            Instead of posting here, but I will answer now.

            First, I would recommend opening up the GUI…

            System Preferences -> Privacy -> Contacts

            So, you get feedback on any changes with the the privacy_services_manager via the GUI.

            So, if you run this command as root like…

            sudo privacy_services_manager.py add contacts /Applications/SpamSieve.app

            or sudo -s in terminal and then run the command

            It will create the tcc database in the root user location, which isn’t what you want to do. We know about this issue and will be fixing it soon and/or provide feedback like are you sure you want to do this, but might not allow it because we can invasion a reason you would want to do this.

            Anyway, instead you want to either have your terminal as the user you want to the privacy_services_manager to make modifications and run the command…

            privacy_services_manager.py add contacts /Applications/SpamSieve.app

            Or if you are running terminal as root…

            privacy_services_manager.py –user [USERNAME] add contacts

            Changing [USERNAME] to your username

            You should see the GUI add SpamSieve and check it in System Preferences.

    • Posted July 30, 2014 at 12:41 pm | Permalink

      Hello Ian:

      Sorry about the confusion with “privacy_services_manager”. We will work on the web and script documentation adding more details and examples.

      So, you should be able to run the command…

      privacy_services_manager.py add contacts /path/to/my.app

      or using the bundle identifier for the application. To find an application’s bundle identifier or bundle path, use the app_lookup.py script in the Management Tools suite. As an example, I will lookup the information on Safari:

      $ app_lookup.py safari
      Safari
      BID: com.apple.Safari
      Path: /Applications/Safari.app
      Info.plist: /Applications/Safari.app/Contents/Info.plist
      Executable: /Applications/Safari.app/Contents/MacOS/Safari

      So, see the BID (i.e. Bundle ID) for the bundle identifier.

      For example…

      privacy_services_manager.py add contacts com.apple.Safari

      You can also find the bundle identifier by opening the info.plist file in the application bundle.

      For example, for Safari…

      You select the application, and CONTROL or Right click and select “Show Package Contents”. Then open the folder “Contents” and then open “Info.plist” with a text editor like TextMate, BBEdit, TextWrangler, etc.

      Look for the key “CFBundleIdentifier”. For example, this is what it looks like for Safari application

      CFBundleIdentifier
      com.apple.Safari

      Or you can specify the application using the shortname as it would be found by Spotlight, e.g. safari, my app like:

      privacy_services_manager.py add contacts safari

      The primary developer, Pierce Darragh, presented on the privacy_services_manager at our last month campus Apple IT meeting. You can view/download the presentation video/slides in our campus iTunes U site.

      Presentation Video

      Presentation Slides

      If you are willing to help make any suggestions orb the documentation and script help, we would appreciate it. So, the tools is beneficial and used by as much of the community as possible.

      If you have any other questions, suggestions or problems in regards to privacy_services_manager, please send use feedback or email. See the github repo for details on sending email or feedback:

      https://github.com/univ-of-utah-marriott-library-apple/privacy_services_manager#contact

Leave a Reply