usermap regexp support
От | Magnus Hagander |
---|---|
Тема | usermap regexp support |
Дата | |
Msg-id | 49076F39.1080502@hagander.net обсуждение исходный текст |
Ответы |
Re: usermap regexp support
(Gianni Ciolli <gianni.ciolli@2ndquadrant.it>)
|
Список | pgsql-hackers |
The attached patch tries to implement regexp support in the usermaps (pg_ident.conf). The use-case will be to do things like realm-based matches in kerberos/GSSAPI authentication (will require some further hacks on that one to expose the realm name). For example you could have: krb /^(.*)@myrealm.com$ \1 krb /^(.*)@otherrealm.com guest and things like that. It will also likely be quite useful once we get SSL certificate based authentication. Reviews particularly appreciated - I really can't claim to *know* our regexp code :-O Obviously docs need to be updated as well. //Magnus *** a/src/backend/libpq/hba.c --- b/src/backend/libpq/hba.c *************** *** 27,32 **** --- 27,33 ---- #include "libpq/ip.h" #include "libpq/libpq.h" + #include "regex/regex.h" #include "storage/fd.h" #include "utils/flatfiles.h" #include "utils/guc.h" *************** *** 1325,1344 **** parse_ident_usermap(List *line, int line_number, const char *usermap_name, token = lfirst(line_item); file_pgrole = token; /* Match? */ ! if (case_insensitive) { ! if (strcmp(file_map, usermap_name) == 0 && ! pg_strcasecmp(file_pgrole, pg_role) == 0 && ! pg_strcasecmp(file_ident_user, ident_user) == 0) ! *found_p = true; } else { ! if (strcmp(file_map, usermap_name) == 0 && ! strcmp(file_pgrole, pg_role) == 0 && ! strcmp(file_ident_user, ident_user) == 0) ! *found_p = true; } return; --- 1326,1453 ---- token = lfirst(line_item); file_pgrole = token; + if (strcmp(file_map, usermap_name) != 0) + /* Line does not match the map name we're looking for, so just abort */ + return; + /* Match? */ ! if (file_ident_user[0] == '/') { ! /* ! * When system username starts with a slash, treat it as a regular expression. ! * In this case, we process the system username as a regular expression that ! * returns exactly one match. This is replaced for $1 in the database username ! * string, if present. ! */ ! int r; ! regex_t re; ! regmatch_t matches[2]; ! pg_wchar *wstr; ! int wlen; ! char *ofs; ! char *regexp_pgrole; ! ! wstr = palloc((strlen(file_ident_user+1) + 1) * sizeof(pg_wchar)); ! wlen = pg_mb2wchar_with_len(file_ident_user+1, wstr, strlen(file_ident_user+1)); ! ! /* ! * XXX: Major room for optimization: regexps could be compiled when the file is loaded ! * and then re-used in every connection. ! */ ! r = pg_regcomp(&re, wstr, wlen, REG_ADVANCED); ! if (r) ! { ! char errstr[100]; ! ! pg_regerror(r, &re, errstr, sizeof(errstr)); ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), ! errmsg("invalid regular expression '%s': %s", file_ident_user+1, errstr))); ! ! pfree(wstr); ! *error_p = true; ! return; ! } ! pfree(wstr); ! ! wstr = palloc((strlen(ident_user) + 1) * sizeof(pg_wchar)); ! wlen = pg_mb2wchar_with_len(ident_user, wstr, strlen(ident_user)); ! ! r = pg_regexec(&re, wstr, wlen, 0, NULL, 2, matches,0); ! if (r) ! { ! char errstr[100]; ! ! if (r != REG_NOMATCH) ! { ! /* REG_NOMATCH is not an error, everything else is */ ! pg_regerror(r, &re, errstr, sizeof(errstr)); ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), ! errmsg("regular expression match for '%s' failed: %s", file_ident_user+1, errstr))); ! *error_p = true; ! } ! ! pfree(wstr); ! pg_regfree(&re); ! return; ! } ! pfree(wstr); ! ! if ((ofs = strstr(file_pgrole, "\\1")) != NULL) ! { ! /* substitution of the first argument requested */ ! if (matches[1].rm_so < 0) ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), ! errmsg("regular expression '%s' has no subexpressions as requested by backreference in '%s'", ! file_ident_user+1, file_pgrole))); ! /* length: original length minus length of \1 plus length of match */ ! regexp_pgrole = palloc0(strlen(file_pgrole)-2+(matches[1].rm_so-matches[1].rm_so)); ! strncpy(regexp_pgrole, file_pgrole, (ofs-file_pgrole)); ! memcpy(regexp_pgrole+strlen(regexp_pgrole), ! ident_user+matches[1].rm_so, ! matches[1].rm_eo-matches[1].rm_so); ! strcat(regexp_pgrole, ofs+2); ! } ! else ! { ! /* no substitution, so copy the match */ ! regexp_pgrole = pstrdup(file_pgrole); ! } ! ! pg_regfree(&re); ! ! /* now check if the username actually matched what the user is trying to connect as */ ! if (case_insensitive) ! { ! if (pg_strcasecmp(regexp_pgrole, pg_role) == 0) ! *found_p = true; ! } ! else ! { ! if (strcmp(regexp_pgrole, pg_role) == 0) ! *found_p = true; ! } ! pfree(regexp_pgrole); ! ! return; } else { ! /* Not regular expression, so make complete match */ ! if (case_insensitive) ! { ! if (pg_strcasecmp(file_pgrole, pg_role) == 0 && ! pg_strcasecmp(file_ident_user, ident_user) == 0) ! *found_p = true; ! } ! else ! { ! if (strcmp(file_pgrole, pg_role) == 0 && ! strcmp(file_ident_user, ident_user) == 0) ! *found_p = true; ! } } return;
В списке pgsql-hackers по дате отправления:
Предыдущее
От: Tom LaneДата:
Сообщение: Re: Re: [COMMITTERS] pgsql: Rework subtransaction commit protocol for hot standby.
Следующее
От: Grzegorz JaskiewiczДата:
Сообщение: Re: current head fails regression tests on mac osx