sethandlers question

2008-10-12 Thread André Warnier

Hi.

Still around a new perl AAA module I'm writing, a question :

If I have a Location like so :



  SetHandler jakarta-servlet
  SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk

  PerlXXXHandler My::Module->some_method

  ...



("jakarta-servlet" above means mod_jk --> Tomcat)
(and PerlXXXHandler being any kind of Perl HTTP Handler running soon enough)

The Question :
Is it possible, in the PerlXXXHandler, on a request-by-request base, to 
"disable" the jakarta-servlet handler, and install the following instead


  SetHandler modperl
  PerlResponseHandler My::Module->some_other_method

?

I know that I can do something like the above for regular static pages, 
and I use this already :

  $r->handler('modperl');
  $r->set_handlers(PerlAuthzHandler => []); # stop authorization from 
running

  $r->set_handlers(PerlResponseHandler => \&_send_login_form);


However, when I try to do the same in a Location like the above, it 
seems that the jakarta-servlet handler runs anyway, and my 
PerlResponseHandler is never called.


The reason I want to do it that way, is that it allows me, in the 
substituted PerlResponseHandler, to do some stuff to the login page that 
I send, which would be more complicated to do via a simple redirect.

Or ?

(One thing I have not tried (nor researched) e.g., is to see if I can 
install both modperl and the jakarta-servlet as handlers, and disable 
the modperl handler if the condition is /not/ met.)


Thanks


Re: sethandlers question

2008-10-13 Thread Torsten Foertsch
On Sun 12 Oct 2008, André Warnier wrote:
> 
>
>    SetHandler jakarta-servlet
>    SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
>
>    PerlXXXHandler My::Module->some_method
>
>    ...
>
> 
>
> ("jakarta-servlet" above means mod_jk --> Tomcat)
> (and PerlXXXHandler being any kind of Perl HTTP Handler running soon
> enough)
>
> The Question :
> Is it possible, in the PerlXXXHandler, on a request-by-request base,
> to "disable" the jakarta-servlet handler, and install the following
> instead
>
>    SetHandler modperl
>    PerlResponseHandler My::Module->some_other_method
>
> ?
>
> I know that I can do something like the above for regular static
> pages, and I use this already :
>    $r->handler('modperl');
>    $r->set_handlers(PerlAuthzHandler => []); # stop authorization
> from running
>    $r->set_handlers(PerlResponseHandler => \&_send_login_form);
>
>
> However, when I try to do the same in a Location like the above, it
> seems that the jakarta-servlet handler runs anyway, and my
> PerlResponseHandler is never called.

Does that piece of code run in a /Perl(PostReadRequest|Trans|
MapToStorage)Handler/ ?

Please, have a look again at the ap_process_request_internal() function 
in httpd-2.x.y/server/request.c. This function implements almost the 
complete request cycle (save PostReadRequest, Response and Log).

Just after ap_run_translate_name(), that is the PerlTransHandler, you'll 
see this piece:

/* Reset to the server default config prior to running 
map_to_storage
 */
r->per_dir_config = r->server->lookup_defaults;

if ((access_status = ap_run_map_to_storage(r))) {
/* This request wasn't in storage (e.g. TRACE) */
return access_status;
}

/* Rerun the location walk, which overrides any map_to_storage 
config.
 */
if ((access_status = ap_location_walk(r))) {
return access_status;
}

/* Only on the main request! */
if (r->main == NULL) {
if ((access_status = ap_run_header_parser(r))) {
return access_status;
}
}
...

The line "r->per_dir_config = r->server->lookup_defaults;" resets all 
request specific configurations applied so far. After that line the 
request is configured as if no Directory/Location or other container 
were present in your httpd.conf. Next comes MapToStorage. Here 
Directory, DirectoryMatch, Files and FilesMatch containers are applied 
to the request. Then, and this is what I think hits you, comes an 
ap_location_walk. Here Location containers are applied. So, your 
SetHandler inside the Location overrides any $r->handler seen before.

After the ap_location_walk comes the PerlHeaderParserHandler. But it is 
skipped for subrequests. A further examination will show you that the 
next phase that is run by all requests is the PerlTypeHandler just 
before Fixup. So, move your "$r->handler('modperl');" to one of those 
and it will work. I prefer Fixup but that is based only on the fact 
that it is documented as do-what-you-want phase. There are directives 
that change the handler in the type-checker phase. In fact the 
AddHandler directive works that way. Mod_mime looks at the file 
extension and adjusts the handler, e.g "AddHandler cgi-script .pl". So 
using Fixup your module is the last to kick in.

