You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Remon Sadikni <re...@zmaw.de> on 2011/09/26 12:40:26 UTC

combination of RemoteAddrValve und basic authentication

Dear Tomcat developers and users,

I managed to restrict a web application by IP-adress with 
RemoteAddrValve and to restrict another one by basic authentication. Now 
I would like to restrict the same web application by both methods:
- If the user is inside a specific network (e.g. 134.134.*.*), then he 
should get direct access to the web application (without login window).
- If he is outside this network he has to authenticate via username / 
password.
I tried to combine RemoteAddrValve und basic authentication, but I only 
managed an "AND" conjunction. What I want is a disjunctive combination 
("OR") of these 2 methods . How can I do that?

Thank you very much,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [partially OT] combination of RemoteAddrValve und basic authentication

Posted by André Warnier <aw...@ice-sa.com>.
Remon Sadikni wrote:
> Dear Tomcat developers and users,
> 
> I managed to restrict a web application by IP-adress with 
> RemoteAddrValve and to restrict another one by basic authentication. Now 
> I would like to restrict the same web application by both methods:
> - If the user is inside a specific network (e.g. 134.134.*.*), then he 
> should get direct access to the web application (without login window).
> - If he is outside this network he has to authenticate via username / 
> password.
> I tried to combine RemoteAddrValve und basic authentication, but I only 
> managed an "AND" conjunction. What I want is a disjunctive combination 
> ("OR") of these 2 methods . How can I do that?
> 

Remon,

I do not know how familiar you are with the "web authentication area", but I am quite 
familiar with it, and apart from the purely technical side, let me give you some tips 
based on experience :

If you are going to do user authentication :

It is almost always a bad idea to do such "group authentication" (like you say above : 
"all users within this network").  Some reasons are :
a) it does not allow you afterward, to know "who did what".  This is not only in a 
"police" kind of way, but also for support when something goes wrong.  You will have for 
example a bunch of lines in your server's logfiles, and will not know which ones are 
related to the user who just called you for a problem.
b) it is almost guaranteed that as soon as this works, whoever asked you to do this, will 
come back to you within the next weeks/months, saying : "Now I would like that the users 
of /this/ sub-group (e.g. this sub-series of IP addresses within 134.134.*.*) get 
something slightly different". (Or, "Now we would like access statistics by country".)

So my recommendation would be that, right from the start, you design a system that allows 
to identify *every* user individually, even if for some of them you do not present a login 
dialog and get their user-id from somewhere else, and even if initially the rules for all 
of them are the same.
You will probably thank yourself later.

For example, it is possible that your network "134.134.*.*" is some kind of "inside 
network", which also is a Windows Domain; and that all users within that domain which 
access your server, have first to login to the Windows Domain on their workstation.
In such a case, you could use a module which allows Tomcat to authenticate the user 
automatically (without any visible login dialog) via his Domain user-id.
And such a module, if it cannot find a Domain user-id for a user, could have a "fall-back" 
feature that is Basic Authentication.

I do not know if the relatively recent Tomcat NTLM Realm has such a fall-back feature; but 
one module that has it is Jespa, which you can read about at http://www.ioplex.com.
It is a commercial module, but it is not expensive, and it works.
It also allows you, for a user authenticated automatically through the Windows Domain, to 
request some "user attributes" from the AD directory, such as "user groups", which you can 
then use much like the "roles" in Tomcat, to allow or not access to some applications.
And it works as a Servlet Filter, which means that you can combine it with other filters 
(maybe of your own design), to achieve precisely what you want, on an 
application-by-application base.

I am not trying to sell you one particular module or method. Maybe your case is different, 
and maybe the above is not applicable.  I am just trying to get you to think maybe a bit 
ahead of the particular issue you are having now, and a maybe in a more general way.

(And I have no percentage on Jespa sales; I am just a satisfied user of it).


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

On 9/27/2011 7:40 AM, André Warnier wrote:
> The reason why I was mentioning further complexity for the Valve 
> solution, is that as far as I know, the HttpServletRequest object
> is "immutable" (iow read-only), as it is received.

