I have a protect, read-only, text file on my Linux operating system that I have to make edits to. Of course I can goto the terminal and type:
sudo gedit /etc/ppp/options
I would then have to type my sudo password. My question is how do I give my java program "sudo" privileges to be able to write to this file and save those edits? I figured once I have given the program these privileges I could then use a BufferedWriter or PrintWriter to make edits.
To clarify, my program prompts the user for their administrative (sudo) password. How could I use this to grant access to this file for writing purposes?
My question is how do I give my java program "sudo" privileges to be able to write to this file and save those edits.
I think that the simple answer is that you can't.
Sudo works by checking a file to see if the user allowed to run a command, and optionally confirming his / her identity by asking for his / her password. If both of these check out, then the sudo
command executes the requested command as a different user; typically root
.
However, in order to do this, the "sudo" program itself is implemented as a "setuid" program; i.e. a program that itself that runs with elevated privileges. Without this, it cannot run the requested program "as root", and it can't even read the "/etc/sudoers" file.
So can we emulate "sudo" in Java?
Basically, no. To do this, you would need to make the java
command a "setuid" program. But the java
command can execute ANY java program written by anyone. So a "setuid" java
would allow anyone to run any java program with administrator privileges. That would be insanely insecure.
So what are the alternatives?
You could use ProcessBuilder
to "exec" the sudo
command as an external command. However, passing a password to sudo
via its command line is not possible. So you would need to either:
configure the sudoers
file to allow the (specific) command to be executed without a password (potentially dangerous), or
figure out a way to use the --askPass
hook to request the user's password securely from Java, or
use the --stdin
option to read the user's password from standard input instead of the user's terminal.
Write a custom "setuid" (or "setgid") wrapper to execute the admin command. Note: "setuid" shell scripts are fundamentally insecure. A C / C++ wrapper is potentially the safest approach ... but you need to be sure that the wrapper can't be tricked into doing something dangerous / nasty by supplying clever arguments or environment variables.
Don't do it in Java. Get the user to run the privileged command from the command line; e.g. using sudo
. You could potentially make it easier for the user by providing a script (shell, perl, whatever) to handle anything complicated, do sanity checking, etcetera.
My recommendation is approach #3 (in general). It is the most secure and transparent approach. (As an administrator / power-user, I would be very uncomfortable with some complicated / opaque Java application asking for my password to run sudo
commands on my system.)
Doing this kind of thing safely and securely requires a good understanding of how UNIx / Linux security works. There are numerous mistakes you could make (too many to list) that could compromise security, and allow users to run arbitrary programs as root, or other dangerous / destructive things. Be careful, and get an real UNIX / Linux expert to review your implemented mechanism.