Making pg_hba.conf case-insensitive

Started by Bruce Momjianover 9 years ago7 messages
#1Bruce Momjian
bruce@momjian.us
1 attachment(s)

I was looking at this TODO item from 2009:

/messages/by-id/4AA7B197.70002@usit.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 <bruce@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 +

Attachments:

hba.difftext/x-diff; charset=us-asciiDownload
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
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#1)
Re: Making pg_hba.conf case-insensitive

Bruce Momjian <bruce@momjian.us> writes:

I was looking at this TODO item from 2009:
/messages/by-id/4AA7B197.70002@usit.uio.no
I have implemented this in the attached patch. It does two things:

Is there really enough demand for this to justify subtle breakage
of existing pg_hba.conf entries? It'd probably have been fine if
we did it like that originally, but I think it's a bit late now.

Also, why strcasecmp and not pg_strcasecmp? The former is going
to induce misbehavior in e.g. Turkish locales.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
1 attachment(s)
Re: Making pg_hba.conf case-insensitive

On Thu, Aug 18, 2016 at 02:06:39PM -0400, Tom Lane wrote:

Bruce Momjian <bruce@momjian.us> writes:

I was looking at this TODO item from 2009:
/messages/by-id/4AA7B197.70002@usit.uio.no
I have implemented this in the attached patch. It does two things:

Is there really enough demand for this to justify subtle breakage
of existing pg_hba.conf entries? It'd probably have been fine if
we did it like that originally, but I think it's a bit late now.

Well, in 2009 the discussion was whether to backpatch or not, which
seems a long way from saying we can't change it in a major release:

/messages/by-id/1336.1252509807@sss.pgh.pa.us
/messages/by-id/5060.1252523065@sss.pgh.pa.us

It is certainly something we can discuss.

Also, why strcasecmp and not pg_strcasecmp? The former is going
to induce misbehavior in e.g. Turkish locales.

OK, changed, and attached.

--
Bruce Momjian <bruce@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 +

Attachments:

hba.difftext/x-diff; charset=us-asciiDownload
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..809cb9a
*** 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 && pg_strcasecmp(t->string, k) == 0)
! /* case-insensitive comparison for unquoted strings */
! #define token_matches(t, k)  (t->quoted ? (strcmp(t->string, k) == 0) : (pg_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 (pg_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 (pg_strcasecmp(token->string, "host") == 0 ||
! 			 pg_strcasecmp(token->string, "hostssl") == 0 ||
! 			 pg_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 (pg_strcasecmp(token->string, "trust") == 0)
  		parsedline->auth_method = uaTrust;
! 	else if (pg_strcasecmp(token->string, "ident") == 0)
  		parsedline->auth_method = uaIdent;
! 	else if (pg_strcasecmp(token->string, "peer") == 0)
  		parsedline->auth_method = uaPeer;
! 	else if (pg_strcasecmp(token->string, "password") == 0)
  		parsedline->auth_method = uaPassword;
! 	else if (pg_strcasecmp(token->string, "gss") == 0)
  #ifdef ENABLE_GSS
  		parsedline->auth_method = uaGSS;
  #else
  		unsupauth = "gss";
  #endif
! 	else if (pg_strcasecmp(token->string, "sspi") == 0)
  #ifdef ENABLE_SSPI
  		parsedline->auth_method = uaSSPI;
  #else
  		unsupauth = "sspi";
  #endif
! 	else if (pg_strcasecmp(token->string, "reject") == 0)
  		parsedline->auth_method = uaReject;
