Using a LaunchAgent inside the Mac app sandbox - macos

How would you use a LaunchAgent inside the sandbox? I want to distribute a UI-less LaunchAgent app bundle inside my main application that I can launch on demand. The reason I want this instead of an XPC service is for the KeepAlive option, which will prevent launchd from automatically killing my process when its idle. This option doesn't exist on XPC services.
The documentation says that there's a plist that needs to be copied into ~/Library/LaunchAgents, and this is obviously not possible inside the sandbox. Is there some sort of system API that would handle copy the plist for me? I've seen Apple's SMJobBless sample code, but it seems like that's for registering a privileged LaunchDaemon rather than an unprivileged LaunchAgent.

The API you're looking for is SMLoginItemSetEnabled(). You'll have to package your long-running agent as a regular .app bundle and put it into your main app's bundle at Content/Library/LoginItems.
Then at runtime in the main application you can use the SMLoginItemSetEnabled() call with the agent's bundle identifier to enable and disable your agent. If your main application quits, the agent stays alive. If the user logs out and back in or reboots, the OS will relaunch your agent when the user logs back in.
Update: As Dmitry notes, the documentation no longer comes with the sample I originally mentioned, but another Apple sample code project, for App Sandbox, demonstrates the same API (see the file NSXPCConnection+LoginItem.m).

Documentation page now doesn't contain a sample project, so here it is: http://rhult.github.io/articles/sandboxed-launch-on-login/

Related

How to protect on mac OS system extension security endpoint from being kill

