Hi, SMJobBless sample doesn't work for me - probably I got the code-signing wrong. Can someone explain?

Hi.


I'm trying to write an OS-X daemon which must run privileged. It will be launched from a System-Preferences Panel, using the SMJobBless() API.


Naturally I downloaded the Apple SMJobBless sample code, which seems simple enough - but It doesn't function. The app builds and runs, asks me for credentials (I provide my admin user and password), then it fails to launch the daemon, with a fairly cryptic error:


"2016-01-10 15:57:58.357 SMJobBlessApp[81654:3736339] Something went wrong! CFErrorDomainLaunchd / 4"


I'm new to security/priviliges and I admit I expected Apple's own code-sample to work out of the box... So, I started playing with the Xcode project (and target) code-signing parameters, to no avail. I tried to use my own developer ID and team to sign both the app and the daemon - but the error persists.


Can anyone shed a little light on how to (first step...) get this Code-sample to work?


Now, provided that the sample DID run... I still have several implications.


1. My daemon needs to use (compile and link against, load at runtime) 4 Private frameworks, some of which must (for license requirements) reside on the client hard-drive. I can't install them in /Library/Frameworks or ~/Library/Frameworks - they really need to be private, and I can't have them as static libraries - I receive them from a 3rdParty. So they should be dynamically loaded.


I know SMJobBless() copies my privileged daemon's binary to /Library/PrivilegedHelperTools/ and launchd will run it from there - but how can it then find its frameworks? What should I do with the @runpath and @executablepath settings when building the daemon?


2. I would like my daemon to be packaged as a code-bundle (can't be application-bundle as it has no UI), but if the SMJobBless copies the actual binary out of its bundle - how will it find its bundle resources? Being detached from its bundle structure, how will it correctly read its "user defaults", and configuration files?


Can anyone shed any light on this? Apple documentation is very basic on this front, and as I said --- the code sample doesn't even work.

Replies

I have recently implemented a privileged helper for an application, hopefully I can help out a little. I was able to get that sample project to work correctly and also was about to get a new example project for Service Management found here: https://developer.apple.com/library/mac/samplecode/EvenBetterAuthorizationSample/Introduction/Intro.html


Regarding the code signing, if you look at the readme file in the SMJobBlessApp it describes how to sign both targets with your developer account and how to use the provided python script to correctly set the values in the info plist for the helper and the app. This python script can also be used for the EvenBetterAuthorizationSample project but I would recommand just reading through the script to understand what the script is accomplishing. This will help when implementing a privileged helper of your own project.


For the private dynamic libraries question, I can't really help you there but this might be relevent: https://forums.developer.apple.com/thread/13161


Lastly, as far as configuration files I believe those resources should be placed in a directory you create in /Library/Application Support/ for access by the daemon. The info.plist and launchd.plist for the daemon are not really bundled with the daemon, they are embedded in the binary file's __TEXT segment.

I'm stuck trying to follow the SMJobBless instructions. ReadMe.txt says:


2. Run SMJobBlessUtil.py's "setreq" command to make the necessary Info.plist changes:
$ ./SMJobBlessUtil.py setreq build/Debug/SMJobBlessApp.app SMJobBlessApp/SMJobBlessApp-Info.plist SMJobBlessHelper/SMJobBlessHelper-Info.plist
SMJobBlessApp/SMJobBlessApp-Info.plist: updated
SMJobBlessHelper/SMJobBlessHelper-Info.plist: updated


How do we "run" that command? I've tried it in Terminal and in the debugger pane. The "./" prefix implies that it's relative to some folder, but I've tried everything.

The instructions in the sample assume that:

  • You’ve changed your current working directory into the top-level directory you get when you unpack the sample.

  • The built app can be found in a

    build/Debug
    directory beneath that.

This second point is problematic because modern versions of Xcode put the built app deep within

~/Library
. To construct the command line you should do this:
  1. Build the SMJobBless app.

  2. Open a Terminal window in the right directory by dragging the

    SMJobBless
    directory (the top-level directory you get when you unpack teh sample) to the Terminal app; this will open a new window and change into that directory.
  3. Enter the command

    ./SMJobBlessUtil.py
    ; this will print usage, confirming that you’re in the right directory.
  4. Build the command like this:

    1. Type

      ./SMJobBlessUtil.py
      .
    2. In Xcode, in the Project Navigator on the left, select Products > SMJobBless.app and drag that to your Terminal window. This will insert the path to the app into your command line. It’ll look something like

      /Users/quinn/Library/Developer/Xcode/DerivedData/SMJobBless-bplmxsbilgkrxtgkitueilmkbltj/Build/Products/Debug/SMJobBless.app
    3. Type

      SMJobBlessApp/SMJobBlessApp-Info.plist
    4. Type

      SMJobBlessHelper/SMJobBlessHelper-Info.plist
  5. Hit Return.

Taking a step back, I recommend that you spend some time becoming comfortable with the UNIX command line.

SMJobBlessUtil.py
assumes that you’re coming at this from the perspective of an experience command line user. That’s pretty reasonable given the level of the system that this sample operates at.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

have you heard, learned or found anything on this? i'm struggling with same issues

Did you work through the process from my 18 Nov 2016 response? If so, what results did you get?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hey eskimo, thanks for providing these updated instructions. When I run that command I receive an error: KeyError: '$(PRODUCT_BUNDLE_IDENTIFIER)'. Rather than steal this thread I created a new one. I would surely appreicate it if you could take a look at my question!