On 5/2/07, Richard Lynch <[EMAIL PROTECTED]> wrote:
On Wed, May 2, 2007 9:41 am, gil ran wrote:
> I am using Apache-2.2.2 with mod_auth_kerb-5.3, php-5.2.1,
> openldap-2.3.27 cyrus-sasl-2.1.21 and heindal-0.7.2 on a
> Linux-from-scratch based system.
>
> The problem I'm presenting is probably a PHP issue or an Apache issue,
> or a mod_auth_kerb issue. I could not understand which one causes the
> problem.
>
> I am trying to connect using SASL and GSSAPI to the LDAP server from a
> PHP script that runs on the Apache server.
>
> The script (in short) does the following:
>   putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
>   echo getenv("KRB5CCNAME");
>   system("klist");

Always use 'exec' instead, and ALWAYS get the output and the error
code and ALWAYS ALWAYS ALWAYS check the error code!

This is not the full code. I did check error codes. Lets call this a
summery of the code.
The "system" command is meant to check if the KRB5CCNAME environment
variable is the valid one when used with "system". This proved that
the variable was indeed passed in this case.

>   $ldapconn = ldap_connect("ldap://example.org";) || die(...);
>   ldap_sasl_bind($ldapconn, NULL, NULL, "GSSAPI") || die(...);
>
> When I run the script manually from a shell that has a proper
> KRB5CCNAME environment variable, both the system("klist") and the
> ldap_sasl_bind(...) work as they should.

When you run the script manually from a shell, you are probably NOT
the same User as PHP runs as, and you are probably NOT using the same
shell either, and you therefore almost certainly do NOT have the same
environment for your test as for Reality.

This is true. I tried from a shell (meaning, running from bash `php
<filename>') in order to debug more easily, and found out that it
always works this way.

This is like stunt-driving a car on a Closed Course with a
Professional Driver, and then pretending that it's safe to do that
same stunt on a busy city street... :-)

99.9% of the time, this problem boils down to:
paths and permissions

Use a FULL PATH for any file/program in your exec call:
NOT klist
/usr/bin/klist
/usr/local/bin/klist
/sharedhost/example.com/usr/local/i/compiled/it/myself/bin/klist

NOT somefile.txt
/full/path/to/wherever/it/lives/somefile.txt

But klist worked. As I said, the klist was added for debug purpose only.

> When I run `restart Apache' and then enter to the PHP page for the
> first time both work as well. The KRB5CCNAME written is
> /tmp/krb5ccname_apache_<something>

I dunno what klist does, nor what any of the KRB stuff is, but if you
want to preserve this KRB thingie from page to page, it looks like you
will need to do more than just run 'klist'...

I don't want to preserve this KRB thingie from page to page. The
opposite is correct: I don't understand why the old file-name is used
instead of the new one.

OK. I'll give some background about KRB5CCNAME, klist, etc.
`klist' is a command that lists the tickets (credentials) that the
current kerberos user holds.
`KRB5CCNAME' contains the full path to a temporary file that holds the
credentials data. This information is passed to the apache by the
browser. The file itself is created by Apache (mod_auth_kerb). Apache
(mod_auth_kerb) also initializes`KRB5CCNAME'.

When using ldap_sasl_bind with the 4th argument set to "GSSAPI" we are
trying to bind to the ldap server using sasl and GSSAPI. The GSSAPI
ignores any provided username/password (authcid, for those of you who
are familiar with sasl). Instead, it uses the information kept in the
"credential cache" file. This is the file Apache (mod_auth_kerb)
creates. This is the file-name provided by it in
$_SERVER['KRB5CCNAME'].

When using GSSAPI for authentication it reads the current credentials
from the "credential cache" file. It knows where it is according to
the environment variable `KRB5CCNAME'.

In this case, for some reason, while KRB5CCNAME contains the correct
value, GSSAPI is not using it. It is using some other value.

You'll need to store the setting somewhere, transmit that storage
location through the stateless HTTP protocol (just like
GET/POST/COOKIE is used) and then retrieve it if it's already been
stored, or make a new one, as appropriate for whatever you are trying
to do, which I also don't really understand, but there it is.

Not relevant. The problem is not that the data is not stored, it's
that the data is stored when I don't want it to be.

> After that, each time I enter the page I get some other KRB5CCNAME
> (other than the one I got before), the system("klist") command works
> as it should, but ldap_sasl_bind returns "Local error". In this case I
> also get an error written to /var/log/auth. This error says that the
> file /tmp/krb5ccname_apache_<something> could not be found (this is
> the same <something> that was written by PHP after I restarted
> Apache). This means that the authentication process tries to use the
> previous file-name.

See above.

> I added a debug print to PHP's ldap_sasl_bind function that prints
> `getenv("KRB5CCNAME")' to Apache's error-log. The KRB5CCNAME written
> to the error-log is the same as the one PHP outputs. Not the one
> written to the auth log.
>
> Why isn't the KRB5CCNAME variable passed on?

Why should it be passed on?

Because this is how the GSSAPI should work, If it has the environment
variable KRB5CCNAME it should use it and pass it on to the
authentication mechanism.

Each "run" of your script is a totally separate process, and if you
have multiple Apache children, they each have their own process.

So unless you've got some magic wand to get them all to share (e.g., a
cross-process storage/communcation) they are not going to share.

> Which of the three (PHP, Apache, mod_auth_kerb) keeps the first
> KRB5CCNAME?

Yes.

:-)

If you are running PHP as CGI, it will never have the same KRB twice,
I suspect.

If you run PHP as Apache module, each Apache child and the related PHP
environment could easily keep its own KRB, I suspect.

I an running PHP as Apache module. All of this works just fine when I
run PHP as CGI...

I got no idea whatsoever what the kerb thing is doing, but as a
mod_xxx, it is also tied to the Apache child process, of which there
might be HUNDREDS.

If you are setting the ENV in the Apache startup with something in
httpd.conf or your Apache startup script, that would maybe share the
KRB across all children, but just setting it with PHP script won't
touch other children.

This is theoretically correct. In practice, something passes the value
of KRB5CCNAME between the children. Could be mod_auth_kerb

> How do I cause the new KRB5CCNAME to be used for authentication?

Hopefully I've outlined the issues enough above for you to know the
answer, even though I have no idea what the answer really is...

--
Some people have a "gift" link here.
Know what I want?
I want you to buy a CD from some indie artist.
http://cdbaby.com/browse/from/lynch
Yeah, I get a buck. So?



Gil Ran.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to