I've for some reason been sitting on this patch for a while, it was supposed to be a part of the pg_hba changes from a few months ago.
Anyway. Here's a patch that makes it possible to set krb_realm and krb_server_hostname on a per-hba-row basis, instead of just for the whole server. Comments? //Magnus
*** a/doc/src/sgml/client-auth.sgml --- b/doc/src/sgml/client-auth.sgml *************** *** 784,789 **** omicron bryanh guest1 --- 784,809 ---- </para> </listitem> </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> </para> </sect2> *************** *** 825,830 **** omicron bryanh guest1 --- 845,860 ---- </para> </listitem> </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> </para> </sect2> *** a/src/backend/libpq/auth.c --- b/src/backend/libpq/auth.c *************** *** 611,617 **** recv_and_check_password_packet(Port *port) #ifdef KRB5 static int ! pg_krb5_init(void) { krb5_error_code retval; char *khostname; --- 611,617 ---- #ifdef KRB5 static int ! pg_krb5_init(Port *port) { krb5_error_code retval; char *khostname; *************** *** 645,651 **** 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 (khostname && khostname[0] == '\0') khostname = NULL; --- 645,654 ---- * If no hostname was specified, pg_krb_server_hostname is already NULL. * If it's set to blank, force it to NULL. */ ! 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,701 **** pg_krb5_recvauth(Port *port) krb5_ticket *ticket; char *kusername; char *cp; if (get_role_line(port->user_name) == NULL) return STATUS_ERROR; ! ret = pg_krb5_init(); if (ret != STATUS_OK) return ret; --- 694,705 ---- krb5_ticket *ticket; char *kusername; char *cp; + char *realmmatch; if (get_role_line(port->user_name) == NULL) return STATUS_ERROR; ! ret = pg_krb5_init(port); if (ret != STATUS_OK) return ret; *************** *** 736,760 **** pg_krb5_recvauth(Port *port) return STATUS_ERROR; } cp = strchr(kusername, '@'); if (cp) { *cp = '\0'; cp++; ! if (pg_krb_realm != NULL && strlen(pg_krb_realm)) { /* Match realm against configured */ if (pg_krb_caseins_users) ! ret = pg_strcasecmp(pg_krb_realm, cp); else ! ret = strcmp(pg_krb_realm, cp); if (ret) { elog(DEBUG2, "krb5 realm (%s) and configured realm (%s) don't match", ! cp, pg_krb_realm); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); --- 740,769 ---- 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 (realmmatch != NULL && strlen(realmmatch)) { /* Match realm against configured */ if (pg_krb_caseins_users) ! ret = pg_strcasecmp(realmmatch, cp); else ! ret = strcmp(realmmatch, cp); if (ret) { elog(DEBUG2, "krb5 realm (%s) and configured realm (%s) don't match", ! cp, realmmatch); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); *************** *** 762,768 **** pg_krb5_recvauth(Port *port) } } } ! else if (pg_krb_realm && strlen(pg_krb_realm)) { elog(DEBUG2, "krb5 did not return realm but realm matching was requested"); --- 771,777 ---- } } } ! else if (realmmatch && strlen(realmmatch)) { elog(DEBUG2, "krb5 did not return realm but realm matching was requested"); *************** *** 859,864 **** pg_GSS_recvauth(Port *port) --- 868,874 ---- int ret; StringInfoData buf; gss_buffer_desc gbuf; + char *realmmatch; /* * GSS auth is not supported for protocol versions before 3, because it *************** *** 1018,1023 **** pg_GSS_recvauth(Port *port) --- 1028,1038 ---- 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,1055 **** pg_GSS_recvauth(Port *port) *cp = '\0'; cp++; ! if (pg_krb_realm != NULL && strlen(pg_krb_realm)) { /* * Match the realm part of the name first */ if (pg_krb_caseins_users) ! ret = pg_strcasecmp(pg_krb_realm, cp); else ! ret = strcmp(pg_krb_realm, cp); if (ret) { /* GSS realm does not match */ elog(DEBUG2, "GSSAPI realm (%s) and configured realm (%s) don't match", ! cp, pg_krb_realm); gss_release_buffer(&lmin_s, &gbuf); return STATUS_ERROR; } } } ! else if (pg_krb_realm && strlen(pg_krb_realm)) { elog(DEBUG2, "GSSAPI did not return realm but realm matching was requested"); --- 1043,1070 ---- *cp = '\0'; cp++; ! if (realmmatch != NULL && strlen(realmmatch)) { /* * Match the realm part of the name first */ if (pg_krb_caseins_users) ! ret = pg_strcasecmp(realmmatch, cp); else ! ret = strcmp(realmmatch, cp); if (ret) { /* GSS realm does not match */ elog(DEBUG2, "GSSAPI realm (%s) and configured realm (%s) don't match", ! cp, realmmatch); gss_release_buffer(&lmin_s, &gbuf); return STATUS_ERROR; } } } ! else if (realmmatch && strlen(realmmatch)) { elog(DEBUG2, "GSSAPI did not return realm but realm matching was requested"); *************** *** 1113,1118 **** pg_SSPI_recvauth(Port *port) --- 1128,1134 ---- 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,1337 **** 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 (pg_strcasecmp(pg_krb_realm, domainname)) { elog(DEBUG2, "SSPI domain (%s) and configured domain (%s) don't match", ! domainname, pg_krb_realm); return STATUS_ERROR; } --- 1341,1358 ---- * Compare realm/domain if requested. In SSPI, always compare case * insensitive. */ ! if (port->hba->krb_realm) ! realmmatch = port->hba->krb_realm; ! else ! realmmatch = pg_krb_realm; ! ! if (realmmatch && strlen(realmmatch)) { ! if (pg_strcasecmp(realmmatch, domainname)) { elog(DEBUG2, "SSPI domain (%s) and configured domain (%s) don't match", ! domainname, realmmatch); return STATUS_ERROR; } *** a/src/backend/libpq/hba.c --- b/src/backend/libpq/hba.c *************** *** 1040,1045 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline) --- 1040,1060 ---- REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap"); parsedline->ldapsuffix = pstrdup(c); } + else if (strcmp(token, "krb_server_hostname") == 0) + { + if (parsedline->auth_method != uaKrb5 && + parsedline->auth_method != uaGSS) + INVALID_AUTH_OPTION("krb_server_hostname", "krb5 and gssapi"); + 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,1247 **** free_hba_record(HbaLine *record) --- 1257,1266 ---- 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); } /* *** a/src/include/libpq/hba.h --- b/src/include/libpq/hba.h *************** *** 56,61 **** typedef struct --- 56,63 ---- char *ldapprefix; char *ldapsuffix; bool clientcert; + char *krb_server_hostname; + char *krb_realm; } HbaLine; typedef struct Port hbaPort;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers