Using setuid in Ubuntu to exec Java from C - java

I am running Ubuntu 11.04.
I am trying to use a "C" execlp program to run a Java program, and then I want to setuid on the "C" program so the Java program can execute as root. There is an example of this here:
http://www.coderanch.com/t/110254/Linux-UNIX/setuid
I followed the example to the letter except instead of being the tomcat user, I used root.
Root is able to execute the "C" program which in turn executes the Java program. And, before giving root ownership, the User (me) can run the "C" program which executes the Java program. But once I setup to use setuid, and the User tries to execute the program. I get what seems to be an LD_LIBRARY_PATH type of error:
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
The libjli.so file exists under the Java JRE. Both the User and Root can see this file when they run individually. But the User cannot see it when he runs the program after setuid to root has taken place.
Is there some different way that root's LD_LIBRARY_PATH gets set when a setuid program executes? Is this an interactive vs. non-interactive problem?
Any ideas? Thanks in advance.

As the LD_* environment variables can be used to load code into a process, they are all ignored by setuid binaries. You will probably need to make the setuid binary a wrapper which executes the C program.

Setting the setuid bit on a file will change the process's effective UID but not the real UID. The dynamic linker will check to see if EUID ≠ RUID, and if so, it will ignore all environment variables. Your wrapper will have to filter the environment variables itself (important!) and once done, change the real UID to match the effective UID.
Warning: Don't forget to scrub the environment variables well, unless you are okay with giving everyone on the box full root access.

To work around the LD_* environment constraints on setuid programs, on most POSIX systems you should be able to do this within your wrapper code:
setreuid(0, 0);
which will set both the real and effective UIDs to be root, although this will only work if the program itself was started with the setuid bit enabled.
I wouldn't do it, though.
Look at why your Java program needs to run as root, and see if there are better ways to give it the privileges it needs without actually running as root.

Related

Delete 'CATALINA_HOME' user variable or update the 'CATALINA_HOME' name to 'CATALINA_HOME_1' using java code

I would like to delete the 'CATALINA_HOME' using java code. Please let me know if someone know this type of problem.
Suppose already set 'CATALINA_HOME' = C:\Program Files\Apache
While installing the software, my software should use the my customize tomcat7
and that store in different location.
'CATALINA_HOME' = D:\Installer\Apache
while running the software it find the tomcat this location 'CATALINA_HOME' = C:\Program Files\Apache but my location is
'CATALINA_HOME' = D:\Installer\Apache
I would like to delete the 'CATALINA_HOME' using java code.
Sorry, but you can't. A program (at least on Linux / Unix / Solaris) cannot modify the environment of its parent shell. At most, a program only sees a snapshot of its parent's environment variables ... as they were when the parent forks the child process.
(Windows variables work a bit differently, but I think the same restriction applies ...)
The only thing that a Java can do (reliably / portably) is to change the environment variables that a child process of your Java process will inherit. You can do that using ProcessBuilder.
Now in theory, a program could attempt to modify the source of the variables' values:
On a Unix like system, they often come from one of the shell's RC files; e.g. $HOME/.profile, $HOME/.bashrc and so on ... depending on the shell. Or the variable may have been set in the "init" script that launches Tomcat.
On a Windows system, the may have come from the registry, or a BAT file or ...
The problem is two-fold:
It is impossible to be entirely sure where the value really comes from.
Even if you can be sure, changing the source of the value won't affect the respective shell's current value for the variable.
Note: this is not a shortcoming of Java. You would have the same problem when coding in C, C++, Python ...

Java switch user using su on linux

I am writing a java program dor Oracle EBS that needs to switch user because of specific permissions defined on an user different than applmgr.
The approach we're taking is to have a java class that will switch user on a separate session and then will list the file from a folder that the new user has access.
Any options available?
So far I could create two shell script files and then I run these shell scripts, one that will store environment variables and the other one will actually switch user and list the files.
Appreciate your help.
you could change the group permissions on the file. You could start a System.process( "su user && cat file" ); You could have the other user copy the file to you using a cronjob...
You can try having Java launch a local command on the system then as part of that command launch another program (far from being very clean, but probably would work)
Check out this Class file for examples on launching local commands:
https://github.com/SnakeDoc/RPi_SerialGPS/blob/master/src/com/vanomaly/rpi/serial/gps/util/System.java
You should be able to use setuid - I expect there is a version available directly in Java, but otherwise, it shouldn't be that hard to make your own JNI code to do that.
However, it may be simpler to run a command that switches user (using su or sudo, for example) and then runs the required Java code.

Setting environment variable permanently from java

