How can I use sudo programmatically? I.e. integrate sudo into my GUI
Asked Answered
D

2

7

I'm writing a program which temporarily needs root the first time it is run to perform a configuration change (create a file in /etc).

How can I temporarily gain root, by asking the user for their password in a graphical dialog box?

The program uses Qt and I am reasonably happy if it only works on Ubuntu, but I don't want to assume that they have gksudo or whatever installed. I also cannot use SUID.

The only thing I can think of is providing my own password dialog, and feeding that to the command line sudo binary via system() (or one of its less insecure cousins).

That seems pretty hacky though - command-line front-ends are generally an awful awful idea and should be avoided at all costs. So is there a better way? Perhaps there is a libsudo, or some method using IPC?

NB: This is not a duplicate. Or at least, the answers there do not treat it as the question I am asking.

Drice answered 2/3, 2013 at 0:31 Comment(0)
S
2

From man sudo:

   -A          Normally, if sudo requires a password, it will read it from the
               user's terminal.  If the -A (askpass) option is specified, a
               (possibly graphical) helper program is executed to read the user's
               password and output the password to the standard output.  If the
               SUDO_ASKPASS environment variable is set, it specifies the path to
               the helper program.  Otherwise, if /etc/sudo.conf contains a line
               specifying the askpass program, that value will be used.  For
               example:

                   # Path to askpass helper program
                   Path askpass /usr/X11R6/bin/ssh-askpass

               If no askpass program is available, sudo will exit with an error.

Either you use ssh-askpass which is installed on many systems or you write your own password prompt command which you then supply to sudo. This is still a bit twiddly, however you don't have to worry much about communicating the password to sudo.

Sprain answered 2/3, 2013 at 0:36 Comment(4)
Yeah I guess that is a reasonable solution. Still very hacky though, and it means I can't distribute my program as a single binary.Drice
Well, technically you could be the askpass executable yourself and check if sudo is the caller, then change the behaviour of your program so it acts as a askpass program. Alternatively you could use some sort of packed binary.Sprain
There might be an issue with sudo -A: it may clear the sudo timeout causing SUDO_ASKPASS program to be launched for each sudo call in your script. See Graphically ask for password in a bash script and retain default sudo timeout setting.Hanfurd
I want to write an askpass program for sudo on Ubuntu that supplies the password for the current user from libsecret. I can find no documentation that explains how this might be done. Is this program a standalone program? How does it supply the results to sudo? Are there any other interface requirements that must be met? These are examples of the type of question that I face and that I can find no documentation for. Is it necessary to examine the source code for sudo to get answers to these questions?Corona
D
0

This is the only solution that have worked for me on a mac machine using ProcessBuilder:

try {
        String command = "sudo -S ls -l /";

        ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", command);

        // Redirect error stream to output stream
        processBuilder.redirectErrorStream(true);

        Process process = processBuilder.start();

        // Create a BufferedWriter to write the sudo password
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
        writer.write("your_sudo_password\n");
        writer.flush();

        // Read the process output
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        // Wait for the process to finish
        int exitCode = process.waitFor();
        System.out.println("Process exited with code " + exitCode);

    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }
Dyarchy answered 19/9, 2023 at 8:18 Comment(1)
Yeah that is this option that I mentioned in the question: "The only thing I can think of is providing my own password dialog, and feeding that to the command line sudo binary via system() (or one of its less insecure cousins). That seems pretty hacky though - command-line front-ends are generally an awful awful idea and should be avoided at all costs."Drice

© 2022 - 2024 — McMap. All rights reserved.