To carry state around use pnotes, notes or subprocess_env.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


Re: sethandlers question

2008-10-13 Thread André Warnier

Hi Torsten.
Once again, I thank you for the time spent researching and answering my 
question(s).
Unfortunately, I am less fluent in C than you (which is why after all I 
like and use mod_perl), so sometimes referring me to the C code is not 
as enlightening to me as it undoubtedly is to you.  But I am trying to 
follow, nevertheless.


Torsten Foertsch wrote:

On Sun 12 Oct 2008, André Warnier wrote:



   SetHandler jakarta-servlet
   SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk

   PerlXXXHandler My::Module->some_method

   ...



("jakarta-servlet" above means mod_jk --> Tomcat)
(and PerlXXXHandler being any kind of Perl HTTP Handler running soon
enough)

The Question :
Is it possible, in the PerlXXXHandler, on a request-by-request base,
to "disable" the jakarta-servlet handler, and install the following
instead

   SetHandler modperl
   PerlResponseHandler My::Module->some_other_method

?

I know that I can do something like the above for regular static
pages, and I use this already :
   $r->handler('modperl');
   $r->set_handlers(PerlAuthzHandler => []); # stop authorization
from running
   $r->set_handlers(PerlResponseHandler => \&_send_login_form);


However, when I try to do the same in a Location like the above, it
seems that the jakarta-servlet handler runs anyway, and my
PerlResponseHandler is never called.


Does that piece of code run in a /Perl(PostReadRequest|Trans|
MapToStorage)Handler/ ?


No, at the moment it runs in a PerlAuthenHandler.
As explained the other thread (requests and subrequests), I thought it 
was more elegant and mod_perl-ish, instead of doing a re-direct to a 
login page if the user needed authentifying, to having the login page 
returned by a content handler.
(One main reason is that it allows me, in that content handler,to 
"filter" the login page and insert in it, things I have stored 
previously in $r->pnotes().)
For that thus, when the user is not authenticated when the request hits 
the PerlAuthenHandler, this handler tries to set the content handler 
(PerlResponseHandler) to the method send_login_form() in the same module.
This works fine when the previous content handler is Apache's default, 
iow for static pages.  But it fails miserably when there is already a 
specific content handler (like mod_jk) for this Location.




Please, have a look again at the ap_process_request_internal() function 
in httpd-2.x.y/server/request.c. 
I would first have to know where this thing is.  I have never so far 
looked at the Apache source code, so I need some pointers there.
Not that if I look, I would necessarily understand much of it, but I can 
try.

Now, why would I, since you provide the nice explanation below ?

This function implements almost the

complete request cycle (save PostReadRequest, Response and Log).

Just after ap_run_translate_name(), that is the PerlTransHandler, you'll 
see this piece:


/* Reset to the server default config prior to running 
map_to_storage

 */
r->per_dir_config = r->server->lookup_defaults;

if ((access_status = ap_run_map_to_storage(r))) {
/* This request wasn't in storage (e.g. TRACE) */
return access_status;
}

/* Rerun the location walk, which overrides any map_to_storage 
config.

 */
if ((access_status = ap_location_walk(r))) {
return access_status;
}

/* Only on the main request! */
if (r->main == NULL) {
if ((access_status = ap_run_header_parser(r))) {
return access_status;
}
}
...

The line "r->per_dir_config = r->server->lookup_defaults;" resets all 
request specific configurations applied so far. After that line the 
request is configured as if no Directory/Location or other container 
were present in your httpd.conf. Next comes MapToStorage. Here 
Directory, DirectoryMatch, Files and FilesMatch containers are applied 
to the request. 
So, you mean that for every and each request, Apache re-configures 
itself ?  If that is so, it is quite amazing the speed at which it can 
serve a page..


Then, and this is what I think hits you, comes an
ap_location_walk. Here Location containers are applied. So, your 
SetHandler inside the Location overrides any $r->handler seen before.

Well, I am not sure :
The handler set in the configuration file for that Location, is 
originally "jakarta-servlet" (as per the snippet below).
It is I, in my PerlAuthenHandler, who is trying to reset this to 
"modperl", and in mod_perl, to my send_login_page() method.

Before I do that, there is no $r->handler nor PerlResponseHandler set.

I may be misunderstanding what you say above of course..



After the ap_location_walk comes the PerlHeaderParserHandler. But it is 
skipped for subrequests.