! 	else if (pg_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 (pg_strcasecmp(token->string, "pam") == 0)
  #ifdef USE_PAM
  		parsedline->auth_method = uaPAM;
  #else
  		unsupauth = "pam";
  #endif
! 	else if (pg_strcasecmp(token->string, "bsd") == 0)
  #ifdef USE_BSD_AUTH
  		parsedline->auth_method = uaBSD;
  #else
  		unsupauth = "bsd";
  #endif
! 	else if (pg_strcasecmp(token->string, "ldap") == 0)
  #ifdef USE_LDAP
  		parsedline->auth_method = uaLDAP;
  #else
  		unsupauth = "ldap";
  #endif
! 	else if (pg_strcasecmp(token->string, "cert") == 0)
  #ifdef USE_SSL
  		parsedline->auth_method = uaCert;
  #else
  		unsupauth = "cert";
  #endif
! 	else if (pg_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 (pg_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 (pg_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 (pg_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 (pg_strcasecmp(name, "pamservice") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
  		hbaline->pamservice = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "pam_use_hostname") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
! 		if (pg_strcasecmp(val, "1") == 0)
  			hbaline->pam_use_hostname = true;
  		else
  			hbaline->pam_use_hostname = false;
  
  	}
! 	else if (pg_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 (pg_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 (pg_strcasecmp(name, "ldaptls") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
! 		if (pg_strcasecmp(val, "1") == 0)
  			hbaline->ldaptls = true;
  		else
  			hbaline->ldaptls = false;
  	}
! 	else if (pg_strcasecmp(name, "ldapserver") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
  		hbaline->ldapserver = pstrdup(val);
  	}
! 	else if (pg_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 (pg_strcasecmp(name, "ldapbinddn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
  		hbaline->ldapbinddn = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "ldapbindpasswd") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
  		hbaline->ldapbindpasswd = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "ldapsearchattribute") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
  		hbaline->ldapsearchattribute = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "ldapbasedn") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
  		hbaline->ldapbasedn = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "ldapprefix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
  		hbaline->ldapprefix = pstrdup(val);
  	}
! 	else if (pg_strcasecmp(name, "ldapsuffix") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
  		hbaline->ldapsuffix = pstrdup(val);
  	}
! 	else if (pg_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 (pg_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 (pg_strcasecmp(val, "1") == 0)
  			hbaline->include_realm = true;
  		else
  			hbaline->include_realm = false;
  	}
! 	else if (pg_strcasecmp(name, "compat_realm") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("compat_realm", gettext_noop("sspi"));
! 		if (pg_strcasecmp(val, "1") == 0)
  			hbaline->compat_realm = true;
  		else
  			hbaline->compat_realm = false;
  	}
! 	else if (pg_strcasecmp(name, "upn_username") == 0)
  	{
  		if (hbaline->auth_method != uaSSPI)
  			INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
! 		if (pg_strcasecmp(val, "1") == 0)
  			hbaline->upn_username = true;
  		else
  			hbaline->upn_username = false;
  	}
! 	else if (pg_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 (pg_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 (pg_strcasecmp(name, "radiussecret") == 0)
  	{
  		REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
  		hbaline->radiussecret = pstrdup(val);
  	}
! 	else if (pg_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
#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#3)
Re: Making pg_hba.conf case-insensitive

Bruce Momjian <bruce@momjian.us> writes:

On Thu, Aug 18, 2016 at 02:06:39PM -0400, Tom Lane wrote:

Is there really enough demand for this to justify subtle breakage
of existing pg_hba.conf entries? It'd probably have been fine if
we did it like that originally, but I think it's a bit late now.

Well, in 2009 the discussion was whether to backpatch or not, which
seems a long way from saying we can't change it in a major release:

That was seven years ago, which means there's now seven more years
of precedent for the way it works today; and still we've only ever
heard the one complaint. I think documenting the gotcha more clearly
might be the right answer at this point.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Peter Eisentraut
peter.eisentraut@2ndquadrant.com
In reply to: Bruce Momjian (#1)
Re: Making pg_hba.conf case-insensitive

On 8/18/16 1:59 PM, Bruce Momjian wrote:

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

I can maybe see the case of the second one, but the first one doesn't
make sense to me.

We've in the past had discussions like this about whether command line
arguments of tools should be case insensitive like SQL, and we had
resolved that since the shell is not SQL, it shouldn't work like that.
pg_hba.conf is also not SQL, and neither, for that matter, is
pg_ident.conf and postgresql.conf.

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Bruce Momjian
bruce@momjian.us
In reply to: Peter Eisentraut (#5)
Re: Making pg_hba.conf case-insensitive

On Thu, Aug 18, 2016 at 03:01:48PM -0400, Peter Eisentraut wrote:

On 8/18/16 1:59 PM, Bruce Momjian wrote:

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

I can maybe see the case of the second one, but the first one doesn't
make sense to me.

We've in the past had discussions like this about whether command line
arguments of tools should be case insensitive like SQL, and we had
resolved that since the shell is not SQL, it shouldn't work like that.
pg_hba.conf is also not SQL, and neither, for that matter, is
pg_ident.conf and postgresql.conf.

OK, I am happy to remove the TODO item and see if we get new complaints.

--
Bruce Momjian <bruce@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 +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#6)
Re: Making pg_hba.conf case-insensitive

On Thu, Aug 18, 2016 at 04:49:04PM -0400, Bruce Momjian wrote:

On Thu, Aug 18, 2016 at 03:01:48PM -0400, Peter Eisentraut wrote:

On 8/18/16 1:59 PM, Bruce Momjian wrote:

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

I can maybe see the case of the second one, but the first one doesn't
make sense to me.

We've in the past had discussions like this about whether command line
arguments of tools should be case insensitive like SQL, and we had
resolved that since the shell is not SQL, it shouldn't work like that.
pg_hba.conf is also not SQL, and neither, for that matter, is
pg_ident.conf and postgresql.conf.

OK, I am happy to remove the TODO item and see if we get new complaints.

TODO item removed.

--
Bruce Momjian <bruce@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 +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers