27
votes

I'm using ProcessBuilder to execute bash commands:

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            Process pb = new ProcessBuilder("gedit").start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

But I want to make something like this:

Process pb = new ProcessBuilder("sudo", "gedit").start();

How to pass superuser password to bash?

("gksudo", "gedit") will not do the trick, because it was deleted since Ubuntu 13.04 and I need to do this with available by default commands.

EDIT

gksudo came back to Ubuntu 13.04 with the last update.

6
What a GREAT idea to remove gksudo! Congratulations, Ubuntu! As a workaround I can suggest xterm -e 'sudo -i gedit'. Or install gksu package. Or even run your whole java program as root. - Aleks-Daniel Jakimenko-A.
@Aleks-DanielJakimenko using xterm is actually a good idea... Thanks. sudo app.jar will work as it should? From the opening application to closing it? - Vare Zon
Yeah, sudo app.jar should give it sudo priveleges for everything. Just note that everything you do is going to be under root, so if you create a file from your java program it wont be visible to other users because user will have no privileges for it. Just take care of it. - Aleks-Daniel Jakimenko-A.

6 Answers

40
votes

I think you can use this, but I'm a bit hesitant to post it. So I'll just say:

Use this at your own risk, not recommended, don't sue me, etc...

public static void main(String[] args) throws IOException {

    String[] cmd = {"/bin/bash","-c","echo password| sudo -S ls"};
    Process pb = Runtime.getRuntime().exec(cmd);

    String line;
    BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
    while ((line = input.readLine()) != null) {
        System.out.println(line);
    }
    input.close();
}
14
votes

Edit /etc/sudoers with visudo and grant your user a NOPASSWD right for a specific script:

username ALL=(ALL) NOPASSWD: /opt/yourscript.sh

8
votes

My solution, doesn't exposes the password in the command line, it just feed the password to the output stream of the process. This is a more flexible solution because allows you to request the password to the user when it is needed.

public static boolean runWithPrivileges() {
    InputStreamReader input;
    OutputStreamWriter output;

    try {
        //Create the process and start it.
        Process pb = new ProcessBuilder(new String[]{"/bin/bash", "-c", "/usr/bin/sudo -S /bin/cat /etc/sudoers 2>&1"}).start();
        output = new OutputStreamWriter(pb.getOutputStream());
        input = new InputStreamReader(pb.getInputStream());

        int bytes, tryies = 0;
        char buffer[] = new char[1024];
        while ((bytes = input.read(buffer, 0, 1024)) != -1) {
            if(bytes == 0)
                continue;
            //Output the data to console, for debug purposes
            String data = String.valueOf(buffer, 0, bytes);
            System.out.println(data);
            // Check for password request
            if (data.contains("[sudo] password")) {
                // Here you can request the password to user using JOPtionPane or System.console().readPassword();
                // I'm just hard coding the password, but in real it's not good.
                char password[] = new char[]{'t','e','s','t'};
                output.write(password);
                output.write('\n');
                output.flush();
                // erase password data, to avoid security issues.
                Arrays.fill(password, '\0');
                tryies++;
            }
        }

        return tryies < 3;
    } catch (IOException ex) {
    }

    return false;
}
6
votes

Do not try to write a system password plainly in a file, especially for a user that have the sudo privilege, just as @jointEffort answered, issued privilege should be solved by system administrators not by app writers.

sudo allow you to grant privileges for specific command to specific user, which is precisely enough, check this post

and you can choose to manage the privilege in a separated file other than the main sudoers file if you want just append #includedirs /etc/sudoers.d/ in the main /etc/sudoers file(most Linux distributions have already done that) and make a file like ifconfig-user with:

 USER_NAME ALL=(ALL) NOPASSWD: /sbin/ifconfig

Another thing, remember to edit the config file with visudo in case you lost control of your system when there is syntax error.

2
votes

I know this is an old thread but i just want to put this here:

you can use sudo -S *command* as a command that you pass to create the Process instance. Then get the output stream and write the password to it, and add at the end of it a new line and a c. return (\n\r). The return may not be required but i passed it just in case. Also it is a good idea to flush the stream, to make sure everything is written to it. I've done it a few times and it works like a charm. And DO NOT forget to close streams :).

1
votes

Once you spawn a process you can extract the input and output streams. Just feed the password to the output stream (you output it into the proccess's input). So the code would look something like -

Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);