Merge ~sergiodj/ubuntu/+source/openldap:mre-2.5.12-JAMMY into ubuntu/+source/openldap:ubuntu/jammy-devel

Proposed by Sergio Durigan Junior
Status: Merged
Merged at revision: c185122b7e63f18dfba2f59df2b30af3d837bc63
Proposed branch: ~sergiodj/ubuntu/+source/openldap:mre-2.5.12-JAMMY
Merge into: ubuntu/+source/openldap:ubuntu/jammy-devel
Diff against target: 1976 lines (+489/-393)
36 files modified
CHANGES (+30/-0)
build/dir.mk (+5/-5)
build/version.var (+4/-4)
contrib/slapd-modules/vc/vc.c (+2/-4)
debian/changelog (+14/-0)
debian/patches/series (+0/-1)
dev/null (+0/-274)
doc/guide/admin/guide.html (+1/-1)
doc/man/man3/ldap_get_option.3 (+22/-1)
doc/man/man5/slapd-config.5 (+2/-3)
doc/man/man5/slapd.conf.5 (+2/-3)
include/ldap_pvt.h (+2/-2)
libraries/libldap/ldif.c (+5/-0)
libraries/libldap/result.c (+10/-4)
libraries/libldap/tls_o.c (+4/-0)
servers/slapd/back-asyncmeta/add.c (+1/-0)
servers/slapd/back-asyncmeta/config.c (+5/-3)
servers/slapd/back-asyncmeta/meta_result.c (+11/-4)
servers/slapd/back-asyncmeta/search.c (+1/-0)
servers/slapd/back-ldap/config.c (+5/-3)
servers/slapd/back-mdb/monitor.c (+2/-1)
servers/slapd/back-meta/config.c (+17/-13)
servers/slapd/back-sql/search.c (+105/-18)
servers/slapd/bconfig.c (+24/-7)
servers/slapd/connection.c (+10/-8)
servers/slapd/daemon.c (+13/-1)
servers/slapd/overlays/dynlist.c (+7/-4)
servers/slapd/overlays/pcache.c (+3/-2)
servers/slapd/overlays/ppolicy.c (+12/-8)
servers/slapd/overlays/syncprov.c (+1/-0)
servers/slapd/overlays/translucent.c (+23/-1)
servers/slapd/proto-slap.h (+1/-0)
servers/slapd/syncrepl.c (+122/-18)
tests/data/dynlist.out (+4/-0)
tests/scripts/test034-translucent (+8/-0)
tests/scripts/test044-dynlist (+11/-0)
Reviewer Review Type Date Requested Status
Athos Ribeiro (community) Approve
Canonical Server Pending
git-ubuntu bot Pending
Canonical Server packageset reviewers Pending
Review via email: mp+424587@code.launchpad.net

This proposal supersedes a proposal from 2022-06-10.

Description of the change

This is the (first) MRE for OpenLDAP 2.5.12 targeting Jammy.

As discussed previously (see https://code.launchpad.net/~sergiodj/ubuntu/+source/openldap/+git/openldap/+merge/424341), I decided to approach this MRE using the same procedure we use for the postgresql MREs. IOW: fetch the DFSG-compatible tarball from upstream and update our source package directly, without using Debian's OpenLDAP package and doing a regular merge.

This has a few benefits. The first is that the MRE is much easier to prepare, and doesn't involve any complicated rebases. The second benefit is that we will have more freedom to adopt only the packaging changes that we deem necessary from Debian, instead of adopting everything and then worrying about whether we want to have them MRE'd or not. The third is that the changelog entry becomes simpler: we just have to write about the upstream changes, always.

Just as a reminder, upstream considers the 2.5.x series to be their LTS, so every minor release contains only bugfixes and no new features. This is perfect for MREs, of course.

You can take a look at upstream's CHANGES file if you'd like to check the bugs that have been fixed by this release:

https://git.openldap.org/openldap/openldap/-/blob/2bda1fa98fbcedc6cd5995ea905427b8bef89f9d/CHANGES

It's always a somewhat subjective task to come up with good/important bugs to mention in the changelog entry for an MRE. For now, the policy I'm adopting is to mention only high priority bugs and CVE fixes in the changelog entry (thanks Athos for the suggestion). Other than that, everything else is pretty much as you would expect from an MRE.

There is a bileto ticket where you can find a PPA with the built package plus all of the dep8 results for OpenLDAP's reverse deps:

https://bileto.ubuntu.com/#/ticket/4868

Do note that currently the following packages' dep8 tests are failing:

- apache2 is failing on all architectures due to an unrelated problem when running some tests. I will report a separate bug. migration-reference/0 also fails.

- cyrus-imapd is failing on ppc64el, but that's because the package was never published on Jammy due to a FTBFS.

- sudo is failing on armhf, but that's also something that was happening before and its migration-reference/0 also fails.

- kopanocore is failing on s390x. Likewise, its migration-reference/0 is also failing.

I will post the dep8 test results for the OpenLDAP package as soon as I have them.

To post a comment you must log in.
Revision history for this message
Sergio Durigan Junior (sergiodj) wrote : Posted in a previous version of this proposal

The dep8 tests have finished on Bileto.

- As expected, apache2 is failing. That's OK, as I explained above.

- cyrus-imapd is failing on ppc64el, but that's because the package was never published on Jammy due to a FTBFS.

- sudo is failing on armhf, but that's also something that was happening before and its migration-reference/0 also fails.

- kopanocore is failing on s390x. Likewise, its migration-reference/0 is also failing.

Other than that, everything else has passed. This is good for review/upload.

Revision history for this message
Sergio Durigan Junior (sergiodj) wrote : Posted in a previous version of this proposal

Something I forgot to mention: this merge was done against the pkg/import/2.5.12+dfsg-1 tag, not debian/sid. This was done because Debian's 2.5.12+dfsg-2 version includes a fix that is not necessary for Ubuntu, because Ubuntu is already carrying a fix for debconf and Debian isn't. For more details, you can check https://bugs.launchpad.net/ubuntu/+source/debhelper/+bug/1959054.

Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote : Posted in a previous version of this proposal

This LGTM.

There is one space in line 2 of the changelog that would be nice to remove before uploading.

As for the changelog entries, I understand you put a lot of effort into filtering what should be added. Still, I believe we could come up with some algorithm for that. For instance, only including mentions to CVEs or bugs set to high in the upstream bug tracker. All the entries are in the upstream changelog anyway and it is being referenced in the package chagelog.

I also see you decided to pick debian's 2.5.12+dfsg-1 release instead of 2.5.12+dfsg-2 as a base for the merge.
It was nice of you to reduce the amount of changes introduced in the MRE. You also explained offline that this specific change was only needed in debian since Ubuntu already has a fix in debconf. However, the next steps here would be to move this changes from Ubuntu to Debian to consolidate them there before the next MRE to avoid complications in a possible following merge.

Finally, since this was a merge from a specific Debian commit, I was wondering why you decided not to include a remaining changes section. It should be fine not to have one since this is not a traditional merge, but an MRE. Still, it would be nice to document "how developers should do things" in the MRE documentation page.

review: Approve
Revision history for this message
Sergio Durigan Junior (sergiodj) wrote : Posted in a previous version of this proposal
Download full text (3.5 KiB)

> This LGTM.

Thanks for the review, Athos.

> There is one space in line 2 of the changelog that would be nice to remove before uploading.

Ops, indeed. Fixed.

> As for the changelog entries, I understand you put a lot of effort
> into filtering what should be added. Still, I believe we could come up
> with some algorithm for that. For instance, only including mentions to
> CVEs or bugs set to high in the upstream bug tracker. All the entries
> are in the upstream changelog anyway and it is being referenced in the
> package chagelog.

Yes, agreed. I thought about only mentioning the CVE issue, but that's
moot since it's already been addressed by the Security team in a
previous upload. I revisited the bugs fixed in this release and the
only one marked as high priority is this:

  https://bugs.openldap.org/show_bug.cgi?id=9584

I don't know if upstream worries too much about setting bug priorities
or not, so maybe we can't rely on this parameter.

I don't have a good answer for how to approach this problem right now.
For that reason, I'm going to postpone uploading this package until next
week.

> I also see you decided to pick debian's 2.5.12+dfsg-1 release instead of 2.5.12+dfsg-2 as a base for the merge.
> It was nice of you to reduce the amount of changes introduced in the
> MRE. You also explained offline that this specific change was only
> needed in debian since Ubuntu already has a fix in debconf. However,
> the next steps here would be to move this changes from Ubuntu to
> Debian to consolidate them there before the next MRE to avoid
> complications in a possible following merge.

Absolutely.

Dave Jones is already taking care of that here:

  https://salsa.debian.org/pkg-debconf/debconf/-/merge_requests/10
  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1006147

> Finally, since this was a merge from a specific Debian commit, I was
> wondering why you decided not to include a remaining changes
> section. It should be fine not to have one since this is not a
> traditional merge, but an MRE. Still, it would be nice to document
> "how developers should do things" in the MRE documentation page.

Thanks for bringing this up. This prompted me into thinking more about
the changelog entry, and then I realized a misconception I was having
about the MRE.

Initially I thought that openldap was "special" because, aside from
doing the MRE the "standard way" (i.e., just grab the upstream tarball
and update the source package by hand with it), we could also merge the
package from Debian because they are also planning to stick with the
2.5.x series.

However, I noticed that openldap 2.5.x is actually just postgresql-14
right now: both packages get uploaded to Debian unstable as soon as
there's a new upstream microrelease. For postgresql-14, we do our MREs
*without* merging the Debian package. So I now believe that we should
do the same for openldap.

This would actually have a few benefits. The first is that the MRE is
much easier: we really just need to grab the tarball and explode it on
top of the current version of the source package, then update the
patches and write a changelog entry for it. The second benefit is that
we won't need...

Read more...

Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote : Posted in a previous version of this proposal

Ack!

Thanks for the thorough reply :)

Revision history for this message
git-ubuntu bot (git-ubuntu-bot) wrote : Posted in a previous version of this proposal

Approvers: sergiodj, athos-ribeiro
Uploaders: sergiodj, athos-ribeiro
MP auto-approved

review: Approve
Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote :

Given the previous review and exchanges, this got simpler to review.

The changelog looks nicer, BTW.

LGTM! Thanks, Sergio :)

review: Approve
Revision history for this message
Sergio Durigan Junior (sergiodj) wrote :

Thanks, Athos.

Uploaded:

$ dput openldap_2.5.12+dfsg-0ubuntu0.22.04.1_source.changes
Trying to upload package to ubuntu
Checking signature on .changes
gpg: /home/sergio/work/openldap/openldap_2.5.12+dfsg-0ubuntu0.22.04.1_source.changes: Valid signature from 106DA1C8C3CBBF14
Checking signature on .dsc
gpg: /home/sergio/work/openldap/openldap_2.5.12+dfsg-0ubuntu0.22.04.1.dsc: Valid signature from 106DA1C8C3CBBF14
Package includes an .orig.tar.gz file although the debian revision suggests
that it might not be required. Multiple uploads of the .orig.tar.gz may be
rejected by the upload queue management software.
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading openldap_2.5.12+dfsg-0ubuntu0.22.04.1.dsc: done.
  Uploading openldap_2.5.12+dfsg.orig.tar.gz: done.
  Uploading openldap_2.5.12+dfsg-0ubuntu0.22.04.1.debian.tar.xz: done.
  Uploading openldap_2.5.12+dfsg-0ubuntu0.22.04.1_source.buildinfo: done.
  Uploading openldap_2.5.12+dfsg-0ubuntu0.22.04.1_source.changes: done.
Successfully uploaded packages.