For the most part, this is true.

> So you cannot just take the incoming HttpServletRequest, and if the
> IP address matches, add a "fake" "Authorization:" header to it with
> some generic user-id/password. You will have to wrap the original
> HttpServletRequest into a custom HttpServletRequest wrapper, (a la
> "class CustomRequest extends HttpServletRequestWrapper"), add the
> fake header there, and forward this CustomRequest instead of the
> original for further processing.

Correct.

> At least, that is what I had to do the last time I wrote some
> Tomcat authentication code as a Servlet Filter.  Maybe for a Valve,
> the situation is different.

Hmm... I was about to say that the Request object is mutable (which it
is), but apparently, headers are something that can't be modified, so
you'll need to wrap the Request in the same way as described above.

Those interested in doing something like this might be interested in
the attachment to this bug:

https://issues.apache.org/bugzilla/show_bug.cgi?id=45014

Hmm... I should go ahead and commit that. :)

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6CD90ACgkQ9CaO5/Lv0PDNMQCdG7+FiiioqZYyLp9e+9jzaVr/
se0AnAh3gTkdCgrvcjnsKD+9/fpeKzVq
=ho/S
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by André Warnier <aw...@ice-sa.com>.
Remon Sadikni wrote:
> Hi André, hi Christopher,
> 
> thanks for your answers.
>>
>> The use of HTTP BASIC authentication confuses things here because of
>> the credential transfer mechanism (HTTP headers). I suppose you could
>> write a Valve that sniffs the user's IP address and then adds HTTP
>> headers to the request for the "Authentication" header to essentially
>> force a login. You'll have to decide what the user's Principal will
>> need to look like (because Tomcat will actually try to /verify/ the
>> fake-user's credentials and maintain a "login" for them, running
>> proper authorization checks, etc.) in order to actually work.
> 
> I think I will try this. Are there any tutorials for writing a Valve? I 
> am a Java programmer but new to Valves.
> 

I am not really a Java programmer, so what I say below may be wrong, and should be 
confirmed by a better guru.

The reason why I was mentioning further complexity for the Valve solution, is that as far 
as I know, the HttpServletRequest object is "immutable" (iow read-only), as it is 
received.  So you cannot just take the incoming HttpServletRequest, and if the IP address 
matches, add a "fake" "Authorization:" header to it with some generic user-id/password.
You will have to wrap the original HttpServletRequest into a custom HttpServletRequest 
wrapper, (a la "class CustomRequest extends HttpServletRequestWrapper"), add the fake 
header there, and forward this CustomRequest instead of the original for further 
processing. In the wrapper class, you also have to override whichever method the Tomcat 
Basic authentication mechanism uses to retrieve the additional "Authorization:" header.
(getHeaderNames, getHeader, getHeaders,..)

At least, that is what I had to do the last time I wrote some Tomcat authentication code 
as a Servlet Filter.  Maybe for a Valve, the situation is different.
Maybe for a seasoned Java programmer this is all a piece of cake; but as for me I had to 
find out the above the hard way, and it was all a bit of a challenge.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Remon Sadikni <re...@zmaw.de>.
Hi Christopher,
> You
>>
> should probably extend ValveBase so you don't have to implement
> all the silly management methods.
>
>> http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/ValveBase.html
>
> This
>>
> will let you implement only the important method: invoke().
>

ok, I will try this.

Thank you very much!
Regards,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Remon Sadikni <re...@zmaw.de>.
Hi Chris,

>> but "allows" is part of RequestFilterValve.
>
> Not in the current trunk. Your code expects the "allows" variable to
> be of type String[], and no such variable exists in RequestFilterValve.

> Right: the point of the RequestFilterValve is that you don't have to
> override the process() method. Overriding it kind of defeats the
> purpose of the class, because it really doesn't have any other methods
> other than the accessors and mutators for the 'deny' and 'allow'
> properties.
>

I only mentioned once, that I use Tomcat 6: And there is an "allows" 
attribute and an additional method "precalculate".

Regards,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Remon,