That's fine, we are always in a main request here.

 A further examination will show you
(probably not)
that the
next phase that is run by all requests is the PerlTypeHandler just 
before Fixup. So, move your "$r->handler('modperl');" to one of thos

Re: sethandlers question

2008-10-13 Thread Torsten Foertsch
On Mon 13 Oct 2008, André Warnier wrote:
> As explained the other thread (requests and subrequests), I thought
> it was more elegant and mod_perl-ish, instead of doing a re-direct to
> a login page if the user needed authentifying, to having the login
> page returned by a content handler.

The apache-way to do this has a name: ErrorDocument or in mod_perl 
$r->custom_response. Configure an ErrorDocument for 403 and return 
HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403 
status is logged and that the browser (think about search engines) sees 
it. But the custom response page must be larger than 512 bytes or 
you'll encounter problems with IE. If you don't care about that you can 
use $r->internal_redirect. That is a bit less work to do for your 
server.

> > Please, have a look again at the ap_process_request_internal()
> > function in httpd-2.x.y/server/request.c.
>
> I would first have to know where this thing is.  I have never so far
> looked at the Apache source code, so I need some pointers there.
> Not that if I look, I would necessarily understand much of it, but I
> can try.
> Now, why would I, since you provide the nice explanation below ?

Out of curiosity! Just download the apache source untar it and open in 
in your favorite editor. C is not that much different from perl and the 
request.c file is really easy to read. You don't have to modify it, 
just try to understand what is going on!

> So, you mean that for every and each request, Apache re-configures
> itself ?  If that is so, it is quite amazing the speed at which it
> can serve a page..

Just keep in mind for the following that apache is originally designed 
to have a static configuration. So at start it splits the configuration 
into blocks, one holds the basic config that is outside all containers 
and others for each Location/Directory/etc. From those blocks it 
generates pre-parsed configuration vectors. At runtime each request 
starts with the basic config fetched from r->server->lookup_defaults 
then it looks for other vectors matching the request and merges them.

But there is another configuration source, .htaccess. Those are read in, 
compiled and merged in the same function (ap_directory_walk() (hard to 
understand)) that applies Directory containers (called from 
ap_run_map_to_storage()).

With mod_perl comes yet another configuration source, $r->add_config. 
This is implemented very similar to .htaccess only the directives are 
not read from a file but from memory and they are compiled and merged 
at the time $r->add_config is called.

> Well, I am not sure :
> The handler set in the configuration file for that Location, is
> originally "jakarta-servlet" (as per the snippet below).
> It is I, in my PerlAuthenHandler, who is trying to reset this to
> "modperl", and in mod_perl, to my send_login_page() method.
> Before I do that, there is no $r->handler nor PerlResponseHandler
> set.

So, why not issue a $r->internal_redirect. I don't exactly know when the 
SetHandler directive sets $r->handler. Maybe it is done in the type 
checker phase. So perhaps you have to move your code to Fixup or use 
$r->add_config(['SetHandler modperl']).

> I don't think I can do that, unless I want the PerlTypeHandler or
> PerlFixupHandler to become an authentication handler.  That would
> probably for one upset Adam, for two be kind of funky, no ?

Why not?

