I need to programmatically edit, write or delete protected files. In Windows, if i do it manually, it asks for permission and in Unix systems i need "sudo".
How can I ask in Java for higher privileges during execution?
If your program requires high level access it is best to advise the user that they need to run it as root / a privileged account in order to work.
Otherwise the best option is to start a new 'proxy process' that is initialised using "sudo" and then a program doing what you want, eg "sudo cp File1 File2" that will perform your dirty work for you.
Unfortunately this is not cross platform and requires the users password.
There is simply no way you can just bump the JVM to a higher user during execution as this would pose a huge security risk.
md_5
Because Java works using a virtual machine, you can't just start (for example) another thread in an elevated mode. Instead, you'll need to launch an entirely new VM, which you won't be able to connect to.
I'd look into ways of executing a separate Java process which can run with elevated permissions. You can still use the same code, but have it be a main method.
You won't be able to just raise your privillages.
I might be entirely wrong, and am happy to be shown otherwise.
Related
Okay, I realize this might not be possible ...
I have a device that runs linux, and it will likely not have a user interface that is visible. It will have a USB port that is open ... I want to be able to write java to allow the overall system to detect when a device is plugged into the USB port and then mount the device.
I know how to do this from a command line, but it requires "sudo" to fork a new process with elevated privilege to perform the task. I don't know how to write a java program that can get around (yes, I want to get around) the security protection of mount.
runtime.exec() doesn't really do what I am hoping to accomplish. Is this a "can't be done in Java" problem?
I'm hoping to do this without resorting to external executable code.
You can't get around the security protection of mount. The protection is not in mount. The protection is in the kernel.
If by chance you find a way and publish it, it will get removed.
If you have control of the OS you are running on, you can add the option user to the mountpoint in /etc/fstab. After doing so, "mount /path" and "umount /path" work from runtime.exec() without elevation. mount and umount are setuid-root to allow this to work.
File mounts are controlled by the host operating system. So controlling mounts is done through system calls. You seem to be using a Unix operating system, so that means the system call interface is C. So you could use JNI to call a small C function that makes the system call needed.
But all such matters are system dependent, and privileged operations. So that approach creates portability and security problems. So you might do better to reconsider why your program itself must do this, rather than letting a control component (such as systemd) do it for you.
I have to check whether someone started my Java application over the network or not, so that I can shut down the application if it was started from another machine.
The solution has to work on Windows and Linux.
I guess interpreting the current working directory might be a starting point, but I have no idea with Java-class; provide me the feature I need.
Why? If it's for security reasons then you probably are out-of-luck. If the attacker can create a process on your machine, then (s)he will be able to create a process with whatever environmental properties your program checks to decide whether the "user" is remote or local.
If it's for security reasons, then you should be trying to prevent the attacker from communicating with the machine at all.
If it's for some other purpose, then you haven't really provided enough information. What kind of "application?" How does a local user normally start it? How would a remote user try to start it? etc.
Ok, so I have a couple of Java programs that I'm running using a chron job on a linux server. These jobs run every ten minutes or so, take literally two minutes to run, and then exit. I need to add a way for the programs to detect, when they start up, if there is already an instance of themselves running, and if so to exit without going any further. I'm really not sure of the best way to handle this though and am hoping someone can offer some advice.
One approach I've considered is to run a command line argument from the java code that does some sort of PS command and looks through those to see if it's running. This seems pretty finicky and complex though for something so small. Plus, I'm not all that knowledgeable with linux and am not even sure the best way to do that. If anyone has some better thoughts, please let me know. Or if that is the best way, if you could provide the linux commands I'd need I'd appreciate it. Thanks.
If you have a writable /tmp directory you can use a lockfile.
When your Java program starts up, check for a file with a name unique to your application (e.g. "my-lock-file.lock") in the /tmp directory. If none exists, create one, and remove it when you're done. If one exists, just exit.
You can check the existence of a file with the .exists() method of the java.io.File class.
If your code needs to be portable, you can use System.getProperty("java.io.tmpdir")); to get an appropriate temporary directory for the platform your code is running on.
You could look at JMX and the Attach API to query for running JVMs.
Or, as Andrew logvinov mentioned, by using a lock file.
If you are using Java WebStart, there's already native support for this.
Many programs solve this by creating a temporary file that points to their PID (often referred to as a "lock" file). The filename should encode all relevant information to distinguish this process from other processes that could legitimately run in parallel.
For example, if the process is bound to a user, it should contain the user name. If the process is bound to a machine, it should (also) contain the hostname (if you put it in machine-bound temp. directory, this is debatable. If you put it in a home directory, think of the case of multiple machines sharing a home via NFS).
The location of these files is typically /tmp. This is a great location, as /tmp is typically wiped during system boot, so no orphan files are left in case of a system crash. Another solution employed by some programs is to put the lock file in the user settings directory, if it is related to the settings. E.g. mozilla thunderbird has a file called /home/<username>/.thunderbird/<profilename>.default/lock.
The file should contain the PID of the process. The idea is simple: If the file contains the PID, it is easy to check whether this process is indeed still running. So if the process crashes, the file gets orphaned. The new process instance will check the PID in the file, see that it is not running any more, and ignore the file (overwrite).
Putting it all together, you could create a file like this:
/tmp/myawesomeservice-username-hostname-lock
With the content:
12345
I have a batch file that starts a Java process in a Windows 2003 server. As per the security policy, the users of that machine are logged off forcefully, if the user is inactive for a certain period of time. The problem is that when the user is logged out, the process also dies.
I scheduled a new task (Control Panel -> Scheduled Tasks) and selected the option of 'When my computer starts' and gave the user account details there. But it doesn't seem to have any effect, the user is still logged out and the process dies. Is a reboot necessary to make this change effective? And after the reboot, will I achieve what I'm expecting (keeping the process alive)?
Alternatively, will running this process as a Windows Service solve the problem? If so, can you please let me know how I can make a Java program or a batch file to run as a Windows Service? I would prefer not to use any other third party tools or libraries.
Thanks
If you want it to run under Scheduled tasks you have to make sure you don't have "only run when user logged in" checked, which usually means you need to supply a password.
A windows service would be the normal way to do this: the Java service wrapper is 3rd party but loads of people use it.
If you really wanted to not use a 3rd party method you could use svrany.exe (http://support.microsoft.com/kb/137890) on WIndows NT or later, but it is not designed specifically for Java.
Wrapping the process with srvany.exe and launching as a service would work as well.
http://support.microsoft.com/kb/137890
I don't know it this is relevant but we are using a flag to the jvm so it does not shutdown on logoffs
"java -Xrs"
Link to suns description of -Xrs
I'm using Java Service Wrapper to start the java process as windows service.
I guess it works similary to the srvany.exe mentioned in the previous posting.
As per my analysis,
The Idle Solution will be writing a VC++ (.net) Windows Service creation program to launch the .bat / .exe as a System service with all the required call back methods to SCM.
Note :
1. Wrapping the process with srvany.exe would not work as it does not have any call back process to the SCM (Service Control Manager).
2. And java service Wrapper is a third party API (many are LGPL licensed).
We have a Java program run as root on Unix, that therefore can read for example the content of the folders /home/user1 and /home/user2. However, if the Unix user "user1" is logged in in our application, he should not be able to access "/home/user2" data.
We would like to use directly the Unix rights and not recreate all the permissions in our application !
So, could we...
try to change the UID of our
program depending on the user logged
in ? Sounds difficult, and each file
access is in different threads so
the UID would be different on each
thread of our program...
use JNI to read permissions of
"/home/user2"...And then determine
if user1 has sufficient permissions
on "/home/user2" ? (how ?).
Use SecurityManager!
Put current unix user id into ThreadLocal
Create your own SecurityManager that checks unix user permissions on checkRead() and checkWrite()
System.setSecurityManager(new MySecurityManager())
Enjoy
Update
There is no, of course, standard library to read unix file permissions. It's not WORA.
But I have tried briefly to find a ready to use library, and found this one:
http://jan.newmarch.name/java/posix/ It uses JNI, but you don't need to write your own JNI code, which is a big relief. :) I'm sure there must also be others.
Class Stat from there gives you all required access information:
http://jan.newmarch.name/java/posix/posix.Stat.html
Update 2
As folks mentioned, this approach fails to check for "non-standard" unix security features, such as ACL or Posix Capabilities (may be; not sure if they apply to files). But if the goal of being totally in sync with host OS security is set, then we even more need to use SecurityManager, because it's a JVM-wide protection mechanism! Yes, we can start a child SUID-process to verify the permissions (and keep it running, talking to it via pipe running while the user is logged in), but we need to do so from SecurityManager!
The simplest and most portable way would be to spawn a child process, have it exec a wrapper written in C which changes the UID, drops all the privileges (be careful, writting a wrapper to do that is tricky - it is as hard as writing a setuid wrapper), and execs another java instance to which you talk via RMI. That java instance would do all the filesystem manipulation on behalf of the user.
For single-threaded Linux programs, you could instead use setfsuid()/setfsgid(), but that is not an option for portable or multithreaded programs.
if you only want the app to be allowed to read files by user1 i strongly suggest the app runs as user1.
If everything else fails, you can run a shellscript from java and parse the result.
Described for example here
For those who were wondering, it's apparently not possible to do this by calling setuid with JNI for each independent thread. setuid affects the whole process, not just the thread that invoked it.
Should you want to call setuid within a single-threaded Java program there's a good example at http://www2.sys-con.com/itsg/virtualcd/Java/archives/0510/Silverman/index.html.
Another option would be to invert the approach: instead of the code running as root most of the time and either changing the user ID or somehow checking the permissions whenever it has to use some restricted resource, run as the user most of the time and talk to a smaller daemon running as root when it needs to do something only root can do. This also has the added benefit of reducing the attack surface.
Of course, you then have to authenticate the connection from the process running as the user to the process running as root.
I am also having the exact problem as Mikael, and got to this page looking for answers.
None of the answers are 100% satisfactionary for me. So I am thinking of 4 alternatives:
Use a Linux group that has access to all the users. Run a single Java app under that group. This Java app can communicate to the 'root' app using whatever means.
Potentially, it can be "hotel"-ed. e.g. 1 "hotel" (app with group permissions) per 100 users (or as appropriate). So if you have 10,000 users you need 100 hotels, which is quite manageable.
Spawn a JVM for each child app under its own user ID. This is like calling a script, but rather than using stdin/stdio/stderr, use any communication protocol. In my case, I'm using XMPP and IO Data (which, since it's already in use by other components, it doesn't matter "where" aka which JVM it runs).
Create a Super-Server 'root' app. This can be part of the original 'root' app or a separate service dedicated to service management.
The Super-Server is responsible for handling incoming requests (i.e. it practically becomes a reverse proxy) for the user-specific sub-apps, and launching the real child apps (if they're not running already), and passing messages back and forth between the client and the child app(s).
Additionally, the child apps can be pooled (or even "passivated", if there's such thing), much in the way Java EE EJB Container does it. So even if there are 10,000 users and (potentially) 10,000 child apps servicing, the maximum number of child apps running are capped. Idle apps are shut down to make room for others.
Same as #3 but rather than creating a proprietary service management mechanism, integrate with Upstart (or the service management framework in the underlying OS). i.e. there is a 'root' service that can control Upstart. Upstart can start, stop, restart, can query the status of the child services, just like it can control mysqld, Apache, etc.
For me, now, the quickest and simplest to implement would be #1. However, my ideal solution would be #4, but it will take time and testing whether it works well. (the concept itself borrows from inetd/xinetd and EJB, so I think it's pretty sound fundamentally)