Trying to write a Java program capable of running a UNIX command as a different UNIX user. I have the user's password, and I know the command I want to run, but the command has to be run as that user - so I have to login as that user first.
For example: say we have a user, jim, who wants to see what's in bob's home directory, and (for whatever reason) jim has access to execute ls whereas bob does not. We are currently logged in as bob. Here is what we (could) do:
bob#host$ su jim && ls ~bob
Problem is, we get prompted for jim's password. Since this is run from a Java program, i.e.
Process p = Runtime.getRuntime().exec("su jim && ls ~bob");
we get prompted for jim's password and hung up. We know jim's password. However, I can't enter it.
Additionally, we can't use an Expect script (don't have it installed) and we can't become the superuser. I also looked into using SSH to try this, since we could technically do
bob#host$ ssh jim#host "ls ~bob"
but this also doesn't work since I don't have permission to setup passwordless SSH.
My last-ditch effort is to try and use an SSH library for Java, since the password is available to the Java program and I would be able to login with that (and execute the proper command). But since I'm going to be running on the same host, it seems like overkill.
Any suggestions?
P.S: Java version 1.4.2, can't upgrade; AIX UNIX 5.3.
Have sudo installed, have the user running the Java program entered in /etc/sudoers for the commands in question, and use sudo -u jim ls ~bob.
Problem solved. Used JSch (http://www.jcraft.com/jsch/) to SSH into the server with known username and password, and execute command. Thanks all for your suggestions!
Possibly a java implementation of Expect? ExpectJ comes up when googling but I couldn't find any documentation regarding running under 1.4.2.
Have you tried redirecting the sudo commands input and writing to that. I haven't used Java in a while but I believe there is a way to get the input stream and write to it. You could use that to write the password followed by a new line and sudo or su should accept the password.
Use getInputStream() and write your password out to that.
su jim -c ls ~Bob
Perhaps this would work:
Process process = Runtime.getRuntime().exec("su jim && ls ~bob");
OutputStream standardInput = process.getOutputStream();
Writer standardInputWriter = new OutputStreamWriter(standardInput);
standardInputWriter.write("password\n");
standardInputWriter.close();
I'm not sure this code:
Process p = Runtime.getRuntime().exec("su jim && ls ~bob");
will be executed in a shell, needed to evaluate the &&, that is a shell command (/bin/sh). You should pass the command "ls ~bob" via a command line swith of su. Something like:
su jim -c 'ls ~bob'
Related
I'm writing a Java program that calls other programs, and some of them need to be ran as root.
I thought about running the whole JAR as root but that sounds like a security risk, I'd rather run just some programs as root.
Currently, I create a ProcessBuilder and use its getStandardOutput method to instantiate a Writer, on the command sudo -S pacman <...>. (-S means ‘read from standard input’).
I then inject the password using that reader and flush it, so far so good.
However, when pacman expects input (for example when asking an interactive yes/no question), and I try to write to the Writer again, it fails with IOException because the stream is closed.
How can I get a Writer that can actually send characters to pacman and other programs ran as root?
This program is only expected to run on UNIX (Arch Linux, Debian, MacOS and maybe Window's WSL) so UNIX-specific solutions are fine, if possible I'd rather not use JNI because it requires to compile multiple times, but if that's the only solution it's fine. I'm also fine replacing sudo with something else as long as it's still ran as root.
If this is not a long-lived service, you could run sudo -v to have sudo cache the credentials and then invoke sudo in your Java program without needing to enter a password. This would work best if you invoked your Java program with something like:
#!/bin/bash
sudo -v
java -jar ...
I am writing a Java application in which (among other stuff) I'd mount a external device, do some copying, and then unmount it.
//I am mounting several devices in created dirs named sdb, sdc... according to the partitions
String[] command = {"gksu", "mount", "/dev/sd" + letter + "1", "mounter/sd" + letter};
Runtime.getRuntime().exec(command);
This works fine both in the terminal and in my program.
To unmount faster, I thought about using umount -a but gksu umount -a doesn't work in the terminal and consequently not in the Java program. sudo umount -a does work in the terminal, but not in the application. Meanwhile, I got it to work by unmounting the devices 1 by 1, but it would be cleaner if I could get umount -a to work someway.
If you understand why either gksu doesn't work with umount or sudo with Runtime.exec(), I'd take your explanation.
Thanks
I feel the problem is sudo not asking me for a password, as gksu does. But I don't know how to give it a password.
This is very likely the case.
There are a couple of different possible situations here, and each I think has it's own solution:
The user running the program (in the case of a desktop app) already has privileges to run the commands you need. - Prompt the user to enter their password and pass it to sudo through stdin using the -s flag. Check out the sudo man page for more. This is simple and ensures that your application doesn't have greater access than the user running it.
If your application needs to run with different privileges than the user has, or if this is running on a server, then the application should be run as it's own System User. You can then use visudo to give that system user the ability to run ONLY the commands you need without requiring a password. Just be very cautious about editing the sudoers file. I recommend adding it as a separate file and just linking to it in the actual sudoers so that it's easier to undo later.
I'm using the followig code to run a command from my Java App:
String cmd[] = {"sh","-c", "sudo chmod 777 -R " + path};
Terminal.runCommand(cmd);
I'd like to execute the .jar just by click in it and choose "Open with.." -> "Java";
The problem is that the app keep wating for a password because of the "sudo" command, but no terminal is called, the user can't give the password..
So, how could I call the coomand above AND a terminal to give the user a chance to insert the password and the application finally keep going?
Thank very much!
This is a sudo question, not a Java one; sudo does things as root. Your process doesn't have root priviledges, so sudo needs to authenticate the human being. That's a feature, not a bug. The system is not supposed to allow you to run root commands.
One option might be to use gksu instead, which is shipped by default on some distributions. It works similarly, but will pop up the password dialog in the GUI instead of on the (in this case non-existent) terminal.
Another might be to simply run your Java process as root, with all the security implications that might have. In some situations that can be a valid choice, but be careful.
Or you can check the man page for sudo and sudoers -- it's possible to configure accounts not to require a password, and to limit them to particular commands when they do.
I was wondering How to execute java Application with different userName and password.
For example:
Right now: When I do,
System.getProperty("user.name");
I get user1.
But I want to program in such a way that it says user2.
Can somebody help me How to accomplish this with Java or bat files.
Any kind of help is appreciated.
The java system property user.name is set by the operating system. So if you login as a different user and start you're java program, it will run under that username.
But You can also change the user under which you execute an program (if you have sufficient rights for it!).
Linux: use the sudo command
sudo -u user2 java yourprogram
(but you need to have sudo rights, for example by being root)
Windows use the runas command:
runas /user:domain\user2 java yourprogram
You can override this value, the same as any other system property with
java -Duser.name=my-new-user
or
System.setProperty("user.name", "my-new-user");
Note: neither solution changes the user-id of the process, just the value returned by System.getProperty("user.name");
You need to switch to user2 (su user2 on linux), then run your program.
If you're doing this on Windows, you can use the runas command in a batch file to run in the context of a different user. On a Unix/Linux system, you can use the su command.
Is it possbile to execute linux commands with java? I am trying to create a web servlet to allow ftp users to change their passwords without ssh login access. I would like to execute the next commands:
# adduser -s /sbin/nologin clientA -d /home/mainclient/clientA
# passwd clientA
# cd /home/mainclient; chgrp -R mainclient clientA
# cd /home/mainclient/clientA; chmod 770 .
Check out this.
However, doing what you are talking about is way outside spec, and I wouldnt reccommend it. To get it to work you are going to either run your app server as root, or use some other mechanism to give the user the app server is running as permission to execute these privileged commands. One small screw-up somewhere and you are "owned".
Use:
Runtime.getRuntim().exec("Command");
where Command is the command string you want to execute.
If you invoke those commands from Java, make sure to pack multiple commands to a single shell-script. This will make invocation much easier.
have a look at java.lang.Runtime
The java RunTime object has exec methods to run commands in a separate process