Обсуждение: BUG #4126: KRB5/GSSAPI authenication fails for multipart kerberos principals

Поиск
Список
Период
Сортировка

BUG #4126: KRB5/GSSAPI authenication fails for multipart kerberos principals

От
"Peter Koczan"
Дата:
The following bug has been logged online:

Bug reference:      4126
Logged by:          Peter Koczan
Email address:      pjkoczan@gmail.com
PostgreSQL version: 8.3.1
Operating system:   Red Hat Enterprise Linux 5
Description:        KRB5/GSSAPI authenication fails for multipart kerberos
principals
Details:

When trying to connect to an 8.3 server using a multipart Kerberos principal
(e.g. ator/wsbackup.cs.wisc.edu@CS.WISC.EDU or koczan/mail@CS.WISC.EDU
instead of wsbackup@CS.WISC.EDU or koczan@CS.WISC.EDU), the connection
fails, claiming a name mismatch. This is a change from 8.2 and I found
nothing in the changelog or documentation to suggest this change or offer a
workaround.

This happens no matter what client libraries I'm using (I'll connect using
8.3 clients only to illustrate this point).

Here's what happens with a normal login principal:

[koczan@ator] ~ $ klist
Ticket cache: FILE:/var/adm/krb5/tmp/tkt/krb5cc_3258_zWQIbO
Default principal: koczan@CS.WISC.EDU
...

[koczan@ator] koczan $ /s/postgresql-8.3/bin/psql -h sensei -p 5432 sushi
Welcome to psql 8.3.1 (server 8.2.6), the PostgreSQL interactive terminal.

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.2,
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)

sushi=> select version();
                                  version

----------------------------------------------------------------------------

 PostgreSQL 8.2.6 on i686-pc-linux-gnu, compiled by GCC gcc.bin (GCC) 3.4.4
(1 row)

sushi=> select current_user;
 current_user
--------------
 koczan
(1 row)


[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 49173 sushi
Welcome to psql 8.3.1, the PostgreSQL interactive terminal.

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

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

sushi=> select version();
                                  version

----------------------------------------------------------------------------

 PostgreSQL 8.3.1 on i686-pc-linux-gnu, compiled by GCC gcc.bin (GCC) 3.4.4
(1 row)

sushi=> select current_user;
 current_user
--------------
 koczan
(1 row)


And what happens with my "mail" instance:

[root@ator ~]# su - koczan
[koczan@ator] ~ $ klist
klist: No credentials cache found (ticket cache
FILE:/var/adm/krb5/tmp/tkt/krb5cc_3258_xQK9wc)
...

[koczan@ator] ~ $ kinit -f -k -t /var/adm/krb5/quickauth/kt/koczan.mail.kt
-l 1d koczan/mail@CS.WISC.EDU
[koczan@ator] ~ $ klist
Ticket cache: FILE:/var/adm/krb5/tmp/tkt/krb5cc_3258_xQK9wc
Default principal: koczan/mail@CS.WISC.EDU
...

Connecting to an 8.2 server works just fine...

[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 5432 sushi
Welcome to psql 8.3.1 (server 8.2.6), the PostgreSQL interactive terminal.

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.2,
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)

sushi=> select version();
                                  version

----------------------------------------------------------------------------

 PostgreSQL 8.2.6 on i686-pc-linux-gnu, compiled by GCC gcc.bin (GCC) 3.4.4
(1 row)

sushi=> select current_user;
 current_user
--------------
 koczan
(1 row)

However, connecting to an 8.3 server...

[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 49173 sushi
psql: FATAL:  no pg_hba.conf entry for host "128.105.162.36", user "koczan",
database "sushi", SSL off

And this shows up in the syslog...
Apr 23 12:02:41 sensei postgres[23100]: [3-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49188
Apr 23 12:02:41 sensei postgres[23100]: [4-1] LOG:  unexpected Kerberos user
name received from client (received "koczan", expected "koczan/mail")
Apr 23 12:02:41 sensei postgres[23100]: [5-1] FATAL:  Kerberos 5
authentication failed for user "koczan"
Apr 23 12:02:41 sensei postgres[23101]: [3-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49189
Apr 23 12:02:41 sensei postgres[23101]: [4-1] FATAL:  no pg_hba.conf entry
for host "128.105.162.36", user "koczan", database "sushi", SSL off

The appropriate line in pg_hba.conf shows
hostssl all         all         128.105.0.0/16     krb5

I'm connecting via native krb5, but this problem (or a variant of it) occurs
when using GSSAPI authentication...

[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 49173 sushi
psql: FATAL:  no pg_hba.conf entry for host "128.105.162.36", user "koczan",
database "sushi", SSL off

Apr 23 12:08:02 sensei postgres[23257]: [4-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49409
Apr 23 12:08:02 sensei postgres[23257]: [5-1] FATAL:  GSSAPI authentication
failed for user "koczan"
Apr 23 12:08:02 sensei postgres[23258]: [4-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49410
Apr 23 12:08:02 sensei postgres[23258]: [5-1] FATAL:  no pg_hba.conf entry
for host "128.105.162.36", user "koczan", database "sushi", SSL off

Different things happen when I turn SSL off, but it's still failing to
connect...

Native krb5 / SSL off:

[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 49173 sushi
psql: FATAL:  Kerberos 5 authentication failed for user "koczan"

Apr 23 12:12:10 sensei postgres[23327]: [6-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49525
Apr 23 12:12:11 sensei postgres[23327]: [7-1] LOG:  unexpected Kerberos user
name received from client (received "koczan", expected "koczan/mail")
Apr 23 12:12:11 sensei postgres[23327]: [8-1] FATAL:  Kerberos 5
authentication failed for user "koczan"
Apr 23 12:12:11 sensei postgres[23328]: [6-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49526
Apr 23 12:12:11 sensei postgres[23328]: [7-1] LOG:  unexpected Kerberos user
name received from client (received "koczan", expected "koczan/mail")
Apr 23 12:12:11 sensei postgres[23328]: [8-1] FATAL:  Kerberos 5
authentication failed for user "koczan"

GSSAPI / SSL off:

[koczan@ator] ~ $ /s/postgresql-8.3/bin/psql -h sensei -p 49173 sushi
psql: duplicate GSS authentication request

Apr 23 12:10:21 sensei postgres[23287]: [5-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49462
Apr 23 12:10:22 sensei postgres[23287]: [6-1] FATAL:  GSSAPI authentication
failed for user "koczan"
Apr 23 12:10:22 sensei postgres[23288]: [5-1] LOG:  connection received:
host=ator.cs.wisc.edu port=49463
Apr 23 12:10:22 sensei postgres[23288]: [6-1] FATAL:  GSSAPI authentication
failed for user "koczan"

Re: BUG #4126: KRB5/GSSAPI authenication fails for multipart kerberos principals

От
"Peter Koczan"
Дата:
> From: "Peter Koczan" <pjkoczan@gmail.com>
> To: pgsql-bugs@postgresql.org
> Date: Wed, 23 Apr 2008 17:17:01 GMT
> Subject: BUG #4126: KRB5/GSSAPI authenication fails for multipart kerberos principals
>
>  When trying to connect to an 8.3 server using a multipart Kerberos principal
>  (e.g. ator/wsbackup.cs.wisc.edu@CS.WISC.EDU or koczan/mail@CS.WISC.EDU
>  instead of wsbackup@CS.WISC.EDU or koczan@CS.WISC.EDU), the connection
>  fails, claiming a name mismatch. This is a change from 8.2 and I found
>  nothing in the changelog or documentation to suggest this change or offer a
>  workaround.

I poked around the code a bit, and found something interesting in
src/backend/libpq/auth.c. Apparently, in 8.2, the kerberos username
gets transformed from a full authentication name to a local
authentication name before being compared to the received name (using
pg_an_to_ln), but in 8.3, this transformation doesn't happen, causing
a name mismatch and therefore an authentication failure. Putting this
back in "worked", in that now the names match, and
"wsbackup/ator.cs.wisc.edu" connects to the database as "wsbackup."

Reading the comment for pg_an_to_ln, I understand that it might be
best in the long run for this behavior to change (some sort of
principal mapping or saying that multipart principals should have
different database roles). However, right now it is a bug because it's
an authentication failure with no discernible workaround. I tried
creating a "wsbackup/ator.cs.wisc.edu" role in my database, but it
still failed because it wasn't even getting to the point of checking
roles in the database.

In any case, here's a patch to src/backend/libpq/auth.c that puts back
the old behavior for krb5 and gss authentication. I didn't check or
modify other auth methods because I don't use them.

Peter

Index: src/backend/libpq/auth.c
===================================================================
RCS file: /s/postgresql-8.3.1/src/CVSROOT/postgresql-8.3.1/src/backend/libpq/auth.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 auth.c
*** src/backend/libpq/auth.c    31 Mar 2008 20:26:15 -0000      1.1.1.1
--- src/backend/libpq/auth.c    24 Apr 2008 18:00:59 -0000
***************
*** 104,109 ****
--- 104,132 ----
  #endif

  /*
+  * pg_an_to_ln -- return the local name corresponding to an authentication
+  *                              name
+  *
+  * XXX Assumes that the first aname component is the user name.  This is NOT
+  *       necessarily so, since an aname can actually be something out of your
+  *       worst X.400 nightmare, like
+  *              ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
+  *       Note that the MIT an_to_ln code does the same thing if you don't
+  *       provide an aname mapping database...it may be a better idea to use
+  *       krb5_an_to_ln, except that it punts if multiple components are found,
+  *       and we can't afford to punt.
+  */
+ static char *
+ pg_an_to_ln(char *aname)
+ {
+       char       *p;
+
+       if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
+               *p = '\0';
+       return aname;
+ }
+
+ /*
   * Various krb5 state which is not connection specfic, and a flag to
   * indicate whether we have initialised it yet.
   */
***************
*** 275,280 ****
--- 298,304 ----
                return STATUS_ERROR;
        }

+       kusername = pg_an_to_ln(kusername);
        if (pg_krb_caseins_users)
                ret = pg_strncasecmp(port->user_name, kusername,
SM_DATABASE_USER);
        else
***************
*** 588,593 ****
--- 612,618 ----
                return STATUS_ERROR;
        }

+       gbuf.value = pg_an_to_ln(gbuf.value);
        if (pg_krb_caseins_users)
                ret = pg_strcasecmp(port->user_name, gbuf.value);
        else