Search code examples
javalinuxtext-filesreadonly

Edit read-only file in java


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?


Solution

  • 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?

    1. 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.

    2. 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.

    3. 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.)

    WARNING

    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.