Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4b606ee

Browse files
committed
Add parameter krb_realm used by GSSAPI, SSPI and Kerberos
to validate the realm of the connecting user. By default it's empty meaning no verification, which is the way Kerberos authentication has traditionally worked in PostgreSQL.
1 parent a7cd5a4 commit 4b606ee

File tree

6 files changed

+120
-39
lines changed

6 files changed

+120
-39
lines changed

doc/src/sgml/client-auth.sgml

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.101 2007/09/14 03:53:54 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.102 2007/11/09 17:31:07 mha Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -773,10 +773,10 @@ local db1,db2,@demodbs all md5
773773
<para>
774774
Client principals must have their <productname>PostgreSQL</> database user
775775
name as their first component, for example
776-
<literal>pgusername/otherstuff@realm</>. At present the realm of
777-
the client is not checked by <productname>PostgreSQL</>; so if you
778-
have cross-realm authentication enabled, then any principal in any
779-
realm that can communicate with yours will be accepted.
776+
<literal>pgusername@realm</>. By default, the realm of the client is
777+
not checked by <productname>PostgreSQL</>. If you have cross-realm
778+
authentication enabled and need to verify the realm, use the
779+
<xref linkend="guc-krb-realm"> parameter.
780780
</para>
781781

782782
<para>

doc/src/sgml/config.sgml

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.153 2007/11/05 17:35:38 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.154 2007/11/09 17:31:07 mha Exp $ -->
22

33
<chapter Id="runtime-config">
44
<title>Server Configuration</title>
@@ -601,6 +601,21 @@ SET ENABLE_SEQSCAN TO OFF;
601601
</listitem>
602602
</varlistentry>
603603

604+
<varlistentry id="guc-krb-realm" xreflabel="krb_realm">
605+
<term><varname>krb_realm</varname> (<type>string</type>)</term>
606+
<indexterm>
607+
<primary><varname>krb_realm</> configuration parameter</primary>
608+
</indexterm>
609+
<listitem>
610+
<para>
611+
Sets the realm to match Kerberos, GSSAPI and SSPI usernames against.
612+
See <xref linkend="kerberos-auth">, <xref linkend="gssapi-auth"> or
613+
<xref linkend="sspi-auth"> for details. This parameter can only be
614+
set at server start.
615+
</para>
616+
</listitem>
617+
</varlistentry>
618+
604619
<varlistentry id="guc-krb-server-keyfile" xreflabel="krb_server_keyfile">
605620
<term><varname>krb_server_keyfile</varname> (<type>string</type>)</term>
606621
<indexterm>

src/backend/libpq/auth.c

+85-31
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.156 2007/09/14 15:58:02 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.157 2007/11/09 17:31:07 mha Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -42,6 +42,7 @@ char *pg_krb_server_keyfile;
4242
char *pg_krb_srvnam;
4343
bool pg_krb_caseins_users;
4444
char *pg_krb_server_hostname = NULL;
45+
char *pg_krb_realm = NULL;
4546

4647
#ifdef USE_PAM
4748
#ifdef HAVE_PAM_PAM_APPL_H
@@ -102,30 +103,6 @@ static int CheckLDAPAuth(Port *port);
102103
#include <com_err.h>
103104
#endif
104105

105-
/*
106-
* pg_an_to_ln -- return the local name corresponding to an authentication
107-
* name
108-
*
109-
* XXX Assumes that the first aname component is the user name. This is NOT
110-
* necessarily so, since an aname can actually be something out of your
111-
* worst X.400 nightmare, like
112-
* ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU
113-
* Note that the MIT an_to_ln code does the same thing if you don't
114-
* provide an aname mapping database...it may be a better idea to use
115-
* krb5_an_to_ln, except that it punts if multiple components are found,
116-
* and we can't afford to punt.
117-
*/
118-
static char *
119-
pg_an_to_ln(char *aname)
120-
{
121-
char *p;
122-
123-
if ((p = strchr(aname, '/')) || (p = strchr(aname, '@')))
124-
*p = '\0';
125-
return aname;
126-
}
127-
128-
129106
/*
130107
* Various krb5 state which is not connection specfic, and a flag to
131108
* indicate whether we have initialised it yet.
@@ -216,6 +193,7 @@ pg_krb5_recvauth(Port *port)
216193
krb5_auth_context auth_context = NULL;
217194
krb5_ticket *ticket;
218195
char *kusername;
196+
char *cp;
219197

220198
if (get_role_line(port->user_name) == NULL)
221199
return STATUS_ERROR;
@@ -240,8 +218,6 @@ pg_krb5_recvauth(Port *port)
240218
* The "client" structure comes out of the ticket and is therefore
241219
* authenticated. Use it to check the username obtained from the
242220
* postmaster startup packet.
243-
*
244-
* I have no idea why this is considered necessary.
245221
*/
246222
#if defined(HAVE_KRB5_TICKET_ENC_PART2)
247223
retval = krb5_unparse_name(pg_krb5_context,
@@ -263,7 +239,42 @@ pg_krb5_recvauth(Port *port)
263239
return STATUS_ERROR;
264240
}
265241

