-1

I try to extract files from archive

I use command rar x file_to_extact.rar /tmp/some_dir

So when i execute it in command line, it show the words RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal...

enter image description here

Ok

But when i execute it in java Process

Process process = new ProcessBuilder(new String[] { "rar", "x", "file_to_extact.rar", "/tmp/some_dir" }).start();

BufferedReader inputReader = new BufferedReader(new
    InputStreamReader(process.getInputStream()));

BufferedReader errorReader = new BufferedReader(new
    InputStreamReader(process.getErrorStream()));

String string = null;
while ((string = inputReader.readLine()) != null) {
    System.out.println(string);
}

while ((string = errorReader.readLine()) != null) {
    System.out.println(string);
}

It return the same words but without Enter password...

enter image description here

I know, that i can check archive for password existing by command -p, like described here

But i cant understand why there is some differences with command line execution and java Process execution

Can anybody explain:

  1. why does it happeneds?
  2. How to correctly execute commands, to get the full out (examples, links are welcome)?

3 Answers3

1

There is no one single truth of "full out". Some examples:

  1. The executable can change its behaviour based on terminal attached (especially, if it's interactive or not)

  2. output will also change based on what output streams you listen to. The executable can print to stdout or stderr and those are different streams, you can listen to one or the other, both or none. And, as noted in other answer, linux password prompt can use direct /dev/tty for the password as a security feature, so not using stdout or stderr.

It might be this case is about the former. The executable is detecting that you're not using an interactive shell and modifying its behaviour accordingly.

However, it might also be that you're not fetching output from processbuilder correctly for this case.

Seems you fetch full lines here:

while ((string = inputReader.readLine()) != null) {
    System.out.println(string);
}

but password prompt is not a full line. Fetching all characters might bring it visible:

int r;
while ((r = reader.read()) != -1) {
    char ch = (char) r;
    System.out.print(ch);
}

note: example above will work for ascii characters only, if you need to support bigger charset than that, it requires more coding. This is just to demonstrate reading character by character.

eis
  • 51,991
  • 13
  • 150
  • 199
  • 1) As i understand, if i want to get the same result as shell result, i need to run the command in interactive mode. Yes or no? 2) Anyway, can you please an example of command, that i need to use in java, to get the same result? 3) I try to read chars, the result is the same – Bestows In Constructing Jan 20 '21 at 15:39
  • @BestowsInConstructoring 1) maybe. Some executables work that way, don't know what rar executable does internally. 2 & 3) then you're out of luck, can't think of a way you would get the same result with java. – eis Jan 20 '21 at 17:09
1

Enter password is not shown in standard output and does not read from standard input. This is a long-standing practice among Unix/Linux programs, to keep passwords secure: the password is read directly from the console/tty (which is also how the program prevents a typed password from being echoed).

While you can send the password as an argument to the -p command-line option, be aware that this is highly insecure, as it will expose the password to any other user who checks the process list.

new ProcessBuilder("rar", "x", "-p" + password, "file_to_extact.rar", "/tmp/some_dir")

Again, this is highly insecure. While the command is running, any user can check the processes, and will be shown something like:

  PID TTY      STAT   TIME COMMAND
 8732 pts/3    S+     0:00 rar x -pswordfish123 file_to_extact.rar /tmp/some_dir

You will want to consider the risk of exposing the password to casual observers on the system.

I don’t know of any way to automate an external command that reads directly from a console.

However, this question addresses using Java, rather than an external command, to read a rar archive. junrar seems to be a popular choice. (I haven’t used it, so I can’t speak to its effectiveness.)

VGR
  • 40,506
  • 4
  • 48
  • 63
  • I think, based on the question, OP already knows about `-p` switch but was still wondering why he isn't seeing the password prompt in his use case (which first paragraph of your reply gives an answer to) – eis Jan 18 '21 at 13:13
  • @eis Thank you, you’re right. Updated language in my answer to acknowledge that. – VGR Jan 18 '21 at 14:38
  • Thanks for important security info! ! ! – Bestows In Constructing Jan 22 '21 at 14:49
0

It's because the rar executable explicitly finds a/the terminal and asks there, or if it can't, determines that the session isn't interactive and refuses to prompt for a password like this. It doesn't send the 'Enter password' prompt to standard output (or standard error), intentionally. The reason it does this, is specifically to stop what you are doing. That may have been overzealous, but you'd have to take that up with the Alexander Roshal and friends.

The solution is to rewrite completely. Use: junrar for example. You'll end up with something far more robust and flexible.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72