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

Commit83aaac4

Browse files
committed
Allow custom search filters to be configured for LDAP auth
Before, only filters of the form "(<ldapsearchattribute>=<user>)"could be used to search an LDAP server. Introduce ldapsearchfilterso that more general filters can be configured using patterns, like"(|(uid=$username)(mail=$username))" and "(&(uid=$username)(objectClass=posixAccount))". Also allow search filters to be includedin an LDAP URL.Author: Thomas MunroReviewed-By: Peter Eisentraut, Mark Cave-Ayland, Magnus HaganderDiscussion:https://postgr.es/m/CAEepm=0XTkYvMci0WRubZcf_1am8=gP=7oJErpsUfRYcKF2gwg@mail.gmail.com
1 parent35e1568 commit83aaac4

File tree

4 files changed

+110
-25
lines changed

4 files changed

+110
-25
lines changed

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

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,20 +1507,34 @@ omicron bryanh guest1
15071507
</para>
15081508
</listitem>
15091509
</varlistentry>
1510+
<varlistentry>
1511+
<term><literal>ldapsearchfilter</literal></term>
1512+
<listitem>
1513+
<para>
1514+
The search filter to use when doing search+bind authentication.
1515+
Occurrences of <literal>$username</literal> will be replaced with the
1516+
user name. This allows for more flexible search filters than
1517+
<literal>ldapsearchattribute</literal>.
1518+
</para>
1519+
</listitem>
1520+
</varlistentry>
15101521
<varlistentry>
15111522
<term><literal>ldapurl</literal></term>
15121523
<listitem>
15131524
<para>
15141525
An RFC 4516 LDAP URL. This is an alternative way to write some of the
15151526
other LDAP options in a more compact and standard form. The format is
15161527
<synopsis>
1517-
ldap://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>]]]
1528+
ldap://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replaceable>basedn</replaceable>[?[<replaceable>attribute</replaceable>][?[<replaceable>scope</replaceable>][?[<replaceable>filter</replaceable>]]]]
15181529
</synopsis>
15191530
<replaceable>scope</replaceable> must be one
15201531
of <literal>base</literal>, <literal>one</literal>, <literal>sub</literal>,
1521-
typically the latter. Only one attribute is used, and some other
1522-
components of standard LDAP URLs such as filters and extensions are
1523-
not supported.
1532+
typically the last. <replaceable>attribute</replaceable> can
1533+
nominate a single attribute, in which case it is used as a value for
1534+
<literal>ldapsearchattribute</literal>. If
1535+
<replaceable>attribute</replaceable> is empty then
1536+
<replaceable>filter</replaceable> can be used as a value for
1537+
<literal>ldapsearchfilter</literal>.
15241538
</para>
15251539

15261540
<para>
@@ -1549,6 +1563,17 @@ ldap://<replaceable>host</replaceable>[:<replaceable>port</replaceable>]/<replac
15491563
for search+bind.
15501564
</para>
15511565

1566+
<para>
1567+
When using search+bind mode, the search can be performed using a single
1568+
attribute specified with <literal>ldapsearchattribute</literal>, or using
1569+
a custom search filter specified with
1570+
<literal>ldapsearchfilter</literal>.
1571+
Specifying <literal>ldapsearchattribute=foo</literal> is equivalent to
1572+
specifying <literal>ldapsearchfilter="(foo=$username)"</literal>. If neither
1573+
option is specified the default is
1574+
<literal>ldapsearchattribute=uid</literal>.
1575+
</para>
1576+
15521577
<para>
15531578
Here is an example for a simple-bind LDAP configuration:
15541579
<programlisting>
@@ -1584,6 +1609,16 @@ host ... ldap ldapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"
15841609
same URL format, so it will be easier to share the configuration.
15851610
</para>
15861611

