Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

KRB5CCNAME is not reread

142 views
Skip to first unread message

Brian C. DeRocher

unread,
Feb 2, 2006, 5:20:47 PM2/2/06
to
Hello all,

I was adding kerberos authentication to a few web apps. This would be
useful for mediawiki (wikipgedia) and phppgadmin, among others. The
problem we are seeing is that, PHP and its PostgreSQL extension will
make a connection on the first web request. But subsequent requests
to the web server fail to connect to the database because Apache2 and
mod_auth_kerb assign a new KRB5CCNAME value.

The error message is
Warning: pg_connect() [function.pg-connect]: Unable to connect to
PostgreSQL server: krb5_sendauth: No credentials cache found

They have the form /tmp/krb5cc_apache_xxxxxx. Each web request has a
different suffix. However mod_php stays in memory. It appears that
libkrb5 doesn't check if KRB5CCNAME has changed.

Here's a simple demonstration.

/*
kinit before you run this program.

output:
Connection established
Connection failed
krb5_sendauth: No credentials cache found
*/

#include <libpq-fe.h>

int main()
{
system( "cp /tmp/krb5cc_1000 /tmp/krb5cc_first" );
system( "cp /tmp/krb5cc_1000 /tmp/krb5cc_second" );
system( "rm /tmp/krb5cc_1000" );

// First
putenv( "KRB5CCNAME=FILE:/tmp/krb5cc_first" );
PGconn * Conn = PQconnectdb( "host=sauron dbname=tsf" );
if (PQstatus(Conn) == CONNECTION_BAD)
{
printf( "Connection failed\n" );
printf( PQerrorMessage( Conn ) );
}
else printf( "Connection established\n" );
PQfinish( Conn );
system( "rm /tmp/krb5cc_first" );

// Second
putenv( "KRB5CCNAME=FILE:/tmp/krb5cc_second" );
Conn = PQconnectdb( "host=sauron dbname=tsf" );
if (PQstatus(Conn) == CONNECTION_BAD)
{
printf( "Connection failed\n" );
printf( PQerrorMessage( Conn ) );
}
else printf( "Connection established\n" );
PQfinish( Conn );
system( "rm /tmp/krb5cc_second" );
}

Any help would be appreciated.

Thanks,
Brian

--
Brian C. DeRocher @ Mitretek Systems
This email was signed using OpenPGP.

Russ Allbery

unread,
Feb 2, 2006, 5:45:41 PM2/2/06
to
"Brian C DeRocher" <brian.d...@mitretek.org> writes:

> I was adding kerberos authentication to a few web apps. This would be
> useful for mediawiki (wikipgedia) and phppgadmin, among others. The
> problem we are seeing is that, PHP and its PostgreSQL extension will
> make a connection on the first web request. But subsequent requests to
> the web server fail to connect to the database because Apache2 and
> mod_auth_kerb assign a new KRB5CCNAME value.

Er, you're setting up the client to forward its TGT to the web server so
that you can use it to make database connections? That's a heck of a lot
of trust you're placing in that web server....

What problem are you trying to solve by using that approach rather than
the easier approach of giving the web server its own principal and keytab
and having it connect to PostgreSQL using its own credentials while
handling access control inside the application?

> They have the form /tmp/krb5cc_apache_xxxxxx. Each web request has a
> different suffix. However mod_php stays in memory. It appears that
> libkrb5 doesn't check if KRB5CCNAME has changed.

mod_php would need to close and reopen the ticket cache, I believe, to
pick up the change in the default ticket cache name.

--
Russ Allbery (r...@stanford.edu) <http://www.eyrie.org/~eagle/>

Jeffrey Altman

unread,
Feb 2, 2006, 6:10:23 PM2/2/06
to

KRB5CCNAME is an environment variable that is used by the krb5 library
to obtain the "default" credential cache name. This is used when the
application chooses to open the default credentials cache. The
application passes a handle to the credential cache to the library with
each call. If the credential cache needs to be changed, it is the
responsibility of the application to make that decision.

Jeffrey Altman

Stephen Frost

unread,
Feb 2, 2006, 8:54:09 PM2/2/06
to

Fair enough, so perhaps PostgreSQL isn't doing something quite right.
Here's what it's doing inside PQconnectdb() wrt krb5, in a nutshell:

----------------------------
krb5_init_context(&pg_krb5_context);
krb5_cc_default(pg_krb5_context,&pg_krb5_ccache);
krb5_cc_get_principal(pg_krb5_context, pg_krb5_ccache, &pg_krb5_client);
krb5_unparse_name(pg_krb5_context, pg_krb5_client, &pg_krb5_name);
krb5_sname_to_principal(pg_krb5_context, hostname, servicename,
KRB5_NT_SRV_HST, &server);
krb5_sendauth(pg_krb5_context, &auth_context, &sock, servicename,
pg_krb5_client, server, AP_OPTS_MUTUAL_REQUIRED, NULL, 0,
pg_krb5_ccache, &err_ret, NULL, NULL);
krb5_free_principal(pg_krb5_context, server);
----------------------------

It doesn't appear to do anything wrt krb5 in PQfinish().

Now, between the two PQconnectdb() calls the KRB5CCNAME environment
variable changes, which means that it's different between the first
krb5_cc_default() call and the second, yet the second call doesn't seem
to notice this. It looks like pg_krb5_ccache is actually a static
variable- if that's not empty when krb5_cc_default() is called does
krb5_cc_default() just leave it as-is? Looking at this more closely I'm
starting to think the problem is with PostgreSQL after all. :/

Thanks for the comments,

Stephen

signature.asc
0 new messages