Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5d2a1a4

Browse files
committed
Support regular expressions in pg_ident.conf.
1 parent2939e20 commit5d2a1a4

File tree

3 files changed

+140
-13
lines changed

3 files changed

+140
-13
lines changed

‎doc/src/sgml/client-auth.sgml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.113 2008/11/20 20:45:29 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.114 2008/11/28 14:26:58 mha Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -595,6 +595,19 @@ local db1,db2,@demodbs all md5
595595
There is no restriction regarding how many database users a given
596596
operating system user can correspond to, nor vice versa.
597597
</para>
598+
<para>
599+
If the <replaceable>system-username</> field starts with a slash (<literal>/</>),
600+
the contents of the field is treated as a regular expression. This regular
601+
expression supports a single capture, which can be back-referenced as
602+
<literal>\1</> (backslash-one). This allows the mapping of different syntax
603+
names with a single line.
604+
<programlisting>
605+
mymap /(.*)@mydomain.com \1
606+
mymap /(.*)@otherdomain.com guest
607+
</programlisting>
608+
will "remove" the domain part for users with system usernames @mydomain.com, and
609+
allow all users from @otherdomain.com to log in as guest.
610+
</para>
598611

599612
<para>
600613
The <filename>pg_ident.conf</filename> file is read on start-up and

‎src/backend/libpq/hba.c

Lines changed: 119 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.175 2008/11/20 20:45:30 momjian Exp $
13+
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.176 2008/11/28 14:26:58 mha Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -27,6 +27,7 @@
2727