if( $override_handler ) {
  $r->push_handlers( PerlFixupHandler=>__PACKAGE__.'::fixup' );
  $r->pnotes->{override_handler}='modperl';
}
...
sub fixup {
  $_[0]->handler($_[0]->pnotes->{override_handler};
  return Apache2::Const::OK;
}

> Now, in summary :
> This is a very specialised authentication module, meant to be used in
> very specific circumstances and not for general usage.  I control the
> environment, so I can pretty much do what I want as long as it does
> not crash the system or present some big security hole or the like.
>
> In my case, that  containing the
> sethandler jakarta-servlet
> is pretty much unique: it is not a sub- or super-location of anything
> else, and it fulfills only one very narrow purpose.
> To my knowledge, there will be no other module playing a role there,
> other than the jakarta-servlet initial handler, plus whatever I
> decide to put in there as mod_perl modules and methods.
> This for the entire duration of one request.
>
> Now, assuming I have no other stuff in there than the following lines
> 
>     SetHandler jakarta-servlet
>     SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
>
>     AuthType MyModule
>     AuthName MyXyzApp
>     PerlSetVar MyModule_var1 "value"
>     PerlAccessHandler My::Module->some_access_method
>     PerlAuthenHandler My::Module->some_auth_method
>     PerlAuthzHandler My::Module->some_authz_method
>     require valid-user
>
> 
>
> then, if I understand correctly what you write above, since I have no
> PerlTransHandler, nor Fixup, etc..  I should be able to do the same
> in

Re: sethandlers question

2008-10-14 Thread Torsten Foertsch
On Tue 14 Oct 2008, André Warnier wrote:
> I doubly appreciate not only because my immediate problem is solved,
> but also because I learned a lot in the process.

Try the $r->add_config again with the right override flag (OR_FILEINFO) 
and you'll see it will also work.

> It seems to me that this whole thread could be collected and
> re-arranged into a Tutorial on mod_perl phases, authentication,
> interactions with Apache etc..  but honestly at the moment I don't
> know where to begin.

Find a place where you think it would fit and send in a patch, see 
http://perl.apache.org/contribute/svn_howto.html#Working_with_SVN on 
how to get the source.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


Re: sethandlers question

2008-10-14 Thread André Warnier

Hi.

I have read and pondered your earlier responses, and I am sure that the 
correct solution is somewhere around the ErrorDocument or the 
$r->internal_redirect.
But I wanted to exhaust the other possibilities first, for the sake of 
completeness and also to learn more about this all.


So one little bit at a time :

reminder of my config :


SetHandler jakarta-servlet
SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk

AuthType MyModule
AuthName MyXyzApp
PerlSetVar MyModule_var1 "value"
PerlAccessHandler My::Module->some_access_method
PerlAuthenHandler My::Module->some_auth_method
PerlAuthzHandler My::Module->some_authz_method
require valid-user




And, in summary, what I was trying to do is :
if the PerlAuthenHandler finds that the request is not authenticated, 
then it tries to change the response handler for this request, from the 
original "jakarta-servlet" handler, to my own response handler, which in 
fact returns a login page.
(I need something "active" to return the login page, because I need to 
insert some data into the login page prior to returning it).


And for that I used this code in the PerlAuthenHandler :

# set our own response handler
$r->handler('modperl');
$r->set_handlers(PerlResponseHandler => \&_send_login_form);
return OK;


One of the possibilities envisioned previously was :



Or, a thought that just occurred to me, is the solution for me
(stopping jakarta-servlet from running and running my
PerlresponseHandler instead), as easy as setting the "no-jk" variable
(if I can do that within my PerlAuthenHandler, and how) ?


I was tempted to suggest that. But I don't know nothing about jakarta. 
If you want to try use $r->subprocess_env->{'no-jk'}=1;




I tried this, because it was the smallest possible change to my module.
It works, in the sense that it sets the "no-jk" variable, which 
consequently has the effect of making the "jakarta-servlet" handler 
above not process this link.
But it is not a solution for me, since what happens is that the 
jakarta-servlet handler is in fact still executed by Apache as the 
response handler, but it probably just returns DECLINED.
Then Apache seems to handle the response with its own default handler, 
which results in a "404 not found" error.


The other possibility looked at was :
> Or, another thought that just occurred : can I comment out the
> > "SetHandler jakarta-servlet" originally, set my PerlresponseHandler
> > as the default handler in the , and then *if the user is
> > authenticated* (the contrary of my current condition), *set* the
> > content handler to be jakarta-servlet instead of modperl ?

> Torsten said : Of course.
But Torsten did not say how, and I don't know how to do that.
How can I set the Apache response handler to be "xyz" ?  All I have at 
this point is the name of that handler : "jakarta-servlet".
This is not a perl handler, it is mod_jk.so, the Apache/Tomcat AJP 
connector. (And I do not need code, I just need a pointer in the right 
direction).


This is now purely for curiosity and for future reference, because after 
your previous explanations, I am convinced that this is not the right 
solution for the current problem.


In the meantime, I'll go have a look at $r->internal_redirect, which is 
probably the correct solution.





Re: sethandlers question

2008-10-14 Thread André Warnier


Torsten Foertsch wrote:
[...]


The apache-way to do this has a name: ErrorDocument or in mod_perl
$r->custom_response. Configure an ErrorDocument for 403 and return
HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403
status is logged and that the browser (think about search engines) sees
it. But the custom response page must be larger than 512 bytes or
you'll encounter problems with IE. 

> If you don't care about that you can

use $r->internal_redirect. That is a bit less work to do for your
server.



At this moment, I cannot see clearly how the ErrorDocument solution 
would allow me to send back a login page created dynamically, as I need 
to do.  I will look it up, but as a definitive solution for the time 
being I would prefer the $r->internal_redirect method, where I can see 
more clearly how to do this.


But I still have some (hopefully) last questions, if you would be so kind :

As I understand this, the internal_redirect() basically stops the 
current request, and replaces it in-place by a totally new request, 
except that in that new request, $r->prev will be set to the (original) 
request that did the redirect, right ?


(So in the new request, I can still access the pnotes set by the 
original request, via $r->prev->pnotes()).


For this new request, the cycle restarts right at the beginning, and
runs through all the steps just as if this was a main request. Right ?

Are there any other significant differences between this new request and
the previous one that I should be very aware of (in a mod_perl/AAA 
context) ?


One thing I do not really understand, is what happens to the original
request, when it issues a call to $r->internal_redirect().
Does the original request still run to completion, or does it "abort"
right there ?
Does Apache still return something to the browser for the original
request, or is that completely replaced by whatever the new (redirected)
request produces ?
After the call to $r->internal_redirect(), should the original request 
still do something ? (like return Apache2::Const::?) ?


Thanks

P.S.
I have downloaded the Apache source, and looked at the code within 
httpd-2.x.y/server/request.c, but it is still a bit obscure to me, 
except in a very general sense.  I kind of approximately follow the 
steps, but do not always understand aspects like why it re-does 
directory walks at several stages, nor can I see at all where mod_perl 
plugs in to that code.





Re: sethandlers question

2008-10-14 Thread Torsten Foertsch
On Tue 14 Oct 2008, André Warnier wrote:
> When I try this, I get an Apache error with the following logfile
> message : [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207]
> $r->add_config() has failed: SetHandler not allowed here at
> /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n

That is an apache error. SetHandler needs the FileInfo override flag, 
see http://httpd.apache.org/docs/2.2/mod/core.html#sethandler. So, the 
correct command would be:

  $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO)

