Reputation: 2006
I'm trying to run a process with elevated privileges - specifically OpenVPN, which requires root privileges to add routes to the system.
Looking around for existing examples around leads me to AuthorizationExecuteWithPrivileges
, which seems to be now deprecated.
I tried the new SMJobBless
method but I have a few questions regarding its viability for this purpose. As I understand it, I can create a separate privileged tool and communicate with it via sockets to ask the tool to perform privileged commands. However, I can't seem to figure out how I can start the OpenVPN process and capture its standard output in real time doing it this way as the main application would not be starting the process itself.
Another option is to use setuid on the OpenVPN
executable. Could I possibly use the helper installed by SMJobBless
to set the file permissions and setuid on the executable, then run it normally via NSTask
?
Edit:
Lastly is there some way to just run one single command with privileges without having to install anything permanently? Although this new method is more secure, it seems very heavy handed.
Upvotes: 4
Views: 2098
Reputation: 1
I had the same problem as you, needed it for a OpenVPN Manager App for MacOs X. Your solution is far from optimum because you open the openvpn binary for everyone setting setuid root. This is a security hole and should be avoided, as it is totally unnecessary when you are using smjobbless helper. This helper runs as root and could do everything you want for you and with administrative privileges, so you can launch openvpn via this helper without setting setuid root on openvpn binary.
Apple designed this process as only your App, the Main App, can communicate with this helper as your Main App and your helper are signed with your developer certificates. Any malicious App can't use this helper.
When you look at Nathans code you see, that he managed it to send messages to this helper and to get answers from this helper. In his example there is sth like "Hey there Helper App" and the answer is "Hey there Host App".
So to get sth useful out of this you only have to send commands to the helper app, extract these commands on helper side and launch them with elevated privileges as the helper App runs with elevated privileges.
Look at Nathans code, there is sty like (in smjobblessappcontroller.m):
xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
const char* request = "openvpn --config OpenvpnConnection.ovpn";
xpc_dictionary_set_string(message, "request", request);
[self appendLog:[NSString stringWithFormat:@"Sending request: %s", request]];
xpc_connection_send_message_with_reply(connection, message, dispatch_get_main_queue(), ^(xpc_object_t event) {
const char* response = xpc_dictionary_get_string(event, "reply");
[self appendLog:[NSString stringWithFormat:@"Received response: %s.", response]];
});
With this you send the openvpn command to your helper App. You only have to extract this command on helper side to launch the process with elevated privileges.
Look at smjobblesshelper.c and do sth like (in __XPC_Peer_Event_Handler else branch):
const char *response = xpc_dictionary_get_string(event, "request");
In string response you have your openvpn command, now simple launch it:
system(response);
Thats all, this goes with elevated privileges. Now you can use this in your App perhaps in an IBAction push button in your main app, to start openvpn connections as you want every time a user clicks this button.
Upvotes: 0
Reputation: 2006
I managed to go the SMJobBless
method by using a helper and communicating it with XPC (the method shown on Nathan de Vries's Blog). Using this helper I set the permissions on the external process to 04555 (setuid, rx). Then the SMJob is removed as it is no longer required. Essentially emulating an "one-off" privileged job.
Following that I was able to use NSTask to start the process and capture its output in my main application.
Additionally I have a check at the start to see if the permissions are set right on the executable, if not the SMJob helper is re-blessed and permissions set.
If anyone has a cleaner solution, feel free to share. Thanks!
Upvotes: 1