From 32c469d7b13e430105ee018b493587c4f6c0150a Mon Sep 17 00:00:00 2001 From: Magnus Hagander Date: Wed, 7 Jan 2009 12:38:11 +0000 Subject: [PATCH] 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. --- doc/src/sgml/client-auth.sgml | 32 ++++++++++++++++++++++++- src/backend/libpq/auth.c | 55 ++++++++++++++++++++++++++++++------------- src/backend/libpq/hba.c | 19 ++++++++++++++- src/include/libpq/hba.h | 4 +++- 4 files changed, 90 insertions(+), 20 deletions(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 8e3b7c1791..1d0ce45ce7 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,4 +1,4 @@ - + Client Authentication @@ -784,6 +784,26 @@ omicron bryanh guest1 + + + krb_realm + + + Overrides the parameter, setting which realm + to verify the authenticated user principal against. + + + + + + krb_server_hostname + + + Overrides the parameter, setting which + hostname will be used for the server principal when using Kerberos. + + + @@ -825,6 +845,16 @@ omicron bryanh guest1 + + + krb_realm + + + Overrides the parameter, setting which realm + to verify the authenticated user principal against. + + + diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 9a93e9ac02..437061c21a 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * 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) #ifdef KRB5 static int -pg_krb5_init(void) +pg_krb5_init(Port *port) { krb5_error_code retval; char *khostname; @@ -645,7 +645,10 @@ pg_krb5_init(void) * If no hostname was specified, pg_krb_server_hostname is already 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') khostname = NULL; @@ -691,11 +694,12 @@ pg_krb5_recvauth(Port *port) krb5_ticket *ticket; char *kusername; char *cp; + char *realmmatch; if (get_role_line(port->user_name) == NULL) return STATUS_ERROR; - ret = pg_krb5_init(); + ret = pg_krb5_init(port); if (ret != STATUS_OK) return ret; @@ -736,25 +740,30 @@ pg_krb5_recvauth(Port *port) return STATUS_ERROR; } + if (port->hba->krb_realm) + realmmatch = port->hba->krb_realm; + else + realmmatch = pg_krb_realm; + cp = strchr(kusername, '@'); if (cp) { *cp = '\0'; cp++; - if (pg_krb_realm != NULL && strlen(pg_krb_realm)) + if (realmmatch != NULL && strlen(realmmatch)) { /* Match realm against configured */ if (pg_krb_caseins_users) - ret = pg_strcasecmp(pg_krb_realm, cp); + ret = pg_strcasecmp(realmmatch, cp); else - ret = strcmp(pg_krb_realm, cp); + ret = strcmp(realmmatch, cp); if (ret) { elog(DEBUG2, "krb5 realm (%s) and configured realm (%s) don't match", - cp, pg_krb_realm); + cp, realmmatch); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); @@ -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, "krb5 did not return realm but realm matching was requested"); @@ -859,6 +868,7 @@ pg_GSS_recvauth(Port *port) int ret; StringInfoData buf; gss_buffer_desc gbuf; + char *realmmatch; /* * GSS auth is not supported for protocol versions before 3, because it @@ -1018,6 +1028,11 @@ pg_GSS_recvauth(Port *port) gettext_noop("retrieving GSS user name failed"), 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 */ @@ -1028,28 +1043,28 @@ pg_GSS_recvauth(Port *port) *cp = '\0'; cp++; - if (pg_krb_realm != NULL && strlen(pg_krb_realm)) + if (realmmatch != NULL && strlen(realmmatch)) { /* * Match the realm part of the name first */ if (pg_krb_caseins_users) - ret = pg_strcasecmp(pg_krb_realm, cp); + ret = pg_strcasecmp(realmmatch, cp); else - ret = strcmp(pg_krb_realm, cp); + ret = strcmp(realmmatch, cp); if (ret) { /* GSS realm does not match */ elog(DEBUG2, "GSSAPI realm (%s) and configured realm (%s) don't match", - cp, pg_krb_realm); + cp, realmmatch); gss_release_buffer(&lmin_s, &gbuf); return STATUS_ERROR; } } } - else if (pg_krb_realm && strlen(pg_krb_realm)) + else if (realmmatch && strlen(realmmatch)) { elog(DEBUG2, "GSSAPI did not return realm but realm matching was requested"); @@ -1113,6 +1128,7 @@ pg_SSPI_recvauth(Port *port) SID_NAME_USE accountnameuse; HMODULE secur32; QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken; + char *realmmatch; /* * SSPI auth is not supported for protocol versions before 3, because it @@ -1325,13 +1341,18 @@ pg_SSPI_recvauth(Port *port) * Compare realm/domain if requested. In SSPI, always compare case * 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, "SSPI domain (%s) and configured domain (%s) don't match", - domainname, pg_krb_realm); + domainname, realmmatch); return STATUS_ERROR; } diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 45edaa9bb8..e7068b10b2 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * 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) REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap"); 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 { ereport(LOG, @@ -1242,6 +1255,10 @@ free_hba_record(HbaLine *record) pfree(record->ldapprefix); if (record->ldapsuffix) pfree(record->ldapsuffix); + if (record->krb_server_hostname) + pfree(record->krb_server_hostname); + if (record->krb_realm) + pfree(record->krb_realm); } /* diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h index 87d04640e4..53ecde2c16 100644 --- a/src/include/libpq/hba.h +++ b/src/include/libpq/hba.h @@ -4,7 +4,7 @@ * 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 char *ldapprefix; char *ldapsuffix; bool clientcert; + char *krb_server_hostname; + char *krb_realm; } HbaLine; typedef struct Port hbaPort; -- 2.11.0