Using Java,
How can I add environment variable permanently to the existing env variables.
so that when I do a restart operation for windows or Linux, this environment variable is still there.
You might want to take a look at this.
In Windows you can set a Path Variable from command line so it should do the trick.
I realize this is only applicable to Windows.
Not in any cross platform sort of way. In Linux, these are typically controlled via shell init scripts. You would have to edit one of those (which one depends on the user, system, and shell type). In Windows, this is controlled via system configuration (i'd imagine there are some windows specific APIs to modify those).
coppy the path of jdk upto C:\Program Files\Java\jdk1.6.0\bin from program and past in user variables and put ;.; at the end and give name .
and in system variables click on new and enter the name and past the path....and save ...
go to command prompt
..
to check current paths >echo %path%
to set path >set path="C:\Program Files\Java\jdk1.6.0\bin" enter ok now check and run java program
Environment variables are platform specific. Windows stores them in Registry.
*In the registry the User environment variables are stored at
HKEY_CURRENT_USER\Environment
and the System environment variables are stored at
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
(from http://demins.blogspot.co.il/2007/10/where-does-windows-xp-store-evrironment.html)*
There are a lot of ways to access windows registry from java. You can for example execute command line using utility named reg that has a reach command line. You can also use one of interoparability APIs like JaWin, Jinterop, Jintegra. You can also refer to my solution explained here.
On linux you can use command line like export MYVAR=myvalue. I mean execute this command line from java using Runtime.exec() or ProcessBuilder. The problem is that this variable will not become really persistent. It will be visiable for all users until the computers is restarted. To make it really persistent you have to modify user login script (e.g. bashrc file for most linux systems if users's default shell is bash).

Where does Java's ProcessBuilder look to execute commands?

When I execute a command using ProcessBuilder, how does it know where to look for that command? Using this hack/trick I've modified my PATH variable (verified by inspecting processBuilder.environment()) to be bad (empty, working dir, etc) but ProcessBuilder can still execute sort, echo, bash, etc. just fine. How is it doing this?!
Note: My particular development environment is OSX but this code will also run on Red Hat Enterprise Linux.
The documentation says
[...] a command, a list of strings which signifies the external program file to be invoked and its arguments, if any. Which string lists represent a valid operating system command is system-dependent. [...]
Which in essence mean that where it looks for programs to execute depends on the particular system and JVM you're running on.
I can't find a complete matrix of JVM / System behaviors, but supposedly it behaves similar to the popular shells of the system (bash for *nix and cmd for windows) i.e. it searches the directories in the PATH environment variable from left to right and executes the first executable file it finds.
If you want to take control of finding commands, then, well, take control of finding commands. Don't let ProcessBuilder search. Use your own code to find what you want to run, and then put an absolute pathname into the parameter to ProcessBuilder.

Runtime exec output path

I am trying to run a perl command with Java runtime exec in linux/ubuntu/gnome. The command generates an pdf file, but it saves it in my home folder. Is there any way that the exec method can set an output path for the commands executed? Thanks in advance.
The exec method just runs the command on the operating system, so you'll want to change the command you're running with exec more than anything in "Java" per se.
There are a few possibilities:
Change the working directory of your java program. The .pdf is being saved in your working directory because this is where the program is being run.
Unfortunately it's not simple to change this value after the program has been launched. It is, however, trivial to change before the program starts; just change the working directory before starting the program.
Move the file to it's desired location after it's been created in your home directory.
Change the command so that it includes the target location. Your perl script may have an option that will enable you to save it's output to a certain location (usually -o or --output). Using this your program would change from:
Runtime.exec("perl someprogram");
to something like:
Runtime.exec("perl someprogram -o /path/to/some.file")
You might be able to use "output redirection", if there is no option to do this.
Try something like what's below as your argument:
Runtime.exec("perl someprogram > /path/to/some.file")
Unfortunately, without knowing more details of your situation I can't provide more concrete advice.
While each approach has benefits and drawbacks, it's probably best to just implement the one that you understand best; if you can't get one to work, try another.
A good, free online resource for learning is Introduction to Linux: A Hands On Guide.
Section 2.2 has details on cd which you can use for 1..
Section 3.3, section 3 teaches about the mv command, which will be useful in 2..
Section 5.1 is about I/O redirection. Knowing about "output redirection" and the > operator, are important for 4..
For 3., you'll have to consult the documentation of the perl program you're using.
You could modify the Perl script to accept an absolute path for the output.
You can trying setting the working directory using exec(java.lang.String[], java.lang.String[], java.io.File) where File is the directory the command is executed from.
If all else fails, you'll can always copy the generated file from the Home directory to your final location.

Categories

Resources