or simpler

  $r->add_config(['SetHandler ...'], ~0)

(since you know what directive you are adding).

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


Re: sethandlers question

2008-10-14 Thread Torsten Foertsch
On Tue 14 Oct 2008, André Warnier wrote:
> At this moment, I cannot see clearly how the ErrorDocument solution
> would allow me to send back a login page created dynamically, as I
> need to do.  I will look it up, but as a definitive solution for the
> time being I would prefer the $r->internal_redirect method, where I
> can see more clearly how to do this.


PerlAuthenHandler "sub { \
  return Apache2::Const::FORBIDDEN unless ...;
}"
ErrorDocument 403 /login



SetHandler modperl
# you still have to supply a login_form function that expects a
# $r object.
PerlResponseHandler "sub { \
  my $r=shift; \
  $r->content_type('text/html'); \
  $r->print(login_form($r->prev));
  return Apache2::Const::OK;
}"


Your A-handler returns 403. Instead of sending the standard FORBIDDEN 
page to the browser apache catches the error because of the 
ErrorDocument directive. "/login" looks like an URI. Hence apache will 
perform an internal redirect to it. "/login" is configured in the 
normal modperl-way.

The browser will see an HTTP status of 403 (it will also be logged as 
403). But the message sent along will be the output of &login_form. And 
that is what the user will see. &login_form has access to the original 
request. So, it can pass the original URI in a hidden field.

See also http://httpd.apache.org/docs/2.2/mod/core.html#errordocument

Instead of 403 you can also use 401 if you want to use 
http-authentication. That is the user will see a browser generated 
password box. But I doubt that is what you want.

> But I still have some (hopefully) last questions, if you would be so
> kind :
>
> As I understand this, the internal_redirect() basically stops the
> current request, and replaces it in-place by a totally new request,
> except that in that new request, $r->prev will be set to the
> (original) request that did the redirect, right ?

Yes. Best if you return OK from the current handler right after the 
$r->internal_redirect line.

> (So in the new request, I can still access the pnotes set by the
> original request, via $r->prev->pnotes()).

Yes.

> For this new request, the cycle restarts right at the beginning, and
> runs through all the steps just as if this was a main request. Right
> ?

AAA are possibly skipped as I mentioned before.

> Are there any other significant differences between this new request
> and the previous one that I should be very aware of (in a
> mod_perl/AAA context) ?

You'll find some, ;-)

> One thing I do not really understand, is what happens to the original
> request, when it issues a call to $r->internal_redirect().
> Does the original request still run to completion, or does it "abort"
> right there ?

I think you'll see the original request again in the logging phase.

> Does Apache still return something to the browser for the original
> request, or is that completely replaced by whatever the new
> (redirected) request produces ?

No, not unless you have sent something prior to the internal_redirect.

> After the call to $r->internal_redirect(), should the original
> request still do something ? (like return Apache2::Const::?) ?

OK, see 
http://perl.apache.org/docs/2.0/api/Apache2/SubRequest.html#C_internal_redirect_

> P.S.
> I have downloaded the Apache source, and looked at the code within
> httpd-2.x.y/server/request.c, but it is still a bit obscure to me,
> except in a very general sense.  I kind of approximately follow the
> steps, but do not always understand aspects like why it re-does
> directory walks at several stages, nor can I see at all where
> mod_perl plugs in to that code.

great! Many treasures are hidden there.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


Re: sethandlers question

2008-10-14 Thread André Warnier
I am trying the 4 receipes one after the other, in order of easiest to 
more complicated.


Torsten Foertsch wrote:


2) replace $r->handler('modperl') in the aaa phase by 
$r->add_config(['SetHandler modperl']). This way you override the 
handler set in the configuration structure. In the fixup phase it is 
then automagically copied to $r->handler.

When I try this, I get an Apache error with the following logfile message :
[Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207] 
$r->add_config() has failed: SetHandler not allowed here at 
/usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n




3) leave the $r->handler('modperl') and add a 
$r->add_config(['SetHandler none']);



When I try this, I get an Apache error with the following logfile message :
[Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207] 
$r->add_config() has failed: SetHandler not allowed here at 
/usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n



So it seems that something does not like the $r->add_config from within 
an AAA method, or at least not when trying to change the handler.


I'll try the others now.



Re: sethandlers question

2008-10-14 Thread André Warnier

André Warnier wrote:
I am trying the 4 receipes one after the other, in order of easiest to 
more complicated.


Torsten Foertsch wrote:


2) replace $r->handler('modperl') in the aaa phase by 
$r->add_config(['SetHandler modperl']). This way you override the 
handler set in the configuration structure. In the fixup phase it is 
then automagically copied to $r->handler.

When I try this, I get an Apache error with the following logfile message :
[Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207] 
$r->add_config() has failed: SetHandler not allowed here at 
/usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n




3) leave the $r->handler('modperl') and add a 
$r->add_config(['SetHandler none']);



When I try this, I get an Apache error with the following logfile message :
[Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207] 
$r->add_config() has failed: SetHandler not allowed here at 
/usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n



So it seems that something does not like the $r->add_config from within 
an AAA method, or at least not when trying to change the handler.




But
> 4) set $r->handler in a fixup handler.

this works :

$r->set_handlers(PerlAuthzHandler => []); # disable authorization
$r->set_handlers(PerlResponseHandler => \&_send_login_form);
$r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')});


Many, many thanks for all the explanations and tips.

I doubly appreciate not only because my immediate problem is solved, but 
 also because I learned a lot in the process.


It seems to me that this whole thread could be collected and re-arranged 
into a Tutorial on mod_perl phases, authentication, interactions with 
Apache etc..  but honestly at the moment I don't know where to begin.




Re: sethandlers question

2008-10-14 Thread Torsten Foertsch
On Tue 14 Oct 2008, André Warnier wrote:
> reminder of my config :
> >> 
> >>     SetHandler jakarta-servlet
...
> >> 
>
> And, in summary, what I was trying to do is :
> if the PerlAuthenHandler finds that the request is not authenticated,
> then it tries to change the response handler for this request, from
> the original "jakarta-servlet" handler, to my own response handler,
> which in fact returns a login page.
> (I need something "active" to return the login page, because I need
> to insert some data into the login page prior to returning it).
>
> And for that I used this code in the PerlAuthenHandler :
>
> # set our own response handler
> $r->handler('modperl');
> $r->set_handlers(PerlResponseHandler => \&_send_login_form);
> return OK;

The problem is the $r->handler statement. The program flow is this:

- ...
- uri translation
- map to storage
- Location container is applied
  the SetHandler directive is applied to the requests configuration
  structure. That does not mean $r->handler is set. It is simply noted
  there is a SetHandler directive active for the request.
- aaa
- ...
- fixup
  the SetHandler value is copied to $r->handler. See
  httpd-2.x.y/server/core.c:core_override_type()

if (conf->handler && strcmp(conf->handler, "none"))
r->handler = conf->handler;

  That means $r->handler is set only if there was a SetHandler directive
  and if it was not "SetHandler none".

