Application, Helper Tool Communication - objective-c

I'm working on a OS X desktop application. I want to bundle a helper tool with it. I was thinking of using SMJobSubmit to start a helper program with elevated privileges. (The tool basically does a sudo call.)
How could I send the console output from the tool back to my main application?
I know with NSTask I could use NSPipe to redirect console output. But, since I don't think I can use NSTask with elevated privileges, I'm using SMJobSubmit instead.
(Yes, I've taken care of the authorization part.)

I think, as far as I know, you should use XPC connection to communicate with your helper program. Instead of using SMJobSubmit(Since it is deprecated anyway) use SMJobBless to install your helper tool as a LaunchD job which runs in elevated privileges. Use XPC connection from your Mac OS X app to communicate with it to invoke the function call that executes your logic, capture the output and reply back to the main app. If you are willing to go ahead with this idea, the below sample code from Apple will guide you through.
https://developer.apple.com/library/mac/samplecode/EvenBetterAuthorizationSample/Listings/Read_Me_About_EvenBetterAuthorizationSample_txt.html

Related

How To Do Privilege Elevation on OSX with Objective C

My custom Cocoa-based setup.app on Mac OSX that I made in Objective C needs to install a LaunchDaemon for doing elevated privilege tasks such as an antivirus program that needs to scan the entire hard drive and therefore needs root privileges. How can I make my setup application prompt the customer for their admin login and then install that LaunchDaemon into /Library/LaunchDaemons (and note I don't mean ~/Library/LaunchDaemons)?
The way I'm currently handling it is by using AppleScript with the admin privilege. It prompts for this login and then the AppleScript does the copying into this folder without the OS complaining. However, I assume that's not the proper technique -- that I should be doing this entirely in Objective C somehow?
Note that I can't use SMBlessJob in this case because it is for this reason that I'm creating the Launch Daemon in the first place.
BACKGROUND INFORMATION
I have a special need to create a custom setup.app -- just like the fact that Norton's AV application uses a custom setup.app. This is because the Apple PKG and DMG installers do not permit downloading of very large files (like virus definitions) from a server during install with some kind of friendly feedback. I mean, I can make a PKG file download a file from the server when running a Perl script or Bash script, but then the installer just hangs the progress bar for the amount of minutes it takes to download, not giving any other feedback to the user except that hung progress bar, and so the user thinks the installer is broke, when it's not. That's why I had to make my own custom setup.app, just like Norton did for their AV application.
Normally, SMJobBless would be the technique to do this. It's the one Apple recommends now as of 2016. Here's the readme.txt for Apple's sample project:
https://developer.apple.com/library/mac/samplecode/SMJobBless/Listings/ReadMe_txt.html
However, that's not the only way to do it. Another route would be to have your installer use AppleScript to prompt and run a Bash or Perl script with elevated privileges to install the LaunchDaemon, as well. (That's actually easier than SMJobBless.)
Basically, either technique installs a LaunchDaemon (e.g., "service") into a special folder, and that daemon can be set with elevated privileges, which can then run anything you want -- even command line commands. A super fantastic explanation of LaunchDaemons and LaunchAgents is here:
http://launchd.info/
Now, the problem is how to communicate with it from your application, once installed. They leave that up to you, and there are various techniques. However, they also leave it up to you to secure this so that it's not an attack vector.
A fantastic article on how to do IPC (Inter Process Communication between your application and this service) is here:
http://nshipster.com/inter-process-communication/
One IPC protocol on OSX is Distributed Objects, which is quite smooth from an architecture perspective -- you'll feel more like it's "coding" instead of "sending messages back and forth" like other IPC protocols. I've written a Stack Overflow post on this because the docs are shoddy and the existing examples on the Apple site and others are stale (won't compile on XCode7.1 with OSX 10.10+).
On communication protocol between your application and daemon/service, you can probably get away with key/value, XML, or JSON messages that are encrypted with AES256 with a long password and converted to Base64 encoding, and then use one of the various IPC mechanisms. However, that's another topic entirely.

how to use privileged helper tool(installed using SMJobless) to launch other application in root privileges on osx

