Thread: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
"Peter Koczan"
Date:
The following bug has been logged online:

Bug reference:      4824
Logged by:          Peter Koczan
Email address:      pjkoczan@gmail.com
PostgreSQL version: 8.4beta2
Operating system:   Red Hat Enterprise Linux 5.3
Description:        KRB5/GSSAPI authentication fails when user != principal
Details:

When authenticating with Kerberos/GSSAPI, if the Kerberos principal is not
the same as the shell user, authentication fails. For instance, as root (for
local fs access) with other tickets (for database and network fs access).

Note: runauth is our homegrown utility to get stashed kerberos tickets.

[root@mitchell ~]# /s/std/bin/runauth -a -l postgres
/s/postgresql-8.4-beta/bin/psql -h mitchell -p 49173 postgres
psql: FATAL:  role "root" does not exist

It appears to assume that the shell user is the user to connect as. However,
using an 8.3 client works as previously expected.

[root@mitchell ~]# /s/std/bin/runauth -a -l postgres
/s/postgresql-8.3/bin/psql -h mitchell -p 49173 postgres
Welcome to psql 8.3.6 (server 8.4beta2), the PostgreSQL interactive
terminal.
...
postgres=# select current_role;
 current_user
--------------
 postgres
(1 row)

This is a difference on the client side.

Even if this is newly expected behavior, it is a change and I could not find
any reference to it in the release notes.

Peter
"Peter Koczan" <pjkoczan@gmail.com> writes:
> PostgreSQL version: 8.4beta2
> Description:        KRB5/GSSAPI authentication fails when user != principal

> When authenticating with Kerberos/GSSAPI, if the Kerberos principal is not
> the same as the shell user, authentication fails.
> It appears to assume that the shell user is the user to connect as. However,
> using an 8.3 client works as previously expected.

This is an intentional change.  It is mentioned in the release notes,
though perhaps not too helpfully:

        Make Kerberos connections use the same method to determine the
        username of the client as all other authentication methods (Magnus)

        Previously a special Kerberos-only API was used.

We should probably at least clarify this release note.  Do you want
to make an argument that this is a fundamental breakage and we need
to revert it?  If so, what's the argument?

            regards, tom lane

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Peter Koczan
Date:
> We should probably at least clarify this release note. =A0Do you want
> to make an argument that this is a fundamental breakage and we need
> to revert it? =A0If so, what's the argument?

Certainly.

It seems like with the changes in 8.4, krb5/gssapi auth looks for a
valid ticket, and if it finds one, connects without regard for the
principal in that ticket. This is a gaping security hole, because it
is very nearly the same as trust authentication.

I'm me...

[koczan@mitchell] ~ $ klist
...
Default principal: koczan@CS.WISC.EDU
...

I connect as me...

[koczan@mitchell] ~ $ /s/postgresql-8.4-beta/bin/psql -h mitchell -p
49173 postgres
psql (8.4beta2)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=3D> select current_role;
 current_user
--------------
 koczan
(1 row)

Now, I connect as someone else...

[koczan@mitchell] ~ $ /s/postgresql-8.4-beta/bin/psql -h mitchell -p
49173 -U strivia postgres
psql (8.4beta2)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=3D> select current_role;
 current_user
--------------
 strivia
(1 row)

Now, I connect as superuser...

[koczan@mitchell] ~ $ /s/postgresql-8.4-beta/bin/psql -h mitchell -p
49173 -U postgres postgres
psql (8.4beta2)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=3D# select current_role;
 current_user
--------------
 postgres
(1 row)

Old clients also exhibit this behavior, so it's also a server-side issue.

[koczan@mitchell] ~ $ /s/postgresql-8.3.6/bin/psql -h mitchell -p
49173 -U postgres postgres
Welcome to psql 8.3.6 (server 8.4beta2), the PostgreSQL interactive termina=
l.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

WARNING:  You are connected to a server with major version 8.4,
but your psql client is major version 8.3.  Some backslash commands,
such as \d, might not work properly.

SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

postgres=3D# select current_role;
 current_user
--------------
 postgres
(1 row)

And just to show you that there is no trickery, I will attempt to
connect without Kerberos tickets.

bash-3.2$ whoami
koczan
bash-3.2$ klist
klist: No credentials cache found (ticket cache
FILE:/var/adm/krb5/tmp/tkt/krb5cc_0_N26236)
...
bash-3.2$ /s/postgresql-8.4-beta/bin/psql -h mitchell -p 49173
postgrespsql: GSSAPI continuation error: Unspecified GSS failure.
Minor code may provide more information
GSSAPI continuation error: Unknown code krb5 195