So, that leads us to 4 possible solutions:

1) remove the SetHandler directive from the Location container and set 
$r->handler either to jakarta-servelet or to modperl in your aaa 
handler. It won't be touched if other modules don't kick in. mod_dir 
comes to mind but it reads (fixup handler):

/* In case mod_mime wasn't present, and no handler was assigned. */
if (!r->handler) {
r->handler = DIR_MAGIC_TYPE;
}

So, that's not a problem. But there may be other modules that don't 
check that.

2) replace $r->handler('modperl') in the aaa phase by 
$r->add_config(['SetHandler modperl']). This way you override the 
handler set in the configuration structure. In the fixup phase it is 
then automagically copied to $r->handler.

3) leave the $r->handler('modperl') and add a 
$r->add_config(['SetHandler none']);

4) set $r->handler in a fixup handler.

$r->add_config works very similar to


your directives


The only difference is the time when it is applied to the config struct. 
That config is reset after the translation phase. So it is useless to 
try $r->add_config before. Location containers from the httpd.conf are 
applied after MapToStorage. So anything you do in your own MapToStorage 
handler can be overridden in Location containers even if your handler 
returns OK to skip the core MapToStorage handler.

But anything applied after that, that means from the header-parser phase 
onward overrides the httpd.conf settings.

> One of the possibilities envisioned previously was :
> >> Or, a thought that just occurred to me, is the solution for me
> >> (stopping jakarta-servlet from running and running my
> >> PerlresponseHandler instead), as easy as setting the "no-jk"
> >> variable (if I can do that within my PerlAuthenHandler, and how) ?
> >
> > I was tempted to suggest that. But I don't know nothing about
> > jakarta. If you want to try use $r->subprocess_env->{'no-jk'}=1;
>
> I tried this, because it was the smallest possible change to my
> module. It works, in the sense that it sets the "no-jk" variable,
> which consequently has the effect of making the "jakarta-servlet"
> handler above not process this link.
> But it is not a solution for me, since what happens is that the
> jakarta-servlet handler is in fact still executed by Apache as the
> response handler, but it probably just returns DECLINED.

That's what I thought it would.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


Re: sethandlers question

2008-10-15 Thread Torsten Foertsch
On Tue 14 Oct 2008, Torsten Foertsch wrote:
> On Tue 14 Oct 2008, André Warnier wrote:
> > When I try this, I get an Apache error with the following logfile
> > message : [Tue Oct 14 16:10:40 2008] [error] [client
> > 84.158.163.207] $r->add_config() has failed: SetHandler not allowed
> > here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line
> > 414.\n
>
> That is an apache error. SetHandler needs the FileInfo override flag,
> see http://httpd.apache.org/docs/2.2/mod/core.html#sethandler. So,
> the correct command would be:
>
>   $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO)
>
> or simpler
>
>   $r->add_config(['SetHandler ...'], ~0)
>
> (since you know what directive you are adding).

Maybe others are interested too, here are 2 private messages:

On Wed 15 Oct 2008, André Warnier wrote:
> Ok, I did, and it seems to work too :
>
> So I have 2 sequences that work :
> a)
>   $r->add_config(['SetHandler modperl'], ~0);
>   $r->set_handlers(PerlAuthzHandler => []); # disable authorization
>   $r->set_handlers(PerlResponseHandler => \&_send_login_form);
>   #$r->set_handlers(PerlFixupHandler => sub {
> $_[0]->handler('modperl') } );
>
> b)
>   #$r->add_config(['SetHandler modperl'], ~0);
>   $r->set_handlers(PerlAuthzHandler => []); # disable authorization
>   $r->set_handlers(PerlResponseHandler => \&_send_login_form);
>   $r->set_handlers(PerlFixupHandler => sub {
> $_[0]->handler('modperl') } );
>
> Now, can you explain ?
> I don't even understand what "~0" means..

On Wed 15 Oct 2008, Torsten Foertsch wrote:
> On Wed 15 Oct 2008, André Warnier wrote:
> > 1) you mentioned that it was due to a Apache bug.
>
> Did I really say bug? I meant an Apache error message. You'll see the
> same message if you try something like that:
>
> 
> AllowOverride AuthConfig
> 
>
> and then have an .htaccess with a SetHandler directive in it.
> SetHandler needs "AllowOverride FileInfo". But only AuthConfig is
> set.
>
> The 2nd parameter to add_config is a AllowOverride bit field. It
> limits what kind of directives are allowed to be added. Think of it
> as if you have read the directives from an untrusted source (like
> .htaccess).
>
> > 2) I do not have a clue why the above would work around that bug.
>
> Apache wants here not only to be told to add the SetHandler but also
> to be ensured "Yes, that is what I want. Just do it!".
>
> ~0 means all bits turned on.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]