I have a application inside which i have kept other applications.I want to launch other application in root privilege through main application.As we know AuthorizationExecuteWithPrivileges() has been deprecated, so that i have created a privileged helper tool. I am using Main application to install this helper tool through SMJobBless() function , and communicate through XPC mechanism. Every thing is working fine, Main application sending message(Path of application to be launch) to helper tool that is already running in root mode. The helper tool is able to launch that application provided in path, but the problem is, launched application doesn't have root privilege. Can anyone tell me how i can use this helper tool to launch another application in root privilege.Or is there any other mechanism to achieve it, i will ever thankful for this.

need a way to securely communicate between Priviliged Helper Tool (installed using SMJobBless) and the application

I am trying to install a privileged helper tool to perform some elevated work. I am using SMJobBless for the same.
I am able to install the tool fine and also able to communicate with it. I am using Mac OS X 10.8.4 and using NSXPCConnection for the same.
I have added .mach service in the plist which will be installed in /Library/LaunchDaemons. I am using [initWithMachServiceName:options:] in the app as the helper is privileged tool and [– initWithMachServiceName:] in the helper to listen. The communication is working fine.
But the problem is I tried the same communication with another application I created which did not have any codesign at all (the helper tool installer earlier was codesigned). I tried to connect to the mach service of the helper tool and was able to connect easily. This is a problem because anybody can communicate with it then and make it do anything.
I wanted some way to securely communicate between my application and the helper tool.
Thanks a lot.
As you've said that you're not signing the second app, I believe that that is the problem that is allowing a 2nd app from calling the helper application. From the Apple docs and specifically the ReadMe file in SMJobBless, it states: -
The Service Management framework uses code signatures to ensure that the helper tool is the one expected to be run by the main application
This document should be able to assist you in getting the helper app correctly associated with its owner.
Note that it references a python script, which is provided here.
Answering my own question: I had logged a radar bug for the same and Apple said that the behavior was intended:
"It is up to the privileged helper to not expose insecure operations"

how to load injection lib in mac applications at application start?

I have a dynamic library, I intent to inject in running application & newly launched applications.
I can inject it in running applications with the help of a process running with root user permissions.
Now I am trying that library should get loaded as soon as application is launched. I know one such library capable of doing this called, application enhancer. I am looking for similar behavior.
Does anyone has an Idea how can this be achieved?
Look at SIMBL agent code. It adds a observer to application launch notification and then injects. You can follow the same approach.

Testing install procedure of a program requiring administrative privileges

I'm trying to write automated test, to ensure that the installer for my program works okay.
The program can be installed for all users (requires admin privs), or for current user (does not require admin privs). The program can also autoupdate itself, which in some cases requires admin privileges, and in some cases doesn't.
I'm looking for a way where I can have an automated test click "Yes, Allow" on the UAC dialogs, so I can write tests for all different scenarios, on many different operating systems, so that I can be confident when I make changes to the installer that I didn't break anything.
Obviously, the installer process itself cannot do this. However, I control the complete machine, and could easily start some sort of daemon process with administrative rights, that the testprogram could make a socket connection to, to request it to "please click ok on the UAC now".
I actually figured out how to do this while looking to answer a similar question about UAC. Here is what you can do:
Write a service that runs as SYSTEM.
Open the process token of the winlogon.exe instance running in your logon session.
Use that token to launch a helper process on the Winlogon desktop via CreateProcessAsUser.
At this point, you have a helper process running as SYSTEM in your logon session on the Winlogon (secure) desktop. From here you can use some kind of IPC mechanism to communicate from your automated test program to the helper process. In the helper process you can EnumDesktopWindows to find the UAC prompt. This is as far as I took it; I didn't actually try to simulate clicking Yes or No, but I don't see any reason why it wouldn't work. Also, I only tested on Windows 7 32-bit; I believe the UAC architecture is identical to Vista, but I didn't test on it.
It took me a while to figure all this out; I can provide some code if you want.
EDIT: Just as a follow up I added code to use FindWindow() to find the "Yes" button and I was able to successfully send it a BM_CLICK message; the UAC prompt went away and the application was allowed to run.
An alternative solution might be to turn UAC off
The least bad solution I've found so far is to run the tests in a VMWare session, and control the mouse/keyboard trough the vmware sdk. Would love to hear about other solutions
Remote Desktop to it or run it as a guest VM (using Virtual PC or whatever, just don't boot to it.) This is also the best way to take a screenshot or video of the UAC prompt.