bash-3.2$ /s/postgresql-8.4-beta/bin/psql -h mitchell -p 49173 -U
postgres postgres
psql: GSSAPI continuation error: Unspecified GSS failure.  Minor code
may provide more information
GSSAPI continuation error: Unknown code krb5 195

This is trust authentication with one rather inconsequential bit of
verification, that's a fundamental breakage. One of the major points
of Kerberos is that, for anything that talks Kerberos, you are the
principal in that ticket. I understand the desire to change some of
that old code, but why is that principal being ignored?

Peter
Peter Koczan <pjkoczan@gmail.com> writes:
> This is trust authentication with one rather inconsequential bit of
> verification, that's a fundamental breakage. One of the major points
> of Kerberos is that, for anything that talks Kerberos, you are the
> principal in that ticket. I understand the desire to change some of
> that old code, but why is that principal being ignored?

Well, the reason for that change was that the libpq code was absorbing
userid from any available Kerberos ticket, even if the server
subsequently issued a non-Kerberos authentication challenge.  I still
think that was wrong.  What your complaint seems to suggest is that
the server-side Kerberos auth code should be insisting that the supplied
principal's first component match the requested database userid.
I kinda thought we *had* been doing that, but can't claim to have read
that code closely.  Magnus?

            regards, tom lane

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Stephen Frost
Date:
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
> Peter Koczan <pjkoczan@gmail.com> writes:
> > This is trust authentication with one rather inconsequential bit of
> > verification, that's a fundamental breakage. One of the major points
> > of Kerberos is that, for anything that talks Kerberos, you are the
> > principal in that ticket. I understand the desire to change some of
> > that old code, but why is that principal being ignored?
>=20
> Well, the reason for that change was that the libpq code was absorbing
> userid from any available Kerberos ticket, even if the server
> subsequently issued a non-Kerberos authentication challenge.  I still
> think that was wrong.  What your complaint seems to suggest is that
> the server-side Kerberos auth code should be insisting that the supplied
> principal's first component match the requested database userid.
> I kinda thought we *had* been doing that, but can't claim to have read
> that code closely.  Magnus?

We should certainly either be requiring the princ match the user in the
database, or that it is allowed through a username mapping where a
mapping table has been supplied, ala ident.

    Stephen

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Magnus Hagander
Date:
Tom Lane wrote:
> Peter Koczan <pjkoczan@gmail.com> writes:
>> This is trust authentication with one rather inconsequential bit of
>> verification, that's a fundamental breakage. One of the major points
>> of Kerberos is that, for anything that talks Kerberos, you are the
>> principal in that ticket. I understand the desire to change some of
>> that old code, but why is that principal being ignored?
>
> Well, the reason for that change was that the libpq code was absorbing
> userid from any available Kerberos ticket, even if the server
> subsequently issued a non-Kerberos authentication challenge.  I still
> think that was wrong.  What your complaint seems to suggest is that
> the server-side Kerberos auth code should be insisting that the supplied
> principal's first component match the requested database userid.
> I kinda thought we *had* been doing that, but can't claim to have read
> that code closely.  Magnus?

We are certainly *supposed* to do that. And we have been doing that. So
if that's not done, it's been broken in 8.4 (most likely by me).

Peter, are you using gssapi or krb5? Only krb5 has changed wrt libpq,
but from your messages it looks like you have gssapi?

Can you show us your pg_hba.conf file, and all lines with krb in them
from postgresql.conf?

Also, can you try it with the server set to log at DEBUG4, and let us
know what output you get?


--
 Magnus Hagander
 Self: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Magnus Hagander
Date:
Magnus Hagander wrote:
> Tom Lane wrote:
>> Peter Koczan <pjkoczan@gmail.com> writes:
>>> This is trust authentication with one rather inconsequential bit of
>>> verification, that's a fundamental breakage. One of the major points
>>> of Kerberos is that, for anything that talks Kerberos, you are the
>>> principal in that ticket. I understand the desire to change some of
>>> that old code, but why is that principal being ignored?
>> Well, the reason for that change was that the libpq code was absorbing
>> userid from any available Kerberos ticket, even if the server
>> subsequently issued a non-Kerberos authentication challenge.  I still
>> think that was wrong.  What your complaint seems to suggest is that
>> the server-side Kerberos auth code should be insisting that the supplied
>> principal's first component match the requested database userid.
>> I kinda thought we *had* been doing that, but can't claim to have read
>> that code closely.  Magnus?
>
> We are certainly *supposed* to do that. And we have been doing that. So
> if that's not done, it's been broken in 8.4 (most likely by me).
>
> Peter, are you using gssapi or krb5? Only krb5 has changed wrt libpq,
> but from your messages it looks like you have gssapi?
>
> Can you show us your pg_hba.conf file, and all lines with krb in them
> from postgresql.conf?
>
> Also, can you try it with the server set to log at DEBUG4, and let us
> know what output you get?

Crap, I think I found the problem.

Tom, or someone else... auth.c line 1076. I'm pretty sure that should be
"return ret" not "return STATUS_OK".

Wow, that's a bad bug :-O

//Magnus

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Magnus Hagander
Date:
Peter Koczan wrote:
> I don't know if it's much use now, but here you go.

<snip>

> May 27 15:37:29 mitchell postgres[30609]: [629-1] LOG:  provided
> username (koczan) and authenticated username (strivia) don't match
> May 27 15:37:29 mitchell postgres[30609]: [630-1] LOG:  connection
> authorized: user=strivia database=postgres

This seems to confirm my suspicions. We detect that the username is
wrong, but we still don't reject the connection.

//Magnus
Magnus Hagander <magnus@hagander.net> writes:
> Tom, or someone else... auth.c line 1076. I'm pretty sure that should be
> "return ret" not "return STATUS_OK".

Doh.

> Wow, that's a bad bug :-O

Hey, that's what beta is for ;-)

You might want to take a quick look for copy-and-pastes of same error.
I see none offhand, but ...

            regards, tom lane

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Magnus Hagander
Date:
Tom Lane wrote:
> Magnus Hagander <magnus@hagander.net> writes:
>> Tom, or someone else... auth.c line 1076. I'm pretty sure that should be
>> "return ret" not "return STATUS_OK".
>
> Doh.

yeah. WIll apply patch.


>> Wow, that's a bad bug :-O
>
> Hey, that's what beta is for ;-)

:-)

Do we need to announce it somehow?


> You might want to take a quick look for copy-and-pastes of same error.
> I see none offhand, but ...

Yeah, I looked over the other similar places and didn't find anything.

//Magnus

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Peter Koczan
Date:
I don't know if it's much use now, but here you go.

On Wed, May 27, 2009 at 3:15 PM, Magnus Hagander <magnus@hagander.net> wrote:
> We are certainly *supposed* to do that. And we have been doing that. So
> if that's not done, it's been broken in 8.4 (most likely by me).
>
> Peter, are you using gssapi or krb5? Only krb5 has changed wrt libpq,
> but from your messages it looks like you have gssapi?

gssapi

> Can you show us your pg_hba.conf file, and all lines with krb in them
> from postgresql.conf?

pg_hba.conf

# this part disables remote "postgres" superuser connections
hostssl all         postgres    127.0.0.1/32       gss
hostssl all         postgres    128.105.207.19/32  gss
hostssl all         postgres    128.105.0.0/16     reject
hostssl all         postgres    198.133.224.0/24   reject

# this part enables non-superuser connections
hostssl all         nobody      128.105.0.0/16     trust
hostssl all         nobody      198.133.224.0/24   trust
hostssl all         all         128.105.0.0/16     gss
hostssl all         all         198.133.224.0/24   gss


postgresql.conf
# Kerberos and GSSAPI
krb_server_keyfile = '/etc/v5srvtab.postgres'
#krb_srvname = 'postgres'               # (Kerberos only)
#krb_caseins_users = off

> Also, can you try it with the server set to log at DEBUG4, and let us
> know what output you get?

Connecting like this...
[koczan@ator] koczan $ /s/postgresql-8.4-beta/bin/psql -h mitchell -p
49173 -U strivia postgres

