Performing Privileged Operations in an OS X Application

I am currently developing an OS X application. The application needs to perform some operations that require root privileges (installing and uninstalling launchd daemons, sending signals to other users' processes, etc.) So I started looking for some documentation about how to do that. I figured it would take a few minutes.

A day later, I finally think I understand it. The solution isn't complicated, but learning about it was difficult for a few reasons:

  • Apple's "Authorization Services Programming Guide" is woefully out of date. It tells you to use AuthorizationExecuteWithPrivileges(), but that has been deprecated since OS X 10.7. It also has links to sample code that doesn't exist anymore. (Apple developer documentation people: It seems many of your docs are way out of date. Pls fix.)
  • Apple provides a SMJobBless sample that purports to demonstrate how to use the new SMJobBless() API that replaces AuthorizationExecuteWithPrivileges(). However, while it does indeed install some kind of service that could in theory run as root, the service it installs doesn't do anything, so it is useless as an example. (But you could waste a lot of time with it before you figure that out.)
  • A lot of old documentation and sample code for the original low-level XPC API is still floating around, but once you have a clue (which I didn't), you'll just use the high-level NSXPCConnection API.

So, in the hope I can help others avoid this tortuous path, here is how i would suggest others learn how to do this:

And here is what I wish somebody could have told me before I started:

  • What you will need to do is create a "helper tool" application to perform the privileged operations. This will be a command-line app that creates an XPC listener and handles requests.
  • The helper app has to have an info.plist and a launchd plist with some magical keys (see the EvenBetterAuthorizationSample for details)
  • The helper app will be embedded in the main app's package.
  • The main app will use the AuthorizationCreate() and SMJobBless() functions to authenticate the user and install the helper tool as a privileged launchd service. (This is the point where the system will display a dialog asking the user for an admin username and password.)
  • After the helper tool is installed, use -[NSXPCConnection initWithMachServiceName:options:] to connect to the helper tool. This will launch the helper tool on demand, running with root privileges.

Setting Up a New Mac, My Way

Over the past couple of weeks, I've set up a few Mac OS X machines to do development of iOS and Android apps. Doing this used to be an all-day chore, but things like app stores, iCloud, and Dropbox have streamlined the process a lot.

(I could streamline the process even more by cloning an existing drive or virtual machine, but I'd rather install everything from scratch to avoid the presence of old cruft.)

As a reminder to myself, and to help out anyone else who needs to do this, here is my procedure for setting up an OS X machine the way I like it:

  1. Install/re-install OS X.
  2. During the OS X setup process, use the same login account name and password that I use on other computers, and provide the Apple IDs for iCloud and iTunes (which are different, in my case).
  3. Open System Preferences and do the following:
    • In the General panel, set Sidebar icon size to Small and Show scroll bars to Always.
    • In the Mission Control panel, uncheck the Automatically rearrange Spaces based on most recent use box.
    • In the Mouse and Trackpad panels, set all speeds to two ticks less than the maximums, and enable all the gestures.
    • In the Keyboard panel, set Key Repeat and Delay Until Repeat all the way to the right, and check the Use F1, F2, etc. keys as standard function keys box
    • In the Keyboard panel, go to the Shortcuts tab, select Services, and then enable the New Terminal at Folder service.
    • In the iCloud panel, enable everything.
    • In the Sharing panel, set the Computer Name to something unique (not "Kristopher's computer") and enable Remote Management, Remote Login, and File Sharing.
    • Set up Time Machine
    • If this is a virtual machine, go to the Desktop & Screen Saver panel and turn off the screen saver, and go to the Energy Saver panel and set the sleep sliders to Never.
  4. Use the Software Update... menu item to install any system updates that are available, and reboot if necessary.
  5. If this is a virtual machine, install VMWare Tools or Parallels Tools.
  6. Download and install these packages (using serial numbers and licenses stored in 1Password):
  7. Open the App Store app and install these applications (skipping any that are not needed):
    • Xcode
    • CodeRunner
    • OS X Server
    • Moom
    • PopClip
    • Alfred
    • Pages
    • Soulver
    • Evernote
    • Sketch
    • Skitch
    • Pixelmator
    • MultiMarkdown Composer
  8. Open Xcode, accept the license agreement and download simulators and documentation. On a Terminal command line, execute xcode-select --install to install the command-line tools.
  9. Install Homebrew
  10. Open the Terminal application and run java. Download and install the JDK when prompted.
  11. Download and install the ADT Bundle. (Note: This is old; now Android Studio is the thing to download and install.)
    • After installation, launch the Eclipse application. Choose the Android SDK Manager menu item, and install/update everything in these subtrees:
      • Tools
      • Android 4.3 (or whatever the newest API level is)
      • Extras
    • Choose Help > Install New Software.... Click the Add... button. Add this repository and install the Eclipse Color Theme plugin:
      • Name: Eclipse Color Theme Update Site
      • Location: http://eclipse-color-theme.github.io/update/
    • Download and install latest the HAXM driver from https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager. (If that link is broken, go to https://software.intel.com/en-us/android/ and look for a HAXM download link.)
  12. Set up ~/.bashrc to run my shared scripts that are in ~/Dropbox/bin.
  13. Execute this in Terminal: chflags nohidden ~/Library
  14. Set up ssh keys for Bitbucket and GitHub.

Then to verify everything is ready to go, I use Git to grab the source code for an iOS app, and build it and run it, and then do the same for an Android app.

(For my Windows setup, see Setting Up Windows, My Way.)

Solving "Symbol not found: _Perl_Gthr_key_ptr" When Running git-svn on Certain Unnamed Operating System Beta Versions

Let's say that you are using a beta version of a new operating system that you can't name because it is covered by a non-disclosure agreement, and you have also installed the newest version of its development tools, which are also covered by NDA, and when you try to run the git svn command, you get this output:

dyld: lazy symbol binding failed: Symbol not found: _Perl_Gthr_key_ptr
  Referenced from: /usr/../Library/Perl/5.12/darwin-thread-multi-2level/auto/SVN/_Core/_Core.bundle
  Expected in: flat namespace

dyld: Symbol not found: _Perl_Gthr_key_ptr
  Referenced from: /usr/../Library/Perl/5.12/darwin-thread-multi-2level/auto/SVN/_Core/_Core.bundle
  Expected in: flat namespace

error: git-svn died of signal 5

Apparently, the problem is that git-svn is implemented in Perl, and there is something wrong with the Perl configuration used when you run /usr/bin/git.

What do you do?

It turns out you can fix this by putting the Git executables provided by the new development tools at the head of your PATH, by executing this command (or adding it to .bashrc):

export PATH="/Applications/XXXXX.app/Contents/Developer/usr/libexec/git-core":$PATH

where XXXXX.app is the unnamed development tool.

Alternatively, you can add all the command-line tools to your PATH like this:

export PATH=”/Applications/XXXXX.app/Contents/Developer/usr/bin/”:$PATH

Credit to Vandad Nahavandipoor for the hint.

Another option would be to use the xcrun utility to run git. You can do this:

xcrun git svn blah-blah-blah

or put this into your .bashrc so that you don't have to remember to type xcrun:

alias git='xcrun git'

If you are the kind of person who thinks its a good idea to replace system files with symlinks, you might try symlinking /usr/bin/git to /Applications/XXXXX.app/Contents/Developer/usr/libexec/git-core/git. However, that alone doesn't work, because Git will still run the git-svn executable from its default location, /Library/Developer/CommandLineTools/usr/libexec/git-core, and you will still have the _Perl_Gthr_key_ptr problem. So you also need to symlink the default location to /Applications/XXXXX.app/Contents/Developer/usr/libexec/git-core/, or set the GIT_EXEC_PATH environment variable.

Mac Software for Software Developers

A fellow developer who is getting his first Mac asked me what software he should get. Here is a list of Mac software that I, as a software developer, find useful.

"Speak Count of Words on Clipboard" Automator Service

As part of my "write a blog entry every day during November" commitment, I considered imposing a minimum word limit for each entry. I've decided against that, because I don't want to feel pressure to add filler, but before deciding that, I created an Automator service that would help me to count words.

A Little Service That Converts Files to EPUB Format

To make it easier to put content on my Sony Reader, I've created a service, using Automator, that will invoke calibre's ebook-convert tool on files selected in the Finder.

Building Emacs from Source for Mac OS X

There are a few binary Emacs packages for OS X floating around out there, but I always build it myself from the sources. This usually results in an Emacs that works the way I expect, rather than the way some "helpful" distributor thinks it ought to work.

I'll assume you have the developer tools and bzr installed, and know how to open Terminal and type some commands. Here are the commands you need to type:

bzr init-repo --2a emacs/

cd emacs

bzr branch bzr://bzr.savannah.gnu.org/emacs/trunk/

cd trunk

./configure --with-ns

make install

When this is complete, you'll end up with Emacs.app in the nextstep subdirectory. You can run Emacs.app from there, or copy it to your Applications directory.

Update 2010/10/29: Discovered that the Emacs team now uses Bazaar (bzr) rather than CVS. Updated the instructions accordingly, following advice from http://www.emacswiki.org/emacs/EmacsForMacOS and http://www.emacswiki.org/emacs/BzrForEmacsDevs. Also, found what appears to be a faithful binary distribution at http://emacsformacosx.com/.

We Loves the Preciousss

It's not always easy to be an Apple fanboy: read "In Nomine Jobs, et Woz, et Spiritus Schiller" by Merlin Mann

I've installed Snow Leopard on my old 13-inch white Macbook (which I don't use for anything important). I've had no problems with it, but I'm going to wait a month or two before upgrading the Macs that I rely on. I want to wait until Apple releases a patch or two, and I need to let some dinosaurs catch up.

Snow Leopard is a nice upgrade which is definitely worth the thirty bucks, but for most users, it doesn't provide any benefits that justify the pain of being an early adopter.

UPDATE: Have installed Snow Leopard on my work laptop. No problems, except that my HAL 9000 screensaver doesn't work anymore.

Leopard Impressions

Unlike the Windows world, where operating systems upgrades are sources of frustration and loathing, among Mac users upgrades are met with enthusiastic interest. I've been using Leopard (Mac OS X 10.5) for a few days now.

The performance improvements promised by Apple are real. Everything feels snappier. Spotlight is actually usable now.

My favorite new feature is Spaces. Some say "Big deal. It's just a virtual desktop manager. UNIX workstations have had those for years." True, but it is an improvement over the original Exposé feature. Unlike other virtual desktops, it is well-integrated into the rest of the UI. Dragging live windows between virtual workspaces is really cool.

Time Machine is pretty cool too. Again, some would say "Big deal. It's just a backup/restore application. I can do the same thing with rsync." What makes Time Machine special is its simplicity. You plug an external drive in, and the Mac asks "Do you want to back up your main drive to this drive?" If you answer "yes," then that's it: you now have automatic hourly, daily, and weekly backups. Unlike other backup systems, Time Machine keeps all these backups available, but conserves drive space by not making copies of files that have not changed from one backup to another.

Time Machine is one of those amazingly great things that seems obvious, now that somebody has done it. I expect Time Machine clones to appear for Windows and UNIX very soon.

I do have some complaints about Time Machine: the UI is a little hard to figure out the first time you see it (and there is no menu bar or online help available in the app), and my MacBook CPU usage goes to eleven for a couple of minutes every hour while it makes the backups. I may turn off the automatic backups and switch to manual backups (right-click the backup drive and choose "Backup Now").

The new version of the Safari web browser is a lot more usable than the previous version, but I went back to Firefox after a few days. Firefox has more "power-user" features than Safari does, and I can't live without them.

I have mixed feelings about the "Leopard look." On one hand, brushed metal has pretty much disappeared, so we can rejoice. But there are other things that, while they look cool, actually make it more difficult to see important information: translucent menus, the 3D Dock, subtle folder icons, too-dark windows, etc. But it's not as bad as Vista.

On the whole, it's a solid upgrade. In a way, it is a bit of a letdown, because it is really just a polishing of an already-good system. Of its touted "300+ new features," few are going to change the way one uses their Mac. I haven't found anything that makes me say "Wow!" but there are a lot of little new things that make me say "Hey, that's kinda neat."

For a good in-depth technical review of Leopard, see the Ars Technica review. From that review, it looks like it is a great time to be a Mac developer—lots of cool new APIs and debugging aids. (Unfortunately, I'm still a Windows whore.)

To sum everything up: the upgrade was definitely worth $129 and a few hours of time. My only regret is that I didn't buy the "family pack" so that I could also upgrade my old iMac G5. Is it time to buy a new iMac?

Syndicate content