Re: [TODO] Process pg_hba.conf keywords as case-insensitive

Поиск
Список
Период
Сортировка
От Kyotaro HORIGUCHI
Тема Re: [TODO] Process pg_hba.conf keywords as case-insensitive
Дата
Msg-id 20140910.175419.199041879.horiguchi.kyotaro@lab.ntt.co.jp
обсуждение исходный текст
Ответ на Re: [TODO] Process pg_hba.conf keywords as case-insensitive  (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>)
Ответы Re: [TODO] Process pg_hba.conf keywords as case-insensitive  (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>)
Re: [TODO] Process pg_hba.conf keywords as case-insensitive  (Florian Pflug <fgp@phlo.org>)
Re: [TODO] Process pg_hba.conf keywords as case-insensitive  (Robert Haas <robertmhaas@gmail.com>)
Список pgsql-hackers
Hello, I had a closer look on this patch.

Finally I think that we need case-insensitive version of
get_role_id and() get_database_id() to acoomplish this patch'es
objective. (This runs full-scans on pg_database or pg_authid X()

And I'd like to propose to change token categorization from
notation-base to how-to-treat base. Concretely this patch
categorizes tokens using 'special quote is used' and 'quote from
the first' but it seems making logics clearer to categorize them
using 'case sensive or not' and 'it represents group name'.

The attached patch is a revised version of your original patch
regarding to the above point. (Sorry in advance that this is a
quick hack, especially the code related to file-inclusion is not
tested at all)

I have tested this only superficial level but it seems works as
expected.

Under the new specifications, next_token will work as following,
 - USER      : token: USER  , case-insensitive - "USeR"    : token: USeR  , case-SENSITIVE - "+uSeR"   : token: +uSeR ,
case-SENSITIVE- "+UsE"R   : token: +UsEr , case-insensitive - U"S""e"R  : token: US"eR , case-insensitive
 
 - +USER     : token: USER  , case-insensitive, group_name - +"uSeR"   : token: uSeR  , case_SENSITIVE, group_name -
+U"sE""r": token: UsE"r , case-insensitive, group_name
 
 - +         : token: +     , (useless?) - @         : token: @     , (useless?) - @ho"ge    : token: ho"ge,
file_inclusion(not confirmed)
 


There's a concern that Case-insensitive matching is accomplished
by full-scan on pg_database or pg_authid so it would be rather
slow than case-sensitive matching. This might not be acceptable
by the community.

And one known defect is that you will get a bit odd message if
you put an hba line having keywords quoted or prefixed with '+',
for example

+locAl   "postgres"           +sUs                        tRust

The server complains for the line above that 

*| LOG:  invalid connection type "locAl"| CONTEXT:  line 84 of configuration file
"/home/horiguti/data/data_work/pg_hba.conf"

The prefixing '+' is omitted. To correct this, either deparsing
token into original string or storing original string into tokens
is needed, I think.

What do you think about the changes, Viswanatham or all ?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index f480be8..db73dd9 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -1991,6 +1991,50 @@ get_database_oid(const char *dbname, bool missing_ok)    return oid;}
+/*
+ * get_database_oid - given a database name, look up the OID in
+ * case-insensitive manner.
+ *
+ * If missing_ok is false, throw an error if database name not found.  If
+ * true, just return InvalidOid.
+ */
+Oid
+get_database_oid_case_insensitive(const char *dbname, bool missing_ok)
+{
+    Relation    relation;
+    SysScanDesc scandesc;
+    HeapTuple    tuple;
+    Oid oid = InvalidOid;
+
+    /*
+     * SysCache has no abirility to case insensitive match, so we have no
+     * means except scanning whole the systable.
+     */
+    relation = heap_open(DatabaseRelationId, AccessShareLock);
+
+    scandesc = systable_beginscan(relation, InvalidOid, false,
+                                  NULL, 0, NULL);
+    while (HeapTupleIsValid(tuple = systable_getnext(scandesc)))
+    {
+        Form_pg_database dbForm = (Form_pg_database) GETSTRUCT(tuple);
+
+        if (pg_strcasecmp(dbname, dbForm->datname.data) == 0)
+        {
+            oid = HeapTupleGetOid(tuple);
+            break;
+        }
+    }
+    systable_endscan(scandesc);
+    heap_close(relation, AccessShareLock);
+
+    if (!OidIsValid(oid) && !missing_ok)
+         ereport(ERROR,
+                (errcode(ERRCODE_UNDEFINED_DATABASE),
+                 errmsg("database \"%s\" does not exist",
+                        dbname)));
+
+    return oid;
+}/* * get_database_name - given a database OID, look up the name
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 84da823..2d3a059 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -60,9 +60,20 @@ typedef struct check_network_data    bool        result;            /* set to true if match */}
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)
+typedef enum TokenType
+{
+    NORMAL,
+    GROUP_NAME,            /* this token had leading '+' */
+    FILE_INCLUSION,        /* this token had leading '@' */
+} TokenType;
+
+#define token_is_keyword(tk, kw)    \
+    ((tk)->type != NORMAL || (tk)->case_sensitive ? false : \
+     (pg_strcasecmp((tk)->string, (kw)) == 0))
+#define token_matches(t, k)           \
+    ((t)->type != NORMAL ? false :                                \
+     ((t)->case_sensitive ? (strcmp((t)->string, (k)) == 0):    \
+      (pg_strcasecmp((t)->string, (k)) == 0)))/* * A single string token lexed from the HBA config file, together with
whether
@@ -71,7 +82,8 @@ typedef struct check_network_datatypedef struct HbaToken{    char       *string;
-    bool        quoted;
+    TokenType    type;
+    bool        case_sensitive;} HbaToken;/*
@@ -111,6 +123,7 @@ pg_isblank(const char c)}
+/* * Grab one token out of the string pointed to by lineptr. * Tokens are strings of non-blank
@@ -123,6 +136,10 @@ pg_isblank(const char c) * the first character.  (We use that to prevent "@x" from being treated *
asa file inclusion request.  Note that @"x" should be so treated; * we want to allow that to support embedded spaces in
filepaths.)
 
+ * we set *special_plus_quote to indicate whether there was quoting after "+"
+ * charecter. (We use this to prevent +"ROLENAME" from treating as unquoted
+ * string as first charecter is not '"', but which require special handling
+ * only incase of role/user-group name). * We set *terminating_comma to indicate whether the token is terminated by a
*comma (which is not returned.) *
 
@@ -136,12 +153,13 @@ pg_isblank(const char c) * Handle comments. */static bool
-next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,
-           bool *terminating_comma)
+next_token(char **lineptr, char *buf, int bufsz,
+           bool *case_sensitive, int *type, bool *terminating_comma){    int            c;    char       *start_buf =
buf;   char       *end_buf = buf + (bufsz - 2);
 
+    char        *p;    bool        in_quote = false;    bool        was_quote = false;    bool        saw_quote =
false;
@@ -149,8 +167,9 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,    /* end_buf reserves two
bytesto ensure we can append \n and \0 */    Assert(end_buf > start_buf);
 
-    *initial_quote = false;    *terminating_comma = false;
+    *case_sensitive = false;
+    *type = NORMAL;    /* Move over initial whitespace and commas */    while ((c = (*(*lineptr)++)) != '\0' &&
(pg_isblank(c)|| c == ','))
 
@@ -162,6 +181,17 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,        return false;    }
+    if (c == '+' || c == '@')
+    {
+        *type = (c == '+' ? GROUP_NAME : FILE_INCLUSION);
+
+        /*
+         * Skip capturing it, and we can read the following characters as
+         * usual.
+         */
+        c = *(*lineptr)++;
+    }
+    /*     * Build a token in buf of next characters up to EOF, EOL, unquoted comma,     * or unquoted whitespace.
@@ -201,8 +231,17 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,        }        if (c != '"'
||was_quote)
 
+        {            *buf++ = c;
+            /*
+             * Cancel case-sensitive state if trailing characters found for
+             * the quoted region.
+             */
+            if (*case_sensitive && !in_quote)
+                *case_sensitive = false;
+        }
+        /* Literal double-quote is two double-quotes */        if (in_quote && c == '"')            was_quote =
!was_quote;
@@ -214,7 +253,7 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,            in_quote =
!in_quote;           saw_quote = true;            if (buf == start_buf)
 