266-
kusername = pg_an_to_ln(kusername);
242+
cp = strchr(kusername, '@');
243+
if (cp)
244+
{
245+
*cp = '\0';
246+
cp++;
247+
248+
if (pg_krb_realm != NULL && strlen(pg_krb_realm))
249+
{
250+
/* Match realm against configured */
251+
if (pg_krb_caseins_users)
252+
ret = pg_strcasecmp(pg_krb_realm, cp);
253+
else
254+
ret = strcmp(pg_krb_realm, cp);
255+
256+
if (ret)
257+
{
258+
elog(DEBUG2,
259+
"krb5 realm (%s) and configured realm (%s) don't match",
260+
cp, pg_krb_realm);
261+
262+
krb5_free_ticket(pg_krb5_context, ticket);
263+
krb5_auth_con_free(pg_krb5_context, auth_context);
264+
return STATUS_ERROR;
265+
}
266+
}
267+
}
268+
else if (pg_krb_realm && strlen(pg_krb_realm))
269+
{
270+
elog(DEBUG2,
271+
"krb5 did not return realm but realm matching was requested");
272+
273+
krb5_free_ticket(pg_krb5_context, ticket);
274+
krb5_auth_con_free(pg_krb5_context, auth_context);
275+
return STATUS_ERROR;
276+
}
277+
267278
if (pg_krb_caseins_users)
268279
ret = pg_strncasecmp(port->user_name, kusername, SM_DATABASE_USER);
269280
else
@@ -509,14 +520,42 @@ pg_GSS_recvauth(Port *port)
509520
maj_stat, min_stat);
510521

511522
/*
512-
* Compare the part of the username that comes before the @
513-
* sign only (ignore realm). The GSSAPI libraries won't have
514-
* authenticated the user if he's from an invalid realm.
523+
* Split the username at the realm separator
515524
*/
516525
if (strchr(gbuf.value, '@'))
517526
{
518527
char *cp = strchr(gbuf.value, '@');
519528
*cp = '\0';
529+
cp++;
530+
531+
if (pg_krb_realm != NULL && strlen(pg_krb_realm))
532+
{
533+
/*
534+
* Match the realm part of the name first
535+
*/
536+
if (pg_krb_caseins_users)
537+
ret = pg_strcasecmp(pg_krb_realm, cp);
538+
else
539+
ret = strcmp(pg_krb_realm, cp);
540+
541+
if (ret)
542+
{
543+
/* GSS realm does not match */
544+
elog(DEBUG2,
545+
"GSSAPI realm (%s) and configured realm (%s) don't match",
546+
cp, pg_krb_realm);
547+
gss_release_buffer(&lmin_s, &gbuf);
548+
return STATUS_ERROR;
549+
}
550+
}
551+
}
552+
else if (pg_krb_realm && strlen(pg_krb_realm))
553+
{
554+
elog(DEBUG2,
555+
"GSSAPI did not return realm but realm matching was requested");
556+
557+
gss_release_buffer(&lmin_s, &gbuf);
558+
return STATUS_ERROR;
520559
}
521560

522561
if (pg_krb_caseins_users)
@@ -792,6 +831,21 @@ pg_SSPI_recvauth(Port *port)
792831

793832
free(tokenuser);
794833

834+
/*
835+
* Compare realm/domain if requested. In SSPI, always compare case insensitive.
836+
*/
837+
if (pg_krb_realm && strlen(pg_krb_realm))
838+
{
839+
if (pg_strcasecmp(pg_krb_realm, domainname))
840+
{
841+
elog(DEBUG2,
842+
"SSPI domain (%s) and configured domain (%s) don't match",
843+
domainname, pg_krb_realm);
844+
845+
return STATUS_ERROR;
846+
}
847+
}
848+
795849
/*
796850
* We have the username (without domain/realm) in accountname, compare
797851
* to the supplied value. In SSPI, always compare case insensitive.

src/backend/utils/misc/guc.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Written by Peter Eisentraut <peter_e@gmx.net>.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.423 2007/09/26 22:36:30 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.424 2007/11/09 17:31:07 mha Exp $
1414
*
1515
*--------------------------------------------------------------------
1616
*/
@@ -2043,6 +2043,16 @@ static struct config_string ConfigureNamesString[] =
20432043
"$libdir", NULL, NULL
20442044
},
20452045

2046+
{
2047+
{"krb_realm", PGC_POSTMASTER, CONN_AUTH_SECURITY,
2048+
gettext_noop("Sets realm to match Kerberos and GSSAPI users against."),
2049+
NULL,
2050+
GUC_SUPERUSER_ONLY
2051+
},
2052+
&pg_krb_realm,
2053+
NULL, NULL, NULL
2054+
},
2055+
20462056
{
20472057
{"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY,
20482058
gettext_noop("Sets the location of the Kerberos server key file."),

src/backend/utils/misc/postgresql.conf.sample

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
#krb_server_hostname = '' # empty string matches any keytab entry
8686
# (change requires restart, kerberos only)
8787
#krb_caseins_users = off # (change requires restart)
88+
#krb_realm = '' # (change requires restart)
8889

8990
# - TCP Keepalives -
9091
# see 'man 7 tcp' for details

src/include/libpq/auth.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/libpq/auth.h,v 1.33 2007/01/05 22:19:55 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/libpq/auth.h,v 1.34 2007/11/09 17:31:07 mha Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -20,6 +20,7 @@ extern char *pg_krb_server_keyfile;
2020
extern char *pg_krb_srvnam;
2121
extern bool pg_krb_caseins_users;
2222
extern char *pg_krb_server_hostname;
23+
extern char *pg_krb_realm;
2324

2425
extern void ClientAuthentication(Port *port);
2526

0 commit comments

Comments
 (0)