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.
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 ...
As an introduction, let's just say I'm a real noob using linux. I try to do the things right, don't hit me if it's ugly.
So, the problematic. I'm trying to run some jars as webservices on an ubuntu server. I created a specific user (nuxservice) with no pwd. I edited sudoers to enable a few users (myself & root) to sudo using this account with no password.
I then took a lot of inspiration from : http://www.jcgonzalez.com/linux-java-service-wrapper-example
Most is working, only one real problem, my java process seems to not have the right to create its logging files.
I run my services with a classic
sudo service myservice start/stop/restart
The command line that are launching my services are :
nohup sudo -u nuxservice java -jar myjar.jar myargs
When I do a ps -ef, the services are launches with my nuxservice user.
When I do ls -ld, nuxservice is the owner and have the rights.
If I launch the command in a terminal myself, it works. When launching as a service, my logs files are not created.
Any clues mates ?
So...
It was kinda silly.
My user rights were fine. Problem is, I did not set the working folder in my script so Java was all lost considering the creation of the folder/files for logging.
All I had to do was adding a little
cd $PATH_TO_JAR
And it was all set !
I executed the netsh command from the CMD that was manually opened by me by right clicking the CMD icon from the start and then selecting run as administrator from the options.It worked fine.Now I tried to run the netsh command through my java code,then it is not working.Nothing is happening when i run that code.I want to ask that I can run applications like notepad.exe from the cmd by calling appropriate methods of the runtime class from my java code,But how can I open the same application with the administrator priviliges from my java code.r.exec("notepad"); where r is an object reference to the runtime class will run the application,but the notepad so opened will not be in administrator mode.Actually I guess that learning to run the application in administrator mode from CMD will be enough to do the work done as The corresponding CMD command will be passed as the argument to the exec() method of the Runtime class.So my questions are:
How to run any application from CMD in windows 8 with administrator privilliges?
The way i want to implement the use of netsh is a good thing to practise or there is some other way out i must use these commands from my java code.
I have seen some commands while googling but they where not working out for me,like runas /user:administrator "notepad.exe" etc.
Thanks
You cannot use the runas /user:administrator approach, as that requires a password input which you cannot provide from an external source (such as a Java application) for security reasons.
I had a similar issue to you in the past, and I solved it using PsExec, running the process on localhost with an administrator username and password allowed me to execute external applications as an administrator.
Using your example you could run:
PsExec.exe \\\\127.0.0.1 /accepteula -u USER -p PASSWORD notepad.exe
The "/accepteula" flag prevents the requirement to accept the EULA interactively when run on a machine for the first time.
This approach may require a bit of tweaking to get working with your setup, but hope it gives you a starting point.
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.
So I have the following problem: I have a web service running inside a Tomcat7 server on Linux. The web service however has to execute some commands (mostly file operations such as copy and mount). Copy I've replaced with java.nio, but I don't think that there is a replacement for mount.
So I'm trying to execute shell commands out of my Tomcat Java process. Unfortunately it doesn't execute my commands. I've implemented the execution of shell commands in Java before. So my code should be correct:
Process pr = Runtime.getRuntime().exec("mount -o loop -t iso9660 <myimage> <mymountpoint>");
pr.waitFor();
<myimage> and <mymountpoint> are absolute paths, so no issues there either.
I've debugged my commands and they are working when executed on the console.
I've tried sending other commands. Simple commands such as id and pwd are working!
I've tried using /bin/bash -c "<command>", which didn't work.
I've tried executing a shell script, which executes the command, which didn't work.
I've tried escaping the spaces in my command, which didn't work.
So I've digged even deeper and now I'm suspecting some Tomcat security policy (Sandbox?), which prevents me from executing the command. Since security is no issue for me (it's an internal system, completely isolated from the outside world), I've tried a hack, which became quite popular just recently:
System.setSecurityManager(null);
This didn't work either. I'm using Java7 and Tomcat7 on RHEL6. Tomcat7 is just extracted! I don't have any files in /etc/.. or any other folder than /opt/tomcat/, where I've extracted the zip from the Tomcat home page. I've searched the /opt/tomcat/conf folder for security settings, but all I could find was the file catalina.policy, where it didn't seem like I could set some security level for shell commands.
Any ideas?
A few things:
System.setSecurityManager(null);
you have just killed the security of your application.
Yes, Tomcat is running as root. If I execute id I'm root as well.
Fix this immediately!
Now on to the question. You shouldnt have Tomcat executing anything, you need to defer this to a separate process whether that be a shell script or another Java program. This should also remove what (I hope) was a dependency on root running Tomcat. It should be possible to perform this command as a non-privileged user that cannot log into the system normally. You would do this by configuring /etc/fstab and supplying that same user the permissions to do this. From a pure security POV the process that mounts should not be owned by the tomcat user. Nor should the tomcat user ever be root. So to recap:
1) Stop running Tomcat as root
2) Create a separate process outside of the context of Tomcat to run this mount
3) Create a tomcat user, this user should not be able to log into the system nor should it be a privileged user (admin,super user, etc)
4) Create a process user, this user should be configured exactly as the tomcat user
5) Edit /etc/fstab giving the process user the necessary permissions to mount correctly.
It's generally a bad idea to use the single-string form of Runtime.exec. A better option is to use ProcessBuilder, and split up the arguments yourself rather than relying on Java to split them for you (which it does very naïvely).
ProcessBuilder pb = new ProcessBuilder("/bin/mount", "-o", "loop", /*...*/);
pb.redirectErrorStream(true); // equivalent of 2>&1
Process p = pb.start();
You say you're on RHEL so do you have selinux active? Check your logs and see if this is what's blocking you (I think it's audit.log you're looking for, it's been a few years since I've used selinux). If this does turn out to be the problem then you should probably ask on superuser or serverfault rather than SO...
I'm not sure if that's the problem you are having, but I've seen issues when Runtime.exec() is used without reading the associated output buffers. You can find a detailed explanation and potential solutions here. Reading the output and error streams can also help you figure out what's going on at the OS level when you run the command.
I've recently had to do something like this from a Swing app.
You'll probably be able to pull it off with ProcessBuilder, as in Ian's answer, but I found that once things start to get complex, it's easier to write a shell script that does what you want, enabling you to pass as few parameters as possible. Then use ProcessBuilder to invoke the shell script.
If you're invoking anything that has more than really minimal output, you'll also have to read the output and error streams to keep the process from blocking when the output buffers fill, as it seems you are already doing.
I use sudo -S before command and for the tomcat7 user: tomcat7 ALL=(ALL) NOPASSWD:ALL