This question is not as simple as telling me to use runas; Please read the question before answering.
When I use C on UNIX/Linux and want to write a program to run with elevated privilege, I use this flow:
program starts.
process lowers privilege using setuid().
process does unprivileged work.
process raises privilege using
setuid().
process does privileged work such as opening a
restricted file.
process lowers privilege using setuid().
The critical part of the flow is that the process lowers its privilege immediately after starting and only raises its privilege long enough to do the corresponding work.
How can I do a similar thing on Windows using Java?
My specific use case is that I want to read and write protected files such that the only way for the user of the program to access the files is thru my Java program. I do not want to run the entire process with Administrator privilege just to protect a couple of files.
The JRE by itself does not allow this. There are two options to do it in "Java":
Use JNI to make C calls into the OS
Script out the calls that use setuid() (use a script language or create a C executable) and have the JVM exec that script.
I believe the more difficult part of your problem will be finding a setuid() equivalent in Windows. See https://serverfault.com/questions/16886/is-there-an-equivalent-of-su-for-windows. The most straightforward way would be to wrap runas (yes, I said it) in a script or perhaps exec your script with runas. See Run command prompt as Administrator for ideas on how to do that.
Related
I have a java program that should run on a Windows machine. It should run "forever", i.e. when the JVM or the program crashes, it should be restarted. When the computer is restarted it should also be restarted.
I saw advice to wrap the program as a "Windows service", but the tools I found seem to be either costly, complicated or outdated.
Can somebody describe me a straightforward way to achieve the desired behaviour?
For the part where you want to start the program after restart you can create a simple batch (.Bat) file and u can put that file in the startup folder.
Also you can use the same file for running the program when it crashes. you can use tasklist command and check if your java program is running and if it is not .just start the program.
Just check our windows batch this is one of the best things you can get everything for doing anything on windows without anything expensive
Yet Another Java Service Wrapper is a tool that easily wraps your Java program into a Windows service. Just start the program, note down the PID and enter it into the wrapper. Two things, which are probably universal to services, should be noted:
For connection to the network, you need to specify an account with the necessary rights.
Connected network drives are not available.
To ensure the correct function of my Java program I need to know which other Java processes are running on the system currently that I have NOT started.
How do I get information about the other running Java processes?
Is it possible to terminate this Java processes from my Java application? It is NOT possible the exit the whole Java process, because that will terminate my program, too.
Is it possible to write a platform independent source code?
Many thanks in advance!
First: I assume you cant control the other java process, and you have not written it
solution 1: use platform dependant commands to kill the other process. Not safe at all.
Runtime runtime = Runtime.getRuntime();
public Process exec(String[] cmdarray);
see that: Killing a process using Java
Platform independant: NO, because of precedent procedures
Solution 2, safer : use JMX , and it is platform independant
example here:How to stop java process gracefully?
Solution 3:
If you can do something with the other process: try to synchronize something (file, or else), to quit quietly.
When we run Runtime.exec(cmd), what user will it be run from? For example, user1(on Unix) ran java -jar Test.jar. In this program we have Runtime.exec("whoami"). Which user id shall we recieve?
I have screen'd terminal, where was ran chrootuid cmd and there is running java program. And somehow, whoami command from this pr. returns NOT SAME user id as chrootuid's owner, from which name was J.p. ran. Can anybody explain this?
All child processes run as the same user as the parent process.
As #SLaks says, the script will be run as the same user which has launched the JVM in the first place.
Rundown:
the JVM is launched within a process;
this process has plenty of data inherited from its parent, along which the user which launched it;
the standard Java API has no way to modify the user;
even if it had such power, changing the running user would require elevated privileges anyway.
So, there you are: the "forked" process will run with the same credentials as the JVM.
Now, some more information on running a separate process in general...
In Java, you really want to use a ProcessBuilder instead of Runtime.exec(), for the following reasons:
it allows you to control I/O output;
it allows you to specify command line arguments "the right way" (think: argument with spaces);
it allows you to defer execution (.start()).
But it clearly does not allow you fine-grained control of shared resources, nor privilege modifications, as native APIs can do. Still, ProcessBuilder is better than Runtime.exec() by a large margin, but Java is yet to experience a radical change for process handling as the new java.nio.file is to File: a revolution.
I need to update my application. To do this, I delete the .jar file my program is currently running from and create a new one with the same name, then restart the application.
However, when I attempt to do this I get a java.io.IOException: Access is denied.
How can I fix this?
Thanks!
The problem is, the jar files are been used by the JVM (specifically, the class loaders). Even under Java 7, where the jar files are closed by the class loaders when the are no longer needed, there is no guarantee that the underlying resources will be released, or more specifically, when they will be released.
For some more information, take a look at Closing a URLClassLoader
You have a few choices.
You Could...
Separate your update process from your application (so it's a standalone program) and use parentless execution process to update the application. This involves executing your program in such away that it allows the current process to terminate before the new process, under windows this can be achieved using something like...
cmd /c start /b /normal "" {command line to be executed}
Under Linux I believe you can use nohup, but I have no experience with that.
(Don't forget to use System.exit to terminate the current process ;))
You Could...
You could use Java Web Start which provides it's own updating capabilities
Is it possible to stop an application in windows using java code ?
I'd like to create a program which is like a shortcut to stop an application on my pc. Is it possible using ProcessBuilder ? Thank you
Plain Java, without native access? No.
ProcessBuilder lets you control processes that you started from within the Java application, but it doesn't give you control to processes that were started by other processes.
As per user988052's comment, you can use pskill from the Sysinternals Suite to accomplish this through Runtime.exec. pskill uses the TerminateProcess function call. You can also call this function with JNI (or some other native caller, like JNA, NLink, etc.), but you'll need to obtain a handle to the process via the OpenProcess function call.
Is it possible to stop an application in windows using java code ? ... Is it possible using ProcessBuilder ?
Only if you launched the application from the same Java application that you are trying to fill it from.
Other than that, you need to resort to running a Windows-specific command to do the killing ... or something based on JNI to make native Windows library calls.
The other complications are that you may not be able to kill certain processes due to permissions issues, and some process may refuse to be killed.
I believe the JRE does not provide an API for system processes. ProcessBuilder can create system processes, but it cannot provide you with a Process object for a process created outside the JVM. I believe that is a philosophical decision on the part of the Java folks, to avoid certain OS-specific tasks where possible. You might think that every OS has pids, or that they all have some kind of kill message, but Java runs on lots of OSes, some of them quite strange.
You could make native code to do it and wrap that with JNI, but that would be wasteful. As Mr 988052 says, I suggest you execute a system-specific command through Runtime.exec or ProcessBuilder. You would need to decide which OSes you want to support, and be sure to get the commands (and the OS-detection code) right for each one.