On 7 November 2013 17:19, Jeff Trawick <traw...@gmail.com> wrote:
> A few comments down below...

Thanks. I've applied a modified version of my original patch in
r1539746. I hope I've taken on board all your comments.



>
> On Wed, Nov 6, 2013 at 5:53 PM, Steve Hay <steve.m....@googlemail.com>
> wrote:
>>
>> On 6 November 2013 19:06, Jeff Trawick <traw...@gmail.com> wrote:
>> > On Wed, Nov 6, 2013 at 1:20 PM, Steve Hay <steve.m....@googlemail.com>
>> > wrote:
>> >>
>> >> On 6 November 2013 14:27, Jeff Trawick <traw...@gmail.com> wrote:
>> >> > On Wed, Nov 6, 2013 at 8:50 AM, Steve Hay
>> >> > <steve.m....@googlemail.com>
>> >> > wrote:
>> >> >>
>> >> >> On 6 November 2013 13:50, Steve Hay <steve.m....@googlemail.com>
>> >> >> wrote:
>> >> >> > On 6 November 2013 12:27, Jeff Trawick <traw...@gmail.com> wrote:
>> >> >> >> On Wed, Nov 6, 2013 at 4:02 AM, Steve Hay
>> >> >> >> <steve.m....@googlemail.com>
>> >> >> >> wrote:
>> >> >> >>>
>> >> >> >>> On 6 November 2013 00:48, Jeff Trawick <traw...@gmail.com>
>> >> >> >>> wrote:
>> >> >> >>> > Back to the httpd24threading branch:
>> >> >> >>> >
>> >> >> >>> > * modperl_interp_pool_select() has this notion of phase, which
>> >> >> >>> > must
>> >> >> >>> > either
>> >> >> >>> > be startup or request context.
>> >> >> >>> > * It thinks it is startup only if the pool passed in is
>> >> >> >>> > s->process->pconf.
>> >> >> >>> > * Sometimes it is passed s->process->pool (parent of pconf),
>> >> >> >>> > such
>> >> >> >>> > as
>> >> >> >>> > from
>> >> >> >>> > perl_parse_require_line().
>> >> >> >>> > * perl_parse_require_line() can sometimes be called from
>> >> >> >>> > request
>> >> >> >>> > context.
>> >> >> >>> > * When perl_parse_require_line() calls
>> >> >> >>> > modperl_interp_pool_select(),
>> >> >> >>> > request
>> >> >> >>> > context can never be identified because
>> >> >> >>> > perl_parse_require_line()
>> >> >> >>> > never
>> >> >> >>> > passes in r->pool (which I guess would be cmd->pool).
>> >> >> >>> > * etc.
>> >> >> >>> >
>> >> >> >>> > This would seem to be the way to get the right pool to
>> >> >> >>> > modperl_interp_pool_select().
>> >> >> >>> >
>> >> >> >>> > Index: src/modules/perl/modperl_util.c
>> >> >> >>> >
>> >> >> >>> >
>> >> >> >>> > ===================================================================
>> >> >> >>> > --- src/modules/perl/modperl_util.c     (revision 1539040)
>> >> >> >>> > +++ src/modules/perl/modperl_util.c     (working copy)
>> >> >> >>> > @@ -989,7 +989,7 @@
>> >> >> >>> >      int count;
>> >> >> >>> >      void *key;
>> >> >> >>> >      auth_callback *ab;
>> >> >> >>> > -    MP_dINTERP_POOLa(cmd->server->process->pool,
>> >> >> >>> > cmd->server);
>> >> >> >>> > +    MP_dINTERP_POOLa(cmd->pool, cmd->server);
>> >> >> >>> >
>> >> >> >>> >      if (global_authz_providers == NULL) {
>> >> >> >>> >          MP_INTERP_PUTBACK(interp, aTHX);
>> >> >> >>> >
>> >> >> >>> > That still doesn't bring happiness (no interpreter returned,
>> >> >> >>> > resulting
>> >> >> >>> > in a
>> >> >> >>> > crash trying to dereference interp).
>> >> >> >>> >
>> >> >> >>>
>> >> >> >>> I'm getting the same crash-on-startup behaviour now myself after
>> >> >> >>> a
>> >> >> >>> fresh rebuild of everything (now using httpd-2.4.6 and
>> >> >> >>> perl-5.19.5). I
>> >> >> >>> will look back over the changes made on the threading branch
>> >> >> >>> and/or
>> >> >> >>> my
>> >> >> >>> merges of them into the httpd24 branch. Hopefully the answer
>> >> >> >>> lies
>> >> >> >>> there somewhere. I'll be very grateful for any help I can get
>> >> >> >>> with
>> >> >> >>> this though -- I didn't do the original work on either of those
>> >> >> >>> branches...
>> >> >> >>
>> >> >> >>
>> >> >> >> With the "fix" above in place, modperl_init_vhost() seems to be
>> >> >> >> the
>> >> >> >> next
>> >> >> >> crucial code.  We go down this path:
>> >> >> >>
>> >> >> >>     if (base_server == s) {
>> >> >> >>         MP_TRACE_i(MP_FUNC, "base server is not vhost, skipping
>> >> >> >> %s",
>> >> >> >>                    vhost);
>> >> >> >>         return OK;
>> >> >> >>     }
>> >> >> >>
>> >> >> >> and fall through this FIXME in modperl_interp_pool_select():
>> >> >> >>
>> >> >> >>                 if (!scfg->mip) {
>> >> >> >>                     /* FIXME: We get here if global "server_rec"
>> >> >> >> ==
>> >> >> >> s,
>> >> >> >> scfg->mip
>> >> >> >>                      * is not created then. I'm not sure if
>> >> >> >> that's
>> >> >> >> bug
>> >> >> >> or
>> >> >> >>                      * bad/good design decicision. For now just
>> >> >> >> return
>> >> >> >> NULL.
>> >> >> >>                      */
>> >> >> >>                     return NULL;
>> >> >> >>                 }
>> >> >> >>
>> >> >> >> (Note: disabling the base_server == s check in
>> >> >> >> modperl_init_vhost()
>> >> >> >> brings
>> >> >> >> no happiness either, though perhaps it is a step in the right
>> >> >> >> direction.)
>> >> >> >>
>> >> >> >> This path is new with httpd 2.4; 2.2 didn't have authz_providers.
>> >> >> >>
>> >> >> >> This seems to be a whack-a-mole issue.  I'd expect that there is
>> >> >> >> some
>> >> >> >> easy
>> >> >> >> way to grab the interpreter for any arbitrary startup path, but I
>> >> >> >> don't
>> >> >> >> see
>> >> >> >> it.  Maybe it is worthwhile seeing if we already went through
>> >> >> >> some
>> >> >> >> paths
>> >> >> >> where we were able to grab an interpreter.
>> >> >> >>
>> >> >> >
>> >> >> > The last change on the httpd24 branch (r1503193) is what added the
>> >> >> > FIXME above, but it also made a change in
>> >> >> > perl_parse_require_line()
>> >> >> > which I've lost in the course of merging the threading branch in:
>> >> >> > it
>> >> >> > made that function tolerant of modperl_interp_pool_select()
>> >> >> > returning
>> >> >> > NULL (which is exactly what happens in the FIXME case).
>> >> >> >
>> >> >> > If modperl_interp_pool_select() returns NULL then
>> >> >> > perl_parse_require_line() just returns NULL itself in r1503193,
>> >> >> > but
>> >> >> > in
>> >> >> > httpd24threading I've hidden the use of
>> >> >> > modperl_interp_pool_select()
>> >> >> > within the MP_dINTERP_POOLa() macro (as per the general style of
>> >> >> > changes in the threading branch), but that macro crashes if
>> >> >> > modperl_interp_pool_select() has returned NULL.
>> >> >> >
>> >> >> > The diff below makes that macro tolerant of
>> >> >> > modperl_interp_pool_select() returning NULL, and makes
>> >> >> > perl_parse_require_line() tolerant of interp ending up NULL, like
>> >> >> > it
>> >> >> > used to be in r1503193.
>> >> >> >
>> >> >> > With this diff in place (which includes your earlier change), the
>> >> >> > server now starts up for me and tests appear to be running as
>> >> >> > normal.
>> >> >>
>> >> >> Oops! In my excitement I forgot the diff!:
>> >> >>
>> >> >> Index: src/modules/perl/modperl_interp.h
>> >> >> ===================================================================
>> >> >> --- src/modules/perl/modperl_interp.h   (revision 1539262)
>> >> >> +++ src/modules/perl/modperl_interp.h   (working copy)
>> >> >> @@ -68,9 +68,12 @@
>> >> >>  #define MP_INTERP_POOLa(p, s)
>> >> >> \
>> >> >>      MP_TRACE_i(MP_FUNC, "selecting interp: p=%pp, s=%pp", (p),
>> >> >> (s));
>> >> >> \
>> >> >>      interp = modperl_interp_pool_select((p), (s));
>> >> >> \
>> >> >> -    MP_TRACE_i(MP_FUNC, "  --> got (0x%pp)->refcnt=%d",
>> >> >> \
>> >> >> -               interp, interp->refcnt);
>> >> >> \
>> >> >> -    aTHX = interp->perl
>> >> >> +    if (interp) {
>> >> >> \
>> >> >> +        MP_TRACE_i(MP_FUNC, "  --> got (0x%pp)->refcnt=%d",
>> >> >> \
>> >> >> +                   interp, interp->refcnt);
>> >> >> \
>> >> >> +        aTHX = interp->perl;
>> >> >> \
>> >> >> +    }
>> >> >> \
>> >> >> +    NOOP
>> >> >>
>> >> >>  #define MP_dINTERP_POOLa(p, s)
>> >> >> \
>> >> >>      MP_dINTERP;
>> >> >> \
>> >> >> Index: src/modules/perl/modperl_util.c
>> >> >> ===================================================================
>> >> >> --- src/modules/perl/modperl_util.c     (revision 1539262)
>> >> >> +++ src/modules/perl/modperl_util.c     (working copy)
>> >> >> @@ -989,8 +989,11 @@
>> >> >>      int count;
>> >> >>      void *key;
>> >> >>      auth_callback *ab;
>> >> >> -    MP_dINTERP_POOLa(cmd->server->process->pool, cmd->server);
>> >> >> +    MP_dINTERP_POOLa(cmd->pool, cmd->server);
>> >> >>
>> >> >> +    if (!interp)
>> >> >> +       return ret;
>> >> >> +
>> >> >>      if (global_authz_providers == NULL) {
>> >> >>          MP_INTERP_PUTBACK(interp, aTHX);
>> >> >>          return ret;
>> >> >
>> >> >
>> >> > I don't think it will ever have an interpreter except when processing
>> >> > a
>> >> > require from htaccess.  Still, it doesn't crash, and I get the same
>> >> > test
>> >> > results as in my prior post.
>> >> >
>> >> > I think this should trigger an error if we get past these checks with
>> >> > no
>> >> > interpreter:
>> >> >
>> >> > if (global_authz_providers == NULL ||
>> >> > apr_hash_count(global_authz_providers)
>> >> > == 0) {
>> >> >     /* put back an interpreter if we got one */
>> >> >     return ret; /* still NULL; why not make it obvious? */
>> >> > }
>> >> >
>> >> > apr_pool_userdata_get(&key, AUTHZ_PROVIDER_NAME_NOTE,
>> >> > cmd->temp_pool);
>> >> > ab = apr_hash_get(global_authz_providers, (char *) key,
>> >> > APR_HASH_KEY_STRING);
>> >> > if (ab == NULL || ab->cb2 == NULL) {
>> >> >     /* put back an interpreter if we got one */
>> >> >     return ret; /* still NULL; why not make it obvious? */
>> >> > }
>> >> >
>> >> > if (!interp) {
>> >> >     return "Require handler is not currently supported in this
>> >> > context."
>> >> > }
>> >> >
>> >> > And the ordering issue (create interpreter vs. handle Require
>> >> > parsing)
>> >> > still
>> >> > needs to be resolved.
>> >>
>> >> I've committed my change to make the macro more robust, plus your
>> >> change to delay trying to fetch an interpreter -- with an early return
>> >> if it still fails -- in revisions 1539412 and 1539414. Thanks for your
>> >> help with this!
>> >
>> >
>> > Cool!
>> >
>> > BTW, to return an error from a require line parser, you actually return
>> > the
>> > error string (like a directive parser).  Here's an example of one from
>> > mod_ssl that just ensures there are no arguments:
>> >
>> > static const char *ssl_authz_require_ssl_parse(cmd_parms *cmd,
>> >                                                const char *require_line,
>> >                                                const void **parsed)
>> > {
>> >     if (require_line && require_line[0])
>> >         return "'Require ssl' does not take arguments";
>> >
>> >     return NULL;
>> > }
>> >
>> > So returning the error string in the unhandled case (instead of NULL)
>> > would
>> > probably be good.
>>
>> Thanks, I hadn't realized that. I thought this was just pseudo-code
>> when you posted this earlier!
>>
>> Now done in r1539487.
>>
>>
>> >
>> > BUT:
>> >
>> >>
>> >> I don't know what to do about trying to fix it for real (i.e. the
>> >> ordering problem that you refer to). I'm hoping someone else on the
>> >> list might be able to help?
>> >
>> >
>> > I'm trying to follow this through from a directive like in the testcase:
>> >
>> > PerlAddAuthzProvider my-user TestAPI::access2_24->authz_handler
>> >
>> > mod_perl.c has
>> >
>> > MP_CMD_SRV_TAKE2("PerlAddAuthzProvider", authz_provider,
>> > "PerlAddAuthzProvider"),
>> >
>> > authz_provider takes exactly 2 arguments (or httpd will trigger an
>> > error).
>> > The first argument (like "my-user") is name and the second argument
>> > (like
>> > "TestAPI::access2_24->authz_handler") is cb in the following call:
>> >
>> > modperl_register_auth_provider_name(p, AUTHZ_PROVIDER_GROUP, name,
>> >                                         AUTHZ_PROVIDER_VERSION, cb,
>> > NULL,
>> >                                         AP_AUTH_INTERNAL_PER_CONF);
>> >
>> > in modperl_register_auth_provider(), cb and the following NULL are
>> > callback1
>> > and callback2, and we have
>> >
>> >     ab->cb1 = callback1;
>> >     ab->cb2 = callback2;
>> >
>> >     return register_auth_provider(pool, provider_group,
>> > provider_name_dup,
>> >                                   provider_version, ab, type);
>> >
>> > (callback2 always NULL for an authz provider)
>> >
>> > register_auth_provider(), for an authz provider like this, stores ab
>> > (the
>> > two callbacks, one always NULL), in the global_authz_providers hash then
>> > calls the httpd API to point to authz_perl_provider for the authz
>> > provider
>> > with this name (e.g., "my-user").
>> >
>> > authz_perl_provider is the thing that says call perl_parse_require_line;
>> > perl_parse_require_line is our new friend that tries real hard to get an
>> > interpreter in case cb2 is non-NULL, which it never will be, until
>> > PerlAddAuthzProvider is updated to allow an optional 2nd handler which
>> > would
>> > be called at init to check a require line for errors.
>> >
>> > Similarly it would seem that the authn variant, for which a second
>> > handler
>> > would have the task of obtaining a password hash for the realm, also
>> > cannot
>> > be configured.
>> >
>> > From the application/script standpoint, I think the drawback of not
>> > being
>> > able to provide a require line parser is that I'd be required to look at
>> > it
>> > a steady state and possibly encounter configuration errors that could
>> > have
>> > been reported at startup  (a.k.a. not the end of the world; nothing
>> > really
>> > to parse for some authz providers).
>>
>> Many thanks for the analysis. I've added a comment summarizing this in
>> the same revision as above (r1539487).
>>
>> I'm now intending to make similar changes for the PerlAddAuthnProvider
>> case to protect that against a future crash if support for the second
>> handler is ever added there too. Does the following look OK? In
>> particular, is it correct to be returning AUTH_GENERAL_ERROR, or
>> should it be AUTH_USER_NOT_FOUND like the existing early returns are?
>>
>> Index: src/modules/perl/modperl_util.c
>> ===================================================================
>> --- src/modules/perl/modperl_util.c    (revision 1539487)
>> +++ src/modules/perl/modperl_util.c    (working copy)
>> @@ -1116,52 +1116,67 @@
>>                                          const char *realm, char
>> **rethash)
>>  {
>>      authn_status ret = AUTH_USER_NOT_FOUND;
>> -    int count;
>> -    SV *rh;
>>      const char *key;
>>      auth_callback *ab;
>> -    MP_dINTERPa(r, NULL, NULL);
>>
>> -    if (global_authn_providers == NULL) {
>> -        MP_INTERP_PUTBACK(interp, aTHX);
>> -        return ret;
>> +    if (global_authn_providers == NULL ||
>> +        apr_hash_count(global_authn_providers) == 0)
>> +    {
>> +        return AUTH_USER_NOT_FOUND;
>
>
> This is a should-not-occur path.  We shouldn't have been called here without
> us being able to find our configuration.
>
> return AUTH_GENERAL_ERROR;
>
>
>>
>>      }
>>
>>      key = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE);
>>      ab = apr_hash_get(global_authn_providers, key, APR_HASH_KEY_STRING);
>>      if (ab == NULL || ab->cb2) {
>
>
> shouldn't that be "ab == NULL || !ab->cb2" ?
>
> ab == NULL is also a should not occur, right? not a provider we know about,
> so how would we be called?
>
>
>>
>> -        MP_INTERP_PUTBACK(interp, aTHX);
>> -        return ret;
>> +        return AUTH_USER_NOT_FOUND;
>
>
> I believe this is correct; it seems to be handled reasonably by
> mod_auth_digest and mod_auth_basic+AuthBasicUseDigestAlgorithm
>
> But if it were me, I wouldn't even tell them I have a realm hash function
> until there is support for providing a Perl handler for that.
>
>
>>      }
>>
>> -    rh = sv_2mortal(newSVpv("", 0));
>>      {
>> -        dSP;
>> -        ENTER;
>> -        SAVETMPS;
>> -        PUSHMARK(SP);
>> -        XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_ "Apache2::RequestRec",
>> r)));
>> -        XPUSHs(sv_2mortal(newSVpv(user, 0)));
>> -        XPUSHs(sv_2mortal(newSVpv(realm, 0)));
>> -        XPUSHs(newRV_noinc(rh));
>> -        PUTBACK;
>> -        count = call_sv(ab->cb2, G_SCALAR);
>> -        SPAGAIN;
>> +        /* PerlAddAuthnProvider currently does not support an optional
>> second
>> +         * handler, so ab->cb2 should always be NULL above and we
>> will never get
>> +         * here. If such support is added in the future then this code
>> will be
>> +         * reached, but cannot succeed in the absence of an interpreter.
>> The
>> +         * second handler would be called at init to obtain a password
>> hash for
>> +         * the realm, but in the current design there is no
>> interpreter available
>> +         * at that time.
>> +         */
>> +        MP_dINTERPa(r, NULL, NULL);
>> +        if (!interp) {
>> +            return AUTH_GENERAL_ERROR;
>> +    }
>>
>> -        if (count == 1) {
>> -            const char *tmp = SvPV_nolen(rh);
>> -            ret = (authn_status) POPi;
>> -            if (*tmp != '\0') {
>> -                *rethash = apr_pstrdup(r->pool, tmp);
>> +        {
>> +            SV* rh = sv_2mortal(newSVpv("", 0));
>> +            int count;
>> +            dSP;
>> +
>> +            ENTER;
>> +            SAVETMPS;
>> +            PUSHMARK(SP);
>> +            XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_
>> "Apache2::RequestRec", r)));
>> +            XPUSHs(sv_2mortal(newSVpv(user, 0)));
>> +            XPUSHs(sv_2mortal(newSVpv(realm, 0)));
>> +            XPUSHs(newRV_noinc(rh));
>> +            PUTBACK;
>> +            count = call_sv(ab->cb2, G_SCALAR);
>> +            SPAGAIN;
>> +
>> +            if (count == 1) {
>> +                const char *tmp = SvPV_nolen(rh);
>> +                ret = (authn_status) POPi;
>> +                if (*tmp != '\0') {
>> +                    *rethash = apr_pstrdup(r->pool, tmp);
>> +                }
>>              }
>> +
>> +            PUTBACK;
>> +            FREETMPS;
>> +            LEAVE;
>>          }
>>
>> -        PUTBACK;
>> -        FREETMPS;
>> -        LEAVE;
>> +        MP_INTERP_PUTBACK(interp, aTHX);
>>      }
>>
>> -    MP_INTERP_PUTBACK(interp, aTHX);
>>      return ret;
>>  }
>
>
>
>
> --
> Born in Roswell... married an alien...
> http://emptyhammock.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@perl.apache.org
For additional commands, e-mail: dev-h...@perl.apache.org

Reply via email to