SetHandlers question, Phase II

2008-10-15 Thread André Warnier

Help ! (please)

To make a long story short, I created an Apache/mod_perl module for AAA, 
which after major help from Torsten Foertsch now works fine... on one 
system, but not on another relatively similar one.  The module is called 
AUTH::StarLogCookie.


the critical line is line 419 of the module, which says :

$r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')});

On one system, this works fine, but on the other one it brings this 
error in the Apache log :
[Tue Oct 14 18:50:26 2008] [error] [client 84.158.163.207] Can't locate 
object method "handler" via package "AUTH::StarLogCookie" at 
/usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 419.\n


The system where it works fine is this one :
ok-system (Intel-based) :
[Tue Oct 14 16:58:47 2008] [notice] Apache/2.2.3 (Debian) DAV/2
SVN/1.4.2 mod_jk/1.2.18 PHP/4.4.4-8+etch4 mod_ssl/2.2.3 OpenSSL/0.9.8c
mod_perl/2.0.2 Perl/v5.8.8 configured -- resuming normal operations

and the one where it brings the error is this one :
bad-system (Apple PPC-based) :
[Tue Oct 14 18:59:43 2008] [notice] Apache/2.2.9 (Debian) DAV/2
mod_jk/1.2.26 mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal
operations

There is a difference between the versions of Apache, perl and mod_perl, 
so my question is : can this problem be attributed to these version 
differences ?


The funny thing is, the way I understand that code above is to mean :
"take a reference to the piece of code between the curly brackets, and 
pass that code reference as the 2d argument to $r->set_handlers()".
But the error message seems to indicate that perl is actually trying to 
execute "$_[0]->handler()" at that point, no ?


Thanks.


Re: SetHandlers question, Phase II

2008-10-15 Thread Clinton Gormley

>  $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')});

> The funny thing is, the way I understand that code above is to mean :
> "take a reference to the piece of code between the curly brackets, and 
> pass that code reference as the 2d argument to $r->set_handlers()".
> But the error message seems to indicate that perl is actually trying to 
> execute "$_[0]->handler()" at that point, no ?
> 

Actually, this code takes a reference to the value returned when you run
the code between the curlies.


What I can't figure out is why it works at all in one of your systems :)

I think you're wanting:

 $r->set_handlers(PerlFixupHandler => sub {$_[0]->handler('modperl')});

hth

Clint




Re: SetHandlers question, Phase II

2008-10-15 Thread André Warnier

Thanks.
Duh.

Clinton Gormley wrote:

 $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')});



The funny thing is, the way I understand that code above is to mean :
"take a reference to the piece of code between the curly brackets, and 
pass that code reference as the 2d argument to $r->set_handlers()".
But the error message seems to indicate that perl is actually trying to 
execute "$_[0]->handler()" at that point, no ?




Actually, this code takes a reference to the value returned when you run
the code between the curlies.


What I can't figure out is why it works at all in one of your systems :)

I think you're wanting:

 $r->set_handlers(PerlFixupHandler => sub {$_[0]->handler('modperl')});


Yes.  That works.
Thank you, my mistake.  Shows how easily I get confused when trying to 
do anything even remotely sophisticated with perl references.


Now that you pointed this out, I also don't understand why it is running 
on the other system.  It would be interesting to figure out what the 
returned value of that call is (was) (probably the old value of 
handler()), and why it is then different between these two systems also. 
 The module is exactly the same in both cases, and it is called in the 
same circumstances, from a  section configured in the same way.

Yes, I know, there must be a difference. Hmm.




Re: SetHandlers question, Phase II

2008-10-15 Thread Torsten Foertsch
On Wed 15 Oct 2008, André Warnier wrote:
> > I think you're wanting:
> >
> >      $r->set_handlers(PerlFixupHandler => sub
> > {$_[0]->handler('modperl')});
>
> Yes.  That works.

Better to return something sane from the handler:

sub {$_[0]->handler('modperl');0}  # 0==Apache2::Const::OK

Also consider push_handlers instead of set_handlers. In case other 
modules already have set a fixup handler.

Torsten

--
Need professional mod_perl support?
Just hire me: [EMAIL PROTECTED]