I was looking at this TODO item from 2009:

        https://www.postgresql.org/message-id/4AA7B197.70002%40usit.uio.no

I have implemented this in the attached patch.  It does two things:

o  compares words in columns that can only support keywords as
case-insensitive, double-quoted or not

o  compares words in columns that can contain user/db names or keywords
as case-sensitive if double-quoted, case-insensitive if not

Here is the 'local' line we install during initdb, and a newly
identically-behaving line:

        # TYPE  DATABASE        USER            ADDRESS                 METHOD
        local   all             all                                     trust
        "LOCAL" ALL             ALL                                     TRUST

This 9.6 line:

        local   Test            all                                     trust

would have to be represented in PG 10 as:

        local   "Test"          all                                     trust

-- 
  Bruce Momjian  <br...@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

+ As you are, so once was I. As I am, so you will be. +
+                     Ancient Roman grave inscription +
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
new file mode 100644
index ca262d9..66a54ef
*** a/doc/src/sgml/client-auth.sgml
--- b/doc/src/sgml/client-auth.sgml
*************** hostnossl  <replaceable>database</replac
*** 195,200 ****
--- 195,201 ----
         replication connections do not specify any particular database).
         Otherwise, this is the name of
         a specific <productname>PostgreSQL</productname> database.
+        Non-keyword values are compared as lower-case, unless double-quoted.
         Multiple database names can be supplied by separating them with
         commas.  A separate file containing database names can be specified by
         preceding the file name with <literal>@</>.
*************** hostnossl  <replaceable>database</replac
*** 218,223 ****
--- 219,225 ----
         considered to be a member of a role if they are explicitly a member
         of the role, directly or indirectly, and not just by virtue of
         being a superuser.
+        Non-keyword values are compared as lower-case, unless double-quoted.
         Multiple user names can be supplied by separating them with commas.
         A separate file containing user names can be specified by preceding the
         file name with <literal>@</>.
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
new file mode 100644
index 1b4bbce..fc8d5a0
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
*************** typedef struct check_network_data
*** 61,68 ****
  } check_network_data;
  
  
! #define token_is_keyword(t, k)	(!t->quoted && strcmp(t->string, k) == 0)
! #define token_matches(t, k)  (strcmp(t->string, k) == 0)
  
  /*
   * A single string token lexed from the HBA config file, together with whether
--- 61,69 ----
  } check_network_data;
  
  
! #define token_is_keyword(t, k)	(!t->quoted && strcasecmp(t->string, k) == 0)
! /* case-insensitive comparison for unquoted strings */
! #define token_matches(t, k)  (t->quoted ? (strcmp(t->string, k) == 0) : (strcasecmp(t->string, k) == 0))
  
  /*
   * A single string token lexed from the HBA config file, together with whether
*************** parse_hba_line(List *line, int line_num,
*** 851,857 ****
  		return NULL;
  	}
  	token = linitial(tokens);
! 	if (strcmp(token->string, "local") == 0)
  	{
  #ifdef HAVE_UNIX_SOCKETS
  		parsedline->conntype = ctLocal;
--- 852,858 ----
  		return NULL;
  	}
  	token = linitial(tokens);
! 	if (strcasecmp(token->string, "local") == 0)
  	{
  #ifdef HAVE_UNIX_SOCKETS
  		parsedline->conntype = ctLocal;
*************** parse_hba_line(List *line, int line_num,
*** 864,872 ****
  		return NULL;
  #endif
  	}
! 	else if (strcmp(token->string, "host") == 0 ||
! 			 strcmp(token->string, "hostssl") == 0 ||
! 			 strcmp(token->string, "hostnossl") == 0)
  	{
  
  		if (token->string[4] == 's')	/* "hostssl" */
--- 865,873 ----
  		return NULL;
  #endif
  	}
