3

I have written a .NET Core Mac OSX Menu Agent App (i.e. UI is an icon in the menu bar with a context menu).

One of the features of this app is hosts file updates (i.e. add/remove entries from /etc/hosts). But to write to the file you need sudo permissions.

The file update re-writes the whole file using System.IO.File.WriteAllText.

How can I either:

  1. Launch the app as sudo (prompting in some way) while still allowing users to click on the App rather than launch from terminal, or

  2. Provide sudo access in some way to the File.WriteAllText command (prompting the user when needed).

In short, what do I need to do to provide access to update the hosts file?

BlackSpy
  • 5,563
  • 5
  • 29
  • 38
  • 1
    On windows I would use `runas` to start a second instance of my program with elevated previleges to perform the desired modifications. Something like that should be possible using sudo I think. – thehennyy Jul 20 '18 at 11:56
  • Yeah windows isn't a problem.... but i need this to be as professional as possible. Opening a terminal to ask for your password won't cut it. Other apps prompt me for fingerprint or password when needing elevated privileges, so it must be possible somehow – BlackSpy Jul 20 '18 at 13:10
  • Yeah there should be some system component that you can invoke to do that. But I am not familiar with osx and can't tell you which one that is. – thehennyy Jul 20 '18 at 13:34
  • Is going to be an App Store app? Or ad-hoc install? – SushiHangover Jul 20 '18 at 14:43
  • Corporate app - development tool. So ad-hoc install but from controlled sources. – BlackSpy Jul 20 '18 at 15:31
  • 1
    @BlackSpy I would use AppleScript programmatically from C# within your Xamarin.Mac that uses `shell` with administrator privileges. (I use it that way for my Agent style apps). `AuthorizationExecuteWithPrivileges` has been deprecated since 10.7 and using `SMJobBless` and XPC is a pain to setup for your use-case (and you need an Apple Developer license for the cert that you have to sign both apps with). If you need a simple let me know and I'll add an answer... – SushiHangover Jul 20 '18 at 19:51
  • Thanks @Sushihangover for giving me the google search terms and what to look at. – BlackSpy Jul 28 '18 at 18:59

2 Answers2

1

I finally found the solution to this thanks to @SushiHangover's suggestions which led to the following post: https://forums.xamarin.com/discussion/103039/xamarin-mac-multiple-do-shell-script-with-administrator-privilege-with-one-password-request

Instead of using the System.IO.File static methods to write to the hosts file directly, I instead write to a temporary file. I then launch the cat command to overwrite the contents of the hosts file with the contents of the temp file by using the ExecuteWithPrivileges method. This brings up the Mac default prompt for the users password and the cat command is executed as sudo.

private static void WriteToHostsFile(IEnumerable<HostEntry> hostEntries, IHostsFileWriter hostsWriter)
    {
        var hostsText = hostsWriter.GetHostsFileText(hostEntries);
        var fi = new FileInfo("hoststemp.txt");
        File.WriteAllText("hoststemp.txt", hostsText);
        var defaults = Security.AuthorizationFlags.Defaults;
        using (var auth = Security.Authorization.Create(defaults))
        {
            auth.ExecuteWithPrivileges("/bin/cat", defaults, new[] { fi.FullName + " > /etc/hosts" });
        }
    }

It should be noted that this method has been marked as deprecated in favor of SMJobBless: https://developer.apple.com/library/archive/samplecode/SMJobBless/Introduction/Intro.html

I haven't managed to work that out in Xamarin yet though, and looks quite involved for the small task I needed to do.

BlackSpy
  • 5,563
  • 5
  • 29
  • 38
0

in your apps boot script you want this.

/usr/bin/osascript -e 'Run app "dotnet MyCoolApp" with administrator privileges?'

More info here: Getting sudo to ask for password via the GUI

  • I can't seem to find where the boot script exists in solution or even the package contents. Do you know the location? – BlackSpy Jul 25 '18 at 21:06
  • Normally in the bundle folder normally MyCoolApp.app there is normally a bash script just called the name of the bundle MyCoolApp you can use this to create use the osascript. – Courtney The coder Jul 25 '18 at 22:58