1612+
<para>
1613+
Here is an example for a search+bind configuration that uses
1614+
<literal>ldapsearchfilter</literal> instead of
1615+
<literal>ldapsearchattribute</literal> to allow authentication by
1616+
user ID or email address:
1617+
<programlisting>
1618+
host ... ldap ldapserver=ldap.example.net ldapbasedn="dc=example, dc=net" ldapsearchfilter="(|(uid=$username)(mail=$username))"
1619+
</programlisting>
1620+
</para>
1621+
15871622
<tip>
15881623
<para>
15891624
Since LDAP often uses commas and spaces to separate the different

‎src/backend/libpq/auth.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,6 +2394,34 @@ InitializeLDAPConnection(Port *port, LDAP **ldap)
23942394
returnSTATUS_OK;
23952395
}
23962396

2397+
/* Placeholders recognized by FormatSearchFilter. For now just one. */
2398+
#defineLPH_USERNAME "$username"
2399+
#defineLPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
2400+
2401+
/*
2402+
* Return a newly allocated C string copied from "pattern" with all
2403+
* occurrences of the placeholder "$username" replaced with "user_name".
2404+
*/
2405+
staticchar*
2406+
FormatSearchFilter(constchar*pattern,constchar*user_name)
2407+
{
2408+
StringInfoDataoutput;
2409+
2410+
initStringInfo(&output);
2411+
while (*pattern!='\0')
2412+
{
2413+
if (strncmp(pattern,LPH_USERNAME,LPH_USERNAME_LEN)==0)
2414+
{
2415+
appendStringInfoString(&output,user_name);
2416+
pattern+=LPH_USERNAME_LEN;
2417+
}
2418+
else
2419+
appendStringInfoChar(&output,*pattern++);
2420+
}
2421+
2422+
returnoutput.data;
2423+
}
2424+
23972425
/*
23982426
* Perform LDAP authentication
23992427
*/
@@ -2437,7 +2465,7 @@ CheckLDAPAuth(Port *port)
24372465
char*filter;
24382466
LDAPMessage*search_message;
24392467
LDAPMessage*entry;
2440-
char*attributes[2];
2468+
char*attributes[]= {LDAP_NO_ATTRS,NULL };
24412469
char*dn;
24422470
char*c;
24432471
intcount;
@@ -2479,13 +2507,13 @@ CheckLDAPAuth(Port *port)
24792507
returnSTATUS_ERROR;
24802508
}
24812509

2482-
/*Fetch just one attribute, else *all* attributes are returned */
2483-
attributes[0]=port->hba->ldapsearchattribute ?port->hba->ldapsearchattribute :"uid";
2484-
attributes[1]=NULL;
2485-
2486-
filter=psprintf("(%s=%s)",
2487-
attributes[0],
2488-
port->user_name);
2510+
/*Build a custom filter or a single attribute filter? */
2511+
if (port->hba->ldapsearchfilter)
2512+
filter=FormatSearchFilter(port->hba->ldapsearchfilter,port->user_name);
2513+
elseif (port->hba->ldapsearchattribute)
2514+
filter=psprintf("(%s=%s)",port->hba->ldapsearchattribute,port->user_name);
2515+
else
2516+
filter=psprintf("(uid=%s)",port->user_name);
24892517