! 	else if (strcasecmp(token->string, "host") == 0 ||
! 			 strcasecmp(token->string, "hostssl") == 0 ||
! 			 strcasecmp(token->string, "hostnossl") == 0)
  	{
  
  		if (token->string[4] == 's')	/* "hostssl" */
*************** parse_hba_line(List *line, int line_num,
*** 1149,1177 ****
  	token = linitial(tokens);
  
  	unsupauth = NULL;
! 	if (strcmp(token->string, "trust") == 0)
  		parsedline->auth_method = uaTrust;
! 	else if (strcmp(token->string, "ident") == 0)
  		parsedline->auth_method = uaIdent;
! 	else if (strcmp(token->string, "peer") == 0)
  		parsedline->auth_method = uaPeer;
! 	else if (strcmp(token->string, "password") == 0)
  		parsedline->auth_method = uaPassword;
! 	else if (strcmp(token->string, "gss") == 0)
  #ifdef ENABLE_GSS
  		parsedline->auth_method = uaGSS;
  #else
  		unsupauth = "gss";
  #endif
! 	else if (strcmp(token->string, "sspi") == 0)
  #ifdef ENABLE_SSPI
  		parsedline->auth_method = uaSSPI;
  #else
  		unsupauth = "sspi";
  #endif
! 	else if (strcmp(token->string, "reject") == 0)
  		parsedline->auth_method = uaReject;
! 	else if (strcmp(token->string, "md5") == 0)
  	{
  		if (Db_user_namespace)
  		{
--- 1150,1178 ----
  	token = linitial(tokens);
  
  	unsupauth = NULL;
! 	if (strcasecmp(token->string, "trust") == 0)
  		parsedline->auth_method = uaTrust;
! 	else if (strcasecmp(token->string, "ident") == 0)
  		parsedline->auth_method = uaIdent;
! 	else if (strcasecmp(token->string, "peer") == 0)
  		parsedline->auth_method = uaPeer;
! 	else if (strcasecmp(token->string, "password") == 0)
  		parsedline->auth_method = uaPassword;
! 	else if (strcasecmp(token->string, "gss") == 0)
  #ifdef ENABLE_GSS
  		parsedline->auth_method = uaGSS;
  #else
  		unsupauth = "gss";
  #endif
! 	else if (strcasecmp(token->string, "sspi") == 0)
  #ifdef ENABLE_SSPI
  		parsedline->auth_method = uaSSPI;
  #else
  		unsupauth = "sspi";
  #endif
! 	else if (strcasecmp(token->string, "reject") == 0)
  		parsedline->auth_method = uaReject;
! 	else if (strcasecmp(token->string, "md5") == 0)
  	{
  		if (Db_user_namespace)
  		{
*************** parse_hba_line(List *line, int line_num,
*** 1184,1214 ****
  		}
  		parsedline->auth_method = uaMD5;
  	}
! 	else if (strcmp(token->string, "pam") == 0)
  #ifdef USE_PAM
  		parsedline->auth_method = uaPAM;
  #else
  		unsupauth = "pam";
  #endif
! 	else if (strcmp(token->string, "bsd") == 0)
  #ifdef USE_BSD_AUTH
  		parsedline->auth_method = uaBSD;
  #else
  		unsupauth = "bsd";
  #endif
! 	else if (strcmp(token->string, "ldap") == 0)
  #ifdef USE_LDAP
  		parsedline->auth_method = uaLDAP;
  #else
  		unsupauth = "ldap";
  #endif
! 	else if (strcmp(token->string, "cert") == 0)
  #ifdef USE_SSL
  		parsedline->auth_method = uaCert;
  #else
  		unsupauth = "cert";
  #endif
! 	else if (strcmp(token->string, "radius") == 0)
  		parsedline->auth_method = uaRADIUS;
  	else
  	{
--- 1185,1215 ----
  		}
  		parsedline->auth_method = uaMD5;
  	}
! 	else if (strcasecmp(token->string, "pam") == 0)
  #ifdef USE_PAM
  		parsedline->auth_method = uaPAM;
  #else
  		unsupauth = "pam";
  #endif
! 	else if (strcasecmp(token->string, "bsd") == 0)
  #ifdef USE_BSD_AUTH
  		parsedline->auth_method = uaBSD;
  #else
  		unsupauth = "bsd";
  #endif
! 	else if (strcasecmp(token->string, "ldap") == 0)
  #ifdef USE_LDAP
  		parsedline->auth_method = uaLDAP;
  #else
  		unsupauth = "ldap";
  #endif
! 	else if (strcasecmp(token->string, "cert") == 0)
  #ifdef USE_SSL
  		parsedline->auth_method = uaCert;
  #else
  		unsupauth = "cert";
  #endif
! 	else if (strcasecmp(token->string, "radius") == 0)
  		parsedline->auth_method = uaRADIUS;
  	else
  	{
*************** parse_hba_auth_opt(char *name, char *val
*** 1406,1412 ****
  	hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
  #endif
  
! 	if (strcmp(name, "map") == 0)
  	{
  		if (hbaline->auth_method != uaIdent &&
  			hbaline->auth_method != uaPeer &&
--- 1407,1413 ----
  	hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
  #endif
  
! 	if (strcasecmp(name, "map") == 0)
  	{
  		if (hbaline->auth_method != uaIdent &&
  			hbaline->auth_method != uaPeer &&
*************** parse_hba_auth_opt(char *name, char *val
*** 1416,1422 ****
  			INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, and cert"));
  		hbaline->usermap = pstrdup(val);
  	}
! 	else if (strcmp(name, "clientcert") == 0)
  	{
  		/*
  		 * Since we require ctHostSSL, this really can never happen on
--- 1417,1423 ----
  			INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, and cert"));
  		hbaline->usermap = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "clientcert") == 0)
  	{
  		/*
  		 * Since we require ctHostSSL, this really can never happen on
*************** parse_hba_auth_opt(char *name, char *val
*** 1431,1437 ****
  								line_num, HbaFileName)));
  			return false;
  		}
! 		if (strcmp(val, "1") == 0)
  		{
  			if (!secure_loaded_verify_locations())
  			{
--- 1432,1438 ----
  								line_num, HbaFileName)));
  			return false;
  		}
! 		if (strcasecmp(val, "1") == 0)
  		{
  			if (!secure_loaded_verify_locations())
  			{
*************** parse_hba_auth_opt(char *name, char *val
*** 1459,1479 ****
  			hbaline->clientcert = false;
  		}
  	}
! 	else if (strcmp(name, "pamservice") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
  		hbaline->pamservice = pstrdup(val);
  	}
! 	else if (strcmp(name, "pam_use_hostname") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
! 		if (strcmp(val, "1") == 0)
  			hbaline->pam_use_hostname = true;
  		else
  			hbaline->pam_use_hostname = false;
  
  	}
! 	else if (strcmp(name, "ldapurl") == 0)
  	{
  #ifdef LDAP_API_FEATURE_X_OPENLDAP
  		LDAPURLDesc *urldata;
--- 1460,1480 ----
  			hbaline->clientcert = false;
  		}
  	}
! 	else if (strcasecmp(name, "pamservice") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
  		hbaline->pamservice = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "pam_use_hostname") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
! 		if (strcasecmp(val, "1") == 0)
  			hbaline->pam_use_hostname = true;
  		else
  			hbaline->pam_use_hostname = false;
  
  	}
! 	else if (strcasecmp(name, "ldapurl") == 0)
  	{
  #ifdef LDAP_API_FEATURE_X_OPENLDAP
  		LDAPURLDesc *urldata;
*************** parse_hba_auth_opt(char *name, char *val
*** 1491,1497 ****
  			return false;
  		}
  
! 		if (strcmp(urldata->lud_scheme, "ldap") != 0)
  		{
  			ereport(LOG,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
--- 1492,1498 ----
  			return false;
  		}
  
! 		if (strcasecmp(urldata->lud_scheme, "ldap") != 0)
  		{
  			ereport(LOG,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
*************** parse_hba_auth_opt(char *name, char *val
*** 1522,1541 ****
  				 errmsg("LDAP URLs not supported on this platform")));
  #endif   /* not OpenLDAP */
  	}
! 	else if (strcmp(name, "ldaptls") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
! 		if (strcmp(val, "1") == 0)
  			hbaline->ldaptls = true;
  		else
  			hbaline->ldaptls = false;
  	}
! 	else if (strcmp(name, "ldapserver") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
  		hbaline->ldapserver = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapport") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
  		hbaline->ldapport = atoi(val);
--- 1523,1542 ----
  				 errmsg("LDAP URLs not supported on this platform")));
  #endif   /* not OpenLDAP */
  	}
! 	else if (strcasecmp(name, "ldaptls") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
! 		if (strcasecmp(val, "1") == 0)
  			hbaline->ldaptls = true;
  		else
  			hbaline->ldaptls = false;
  	}
! 	else if (strcasecmp(name, "ldapserver") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
  		hbaline->ldapserver = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapport") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
  		hbaline->ldapport = atoi(val);
*************** parse_hba_auth_opt(char *name, char *val
*** 1549,1620 ****
  			return false;
  		}
  	}
! 	else if (strcmp(name, "ldapbinddn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
  		hbaline->ldapbinddn = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapbindpasswd") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
  		hbaline->ldapbindpasswd = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapsearchattribute") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
  		hbaline->ldapsearchattribute = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapbasedn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
  		hbaline->ldapbasedn = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapprefix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
  		hbaline->ldapprefix = pstrdup(val);
  	}
! 	else if (strcmp(name, "ldapsuffix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
  		hbaline->ldapsuffix = pstrdup(val);
  	}
! 	else if (strcmp(name, "krb_realm") == 0)
  	{
  		if (hbaline->auth_method != uaGSS &&
  			hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("krb_realm", gettext_noop("gssapi and sspi"));
  		hbaline->krb_realm = pstrdup(val);
  	}
! 	else if (strcmp(name, "include_realm") == 0)
  	{
  		if (hbaline->auth_method != uaGSS &&
  			hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("include_realm", gettext_noop("gssapi and sspi"));
! 		if (strcmp(val, "1") == 0)
  			hbaline->include_realm = true;
  		else
  			hbaline->include_realm = false;
  	}
! 	else if (strcmp(name, "compat_realm") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("compat_realm", gettext_noop("sspi"));
! 		if (strcmp(val, "1") == 0)
  			hbaline->compat_realm = true;
  		else
  			hbaline->compat_realm = false;
  	}
! 	else if (strcmp(name, "upn_username") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
! 		if (strcmp(val, "1") == 0)
  			hbaline->upn_username = true;
  		else
  			hbaline->upn_username = false;
  	}
! 	else if (strcmp(name, "radiusserver") == 0)
  	{
  		struct addrinfo *gai_result;
  		struct addrinfo hints;
--- 1550,1621 ----
  			return false;
  		}
  	}
! 	else if (strcasecmp(name, "ldapbinddn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
  		hbaline->ldapbinddn = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapbindpasswd") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
  		hbaline->ldapbindpasswd = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapsearchattribute") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
  		hbaline->ldapsearchattribute = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapbasedn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
  		hbaline->ldapbasedn = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapprefix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
  		hbaline->ldapprefix = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "ldapsuffix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
  		hbaline->ldapsuffix = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "krb_realm") == 0)
  	{
  		if (hbaline->auth_method != uaGSS &&
  			hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("krb_realm", gettext_noop("gssapi and sspi"));
  		hbaline->krb_realm = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "include_realm") == 0)
  	{
  		if (hbaline->auth_method != uaGSS &&
  			hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("include_realm", gettext_noop("gssapi and sspi"));
! 		if (strcasecmp(val, "1") == 0)
  			hbaline->include_realm = true;
  		else
  			hbaline->include_realm = false;
  	}
! 	else if (strcasecmp(name, "compat_realm") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("compat_realm", gettext_noop("sspi"));
! 		if (strcasecmp(val, "1") == 0)
  			hbaline->compat_realm = true;
  		else
  			hbaline->compat_realm = false;
  	}
! 	else if (strcasecmp(name, "upn_username") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
! 		if (strcasecmp(val, "1") == 0)
  			hbaline->upn_username = true;
  		else
  			hbaline->upn_username = false;
  	}
! 	else if (strcasecmp(name, "radiusserver") == 0)
  	{
  		struct addrinfo *gai_result;
  		struct addrinfo hints;
*************** parse_hba_auth_opt(char *name, char *val
*** 1642,1648 ****
  		pg_freeaddrinfo_all(hints.ai_family, gai_result);
  		hbaline->radiusserver = pstrdup(val);
  	}
! 	else if (strcmp(name, "radiusport") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport", "radius");
  		hbaline->radiusport = atoi(val);
--- 1643,1649 ----
  		pg_freeaddrinfo_all(hints.ai_family, gai_result);
  		hbaline->radiusserver = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "radiusport") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport", "radius");
  		hbaline->radiusport = atoi(val);
*************** parse_hba_auth_opt(char *name, char *val
*** 1656,1667 ****
  			return false;
  		}
  	}
! 	else if (strcmp(name, "radiussecret") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
  		hbaline->radiussecret = pstrdup(val);
  	}
! 	else if (strcmp(name, "radiusidentifier") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
  		hbaline->radiusidentifier = pstrdup(val);
--- 1657,1668 ----
  			return false;
  		}
  	}
! 	else if (strcasecmp(name, "radiussecret") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
  		hbaline->radiussecret = pstrdup(val);
  	}
! 	else if (strcasecmp(name, "radiusidentifier") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
  		hbaline->radiusidentifier = pstrdup(val);
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
new file mode 100644
index 86a89ed..f9a2be2
*** a/src/backend/libpq/pg_hba.conf.sample
--- b/src/backend/libpq/pg_hba.conf.sample
***************
*** 53,63 ****
  # section in the documentation for a list of which options are
  # available for which authentication methods.
  #
! # Database and user names containing spaces, commas, quotes and other
! # special characters must be quoted.  Quoting one of the keywords
! # "all", "sameuser", "samerole" or "replication" makes the name lose
! # its special character, and just match a database or username with
! # that name.
  #
  # This file is read on server startup and when the postmaster receives
  # a SIGHUP signal.  If you edit the file on a running system, you have
--- 53,64 ----
  # section in the documentation for a list of which options are
  # available for which authentication methods.
  #
! # Database and user names are compared as lower-case, unless
! # double-quoted.  Database and user names containing spaces, commas,
! # quotes and other special characters must be double-quoted.  Quoting
! # one of the keywords "all", "sameuser", "samerole" or "replication"
! # makes the name lose its special meaning, and just case-sensitive
! # matches a database or username.
  #
  # This file is read on server startup and when the postmaster receives
  # a SIGHUP signal.  If you edit the file on a running system, you have
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to