I'll also keep an eye on the dep8 results from bileto, since they're an important part of the MRE.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/CHANGES b/CHANGES
2index c9ce92c..d8092be 100644
3--- a/CHANGES
4+++ b/CHANGES
5@@ -1,5 +1,35 @@
6 OpenLDAP 2.5 Change Log
7
8+OpenLDAP 2.5.12 Release (2022/05/04)
9+ Fixed libldap to drop connection when non-LDAP data is received (ITS#9803)
10+ Fixed libldap to allow newlines at end of included file (ITS#9811)
11+ Fixed slapd slaptest conversion of olcLastBind (ITS#9808)
12+ Fixed slapd usage of thread local counters (ITS#9789)
13+ Fixed slapd to clear runqueue task correctly (ITS#9785)
14+ Fixed slapd idletimeout handling (ITS#9820)
15+ Fixed slapd bconfig locking for cn=config replication (ITS#9584)
16+ Fixed slapd syncrepl handling of new sessions (ITS#9584)
17+ Fixed slapd to clear connections on bind (ITS#9799)
18+ Fixed slapd to correctly advance connections index (ITS#9831)
19+ Fixed slapd syncrepl ODSEE replication of unknown attr (ITS#9801)
20+ Fixed slapd-asyncmeta memory leak in keepalive setting (ITS#9802)
21+ Fixed slapd-ldap memory leak in keepalive setting (ITS#9802)
22+ Fixed slapd-meta SEGV on config rewrite (ITS#9802)
23+ Fixed slapd-meta ordering on config rewrite (ITS#9802)
24+ Fixed slapd-meta memory leak in keepalive setting (ITS#9802)
25+ Fixed slapd-monitor SEGV on shutdown (ITS#9809)
26+ Fixed slapd-sql to properly escape filter value (ITS#9815)
27+ Fixed slapo-dynlist dynamic group regression (ITS#9825)
28+ Fixed slapo-pcache SEGV on shutdown (ITS#9809)
29+ Fixed slapo-ppolicy operation handling to be consistent (ITS#9794)
30+ Fixed slapo-translucent to correctly duplicate substring filters (ITS#9818)
31+ Build Environment
32+ Fix compilation with openssl exclusions (ITS#9791)
33+ Fix warnings from make jobserver (ITS#9788)
34+ Fix compiliation with certain versions of gcc (ITS#9790)
35+ Documentation
36+ Fixed slapd.conf(5)/slapd-config(5) syncrepl sizelimit/timelimit documentation (ITS#9804)
37+
38 OpenLDAP 2.5.11 Release (2022/01/20)
39 Fix broken build release variable
40
41diff --git a/build/dir.mk b/build/dir.mk
42index a73c6b8..e42406b 100644
43--- a/build/dir.mk
44+++ b/build/dir.mk
45@@ -21,7 +21,7 @@ all-common: FORCE
46 @echo "Making all in `$(PWD)`"
47 @for i in $(SUBDIRS) $(ALLDIRS); do \
48 echo " Entering subdirectory $$i"; \
49- ( cd $$i && $(MAKE) $(MFLAGS) all ); \
50+ ( cd $$i && $(MAKE) all ); \
51 if test $$? != 0 ; then exit 1; fi ; \
52 echo " "; \
53 done
54@@ -30,7 +30,7 @@ install-common: FORCE
55 @echo "Making install in `$(PWD)`"
56 @for i in $(SUBDIRS) $(INSTALLDIRS); do \
57 echo " Entering subdirectory $$i"; \
58- ( cd $$i && $(MAKE) $(MFLAGS) install ); \
59+ ( cd $$i && $(MAKE) install ); \
60 if test $$? != 0 ; then exit 1; fi ; \
61 echo " "; \
62 done
63@@ -39,7 +39,7 @@ clean-common: FORCE
64 @echo "Making clean in `$(PWD)`"
65 @for i in $(SUBDIRS) $(CLEANDIRS); do \
66 echo " Entering subdirectory $$i"; \
67- ( cd $$i && $(MAKE) $(MFLAGS) clean ); \
68+ ( cd $$i && $(MAKE) clean ); \
69 if test $$? != 0 ; then exit 1; fi ; \
70 echo " "; \
71 done
72@@ -48,7 +48,7 @@ veryclean-common: FORCE
73 @echo "Making veryclean in `$(PWD)`"
74 @for i in $(SUBDIRS) $(CLEANDIRS); do \
75 echo " Entering subdirectory $$i"; \
76- ( cd $$i && $(MAKE) $(MFLAGS) veryclean ); \
77+ ( cd $$i && $(MAKE) veryclean ); \
78 if test $$? != 0 ; then exit 1; fi ; \
79 echo " "; \
80 done
81@@ -57,7 +57,7 @@ depend-common: FORCE
82 @echo "Making depend in `$(PWD)`"
83 @for i in $(SUBDIRS) $(DEPENDDIRS); do \
84 echo " Entering subdirectory $$i"; \
85- ( cd $$i && $(MAKE) $(MFLAGS) depend ); \
86+ ( cd $$i && $(MAKE) depend ); \
87 if test $$? != 0 ; then exit 1; fi ; \
88 echo " "; \
89 done
90diff --git a/build/version.var b/build/version.var
91index e547d3d..df94973 100644
92--- a/build/version.var
93+++ b/build/version.var
94@@ -15,9 +15,9 @@
95 ol_package=OpenLDAP
96 ol_major=2
97 ol_minor=5
98-ol_patch=11
99-ol_api_inc=20511
100+ol_patch=12
101+ol_api_inc=20512
102 ol_api_current=1
103-ol_api_revision=6
104+ol_api_revision=7
105 ol_api_age=1
106-ol_release_date="2022/01/20"
107+ol_release_date="2022/05/04"
108diff --git a/contrib/slapd-modules/vc/vc.c b/contrib/slapd-modules/vc/vc.c
109index 2039556..0760af2 100644
110--- a/contrib/slapd-modules/vc/vc.c
111+++ b/contrib/slapd-modules/vc/vc.c
112@@ -289,16 +289,14 @@ vc_exop(
113 goto done;
114 }
115 conn->refcnt++;
116+ operation_counter_init( conn->op, op->o_threadctx );
117 ldap_pvt_thread_mutex_unlock( &vc_mutex );
118
119 } else {
120- void *thrctx;
121-
122 conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) );
123 conn->refcnt = 1;
124
125- thrctx = ldap_pvt_thread_pool_context();
126- connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 );
127+ connection_fake_init2( &conn->connbuf, &conn->opbuf, op->o_threadctx, 0 );
128 conn->op = &conn->opbuf.ob_op;
129 snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ),
130 "%s VERIFYCREDENTIALS", op->o_log_prefix );
131diff --git a/debian/changelog b/debian/changelog
132index 8fc3770..4c4b66d 100644
133--- a/debian/changelog
134+++ b/debian/changelog
135@@ -1,3 +1,17 @@
136+openldap (2.5.12+dfsg-0ubuntu0.22.04.1) jammy; urgency=medium
137+
138+ * New upstream version (LP: #1977627).
139+ - Fixed slapd syncrepl handling of new sessions (ITS#9584)
140+ - Fixed slapd-sql to properly escape filter value (ITS#9815)
141+ (CVE-2022-29155)
142+ [ Already included in 2.5.11+dfsg-1~exp1ubuntu3.1 ]
143+ - More details about this release can be found at:
144+ https://git.openldap.org/openldap/openldap/-/blob/2bda1fa98fbcedc6cd5995ea905427b8bef89f9d/CHANGES
145+ * d/p/CVE-2022-29155.patch: Dropped patch; included in this new upstream
146+ version.
147+
148+ -- Sergio Durigan Junior <sergio.durigan@canonical.com> Mon, 13 Jun 2022 13:19:52 -0400
149+
150 openldap (2.5.11+dfsg-1~exp1ubuntu3.1) jammy-security; urgency=medium
151
152 * SECURITY UPDATE: SQL injection in experimental back-sql backend
153diff --git a/debian/patches/CVE-2022-29155.patch b/debian/patches/CVE-2022-29155.patch
154deleted file mode 100644
155index 5f81868..0000000
156--- a/debian/patches/CVE-2022-29155.patch
157+++ /dev/null
158@@ -1,274 +0,0 @@
159-From 40f3ae4f5c9a8baf75b237220f62c436a571d66e Mon Sep 17 00:00:00 2001
160-From: Howard Chu <hyc@openldap.org>
161-Date: Wed, 23 Mar 2022 12:43:31 +0000
162-Subject: [PATCH] ITS#9815 slapd-sql: escape filter values
163-
164-Escape filter values to slapd-sql (CVE-2022-29155)
165----
166- servers/slapd/back-sql/search.c | 123 +++++++++++++++++++++++++++-----
167- 1 file changed, 105 insertions(+), 18 deletions(-)
168-
169-diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c
170-index 2168a1553b..d4177f6292 100644
171---- a/servers/slapd/back-sql/search.c
172-+++ b/servers/slapd/back-sql/search.c
173-@@ -63,6 +63,38 @@ static void send_paged_response(
174- ID *lastid );
175- #endif /* ! BACKSQL_ARBITRARY_KEY */
176-
177-+/* Look for chars that need to be escaped, return count of them.
178-+ * If out is non-NULL, copy escape'd val to it.
179-+ */
180-+static int
181-+backsql_val_escape( Operation *op, struct berval *in, struct berval *out )
182-+{
183-+ char *ptr, *end;
184-+ int q = 0;
185-+
186-+ ptr = in->bv_val;
187-+ end = ptr + in->bv_len;
188-+ while (ptr < end) {
189-+ if ( *ptr == '\'' )
190-+ q++;
191-+ ptr++;
192-+ }
193-+ if ( q && out ) {
194-+ char *dst;
195-+ out->bv_len = in->bv_len + q;
196-+ out->bv_val = op->o_tmpalloc( out->bv_len + 1, op->o_tmpmemctx );
197-+ ptr = in->bv_val;
198-+ dst = out->bv_val;
199-+ while (ptr < end ) {
200-+ if ( *ptr == '\'' )
201-+ *dst++ = '\'';
202-+ *dst++ = *ptr++;
203-+ }
204-+ *dst = '\0';
205-+ }
206-+ return q;
207-+}
208-+
209- static int
210- backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
211- {
212-@@ -429,6 +461,8 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
213- backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
214- int i;
215- int casefold = 0;
216-+ int escaped = 0;
217-+ struct berval escval, *fvalue;
218-
219- if ( !f ) {
220- return 0;
221-@@ -462,50 +496,68 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
222-
223- BER_BVZERO( &bv );
224- if ( f->f_sub_initial.bv_val ) {
225-- bv.bv_len += f->f_sub_initial.bv_len;
226-+ bv.bv_len += f->f_sub_initial.bv_len + backsql_val_escape( NULL, &f->f_sub_initial, NULL );
227- }
228- if ( f->f_sub_any != NULL ) {
229- for ( a = 0; f->f_sub_any[ a ].bv_val != NULL; a++ ) {
230-- bv.bv_len += f->f_sub_any[ a ].bv_len;
231-+ bv.bv_len += f->f_sub_any[ a ].bv_len + backsql_val_escape( NULL, &f->f_sub_any[ a ], NULL );
232- }
233- }
234- if ( f->f_sub_final.bv_val ) {
235-- bv.bv_len += f->f_sub_final.bv_len;
236-+ bv.bv_len += f->f_sub_final.bv_len + backsql_val_escape( NULL, &f->f_sub_final, NULL );
237- }
238- bv.bv_len = 2 * bv.bv_len - 1;
239- bv.bv_val = ch_malloc( bv.bv_len + 1 );
240-
241- s = 0;
242- if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
243-- bv.bv_val[ s ] = f->f_sub_initial.bv_val[ 0 ];
244-- for ( i = 1; i < f->f_sub_initial.bv_len; i++ ) {
245-+ fvalue = &f->f_sub_initial;
246-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
247-+ if ( escaped )
248-+ fvalue = &escval;
249-+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
250-+ for ( i = 1; i < fvalue->bv_len; i++ ) {
251- bv.bv_val[ s + 2 * i - 1 ] = '%';
252-- bv.bv_val[ s + 2 * i ] = f->f_sub_initial.bv_val[ i ];
253-+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
254- }
255- bv.bv_val[ s + 2 * i - 1 ] = '%';
256- s += 2 * i;
257-+ if ( escaped )
258-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
259- }
260-
261- if ( f->f_sub_any != NULL ) {
262- for ( a = 0; !BER_BVISNULL( &f->f_sub_any[ a ] ); a++ ) {
263-- bv.bv_val[ s ] = f->f_sub_any[ a ].bv_val[ 0 ];
264-- for ( i = 1; i < f->f_sub_any[ a ].bv_len; i++ ) {
265-+ fvalue = &f->f_sub_any[ a ];
266-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
267-+ if ( escaped )
268-+ fvalue = &escval;
269-+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
270-+ for ( i = 1; i < fvalue->bv_len; i++ ) {
271- bv.bv_val[ s + 2 * i - 1 ] = '%';
272-- bv.bv_val[ s + 2 * i ] = f->f_sub_any[ a ].bv_val[ i ];
273-+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
274- }
275- bv.bv_val[ s + 2 * i - 1 ] = '%';
276- s += 2 * i;
277-+ if ( escaped )
278-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
279- }
280- }
281-
282- if ( !BER_BVISNULL( &f->f_sub_final ) ) {
283-- bv.bv_val[ s ] = f->f_sub_final.bv_val[ 0 ];
284-- for ( i = 1; i < f->f_sub_final.bv_len; i++ ) {
285-+ fvalue = &f->f_sub_final;
286-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
287-+ if ( escaped )
288-+ fvalue = &escval;
289-+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
290-+ for ( i = 1; i < fvalue->bv_len; i++ ) {
291- bv.bv_val[ s + 2 * i - 1 ] = '%';
292-- bv.bv_val[ s + 2 * i ] = f->f_sub_final.bv_val[ i ];
293-+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
294- }
295-- bv.bv_val[ s + 2 * i - 1 ] = '%';
296-+ bv.bv_val[ s + 2 * i - 1 ] = '%';
297- s += 2 * i;
298-+ if ( escaped )
299-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
300- }
301-
302- bv.bv_val[ s - 1 ] = '\0';
303-@@ -561,11 +613,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
304- f->f_sub_initial.bv_val );
305- #endif /* BACKSQL_TRACE */
306-
307-+ fvalue = &f->f_sub_initial;
308-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
309-+ if ( escaped )
310-+ fvalue = &escval;
311- start = bsi->bsi_flt_where.bb_val.bv_len;
312- backsql_strfcat_x( &bsi->bsi_flt_where,
313- bsi->bsi_op->o_tmpmemctx,
314- "b",
315-- &f->f_sub_initial );
316-+ fvalue );
317-+ if ( escaped )
318-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
319- if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
320- ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] );
321- }
322-@@ -586,12 +644,18 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
323- i, f->f_sub_any[ i ].bv_val );
324- #endif /* BACKSQL_TRACE */
325-
326-+ fvalue = &f->f_sub_any[ i ];
327-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
328-+ if ( escaped )
329-+ fvalue = &escval;
330- start = bsi->bsi_flt_where.bb_val.bv_len;
331- backsql_strfcat_x( &bsi->bsi_flt_where,
332- bsi->bsi_op->o_tmpmemctx,
333- "bc",
334-- &f->f_sub_any[ i ],
335-+ fvalue,
336- '%' );
337-+ if ( escaped )
338-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
339- if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
340- /*
341- * Note: toupper('%') = '%'
342-@@ -611,11 +675,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
343- f->f_sub_final.bv_val );
344- #endif /* BACKSQL_TRACE */
345-
346-+ fvalue = &f->f_sub_final;
347-+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
348-+ if ( escaped )
349-+ fvalue = &escval;
350- start = bsi->bsi_flt_where.bb_val.bv_len;
351- backsql_strfcat_x( &bsi->bsi_flt_where,
352- bsi->bsi_op->o_tmpmemctx,
353- "b",
354-- &f->f_sub_final );
355-+ fvalue );
356-+ if ( escaped )
357-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
358- if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
359- ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] );
360- }
361-@@ -1182,6 +1252,8 @@ backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, backsql_at_map_r
362- struct berval *filter_value = NULL;
363- MatchingRule *matching_rule = NULL;
364- struct berval ordering = BER_BVC("<=");
365-+ struct berval escval;
366-+ int escaped = 0;
367-
368- Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter_attr(%s)\n",
369- at->bam_ad->ad_cname.bv_val );
370-@@ -1236,6 +1308,10 @@ equality_match:;
371- casefold = 1;
372- }
373-
374-+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
375-+ if ( escaped )
376-+ filter_value = &escval;
377-+
378- /* FIXME: directoryString filtering should use a similar
379- * approach to deal with non-prettified values like
380- * " A non prettified value ", by using a LIKE
381-@@ -1316,6 +1392,10 @@ equality_match:;
382- casefold = 1;
383- }
384-
385-+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
386-+ if ( escaped )
387-+ filter_value = &escval;
388-+
389- /*
390- * FIXME: should we uppercase the operands?
391- */
392-@@ -1349,7 +1429,7 @@ equality_match:;
393- &at->bam_sel_expr,
394- &ordering,
395- '\'',
396-- &f->f_av_value,
397-+ filter_value,
398- (ber_len_t)STRLENOF( /* (' */ "')" ),
399- /* ( */ "')" );
400- }
401-@@ -1373,13 +1453,17 @@ equality_match:;
402- case LDAP_FILTER_APPROX:
403- /* we do our best */
404-
405-+ filter_value = &f->f_av_value;
406-+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
407-+ if ( escaped )
408-+ filter_value = &escval;
409- /*
410- * maybe we should check type of at->sel_expr here somehow,
411- * to know whether upper_func is applicable, but for now
412- * upper_func stuff is made for Oracle, where UPPER is
413- * safely applicable to NUMBER etc.
414- */
415-- (void)backsql_process_filter_like( bsi, at, 1, &f->f_av_value );
416-+ (void)backsql_process_filter_like( bsi, at, 1, filter_value );
417- break;
418-
419- default:
420-@@ -1393,6 +1477,9 @@ equality_match:;
421-
422- }
423-
424-+ if ( escaped )
425-+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
426-+
427- Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter_attr(%s)\n",
428- at->bam_ad->ad_cname.bv_val );
429-
430---
431-GitLab
432-
433diff --git a/debian/patches/series b/debian/patches/series
434index 34a5f20..a8d57cb 100644
435--- a/debian/patches/series
436+++ b/debian/patches/series
437@@ -13,4 +13,3 @@ add-tlscacert-option-to-ldap-conf
438 fix-build-top-mk
439 switch-to-lt_dlopenadvise-to-get-RTLD_GLOBAL-set.diff
440 set-maintainer-name
441-CVE-2022-29155.patch
442diff --git a/doc/guide/admin/guide.html b/doc/guide/admin/guide.html
443index c256e1b..7415912 100644
444--- a/doc/guide/admin/guide.html
445+++ b/doc/guide/admin/guide.html
446@@ -23,7 +23,7 @@
447 <DIV CLASS="title">
448 <H1 CLASS="doc-title">OpenLDAP Software 2.5 Administrator's Guide</H1>
449 <ADDRESS CLASS="doc-author">The OpenLDAP Project &lt;<A HREF="https://www.openldap.org/">https://www.openldap.org/</A>&gt;</ADDRESS>
450-<ADDRESS CLASS="doc-modified">20 January 2022</ADDRESS>
451+<ADDRESS CLASS="doc-modified">4 May 2022</ADDRESS>
452 <BR CLEAR="All">
453 </DIV>
454 <DIV CLASS="contents">
455diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3
456index f08cd01..3477f02 100644
457--- a/doc/man/man3/ldap_get_option.3
458+++ b/doc/man/man3/ldap_get_option.3
459@@ -455,6 +455,12 @@ This option is OpenLDAP specific.
460 .B LDAP_OPT_TCP_USER_TIMEOUT
461 Allows to configure TCP_USER_TIMEOUT in milliseconds on the connection, overriding the operating system setting.
462 This option is OpenLDAP specific and supported only on Linux 2.6.37 or higher.
463+.B invalue
464+must be a
465+.BR "const unsigned int *" ;
466+.BR outvalue
467+must be an
468+.BR "unsigned int *" .
469
470 .SH SASL OPTIONS
471 The SASL options are OpenLDAP specific.
472@@ -587,6 +593,7 @@ must be a
473 .BR "char **" .
474 Its content needs to be freed by the caller using
475 .BR ldap_memfree (3).
476+.TP
477 .B LDAP_OPT_X_SASL_CBINDING
478 Sets/gets the channel-binding type to use in SASL,
479 one of
480@@ -602,7 +609,6 @@ must be
481 .BR outvalue
482 must be
483 .BR "int *" .
484-.TP
485 .SH TCP OPTIONS
486 The TCP options are OpenLDAP specific.
487 Mainly intended for use with Linux, they may not be portable.
488@@ -873,6 +879,21 @@ must be
489 .BR "char **" ,
490 and its contents need to be freed by the caller using
491 .BR ldap_memfree (3).
492+.TP
493+.B LDAP_OPT_X_TLS_PEERKEY_HASH
494+Sets the (public) key that the application expects the peer to be using.
495+.B invalue
496+must be
497+.BR "const char *"
498+containing the base64 encoding of the expected peer's key or in the format
499+.B "<hashalg>:<peerkey hash base64 encoded>"
500+where as a TLS session is established, the library will hash the peer's key
501+with the provided hash algorithm and compare it with value provided and will
502+only allow the session to continue if they match. This happens regardless of
503+certificate checking strategy. The list of supported
504+.B hashalg
505+values depends on the crypto library used, check its documentation to get
506+a list.
507 .SH ERRORS
508 On success, the functions return
509 .BR LDAP_OPT_SUCCESS ,
510diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
511index 9e40804..d402340 100644
512--- a/doc/man/man5/slapd-config.5
513+++ b/doc/man/man5/slapd-config.5
514@@ -1945,9 +1945,8 @@ The \fBsizelimit\fP and \fBtimelimit\fP only
515 accept "unlimited" and positive integers, and both default to "unlimited".
516 The \fBsizelimit\fP and \fBtimelimit\fP parameters define
517 a consumer requested limitation on the number of entries that can be returned
518-by the LDAP Content Synchronization operation; as such, it is intended
519-to implement partial replication based on the size of the replicated database
520-and on the time required by the synchronization.
521+by the LDAP Content Synchronization operation; these should be left unchanged
522+from the default otherwise replication may never succeed.
523 Note, however, that any provider-side limits for the replication identity
524 will be enforced by the provider regardless of the limits requested
525 by the LDAP Content Synchronization operation, much like for any other
526diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
527index 37ec52e..6ec19c5 100644
528--- a/doc/man/man5/slapd.conf.5
529+++ b/doc/man/man5/slapd.conf.5
530@@ -1877,9 +1877,8 @@ The \fBsizelimit\fP and \fBtimelimit\fP only
531 accept "unlimited" and positive integers, and both default to "unlimited".
532 The \fBsizelimit\fP and \fBtimelimit\fP parameters define
533 a consumer requested limitation on the number of entries that can be returned
534-by the LDAP Content Synchronization operation; as such, it is intended
535-to implement partial replication based on the size of the replicated database
536-and on the time required by the synchronization.
537+by the LDAP Content Synchronization operation; these should be left unchanged
538+from the default otherwise replication may never succeed.
539 Note, however, that any provider-side limits for the replication identity
540 will be enforced by the provider regardless of the limits requested
541 by the LDAP Content Synchronization operation, much like for any other
542diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h
543index 27a5afd..ba6ec15 100644
544--- a/include/ldap_pvt.h
545+++ b/include/ldap_pvt.h
546@@ -185,11 +185,11 @@ ldap_pvt_get_hname LDAP_P((
547 #define LDAP_IPADDRLEN sizeof("IP=255.255.255.255:65336")
548 #endif
549
550-typedef union Sockaddr Sockaddr;
551+union Sockaddr;
552
553 LDAP_F (void)
554 ldap_pvt_sockaddrstr LDAP_P((
555- Sockaddr *sa,
556+ union Sockaddr *sa,
557 struct berval * ));
558
559
560diff --git a/libraries/libldap/ldif.c b/libraries/libldap/ldif.c
561index 7ca5e32..900a979 100644
562--- a/libraries/libldap/ldif.c
563+++ b/libraries/libldap/ldif.c
564@@ -796,6 +796,7 @@ ldif_read_record(
565 * back to a previous file. (return from an include)
566 */
567 while ( feof( lfp->fp )) {
568+pop:
569 if ( lfp->prev ) {
570 LDIFFP *tmp = lfp->prev;
571 fclose( lfp->fp );
572@@ -808,6 +809,10 @@ ldif_read_record(
573 }
574 if ( !stop ) {
575 if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
576+ if ( !found_entry && !ferror( lfp->fp ) ) {
577+ /* ITS#9811 Reached the end looking for an entry, try again */
578+ goto pop;
579+ }
580 stop = 1;
581 len = 0;
582 } else {
583diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c
584index c1b4a45..40ff1c1 100644
585--- a/libraries/libldap/result.c
586+++ b/libraries/libldap/result.c
587@@ -506,6 +506,16 @@ nextresp3:
588 lc->lconn_ber = NULL;
589 break;
590
591+ default:
592+ /*
593+ * We read a BerElement that isn't LDAP or the stream has desync'd.
594+ * In either case, anything we read from now on is probably garbage,
595+ * just drop the connection.
596+ */
597+ ber_free( ber, 1 );
598+ lc->lconn_ber = NULL;
599+ /* FALLTHRU */
600+
601 case LBER_DEFAULT:
602 fail:
603 err = sock_errno();
604@@ -521,10 +531,6 @@ fail:
605 }
606 lc->lconn_status = 0;
607 return -1;
608-
609- default:
610- ld->ld_errno = LDAP_LOCAL_ERROR;
611- return -1;
612 }
613
614 /* message id */
615diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
616index c31c657..834d986 100644
617--- a/libraries/libldap/tls_o.c
618+++ b/libraries/libldap/tls_o.c
619@@ -1026,8 +1026,12 @@ tlso_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
620 #ifndef OPENSSL_NO_MD2
621 md == EVP_md2() ||
622 #endif
623+#ifndef OPENSSL_NO_MD4
624 md == EVP_md4() ||
625+#endif
626+#ifndef OPENSSL_NO_MD5
627 md == EVP_md5() ||
628+#endif
629 md == EVP_sha1() )
630 md = EVP_sha256();
631
632diff --git a/servers/slapd/back-asyncmeta/add.c b/servers/slapd/back-asyncmeta/add.c
633index d32415b..1f194ed 100644
634--- a/servers/slapd/back-asyncmeta/add.c
635+++ b/servers/slapd/back-asyncmeta/add.c
636@@ -51,6 +51,7 @@ asyncmeta_error_cleanup(Operation *op,
637 }
638 asyncmeta_drop_bc(mc, bc);
639 slap_sl_mem_setctx(op->o_threadctx, op->o_tmpmemctx);
640+ operation_counter_init( op, op->o_threadctx );
641 ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
642 send_ldap_result(op, rs);
643 return LDAP_SUCCESS;
644diff --git a/servers/slapd/back-asyncmeta/config.c b/servers/slapd/back-asyncmeta/config.c
645index 866fb98..849ac01 100644
646--- a/servers/slapd/back-asyncmeta/config.c
647+++ b/servers/slapd/back-asyncmeta/config.c
648@@ -2405,9 +2405,11 @@ asyncmeta_back_cf_gen( ConfigArgs *c )
649 break;
650 #endif /* SLAPD_META_CLIENT_PR */
651
652- case LDAP_BACK_CFG_KEEPALIVE:
653- slap_keepalive_parse( ber_bvstrdup(c->argv[1]),
654- &mt->mt_tls.sb_keepalive, 0, 0, 0);
655+ case LDAP_BACK_CFG_KEEPALIVE: {
656+ struct berval bv;
657+ ber_str2bv( c->argv[1], 0, 1, &bv );
658+ slap_keepalive_parse( &bv, &mt->mt_tls.sb_keepalive, 0, 0, 0 );
659+ }
660 break;
661
662 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
663diff --git a/servers/slapd/back-asyncmeta/meta_result.c b/servers/slapd/back-asyncmeta/meta_result.c
664index 07863bb..0ce279a 100644
665--- a/servers/slapd/back-asyncmeta/meta_result.c
666+++ b/servers/slapd/back-asyncmeta/meta_result.c
667@@ -650,6 +650,7 @@ asyncmeta_send_all_pending_ops(a_metaconn_t *mc, int candidate, void *ctx, int d
668 bc->op->o_threadctx = ctx;
669 bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
670 slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
671+ operation_counter_init( bc->op, ctx );
672 bc->bc_active++;
673 ret = asyncmeta_send_pending_op(bc, candidate);
674 if (ret != META_SEARCH_CANDIDATE) {
675@@ -699,6 +700,7 @@ asyncmeta_return_bind_errors(a_metaconn_t *mc, int candidate, SlapReply *bind_re
676 bc->op->o_threadctx = ctx;
677 bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
678 slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
679+ operation_counter_init( bc->op, ctx );
680 bc->rs.sr_err = bind_result->sr_err;
681 bc->rs.sr_text = bind_result->sr_text;
682 mc->pending_ops--;
683@@ -1422,6 +1424,7 @@ asyncmeta_op_read_error(a_metaconn_t *mc, int candidate, int error, void* ctx)
684 bc->op->o_threadctx = ctx;
685 bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
686 slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
687+ operation_counter_init( bc->op, ctx );
688
689 op = bc->op;
690 rs = &bc->rs;
691@@ -1569,6 +1572,7 @@ retry_bc:
692 bc->op->o_threadctx = ctx;
693 bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
694 slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
695+ operation_counter_init( bc->op, ctx );
696 if (bc->op->o_abandon) {
697 ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
698 asyncmeta_drop_bc( mc, bc);
699@@ -1668,12 +1672,14 @@ void* asyncmeta_timeout_loop(void *ctx, void *arg)
700 }
701
702 if (bc->op->o_abandon ) {
703- /* set our memctx */
704- bc->op->o_threadctx = ctx;
705- bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
706- slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
707 Operation *op = bc->op;
708
709+ /* set our memctx */
710+ op->o_threadctx = ctx;
711+ op->o_tid = ldap_pvt_thread_pool_tid( ctx );
712+ slap_sl_mem_setctx(ctx, op->o_tmpmemctx);
713+ operation_counter_init( op, ctx );
714+
715 LDAP_STAILQ_REMOVE(&mc->mc_om_list, bc, bm_context_t, bc_next);
716 mc->pending_ops--;
717 for (j=0; j<mi->mi_ntargets; j++) {
718@@ -1730,6 +1736,7 @@ void* asyncmeta_timeout_loop(void *ctx, void *arg)
719 bc->op->o_threadctx = ctx;
720 bc->op->o_tid = ldap_pvt_thread_pool_tid( ctx );
721 slap_sl_mem_setctx(ctx, bc->op->o_tmpmemctx);
722+ operation_counter_init( bc->op, ctx );
723
724 if (bc->searchtime) {
725 timeout_err = LDAP_TIMELIMIT_EXCEEDED;
726diff --git a/servers/slapd/back-asyncmeta/search.c b/servers/slapd/back-asyncmeta/search.c
727index 5310ca1..0b0db82 100644
728--- a/servers/slapd/back-asyncmeta/search.c
729+++ b/servers/slapd/back-asyncmeta/search.c
730@@ -58,6 +58,7 @@ asyncmeta_handle_onerr_stop(Operation *op,
731 }
732 }
733 slap_sl_mem_setctx(op->o_threadctx, op->o_tmpmemctx);
734+ operation_counter_init( op, op->o_threadctx );
735 ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
736 send_ldap_result(op, rs);
737 }
738diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c
739index 07fe8e9..fb97e8e 100644
740--- a/servers/slapd/back-ldap/config.c
741+++ b/servers/slapd/back-ldap/config.c
742@@ -2051,9 +2051,11 @@ done_url:;
743 }
744 break;
745
746- case LDAP_BACK_CFG_KEEPALIVE:
747- slap_keepalive_parse( ber_bvstrdup(c->argv[1]),
748- &li->li_tls.sb_keepalive, 0, 0, 0);
749+ case LDAP_BACK_CFG_KEEPALIVE: {
750+ struct berval bv;
751+ ber_str2bv( c->argv[1], 0, 1, &bv );
752+ slap_keepalive_parse( &bv, &li->li_tls.sb_keepalive, 0, 0, 0 );
753+ }
754 break;
755
756 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
757diff --git a/servers/slapd/back-mdb/monitor.c b/servers/slapd/back-mdb/monitor.c
758index 7f26074..fc77bc6 100644
759--- a/servers/slapd/back-mdb/monitor.c
760+++ b/servers/slapd/back-mdb/monitor.c
761@@ -578,10 +578,11 @@ mdb_monitor_db_close( BackendDB *be )
762 monitor_extra_t *mbe;
763
764 if ( mi && mi->bi_extra ) {
765+ struct berval dummy = BER_BVNULL;
766 mbe = mi->bi_extra;
767 mbe->unregister_entry_callback( &mdb->mi_monitor.mdm_ndn,
768 (monitor_callback_t *)mdb->mi_monitor.mdm_cb,
769- NULL, 0, NULL );
770+ &dummy, 0, &dummy );
771 }
772
773 memset( &mdb->mi_monitor, 0, sizeof( mdb->mi_monitor ) );
774diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c
775index 51d090f..6b1e607 100644
776--- a/servers/slapd/back-meta/config.c
777+++ b/servers/slapd/back-meta/config.c
778@@ -2662,7 +2662,6 @@ idassert-authzFrom "dn:<rootdn>"
779 c->fname, c->lineno, ca.argc, ca.argv );
780 }
781 assert( rc == 0 );
782- ch_free( ca.argv );
783 ch_free( ca.tline );
784 }
785 }
786@@ -2699,9 +2698,9 @@ idassert-authzFrom "dn:<rootdn>"
787 c->fname, c->lineno, ca.argc, argv );
788 }
789 assert( rc == 0 );
790- ch_free( ca.argv );
791 ch_free( ca.tline );
792 }
793+ ch_free( ca.argv );
794 }
795
796 /* save the rule info */
797@@ -2718,7 +2717,7 @@ idassert-authzFrom "dn:<rootdn>"
798 /* move it to the right slot */
799 if ( ix < cnt ) {
800 for ( i=cnt; i>ix; i-- )
801- mt->mt_rwmap.rwm_bva_rewrite[i+1] = mt->mt_rwmap.rwm_bva_rewrite[i];
802+ mt->mt_rwmap.rwm_bva_rewrite[i] = mt->mt_rwmap.rwm_bva_rewrite[i-1];
803 mt->mt_rwmap.rwm_bva_rewrite[i] = bv;
804
805 /* destroy old rules */
806@@ -2730,7 +2729,7 @@ idassert-authzFrom "dn:<rootdn>"
807 case LDAP_BACK_CFG_MAP: {
808 /* objectclass/attribute mapping */
809 ConfigArgs ca = { 0 };
810- char *argv[5];
811+ char *argv[5], **argvp;
812 struct ldapmap rwm_oc;
813 struct ldapmap rwm_at;
814 int cnt = 0, ix = c->valx;
815@@ -2763,7 +2762,8 @@ idassert-authzFrom "dn:<rootdn>"
816 argv[2] = ca.argv[1];
817 argv[3] = ca.argv[2];
818 argv[4] = ca.argv[3];
819- ch_free( ca.argv );
820+
821+ argvp = ca.argv;
822 ca.argv = argv;
823 ca.argc++;
824 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc,
825@@ -2771,7 +2771,7 @@ idassert-authzFrom "dn:<rootdn>"
826
827 ch_free( ca.tline );
828 ca.tline = NULL;
829- ca.argv = NULL;
830+ ca.argv = argvp;
831
832 /* in case of failure, restore
833 * the existing mapping */
834@@ -2788,7 +2788,7 @@ idassert-authzFrom "dn:<rootdn>"
835 }
836
837 if ( ix < cnt ) {
838- for ( ; i<cnt ; cnt++ ) {
839+ for ( ; i<cnt ; i++ ) {
840 ca.line = mt->mt_rwmap.rwm_bva_map[ i ].bv_val;
841 ca.argc = 0;
842 config_fp_parse_line( &ca );
843@@ -2798,7 +2798,7 @@ idassert-authzFrom "dn:<rootdn>"
844 argv[3] = ca.argv[2];
845 argv[4] = ca.argv[3];
846
847- ch_free( ca.argv );
848+ argvp = ca.argv;
849 ca.argv = argv;
850 ca.argc++;
851 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc,
852@@ -2806,7 +2806,7 @@ idassert-authzFrom "dn:<rootdn>"
853
854 ch_free( ca.tline );
855 ca.tline = NULL;
856- ca.argv = NULL;
857+ ca.argv = argvp;
858
859 /* in case of failure, restore
860 * the existing mapping */
861@@ -2814,6 +2814,7 @@ idassert-authzFrom "dn:<rootdn>"
862 goto map_fail;
863 }
864 }
865+ ch_free( ca.argv );
866 }
867
868 /* save the map info */
869@@ -2825,7 +2826,7 @@ idassert-authzFrom "dn:<rootdn>"
870 /* move it to the right slot */
871 if ( ix < cnt ) {
872 for ( i=cnt; i>ix; i-- )
873- mt->mt_rwmap.rwm_bva_map[i+1] = mt->mt_rwmap.rwm_bva_map[i];
874+ mt->mt_rwmap.rwm_bva_map[i] = mt->mt_rwmap.rwm_bva_map[i-1];
875 mt->mt_rwmap.rwm_bva_map[i] = bv;
876
877 /* destroy old mapping */
878@@ -2841,6 +2842,7 @@ map_fail:;
879 meta_back_map_free( &mt->mt_rwmap.rwm_at );
880 mt->mt_rwmap.rwm_oc = rwm_oc;
881 mt->mt_rwmap.rwm_at = rwm_at;
882+ ch_free( ca.argv );
883 }
884 } break;
885
886@@ -2913,9 +2915,11 @@ map_fail:;
887 break;
888 #endif /* SLAPD_META_CLIENT_PR */
889
890- case LDAP_BACK_CFG_KEEPALIVE:
891- slap_keepalive_parse( ber_bvstrdup(c->argv[1]),
892- &mt->mt_tls.sb_keepalive, 0, 0, 0);
893+ case LDAP_BACK_CFG_KEEPALIVE: {
894+ struct berval bv;
895+ ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
896+ slap_keepalive_parse( &bv, &mt->mt_tls.sb_keepalive, 0, 0, 0 );
897+ }
898 break;
899
900 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
901diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c
902index 2168a15..d4177f6 100644
903--- a/servers/slapd/back-sql/search.c
904+++ b/servers/slapd/back-sql/search.c
905@@ -63,6 +63,38 @@ static void send_paged_response(
906 ID *lastid );
907 #endif /* ! BACKSQL_ARBITRARY_KEY */
908
909+/* Look for chars that need to be escaped, return count of them.
910+ * If out is non-NULL, copy escape'd val to it.
911+ */
912+static int
913+backsql_val_escape( Operation *op, struct berval *in, struct berval *out )
914+{
915+ char *ptr, *end;
916+ int q = 0;
917+
918+ ptr = in->bv_val;
919+ end = ptr + in->bv_len;
920+ while (ptr < end) {
921+ if ( *ptr == '\'' )
922+ q++;
923+ ptr++;
924+ }
925+ if ( q && out ) {
926+ char *dst;
927+ out->bv_len = in->bv_len + q;
928+ out->bv_val = op->o_tmpalloc( out->bv_len + 1, op->o_tmpmemctx );
929+ ptr = in->bv_val;
930+ dst = out->bv_val;
931+ while (ptr < end ) {
932+ if ( *ptr == '\'' )
933+ *dst++ = '\'';
934+ *dst++ = *ptr++;
935+ }
936+ *dst = '\0';
937+ }
938+ return q;
939+}
940+
941 static int
942 backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
943 {
944@@ -429,6 +461,8 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
945 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
946 int i;
947 int casefold = 0;
948+ int escaped = 0;
949+ struct berval escval, *fvalue;
950
951 if ( !f ) {
952 return 0;
953@@ -462,50 +496,68 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
954
955 BER_BVZERO( &bv );
956 if ( f->f_sub_initial.bv_val ) {
957- bv.bv_len += f->f_sub_initial.bv_len;
958+ bv.bv_len += f->f_sub_initial.bv_len + backsql_val_escape( NULL, &f->f_sub_initial, NULL );
959 }
960 if ( f->f_sub_any != NULL ) {
961 for ( a = 0; f->f_sub_any[ a ].bv_val != NULL; a++ ) {
962- bv.bv_len += f->f_sub_any[ a ].bv_len;
963+ bv.bv_len += f->f_sub_any[ a ].bv_len + backsql_val_escape( NULL, &f->f_sub_any[ a ], NULL );
964 }
965 }
966 if ( f->f_sub_final.bv_val ) {
967- bv.bv_len += f->f_sub_final.bv_len;
968+ bv.bv_len += f->f_sub_final.bv_len + backsql_val_escape( NULL, &f->f_sub_final, NULL );
969 }
970 bv.bv_len = 2 * bv.bv_len - 1;
971 bv.bv_val = ch_malloc( bv.bv_len + 1 );
972
973 s = 0;
974 if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
975- bv.bv_val[ s ] = f->f_sub_initial.bv_val[ 0 ];
976- for ( i = 1; i < f->f_sub_initial.bv_len; i++ ) {
977+ fvalue = &f->f_sub_initial;
978+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
979+ if ( escaped )
980+ fvalue = &escval;
981+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
982+ for ( i = 1; i < fvalue->bv_len; i++ ) {
983 bv.bv_val[ s + 2 * i - 1 ] = '%';
984- bv.bv_val[ s + 2 * i ] = f->f_sub_initial.bv_val[ i ];
985+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
986 }
987 bv.bv_val[ s + 2 * i - 1 ] = '%';
988 s += 2 * i;
989+ if ( escaped )
990+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
991 }
992
993 if ( f->f_sub_any != NULL ) {
994 for ( a = 0; !BER_BVISNULL( &f->f_sub_any[ a ] ); a++ ) {
995- bv.bv_val[ s ] = f->f_sub_any[ a ].bv_val[ 0 ];
996- for ( i = 1; i < f->f_sub_any[ a ].bv_len; i++ ) {
997+ fvalue = &f->f_sub_any[ a ];
998+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
999+ if ( escaped )
1000+ fvalue = &escval;
1001+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
1002+ for ( i = 1; i < fvalue->bv_len; i++ ) {
1003 bv.bv_val[ s + 2 * i - 1 ] = '%';
1004- bv.bv_val[ s + 2 * i ] = f->f_sub_any[ a ].bv_val[ i ];
1005+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
1006 }
1007 bv.bv_val[ s + 2 * i - 1 ] = '%';
1008 s += 2 * i;
1009+ if ( escaped )
1010+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1011 }
1012 }
1013
1014 if ( !BER_BVISNULL( &f->f_sub_final ) ) {
1015- bv.bv_val[ s ] = f->f_sub_final.bv_val[ 0 ];
1016- for ( i = 1; i < f->f_sub_final.bv_len; i++ ) {
1017+ fvalue = &f->f_sub_final;
1018+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
1019+ if ( escaped )
1020+ fvalue = &escval;
1021+ bv.bv_val[ s ] = fvalue->bv_val[ 0 ];
1022+ for ( i = 1; i < fvalue->bv_len; i++ ) {
1023 bv.bv_val[ s + 2 * i - 1 ] = '%';
1024- bv.bv_val[ s + 2 * i ] = f->f_sub_final.bv_val[ i ];
1025+ bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ];
1026 }
1027- bv.bv_val[ s + 2 * i - 1 ] = '%';
1028+ bv.bv_val[ s + 2 * i - 1 ] = '%';
1029 s += 2 * i;
1030+ if ( escaped )
1031+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1032 }
1033
1034 bv.bv_val[ s - 1 ] = '\0';
1035@@ -561,11 +613,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
1036 f->f_sub_initial.bv_val );
1037 #endif /* BACKSQL_TRACE */
1038
1039+ fvalue = &f->f_sub_initial;
1040+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
1041+ if ( escaped )
1042+ fvalue = &escval;
1043 start = bsi->bsi_flt_where.bb_val.bv_len;
1044 backsql_strfcat_x( &bsi->bsi_flt_where,
1045 bsi->bsi_op->o_tmpmemctx,
1046 "b",
1047- &f->f_sub_initial );
1048+ fvalue );
1049+ if ( escaped )
1050+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1051 if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
1052 ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] );
1053 }
1054@@ -586,12 +644,18 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
1055 i, f->f_sub_any[ i ].bv_val );
1056 #endif /* BACKSQL_TRACE */
1057
1058+ fvalue = &f->f_sub_any[ i ];
1059+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
1060+ if ( escaped )
1061+ fvalue = &escval;
1062 start = bsi->bsi_flt_where.bb_val.bv_len;
1063 backsql_strfcat_x( &bsi->bsi_flt_where,
1064 bsi->bsi_op->o_tmpmemctx,
1065 "bc",
1066- &f->f_sub_any[ i ],
1067+ fvalue,
1068 '%' );
1069+ if ( escaped )
1070+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1071 if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
1072 /*
1073 * Note: toupper('%') = '%'
1074@@ -611,11 +675,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
1075 f->f_sub_final.bv_val );
1076 #endif /* BACKSQL_TRACE */
1077
1078+ fvalue = &f->f_sub_final;
1079+ escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval );
1080+ if ( escaped )
1081+ fvalue = &escval;
1082 start = bsi->bsi_flt_where.bb_val.bv_len;
1083 backsql_strfcat_x( &bsi->bsi_flt_where,
1084 bsi->bsi_op->o_tmpmemctx,
1085 "b",
1086- &f->f_sub_final );
1087+ fvalue );
1088+ if ( escaped )
1089+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1090 if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {
1091 ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] );
1092 }
1093@@ -1182,6 +1252,8 @@ backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, backsql_at_map_r
1094 struct berval *filter_value = NULL;
1095 MatchingRule *matching_rule = NULL;
1096 struct berval ordering = BER_BVC("<=");
1097+ struct berval escval;
1098+ int escaped = 0;
1099
1100 Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter_attr(%s)\n",
1101 at->bam_ad->ad_cname.bv_val );
1102@@ -1236,6 +1308,10 @@ equality_match:;
1103 casefold = 1;
1104 }
1105
1106+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
1107+ if ( escaped )
1108+ filter_value = &escval;
1109+
1110 /* FIXME: directoryString filtering should use a similar
1111 * approach to deal with non-prettified values like
1112 * " A non prettified value ", by using a LIKE
1113@@ -1316,6 +1392,10 @@ equality_match:;
1114 casefold = 1;
1115 }
1116
1117+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
1118+ if ( escaped )
1119+ filter_value = &escval;
1120+
1121 /*
1122 * FIXME: should we uppercase the operands?
1123 */
1124@@ -1349,7 +1429,7 @@ equality_match:;
1125 &at->bam_sel_expr,
1126 &ordering,
1127 '\'',
1128- &f->f_av_value,
1129+ filter_value,
1130 (ber_len_t)STRLENOF( /* (' */ "')" ),
1131 /* ( */ "')" );
1132 }
1133@@ -1373,13 +1453,17 @@ equality_match:;
1134 case LDAP_FILTER_APPROX:
1135 /* we do our best */
1136
1137+ filter_value = &f->f_av_value;
1138+ escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval );
1139+ if ( escaped )
1140+ filter_value = &escval;
1141 /*
1142 * maybe we should check type of at->sel_expr here somehow,
1143 * to know whether upper_func is applicable, but for now
1144 * upper_func stuff is made for Oracle, where UPPER is
1145 * safely applicable to NUMBER etc.
1146 */
1147- (void)backsql_process_filter_like( bsi, at, 1, &f->f_av_value );
1148+ (void)backsql_process_filter_like( bsi, at, 1, filter_value );
1149 break;
1150
1151 default:
1152@@ -1393,6 +1477,9 @@ equality_match:;
1153
1154 }
1155
1156+ if ( escaped )
1157+ bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx );
1158+
1159 Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter_attr(%s)\n",
1160 at->bam_ad->ad_cname.bv_val );
1161
1162diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
1163index 3e6136f..c5c69ba 100644
1164--- a/servers/slapd/bconfig.c
1165+++ b/servers/slapd/bconfig.c
1166@@ -75,6 +75,7 @@ typedef struct {
1167 BackendDB cb_db; /* underlying database */
1168 int cb_got_ldif;
1169 int cb_use_ldif;
1170+ ldap_pvt_thread_rdwr_t cb_rwlock;
1171 } CfBackInfo;
1172
1173 static CfBackInfo cfBackInfo;
1174@@ -1363,7 +1364,7 @@ config_generic(ConfigArgs *c) {
1175 c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
1176 break;
1177 case CFG_LASTBIND:
1178- c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
1179+ c->value_int = (SLAP_LASTBIND(c->be) != 0);
1180 break;
1181 case CFG_SYNC_SUBENTRY:
1182 c->value_int = (SLAP_SYNC_SUBENTRY(c->be) != 0);
1183@@ -5959,6 +5960,8 @@ config_back_add( Operation *op, SlapReply *rs )
1184 if ( slap_pause_server() < 0 )
1185 dopause = 0;
1186
1187+ ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
1188+
1189 /* Strategy:
1190 * 1) check for existence of entry
1191 * 2) check for sibling renumbering
1192@@ -6007,6 +6010,7 @@ config_back_add( Operation *op, SlapReply *rs )
1193 }
1194
1195 out2:;
1196+ ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
1197 if ( dopause )
1198 slap_unpause_server();
1199
1200@@ -6493,6 +6497,7 @@ config_back_modify( Operation *op, SlapReply *rs )
1201 if ( slap_pause_server() < 0 )
1202 do_pause = 0;
1203 }
1204+ ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
1205
1206 /* Strategy:
1207 * 1) perform the Modify on the cached Entry.
1208@@ -6524,6 +6529,7 @@ config_back_modify( Operation *op, SlapReply *rs )
1209 op->o_ndn = ndn;
1210 }
1211
1212+ ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
1213 if ( do_pause )
1214 slap_unpause_server();
1215 out:
1216@@ -6663,6 +6669,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
1217 if ( slap_pause_server() < 0 )
1218 dopause = 0;
1219
1220+ ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
1221+
1222 if ( ce->ce_type == Cft_Schema ) {
1223 req_modrdn_s modr = op->oq_modrdn;
1224 struct berval rdn;
1225@@ -6727,6 +6735,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
1226 op->oq_modrdn = modr;
1227 }
1228
1229+ ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
1230+
1231 if ( dopause )
1232 slap_unpause_server();
1233 out:
1234@@ -6762,6 +6772,8 @@ config_back_delete( Operation *op, SlapReply *rs )
1235 if ( slap_pause_server() < 0 )
1236 dopause = 0;
1237
1238+ ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
1239+
1240 if ( ce->ce_type == Cft_Overlay ){
1241 overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op );
1242 } else if ( ce->ce_type == Cft_Misc ) {
1243@@ -6780,8 +6792,7 @@ config_back_delete( Operation *op, SlapReply *rs )
1244 if ( !oc_at ) {
1245 rs->sr_err = LDAP_OTHER;
1246 rs->sr_text = "objectclass not found";
1247- if ( dopause ) slap_unpause_server();
1248- goto out;
1249+ goto out2;
1250 }
1251 for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
1252 co.co_name = &oc_at->a_nvals[i];
1253@@ -6798,8 +6809,7 @@ config_back_delete( Operation *op, SlapReply *rs )
1254 /* FIXME: We should return a helpful error message
1255 * here */
1256 }
1257- if ( dopause ) slap_unpause_server();
1258- goto out;
1259+ goto out2;
1260 }
1261 break;
1262 }
1263@@ -6807,8 +6817,7 @@ config_back_delete( Operation *op, SlapReply *rs )
1264 if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
1265 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1266 rs->sr_text = "Cannot delete config or frontend database";
1267- if ( dopause ) slap_unpause_server();
1268- goto out;
1269+ goto out2;
1270 }
1271 if ( ce->ce_be->bd_info->bi_db_close ) {
1272 ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
1273@@ -6869,6 +6878,8 @@ config_back_delete( Operation *op, SlapReply *rs )
1274 ce->ce_entry->e_private=NULL;
1275 entry_free(ce->ce_entry);
1276 ch_free(ce);
1277+out2:
1278+ ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
1279 if ( dopause ) slap_unpause_server();
1280 } else {
1281 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1282@@ -6890,6 +6901,7 @@ config_back_search( Operation *op, SlapReply *rs )
1283
1284 cfb = (CfBackInfo *)op->o_bd->be_private;
1285
1286+ ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
1287 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
1288 if ( !ce ) {
1289 if ( last )
1290@@ -6924,6 +6936,7 @@ config_back_search( Operation *op, SlapReply *rs )
1291 }
1292
1293 out:
1294+ ldap_pvt_thread_rdwr_runlock( &cfb->cb_rwlock );
1295 send_ldap_result( op, rs );
1296 return rs->sr_err;
1297 }
1298@@ -7659,6 +7672,8 @@ config_back_db_destroy( BackendDB *be, ConfigReply *cr )
1299
1300 ch_free( cfdir.bv_val );
1301
1302+ ldap_pvt_thread_rdwr_destroy( &cfb->cb_rwlock );
1303+
1304 ldap_avl_free( CfOcTree, NULL );
1305
1306 if ( cfb->cb_db.bd_info ) {
1307@@ -7693,6 +7708,8 @@ config_back_db_init( BackendDB *be, ConfigReply* cr )
1308 ber_dupbv( &dn, &be->be_rootdn );
1309 ber_bvarray_add( &be->be_nsuffix, &dn );
1310
1311+ ldap_pvt_thread_rdwr_init( &cfb->cb_rwlock );
1312+
1313 /* Hide from namingContexts */
1314 SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
1315
1316diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
1317index 324c3b0..b8ea92a 100644
1318--- a/servers/slapd/connection.c
1319+++ b/servers/slapd/connection.c
1320@@ -212,7 +212,7 @@ int connections_timeout_idle(time_t now)
1321 /* Don't timeout a slow-running request or a persistent
1322 * outbound connection.
1323 */
1324- if((( c->c_n_ops_executing || c->c_n_ops_async ) && !c->c_writewaiter)
1325+ if( c->c_n_ops_executing || c->c_n_ops_async
1326 || c->c_conn_state == SLAP_C_CLIENT ) {
1327 continue;
1328 }
1329@@ -244,7 +244,7 @@ void connections_drop()
1330 /* Don't close a slow-running request or a persistent
1331 * outbound connection.
1332 */
1333- if((( c->c_n_ops_executing || c->c_n_ops_async ) && !c->c_writewaiter)
1334+ if( c->c_n_ops_executing || c->c_n_ops_async
1335 || c->c_conn_state == SLAP_C_CLIENT ) {
1336 continue;
1337 }
1338@@ -734,6 +734,7 @@ static void connection_abandon( Connection *c )
1339 LDAP_STAILQ_NEXT(o, o_next) = NULL;
1340 slap_op_free( o, NULL );
1341 }
1342+ c->c_n_ops_pending = 0;
1343 }
1344
1345 static void
1346@@ -870,13 +871,14 @@ Connection* connection_next( Connection *c, ber_socket_t *index )
1347
1348 for(; *index < dtblsize; (*index)++) {
1349 if( connections[*index].c_sb ) {
1350- c = &connections[(*index)++];
1351+ c = &connections[*index];
1352 ldap_pvt_thread_mutex_lock( &c->c_mutex );
1353 if ( c->c_conn_state == SLAP_C_INVALID ) {
1354 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
1355 c = NULL;
1356 continue;
1357 }
1358+ (*index)++;
1359 break;
1360 }
1361 }
1362@@ -963,18 +965,18 @@ conn_counter_destroy( void *key, void *data )
1363 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
1364 }
1365
1366-static void
1367-conn_counter_init( Operation *op, void *ctx )
1368+void
1369+operation_counter_init( Operation *op, void *ctx )
1370 {
1371 slap_counters_t *sc;
1372 void *vsc = NULL;
1373
1374 if ( ldap_pvt_thread_pool_getkey(
1375- ctx, (void *)conn_counter_init, &vsc, NULL ) || !vsc ) {
1376+ ctx, (void *)operation_counter_init, &vsc, NULL ) || !vsc ) {
1377 vsc = ch_malloc( sizeof( slap_counters_t ));
1378 sc = vsc;
1379 slap_counters_init( sc );
1380- ldap_pvt_thread_pool_setkey( ctx, (void*)conn_counter_init, vsc,
1381+ ldap_pvt_thread_pool_setkey( ctx, (void*)operation_counter_init, vsc,
1382 conn_counter_destroy, NULL, NULL );
1383
1384 ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
1385@@ -1030,7 +1032,7 @@ connection_operation( void *ctx, void *arg_v )
1386 op->o_qtime.tv_sec--;
1387 }
1388 op->o_qtime.tv_sec -= op->o_time;
1389- conn_counter_init( op, ctx );
1390+ operation_counter_init( op, ctx );
1391 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
1392 /* FIXME: returns 0 in case of failure */
1393 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated, 1);
1394diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
1395index c982cc9..2f78b77 100644
1396--- a/servers/slapd/daemon.c
1397+++ b/servers/slapd/daemon.c
1398@@ -2413,6 +2413,18 @@ slap_listener_activate(
1399 }
1400
1401 static void *
1402+slapd_rtask_trampoline(
1403+ void *ctx,
1404+ void *arg )
1405+{
1406+ struct re_s *rtask = arg;
1407+
1408+ /* invalidate pool_cookie */
1409+ rtask->pool_cookie = NULL;
1410+ return rtask->routine( ctx, arg );
1411+}
1412+
1413+static void *
1414 slapd_daemon_task(
1415 void *ptr )
1416 {
1417@@ -2775,7 +2787,7 @@ loop:
1418 ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
1419 ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
1420 ldap_pvt_thread_pool_submit2( &connection_pool,
1421- rtask->routine, (void *) rtask, &rtask->pool_cookie );
1422+ slapd_rtask_trampoline, (void *) rtask, &rtask->pool_cookie );
1423 ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
1424 }
1425 rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
1426diff --git a/servers/slapd/overlays/dynlist.c b/servers/slapd/overlays/dynlist.c
1427index b04f65c..3490cfb 100644
1428--- a/servers/slapd/overlays/dynlist.c
1429+++ b/servers/slapd/overlays/dynlist.c
1430@@ -1208,13 +1208,16 @@ dynlist_filter_stgroup( Operation *op, Filter *n, Attribute *a )
1431 Filter *dnf, *orf = NULL;
1432 int i;
1433
1434- if ( a->a_numvals == 1 ) {
1435+ if ( a->a_numvals == 1 && n->f_choice == SLAPD_FILTER_COMPUTED ) {
1436 dnf = n;
1437 } else {
1438 orf = n;
1439- orf->f_choice = LDAP_FILTER_OR;
1440+ if ( n->f_choice != LDAP_FILTER_OR ) {
1441+ orf->f_choice = LDAP_FILTER_OR;
1442+ orf->f_list = NULL;
1443+ }
1444 dnf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
1445- dnf->f_next = NULL;
1446+ dnf->f_next = orf->f_list;
1447 orf->f_list = dnf;
1448 }
1449
1450@@ -1298,9 +1301,9 @@ dynlist_filter_dup( Operation *op, Filter *f, AttributeDescription *ad, dynlist_
1451 break;
1452
1453 case LDAP_FILTER_EQUALITY:
1454- n->f_choice = SLAPD_FILTER_COMPUTED;
1455 if ( f->f_av_desc == ad ) {
1456 dynlist_name_t *dyn = ldap_tavl_find( ds->ds_names, &f->f_av_value, dynlist_avl_cmp );
1457+ n->f_choice = SLAPD_FILTER_COMPUTED;
1458 if ( dyn && !dynlist_filter_group( op, dyn, n, ds ))
1459 break;
1460 }
1461diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c
1462index fa70d5d..fcf29c6 100644
1463--- a/servers/slapd/overlays/pcache.c
1464+++ b/servers/slapd/overlays/pcache.c
1465@@ -5660,15 +5660,16 @@ pcache_monitor_db_close( BackendDB *be )
1466 slap_overinst *on = (slap_overinst *)be->bd_info;
1467 cache_manager *cm = on->on_bi.bi_private;
1468
1469- if ( cm->monitor_cb != NULL ) {
1470+ if ( !BER_BVISNULL( &cm->monitor_ndn )) {
1471 BackendInfo *mi = backend_info( "monitor" );
1472 monitor_extra_t *mbe;
1473
1474 if ( mi && mi->bi_extra ) {
1475+ struct berval dummy = BER_BVNULL;
1476 mbe = mi->bi_extra;
1477 mbe->unregister_entry_callback( &cm->monitor_ndn,
1478 (monitor_callback_t *)cm->monitor_cb,
1479- NULL, 0, NULL );
1480+ &dummy, 0, &dummy );
1481 }
1482 }
1483
1484diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c
1485index abde6d2..a2c86f6 100644
1486--- a/servers/slapd/overlays/ppolicy.c
1487+++ b/servers/slapd/overlays/ppolicy.c
1488@@ -2215,6 +2215,7 @@ ppolicy_add(
1489 PassPolicy pp;
1490 Attribute *pa;
1491 const char *txt;
1492+ int is_pwdadmin = 0;
1493
1494 if ( ppolicy_restrict( op, rs ) != SLAP_CB_CONTINUE )
1495 return rs->sr_err;
1496@@ -2223,10 +2224,14 @@ ppolicy_add(
1497 if ( SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) )
1498 return SLAP_CB_CONTINUE;
1499
1500+ ppolicy_get( op, op->ora_e, &pp );
1501+
1502+ if ( access_allowed( op, op->ora_e, pp.ad, NULL, ACL_MANAGE, NULL ) ) {
1503+ is_pwdadmin = 1;
1504+ }
1505+
1506 /* Check for password in entry */
1507- if ((pa = attr_find( op->oq_add.rs_e->e_attrs,
1508- slap_schema.si_ad_userPassword )))
1509- {
1510+ if ( (pa = attr_find( op->oq_add.rs_e->e_attrs, pp.ad )) ) {
1511 assert( pa->a_vals != NULL );
1512 assert( !BER_BVISNULL( &pa->a_vals[ 0 ] ) );
1513
1514@@ -2235,15 +2240,13 @@ ppolicy_add(
1515 return rs->sr_err;
1516 }
1517
1518- ppolicy_get( op, op->ora_e, &pp );
1519-
1520 /*
1521- * new entry contains a password - if we're not the root user
1522+ * new entry contains a password - if we're not the password admin
1523 * then we need to check that the password fits in with the
1524 * security policy for the new entry.
1525 */
1526
1527- if (pp.pwdCheckQuality > 0 && !be_isroot( op )) {
1528+ if ( pp.pwdCheckQuality > 0 && !is_pwdadmin ) {
1529 struct berval *bv = &(pa->a_vals[0]);
1530 int rc, send_ctrl = 0;
1531 LDAPPasswordPolicyError pErr = PP_noError;
1532@@ -2305,7 +2308,8 @@ ppolicy_add(
1533 }
1534
1535 /* If password aging is in effect, set the pwdChangedTime */
1536- if ( pp.pwdMaxAge || pp.pwdMinAge ) {
1537+ if ( ( pp.pwdMaxAge || pp.pwdMinAge ) &&
1538+ !attr_find( op->ora_e->e_attrs, ad_pwdChangedTime ) ) {
1539 struct berval timestamp;
1540 char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
1541 time_t now = slap_get_time();
1542diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
1543index 364ee8a..36978d6 100644
1544--- a/servers/slapd/overlays/syncprov.c
1545+++ b/servers/slapd/overlays/syncprov.c
1546@@ -1075,6 +1075,7 @@ syncprov_qtask( void *ctx, void *arg )
1547 op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx, 1);
1548 op->o_tmpmfuncs = &slap_sl_mfuncs;
1549 op->o_threadctx = ctx;
1550+ operation_counter_init( op, ctx );
1551
1552 /* syncprov_qplay expects a fake db */
1553 be = *so->s_op->o_bd;
1554diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c
1555index 1e4e338..a034a58 100644
1556--- a/servers/slapd/overlays/translucent.c
1557+++ b/servers/slapd/overlays/translucent.c
1558@@ -999,7 +999,6 @@ trans_filter_dup(Operation *op, Filter *f, AttributeName *an)
1559 case LDAP_FILTER_GE:
1560 case LDAP_FILTER_LE:
1561 case LDAP_FILTER_APPROX:
1562- case LDAP_FILTER_SUBSTRINGS:
1563 case LDAP_FILTER_EXT:
1564 if ( !f->f_av_desc || ad_inlist( f->f_av_desc, an )) {
1565 AttributeAssertion *nava;
1566@@ -1016,6 +1015,29 @@ trans_filter_dup(Operation *op, Filter *f, AttributeName *an)
1567 }
1568 break;
1569
1570+ case LDAP_FILTER_SUBSTRINGS:
1571+ if ( !f->f_av_desc || ad_inlist( f->f_av_desc, an )) {
1572+ SubstringsAssertion *nsub;
1573+
1574+ n = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
1575+ n->f_choice = f->f_choice;
1576+
1577+ nsub = op->o_tmpalloc( sizeof(SubstringsAssertion), op->o_tmpmemctx );
1578+ *nsub = *f->f_sub;
1579+ n->f_sub = nsub;
1580+
1581+ if ( !BER_BVISNULL( &f->f_sub_initial ))
1582+ ber_dupbv_x( &n->f_sub_initial, &f->f_sub_initial, op->o_tmpmemctx );
1583+
1584+ ber_bvarray_dup_x( &n->f_sub_any, f->f_sub_any, op->o_tmpmemctx );
1585+
1586+ if ( !BER_BVISNULL( &f->f_sub_final ))
1587+ ber_dupbv_x( &n->f_sub_final, &f->f_sub_final, op->o_tmpmemctx );
1588+
1589+ n->f_next = NULL;
1590+ }
1591+ break;
1592+
1593 case LDAP_FILTER_AND:
1594 case LDAP_FILTER_OR:
1595 case LDAP_FILTER_NOT: {
1596diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
1597index a9a6f4c..d7073d7 100644
1598--- a/servers/slapd/proto-slap.h
1599+++ b/servers/slapd/proto-slap.h
1600@@ -800,6 +800,7 @@ LDAP_SLAPD_F (Connection *) connection_init LDAP_P((
1601 struct berval *id
1602 LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv)));
1603
1604+LDAP_SLAPD_F (void) operation_counter_init LDAP_P(( Operation *op, void *threadctx ));
1605 LDAP_SLAPD_F (void) connection_closing LDAP_P((
1606 Connection *c, const char *why ));
1607 LDAP_SLAPD_F (int) connection_is_active LDAP_P(( ber_socket_t s ));
1608diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
1609index bccef38..6ed5580 100644
1610--- a/servers/slapd/syncrepl.c
1611+++ b/servers/slapd/syncrepl.c
1612@@ -58,6 +58,8 @@ static AttributeDescription *sy_ad_dseeLastChange;
1613
1614 #define UUIDLEN 16
1615
1616+struct syncinfo_s;
1617+
1618 struct nonpresent_entry {
1619 struct berval *npe_name;
1620 struct berval *npe_nname;
1621@@ -85,8 +87,19 @@ typedef struct cookie_state {
1622 struct berval *cs_pvals;
1623 int *cs_psids;
1624 int cs_pnum;
1625+
1626+ /* serialize multi-consumer refreshes */
1627+ ldap_pvt_thread_mutex_t cs_refresh_mutex;
1628+ struct syncinfo_s *cs_refreshing;
1629 } cookie_state;
1630
1631+#define SYNC_TIMEOUT 0
1632+#define SYNC_SHUTDOWN -100
1633+#define SYNC_ERROR -101
1634+#define SYNC_REPOLL -102
1635+#define SYNC_PAUSED -103
1636+#define SYNC_BUSY -104
1637+
1638 #define SYNCDATA_DEFAULT 0 /* entries are plain LDAP entries */
1639 #define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */
1640 #define SYNCDATA_CHANGELOG 2 /* entries are changelog format */
1641@@ -139,6 +152,7 @@ typedef struct syncinfo_s {
1642 int si_refreshDelete;
1643 int si_refreshPresent;
1644 int si_refreshDone;
1645+ int si_paused;
1646 int si_syncdata;
1647 int si_logstate;
1648 int si_lazyCommit;
1649@@ -488,6 +502,64 @@ init_syncrepl(syncinfo_t *si)
1650 si->si_exattrs = exattrs;
1651 }
1652
1653+static int
1654+start_refresh(syncinfo_t *si)
1655+{
1656+ ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_refresh_mutex );
1657+ if ( si->si_cookieState->cs_refreshing ) {
1658+ struct re_s* rtask = si->si_re;
1659+
1660+ ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
1661+ ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
1662+ ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
1663+
1664+ si->si_paused = 1;
1665+ Debug( LDAP_DEBUG_SYNC, "start_refresh: %s "
1666+ "a refresh on %s in progress, pausing\n",
1667+ si->si_ridtxt, si->si_cookieState->cs_refreshing->si_ridtxt );
1668+ ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_refresh_mutex );
1669+ return SYNC_BUSY;
1670+ }
1671+ si->si_cookieState->cs_refreshing = si;
1672+ ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_refresh_mutex );
1673+
1674+ return LDAP_SUCCESS;
1675+}
1676+
1677+static int
1678+refresh_finished(syncinfo_t *si)
1679+{
1680+ syncinfo_t *sie;
1681+ int removed = 0;
1682+
1683+ ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_refresh_mutex );
1684+ if ( si->si_cookieState->cs_refreshing == si ) {
1685+ si->si_cookieState->cs_refreshing = NULL;
1686+ removed = 1;
1687+ }
1688+
1689+ if ( removed ) {
1690+ for ( sie = si->si_be->be_syncinfo; sie; sie = sie->si_next ) {
1691+ if ( sie->si_paused ) {
1692+ struct re_s* rtask = sie->si_re;
1693+
1694+ Debug( LDAP_DEBUG_SYNC, "refresh_finished: %s "
1695+ "rescheduling refresh on %s\n",
1696+ si->si_ridtxt, sie->si_ridtxt );
1697+ sie->si_paused = 0;
1698+ ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
1699+ rtask->interval.tv_sec = 0;
1700+ ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
1701+ rtask->interval.tv_sec = si->si_interval;
1702+ ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
1703+ break;
1704+ }
1705+ }
1706+ }
1707+ ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_refresh_mutex );
1708+ return removed;
1709+}
1710+
1711 static struct berval generic_filterstr = BER_BVC("(objectclass=*)");
1712
1713 static int
1714@@ -511,6 +583,8 @@ ldap_sync_search(
1715 ber_init2( ber, NULL, LBER_USE_DER );
1716 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx );
1717
1718+ si->si_msgid = 0;
1719+
1720 /* If we're using a log but we have no state, then fallback to
1721 * normal mode for a full refresh.
1722 */
1723@@ -519,6 +593,11 @@ ldap_sync_search(
1724 LDAPMessage *res, *msg;
1725 unsigned long first = 0, last = 0;
1726 int gotfirst = 0, gotlast = 0;
1727+
1728+ if ( (rc = start_refresh( si )) ) {
1729+ return rc;
1730+ }
1731+
1732 /* See if we're new enough for the remote server */
1733 lattrs[0] = "firstchangenumber";
1734 lattrs[1] = "lastchangenumber";
1735@@ -597,6 +676,10 @@ ldap_sync_search(
1736 attrs = lattrs;
1737 attrsonly = 0;
1738 } else {
1739+ if ( (rc = start_refresh( si )) ) {
1740+ return rc;
1741+ }
1742+
1743 rhint = 1;
1744 base = si->si_base.bv_val;
1745 filter = si->si_filterstr.bv_val;
1746@@ -680,6 +763,10 @@ ldap_sync_search(
1747 }
1748 }
1749
1750+ si->si_refreshDone = 0;
1751+ si->si_refreshPresent = 0;
1752+ si->si_refreshDelete = 0;
1753+
1754 rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
1755 ctrls, NULL, NULL, si->si_slimit, &si->si_msgid );
1756 ber_free_buf( ber );
1757@@ -929,7 +1016,6 @@ do_syncrep1(
1758 #endif
1759
1760 si->si_lastconnect = slap_get_time();
1761- si->si_refreshDone = 0;
1762 rc = slap_client_connect( &si->si_ld, &si->si_bindconf );
1763 if ( rc != LDAP_SUCCESS ) {
1764 goto done;
1765@@ -1095,7 +1181,10 @@ do_syncrep1(
1766
1767 rc = ldap_sync_search( si, op->o_tmpmemctx );
1768
1769- if( rc != LDAP_SUCCESS ) {
1770+ if ( rc == SYNC_BUSY ) {
1771+ return rc;
1772+ } else if ( rc != LDAP_SUCCESS ) {
1773+ refresh_finished( si );
1774 Debug( LDAP_DEBUG_ANY, "do_syncrep1: %s "
1775 "ldap_search_ext: %s (%d)\n",
1776 si->si_ridtxt, ldap_err2string( rc ), rc );
1777@@ -1187,12 +1276,6 @@ check_csn_age(
1778 return rc;
1779 }
1780
1781-#define SYNC_TIMEOUT 0
1782-#define SYNC_SHUTDOWN -100
1783-#define SYNC_ERROR -101
1784-#define SYNC_REPOLL -102
1785-#define SYNC_PAUSED -103
1786-
1787 static int
1788 get_pmutex(
1789 syncinfo_t *si
1790@@ -1236,6 +1319,8 @@ do_syncrep2(
1791 struct timeval tout = { 0, 0 };
1792
1793 int refreshDeletes = 0;
1794+ int refreshing = !si->si_refreshDone &&
1795+ !( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING );
1796 char empty[6] = "empty";
1797
1798 if ( slapd_shutdown ) {
1799@@ -1291,6 +1376,7 @@ do_syncrep2(
1800 break;
1801 }
1802 #endif
1803+ punlock = -1;
1804 ldap_get_entry_controls( si->si_ld, msg, &rctrls );
1805 ldap_get_dn_ber( si->si_ld, msg, NULL, &bdn );
1806 if (!bdn.bv_len) {
1807@@ -1307,8 +1393,6 @@ do_syncrep2(
1808 /* The notification control is only sent during persist phase */
1809 rctrlp = ldap_control_find( LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE, rctrls, &next );
1810 if ( rctrlp ) {
1811- if ( !si->si_refreshDone )
1812- si->si_refreshDone = 1;
1813 if ( si->si_refreshDone )
1814 syncrepl_dsee_update( si, op );
1815 }
1816@@ -1380,7 +1464,6 @@ do_syncrep2(
1817 rc = -1;
1818 goto done;
1819 }
1820- punlock = -1;
1821 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
1822 if ( ber_scanf( ber, /*"{"*/ "m}", &cookie ) != LBER_ERROR ) {
1823
1824@@ -1716,6 +1799,14 @@ logerr:
1825 "LDAP_RES_INTERMEDIATE",
1826 si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ?
1827 "REFRESH_PRESENT" : "REFRESH_DELETE" );
1828+ if ( si->si_refreshDone ) {
1829+ Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
1830+ "server sent multiple refreshDone "
1831+ "messages? Ending session\n",
1832+ si->si_ridtxt );
1833+ rc = LDAP_PROTOCOL_ERROR;
1834+ goto done;
1835+ }
1836 if ( si_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
1837 si->si_refreshDelete = 1;
1838 } else {
1839@@ -1754,9 +1845,9 @@ logerr:
1840 si->si_refreshDone = 1;
1841 }
1842 ber_scanf( ber, /*"{"*/ "}" );
1843- if ( si->si_refreshDone ) {
1844- Debug( LDAP_DEBUG_SYNC, "do_syncrep1: %s finished refresh\n",
1845- si->si_ridtxt );
1846+ if ( refreshing && si->si_refreshDone ) {
1847+ refresh_finished( si );
1848+ refreshing = 0;
1849 }
1850 break;
1851 case LDAP_TAG_SYNC_ID_SET:
1852@@ -1903,6 +1994,9 @@ done:
1853 "do_syncrep2: %s (%d) %s\n",
1854 si->si_ridtxt, err, ldap_err2string( err ) );
1855 }
1856+ if ( refreshing && ( rc || si->si_refreshDone ) ) {
1857+ refresh_finished( si );
1858+ }
1859
1860 slap_sync_cookie_free( &syncCookie, 0 );
1861 slap_sync_cookie_free( &syncCookie_req, 0 );
1862@@ -2041,9 +2135,6 @@ do_syncrepl(
1863
1864 /* Establish session, do search */
1865 if ( !si->si_ld ) {
1866- si->si_refreshDelete = 0;
1867- si->si_refreshPresent = 0;
1868-
1869 if ( si->si_presentlist ) {
1870 presentlist_free( si->si_presentlist );
1871 si->si_presentlist = NULL;
1872@@ -2054,6 +2145,13 @@ do_syncrepl(
1873 op->o_dn = op->o_bd->be_rootdn;
1874 op->o_ndn = op->o_bd->be_rootndn;
1875 rc = do_syncrep1( op, si );
1876+ } else if ( !si->si_msgid ) {
1877+ /* We got a SYNC_BUSY, now told to resume */
1878+ rc = ldap_sync_search( si, op->o_tmpmemctx );
1879+ }
1880+ if ( rc == SYNC_BUSY ) {
1881+ ldap_pvt_thread_mutex_unlock( &si->si_mutex );
1882+ return NULL;
1883 }
1884
1885 reload:
1886@@ -6007,6 +6105,9 @@ syncinfo_free( syncinfo_t *sie, int free_all )
1887 ch_free( npe );
1888 }
1889 if ( sie->si_cookieState ) {
1890+ /* Could be called from do_syncrepl (server unpaused) */
1891+ refresh_finished( sie );
1892+
1893 sie->si_cookieState->cs_ref--;
1894 if ( !sie->si_cookieState->cs_ref ) {
1895 ch_free( sie->si_cookieState->cs_sids );
1896@@ -6016,6 +6117,8 @@ syncinfo_free( syncinfo_t *sie, int free_all )
1897 ch_free( sie->si_cookieState->cs_psids );
1898 ber_bvarray_free( sie->si_cookieState->cs_pvals );
1899 ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_pmutex );
1900+ ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_refresh_mutex );
1901+ assert( sie->si_cookieState->cs_refreshing == NULL );
1902 ch_free( sie->si_cookieState );
1903 }
1904 }
1905@@ -7231,6 +7334,7 @@ add_syncrepl(
1906 si->si_cookieState = ch_calloc( 1, sizeof( cookie_state ));
1907 ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex );
1908 ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_pmutex );
1909+ ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_refresh_mutex );
1910 ldap_pvt_thread_cond_init( &si->si_cookieState->cs_cond );
1911
1912 c->be->be_syncinfo = si;
1913@@ -7489,7 +7593,7 @@ syncrepl_config( ConfigArgs *c )
1914 ldap_pvt_runqueue_stoptask( &slapd_rq, re );
1915 isrunning = 1;
1916 }
1917- if ( ldap_pvt_thread_pool_retract( re->pool_cookie ) > 0 )
1918+ if ( !re->pool_cookie || ldap_pvt_thread_pool_retract( re->pool_cookie ) > 0 )
1919 isrunning = 0;
1920
1921 ldap_pvt_runqueue_remove( &slapd_rq, re );
1922diff --git a/tests/data/dynlist.out b/tests/data/dynlist.out
1923index 0e9e479..926e830 100644
1924--- a/tests/data/dynlist.out
1925+++ b/tests/data/dynlist.out
1926@@ -679,6 +679,10 @@ memberOf: cn=bonus group,ou=groups,dc=example,dc=com
1927 memberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
1928 memberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
1929
1930+dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=example
1931+ ,dc=com
1932+uid: jjones
1933+
1934 # Testing negated filtered memberOf functionality...
1935 dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
1936 dc=com
1937diff --git a/tests/scripts/test034-translucent b/tests/scripts/test034-translucent
1938index 511ebed..8b834d9 100755
1939--- a/tests/scripts/test034-translucent
1940+++ b/tests/scripts/test034-translucent
1941@@ -755,6 +755,14 @@ if test -z "$ATTR" ; then
1942 exit 1
1943 fi
1944
1945+$LDAPSEARCH -H $URI2 -b "o=translucent" "(employeeType=consult*)" > $SEARCHOUT 2>&1
1946+ATTR=`grep dn: $SEARCHOUT` > $NOWHERE 2>&1
1947+if test -z "$ATTR" ; then
1948+ echo "got no result, should have found entry"
1949+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
1950+ exit 1
1951+fi
1952+
1953 echo "Testing search: unconfigured remote filter..."
1954 $LDAPSEARCH -H $URI2 -b "o=translucent" "(|(employeeType=foo)(carlicense=right))" > $SEARCHOUT 2>&1
1955
1956diff --git a/tests/scripts/test044-dynlist b/tests/scripts/test044-dynlist
1957index 52960ea..b7a6b20 100755
1958--- a/tests/scripts/test044-dynlist
1959+++ b/tests/scripts/test044-dynlist
1960@@ -1049,6 +1049,17 @@ if test $RC != 0 ; then
1961 exit $RC
1962 fi
1963
1964+$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
1965+ -D "$BABSDN" -w bjensen \
1966+ "(&(uid=jjones)(memberOf=cn=jjs,ou=groups,$BASEDN))" 'uid' \
1967+ >> $SEARCHOUT 2>&1
1968+RC=$?
1969+if test $RC != 0 ; then
1970+ echo "ldapsearch failed ($RC)!"
1971+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
1972+ exit $RC
1973+fi
1974+
1975 echo "Testing negated filtered memberOf functionality..."
1976 echo "# Testing negated filtered memberOf functionality..." >> $SEARCHOUT
1977

Subscribers

People subscribed via source and target branches