On 10/19/2011 12:23 PM, Remon Sadikni wrote:
> Hi Chris,
>> 
>> If you overrode the process() method (and I'm sure you changed
>> other things, too, since the variable "allows" is not part of 
>> RequestFilterValve), then you really aren't getting anything by 
>> extending RequestFilterValve.
> 
> but "allows" is part of RequestFilterValve.

Not in the current trunk. Your code expects the "allows" variable to
be of type String[], and no such variable exists in RequestFilterValve.

> I only extended this class. I took the same invoke() method as
> RequestAddrValve, so that I get the IP-address of the user:
> 
> public void invoke(Request request, Response response) throws
> IOException, ServletException { 
> process(request.getRequest().getRemoteAddr(), request, response); 
> }
> 
> and overwrote the process method to react on this IP address.

Right: the point of the RequestFilterValve is that you don't have to
override the process() method. Overriding it kind of defeats the
purpose of the class, because it really doesn't have any other methods
other than the accessors and mutators for the 'deny' and 'allow'
properties.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6fEtAACgkQ9CaO5/Lv0PAVagCdGCDoraUl41tI7H9hgKxIPkqU
AvwAoLV9OW95mDaPVXL7vibCfWo5Yokj
=4oGY
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Remon Sadikni <re...@zmaw.de>.
Hi Chris,
>
> If you overrode the process() method (and I'm sure you changed other
> things, too, since the variable "allows" is not part of
> RequestFilterValve), then you really aren't getting anything by
> extending RequestFilterValve.

but "allows" is part of RequestFilterValve. I only extended this class. 
I took the same invoke() method as RequestAddrValve, so that I get the 
IP-address of the user:

  public void invoke(Request request, Response response)
         throws IOException, ServletException {
    process(request.getRequest().getRemoteAddr(), request, response);
  }

and overwrote the process method to react on this IP address.

>
> Note that there has been some grumbling on the list about the use of
> Matcher.matches() instead of Matcher.lookingAt(): you might want to
> consider your requirements before choosing one over the other: most
> regular expression folks will expect the behavior of lookingAt and not
> matches().

I will look at it.

> Hey, that's an idea: I didn't think of just shoving the principal into
> the request. Just be aware that you will do this on every request,
> because Tomcat isn't storing the Principal anywhere to maintain the
> "login".

That's ok for me.

Regards,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Remon,

On 10/19/2011 7:57 AM, Remon Sadikni wrote:
> I managed to get it working. If you are interested in my solution
> for Tomcat 6: I extended the Valve RequestFilterValve and overwrote
> the method process with this content:
> 
> // Check the allow patterns for (int i = 0; i < allows.length; i++)
> { if (allows[i].matcher(property).matches()) { // create a
> principal for an existing fake user final List<String> roles = new
> ArrayList<String>(); roles.add("ROLE"); final Principal principal =
> new GenericPrincipal(null, "USER", "PASS", roles); // set the
> principal in this request request.setUserPrincipal(principal); } } 
> // pass this request to the next valve (basic authentication) 
> getNext().invoke(request, response); return;

If you overrode the process() method (and I'm sure you changed other
things, too, since the variable "allows" is not part of
RequestFilterValve), then you really aren't getting anything by
extending RequestFilterValve.

Note that there has been some grumbling on the list about the use of
Matcher.matches() instead of Matcher.lookingAt(): you might want to
consider your requirements before choosing one over the other: most
regular expression folks will expect the behavior of lookingAt and not
matches().

> If the User has an allowed IP address, the UserPrincipal will be
> set in this request, so that the next valve (the Basic
> Authentication) will not show the login window. If the User has
> another IP address, the request will be forwarded to the next valve
> without any changes, so that you need to log in.

Hey, that's an idea: I didn't think of just shoving the principal into
the request. Just be aware that you will do this on every request,
because Tomcat isn't storing the Principal anywhere to maintain the
"login".

> At first I tried solving it with RequestWrappers and changing
> Headers, but that failed, because the Basic Authentication Method
> tests for the UserPrincipal.

It should be doing both, but the Principal is more efficient because
you don't have to use  "real" user that can be authenticated using the
webapp's Realm.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6e3RcACgkQ9CaO5/Lv0PCIQQCdGKJ3w7mLQqir8wDswf2b/Np2
x0cAoKzOb5X9Ka/BRpeWzEWie0UMCQqQ
=3Qln
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Remon Sadikni <re...@zmaw.de>.
Hi André, hi Christopher,
>>>
>>> The use of HTTP BASIC authentication confuses things here because
>>> of the credential transfer mechanism (HTTP headers). I suppose
>>> you could write a Valve that sniffs the user's IP address and
>>> then adds HTTP headers to the request for the "Authentication"
>>> header to essentially force a login. You'll have to decide what
>>> the user's Principal will need to look like (because Tomcat will
>>> actually try to /verify/ the fake-user's credentials and maintain
>>> a "login" for them, running proper authorization checks, etc.) in
>>> order to actually work.
>>

I managed to get it working. If you are interested in my solution for 
Tomcat 6: I extended the Valve RequestFilterValve and overwrote the 
method process with this content:

// Check the allow patterns
for (int i = 0; i < allows.length; i++) {
   if (allows[i].matcher(property).matches()) {
     // create a principal for an existing fake user
     final List<String> roles = new ArrayList<String>();
     roles.add("ROLE");
     final Principal principal = new GenericPrincipal(null, "USER", 
"PASS", roles);
     // set the principal in this request
     request.setUserPrincipal(principal);
   }
}
// pass this request to the next valve (basic authentication)
getNext().invoke(request, response);
return;

If the User has an allowed IP address, the UserPrincipal will be set in 
this request, so that the next valve (the Basic Authentication) will not 
show the login window. If the User has another IP address, the request 
will be forwarded to the next valve without any changes, so that you 
need to log in.

At first I tried solving it with RequestWrappers and changing Headers, 
but that failed, because the Basic Authentication Method tests for the 
UserPrincipal.

Thanks for your help,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Remon,

On 9/27/2011 5:14 AM, Remon Sadikni wrote:
> Hi André, hi Christopher,
> 
> thanks for your answers.
>> 
>> The use of HTTP BASIC authentication confuses things here because
>> of the credential transfer mechanism (HTTP headers). I suppose
>> you could write a Valve that sniffs the user's IP address and
>> then adds HTTP headers to the request for the "Authentication"
>> header to essentially force a login. You'll have to decide what
>> the user's Principal will need to look like (because Tomcat will
>> actually try to /verify/ the fake-user's credentials and maintain
>> a "login" for them, running proper authorization checks, etc.) in
>> order to actually work.
> 
> I think I will try this. Are there any tutorials for writing a
> Valve? I am a Java programmer but new to Valves.

It's a very simple interface:

> http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/Valve.html

You
> 
should probably extend ValveBase so you don't have to implement
all the silly management methods.

> http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/ValveBase.html

This
> 
will let you implement only the important method: invoke().

Note that the arguments to that method are Request and Response, which
are Tomcat internal classes. They are similar to the ServletRequest
and ServletResponse classes with which you may have some familiarity,
but they are different so you should make sure you have the Tomcat
Javadocs handy when writing your Valve.

See the documentation for the invoke() method for tips on how to
implement it properly. At some point, you have to make up your own
code to accomplish your own requirements, but you need to follow the
rules for making sure that the Valve actually works when you install it.

Install the Valve by adding a <Valve> declaration in your <Context>
element. I'm not entirely sure if your Valve will be invoked before
the Valves that do Tomcat's authentication and authorization, but you
have to make sure that yours run first. If yours appears to be
skipped, post back and we'll figure out how to get it to run before
the auth stuff.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6CCewACgkQ9CaO5/Lv0PBaIgCggciYF4svta9QFXepV5Zzb85E
pLYAn0orX31r9DbCBMrmfNlWYp6+jqqp
=BJEn
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Remon Sadikni <re...@zmaw.de>.
Hi André, hi Christopher,

