IMAP and kerberos
| From: | Blaise Camp | Date: | Tue, 06 Nov 2001 19:20:24 +0000 |
| Subject: | IMAP and kerberos | ||
| Groups: | php.general | ||
| Request: | Send a blank email to php-general+get-73641@lists.php.net to get a copy of this message | ||
I apologize for the length of this, but I thought it would be good to get it
all out. If anyone has anything to add, I'd love to hear it. Or if anyone
knows if my work has been worthless, and there's a way around this without
tweaking code, I would be very pleased.
I've been having a lot of fun with PHP, c-client, and kerberos v5 lately.
What I wanted to do was have a user authenticate via a homegrown apache
module which did kerberos authentication, creating a TGT which is stashed
in /var/tmp/tkt/<username's first character>/<username>.
Then the user would access a PHP page which sets the environment KRB5CCNAME,
so that the proper ticket could be found and used with an IMAP session. Much
to my surprise (initially), even with --with-kerberos flags for PHP, there
was no attempted GSSAPI authentication over the IMAP connection. So in the
ext/imap/php_imap.c file, I added the line
auth_link(&auth_gss);
right before
auth_link(&auth_log);
So then it tries to do GSSAPI authentication upon establishing an IMAP
connection. But I discover that despite my setting of the KRB5CCNAME variable
(using putenv), the only place that PHP looks for the ticket is in
/tmp/krb5cc_<server uid>.
So with some trussing I discover that when apache starts up and
auth_link(&auth_gss) is called, a function is called that initializes a
kerberos context, sets KRB5CCNAME (with whatever KRB5CCNAME is currently set
to, or just the default), yadda yadda, etc etc. This apparently sets some
static flags and variables which indicate to kerberos/gssapi that it doesn't
ever need to read the KRB5CCNAME environment variable again. This really
sucks when you want to do a putenv for every individual user so you can
find their TGT.
I wrote to the author of c-client and told him what I was trying to do - that
is, use c-client in a single process to serve multiple users. To
paraphrase his response, "You're trying to do what? It wasn't meant to be
used that way." I was somewhat surprised, since I had thought this
was sort of the intent behind including kerberos support for IMAP in PHP.
Huh. So there are a few things that can be done, a few of which I tried.
1) mangle the c-client auth_link function so that it doesn't initialize some
gssapi/kerberos stuff, so that in your PHP script you can use the KRB5CCNAME
environment variable (but only once). Then set up apache so that each
forked process only services one request. I determined that this was not
too pretty of a solution, especially since I'd be using it for an
application that already gets around 10 hits a second at peak load, and I
want to keep things fast.
2) Let all the tickets go into the default file. But we have over 25,000
users, so the file would end up being huge, and it would take a long time
to find a TGT for a particular user.
3) find a gssapi function, hack the PHP source a little more, and force a
deletion of the gssapi context each time, so the KRB5CCNAME environment
variable is read on each open of an IMAP connection. So this is what I
am currently doing, although it's not in production yet.
Note: this is all with krb5-1.2.2
apache 1.3.20
php 4.0.6
imap-2001a.RELEASE-CANDIDATE.1
Solaris 8
The changes I made were all to php-4.0.6/ext/imap/php_imap.c
Here's what I did:
Added auth_link(&auth_gss); as I said before.
Added #include <gssapi/gssapi.h> at the top of the file.
In
void imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
I added the declaration
OM_uint32 minor_status;
Then, as the first line of code in this function after declarations , I called
gss_krb5_ccache_name(&minor_status, NULL, NULL);
That's it. Hopefully this will be of benefit to someone.
-Blaise