diff --git a/testing/tests/ldap/0003-sync-ldap.result b/testing/tests/ldap/0003-sync-ldap.result
index 1bffbba9..9f77e25c 100644
--- a/testing/tests/ldap/0003-sync-ldap.result
+++ b/testing/tests/ldap/0003-sync-ldap.result
@@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
-ETag: "ed58709591152964fd4a584af5b55d79"
-Content-Length: 942
+ETag: "484a5b4172cb19240bad5a30bbcc9ab9"
+Content-Length: 945
Content-Type: text/xml; charset="utf-8"
@@ -44,7 +44,7 @@ Content-Type: text/xml; charset="utf-8"
- /caldav.php/ldap1/
+ /caldav.php/pg_ldap1/
@@ -58,62 +58,62 @@ Content-Type: text/xml; charset="utf-8"
active: >1<
- email: >ldap1@example.com<
- fullname: >LDAP 1<
+ email: >pg_ldap1@example.com<
+ fullname: >pg LDAP 1<
last_used: >NULL<
password: >NULL<
user_no: >1001<
- username: >ldap1<
+ username: >pg_ldap1<
active: >1<
- email: >ldap2@example.com<
- fullname: >LDAP 2<
+ email: >pg_ldap2@example.com<
+ fullname: >pg LDAP 2<
last_used: >NULL<
password: >NULL<
user_no: >1002<
- username: >ldap2<
+ username: >pg_ldap2<
active: >1<
email: >NULL<
- fullname: >ldap_group1<
+ fullname: >pg LDAP Group 1<
last_used: >NULL<
password: >NULL<
user_no: >1003<
- username: >ldap_group1<
+ username: >pg_ldap_group1<
active: >1<
email: >NULL<
- fullname: >ldap_group2<
+ fullname: >pg LDAP Group 2<
last_used: >NULL<
password: >NULL<
user_no: >1004<
- username: >ldap_group2<
+ username: >pg_ldap_group2<
active: >1<
email: >NULL<
- fullname: >ldap_group3<
+ fullname: >pg LDAP Group 3<
last_used: >NULL<
password: >NULL<
user_no: >1005<
- username: >ldap_group3<
+ username: >pg_ldap_group3<
active: >1<
email: >NULL<
- fullname: >ldap_group4<
+ fullname: >pg LDAP Group 4<
last_used: >NULL<
password: >NULL<
user_no: >1006<
- username: >ldap_group4<
+ username: >pg_ldap_group4<
- group_name: >ldap_group1<
- user_name: >ldap1<
+ group_name: >pg_ldap_group1<
+ user_name: >pg_ldap1<
- group_name: >ldap_group2<
- user_name: >ldap2<
+ group_name: >pg_ldap_group2<
+ user_name: >pg_ldap2<
- group_name: >ldap_group3<
+ group_name: >pg_ldap_group3<
user_name: >NULL<
- group_name: >ldap_group4<
+ group_name: >pg_ldap_group4<
user_name: >NULL<
diff --git a/testing/tests/ldap/0003-sync-ldap.test b/testing/tests/ldap/0003-sync-ldap.test
index 777eb789..6ddc171a 100644
--- a/testing/tests/ldap/0003-sync-ldap.test
+++ b/testing/tests/ldap/0003-sync-ldap.test
@@ -2,6 +2,12 @@
# Portions Copyright (c) Best Practical Solutions, LLC
# , licensed under the GPL v2.
#
+# Test where the posixGroup with MemberUid as a plain UID is used.
+#
+# See:
+# - https://ldapwiki.com/wiki/Wiki.jsp?page=PosixGroup
+# - https://ldapwiki.com/wiki/Wiki.jsp?page=MemberUid
+#
BEGINPERL
if ($debug) { $ENV{'LDAP_DEBUG'} = 1 };
@@ -27,47 +33,49 @@ my $users = "ou=users,$base";
my $groups = "ou=groups,$base";
$ldap->add( $base );
-for my $username (qw/ldap1 ldap2/) {
+# pg = posixGroup
+for my $username (qw/pg_ldap1 pg_ldap2/) {
my $dn = "uid=$username,$users";
- (my $cn = $username) =~ s/ldap(\d+)/LDAP $1/;
+ (my $cn = $username) =~ s/_ldap(\d+)/ LDAP $1/;
my $entry = {
cn => $cn,
mail => "$username\@example.com",
uid => $username,
- objectClass => 'User',
+ objectClass => 'person',
userPassword => $username,
modifyTimestamp => 20240203001020,
};
$ldap->add( $dn, attr => [%$entry] );
}
-for my $group (qw/ldap_group1 ldap_group2/) {
- my $dn = "cn=$group,$groups";
- (my $member = $group) =~ s/_group//;
- my $entry = {
- cn => $group,
- objectClass => 'groupofNames',
- memberUid => $member,
- modifyTimestamp => 20240203001020,
- };
- $ldap->add( $dn, attr => [%$entry] );
-}
-
-# Create some empty groups.
-for my $group (qw/ldap_group3 ldap_group4/) {
- my $dn = "cn=$group,$groups";
- my $entry = {
- cn => $group,
- objectClass => 'groupofNames',
- modifyTimestamp => 20240203001020,
- };
- $ldap->add( $dn, attr => [%$entry] );
-}
-
+make_group($ldap, 'pg_ldap_group1', 'pg_ldap1');
+make_group($ldap, 'pg_ldap_group2', 'pg_ldap2');
+make_group($ldap, 'pg_ldap_group3');
+make_group($ldap, 'pg_ldap_group4');
# We need to keep the client around, otherwise the test server will exit.
$evaled{'ldap_client'} = $ldap;
-#sleep 60;
+sleep 60;
+
+sub make_group {
+ my $ldap = shift;
+ my $name = shift;
+ my @users = @_;
+
+ my $dn = "cn=$name,$groups";
+ (my $desc = $name) =~ s/_ldap_group(\d+)/ LDAP Group $1/;
+ my $entry = {
+ cn => $name,
+ objectClass => 'posixGroup',
+ description => $desc,
+ (@users
+ ? (memberUid => [ @users ])
+ : ()
+ ),
+ modifyTimestamp => 20240203001020,
+ };
+ $ldap->add( $dn, attr => [%$entry] );
+}
ENDPERL
SCRIPT=../scripts/cron-sync-ldap.php regression_ldap.host
@@ -77,7 +85,7 @@ TYPE=PROPFIND
URL=http://regression_ldap.host/caldav.php/
HEADER=Content-Type: text/xml
HEADER=Depth: 1
-AUTH=ldap1:ldap1
+AUTH=pg_ldap1:pg_ldap1
HEAD
BEGINDATA
@@ -94,12 +102,11 @@ ENDDATA
QUERY
SELECT active, email, fullname, last_used, password, username, user_no
FROM usr
-WHERE username LIKE 'ldap%'
+WHERE username LIKE 'pg_ldap%'
ORDER BY username;
ENDQUERY
-# Check that ldap1 is a member of ldap_qroup1 and ldap2 is a member of
-# ldap_group2, and that ldap_group3 is empty.
+# Make sure that group membership matches above.
QUERY
SELECT grp_u.username AS group_name, usr_u.username AS user_name
FROM principal AS grp_p
@@ -107,6 +114,6 @@ FROM principal AS grp_p
left join principal AS usr_p ON (group_member.member_id = usr_p.principal_id)
left join usr AS usr_u ON (usr_p.user_no = usr_u.user_no)
left join usr AS grp_u ON (grp_p.user_no = grp_u.user_no)
-WHERE grp_u.username LIKE 'ldap_group%'
+WHERE grp_u.username LIKE 'pg_ldap_group%'
ORDER BY group_name, user_name;
ENDQUERY
diff --git a/testing/tests/ldap/0004-sync-ldap-changes.result b/testing/tests/ldap/0004-sync-ldap-changes.result
index 46ee9b73..dc1ecd1d 100644
--- a/testing/tests/ldap/0004-sync-ldap-changes.result
+++ b/testing/tests/ldap/0004-sync-ldap-changes.result
@@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
-ETag: "ed58709591152964fd4a584af5b55d79"
-Content-Length: 942
+ETag: "484a5b4172cb19240bad5a30bbcc9ab9"
+Content-Length: 945
Content-Type: text/xml; charset="utf-8"
@@ -44,7 +44,7 @@ Content-Type: text/xml; charset="utf-8"
- /caldav.php/ldap1/
+ /caldav.php/pg_ldap1/
@@ -58,65 +58,59 @@ Content-Type: text/xml; charset="utf-8"
active: >1<
- email: >ldap1@example.com<
- fullname: >LDAP 1<
+ email: >pg_ldap1@example.com<
+ fullname: >pg LDAP 1<
last_used: >NULL<
password: >NULL<
- user_no: >1001<
- username: >ldap1<
+ username: >pg_ldap1<
active: >1<
- email: >ldap2@example.com<
- fullname: >LDAP 2<
+ email: >pg_ldap2@example.com<
+ fullname: >pg LDAP 2<
last_used: >NULL<
password: >NULL<
- user_no: >1002<
- username: >ldap2<
+ username: >pg_ldap2<
active: >1<
email: >NULL<
- fullname: >ldap_group1<
+ fullname: >pg_ldap_group1<
last_used: >NULL<
password: >NULL<
- user_no: >1003<
- username: >ldap_group1<
+ username: >pg_ldap_group1<
active: >1<
email: >NULL<
- fullname: >ldap_group2<
+ fullname: >pg_ldap_group2<
last_used: >NULL<
password: >NULL<
- user_no: >1004<
- username: >ldap_group2<
+ username: >pg_ldap_group2<
active: >1<
email: >NULL<
- fullname: >ldap_group3<
+ fullname: >pg_ldap_group3<
last_used: >NULL<
password: >NULL<
- user_no: >1005<
- username: >ldap_group3<
+ username: >pg_ldap_group3<
active: >1<
email: >NULL<
- fullname: >ldap_group4<
+ fullname: >pg_ldap_group4<
last_used: >NULL<
password: >NULL<
- user_no: >1006<
- username: >ldap_group4<
+ username: >pg_ldap_group4<
- group_name: >ldap_group1<
- user_name: >ldap2<
+ group_name: >pg_ldap_group1<
+ user_name: >pg_ldap2<
- group_name: >ldap_group2<
- user_name: >ldap1<
+ group_name: >pg_ldap_group2<
+ user_name: >pg_ldap1<
- group_name: >ldap_group2<
- user_name: >ldap2<
+ group_name: >pg_ldap_group2<
+ user_name: >pg_ldap2<
- group_name: >ldap_group3<
- user_name: >ldap1<
+ group_name: >pg_ldap_group3<
+ user_name: >pg_ldap1<
- group_name: >ldap_group4<
+ group_name: >pg_ldap_group4<
user_name: >NULL<
diff --git a/testing/tests/ldap/0004-sync-ldap-changes.test b/testing/tests/ldap/0004-sync-ldap-changes.test
index 51e4050f..8e6c0ec1 100644
--- a/testing/tests/ldap/0004-sync-ldap-changes.test
+++ b/testing/tests/ldap/0004-sync-ldap-changes.test
@@ -6,16 +6,19 @@
# the previous test to make sure that changes are reflected.
#
# Database will start with:
-# ldap_group1: ldap1
-# ldap_group2: ldap2
-# ldap_group3:
-# ldap_group4: ldap1
+# pg_ldap_group1: pg_ldap1
+# pg_ldap_group2: pg_ldap2
+# pg_ldap_group3:
+# pg_ldap_group4: pg_ldap1
#
# We will change that to:
-# ldap_group1: ldap2
-# ldap_group2: ldap1, ldap2
-# ldap_group3: ldap1
-# ldap_group4:
+# pg_ldap_group1: pg_ldap2
+# pg_ldap_group2: pg_ldap1, pg_ldap2
+# pg_ldap_group3: pg_ldap1
+# pg_ldap_group4:
+#
+# The fullanme for each group should change from "pg LDAP Group $n" to
+# "pg_ldap_group_$n".
#
BEGINPERL
if ($debug) { $ENV{'LDAP_DEBUG'} = 1 };
@@ -42,24 +45,25 @@ my $users = "ou=users,$base";
my $groups = "ou=groups,$base";
$ldap->add( $base );
-for my $username (qw/ldap1 ldap2/) {
+# pg = posixGroup
+for my $username (qw/pg_ldap1 pg_ldap2/) {
my $dn = "uid=$username,$users";
- (my $cn = $username) =~ s/ldap(\d+)/LDAP $1/;
+ (my $cn = $username) =~ s/_ldap(\d+)/LDAP $1/;
my $entry = {
cn => $cn,
mail => "$username\@example.com",
uid => $username,
- objectClass => 'User',
+ objectClass => 'person',
userPassword => $username,
modifyTimestamp => 20240203001020,
};
$ldap->add( $dn, attr => [%$entry] );
}
-make_group($ldap, 'ldap_group1', 'ldap2');
-make_group($ldap, 'ldap_group2', 'ldap1', 'ldap2');
-make_group($ldap, 'ldap_group3', 'ldap1');
-make_group($ldap, 'ldap_group4');
+make_group($ldap, 'pg_ldap_group1', 'pg_ldap2');
+make_group($ldap, 'pg_ldap_group2', 'pg_ldap1', 'pg_ldap2');
+make_group($ldap, 'pg_ldap_group3', 'pg_ldap1');
+make_group($ldap, 'pg_ldap_group4');
# We need to keep the client around, otherwise the test server will exit.
$evaled{'ldap_client'} = $ldap;
@@ -70,12 +74,13 @@ sub make_group {
my $name = shift;
my @users = @_;
- my $dn = "cn=$name,$groups";
- my $entry = {
+ my $dn = "cn=$name,$groups";
+ my $entry = {
cn => $name,
- objectClass => 'groupofNames',
+ objectClass => 'posixGroup',
+ description => $name,
(@users
- ? (memberUid => [ @users ])
+ ? (memberUid => [ @users ])
: ()
),
modifyTimestamp => 20240203001020,
@@ -91,7 +96,7 @@ TYPE=PROPFIND
URL=http://regression_ldap.host/caldav.php/
HEADER=Content-Type: text/xml
HEADER=Depth: 1
-AUTH=ldap1:ldap1
+AUTH=pg_ldap1:pg_ldap1
HEAD
BEGINDATA
@@ -105,14 +110,13 @@ ENDDATA
# Check that a usr record has been created for all users and groups
QUERY
-SELECT active, email, fullname, last_used, password, username, user_no
+SELECT active, email, fullname, last_used, password, username
FROM usr
-WHERE username LIKE 'ldap%'
+WHERE username LIKE 'pg_ldap%'
ORDER BY username;
ENDQUERY
-# Check that ldap1 is a member of ldap_qroup1 and ldap2 is a member of
-# ldap_group2, and that ldap_group3 is empty.
+# Check that group membership matches what was created above.
QUERY
SELECT grp_u.username AS group_name, usr_u.username AS user_name
FROM principal AS grp_p
@@ -120,6 +124,6 @@ FROM principal AS grp_p
left join principal AS usr_p ON (group_member.member_id = usr_p.principal_id)
left join usr AS usr_u ON (usr_p.user_no = usr_u.user_no)
left join usr AS grp_u ON (grp_p.user_no = grp_u.user_no)
-WHERE grp_u.username LIKE 'ldap_group%'
+WHERE grp_u.username LIKE 'pg_ldap_group%'
ORDER BY group_name, user_name;
ENDQUERY
diff --git a/testing/tests/ldap/0005-test-ldap.result b/testing/tests/ldap/0005-test-ldap.result
index e8434050..85167726 100644
--- a/testing/tests/ldap/0005-test-ldap.result
+++ b/testing/tests/ldap/0005-test-ldap.result
@@ -62,6 +62,5 @@ Content-Type: text/xml; charset="utf-8"
fullname: >ldap3<
last_used: >NULL<
password: >NULL<
- user_no: >1007<
username: >ldap3<
diff --git a/testing/tests/ldap/0005-test-ldap.test b/testing/tests/ldap/0005-test-ldap.test
index bf9c0dd3..3cceeb6d 100644
--- a/testing/tests/ldap/0005-test-ldap.test
+++ b/testing/tests/ldap/0005-test-ldap.test
@@ -64,7 +64,7 @@ ENDDATA
# Check that a usr record has been created.
QUERY
-SELECT active, email, fullname, last_used, password, username, user_no
+SELECT active, email, fullname, last_used, password, username
FROM usr
WHERE username = 'ldap3';
ENDQUERY
diff --git a/testing/tests/ldap/0006-test-DN-in-Groups.result b/testing/tests/ldap/0006-test-DN-in-Groups.result
new file mode 100644
index 00000000..353acdc3
--- /dev/null
+++ b/testing/tests/ldap/0006-test-DN-in-Groups.result
@@ -0,0 +1,127 @@
+HTTP/1.1 207 Multi-Status
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
+DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
+ETag: "da739b6b98d20b87833748d890466cde"
+Content-Length: 946
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/
+
+
+
+
+
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/resource1/
+
+
+
+
+
+
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/resource2/
+
+
+
+
+
+
+
+ HTTP/1.1 200 OK
+
+
+
+ /caldav.php/gON_ldap1/
+
+
+
+
+
+
+
+ HTTP/1.1 200 OK
+
+
+
+
+ active: >1<
+ email: >gON_ldap1@example.com<
+ fullname: >gON LDAP 1<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap1<
+
+ active: >1<
+ email: >gON_ldap2@example.com<
+ fullname: >gON LDAP 2<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap2<
+
+ active: >1<
+ email: >gON_ldap3@example.com<
+ fullname: >gON LDAP 3<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap3<
+
+ active: >1<
+ email: >gON_ldap4@example.com<
+ fullname: >gON LDAP 4<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap4<
+
+ active: >1<
+ email: >NULL<
+ fullname: >gON_ldap_group1<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap_group1<
+
+ active: >1<
+ email: >NULL<
+ fullname: >gON_ldap_group2<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap_group2<
+
+ active: >1<
+ email: >NULL<
+ fullname: >gON_ldap_group3<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap_group3<
+
+ active: >1<
+ email: >NULL<
+ fullname: >gON_ldap_group4<
+ last_used: >NULL<
+ password: >NULL<
+ username: >gON_ldap_group4<
+
+ group_name: >gON_ldap_group1<
+ user_name: >NULL<
+
+ group_name: >gON_ldap_group2<
+ user_name: >NULL<
+
+ group_name: >gON_ldap_group3<
+ user_name: >NULL<
+
+ group_name: >gON_ldap_group4<
+ user_name: >NULL<
+
diff --git a/testing/tests/ldap/0006-test-DN-in-Groups.test b/testing/tests/ldap/0006-test-DN-in-Groups.test
new file mode 100644
index 00000000..85fd4078
--- /dev/null
+++ b/testing/tests/ldap/0006-test-DN-in-Groups.test
@@ -0,0 +1,147 @@
+# Copyright (c) 2021-2024 Andrew Ruthven
+# Portions Copyright (c) Best Practical Solutions, LLC
+# , licensed under the GPL v2.
+#
+# Test where the groupOfNames style of groups are used. In this case the
+# DN of each member is stored, typically in a "member" attribute.
+#
+# See:
+# - https://ldapwiki.com/wiki/Wiki.jsp?page=GroupOfNames
+# - https://ldapwiki.com/wiki/Wiki.jsp?page=Member
+#
+BEGINPERL
+if ($debug) { $ENV{'LDAP_DEBUG'} = 1 };
+
+use Net::LDAP::Server::Test;
+use Net::LDAP;
+use IO::Socket::INET;
+
+my $ldap_port = 21394;
+my $ldap_socket = IO::Socket::INET->new(
+ Listen => 5,
+ Proto => 'tcp',
+ Reuse => 1,
+ LocalPort => $ldap_port,
+);
+
+# Keep it around after this block exits.
+$evaled{'ldap_server'}
+ = Net::LDAP::Server::Test->new( $ldap_socket, auto_schema => 1 );
+
+my $ldap = Net::LDAP->new("localhost:$ldap_port")
+ || die "Failed to instantiate Net::LDAP: $!";
+$ldap->bind();
+
+my $base = "dc=example,dc=com";
+my $users = "ou=users,$base";
+my $groups = "ou=groups,$base";
+$ldap->add( $base );
+
+my %users;
+
+# gON = groupOfNames test
+for my $username (qw/gON_ldap1 gON_ldap2/) {
+ my $dn = "uid=$username,$users";
+ (my $cn = $username) =~ s/_ldap(\d+)/ LDAP $1/;
+ $users{$username} = $dn;
+
+ my $entry = {
+ cn => $cn,
+ mail => "$username\@example.com",
+ uid => $username,
+ objectClass => 'person',
+ userPassword => $username,
+ modifyTimestamp => 20240203001020,
+ };
+
+ $ldap->add( $dn, attr => [%$entry] );
+}
+
+# Users where the DN does not have uid as an RDN.
+for my $username (qw/gON_ldap3 gON_ldap4/) {
+ (my $cn = $username) =~ s/_ldap(\d+)/ LDAP $1/;
+ my $dn = "cn=$cn,$users";
+ $users{$username} = $dn;
+
+ my $entry = {
+ cn => $cn,
+ mail => "$username\@example.com",
+ uid => $username,
+ objectClass => 'person',
+ userPassword => $username,
+ modifyTimestamp => 20240203001020,
+ };
+
+ $ldap->add( $dn, attr => [%$entry] );
+}
+
+
+make_group($ldap, 'gON_ldap_group1', $users{gON_ldap1});
+make_group($ldap, 'gON_ldap_group2', $users{gON_ldap1}, $users{gON_ldap2},
+ $users{gON_ldap4});
+make_group($ldap, 'gON_ldap_group3', $users{gON_ldap1}, $users{gON_ldap3});
+make_group($ldap, 'gON_ldap_group4');
+
+# We need to keep the client around, otherwise the test server will exit.
+$evaled{'ldap_client'} = $ldap;
+#sleep 60;
+
+sub make_group {
+ my $ldap = shift;
+ my $name = shift;
+ my @users = @_;
+
+ my $dn = "cn=$name,$groups";
+ my $entry = {
+ cn => $name,
+ objectClass => 'groupOfNames',
+ (@users
+ ? (member => [ @users ])
+ : ()
+ ),
+ modifyTimestamp => 20240203001020,
+ };
+ $ldap->add( $dn, attr => [%$entry] );
+}
+
+ENDPERL
+
+SCRIPT=../scripts/cron-sync-ldap.php regression_ldap.host
+
+# Testing logging in as one of the users - should work.
+TYPE=PROPFIND
+URL=http://regression_ldap.host/caldav.php/
+HEADER=Content-Type: text/xml
+HEADER=Depth: 1
+AUTH=gON_ldap1:gON_ldap1
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+ENDDATA
+
+
+# Check that a usr record has been created for all users and groups
+QUERY
+SELECT active, email, fullname, last_used, password, username
+FROM usr
+WHERE username LIKE 'gON_ldap%'
+ORDER BY username;
+ENDQUERY
+
+# Check group membership matches above.
+QUERY
+SELECT grp_u.username AS group_name, usr_u.username AS user_name
+FROM principal AS grp_p
+ left join group_member ON (grp_p.principal_id = group_member.group_id)
+ left join principal AS usr_p ON (group_member.member_id = usr_p.principal_id)
+ left join usr AS usr_u ON (usr_p.user_no = usr_u.user_no)
+ left join usr AS grp_u ON (grp_p.user_no = grp_u.user_no)
+WHERE grp_u.username LIKE 'gON_ldap_group%'
+ORDER BY group_name, user_name;
+ENDQUERY