thanks for your answers.
>
> The use of HTTP BASIC authentication confuses things here because of
> the credential transfer mechanism (HTTP headers). I suppose you could
> write a Valve that sniffs the user's IP address and then adds HTTP
> headers to the request for the "Authentication" header to essentially
> force a login. You'll have to decide what the user's Principal will
> need to look like (because Tomcat will actually try to /verify/ the
> fake-user's credentials and maintain a "login" for them, running
> proper authorization checks, etc.) in order to actually work.

I think I will try this. Are there any tutorials for writing a Valve? I 
am a Java programmer but new to Valves.

Thank you very much,
Remon

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

On 9/26/2011 9:29 AM, André Warnier wrote:
> You may also want to have a look at SecurityFilter, which could
> well be an easier way for you
> (http://securityfilter.sourceforge.net/) I do not think that it has
> provisions for "automatically" authenticating a user based on his
> client IP address, but it may be easier to just add the required
> code there.

Securityfilter is a bit simpler than Tomcat's authentication system,
and so be a bit more hackable. But sf itself does not have any
CombinedRealm (like Tomcat, which checks attempts several realms for
authentication until one succeeds) nor can it use IP address for
credentials (what is the user's username/id when the IP address is
sufficient for authentication?).

I would have suggested a custom Realm in Tomcat but Tomcat doesn't
give you access to the HttpServletRequest and therefore you can't
sniff the IP address. :(

The use of HTTP BASIC authentication confuses things here because of
the credential transfer mechanism (HTTP headers). I suppose you could
write a Valve that sniffs the user's IP address and then adds HTTP
headers to the request for the "Authentication" header to essentially
force a login. You'll have to decide what the user's Principal will
need to look like (because Tomcat will actually try to /verify/ the
fake-user's credentials and maintain a "login" for them, running
proper authorization checks, etc.) in order to actually work.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6A09IACgkQ9CaO5/Lv0PAJCQCfStx77PBDPC73Qf9riib3FzUL
DKcAnjBmMQgqYC4HW0ohxIVpqmfMf5Tp
=DjaE
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: combination of RemoteAddrValve und basic authentication

Posted by André Warnier <aw...@ice-sa.com>.
Remon Sadikni wrote:
> Dear Tomcat developers and users,
> 
> I managed to restrict a web application by IP-adress with 
> RemoteAddrValve and to restrict another one by basic authentication. Now 
> I would like to restrict the same web application by both methods:
> - If the user is inside a specific network (e.g. 134.134.*.*), then he 
> should get direct access to the web application (without login window).
> - If he is outside this network he has to authenticate via username / 
> password.
> I tried to combine RemoteAddrValve und basic authentication, but I only 
> managed an "AND" conjunction. What I want is a disjunctive combination 
> ("OR") of these 2 methods . How can I do that?
> 
Hi.

Those 2 things do not happen at the same time.
The Valve executes first, and it either blocks the request totally, or lets it through 
unchanged.
Then, if the Valve let the request pass through, comes the authentication/authorization logic.
But by then of course it is too late, because if the request was blocked by the Valve, it 
will not even make it to the AA stage.

What you could do, is write a custom Valve.  This Valve would have to check the client IP 
address, and if it matches the "specific network", it should "pre-authenticate" the 
request, using some dummy user-id (like "internal_user") before it forwards the request.

I am not sure how easy that is however, since I do not know if Tomcat's Basic 
Authentication mechanism /always/ checks the "Authorization:" header first, or if it first 
checks if the request has already a UserPrincipal assigned to it.

(Gurus, please fill in here : ........ )

If the Valve needs to add an "Authorization:" header to the request, then you are in for a 
bit more complexity.

This would be a case where I would handle the problem at the level of a front-end Apache 
httpd, where such things are easier (for me) by an order of magnitude.
I even happen to have written an Apache/mod_perl module which does exactly what you want, 
and more.

You may also want to have a look at SecurityFilter, which could well be an easier way for 
you (http://securityfilter.sourceforge.net/)
I do not think that it has provisions for "automatically" authenticating a user based on 
his client IP address, but it may be easier to just add the required code there.




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org