Produced this in the syslog.
May 27 15:37:29 mitchell postgres[30574]: [624-1] DEBUG:  forked new
backend, pid=30609 socket=8
May 27 15:37:29 mitchell postgres[30609]: [624-1] LOG:  connection
received: host=ator.cs.wisc.edu port=44228
May 27 15:37:29 mitchell postgres[30609]: [625-1] DEBUG:  SSL
connection from "(anonymous)"
May 27 15:37:29 mitchell postgres[30609]: [626-1] DEBUG:  Processing
received GSS token of length 477
May 27 15:37:29 mitchell postgres[30609]: [627-1] DEBUG:  sending GSS
response token of length 114
May 27 15:37:29 mitchell postgres[30609]: [628-1] DEBUG:  sending GSS
token of length 114
May 27 15:37:29 mitchell postgres[30609]: [629-1] LOG:  provided
username (koczan) and authenticated username (strivia) don't match
May 27 15:37:29 mitchell postgres[30609]: [630-1] LOG:  connection
authorized: user=strivia database=postgres
May 27 15:37:29 mitchell postgres[30609]: [631-1] DEBUG:  postgres
child[30609]: starting with (
May 27 15:37:29 mitchell postgres[30609]: [632-1] DEBUG:        postgres
May 27 15:37:29 mitchell postgres[30609]: [633-1] DEBUG:        -v196608
May 27 15:37:29 mitchell postgres[30609]: [634-1] DEBUG:        -y
May 27 15:37:29 mitchell postgres[30609]: [635-1] DEBUG:        postgres
May 27 15:37:29 mitchell postgres[30609]: [636-1] DEBUG:  )
May 27 15:37:29 mitchell postgres[30609]: [637-1] DEBUG:  InitPostgres
May 27 15:37:29 mitchell postgres[30609]: [638-1] DEBUG:  my backend id is 1
May 27 15:37:29 mitchell postgres[30609]: [639-1] DEBUG:  StartTransaction
May 27 15:37:29 mitchell postgres[30609]: [640-1] DEBUG:  name:
unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid:
0/1/0, nestlvl: 1, children:
May 27 15:37:29 mitchell postgres[30609]: [641-1] DEBUG:  CommitTransaction
May 27 15:37:29 mitchell postgres[30609]: [642-1] DEBUG:  name:
unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid:
0/1/0, nestlvl: 1, children:
....
May 27 15:37:55 mitchell postgres[30574]: [625-1] DEBUG:  reaping dead processes
May 27 15:37:55 mitchell postgres[30574]: [626-1] DEBUG:  server
process (PID 30612) exited with exit code 0
May 27 15:38:24 mitchell postgres[30609]: [643-1] DEBUG:  shmem_exit(0)
May 27 15:38:24 mitchell postgres[30609]: [644-1] DEBUG:  proc_exit(0)
May 27 15:38:24 mitchell postgres[30609]: [645-1] LOG:  disconnection:
session time: 0:00:54.389 user=strivia database=postgres
host=ator.cs.wisc.edu port=44228
May 27 15:38:24 mitchell postgres[30609]: [646-1] DEBUG:  SSL: write
alert (0x0100)
May 27 15:38:24 mitchell postgres[30609]: [647-1] DEBUG:  exit(0)
May 27 15:38:24 mitchell postgres[30609]: [648-1] DEBUG:  shmem_exit(-1)
May 27 15:38:24 mitchell postgres[30609]: [649-1] DEBUG:  proc_exit(-1)

Peter

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Magnus Hagander
Date:
Magnus Hagander wrote:
> Tom Lane wrote:
>> Magnus Hagander <magnus@hagander.net> writes:
>>> Tom, or someone else... auth.c line 1076. I'm pretty sure that should be
>>> "return ret" not "return STATUS_OK".
>> Doh.
>
> yeah. WIll apply patch.

And, applied.


--
 Magnus Hagander
 Self: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/
Magnus Hagander <magnus@hagander.net> writes:
> Magnus Hagander wrote:
>> Tom Lane wrote:
>>> Magnus Hagander <magnus@hagander.net> writes:
>>>> Tom, or someone else... auth.c line 1076. I'm pretty sure that should be
>>>> "return ret" not "return STATUS_OK".
>>> Doh.
>>
>> yeah. WIll apply patch.

> And, applied.

I have also patched the release notes to better explain the intentional
change that I initially thought Peter was complaining about:

diff -r1.6 release-8.4.sgml
2706,2707c2706,2707
<         Make Kerberos connections use the same method to determine the
<         username of the client as all other authentication methods (Magnus)
---
>         Do not rely on Kerberos tickets to determine the default database
>         username (Magnus)
2711c2711,2717
<         Previously a special Kerberos-only API was used.
---
>         Previously, a Kerberos-capable build of libpq would use the
>         principal name from any available Kerberos ticket as default
>         database username, even if the connection wasn't using Kerberos
>         authentication.  This was deemed inconsistent and confusing.
>         The default username is now determined the same way with or
>         without Kerberos.  Note however that the database username must still
>         match the ticket when Kerberos authentication is used.

What this still leaves us with is whether that change is a bad idea or
not.  I still think it's OK, but maybe Peter can point to something
else.

            regards, tom lane

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Peter Koczan
Date:
On Wed, May 27, 2009 at 5:16 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> What this still leaves us with is whether that change is a bad idea or
> not. =A0I still think it's OK, but maybe Peter can point to something
> else.