2828
#include"libpq/ip.h"
2929
#include"libpq/libpq.h"
30+
#include"regex/regex.h"
3031
#include"storage/fd.h"
3132
#include"utils/flatfiles.h"
3233
#include"utils/guc.h"
@@ -1403,20 +1404,128 @@ parse_ident_usermap(List *line, int line_number, const char *usermap_name,
14031404
token=lfirst(line_item);
14041405
file_pgrole=token;
14051406

1407+
if (strcmp(file_map,usermap_name)!=0)
1408+
/* Line does not match the map name we're looking for, so just abort */
1409+
return;
1410+
14061411
/* Match? */
1407-
if (case_insensitive)
1412+
if (file_ident_user[0]=='/')
14081413
{
1409-
if (strcmp(file_map,usermap_name)==0&&
1410-
pg_strcasecmp(file_pgrole,pg_role)==0&&
1411-
pg_strcasecmp(file_ident_user,ident_user)==0)
1412-
*found_p= true;
1414+
/*
1415+
* When system username starts with a slash, treat it as a regular expression.
1416+
* In this case, we process the system username as a regular expression that
1417+
* returns exactly one match. This is replaced for \1 in the database username
1418+
* string, if present.
1419+
*/
1420+
intr;
1421+
regex_tre;
1422+
regmatch_tmatches[2];
1423+
pg_wchar*wstr;
1424+
intwlen;
1425+
char*ofs;
1426+
char*regexp_pgrole;
1427+
1428+
wstr=palloc((strlen(file_ident_user+1)+1)*sizeof(pg_wchar));
1429+
wlen=pg_mb2wchar_with_len(file_ident_user+1,wstr,strlen(file_ident_user+1));
1430+
1431+
/*
1432+
* XXX: Major room for optimization: regexps could be compiled when the file is loaded
1433+
* and then re-used in every connection.
1434+
*/
1435+
r=pg_regcomp(&re,wstr,wlen,REG_ADVANCED);
1436+
if (r)
1437+
{
1438+
charerrstr[100];
1439+
1440+
pg_regerror(r,&re,errstr,sizeof(errstr));
1441+
ereport(ERROR,
1442+
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1443+
errmsg("invalid regular expression '%s': %s",file_ident_user+1,errstr)));
1444+
1445+
pfree(wstr);
1446+
*error_p= true;
1447+
return;
1448+
}
1449+
pfree(wstr);
1450+
1451+
wstr=palloc((strlen(ident_user)+1)*sizeof(pg_wchar));
1452+
wlen=pg_mb2wchar_with_len(ident_user,wstr,strlen(ident_user));
1453+
1454+
r=pg_regexec(&re,wstr,wlen,0,NULL,2,matches,0);
1455+
if (r)
1456+
{
1457+
charerrstr[100];
1458+
1459+
if (r!=REG_NOMATCH)
1460+
{
1461+
/* REG_NOMATCH is not an error, everything else is */
1462+
pg_regerror(r,&re,errstr,sizeof(errstr));
1463+
ereport(ERROR,
1464+
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1465+
errmsg("regular expression match for '%s' failed: %s",file_ident_user+1,errstr)));
1466+
*error_p= true;
1467+
}
1468+
1469+
pfree(wstr);
1470+
pg_regfree(&re);
1471+
return;
1472+
}
1473+
pfree(wstr);
1474+
1475+
if ((ofs=strstr(file_pgrole,"\\1"))!=NULL)
1476+
{
1477+
/* substitution of the first argument requested */
1478+
if (matches[1].rm_so<0)
1479+
ereport(ERROR,
1480+
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1481+
errmsg("regular expression '%s' has no subexpressions as requested by backreference in '%s'",
1482+
file_ident_user+1,file_pgrole)));
1483+
/* length: original length minus length of \1 plus length of match plus null terminator */
1484+
regexp_pgrole=palloc0(strlen(file_pgrole)-2+ (matches[1].rm_eo-matches[1].rm_so)+1);
1485+
strncpy(regexp_pgrole,file_pgrole, (ofs-file_pgrole));
1486+
memcpy(regexp_pgrole+strlen(regexp_pgrole),
1487+
ident_user+matches[1].rm_so,
1488+
matches[1].rm_eo-matches[1].rm_so);
1489+
strcat(regexp_pgrole,ofs+2);
1490+
}
1491+
else
1492+
{
1493+
/* no substitution, so copy the match */
1494+
regexp_pgrole=pstrdup(file_pgrole);
1495+
}
1496+
1497+
pg_regfree(&re);
1498+
1499+
/* now check if the username actually matched what the user is trying to connect as */
1500+
if (case_insensitive)
1501+
{
1502+
if (pg_strcasecmp(regexp_pgrole,pg_role)==0)
1503+
*found_p= true;
1504+
}
1505+
else
1506+
{
1507+
if (strcmp(regexp_pgrole,pg_role)==0)
1508+
*found_p= true;
1509+
}
1510+
pfree(regexp_pgrole);
1511+
1512+
return;
14131513
}
14141514
else
14151515
{
1416-
if (strcmp(file_map,usermap_name)==0&&
1417-
strcmp(file_pgrole,pg_role)==0&&
1418-
strcmp(file_ident_user,ident_user)==0)
1419-
*found_p= true;
1516+
/* Not regular expression, so make complete match */
1517+
if (case_insensitive)
1518+
{
1519+
if (pg_strcasecmp(file_pgrole,pg_role)==0&&
1520+
pg_strcasecmp(file_ident_user,ident_user)==0)
1521+
*found_p= true;
1522+
}
1523+
else
1524+
{
1525+
if (strcmp(file_pgrole,pg_role)==0&&
1526+
strcmp(file_ident_user,ident_user)==0)
1527+
*found_p= true;
1528+
}
14201529
}
14211530

14221531
return;

‎src/backend/libpq/pg_ident.conf.sample

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
# pg_hba.conf. SYSTEM-USERNAME is the detected user name of the
1818
# client. PG-USERNAME is the requested PostgreSQL user name. The
1919
# existence of a record specifies that SYSTEM-USERNAME may connect as
20-
# PG-USERNAME. Multiple maps may be specified in this file and used
21-
# by pg_hba.conf.
20+
# PG-USERNAME.
21+
#
22+
# If SYSTEM-USERNAME starts with a slash (/), it will be treated as
23+
# a regular expression. Up to one capture is allowed, and this will
24+
# be replaced in PG-USERNAME for backslash-one (\1) if present.
25+
#
26+
# Multiple maps may be specified in this file and used # by pg_hba.conf.
2227
#
2328
# This file is read on server startup and when the postmaster receives
2429
# a SIGHUP signal. If you edit the file on a running system, you have

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp