JSVC and Grizzly

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

JSVC and Grizzly

Scott McClure
Hi all,

I am trying to use JSVC to bind to a privileged port while root, than
run the application as a separate user. This would require that I bind
the port separate from starting the server (accepting connections /
creating a thread pool, etc)

The issue I am facing is in NetworkListener.start() - this call
combines the TCPNIOTransport.bind and the TCPNIOTransport.start.

Additionally, it appears that TCPNIOTransport.bind also listens on the
port as well.

Any suggestions on how to separate binding to the port from the rest of
the operations? Or alternatively, any suggestions on how to bind to
Grizzly a privileged port? Specifically - has anyone used authbind with
Grizzly?

Thanks!
 - Scott
Reply | Threaded
Open this post in threaded view
|

Re: JSVC and Grizzly

Ryan Lubke-2
Looking at the JSVC documentation, it appears it already supports [1]
this functionality (-user option).   I don't believe you need to do
anything special with the application's initialization code.
I'd recommend following up with the jsvc creators to confirm this -
particularly, if it isn't working.


[1] Jsvc allows the application (e.g. Tomcat) to perform some privileged
operations as root (e.g. bind to a port < 1024), and then switch
identity to a non-privileged user.



[hidden email] wrote:

> Hi all,
>
> I am trying to use JSVC to bind to a privileged port while root, than
> run the application as a separate user. This would require that I bind
> the port separate from starting the server (accepting connections /
> creating a thread pool, etc)
>
> The issue I am facing is in NetworkListener.start() - this call
> combines the TCPNIOTransport.bind and the TCPNIOTransport.start.
>
> Additionally, it appears that TCPNIOTransport.bind also listens on the
> port as well.
>
> Any suggestions on how to separate binding to the port from the rest of
> the operations? Or alternatively, any suggestions on how to bind to
> Grizzly a privileged port? Specifically - has anyone used authbind with
> Grizzly?
>
> Thanks!
>   - Scott
Reply | Threaded
Open this post in threaded view
|

Re: JSVC and Grizzly

oleksiys
Administrator
In reply to this post by Scott McClure
Hi Scott,

it's not possible at the moment, but if you can provide more details on
JSVC (based on your question, it should have some programmatic API),
specifically how you think it should work with Grizzly HttpServer, may
be some *fake* code, which will demonstrate that (I see you spent some
time learning Grizzly code, so probably you have some ideas :)). We can
try to implement this feature and include it into the 2.3.4 release
(we're planning 2.3.4 release this week).

Thank you.

WBR,
Alexey.

On 10.07.13 13:41, [hidden email] wrote:

> Hi all,
>
> I am trying to use JSVC to bind to a privileged port while root, than
> run the application as a separate user. This would require that I bind
> the port separate from starting the server (accepting connections /
> creating a thread pool, etc)
>
> The issue I am facing is in NetworkListener.start() - this call
> combines the TCPNIOTransport.bind and the TCPNIOTransport.start.
>
> Additionally, it appears that TCPNIOTransport.bind also listens on the
> port as well.
>
> Any suggestions on how to separate binding to the port from the rest of
> the operations? Or alternatively, any suggestions on how to bind to
> Grizzly a privileged port? Specifically - has anyone used authbind with
> Grizzly?
>
> Thanks!
>   - Scott

Reply | Threaded
Open this post in threaded view
|

Re: JSVC and Grizzly

Scott McClure
Hi Alexey/Ryan,

Here is a simple example. Below is the code for TestDaemon. If you compile that, install jsvc (should be a package on most platforms), and run the command as follows:

sudo jsvc -cp "PATH_TO_JAKARTKA_COMMONS_JAR:PATH_TO_TEST_DAEMON" -user SOME_USER -outfile /tmp/out.log -errfile /tmp/err.log TestDaemon

then maybe try telnetting, then:

sudo jsvc -cp "PATH_TO_JAKARTKA_COMMONS_JAR:PATH_TO_TEST_DAEMON" -user SOME_USER -outfile /tmp/out.log -errfile /tmp/err.log -stop TestDaemon

and then you look at the output of out.log:
[init()]
Binding to 80...
[start()]
Tried to bind to to test port 81 from start(), but failed! - "Permission denied"
Accepting connections on 80...
Stopping....
exiting thread...
Destroying...

You can see that the server was able to bind to a privileged port in init, but not in start. What I didnt fully understand is that JSVC appears to be using Linux capabilities to pull all this off (CAP_NET_BIND_SERVICE). Therefore, the danger of starting something from init is less than I thought (I cant open a file owned and only readable by root, for example). This little experiment has suggested I should probably talk to the JSVC guys a bit more before you make any changes... Once I hear back more lets continue this discussion.

Thanks for the really quick response!


 - Scott

---------------------------------------------------------------------------------------

Source of TestDaemon.java:

import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TestDaemon {

private final ServerSocket socket;
private int port = 80;
private int testPort = 81;
private Thread thread = new Thread() {
@Override
public void run() {
while (true) {
Socket connection = null;
OutputStream stream = null;
try {
connection = socket.accept();
stream = connection.getOutputStream();
stream.write("Hello World!\r\n".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stream != null)
stream.close();
if (connection != null)
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (Thread.interrupted())
break;
}
System.out.println("exiting thread...");
}
};
public TestDaemon() throws Exception {
//unbound
socket = new ServerSocket();
}

public void init(String[] args) throws Exception {
System.out.println("[init()]");
System.out.println("Binding to " + port + "...");
socket.bind(new InetSocketAddress(port));

}

public void start() throws Exception {
System.out.println("[start()]");
try {
new ServerSocket(testPort);
} catch (Exception e) {
System.out.println("Tried to bind to to test port " + testPort + " from start(), but failed! - \"" + e.getMessage() + "\"");
}
System.out.println("Accepting connections on " + port + "...");
thread.start();
}


public void stop() throws Exception {
System.out.println("Stopping....");
//close socket first to get out of blocking on accept
socket.close();
thread.interrupt();
thread.join();

}

public void destroy() {
System.out.println("Destroying...");
}
}



On Wed, Jul 10, 2013 at 5:34 PM, Oleksiy Stashok <[hidden email]> wrote:
Hi Scott,

it's not possible at the moment, but if you can provide more details on JSVC (based on your question, it should have some programmatic API), specifically how you think it should work with Grizzly HttpServer, may be some *fake* code, which will demonstrate that (I see you spent some time learning Grizzly code, so probably you have some ideas :)). We can try to implement this feature and include it into the 2.3.4 release (we're planning 2.3.4 release this week).

Thank you.

WBR,
Alexey.


On 10.07.13 13:41, [hidden email] wrote:
Hi all,

I am trying to use JSVC to bind to a privileged port while root, than
run the application as a separate user. This would require that I bind
the port separate from starting the server (accepting connections /
creating a thread pool, etc)

The issue I am facing is in NetworkListener.start() - this call
combines the TCPNIOTransport.bind and the TCPNIOTransport.start.

Additionally, it appears that TCPNIOTransport.bind also listens on the
port as well.

Any suggestions on how to separate binding to the port from the rest of
the operations? Or alternatively, any suggestions on how to bind to
Grizzly a privileged port? Specifically - has anyone used authbind with
Grizzly?

Thanks!
  - Scott