I recompiled postgres with the auth.c patch.

This is only an issue if you are trying to connect as a principal
that's not the same as your current username. Where I work, we have
security and mode bits set up on Kerberos tickets and keytabs such
that you either have to be the user in question or root to get those
credentials. And we only have a couple of things that run as root with
others' principals.

There is a workaround to get the "expected behavior", just specify the
proper username in the connection parameters. This should be
explicitly said in the release notes.

/s/std/bin/runauth -a -l postgres /s/postgresql-8.4-beta/bin/psql -h
mitchell -p 49173 postgres
psql: FATAL:  GSSAPI authentication failed for user "root"
FATAL:  no pg_hba.conf entry for host "128.105.207.19", user "root",
database "postgres", SSL off

[root@mitchell ~]# /s/std/bin/runauth -a -l postgres
/s/postgresql-8.4-beta/bin/psql -h mitchell -p 49173 -U postgres
postgres
psql (8.4beta2)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=3D#

I should also point out that old clients still exhibit the old behavior.

[root@mitchell ~]# /s/std/bin/runauth -a -l postgres
/s/postgresql-8.3.6/bin/psql -h mitchell -p 49173 postgres
Welcome to psql 8.3.6 (server 8.4beta2), the PostgreSQL interactive termina=
l.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

WARNING:  You are connected to a server with major version 8.4,
but your psql client is major version 8.3.  Some backslash commands,
such as \d, might not work properly.

SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

postgres=3D#

It was rather convenient to know that whatever Kerberos principal was
used was going to be the database user. The old behavior is more in
line with other Kerberos'd systems like AFS or NFSv4 that take their
authentication from the Kerberos principal (through an AFS token or
LDAP), sometimes regardless of the shell user. Of course, file systems
are different animals than DBMS's since they need to "always be on"
instead of requiring explicit connections every time you authenticate.
I can't think of any other major services that explicitly use
Kerberos, so I'm not sure how many other models exist.

=46rom a practical standpoint, I can accept this change since there is a
simple workaround and since Kerberos is properly verifying the user.
Though it would be nice to make the assumption that the principal is
the user for Kerberos/GSSAPI connections, I don't think it's worth it
to differently handle that rare case where it would actually make a
difference.

Peter
Peter Koczan <pjkoczan@gmail.com> writes:
> I should also point out that old clients still exhibit the old behavior.

Sure, because this is a libpq change.

> It was rather convenient to know that whatever Kerberos principal was
> used was going to be the database user.

Isn't that still true?  (Modulo the auth.c bug fix of course.)  The only
issue here is where the default guess for a not-explicitly-specified
username comes from, not whether you'll be allowed to connect or not.

            regards, tom lane

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Peter Koczan
Date:
On Thu, May 28, 2009 at 1:30 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Peter Koczan <pjkoczan@gmail.com> writes:
>> It was rather convenient to know that whatever Kerberos principal was
>> used was going to be the database user.
>
> Isn't that still true? =A0(Modulo the auth.c bug fix of course.) =A0The o=
nly
> issue here is where the default guess for a not-explicitly-specified
> username comes from, not whether you'll be allowed to connect or not.

That's what I meant. It was convenient to have the default guess be
the Kerberos principal for krb5/gss connections. This is still the
case in the vast majority of connections, so it's probably not worth
bending over backwards to satisfy these edge cases.

Sorry for the confusion.

Peter

Re: BUG #4824: KRB5/GSSAPI authentication fails when user != principal

From
Peter Koczan
Date:
On Thu, May 28, 2009 at 2:07 PM, Peter Koczan <pjkoczan@gmail.com> wrote:
> On Thu, May 28, 2009 at 1:30 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Peter Koczan <pjkoczan@gmail.com> writes:
>>> It was rather convenient to know that whatever Kerberos principal was
>>> used was going to be the database user.
>>
>> Isn't that still true? =A0(Modulo the auth.c bug fix of course.) =A0The =
only
>> issue here is where the default guess for a not-explicitly-specified
>> username comes from, not whether you'll be allowed to connect or not.
>
> That's what I meant. It was convenient to have the default guess be
> the Kerberos principal for krb5/gss connections. This is still the
> case in the vast majority of connections, so it's probably not worth
> bending over backwards to satisfy these edge cases.

And by "this is still the case", I mean that the principal name and
the username line up and exhibit the same overt behavior. Not that the
principal forces the username.

I need a break. :-)

Peter