-                *initial_quote = true;
+                *case_sensitive = true;        }        c = *(*lineptr)++;
@@ -226,13 +265,19 @@ next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote,     */    (*lineptr)--;
+    if (buf == start_buf && *type != NORMAL)
+    {
+        *buf++ = (*type == GROUP_NAME ? '+' : '@');
+        *type = NORMAL;
+    }
+    *buf = '\0';    return (saw_quote || buf > start_buf);}static HbaToken *
-make_hba_token(char *token, bool quoted)
+make_hba_token(char *token, TokenType toktype, bool case_sensitive){    HbaToken   *hbatoken;    int
toklen;
@@ -240,7 +285,8 @@ make_hba_token(char *token, bool quoted)    toklen = strlen(token);    hbatoken = (HbaToken *)
palloc(sizeof(HbaToken)+ toklen + 1);    hbatoken->string = (char *) hbatoken + sizeof(HbaToken);
 
-    hbatoken->quoted = quoted;
+    hbatoken->type = toktype;
+    hbatoken->case_sensitive = case_sensitive;    memcpy(hbatoken->string, token, toklen + 1);    return hbatoken;
@@ -252,7 +298,8 @@ make_hba_token(char *token, bool quoted)static HbaToken *copy_hba_token(HbaToken *in){
-    HbaToken   *out = make_hba_token(in->string, in->quoted);
+    HbaToken   *out = make_hba_token(in->string,
+                                     in->type, in->case_sensitive);    return out;}
@@ -269,19 +316,26 @@ next_field_expand(const char *filename, char **lineptr){    char        buf[MAX_TOKEN];    bool
    trailing_comma;
 
-    bool        initial_quote;
+    bool        case_sensitive;
+    int            type;    List       *tokens = NIL;    do    {
-        if (!next_token(lineptr, buf, sizeof(buf), &initial_quote, &trailing_comma))
+        if (!next_token(lineptr, buf, sizeof(buf), 
+                        &case_sensitive, &type,
+                        &trailing_comma))            break;        /* Is this referencing a file? */
-        if (!initial_quote && buf[0] == '@' && buf[1] != '\0')
-            tokens = tokenize_inc_file(tokens, filename, buf + 1);
+        if (type == FILE_INCLUSION)
+            tokens = tokenize_inc_file(tokens, filename, buf);
+        else if (type == GROUP_NAME)
+            tokens = lappend(tokens,
+                             make_hba_token(buf, GROUP_NAME, case_sensitive));        else
-            tokens = lappend(tokens, make_hba_token(buf, initial_quote));
+            tokens = lappend(tokens,
+                             make_hba_token(buf, NORMAL, case_sensitive));    } while (trailing_comma);    return
tokens;
@@ -457,14 +511,17 @@ tokenize_file(const char *filename, FILE *file, * We check to see if it is a member of the
specifiedrole name. */static bool
 
-is_member(Oid userid, const char *role)
+is_member(Oid userid, const char *role, bool case_sensitive){    Oid            roleid;    if (!OidIsValid(userid))
   return false;            /* if user not exist, say "no" */
 
-    roleid = get_role_oid(role, true);
+    if (case_sensitive)
+        roleid = get_role_oid(role, true);
+    else
+        roleid = get_role_oid_case_insensitive(role, true);    if (!OidIsValid(roleid))        return false;
/* if target role not exist, say "no" */
 
@@ -489,9 +546,9 @@ check_role(const char *role, Oid roleid, List *tokens)    foreach(cell, tokens)    {        tok =
lfirst(cell);
-        if (!tok->quoted && tok->string[0] == '+')
+        if (tok->type == GROUP_NAME)        {
-            if (is_member(roleid, tok->string + 1))
+            if (is_member(roleid, tok->string, tok->case_sensitive))                return true;        }        else
if(token_matches(tok, role) ||
 
@@ -529,7 +586,7 @@ check_db(const char *dbname, const char *role, Oid roleid, List *tokens)        else if
(token_is_keyword(tok,"samegroup") ||                 token_is_keyword(tok, "samerole"))        {
 
-            if (is_member(roleid, dbname))
+            if (is_member(roleid, dbname, tok->case_sensitive))                return true;        }        else if
(token_is_keyword(tok,"replication"))
 
@@ -881,7 +938,7 @@ parse_hba_line(List *line, int line_num, char *raw_line)        return NULL;    }    token =
linitial(tokens);
-    if (strcmp(token->string, "local") == 0)
+    if (token_is_keyword(token, "local"))    {#ifdef HAVE_UNIX_SOCKETS        parsedline->conntype = ctLocal;
@@ -894,12 +951,12 @@ parse_hba_line(List *line, int line_num, char *raw_line)        return NULL;#endif    }
-    else if (strcmp(token->string, "host") == 0 ||
-             strcmp(token->string, "hostssl") == 0 ||
-             strcmp(token->string, "hostnossl") == 0)
+    else if (token_is_keyword(token, "host") ||
+             token_is_keyword(token, "hostssl") ||
+             token_is_keyword(token, "hostnossl"))    {
-        if (token->string[4] == 's')    /* "hostssl" */
+        if ((token->string[4] == 's') || (token->string[4] == 'S'))        /* "hostssl" */        {            /* SSL
supportmust be actually active, else complain */#ifdef USE_SSL
 
@@ -926,7 +983,7 @@ parse_hba_line(List *line, int line_num, char *raw_line)#endif        }#ifdef USE_SSL
-        else if (token->string[4] == 'n')        /* "hostnossl" */
+        else if ((token->string[4] == 'n') || (token->string[4] == 'N'))        /* "hostnossl" */        {
parsedline->conntype= ctHostNoSSL;        }
 
@@ -1181,29 +1238,29 @@ parse_hba_line(List *line, int line_num, char *raw_line)    token = linitial(tokens);
unsupauth= NULL;
 
-    if (strcmp(token->string, "trust") == 0)
+    if (token_is_keyword(token, "trust"))        parsedline->auth_method = uaTrust;
-    else if (strcmp(token->string, "ident") == 0)
+    else if (token_is_keyword(token, "ident"))        parsedline->auth_method = uaIdent;
-    else if (strcmp(token->string, "peer") == 0)
+    else if (token_is_keyword(token, "peer"))        parsedline->auth_method = uaPeer;
-    else if (strcmp(token->string, "password") == 0)
+    else if (token_is_keyword(token, "password"))        parsedline->auth_method = uaPassword;
-    else if (strcmp(token->string, "gss") == 0)
+    else if (token_is_keyword(token, "gss"))#ifdef ENABLE_GSS        parsedline->auth_method = uaGSS;#else
unsupauth= "gss";#endif
 
-    else if (strcmp(token->string, "sspi") == 0)
+    else if (token_is_keyword(token, "sspi"))#ifdef ENABLE_SSPI        parsedline->auth_method = uaSSPI;#else
unsupauth= "sspi";#endif
 
-    else if (strcmp(token->string, "reject") == 0)
+    else if (token_is_keyword(token, "reject"))        parsedline->auth_method = uaReject;
-    else if (strcmp(token->string, "md5") == 0)
+    else if (token_is_keyword(token, "md5"))    {        if (Db_user_namespace)        {
@@ -1216,25 +1273,25 @@ parse_hba_line(List *line, int line_num, char *raw_line)        }
parsedline->auth_method= uaMD5;    }
 
-    else if (strcmp(token->string, "pam") == 0)
+    else if (token_is_keyword(token, "pam"))#ifdef USE_PAM        parsedline->auth_method = uaPAM;#else
unsupauth= "pam";#endif
 
-    else if (strcmp(token->string, "ldap") == 0)
+    else if (token_is_keyword(token, "ldap"))#ifdef USE_LDAP        parsedline->auth_method = uaLDAP;#else
unsupauth= "ldap";#endif
 
-    else if (strcmp(token->string, "cert") == 0)
+    else if (token_is_keyword(token, "cert"))#ifdef USE_SSL        parsedline->auth_method = uaCert;#else
unsupauth= "cert";#endif
 
-    else if (strcmp(token->string, "radius") == 0)
+    else if (token_is_keyword(token, "radius"))        parsedline->auth_method = uaRADIUS;    else    {
@@ -1408,7 +1465,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)    hbaline->ldapscope =
LDAP_SCOPE_SUBTREE;#endif
-    if (strcmp(name, "map") == 0)
+    if (pg_strcasecmp(name, "map") == 0)    {        if (hbaline->auth_method != uaIdent &&
hbaline->auth_method!= uaPeer &&
 
@@ -1418,7 +1475,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
INVALID_AUTH_OPTION("map",gettext_noop("ident, peer, gssapi, sspi, and cert"));        hbaline->usermap = pstrdup(val);
  }
 
-    else if (strcmp(name, "clientcert") == 0)
+    else if (pg_strcasecmp(name, "clientcert") == 0)    {        /*         * Since we require ctHostSSL, this really
cannever happen on
 
@@ -1461,12 +1518,12 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
hbaline->clientcert= false;        }    }
 
-    else if (strcmp(name, "pamservice") == 0)
+    else if (pg_strcasecmp(name, "pamservice") == 0)    {        REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
 hbaline->pamservice = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapurl") == 0)
+    else if (pg_strcasecmp(name, "ldapurl") == 0)    {#ifdef LDAP_API_FEATURE_X_OPENLDAP        LDAPURLDesc *urldata;
@@ -1484,7 +1541,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)            return
false;       }
 
-        if (strcmp(urldata->lud_scheme, "ldap") != 0)
+        if (pg_strcasecmp(urldata->lud_scheme, "ldap") != 0)        {            ereport(LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
@@ -1515,7 +1572,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
errmsg("LDAPURLs not supported on this platform")));#endif   /* not OpenLDAP */    }
 
-    else if (strcmp(name, "ldaptls") == 0)
+    else if (pg_strcasecmp(name, "ldaptls") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
if(strcmp(val, "1") == 0)
 
@@ -1523,12 +1580,12 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)        else
hbaline->ldaptls = false;    }
 
-    else if (strcmp(name, "ldapserver") == 0)
+    else if (pg_strcasecmp(name, "ldapserver") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
   hbaline->ldapserver = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapport") == 0)
+    else if (pg_strcasecmp(name, "ldapport") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
hbaline->ldapport= atoi(val);
 
@@ -1542,44 +1599,44 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)            return
false;       }    }
 
-    else if (strcmp(name, "ldapbinddn") == 0)
+    else if (pg_strcasecmp(name, "ldapbinddn") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
   hbaline->ldapbinddn = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapbindpasswd") == 0)
+    else if (pg_strcasecmp(name, "ldapbindpasswd") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd",
"ldap");       hbaline->ldapbindpasswd = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapsearchattribute") == 0)
+    else if (pg_strcasecmp(name, "ldapsearchattribute") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP,
"ldapsearchattribute","ldap");        hbaline->ldapsearchattribute = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapbasedn") == 0)
+    else if (pg_strcasecmp(name, "ldapbasedn") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
   hbaline->ldapbasedn = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapprefix") == 0)
+    else if (pg_strcasecmp(name, "ldapprefix") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
   hbaline->ldapprefix = pstrdup(val);    }
 
-    else if (strcmp(name, "ldapsuffix") == 0)
+    else if (pg_strcasecmp(name, "ldapsuffix") == 0)    {        REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
   hbaline->ldapsuffix = pstrdup(val);    }
 
-    else if (strcmp(name, "krb_realm") == 0)
+    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 (strcmp(name, "include_realm") == 0)
+    else if (pg_strcasecmp(name, "include_realm") == 0)    {        if (hbaline->auth_method != uaGSS &&
hbaline->auth_method!= uaSSPI)
 
@@ -1589,7 +1646,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)        else
hbaline->include_realm= false;    }
 
-    else if (strcmp(name, "radiusserver") == 0)
+    else if (pg_strcasecmp(name, "radiusserver") == 0)    {        struct addrinfo *gai_result;        struct addrinfo
hints;
@@ -1617,7 +1674,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
pg_freeaddrinfo_all(hints.ai_family,gai_result);        hbaline->radiusserver = pstrdup(val);    }
 
-    else if (strcmp(name, "radiusport") == 0)
+    else if (pg_strcasecmp(name, "radiusport") == 0)    {        REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport",
"radius");       hbaline->radiusport = atoi(val);
 
@@ -1631,12 +1688,12 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)            return
false;       }    }
 
-    else if (strcmp(name, "radiussecret") == 0)
+    else if (pg_strcasecmp(name, "radiussecret") == 0)    {        REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret",
"radius");       hbaline->radiussecret = pstrdup(val);    }
 
-    else if (strcmp(name, "radiusidentifier") == 0)
+    else if (pg_strcasecmp(name, "radiusidentifier") == 0)    {        REQUIRE_AUTH_OPTION(uaRADIUS,
"radiusidentifier","radius");        hbaline->radiusidentifier = pstrdup(val);
 
@@ -1666,6 +1723,7 @@ check_hba(hbaPort *port)    HbaLine    *hba;    /* Get the target role's OID.  Note we do not
errorout for bad role. */
 
+    roleid = get_role_oid(port->user_name, true);    foreach(line, parsed_hba_lines)
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 38cd5b8..9adad8c 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -5123,6 +5123,50 @@ get_role_oid(const char *rolname, bool missing_ok)}/*
+ * get_role_oid_case_insensitive - Given a role name, look up the role's OID
+ * in case-insensitive manner.
+ *
+ * If missing_ok is false, throw an error if tablespace name not found.  If
+ * true, just return InvalidOid.
+ */
+Oid
+get_role_oid_case_insensitive(const char *rolname, bool missing_ok)
+{
+    Relation    relation;
+    SysScanDesc scandesc;
+    HeapTuple    tuple;
+    Oid oid = InvalidOid;
+
+    /*
+     * SysCache has no abirility to case insensitive match, so we have no
+     * means except scanning whole the systable.
+     */
+    relation = heap_open(AuthIdRelationId, AccessShareLock);
+
+    scandesc = systable_beginscan(relation, InvalidOid, false,
+                                  NULL, 0, NULL);
+    while (HeapTupleIsValid(tuple = systable_getnext(scandesc)))
+    {
+        Form_pg_authid authForm = (Form_pg_authid) GETSTRUCT(tuple);
+
+        if (pg_strcasecmp(rolname, authForm->rolname.data) == 0)
+        {
+            oid = HeapTupleGetOid(tuple);
+            break;
+        }
+    }
+    systable_endscan(scandesc);
+    heap_close(relation, NoLock);
+
+    if (!OidIsValid(oid) && !missing_ok)
+        ereport(ERROR,
+                (errcode(ERRCODE_UNDEFINED_OBJECT),
+                 errmsg("role \"%s\" does not exist", rolname)));
+
+    return oid;
+}
+
+/* * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the *        role name is "public". */
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index c2380dc..9ec3dae 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -60,6 +60,7 @@ extern Oid    AlterDatabaseSet(AlterDatabaseSetStmt *stmt);extern Oid    AlterDatabaseOwner(const
char*dbname, Oid newOwnerId);extern Oid    get_database_oid(const char *dbname, bool missingok);
 
+extern Oid    get_database_oid_case_insensitive(const char *dbname, bool missingok);extern char *get_database_name(Oid
dbid);externvoid dbase_redo(XLogRecPtr lsn, XLogRecord *rptr);
 
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 9430baa..819b33c 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -228,6 +228,7 @@ extern bool is_member_of_role_nosuper(Oid member, Oid role);extern bool is_admin_of_role(Oid
member,Oid role);extern void check_is_member_of_role(Oid member, Oid role);extern Oid    get_role_oid(const char
*rolname,bool missing_ok);
 
+extern Oid    get_role_oid_case_insensitive(const char *rolname, bool missing_ok);extern void select_best_grantor(Oid
roleId,AclMode privileges,                    const Acl *acl, Oid ownerId, 

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Fabien COELHO
Дата:
Сообщение: Re: add modulo (%) operator to pgbench
Следующее
От: Etsuro Fujita
Дата:
Сообщение: Re: LIMIT for UPDATE and DELETE