Commit 32c469d7 authored by Magnus Hagander's avatar Magnus Hagander

Allow krb_realm (krb5, gssapi and sspi) and krb_server_hostname (krb5 only)

authentication options to be set in pg_hba.conf on a per-line basis, to
override the defaults set in postgresql.conf.
parent af260898
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.115 2009/01/02 11:51:53 mha Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.116 2009/01/07 12:38:10 mha Exp $ -->
<chapter id="client-authentication"> <chapter id="client-authentication">
<title>Client Authentication</title> <title>Client Authentication</title>
...@@ -784,6 +784,26 @@ omicron bryanh guest1 ...@@ -784,6 +784,26 @@ omicron bryanh guest1
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>krb_realm</term>
<listitem>
<para>
Overrides the <xref linkend="guc-krb-realm"> parameter, setting which realm
to verify the authenticated user principal against.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>krb_server_hostname</term>
<listitem>
<para>
Overrides the <xref linkend="guc-krb-server-hostname"> parameter, setting which
hostname will be used for the server principal when using Kerberos.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</sect2> </sect2>
...@@ -825,6 +845,16 @@ omicron bryanh guest1 ...@@ -825,6 +845,16 @@ omicron bryanh guest1
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>krb_realm</term>
<listitem>
<para>
Overrides the <xref linkend="guc-krb-realm"> parameter, setting which realm
to verify the authenticated user principal against.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</sect2> </sect2>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.175 2009/01/01 17:23:42 momjian Exp $ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.176 2009/01/07 12:38:11 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -611,7 +611,7 @@ recv_and_check_password_packet(Port *port) ...@@ -611,7 +611,7 @@ recv_and_check_password_packet(Port *port)
#ifdef KRB5 #ifdef KRB5
static int static int
pg_krb5_init(void) pg_krb5_init(Port *port)
{ {
krb5_error_code retval; krb5_error_code retval;
char *khostname; char *khostname;
...@@ -645,7 +645,10 @@ pg_krb5_init(void) ...@@ -645,7 +645,10 @@ pg_krb5_init(void)
* If no hostname was specified, pg_krb_server_hostname is already NULL. * If no hostname was specified, pg_krb_server_hostname is already NULL.
* If it's set to blank, force it to NULL. * If it's set to blank, force it to NULL.
*/ */
khostname = pg_krb_server_hostname; if (port->hba->krb_server_hostname)
khostname = port->hba->krb_server_hostname;
else
khostname = pg_krb_server_hostname;
if (khostname && khostname[0] == '\0') if (khostname && khostname[0] == '\0')
khostname = NULL; khostname = NULL;
...@@ -691,11 +694,12 @@ pg_krb5_recvauth(Port *port) ...@@ -691,11 +694,12 @@ pg_krb5_recvauth(Port *port)
krb5_ticket *ticket; krb5_ticket *ticket;
char *kusername; char *kusername;
char *cp; char *cp;
char *realmmatch;
if (get_role_line(port->user_name) == NULL) if (get_role_line(port->user_name) == NULL)
return STATUS_ERROR; return STATUS_ERROR;
ret = pg_krb5_init(); ret = pg_krb5_init(port);
if (ret != STATUS_OK) if (ret != STATUS_OK)
return ret; return ret;
...@@ -736,25 +740,30 @@ pg_krb5_recvauth(Port *port) ...@@ -736,25 +740,30 @@ pg_krb5_recvauth(Port *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
if (port->hba->krb_realm)
realmmatch = port->hba->krb_realm;
else
realmmatch = pg_krb_realm;
cp = strchr(kusername, '@'); cp = strchr(kusername, '@');
if (cp) if (cp)
{ {
*cp = '\0'; *cp = '\0';
cp++; cp++;
if (pg_krb_realm != NULL && strlen(pg_krb_realm)) if (realmmatch != NULL && strlen(realmmatch))
{ {
/* Match realm against configured */ /* Match realm against configured */
if (pg_krb_caseins_users) if (pg_krb_caseins_users)
ret = pg_strcasecmp(pg_krb_realm, cp); ret = pg_strcasecmp(realmmatch, cp);
else else
ret = strcmp(pg_krb_realm, cp); ret = strcmp(realmmatch, cp);
if (ret) if (ret)
{ {
elog(DEBUG2, elog(DEBUG2,
"krb5 realm (%s) and configured realm (%s) don't match", "krb5 realm (%s) and configured realm (%s) don't match",
cp, pg_krb_realm); cp, realmmatch);
krb5_free_ticket(pg_krb5_context, ticket); krb5_free_ticket(pg_krb5_context, ticket);
krb5_auth_con_free(pg_krb5_context, auth_context); krb5_auth_con_free(pg_krb5_context, auth_context);
...@@ -762,7 +771,7 @@ pg_krb5_recvauth(Port *port) ...@@ -762,7 +771,7 @@ pg_krb5_recvauth(Port *port)
} }
} }
} }
else if (pg_krb_realm && strlen(pg_krb_realm)) else if (realmmatch && strlen(realmmatch))
{ {
elog(DEBUG2, elog(DEBUG2,
"krb5 did not return realm but realm matching was requested"); "krb5 did not return realm but realm matching was requested");
...@@ -859,6 +868,7 @@ pg_GSS_recvauth(Port *port) ...@@ -859,6 +868,7 @@ pg_GSS_recvauth(Port *port)
int ret; int ret;
StringInfoData buf; StringInfoData buf;
gss_buffer_desc gbuf; gss_buffer_desc gbuf;
char *realmmatch;
/* /*
* GSS auth is not supported for protocol versions before 3, because it * GSS auth is not supported for protocol versions before 3, because it
...@@ -1018,6 +1028,11 @@ pg_GSS_recvauth(Port *port) ...@@ -1018,6 +1028,11 @@ pg_GSS_recvauth(Port *port)
gettext_noop("retrieving GSS user name failed"), gettext_noop("retrieving GSS user name failed"),
maj_stat, min_stat); maj_stat, min_stat);
if (port->hba->krb_realm)
realmmatch = port->hba->krb_realm;
else
realmmatch = pg_krb_realm;
/* /*
* Split the username at the realm separator * Split the username at the realm separator
*/ */
...@@ -1028,28 +1043,28 @@ pg_GSS_recvauth(Port *port) ...@@ -1028,28 +1043,28 @@ pg_GSS_recvauth(Port *port)
*cp = '\0'; *cp = '\0';
cp++; cp++;
if (pg_krb_realm != NULL && strlen(pg_krb_realm)) if (realmmatch != NULL && strlen(realmmatch))
{ {
/* /*
* Match the realm part of the name first * Match the realm part of the name first
*/ */
if (pg_krb_caseins_users) if (pg_krb_caseins_users)
ret = pg_strcasecmp(pg_krb_realm, cp); ret = pg_strcasecmp(realmmatch, cp);
else else
ret = strcmp(pg_krb_realm, cp); ret = strcmp(realmmatch, cp);
if (ret) if (ret)
{ {
/* GSS realm does not match */ /* GSS realm does not match */
elog(DEBUG2, elog(DEBUG2,
"GSSAPI realm (%s) and configured realm (%s) don't match", "GSSAPI realm (%s) and configured realm (%s) don't match",
cp, pg_krb_realm); cp, realmmatch);
gss_release_buffer(&lmin_s, &gbuf); gss_release_buffer(&lmin_s, &gbuf);
return STATUS_ERROR; return STATUS_ERROR;
} }
} }
} }
else if (pg_krb_realm && strlen(pg_krb_realm)) else if (realmmatch && strlen(realmmatch))
{ {
elog(DEBUG2, elog(DEBUG2,
"GSSAPI did not return realm but realm matching was requested"); "GSSAPI did not return realm but realm matching was requested");
...@@ -1113,6 +1128,7 @@ pg_SSPI_recvauth(Port *port) ...@@ -1113,6 +1128,7 @@ pg_SSPI_recvauth(Port *port)
SID_NAME_USE accountnameuse; SID_NAME_USE accountnameuse;
HMODULE secur32; HMODULE secur32;
QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken; QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
char *realmmatch;
/* /*
* SSPI auth is not supported for protocol versions before 3, because it * SSPI auth is not supported for protocol versions before 3, because it
...@@ -1325,13 +1341,18 @@ pg_SSPI_recvauth(Port *port) ...@@ -1325,13 +1341,18 @@ pg_SSPI_recvauth(Port *port)
* Compare realm/domain if requested. In SSPI, always compare case * Compare realm/domain if requested. In SSPI, always compare case
* insensitive. * insensitive.
*/ */
if (pg_krb_realm && strlen(pg_krb_realm)) if (port->hba->krb_realm)
realmmatch = port->hba->krb_realm;
else
realmmatch = pg_krb_realm;
if (realmmatch && strlen(realmmatch))
{ {
if (pg_strcasecmp(pg_krb_realm, domainname)) if (pg_strcasecmp(realmmatch, domainname))
{ {
elog(DEBUG2, elog(DEBUG2,
"SSPI domain (%s) and configured domain (%s) don't match", "SSPI domain (%s) and configured domain (%s) don't match",
domainname, pg_krb_realm); domainname, realmmatch);
return STATUS_ERROR; return STATUS_ERROR;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.178 2009/01/02 11:34:03 mha Exp $ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.179 2009/01/07 12:38:11 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1040,6 +1040,19 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline) ...@@ -1040,6 +1040,19 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap"); REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
parsedline->ldapsuffix = pstrdup(c); parsedline->ldapsuffix = pstrdup(c);
} }
else if (strcmp(token, "krb_server_hostname") == 0)
{
REQUIRE_AUTH_OPTION(uaKrb5, "krb_server_hostname", "krb5");
parsedline->krb_server_hostname = pstrdup(c);
}
else if (strcmp(token, "krb_realm") == 0)
{
if (parsedline->auth_method != uaKrb5 &&
parsedline->auth_method != uaGSS &&
parsedline->auth_method != uaSSPI)
INVALID_AUTH_OPTION("krb_realm", "krb5, gssapi and sspi");
parsedline->krb_realm = pstrdup(c);
}
else else
{ {
ereport(LOG, ereport(LOG,
...@@ -1242,6 +1255,10 @@ free_hba_record(HbaLine *record) ...@@ -1242,6 +1255,10 @@ free_hba_record(HbaLine *record)
pfree(record->ldapprefix); pfree(record->ldapprefix);
if (record->ldapsuffix) if (record->ldapsuffix)
pfree(record->ldapsuffix); pfree(record->ldapsuffix);
if (record->krb_server_hostname)
pfree(record->krb_server_hostname);
if (record->krb_realm)
pfree(record->krb_realm);
} }
/* /*
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Interface to hba.c * Interface to hba.c
* *
* *
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.53 2008/11/20 11:48:26 mha Exp $ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.54 2009/01/07 12:38:11 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -56,6 +56,8 @@ typedef struct ...@@ -56,6 +56,8 @@ typedef struct
char *ldapprefix; char *ldapprefix;
char *ldapsuffix; char *ldapsuffix;
bool clientcert; bool clientcert;
char *krb_server_hostname;
char *krb_realm;
} HbaLine; } HbaLine;
typedef struct Port hbaPort; typedef struct Port hbaPort;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment