views:

837

answers:

6

I would like to start tomcat (Web Server) as a privileged user, and then bring it back to an unprivileged user once it has started. Is there a way to do this programatically, or in general with Linux?

Thanks.

A: 

While a process can drop its own privileges, I don't think you can just change the user of another running process.

Draemon
A: 

You can do it in you own application code via a system call, seteuid (http://www.opengroup.org/onlinepubs/009695399/functions/seteuid.html) but doing it via a bash script or something else, I'm not sure about. Why not just start the process as the normal user in the first place?

Alex Fort
A: 

Can you explain why you want to do this? Generally it's better to define a user that has the privs needed (see the "Principle of Least Privilege") and run it as that user.

Charlie Martin
probably because he wants to listen on a privileged (<1024) port!
Alnitak
+1  A: 

I am aware of kchuid which does exactly that, and although it appears abandoned, it doesn't look like it would be hard to bring up-to-date.

That said, the hosting company I work for does allow (on the shared hosting packages) users to run their own webserver- including Tomcat- on port 80. This is done using a tool called authbind which doesn't require the server start as root- but simply lets non-root users bind to selected IP addresses and selected ports.

The only catch is that authbind won't work with Java's network abstraction layer by default. You will need to disable Java's IPV6 support, and probably specify a specific IP address to bind to within your application. The former can be done by starting the JRE with -Djava.net.preferIPv4Stack=true but the latter is application-specific.

geocar
A: 

You can create a separate program which is started with root privileges (for example by having the binary setuid), does the work which needs privileges, drops the privileges by using setuid, and finally execs tomcat.

Depending on what problem you are trying to solve, this may or may not be a solution. E.g. if you need to run the server with higher priority this would work.

matli
+1  A: 

The underlying system call that you need is setuid(2), but it's not exposed by any of the Java APIs.

It's not hard to write a JNI wrapper that would give access to it though, although even then you'd need to find a suitable place in the Tomcat startup code to invoke setuid after the bind(2) calls have been made (those being the ones that normally require the root privileges).

As recommended by geocar you could use authbind so that Tomcat never needs to run as root at all.

Alternatively, as you've presumably got root access on the server in question, just run Tomcat on a non-privileged port and then use iptables tricks to forward inbound requests from the privileged port to the one that Tomcat is actually listening on. See this SO post for info on how to do this.

Alnitak