How can I protect my macOS system extension endpoint security from:
A. kill by the user (root user)
B. unloading by the root user?
I would say you could subscribe to a ES_EVENT_TYPE_AUTH_SIGNAL event to filter out all kill-alike signals to your process (if you run it inside your daemon. In case you are loading it into system process, user just can't kill it).
Well, I would not recomend to do this. The main question you should ask yourself: how the one will unload your system extension to uninstall a software or to update it, if it could not be unloaded?
The root user is the one that should be able to do any sane operation on the system by design.
You could still do some tricks here, like subscribe to the ES_EVENT_TYPE_AUTH_EXEC event and cancel all launchctl unload attempts, or systemextensionsctl with your system extension parameters in case you are doing this via separate extension.

WebView in MacOS: How to request file system permissions correctly

It may be because I'm not developing a traditional Swift app, instead I'm using the https://github.com/zserge/webview library to develop a cross platform app.
My app has 2 parts, divided into 2 different threads: one thread launches the window and displays a JS app. The second thread contains a background server bound to an ephemeral port and serves a json api, written in Rust. The Rust side is also the one talking with the File System and making all requests. On Linux I don't have any problem, but on Mac it works only when requesting resources from root and home directories but not from Documents/Desktop etc
The first problem I had when running it on Mac has been allowing access to the server from the window: I had to add a new entry to the info.plist file, according to this answer in stackoverflow: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection
This resolved the issue I had talking to the server bound to the ephemeral port. Truth be said I have to also say that now it requests me to allow access to external resources every time I launch the app.
But, when trying to execute a function which requires access from the Rust side to the Desktop (for example), it doesn't work and it does not show any popup and never did
Btw, if you want to have a look at the final product, maybe to help you understand better the app, have a look here: http://getdevspace.com/
Check the ch mode file system
Even had the same problem so i checked the ch mode so it worked
Thanks

Can Kernel Control API support multiple, simultaneous client connections?

I'm using the Kernel Control API (SYSPROTO_CONTROL) for a user-land application to request information from a kernel extension, based on the code in Apple's documentation.
All works as expected with a single connected client. If a 2nd client tries to connect whilst the first is connected, it fails with the message: -
Error 16 (Resource busy).
The first client is then automatically disconnected.
Is it possible for two clients to be connected using the Kernel Control API and if not, is the best solution to keep trying to connect if the resource is busy?
I don't know if it is possible but the recommend way is to always only have one user space client that talks to one kernel extension, usually a background daemon running in user space and started by launchd. If you want multiple other apps or processes to access data from your kernel extension or somehow interact with it, then these would talk to the user space daemon and not directly to the kernel extension, which can also cache data in user space as crossing the users space/kernel space bridge is always expensive for data, so when 10 processes all want the same data, it would be better to just pull it once from the kernel and then distribute it 10 times in user space using any IPC mechanism of your choice.
This setup is recommend as you should limit kernel control to root processes (using the CTL_FLAG_PRIVILEGED flag), so your daemon would run as such a root process, whereas normal apps and processes run with the privileges of the current user. Such a root helper daemon can be bundled inside an app bundle and using the SMJobBless API, the daemon is automatically copied to /Library/PrivilegedHelperTools and it's embedded plist (see SMJobBless documentation, which is only available in its header file AFAIK) is copied to /Library/LaunchDaemons and registered with launchd. Within such a plist you can use various triggers when the daemon shall be started by launchd, e.g. when your application tries to connect to a specific IPC UNIX socket. Then all you have to do in your app is trying to open that socket, what launchd will detect and start the daemon for you, which can then use launchd's API to get hold of that connected socket and immediately start talking with your app. So the whole thing is only installed once and then brings up itself each time your app is launched.
For a SMJobBless sample project, see here.

Retrieving Sandbox entitlements from an XPC bundle

It's usually possible to see if sandbox entitlements exist for an application with the codesign command line call. For example, calling this
codesign --display --entitlements :- /Applications/Notes.app/ | grep sandbox
Will result in this output
Executable=/Applications/Notes.app/Contents/MacOS/Notes
<key>com.apple.security.app-sandbox</key>
Where the key com.apple.security.app-sandbox denotes that the app runs in a sandbox.
On Mavericks, some XPC helper apps show in Activity Monitor to be running in a sandbox, but calling codesign on them doesn't reveal anything. An example for one of Safari's XPC helper applications: -
codesign -display --entitlements :- /System/Library/PrivateFrameworks/WebKit2.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent | grep sandbox
Just returns this: -
Executable=/System/Library/PrivateFrameworks/WebKit2.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent
I've also tried checking programatically if the bundle is sandboxed, with the code described in this article, but again, returns as not sandboxed, even though Activity Monitor clearly states that it is.
Is it possible to check such an xpc bundle, to see if will be executed in a sandbox and uses sandbox entitlements?
Looking for the com.apple.security.app-sandbox entitlement as you're doing is the way to check if an XPC service uses App Sandbox. The reason that the Safari Web Content process shows up as sandboxed despite not having this entitlement is that it does not use App Sandbox, but rather lower level interfaces to the underlying sandbox facility in OS X. Early on the web content process calls WebKit's initializeSandbox() method, which uses a system private interface to apply a sandbox policy at runtime. So finding out whether a given XPC service will create a sandboxed process is as difficult as finding out whether that service will call a function. However, if you're curious about the restrictions placed on such processes the sandbox policy is usually stored in a .sb file somewhere on the system. In this case it's at /System/Library/PrivateFrameworks/WebKit2.framework/Versions/A/Resources/com.apple.WebProcess.sb.

Starting Daemon from Cocoa application

Anyone can please provide sample code to launch a daemon from cocoa application using AuthorizationRef.
A daemon is generally defined as a long-running system service that has no user interaction. If that is what you mean by daemon then this is the wrong way to solve your problem most likely. Daemons should be started through launchctl and should have a preferences plist in /Library/LaunchDaemons or ~/Library/LaunchDaemons depending on whether they are system-wide or user-specific. Communication between your user application and the daemon can be done any way you please but I've found NotificationCenter (CFNotificationCenterRef) to be useful for such things.
However, if what you really need is to launch a tool to perform a specific task and that tool needs special privileges then check out the sample code here :
http://developer.apple.com/library/mac/#documentation/Security/Conceptual/authorization_concepts/03authtasks/authtasks.html%23//apple_ref/doc/uid/TP30000995-CH206-TPXREF33

Resources