24902518
r=ldap_search_s(ldap,
24912519
port->hba->ldapbasedn,

‎src/backend/libpq/hba.c

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,22 +1505,24 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
15051505
/*
15061506
* LDAP can operate in two modes: either with a direct bind, using
15071507
* ldapprefix and ldapsuffix, or using a search+bind, using
1508-
* ldapbasedn, ldapbinddn, ldapbindpasswd and ldapsearchattribute.
1509-
* Disallow mixing these parameters.
1508+
* ldapbasedn, ldapbinddn, ldapbindpasswd and one of
1509+
* ldapsearchattribute or ldapsearchfilter. Disallow mixing these
1510+
* parameters.
15101511
*/
15111512
if (parsedline->ldapprefix||parsedline->ldapsuffix)
15121513
{
15131514
if (parsedline->ldapbasedn||
15141515
parsedline->ldapbinddn||
15151516
parsedline->ldapbindpasswd||
1516-
parsedline->ldapsearchattribute)
1517+
parsedline->ldapsearchattribute||
1518+
parsedline->ldapsearchfilter)
15171519
{
15181520
ereport(elevel,
15191521
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1520-
errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix"),
1522+
errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute,ldapsearchfilteror ldapurl together with ldapprefix"),
15211523
errcontext("line %d of configuration file \"%s\"",
15221524
line_num,HbaFileName)));
1523-
*err_msg="cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, or ldapurl together with ldapprefix";
1525+
*err_msg="cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute,ldapsearchfilteror ldapurl together with ldapprefix";
15241526
returnNULL;
15251527
}
15261528
}
@@ -1534,6 +1536,22 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
15341536
*err_msg="authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set";
15351537
returnNULL;
15361538
}
1539+
1540+
/*
1541+
* When using search+bind, you can either use a simple attribute
1542+
* (defaulting to "uid") or a fully custom search filter. You can't
1543+
* do both.
1544+
*/
1545+
if (parsedline->ldapsearchattribute&&parsedline->ldapsearchfilter)
1546+
{
1547+
ereport(elevel,
1548+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1549+
errmsg("cannot use ldapsearchattribute together with ldapsearchfilter"),
1550+
errcontext("line %d of configuration file \"%s\"",
1551+
line_num,HbaFileName)));
1552+
*err_msg="cannot use ldapsearchattribute together with ldapsearchfilter";
1553+
returnNULL;
1554+
}
15371555
}
15381556

15391557
if (parsedline->auth_method==uaRADIUS)
@@ -1729,14 +1747,7 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
17291747
hbaline->ldapsearchattribute=pstrdup(urldata->lud_attrs[0]);/* only use first one */
17301748
hbaline->ldapscope=urldata->lud_scope;
17311749
if (urldata->lud_filter)
1732-
{
1733-
ereport(elevel,
1734-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1735-
errmsg("filters not supported in LDAP URLs")));
1736-
*err_msg="filters not supported in LDAP URLs";
1737-
ldap_free_urldesc(urldata);
1738-
return false;
1739-
}
1750+
hbaline->ldapsearchfilter=pstrdup(urldata->lud_filter);
17401751
ldap_free_urldesc(urldata);
17411752
#else/* not OpenLDAP */
17421753
ereport(elevel,
@@ -1788,6 +1799,11 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
17881799
REQUIRE_AUTH_OPTION(uaLDAP,"ldapsearchattribute","ldap");
17891800
hbaline->ldapsearchattribute=pstrdup(val);
17901801
}
1802+
elseif (strcmp(name,"ldapsearchfilter")==0)
1803+
{
1804+
REQUIRE_AUTH_OPTION(uaLDAP,"ldapsearchfilter","ldap");
1805+
hbaline->ldapsearchfilter=pstrdup(val);
1806+
}
17911807
elseif (strcmp(name,"ldapbasedn")==0)
17921808
{
17931809
REQUIRE_AUTH_OPTION(uaLDAP,"ldapbasedn","ldap");
@@ -2266,6 +2282,11 @@ gethba_options(HbaLine *hba)
22662282
CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
22672283
hba->ldapsearchattribute));
22682284

2285+
if (hba->ldapsearchfilter)
2286+
options[noptions++]=
2287+
CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
2288+
hba->ldapsearchfilter));
2289+
22692290
if (hba->ldapscope)
22702291
options[noptions++]=
22712292
CStringGetTextDatum(psprintf("ldapscope=%d",hba->ldapscope));

‎src/include/libpq/hba.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ typedef struct HbaLine
8080
char*ldapbinddn;
8181
char*ldapbindpasswd;
8282
char*ldapsearchattribute;
83+
char*ldapsearchfilter;
8384
char*ldapbasedn;
8485
intldapscope;
8586
char*ldapprefix;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp