Merge ~sergiodj/ubuntu/+source/openldap:MRE-2.5.17-jammy into ubuntu/+source/openldap:ubuntu/jammy-devel

Proposed by Sergio Durigan Junior
Status: Merged
Approved by: git-ubuntu bot
Approved revision: not available
Merged at revision: a2130beb84a0617b364fd2d7beca33aac443a08b
Proposed branch: ~sergiodj/ubuntu/+source/openldap:MRE-2.5.17-jammy
Merge into: ubuntu/+source/openldap:ubuntu/jammy-devel
Diff against target: 4842 lines (+1607/-800)
50 files modified
CHANGES (+32/-0)
build/version.var (+4/-4)
clients/tools/common.c (+4/-3)
clients/tools/ldappasswd.c (+12/-2)
clients/tools/ldapvc.c (+7/-2)
contrib/slapd-modules/lastmod/lastmod.c (+10/-2)
debian/changelog (+19/-0)
doc/guide/admin/guide.html (+1/-1)
doc/man/man5/lloadd.conf.5 (+26/-26)
doc/man/man5/slapo-dynlist.5 (+7/-0)
doc/man/man5/slapo-homedir.5 (+28/-1)
doc/man/man8/slapd.8 (+3/-1)
include/ac/string.h (+3/-3)
libraries/liblber/debug.c (+4/-1)
libraries/libldap/getdn.c (+8/-0)
libraries/libldap/init.c (+0/-3)
libraries/libldap/open.c (+1/-0)
libraries/libldap/tls2.c (+13/-1)
libraries/libldap/tls_o.c (+14/-4)
libraries/libldap/url.c (+4/-0)
libraries/libldap/util-int.c (+51/-123)
libraries/liblmdb/CHANGES (+6/-0)
libraries/liblmdb/Makefile (+1/-0)
libraries/liblmdb/lmdb.h (+2/-2)
libraries/liblmdb/mdb.c (+112/-37)
libraries/liblmdb/mdb_load.c (+4/-2)
libraries/liblmdb/midl.h (+2/-0)
libraries/liblmdb/mplay.c (+582/-0)
servers/lloadd/daemon.c (+15/-1)
servers/lloadd/libevent_support.c (+7/-1)
servers/lloadd/module_init.c (+0/-1)
servers/lloadd/upstream.c (+8/-3)
servers/slapd/aci.c (+14/-12)
servers/slapd/aclparse.c (+416/-448)
servers/slapd/back-asyncmeta/map.c (+11/-1)
servers/slapd/back-ldap/chain.c (+1/-1)
servers/slapd/back-null/null.c (+2/-2)
servers/slapd/bconfig.c (+30/-17)
servers/slapd/controls.c (+1/-0)
servers/slapd/overlays/dynlist.c (+35/-20)
servers/slapd/proto-slap.h (+1/-3)
servers/slapd/slap-config.h (+22/-22)
servers/slapd/slap.h (+4/-2)
servers/slapd/slapi/Makefile.in (+6/-6)
servers/slapd/slapi/plugin.c (+35/-36)
servers/slapd/slapi/printmsg.c (+20/-0)
servers/slapd/slapi/proto-slapi.h (+1/-2)
servers/slapd/slapi/slapi_utils.c (+6/-0)
servers/slapd/slappasswd.c (+9/-4)
tests/progs/slapd-tester.c (+3/-0)
Reviewer Review Type Date Requested Status
git-ubuntu bot Approve
Bryce Harrington (community) Approve
Canonical Server Reporter Pending
Review via email: mp+460353@code.launchpad.net

Description of the change

This is the MRE of OpenLDAP 2.5.17 to Jammy.

Nothing major to report here. Instead of trying to decide for a small set of upstream changes to list on d/changelog, I'm now listing everything.

PPA: https://launchpad.net/~sergiodj/+archive/ubuntu/openldap

dep8 results will be posted soon.

To post a comment you must log in.
Revision history for this message
Bryce Harrington (bryce) wrote :

LGTM, +1, presuming the autopkgtests pass.

I like the more detailed changelog personally, and if it saves some thinking time not to have to filter it, then that's a bonus.

I skimmed briefly through the upstream diff, nothing caught my eye. A healthy chunk of it is debug messaging, which is a good sign. There's an `mplay` command being added although that appears just for analysis/debugging (I can't tell if it gets installed but am guessing no.) The remainder does indeed look like bugfixes.

review: Approve
Revision history for this message
git-ubuntu bot (git-ubuntu-bot) wrote :

Approvers: sergiodj, bryce
Uploaders: sergiodj, bryce
MP auto-approved

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

On Friday, February 09 2024, Bryce Harrington wrote:

> LGTM, +1, presuming the autopkgtests pass.

Thanks, Bryce.

I just got the results:

Results: (from http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/?format=plain)
  openldap @ amd64:
    http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/jammy/amd64/o/openldap/20240209_225823_2ec27@/log.gz
    09.02.24 22:58:23 ✅ Triggers: openldap/2.5.17+dfsg-0ubuntu0.22.04.1~ppa1
  openldap @ arm64:
    http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/jammy/arm64/o/openldap/20240209_230358_34851@/log.gz
    09.02.24 23:03:58 ✅ Triggers: openldap/2.5.17+dfsg-0ubuntu0.22.04.1~ppa1
  openldap @ armhf:
    http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/jammy/armhf/o/openldap/20240209_230114_34851@/log.gz
    09.02.24 23:01:14 ✅ Triggers: openldap/2.5.17+dfsg-0ubuntu0.22.04.1~ppa1
  openldap @ ppc64el:
    http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/jammy/ppc64el/o/openldap/20240209_231213_2ec27@/log.gz
    09.02.24 23:12:13 ✅ Triggers: openldap/2.5.17+dfsg-0ubuntu0.22.04.1~ppa1
  openldap @ s390x:
    http://autopkgtest.ubuntu.com/results/autopkgtest-jammy-sergiodj-openldap/jammy/s390x/o/openldap/20240209_225840_2ec27@/log.gz
    09.02.24 22:58:40 ✅ Triggers: openldap/2.5.17+dfsg-0ubuntu0.22.04.1~ppa1

Therefore, I'm uploading the package now:

$ dput openldap_2.5.17+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.17+dfsg-0ubuntu0.22.04.1_source.changes: Valid signature from 106DA1C8C3CBBF14
Checking signature on .dsc
gpg: /home/sergio/work/openldap/openldap_2.5.17+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.17+dfsg-0ubuntu0.22.04.1.dsc: done.
  Uploading openldap_2.5.17+dfsg.orig.tar.gz: done.
  Uploading openldap_2.5.17+dfsg-0ubuntu0.22.04.1.debian.tar.xz: done.
  Uploading openldap_2.5.17+dfsg-0ubuntu0.22.04.1_source.buildinfo: done.
  Uploading openldap_2.5.17+dfsg-0ubuntu0.22.04.1_source.changes: done.
Successfully uploaded packages.

--
Sergio
GPG key ID: E92F D0B3 6B14 F1F4 D8E0 EB2F 106D A1C8 C3CB BF14

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/CHANGES b/CHANGES
2index 23c0e5e..8b691f0 100644
3--- a/CHANGES
4+++ b/CHANGES
5@@ -1,5 +1,37 @@
6 OpenLDAP 2.5 Change Log
7
8+OpenLDAP 2.5.17 Release (2024/01/29)
9+ Added slapo-dynlist option to disable filter support (ITS#10025)
10+ Fixed liblber missing newline on long msg (ITS#10105)
11+ Fixed libldap exit handling with OpenSSL3 (ITS#9952)
12+ Fixed libldap with TLS and multiple ldap URIs (ITS#10101)
13+ Fixed libldap OpenSSL cipher suite handling (ITS#10094)
14+ Fixed libldap OpenSSL 3.0 and Diffie-Hellman param files (ITS#10124)
15+ Fixed libldap timestamps on Windows (ITS#10100)
16+ Fixed lloadd to work when resolv.conf is missing (ITS#10070)
17+ Fixed lloadd handling of closing connection (ITS#10083)
18+ Fixed slapd to honour disclose in matchedDN handling (ITS#10139)
19+ Fixed slapd handling of regex testing in ACLs (ITS#10089)
20+ Fixed slapd-asyncmeta when remote suffix is empty (ITS#10076)
21+ Fixed slapo-dynlist so it can't be global (ITS#10091)
22+ Build
23+ Fixed lloadd type mismatches (ITS#10074)
24+ Fixed builds for Windows (ITS#10117)
25+ Fixed build with clang16 (ITS#10123
26+ Documentation
27+ Fixed slapo-homedir(5) attribute name for olcHomedirArchivePath (ITS#10057)
28+ Minor Cleanup
29+ ITS#10059
30+ ITS#10068
31+ ITS#10109
32+ ITS#10110
33+ ITS#10129
34+ ITS#10130
35+ ITS#10135
36+ ITS#10144
37+ ITS#10145
38+ ITS#10153
39+
40 OpenLDAP 2.5.16 Release (2023/07/31)
41 Fixed slapd cn=config incorrect handling of paused (ITS#10045)
42 Fixed slapd-meta to account for MOD ops being optional (ITS#10067)
43diff --git a/build/version.var b/build/version.var
44index cd4e7aa..e2d54d0 100644
45--- a/build/version.var
46+++ b/build/version.var
47@@ -15,9 +15,9 @@
48 ol_package=OpenLDAP
49 ol_major=2
50 ol_minor=5
51-ol_patch=16
52-ol_api_inc=20516
53+ol_patch=17
54+ol_api_inc=20517
55 ol_api_current=1
56-ol_api_revision=11
57+ol_api_revision=12
58 ol_api_age=1
59-ol_release_date="2023/07/31"
60+ol_release_date="2024/01/29"
61diff --git a/clients/tools/common.c b/clients/tools/common.c
62index b88f219..9dfbb53 100644
63--- a/clients/tools/common.c
64+++ b/clients/tools/common.c
65@@ -1472,10 +1472,11 @@ tool_bind( LDAP *ld )
66
67 } else {
68 char *pw = getpassphrase( _("Enter LDAP Password: ") );
69- if ( pw ) {
70- passwd.bv_val = ber_strdup( pw );
71- passwd.bv_len = strlen( passwd.bv_val );
72+ if ( pw == NULL ) { /* Allow EOF to exit. */
73+ tool_exit( ld, EXIT_FAILURE );
74 }
75+ passwd.bv_val = ber_strdup( pw );
76+ passwd.bv_len = strlen( passwd.bv_val );
77 }
78 }
79
80diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c
81index 2cf14d1..036e5e1 100644
82--- a/clients/tools/ldappasswd.c
83+++ b/clients/tools/ldappasswd.c
84@@ -206,7 +206,12 @@ main( int argc, char *argv[] )
85 if( want_oldpw && oldpw.bv_val == NULL ) {
86 /* prompt for old password */
87 char *ckoldpw;
88- oldpw.bv_val = strdup(getpassphrase(_("Old password: ")));
89+ ckoldpw = getpassphrase(_("Old password: "));
90+ if ( ckoldpw == NULL ) { /* Allow EOF to exit. */
91+ rc = EXIT_FAILURE;
92+ goto done;
93+ }
94+ oldpw.bv_val = strdup( ckoldpw );
95 ckoldpw = getpassphrase(_("Re-enter old password: "));
96
97 if( oldpw.bv_val == NULL || ckoldpw == NULL ||
98@@ -231,7 +236,12 @@ main( int argc, char *argv[] )
99 if( want_newpw && newpw.bv_val == NULL ) {
100 /* prompt for new password */
101 char *cknewpw;
102- newpw.bv_val = strdup(getpassphrase(_("New password: ")));
103+ cknewpw = getpassphrase(_("New password: "));
104+ if ( cknewpw == NULL ) { /* Allow EOF to exit. */
105+ rc = EXIT_FAILURE;
106+ goto done;
107+ }
108+ newpw.bv_val = strdup( cknewpw );
109 cknewpw = getpassphrase(_("Re-enter new password: "));
110
111 if( newpw.bv_val == NULL || cknewpw == NULL ||
112diff --git a/clients/tools/ldapvc.c b/clients/tools/ldapvc.c
113index 4f35025..264f293 100644
114--- a/clients/tools/ldapvc.c
115+++ b/clients/tools/ldapvc.c
116@@ -309,8 +309,13 @@ main( int argc, char *argv[] )
117 #endif
118 && !cred.bv_val)
119 {
120- cred.bv_val = strdup(getpassphrase(_("User's password: ")));
121- cred.bv_len = strlen(cred.bv_val);
122+ char *userpw = getpassphrase(_("User's password: "));
123+ if ( userpw == NULL ) /* Allow EOF to exit. */
124+ {
125+ tool_exit( ld, EXIT_FAILURE );
126+ }
127+ cred.bv_val = strdup(userpw);
128+ cred.bv_len = strlen(cred.bv_val);
129 }
130
131 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
132diff --git a/contrib/slapd-modules/lastmod/lastmod.c b/contrib/slapd-modules/lastmod/lastmod.c
133index 116b9ae..b329ef7 100644
134--- a/contrib/slapd-modules/lastmod/lastmod.c
135+++ b/contrib/slapd-modules/lastmod/lastmod.c
136@@ -372,7 +372,7 @@ best_guess( Operation *op,
137
138 entryCSN.bv_val = csnbuf;
139 entryCSN.bv_len = sizeof( csnbuf );
140- slap_get_csn( NULL, &entryCSN, 0 );
141+ slap_get_csn( op, &entryCSN, 0 );
142
143 ber_dupbv( bv_entryCSN, &entryCSN );
144 ber_dupbv( bv_nentryCSN, &entryCSN );
145@@ -833,6 +833,11 @@ lastmod_db_open( BackendDB *be, ConfigReply *cr )
146 static char tmbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
147
148 char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
149+ void *thrctx = ldap_pvt_thread_pool_context();
150+ Connection conn = { 0 };
151+ OperationBuffer opbuf;
152+ Operation *op;
153+
154 struct berval entryCSN;
155 struct berval timestamp;
156
157@@ -841,6 +846,9 @@ lastmod_db_open( BackendDB *be, ConfigReply *cr )
158 return -1;
159 }
160
161+ connection_fake_init2( &conn, &opbuf, thrctx, 0 );
162+ op = &opbuf.ob_op;
163+
164 /*
165 * Start
166 */
167@@ -850,7 +858,7 @@ lastmod_db_open( BackendDB *be, ConfigReply *cr )
168
169 entryCSN.bv_val = csnbuf;
170 entryCSN.bv_len = sizeof( csnbuf );
171- slap_get_csn( NULL, &entryCSN, 0 );
172+ slap_get_csn( op, &entryCSN, 0 );
173
174 if ( BER_BVISNULL( &lmi->lmi_rdnvalue ) ) {
175 ber_str2bv( "Lastmod", 0, 1, &lmi->lmi_rdnvalue );
176diff --git a/debian/changelog b/debian/changelog
177index 96e71ea..5b5eb53 100644
178--- a/debian/changelog
179+++ b/debian/changelog
180@@ -1,3 +1,22 @@
181+openldap (2.5.17+dfsg-0ubuntu0.22.04.1) jammy; urgency=medium
182+
183+ * New upstream version (LP: #2040465).
184+ - Added slapo-dynlist option to disable filter support (ITS#10025)
185+ - Fixed liblber missing newline on long msg (ITS#10105)
186+ - Fixed libldap exit handling with OpenSSL3 (ITS#9952)
187+ - Fixed libldap with TLS and multiple ldap URIs (ITS#10101)
188+ - Fixed libldap OpenSSL cipher suite handling (ITS#10094)
189+ - Fixed libldap OpenSSL 3.0 and Diffie-Hellman param files (ITS#10124)
190+ - Fixed libldap timestamps on Windows (ITS#10100)
191+ - Fixed lloadd to work when resolv.conf is missing (ITS#10070)
192+ - Fixed lloadd handling of closing connection (ITS#10083)
193+ - Fixed slapd to honour disclose in matchedDN handling (ITS#10139)
194+ - Fixed slapd handling of regex testing in ACLs (ITS#10089)
195+ - Fixed slapd-asyncmeta when remote suffix is empty (ITS#10076)
196+ - Fixed slapo-dynlist so it can't be global (ITS#10091)
197+
198+ -- Sergio Durigan Junior <sergio.durigan@canonical.com> Fri, 09 Feb 2024 15:12:07 -0500
199+
200 openldap (2.5.16+dfsg-0ubuntu0.22.04.2) jammy-security; urgency=medium
201
202 * No change rebuild to fix CVE-2023-2953 in the -security pocket.
203diff --git a/doc/guide/admin/guide.html b/doc/guide/admin/guide.html
204index 679b61e..dc31ac2 100644
205--- a/doc/guide/admin/guide.html
206+++ b/doc/guide/admin/guide.html
207@@ -23,7 +23,7 @@
208 <DIV CLASS="title">
209 <H1 CLASS="doc-title">OpenLDAP Software 2.5 Administrator's Guide</H1>
210 <ADDRESS CLASS="doc-author">The OpenLDAP Project &lt;<A HREF="https://www.openldap.org/">https://www.openldap.org/</A>&gt;</ADDRESS>
211-<ADDRESS CLASS="doc-modified">31 July 2023</ADDRESS>
212+<ADDRESS CLASS="doc-modified">29 January 2024</ADDRESS>
213 <BR CLEAR="All">
214 </DIV>
215 <DIV CLASS="contents">
216diff --git a/doc/man/man5/lloadd.conf.5 b/doc/man/man5/lloadd.conf.5
217index 49c72b9..50269b3 100644
218--- a/doc/man/man5/lloadd.conf.5
219+++ b/doc/man/man5/lloadd.conf.5
220@@ -598,7 +598,16 @@ option. The authentication configuration is shared between them.
221 .B [secprops=<properties>]
222 .B [timeout=<seconds>]
223 .B [network\-timeout=<seconds>]
224+.B [keepalive=<idle>:<probes>:<interval>]
225 .B [tcp\-user\-timeout=<milliseconds>]
226+.B [tls_cert=<file>]
227+.B [tls_key=<file>]
228+.B [tls_cacert=<file>]
229+.B [tls_cacertdir=<path>]
230+.B [tls_reqcert=never|allow|try|demand]
231+.B [tls_cipher_suite=<ciphers>]
232+.B [tls_crlcheck=none|peer|all]
233+.B [tls_protocol_min=<major>[.<minor>]]
234
235 Specifies the bind credentials
236 .B lloadd
237@@ -658,6 +667,23 @@ Timeout set to 0 means no timeout is in effect and by default, no timeouts are
238 in effect.
239
240 The
241+.B keepalive
242+parameter sets the values of \fIidle\fP, \fIprobes\fP, and \fIinterval\fP
243+used to check whether a socket is alive;
244+.I idle
245+is the number of seconds a connection needs to remain idle before TCP
246+starts sending keepalive probes;
247+.I probes
248+is the maximum number of keepalive probes TCP should send before dropping
249+the connection;
250+.I interval
251+is interval in seconds between individual keepalive probes.
252+Only some systems support the customization of these values;
253+the
254+.B keepalive
255+parameter is ignored otherwise, and system-wide settings are used.
256+
257+The
258 .B tcp\-user\-timeout
259 parameter, if non-zero, corresponds to the
260 .B TCP_USER_TIMEOUT
261@@ -671,16 +697,7 @@ ignored otherwise and system-wide settings are used.
262 .B backend-server
263 .B uri=ldap[s]://<hostname>[:port]
264 .B [retry=<retry interval in ms>]
265-.B [keepalive=<idle>:<probes>:<interval>]
266 .B [starttls=yes|critical]
267-.B [tls_cert=<file>]
268-.B [tls_key=<file>]
269-.B [tls_cacert=<file>]
270-.B [tls_cacertdir=<path>]
271-.B [tls_reqcert=never|allow|try|demand]
272-.B [tls_cipher_suite=<ciphers>]
273-.B [tls_crlcheck=none|peer|all]
274-.B [tls_protocol_min=<major>[.<minor>]]
275 .B [numconns=<conns>]
276 .B [bindconns=<conns>]
277 .B [max-pending-ops=<ops>]
278@@ -725,23 +742,6 @@ connections,
279 the default, means no limit will be imposed for this backend.
280
281 The
282-.B keepalive
283-parameter sets the values of \fIidle\fP, \fIprobes\fP, and \fIinterval\fP
284-used to check whether a socket is alive;
285-.I idle
286-is the number of seconds a connection needs to remain idle before TCP
287-starts sending keepalive probes;
288-.I probes
289-is the maximum number of keepalive probes TCP should send before dropping
290-the connection;
291-.I interval
292-is interval in seconds between individual keepalive probes.
293-Only some systems support the customization of these values;
294-the
295-.B keepalive
296-parameter is ignored otherwise, and system-wide settings are used.
297-
298-The
299 .B starttls
300 parameter specifies use of the StartTLS extended operation
301 to establish a TLS session before Binding to the provider. If the
302diff --git a/doc/man/man5/slapo-dynlist.5 b/doc/man/man5/slapo-dynlist.5
303index 49a3d50..7fe0f70 100644
304--- a/doc/man/man5/slapo-dynlist.5
305+++ b/doc/man/man5/slapo-dynlist.5
306@@ -134,6 +134,13 @@ character is also specified, then the member and memberOf values will be
307 populated recursively, for nested groups. Note that currently nesting is
308 only supported for Search operations, not Compares.
309
310+.TP
311+.B dynlist\-simple TRUE | FALSE
312+This option downgrades to the behavior of the OpenLDAP 2.4 dynlist overlay.
313+It disables memberOf processing, nested group support, and filter evaluation
314+of dynamically generated values.
315+The default is FALSE.
316+
317 .LP
318 The dynlist overlay may be used with any backend, but it is mainly
319 intended for use with local storage backends.
320diff --git a/doc/man/man5/slapo-homedir.5 b/doc/man/man5/slapo-homedir.5
321index 5cd4ee8..cb1ac5b 100644
322--- a/doc/man/man5/slapo-homedir.5
323+++ b/doc/man/man5/slapo-homedir.5
324@@ -77,7 +77,7 @@ IGNORE.
325 .TP
326 .B homedir\-archive\-path <pathname>
327 .TP
328-.B olcArchivePath: pathname
329+.B olcHomedirArchivePath: pathname
330 These options specify the destination path for TAR files created by
331 the ARCHIVE delete style.
332 .SH REPLICATION
333@@ -90,6 +90,32 @@ for more information on configure syncrepl.
334
335 Partial replication (e.g. with filters) is especially useful for
336 providing different provisioning options to different sets of users.
337+.SH EXAMPLE
338+The following LDIF could be used to add this overlay to
339+.B cn=config
340+(adjust to suit)
341+.LP
342+.RS
343+.nf
344+dn: cn=module{0},cn=config
345+changetype: modify
346+add: olcModuleLoad
347+olcModuleLoad: homedir
348+
349+dn: olcOverlay=homedir,olcDatabase={1}mdb,cn=config
350+changetype: add
351+objectClass: olcOverlayConfig
352+objectClass: olcHomedirConfig
353+olcOverlay: homedir
354+olcSkeletonPath: /etc/skel
355+olcMinimumUidNumber: 1000
356+olcHomedirRegexp: ^(/home/[-_/a-z0-9]+)$ /export/$1
357+olcHomedirDeleteStyle: ARCHIVE
358+olcHomedirArchivePath: /archive
359+.fi
360+.RE
361+.LP
362+
363 .SH BUGS
364 DELETE, MOD, and MODRDN operations that remove the unix attributes
365 when delete style is set to DELETE will recursively delete the (regex
366@@ -113,6 +139,7 @@ resolve uid/gid into symbolic names.
367
368 No attempt is made to try to mkdir() the parent directories needed for
369 a given home directory or archive path.
370+
371 .SH FILES
372 .TP
373 ETCDIR/slapd.conf
374diff --git a/doc/man/man8/slapd.8 b/doc/man/man8/slapd.8
375index a93fcbc..809f9e7 100644
376--- a/doc/man/man8/slapd.8
377+++ b/doc/man/man8/slapd.8
378@@ -12,7 +12,7 @@ slapd \- Stand-alone LDAP Daemon
379 .BR \-4 | \-6 ]
380 [\c
381 .BR \-T \ { acl \||\| a [ dd ]\||\| auth \||\| c [ at ]\||\|
382-.BR d [ n ]\||\| i [ ndex ]\||\| p [ asswd ]\||\| s [ chema ]\||\| t [ est ]}]
383+.BR d [ n ]\||\| i [ ndex ]\||\| m [ odify ]\||\| p [ asswd ]\||\| s [ chema ]\||\| t [ est ]}]
384 [\c
385 .BI \-d \ debug-level\fR]
386 [\c
387@@ -87,6 +87,7 @@ Run in Tool mode. The \fItool\fP argument selects whether to run as
388 .IR slapcat ,
389 .IR slapdn ,
390 .IR slapindex ,
391+.IR slapmodify ,
392 .IR slappasswd ,
393 .IR slapschema ,
394 or
395@@ -366,6 +367,7 @@ To test whether the configuration file is correct or not, type:
396 .BR slapcat (8),
397 .BR slapdn (8),
398 .BR slapindex (8),
399+.BR slapmodify (8),
400 .BR slappasswd (8),
401 .BR slapschema (8),
402 .BR slaptest (8).
403diff --git a/include/ac/string.h b/include/ac/string.h
404index c4c1354..20a68d7 100644
405--- a/include/ac/string.h
406+++ b/include/ac/string.h
407@@ -58,7 +58,7 @@ LDAP_F(char *) ldap_pvt_strtok LDAP_P(( char *str,
408 #elif !defined(_WIN32)
409 /* some systems fail to declare strdup */
410 /* Windows does not require this declaration */
411- LDAP_LIBC_F(char *) (strdup)();
412+ LDAP_LIBC_F(char *) (strdup) LDAP_P((const char *s));
413 #endif
414
415 /*
416@@ -68,8 +68,8 @@ LDAP_F(char *) ldap_pvt_strtok LDAP_P(( char *str,
417
418 /* we don't want these declared for Windows or Mingw */
419 #ifndef _WIN32
420-int (strcasecmp)();
421-int (strncasecmp)();
422+LDAP_LIBC_F(int) (strcasecmp) LDAP_P((const char *s1, const char *s2));
423+LDAP_LIBC_F(int) (strncasecmp) LDAP_P((const char *s1, const char *s2, size_t n));
424 #endif
425
426 #ifndef SAFEMEMCPY
427diff --git a/libraries/liblber/debug.c b/libraries/liblber/debug.c
428index 1744e58..1f4fdbb 100644
429--- a/libraries/liblber/debug.c
430+++ b/libraries/liblber/debug.c
431@@ -43,12 +43,15 @@ void (lutil_debug)( int debug, int level, const char *fmt, ... )
432 {
433 char buffer[4096];
434 va_list vl;
435+ int len;
436
437 if ( !(level & debug ) ) return;
438
439 va_start( vl, fmt );
440- vsnprintf( buffer, sizeof(buffer), fmt, vl );
441+ len = vsnprintf( buffer, sizeof(buffer), fmt, vl );
442 va_end( vl );
443+ if ( len >= sizeof(buffer)-2 )
444+ buffer[sizeof(buffer)-2] = '\n';
445 ber_pvt_log_print( buffer );
446 }
447
448diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c
449index 6170596..7d8b52f 100644
450--- a/libraries/libldap/getdn.c
451+++ b/libraries/libldap/getdn.c
452@@ -2562,6 +2562,8 @@ rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len,
453 l += vl;
454 }
455 }
456+ if ( !iAVA )
457+ return( -1 ); /* RDN ::= SET SIZE (1..MAX) OF AVA */
458
459 *len = l;
460
461@@ -2635,6 +2637,8 @@ rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
462 l += vl;
463 }
464 }
465+ if ( !iAVA )
466+ return( -1 ); /* RDN ::= SET SIZE (1..MAX) OF AVA */
467
468 *len = l;
469
470@@ -2716,6 +2720,8 @@ rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
471 l += vl;
472 }
473 }
474+ if ( !iAVA )
475+ return( -1 ); /* RDN ::= SET SIZE (1..MAX) OF AVA */
476
477 *len = l;
478
479@@ -2794,6 +2800,8 @@ rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
480 l += vl;
481 }
482 }
483+ if ( !iAVA )
484+ return( -1 ); /* RDN ::= SET SIZE (1..MAX) OF AVA */
485
486 *len = l;
487
488diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c
489index 3a81790..b991553 100644
490--- a/libraries/libldap/init.c
491+++ b/libraries/libldap/init.c
492@@ -544,9 +544,6 @@ ldap_int_destroy_global_options(void)
493 gopts->ldo_def_sasl_authcid = NULL;
494 }
495 #endif
496-#ifdef HAVE_TLS
497- ldap_int_tls_destroy( gopts );
498-#endif
499 }
500
501 /*
502diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c
503index bfdbb25..93720eb 100644
504--- a/libraries/libldap/open.c
505+++ b/libraries/libldap/open.c
506@@ -543,6 +543,7 @@ ldap_int_open_connection(
507 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
508 }
509 ber_int_sb_close( conn->lconn_sb );
510+ ber_int_sb_destroy( conn->lconn_sb );
511 return -1;
512 }
513 }
514diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
515index 4a5d42b..f9dcbfc 100644
516--- a/libraries/libldap/tls2.c
517+++ b/libraries/libldap/tls2.c
518@@ -160,6 +160,14 @@ ldap_pvt_tls_destroy( void )
519 tls_imp->ti_tls_destroy();
520 }
521
522+static void
523+ldap_exit_tls_destroy( void )
524+{
525+ struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();
526+
527+ ldap_int_tls_destroy( lo );
528+}
529+
530 /*
531 * Initialize a particular TLS implementation.
532 * Called once per implementation.
533@@ -168,6 +176,7 @@ static int
534 tls_init(tls_impl *impl, int do_threads )
535 {
536 static int tls_initialized = 0;
537+ int rc;
538
539 if ( !tls_initialized++ ) {
540 #ifdef LDAP_R_COMPILE
541@@ -183,7 +192,10 @@ tls_init(tls_impl *impl, int do_threads )
542 #endif
543 }
544
545- return impl->ti_tls_init();
546+ rc = impl->ti_tls_init();
547+
548+ atexit( ldap_exit_tls_destroy );
549+ return rc;
550 }
551
552 /*
553diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
554index d6405bc..055d140 100644
555--- a/libraries/libldap/tls_o.c
556+++ b/libraries/libldap/tls_o.c
557@@ -294,7 +294,7 @@ tlso_stecpy( char *dst, const char *src, const char *end )
558 * Try to find any TLS1.3 ciphers in the given list of suites.
559 */
560 static void
561-tlso_ctx_cipher13( tlso_ctx *ctx, char *suites )
562+tlso_ctx_cipher13( tlso_ctx *ctx, char *suites, char **oldsuites )
563 {
564 char tls13_suites[1024], *ts = tls13_suites, *te = tls13_suites + sizeof(tls13_suites);
565 char *ptr, *colon, *nptr;
566@@ -303,6 +303,8 @@ tlso_ctx_cipher13( tlso_ctx *ctx, char *suites )
567 SSL *s = SSL_new( ctx );
568 int ret;
569
570+ *oldsuites = NULL;
571+
572 if ( !s )
573 return;
574
575@@ -334,8 +336,15 @@ tlso_ctx_cipher13( tlso_ctx *ctx, char *suites )
576 if ( tls13_suites[0] )
577 ts = tlso_stecpy( ts, ":", te );
578 ts = tlso_stecpy( ts, nptr, te );
579+ } else if (! *oldsuites) {
580+ /* should never happen, set_ciphersuites should
581+ * only succeed for TLSv1.3 and above
582+ */
583+ *oldsuites = ptr;
584 }
585 }
586+ } else if (! *oldsuites) {
587+ *oldsuites = ptr;
588 }
589 if ( !colon || ts >= te )
590 break;
591@@ -415,10 +424,11 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
592 }
593
594 if ( lo->ldo_tls_ciphersuite ) {
595+ char *oldsuites = lt->lt_ciphersuite;
596 #if OPENSSL_VERSION_NUMBER >= 0x10101000
597- tlso_ctx_cipher13( ctx, lt->lt_ciphersuite );
598+ tlso_ctx_cipher13( ctx, lt->lt_ciphersuite, &oldsuites );
599 #endif
600- if ( !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) )
601+ if ( oldsuites && !SSL_CTX_set_cipher_list( ctx, oldsuites ) )
602 {
603 Debug1( LDAP_DEBUG_ANY,
604 "TLS: could not set cipher list %s.\n",
605@@ -529,7 +539,7 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
606 if ( is_server && lo->ldo_tls_dhfile ) {
607 #if OPENSSL_VERSION_MAJOR >= 3
608 EVP_PKEY *dh;
609-#define bio_params( bio, dh ) dh = PEM_read_bio_Parameters( bio, &dh )
610+#define bio_params( bio, dh ) dh = PEM_read_bio_Parameters( bio, NULL )
611 #else
612 DH *dh;
613 #define bio_params( bio, dh ) dh = PEM_read_bio_DHparams( bio, NULL, NULL, NULL )
614diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c
615index 493fd7c..a56af30 100644
616--- a/libraries/libldap/url.c
617+++ b/libraries/libldap/url.c
618@@ -867,6 +867,10 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags
619 }
620
621 if ( enclosed ) {
622+ if ( ! *url ) {
623+ LDAP_FREE( url );
624+ return LDAP_URL_ERR_BADENCLOSURE;
625+ }
626 p = &url[strlen(url)-1];
627
628 if( *p != '>' ) {
629diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c
630index 57c6523..7cab9ea 100644
631--- a/libraries/libldap/util-int.c
632+++ b/libraries/libldap/util-int.c
633@@ -182,116 +182,65 @@ static int _ldap_pvt_gt_subs;
634 * This is pretty clunky.
635 */
636 static LARGE_INTEGER _ldap_pvt_gt_freq;
637-static LARGE_INTEGER _ldap_pvt_gt_prev;
638-static int _ldap_pvt_gt_offset;
639+static LARGE_INTEGER _ldap_pvt_gt_start_count;
640+static long _ldap_pvt_gt_start_sec;
641+static long _ldap_pvt_gt_start_nsec;
642+static double _ldap_pvt_gt_nanoticks;
643
644 #define SEC_TO_UNIX_EPOCH 11644473600LL
645 #define TICKS_PER_SECOND 10000000
646 #define BILLION 1000000000L
647
648 static int
649-ldap_pvt_gettimensec(int *sec)
650+ldap_pvt_gettimensec(long *sec)
651 {
652 LARGE_INTEGER count;
653+ LARGE_INTEGER freq;
654+ int nsec;
655
656- QueryPerformanceCounter( &count );
657-
658- /* It shouldn't ever go backwards, but multiple CPUs might
659- * be able to hit in the same tick.
660- */
661- LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex );
662+ QueryPerformanceFrequency( &freq );
663 /* We assume Windows has at least a vague idea of
664 * when a second begins. So we align our nanosecond count
665- * with the Windows millisecond count using this offset.
666- * We retain the submillisecond portion of our own count.
667- *
668- * Note - this also assumes that the relationship between
669- * the PerformanceCounter and SystemTime stays constant;
670- * that assumption breaks if the SystemTime is adjusted by
671- * an external action.
672+ * with the Windows millisecond count.
673 */
674- if ( !_ldap_pvt_gt_freq.QuadPart ) {
675- LARGE_INTEGER c2;
676+ if ( freq.QuadPart != _ldap_pvt_gt_freq.QuadPart ) {
677 ULARGE_INTEGER ut;
678 FILETIME ft0, ft1;
679- long long t;
680- int nsec;
681-
682- /* Initialize our offset */
683- QueryPerformanceFrequency( &_ldap_pvt_gt_freq );
684-
685+ /* initialize */
686+ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex );
687 /* Wait for a tick of the system time: 10-15ms */
688 GetSystemTimeAsFileTime( &ft0 );
689 do {
690 GetSystemTimeAsFileTime( &ft1 );
691 } while ( ft1.dwLowDateTime == ft0.dwLowDateTime );
692+ QueryPerformanceCounter( &_ldap_pvt_gt_start_count );
693
694 ut.LowPart = ft1.dwLowDateTime;
695 ut.HighPart = ft1.dwHighDateTime;
696- QueryPerformanceCounter( &c2 );
697-
698- /* get second and fraction portion of counter */
699- t = c2.QuadPart % (_ldap_pvt_gt_freq.QuadPart*10);
700-
701- /* convert to nanoseconds */
702- t *= BILLION;
703- nsec = t / _ldap_pvt_gt_freq.QuadPart;
704-
705- ut.QuadPart /= 10;
706- ut.QuadPart %= (10 * BILLION);
707- _ldap_pvt_gt_offset = nsec - ut.QuadPart;
708- count = c2;
709+ _ldap_pvt_gt_start_nsec = ut.QuadPart % TICKS_PER_SECOND * 100;
710+ _ldap_pvt_gt_start_sec = ut.QuadPart / TICKS_PER_SECOND - SEC_TO_UNIX_EPOCH;
711+ _ldap_pvt_gt_freq = freq;
712+ _ldap_pvt_gt_nanoticks = (double)BILLION / freq.QuadPart;
713+ LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex );
714 }
715- if ( count.QuadPart <= _ldap_pvt_gt_prev.QuadPart ) {
716- _ldap_pvt_gt_subs++;
717- } else {
718- _ldap_pvt_gt_subs = 0;
719- _ldap_pvt_gt_prev = count;
720+ QueryPerformanceCounter( &count );
721+ count.QuadPart -= _ldap_pvt_gt_start_count.QuadPart;
722+ *sec = _ldap_pvt_gt_start_sec + count.QuadPart / freq.QuadPart;
723+ nsec = _ldap_pvt_gt_start_nsec + (double)(count.QuadPart % freq.QuadPart) * _ldap_pvt_gt_nanoticks;
724+ if ( nsec > BILLION) {
725+ nsec -= BILLION;
726+ (*sec)++;
727 }
728- LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex );
729-
730- /* convert to nanoseconds */
731- count.QuadPart %= _ldap_pvt_gt_freq.QuadPart*10;
732- count.QuadPart *= BILLION;
733- count.QuadPart /= _ldap_pvt_gt_freq.QuadPart;
734- count.QuadPart -= _ldap_pvt_gt_offset;
735-
736- /* We've extracted the 1s and nanoseconds.
737- * The 1sec digit is used to detect wraparound in nanosecnds.
738- */
739- if (count.QuadPart < 0)
740- count.QuadPart += (10 * BILLION);
741- else if (count.QuadPart >= (10 * BILLION))
742- count.QuadPart -= (10 * BILLION);
743-
744- *sec = count.QuadPart / BILLION;
745- return count.QuadPart % BILLION;
746+ return nsec;
747 }
748
749-
750 /* emulate POSIX clock_gettime */
751 int
752 ldap_pvt_clock_gettime( int clk_id, struct timespec *tv )
753 {
754- FILETIME ft;
755- ULARGE_INTEGER ut;
756- int sec, sec0;
757-
758- GetSystemTimeAsFileTime( &ft );
759- ut.LowPart = ft.dwLowDateTime;
760- ut.HighPart = ft.dwHighDateTime;
761-
762- /* convert to sec */
763- ut.QuadPart /= TICKS_PER_SECOND;
764-
765- tv->tv_nsec = ldap_pvt_gettimensec(&sec);
766- tv->tv_sec = ut.QuadPart - SEC_TO_UNIX_EPOCH;
767-
768- /* check for carry from microseconds */
769- sec0 = tv->tv_sec % 10;
770- if (sec0 < sec || (sec0 == 9 && !sec))
771- tv->tv_sec++;
772-
773+ long sec;
774+ tv->tv_nsec = ldap_pvt_gettimensec( &sec );
775+ tv->tv_sec = sec;
776 return 0;
777 }
778
779@@ -306,6 +255,8 @@ ldap_pvt_gettimeofday( struct timeval *tv, void *unused )
780 return 0;
781 }
782
783+static long _ldap_pvt_gt_prevsec;
784+static int _ldap_pvt_gt_prevnsec;
785
786 /* return a broken out time, with nanoseconds
787 */
788@@ -313,17 +264,18 @@ void
789 ldap_pvt_gettime( struct lutil_tm *tm )
790 {
791 SYSTEMTIME st;
792- int sec, sec0;
793- static const char daysPerMonth[] = {
794- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
795+ LARGE_INTEGER ft;
796+ long sec;
797
798- GetSystemTime( &st );
799+ /* Convert sec/nsec to Windows FILETIME,
800+ * then turn that into broken out SYSTEMTIME */
801 tm->tm_nsec = ldap_pvt_gettimensec(&sec);
802- tm->tm_usub = _ldap_pvt_gt_subs;
803+ ft.QuadPart = sec;
804+ ft.QuadPart += SEC_TO_UNIX_EPOCH;
805+ ft.QuadPart *= TICKS_PER_SECOND;
806+ ft.QuadPart += tm->tm_nsec / 100;
807+ FileTimeToSystemTime( (FILETIME *)&ft, &st );
808
809- /* any difference larger than nanoseconds is
810- * already reflected in st
811- */
812 tm->tm_sec = st.wSecond;
813 tm->tm_min = st.wMinute;
814 tm->tm_hour = st.wHour;
815@@ -331,42 +283,18 @@ ldap_pvt_gettime( struct lutil_tm *tm )
816 tm->tm_mon = st.wMonth - 1;
817 tm->tm_year = st.wYear - 1900;
818
819- /* check for carry from nanoseconds */
820- sec0 = tm->tm_sec % 10;
821- if (sec0 < sec || (sec0 == 9 && !sec)) {
822- tm->tm_sec++;
823- /* FIXME: we don't handle leap seconds */
824- if (tm->tm_sec > 59) {
825- tm->tm_sec = 0;
826- tm->tm_min++;
827- if (tm->tm_min > 59) {
828- tm->tm_min = 0;
829- tm->tm_hour++;
830- if (tm->tm_hour > 23) {
831- int days = daysPerMonth[tm->tm_mon];
832- tm->tm_hour = 0;
833- tm->tm_mday++;
834-
835- /* if it's February of a leap year,
836- * add 1 day to this month
837- */
838- if (tm->tm_mon == 1 &&
839- ((!(st.wYear % 4) && (st.wYear % 100)) ||
840- !(st.wYear % 400)))
841- days++;
842-
843- if (tm->tm_mday > days) {
844- tm->tm_mday = 1;
845- tm->tm_mon++;
846- if (tm->tm_mon > 11) {
847- tm->tm_mon = 0;
848- tm->tm_year++;
849- }
850- }
851- }
852- }
853- }
854+ LDAP_MUTEX_LOCK( &ldap_int_gettime_mutex );
855+ if ( tm->tm_sec < _ldap_pvt_gt_prevsec
856+ || ( tm->tm_sec == _ldap_pvt_gt_prevsec
857+ && tm->tm_nsec <= _ldap_pvt_gt_prevnsec )) {
858+ _ldap_pvt_gt_subs++;
859+ } else {
860+ _ldap_pvt_gt_subs = 0;
861+ _ldap_pvt_gt_prevsec = sec;
862+ _ldap_pvt_gt_prevnsec = tm->tm_nsec;
863 }
864+ LDAP_MUTEX_UNLOCK( &ldap_int_gettime_mutex );
865+ tm->tm_usub = _ldap_pvt_gt_subs;
866 }
867 #else
868
869diff --git a/libraries/liblmdb/CHANGES b/libraries/liblmdb/CHANGES
870index 76dd591..10e81d5 100644
871--- a/libraries/liblmdb/CHANGES
872+++ b/libraries/liblmdb/CHANGES
873@@ -1,5 +1,11 @@
874 LMDB 0.9 Change Log
875
876+LMDB 0.9.32 Release (2024/01/29)
877+ ITS#9378 - Add ability to replay log and replay log tool
878+ ITS#10095 - partial revert of ITS#9278. The patch was incorrect and introduced numerous race conditions.
879+ ITS#10125 - mdb_load: fix cursor reinit in Append mode
880+ ITS#10137 - Allow users to define MDB_IDL_LOGN
881+
882 LMDB 0.9.31 Release (2023/07/10)
883 ITS#8447 - Fix cursor_put(MDB_CURRENT) on DUPSORT DB with different sized data
884
885diff --git a/libraries/liblmdb/Makefile b/libraries/liblmdb/Makefile
886index f254511..000f1f9 100644
887--- a/libraries/liblmdb/Makefile
888+++ b/libraries/liblmdb/Makefile
889@@ -78,6 +78,7 @@ mtest3: mtest3.o liblmdb.a
890 mtest4: mtest4.o liblmdb.a
891 mtest5: mtest5.o liblmdb.a
892 mtest6: mtest6.o liblmdb.a
893+mplay: mplay.o liblmdb.a
894
895 mdb.o: mdb.c lmdb.h midl.h
896 $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c
897diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h
898index ff03c22..d638a67 100644
899--- a/libraries/liblmdb/lmdb.h
900+++ b/libraries/liblmdb/lmdb.h
901@@ -200,7 +200,7 @@ typedef int mdb_filehandle_t;
902 /** Library minor version */
903 #define MDB_VERSION_MINOR 9
904 /** Library patch version */
905-#define MDB_VERSION_PATCH 31
906+#define MDB_VERSION_PATCH 32
907
908 /** Combine args a,b,c into a single integer for easy version comparisons */
909 #define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
910@@ -210,7 +210,7 @@ typedef int mdb_filehandle_t;
911 MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
912
913 /** The release date of this library version */
914-#define MDB_VERSION_DATE "July 10, 2023"
915+#define MDB_VERSION_DATE "January 29, 2024"
916
917 /** A stringifier for the version info */
918 #define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
919diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c
920index deb6779..0570dea 100644
921--- a/libraries/liblmdb/mdb.c
922+++ b/libraries/liblmdb/mdb.c
923@@ -481,18 +481,26 @@ typedef MDB_ID txnid_t;
924 #define MDB_DEBUG 0
925 #endif
926
927+#define MDB_DBG_INFO 1
928+#define MDB_DBG_TRACE 2
929+
930 #if MDB_DEBUG
931-static int mdb_debug;
932+static int mdb_debug = MDB_DBG_TRACE;
933 static txnid_t mdb_debug_start;
934
935 /** Print a debug message with printf formatting.
936 * Requires double parenthesis around 2 or more args.
937 */
938-# define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args))
939+# define DPRINTF(args) ((void) ((mdb_debug & MDB_DBG_INFO) && DPRINTF0 args))
940 # define DPRINTF0(fmt, ...) \
941 fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__)
942+ /** Trace info for replaying */
943+# define MDB_TRACE(args) ((void) ((mdb_debug & MDB_DBG_TRACE) && DPRINTF1 args))
944+# define DPRINTF1(fmt, ...) \
945+ fprintf(stderr, ">%d:%s: " fmt "\n", getpid(), mdb_func_, __VA_ARGS__)
946 #else
947 # define DPRINTF(args) ((void) 0)
948+# define MDB_TRACE(args) ((void) 0)
949 #endif
950 /** Print a debug string.
951 * The string is printed literally, with no format processing.
952@@ -589,6 +597,11 @@ static txnid_t mdb_debug_start;
953 * This is used for printing a hex dump of a key's contents.
954 */
955 #define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1]
956+ /** A data value buffer.
957+ * @ingroup debug
958+ * This is used for printing a hex dump of a #MDB_DUPSORT value's contents.
959+ */
960+#define DDBUF char dbuf[DKBUF_MAXKEYSIZE*2+1+2]
961 /** Display a key in hex.
962 * @ingroup debug
963 * Invoke a function to display a key in hex.
964@@ -596,6 +609,7 @@ static txnid_t mdb_debug_start;
965 #define DKEY(x) mdb_dkey(x, kbuf)
966 #else
967 #define DKBUF
968+#define DDBUF
969 #define DKEY(x) 0
970 #endif
971
972@@ -1423,6 +1437,9 @@ static int mdb_update_key(MDB_cursor *mc, MDB_val *key);
973 static void mdb_cursor_pop(MDB_cursor *mc);
974 static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp);
975
976+static int _mdb_cursor_del(MDB_cursor *mc, unsigned int flags);
977+static int _mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, unsigned int flags);
978+
979 static int mdb_cursor_del0(MDB_cursor *mc);
980 static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags);
981 static int mdb_cursor_sibling(MDB_cursor *mc, int move_right);
982@@ -1614,6 +1631,18 @@ mdb_dkey(MDB_val *key, char *buf)
983 return buf;
984 }
985
986+static char *
987+mdb_dval(MDB_txn *txn, MDB_dbi dbi, MDB_val *data, char *buf)
988+{
989+ if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
990+ mdb_dkey(data, buf+1);
991+ *buf = '[';
992+ strcpy(buf + data->mv_size * 2 + 1, "]");
993+ } else
994+ *buf = '\0';
995+ return buf;
996+}
997+
998 static const char *
999 mdb_leafnode_type(MDB_node *n)
1000 {
1001@@ -2786,7 +2815,7 @@ mdb_txn_renew0(MDB_txn *txn)
1002 txn->mt_txnid++;
1003 #if MDB_DEBUG
1004 if (txn->mt_txnid == mdb_debug_start)
1005- mdb_debug = 1;
1006+ mdb_debug = MDB_DBG_INFO;
1007 #endif
1008 txn->mt_child = NULL;
1009 txn->mt_loose_pgs = NULL;
1010@@ -2945,6 +2974,7 @@ renew:
1011 txn->mt_txnid, (flags & MDB_RDONLY) ? 'r' : 'w',
1012 (void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root));
1013 }
1014+ MDB_TRACE(("%p, %p, %u = %p", env, parent, flags, txn));
1015
1016 return rc;
1017 }
1018@@ -3080,18 +3110,25 @@ mdb_txn_reset(MDB_txn *txn)
1019 mdb_txn_end(txn, MDB_END_RESET);
1020 }
1021
1022-void
1023-mdb_txn_abort(MDB_txn *txn)
1024+static void
1025+_mdb_txn_abort(MDB_txn *txn)
1026 {
1027 if (txn == NULL)
1028 return;
1029
1030 if (txn->mt_child)
1031- mdb_txn_abort(txn->mt_child);
1032+ _mdb_txn_abort(txn->mt_child);
1033
1034 mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE);
1035 }
1036
1037+void
1038+mdb_txn_abort(MDB_txn *txn)
1039+{
1040+ MDB_TRACE(("%p", txn));
1041+ _mdb_txn_abort(txn);
1042+}
1043+
1044 /** Save the freelist as of this transaction to the freeDB.
1045 * This changes the freelist. Keep trying until it stabilizes.
1046 */
1047@@ -3182,7 +3219,7 @@ mdb_freelist_save(MDB_txn *txn)
1048 pglast = head_id = *(txnid_t *)key.mv_data;
1049 total_room = head_room = 0;
1050 mdb_tassert(txn, pglast <= env->me_pglast);
1051- rc = mdb_cursor_del(&mc, 0);
1052+ rc = _mdb_cursor_del(&mc, 0);
1053 if (rc)
1054 return rc;
1055 }
1056@@ -3202,7 +3239,7 @@ mdb_freelist_save(MDB_txn *txn)
1057 do {
1058 freecnt = free_pgs[0];
1059 data.mv_size = MDB_IDL_SIZEOF(free_pgs);
1060- rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
1061+ rc = _mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
1062 if (rc)
1063 return rc;
1064 /* Retry if mt_free_pgs[] grew during the Put() */
1065@@ -3251,7 +3288,7 @@ mdb_freelist_save(MDB_txn *txn)
1066 key.mv_size = sizeof(head_id);
1067 key.mv_data = &head_id;
1068 data.mv_size = (head_room + 1) * sizeof(pgno_t);
1069- rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
1070+ rc = _mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
1071 if (rc)
1072 return rc;
1073 /* IDL is initially empty, zero out at least the length */
1074@@ -3306,7 +3343,7 @@ mdb_freelist_save(MDB_txn *txn)
1075 data.mv_data = mop -= len;
1076 save = mop[0];
1077 mop[0] = len;
1078- rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT);
1079+ rc = _mdb_cursor_put(&mc, &key, &data, MDB_CURRENT);
1080 mop[0] = save;
1081 if (rc || !(mop_len -= len))
1082 break;
1083@@ -3467,8 +3504,8 @@ done:
1084 return MDB_SUCCESS;
1085 }
1086
1087-int
1088-mdb_txn_commit(MDB_txn *txn)
1089+static int
1090+_mdb_txn_commit(MDB_txn *txn)
1091 {
1092 int rc;
1093 unsigned int i, end_mode;
1094@@ -3481,7 +3518,7 @@ mdb_txn_commit(MDB_txn *txn)
1095 end_mode = MDB_END_EMPTY_COMMIT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE;
1096
1097 if (txn->mt_child) {
1098- rc = mdb_txn_commit(txn->mt_child);
1099+ rc = _mdb_txn_commit(txn->mt_child);
1100 if (rc)
1101 goto fail;
1102 }
1103@@ -3661,7 +3698,7 @@ mdb_txn_commit(MDB_txn *txn)
1104 goto fail;
1105 }
1106 data.mv_data = &txn->mt_dbs[i];
1107- rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data,
1108+ rc = _mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data,
1109 F_SUBDATA);
1110 if (rc)
1111 goto fail;
1112@@ -3692,10 +3729,17 @@ done:
1113 return MDB_SUCCESS;
1114
1115 fail:
1116- mdb_txn_abort(txn);
1117+ _mdb_txn_abort(txn);
1118 return rc;
1119 }
1120
1121+int
1122+mdb_txn_commit(MDB_txn *txn)
1123+{
1124+ MDB_TRACE(("%p", txn));
1125+ return _mdb_txn_commit(txn);
1126+}
1127+
1128 /** Read the environment parameters of a DB environment before
1129 * mapping it into memory.
1130 * @param[in] env the environment handle
1131@@ -3992,6 +4036,7 @@ mdb_env_create(MDB_env **env)
1132 GET_PAGESIZE(e->me_os_psize);
1133 VGMEMP_CREATE(e,0,0);
1134 *env = e;
1135+ MDB_TRACE(("%p", e));
1136 return MDB_SUCCESS;
1137 }
1138
1139@@ -4115,6 +4160,7 @@ mdb_env_set_mapsize(MDB_env *env, size_t size)
1140 env->me_mapsize = size;
1141 if (env->me_psize)
1142 env->me_maxpg = env->me_mapsize / env->me_psize;
1143+ MDB_TRACE(("%p, %"Yu"", env, size));
1144 return MDB_SUCCESS;
1145 }
1146
1147@@ -4124,6 +4170,7 @@ mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
1148 if (env->me_map)
1149 return EINVAL;
1150 env->me_maxdbs = dbs + CORE_DBS;
1151+ MDB_TRACE(("%p, %u", env, dbs));
1152 return MDB_SUCCESS;
1153 }
1154
1155@@ -4133,6 +4180,7 @@ mdb_env_set_maxreaders(MDB_env *env, unsigned int readers)
1156 if (env->me_map || readers < 1)
1157 return EINVAL;
1158 env->me_maxreaders = readers;
1159+ MDB_TRACE(("%p, %u", env, readers));
1160 return MDB_SUCCESS;
1161 }
1162
1163@@ -5076,6 +5124,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
1164 }
1165
1166 leave:
1167+ MDB_TRACE(("%p, %s, %u, %04o", env, path, flags & (CHANGEABLE|CHANGELESS), mode));
1168 if (rc) {
1169 mdb_env_close0(env, excl);
1170 }
1171@@ -5162,17 +5211,6 @@ mdb_env_close0(MDB_env *env, int excl)
1172 sem_unlink(env->me_txns->mti_wmname);
1173 }
1174 }
1175-#elif defined(MDB_ROBUST_SUPPORTED)
1176- /* If we have the filelock: If we are the
1177- * only remaining user, clean up robust
1178- * mutexes.
1179- */
1180- if (excl == 0)
1181- mdb_env_excl_lock(env, &excl);
1182- if (excl > 0) {
1183- pthread_mutex_destroy(env->me_txns->mti_rmutex);
1184- pthread_mutex_destroy(env->me_txns->mti_wmutex);
1185- }
1186 #endif
1187 munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo));
1188 }
1189@@ -5199,6 +5237,7 @@ mdb_env_close(MDB_env *env)
1190 if (env == NULL)
1191 return;
1192
1193+ MDB_TRACE(("%p", env));
1194 VGMEMP_DESTROY(env);
1195 while ((dp = env->me_dpages) != NULL) {
1196 VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
1197@@ -6570,8 +6609,8 @@ mdb_cursor_touch(MDB_cursor *mc)
1198 /** Do not spill pages to disk if txn is getting full, may fail instead */
1199 #define MDB_NOSPILL 0x8000
1200
1201-int
1202-mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
1203+static int
1204+_mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
1205 unsigned int flags)
1206 {
1207 MDB_env *env;
1208@@ -7034,7 +7073,7 @@ put_sub:
1209 new_dupdata = (int)dkey.mv_size;
1210 /* converted, write the original data first */
1211 if (dkey.mv_size) {
1212- rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
1213+ rc = _mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
1214 if (rc)
1215 goto bad_sub;
1216 /* we've done our job */
1217@@ -7062,7 +7101,7 @@ put_sub:
1218 ecount = mc->mc_xcursor->mx_db.md_entries;
1219 if (flags & MDB_APPENDDUP)
1220 xflags |= MDB_APPEND;
1221- rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags);
1222+ rc = _mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags);
1223 if (flags & F_SUBDATA) {
1224 void *db = NODEDATA(leaf);
1225 memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db));
1226@@ -7103,7 +7142,20 @@ bad_sub:
1227 }
1228
1229 int
1230-mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
1231+mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
1232+ unsigned int flags)
1233+{
1234+ DKBUF;
1235+ DDBUF;
1236+ int rc = _mdb_cursor_put(mc, key, data, flags);
1237+ MDB_TRACE(("%p, %"Z"u[%s], %"Z"u%s, %u",
1238+ mc, key ? key->mv_size:0, DKEY(key), data ? data->mv_size:0,
1239+ data ? mdb_dval(mc->mc_txn, mc->mc_dbi, data, dbuf):"", flags));
1240+ return rc;
1241+}
1242+
1243+static int
1244+_mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
1245 {
1246 MDB_node *leaf;
1247 MDB_page *mp;
1248@@ -7141,7 +7193,7 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
1249 if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
1250 mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
1251 }
1252- rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL);
1253+ rc = _mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL);
1254 if (rc)
1255 return rc;
1256 /* If sub-DB still has entries, we're done */
1257@@ -7205,6 +7257,14 @@ fail:
1258 return rc;
1259 }
1260
1261+int
1262+mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
1263+{
1264+ MDB_TRACE(("%p, %u",
1265+ mc, flags));
1266+ return _mdb_cursor_del(mc, flags);
1267+}
1268+
1269 /** Allocate and initialize new pages for a database.
1270 * Set #MDB_TXN_ERROR on failure.
1271 * @param[in] mc a cursor on the database being added to.
1272@@ -7698,6 +7758,7 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
1273 return ENOMEM;
1274 }
1275
1276+ MDB_TRACE(("%p, %u = %p", txn, dbi, mc));
1277 *ret = mc;
1278
1279 return MDB_SUCCESS;
1280@@ -7761,6 +7822,7 @@ mdb_cursor_count(MDB_cursor *mc, size_t *countp)
1281 void
1282 mdb_cursor_close(MDB_cursor *mc)
1283 {
1284+ MDB_TRACE(("%p", mc));
1285 if (mc && !mc->mc_backup) {
1286 /* remove from txn, if tracked */
1287 if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) {
1288@@ -8570,6 +8632,8 @@ int
1289 mdb_del(MDB_txn *txn, MDB_dbi dbi,
1290 MDB_val *key, MDB_val *data)
1291 {
1292+ DKBUF;
1293+ DDBUF;
1294 if (!key || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
1295 return EINVAL;
1296
1297@@ -8581,6 +8645,9 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
1298 data = NULL;
1299 }
1300
1301+ MDB_TRACE(("%p, %u, %"Z"u[%s], %"Z"u%s",
1302+ txn, dbi, key ? key->mv_size:0, DKEY(key), data ? data->mv_size:0,
1303+ data ? mdb_dval(txn, dbi, data, dbuf):""));
1304 return mdb_del0(txn, dbi, key, data, 0);
1305 }
1306
1307@@ -8621,7 +8688,7 @@ mdb_del0(MDB_txn *txn, MDB_dbi dbi,
1308 mc.mc_flags |= C_UNTRACK;
1309 mc.mc_next = txn->mt_cursors[dbi];
1310 txn->mt_cursors[dbi] = &mc;
1311- rc = mdb_cursor_del(&mc, flags);
1312+ rc = _mdb_cursor_del(&mc, flags);
1313 txn->mt_cursors[dbi] = mc.mc_next;
1314 }
1315 return rc;
1316@@ -9063,6 +9130,8 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
1317 MDB_cursor mc;
1318 MDB_xcursor mx;
1319 int rc;
1320+ DKBUF;
1321+ DDBUF;
1322
1323 if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
1324 return EINVAL;
1325@@ -9073,10 +9142,12 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
1326 if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
1327 return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
1328
1329+ MDB_TRACE(("%p, %u, %"Z"u[%s], %"Z"u%s, %u",
1330+ txn, dbi, key ? key->mv_size:0, DKEY(key), data->mv_size, mdb_dval(txn, dbi, data, dbuf), flags));
1331 mdb_cursor_init(&mc, txn, dbi, &mx);
1332 mc.mc_next = txn->mt_cursors[dbi];
1333 txn->mt_cursors[dbi] = &mc;
1334- rc = mdb_cursor_put(&mc, key, data, flags);
1335+ rc = _mdb_cursor_put(&mc, key, data, flags);
1336 txn->mt_cursors[dbi] = mc.mc_next;
1337 return rc;
1338 }
1339@@ -9479,7 +9550,7 @@ finish:
1340 my.mc_error = rc;
1341 mdb_env_cthr_toggle(&my, 1 | MDB_EOF);
1342 rc = THREAD_FINISH(thr);
1343- mdb_txn_abort(txn);
1344+ _mdb_txn_abort(txn);
1345
1346 done:
1347 #ifdef _WIN32
1348@@ -9591,7 +9662,7 @@ mdb_env_copyfd0(MDB_env *env, HANDLE fd)
1349 }
1350
1351 leave:
1352- mdb_txn_abort(txn);
1353+ _mdb_txn_abort(txn);
1354 return rc;
1355 }
1356
1357@@ -9806,6 +9877,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
1358 }
1359 }
1360 mdb_default_cmp(txn, MAIN_DBI);
1361+ MDB_TRACE(("%p, (null), %u = %u", txn, flags, MAIN_DBI));
1362 return MDB_SUCCESS;
1363 }
1364
1365@@ -9867,7 +9939,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
1366 dummy.md_root = P_INVALID;
1367 dummy.md_flags = flags & PERSISTENT_FLAGS;
1368 WITH_CURSOR_TRACKING(mc,
1369- rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA));
1370+ rc = _mdb_cursor_put(&mc, &key, &data, F_SUBDATA));
1371 dbflag |= DB_DIRTY;
1372 }
1373
1374@@ -9892,6 +9964,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
1375 if (!unused) {
1376 txn->mt_numdbs++;
1377 }
1378+ MDB_TRACE(("%p, %s, %u = %u", txn, name, flags, slot));
1379 }
1380
1381 return rc;
1382@@ -9923,6 +9996,7 @@ void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
1383 ptr = env->me_dbxs[dbi].md_name.mv_data;
1384 /* If there was no name, this was already closed */
1385 if (ptr) {
1386+ MDB_TRACE(("%p, %u", env, dbi));
1387 env->me_dbxs[dbi].md_name.mv_data = NULL;
1388 env->me_dbxs[dbi].md_name.mv_size = 0;
1389 env->me_dbflags[dbi] = 0;
1390@@ -10057,6 +10131,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
1391 if (rc)
1392 return rc;
1393
1394+ MDB_TRACE(("%u, %d", dbi, del));
1395 rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT);
1396 /* Invalidate the dropped DB's cursors */
1397 for (m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next)
1398diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c
1399index d2a3cec..cba6c06 100644
1400--- a/libraries/liblmdb/mdb_load.c
1401+++ b/libraries/liblmdb/mdb_load.c
1402@@ -449,7 +449,7 @@ int main(int argc, char *argv[])
1403 if (rc == MDB_KEYEXIST && putflags)
1404 continue;
1405 if (rc) {
1406- fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc));
1407+ fprintf(stderr, "%s: line %" Z "d: mdb_cursor_put failed, error %d %s\n", prog, lineno, rc, mdb_strerror(rc));
1408 goto txn_abort;
1409 }
1410 batch++;
1411@@ -470,9 +470,11 @@ int main(int argc, char *argv[])
1412 fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
1413 goto txn_abort;
1414 }
1415- if (appflag & MDB_APPENDDUP) {
1416+ if (append) {
1417 MDB_val k, d;
1418 mdb_cursor_get(mc, &k, &d, MDB_LAST);
1419+ memcpy(prevk.mv_data, k.mv_data, k.mv_size);
1420+ prevk.mv_size = k.mv_size;
1421 }
1422 batch = 0;
1423 }
1424diff --git a/libraries/liblmdb/midl.h b/libraries/liblmdb/midl.h
1425index 2075206..ff740ae 100644
1426--- a/libraries/liblmdb/midl.h
1427+++ b/libraries/liblmdb/midl.h
1428@@ -56,7 +56,9 @@ typedef MDB_ID *MDB_IDL;
1429 /* IDL sizes - likely should be even bigger
1430 * limiting factors: sizeof(ID), thread stack size
1431 */
1432+#ifndef MDB_IDL_LOGN
1433 #define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
1434+#endif
1435 #define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
1436 #define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
1437
1438diff --git a/libraries/liblmdb/mplay.c b/libraries/liblmdb/mplay.c
1439new file mode 100644
1440index 0000000..0fef74f
1441--- /dev/null
1442+++ b/libraries/liblmdb/mplay.c
1443@@ -0,0 +1,582 @@
1444+/* mplay.c - memory-mapped database log replay */
1445+/*
1446+ * Copyright 2011-2023 Howard Chu, Symas Corp.
1447+ * All rights reserved.
1448+ *
1449+ * Redistribution and use in source and binary forms, with or without
1450+ * modification, are permitted only as authorized by the OpenLDAP
1451+ * Public License.
1452+ *
1453+ * A copy of this license is available in the file LICENSE in the
1454+ * top-level directory of the distribution or, alternatively, at
1455+ * <http://www.OpenLDAP.org/license.html>.
1456+ */
1457+#include <stdio.h>
1458+#include <stdlib.h>
1459+#include <unistd.h>
1460+#include <time.h>
1461+#include <string.h>
1462+#include <ctype.h>
1463+#include <assert.h>
1464+#include <sys/types.h>
1465+#include <sys/wait.h>
1466+
1467+#include "lmdb.h"
1468+
1469+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
1470+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
1471+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
1472+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
1473+
1474+#define MDB_SCNy(t) "z" #t
1475+
1476+#define SCMP(s) s, (sizeof(s)-1)
1477+char inbuf[8192];
1478+char *dbuf, *kbuf;
1479+size_t dbufsize;
1480+int maxkey;
1481+
1482+#define SOFF(s) (sizeof(s)+1)
1483+
1484+#define MAXENVS 16
1485+#define MAXTXNS 16
1486+#define MAXCRSS 16
1487+
1488+#define MAXPIDS 16
1489+
1490+typedef struct crspair {
1491+ void *tcrs; /* scanned text pointer */
1492+ MDB_cursor *rcrs;
1493+} crspair;
1494+
1495+typedef struct txnpair {
1496+ void *ttxn; /* scanned text pointer */
1497+ MDB_txn *rtxn;
1498+ crspair cursors[MAXCRSS];
1499+ int ncursors;
1500+} txnpair;
1501+
1502+typedef struct envpair {
1503+ void *tenv;
1504+ MDB_env *renv;
1505+ txnpair txns[MAXTXNS];
1506+ int ntxns;
1507+} envpair;
1508+
1509+envpair envs[MAXENVS];
1510+int nenvs;
1511+
1512+envpair *lastenv;
1513+txnpair *lasttxn;
1514+crspair *lastcrs;
1515+
1516+typedef struct pidpair {
1517+ int tpid;
1518+ pid_t rpid;
1519+ int fdout, fdin;
1520+} pidpair;
1521+
1522+pidpair *lastpid;
1523+
1524+pidpair pids[MAXPIDS];
1525+int npids;
1526+
1527+unsigned long lcount;
1528+
1529+static int unhex(unsigned char *c2)
1530+{
1531+ int x, c;
1532+ x = *c2++ & 0x4f;
1533+ if (x & 0x40)
1534+ x -= 55;
1535+ c = x << 4;
1536+ x = *c2 & 0x4f;
1537+ if (x & 0x40)
1538+ x -= 55;
1539+ c |= x;
1540+ return c;
1541+}
1542+
1543+int inhex(char *in, char *out)
1544+{
1545+ char *c2 = out;
1546+ while (isxdigit(*in)) {
1547+ *c2++ = unhex((unsigned char *)in);
1548+ in += 2;
1549+ }
1550+ return c2 - out;
1551+}
1552+
1553+static void addenv(void *tenv, MDB_env *renv)
1554+{
1555+ assert(nenvs < MAXENVS);
1556+ envs[nenvs].tenv = tenv;
1557+ envs[nenvs].renv = renv;
1558+ envs[nenvs].ntxns = 0;
1559+ lastenv = envs+nenvs;
1560+ nenvs++;
1561+}
1562+
1563+static envpair *findenv(void *tenv)
1564+{
1565+ int i;
1566+ if (!lastenv || lastenv->tenv != tenv) {
1567+ for (i=0; i<nenvs; i++)
1568+ if (envs[i].tenv == tenv)
1569+ break;
1570+ assert(i < nenvs);
1571+ lastenv = &envs[i];
1572+ }
1573+ return lastenv;
1574+}
1575+
1576+static void delenv(envpair *ep)
1577+{
1578+ int i = ep - envs;
1579+ for (; i<nenvs-1; i++)
1580+ envs[i] = envs[i+1];
1581+ nenvs--;
1582+ lastenv = NULL;
1583+}
1584+
1585+static void addtxn(void *tenv, void *ttxn, MDB_txn *rtxn)
1586+{
1587+ envpair *ep;
1588+ txnpair *tp;
1589+
1590+ ep = findenv(tenv);
1591+ assert(ep->ntxns < MAXTXNS);
1592+ tp = ep->txns+ep->ntxns;
1593+ tp->ttxn = ttxn;
1594+ tp->rtxn = rtxn;
1595+ tp->ncursors = 0;
1596+ ep->ntxns++;
1597+ lasttxn = tp;
1598+}
1599+
1600+static txnpair *findtxn(void *ttxn)
1601+{
1602+ int i, j;
1603+ if (lasttxn && lasttxn->ttxn == ttxn)
1604+ return lasttxn;
1605+ if (lastenv) {
1606+ for (i=0; i<lastenv->ntxns; i++) {
1607+ if (lastenv->txns[i].ttxn == ttxn) {
1608+ lasttxn = lastenv->txns+i;
1609+ return lasttxn;
1610+ }
1611+ }
1612+ }
1613+ for (i=0; i<nenvs; i++) {
1614+ if (envs+i == lastenv) continue;
1615+ for (j=0; j<envs[i].ntxns; j++) {
1616+ if (envs[i].txns[j].ttxn == ttxn) {
1617+ lastenv = envs+i;
1618+ lasttxn = envs[i].txns+j;
1619+ return lasttxn;
1620+ }
1621+ }
1622+ }
1623+ assert(0); /* should have found it */
1624+}
1625+
1626+static void deltxn(txnpair *tp)
1627+{
1628+ int i = tp - lastenv->txns;
1629+ for (; i<lastenv->ntxns-1; i++)
1630+ lastenv->txns[i] = lastenv->txns[i+1];
1631+ lastenv->ntxns--;
1632+ lasttxn = NULL;
1633+}
1634+
1635+static void addcrs(txnpair *tp, void *tcrs, MDB_cursor *rcrs)
1636+{
1637+ int j = tp->ncursors;
1638+ assert(tp->ncursors < MAXCRSS);
1639+
1640+ tp->cursors[j].tcrs = tcrs;
1641+ tp->cursors[j].rcrs = rcrs;
1642+ tp->ncursors++;
1643+ lastcrs = tp->cursors+j;
1644+}
1645+
1646+static crspair *findcrs(void *tcrs)
1647+{
1648+ int i, j, k;
1649+ envpair *ep;
1650+ txnpair *tp;
1651+ crspair *cp;
1652+ if (lastcrs && lastcrs->tcrs == tcrs)
1653+ return lastcrs;
1654+ if (lasttxn) {
1655+ for (k=0, cp=lasttxn->cursors; k<lasttxn->ncursors; k++, cp++) {
1656+ if (cp->tcrs == tcrs) {
1657+ lastcrs = cp;
1658+ return lastcrs;
1659+ }
1660+ }
1661+ }
1662+ if (lastenv) {
1663+ for (j=0, tp=lastenv->txns; j<lastenv->ntxns; j++, tp++){
1664+ if (tp == lasttxn)
1665+ continue;
1666+ for (k=0, cp = tp->cursors; k<tp->ncursors; k++, cp++) {
1667+ if (cp->tcrs == tcrs) {
1668+ lastcrs = cp;
1669+ lasttxn = tp;
1670+ return lastcrs;
1671+ }
1672+ }
1673+ }
1674+ }
1675+ for (i=0, ep=envs; i<nenvs; i++, ep++) {
1676+ for (j=0, tp=ep->txns; j<ep->ntxns; j++, tp++) {
1677+ if (tp == lasttxn)
1678+ continue;
1679+ for (k=0, cp = tp->cursors; k<tp->ncursors; k++, cp++) {
1680+ if (cp->tcrs == tcrs) {
1681+ lastcrs = cp;
1682+ lasttxn = tp;
1683+ lastenv = ep;
1684+ return lastcrs;
1685+ }
1686+ }
1687+ }
1688+ }
1689+ assert(0); /* should have found it already */
1690+}
1691+
1692+static void delcrs(void *tcrs)
1693+{
1694+ int i;
1695+ crspair *cp = findcrs(tcrs);
1696+ mdb_cursor_close(cp->rcrs);
1697+ for (i = cp - lasttxn->cursors; i<lasttxn->ncursors-1; i++)
1698+ lasttxn->cursors[i] = lasttxn->cursors[i+1];
1699+ lasttxn->ncursors--;
1700+ lastcrs = NULL;
1701+}
1702+
1703+void child()
1704+{
1705+ int rc;
1706+ MDB_val key, data;
1707+ char *ptr;
1708+
1709+ while (fgets(inbuf, sizeof(inbuf), stdin)) {
1710+ ptr = inbuf;
1711+ if (!strncmp(ptr, SCMP("exit")))
1712+ break;
1713+
1714+ if (!strncmp(ptr, SCMP("mdb_env_create"))) {
1715+ void *tenv;
1716+ MDB_env *renv;
1717+ sscanf(ptr+SOFF("mdb_env_create"), "%p", &tenv);
1718+ E(mdb_env_create(&renv));
1719+ addenv(tenv, renv);
1720+ } else if (!strncmp(ptr, SCMP("mdb_env_set_maxdbs"))) {
1721+ void *tenv;
1722+ envpair *ep;
1723+ unsigned int maxdbs;
1724+ sscanf(ptr+SOFF("mdb_env_set_maxdbs"), "%p, %u", &tenv, &maxdbs);
1725+ ep = findenv(tenv);
1726+ E(mdb_env_set_maxdbs(ep->renv, maxdbs));
1727+ } else if (!strncmp(ptr, SCMP("mdb_env_set_mapsize"))) {
1728+ void *tenv;
1729+ envpair *ep;
1730+ size_t mapsize;
1731+ sscanf(ptr+SOFF("mdb_env_set_mapsize"), "%p, %"MDB_SCNy(u), &tenv, &mapsize);
1732+ ep = findenv(tenv);
1733+ E(mdb_env_set_mapsize(ep->renv, mapsize));
1734+ } else if (!strncmp(ptr, SCMP("mdb_env_open"))) {
1735+ void *tenv;
1736+ envpair *ep;
1737+ char *path;
1738+ int len;
1739+ unsigned int flags, mode;
1740+ sscanf(ptr+SOFF("mdb_env_open"), "%p, %n", &tenv, &len);
1741+ path = ptr+SOFF("mdb_env_open")+len;
1742+ ptr = strchr(path, ',');
1743+ *ptr++ = '\0';
1744+ sscanf(ptr, "%u, %o", &flags, &mode);
1745+ ep = findenv(tenv);
1746+ E(mdb_env_open(ep->renv, path, flags, mode));
1747+ if (!maxkey) {
1748+ maxkey = mdb_env_get_maxkeysize(ep->renv);
1749+ kbuf = malloc(maxkey+2);
1750+ dbuf = malloc(maxkey+2);
1751+ dbufsize = maxkey;
1752+ }
1753+ } else if (!strncmp(ptr, SCMP("mdb_env_close"))) {
1754+ void *tenv;
1755+ envpair *ep;
1756+ sscanf(ptr+SOFF("mdb_env_close"), "%p", &tenv);
1757+ ep = findenv(tenv);
1758+ mdb_env_close(ep->renv);
1759+ delenv(ep);
1760+ if (!nenvs) /* if no other envs left, this process is done */
1761+ break;
1762+ } else if (!strncmp(ptr, SCMP("mdb_txn_begin"))) {
1763+ unsigned int flags;
1764+ void *tenv, *ttxn;
1765+ envpair *ep;
1766+ MDB_txn *rtxn;
1767+ sscanf(ptr+SOFF("mdb_txn_begin"), "%p, %*p, %u = %p", &tenv, &flags, &ttxn);
1768+ ep = findenv(tenv);
1769+ E(mdb_txn_begin(ep->renv, NULL, flags, &rtxn));
1770+ addtxn(tenv, ttxn, rtxn);
1771+ } else if (!strncmp(ptr, SCMP("mdb_txn_commit"))) {
1772+ void *ttxn;
1773+ txnpair *tp;
1774+ sscanf(ptr+SOFF("mdb_txn_commit"), "%p", &ttxn);
1775+ tp = findtxn(ttxn);
1776+ E(mdb_txn_commit(tp->rtxn));
1777+ deltxn(tp);
1778+ } else if (!strncmp(ptr, SCMP("mdb_txn_abort"))) {
1779+ void *ttxn;
1780+ txnpair *tp;
1781+ sscanf(ptr+SOFF("mdb_txn_abort"), "%p", &ttxn);
1782+ tp = findtxn(ttxn);
1783+ mdb_txn_abort(tp->rtxn);
1784+ deltxn(tp);
1785+ } else if (!strncmp(ptr, SCMP("mdb_dbi_open"))) {
1786+ void *ttxn;
1787+ txnpair *tp;
1788+ char *dbname;
1789+ unsigned int flags;
1790+ unsigned int tdbi;
1791+ MDB_dbi dbi;
1792+ sscanf(ptr+SOFF("mdb_dbi_open"), "%p, ", &ttxn);
1793+ dbname = strchr(ptr+SOFF("mdb_dbi_open"), ',');
1794+ dbname += 2;
1795+ ptr = strchr(dbname, ',');
1796+ *ptr++ = '\0';
1797+ if (!strcmp(dbname, "(null)"))
1798+ dbname = NULL;
1799+ sscanf(ptr, "%u = %u", &flags, &tdbi);
1800+ tp = findtxn(ttxn);
1801+ E(mdb_dbi_open(tp->rtxn, dbname, flags, &dbi));
1802+ } else if (!strncmp(ptr, SCMP("mdb_dbi_close"))) {
1803+ void *tenv;
1804+ envpair *ep;
1805+ unsigned int tdbi;
1806+ sscanf(ptr+SOFF("mdb_dbi_close"), "%p, %u", &tenv, &tdbi);
1807+ ep = findenv(tenv);
1808+ mdb_dbi_close(ep->renv, tdbi);
1809+ } else if (!strncmp(ptr, SCMP("mdb_cursor_open"))) {
1810+ void *ttxn, *tcrs;
1811+ txnpair *tp;
1812+ MDB_cursor *rcrs;
1813+ unsigned int tdbi;
1814+ sscanf(ptr+SOFF("mdb_cursor_open"), "%p, %u = %p", &ttxn, &tdbi, &tcrs);
1815+ tp = findtxn(ttxn);
1816+ E(mdb_cursor_open(tp->rtxn, tdbi, &rcrs));
1817+ addcrs(tp, tcrs, rcrs);
1818+ } else if (!strncmp(ptr, SCMP("mdb_cursor_close"))) {
1819+ void *tcrs;
1820+ sscanf(ptr+SOFF("mdb_cursor_close"), "%p", &tcrs);
1821+ delcrs(tcrs);
1822+ } else if (!strncmp(ptr, SCMP("mdb_cursor_put"))) {
1823+ void *tcrs;
1824+ crspair *cp;
1825+ unsigned int flags;
1826+ int len;
1827+ sscanf(ptr+SOFF("mdb_cursor_put"), "%p, ", &tcrs);
1828+ cp = findcrs(tcrs);
1829+ ptr = strchr(ptr+SOFF("mdb_cursor_put"), ',');
1830+ sscanf(ptr+1, "%"MDB_SCNy(u)",", &key.mv_size);
1831+ if (key.mv_size) {
1832+ ptr = strchr(ptr, '[');
1833+ inhex(ptr+1, kbuf);
1834+ key.mv_data = kbuf;
1835+ ptr += key.mv_size * 2 + 2;
1836+ }
1837+ ptr = strchr(ptr+1, ',');
1838+ sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len);
1839+ if (data.mv_size > dbufsize) {
1840+ dbuf = realloc(dbuf, data.mv_size+2);
1841+ assert(dbuf != NULL);
1842+ dbufsize = data.mv_size;
1843+ }
1844+ ptr += len+1;
1845+ if (*ptr == '[') {
1846+ inhex(ptr+1, dbuf);
1847+ data.mv_data = dbuf;
1848+ ptr += data.mv_size * 2 + 2;
1849+ } else {
1850+ sprintf(dbuf, "%09ld", (long)mdb_txn_id(lasttxn->rtxn));
1851+ }
1852+ sscanf(ptr+1, "%u", &flags);
1853+ E(mdb_cursor_put(cp->rcrs, &key, &data, flags));
1854+ } else if (!strncmp(ptr, SCMP("mdb_cursor_del"))) {
1855+ void *tcrs;
1856+ crspair *cp;
1857+ unsigned int flags;
1858+ sscanf(ptr+SOFF("mdb_cursor_del"), "%p, %u", &tcrs, &flags);
1859+ cp = findcrs(tcrs);
1860+ E(mdb_cursor_del(cp->rcrs, flags));
1861+ } else if (!strncmp(ptr, SCMP("mdb_put"))) {
1862+ void *ttxn;
1863+ txnpair *tp;
1864+ unsigned int tdbi, flags;
1865+ int len;
1866+ sscanf(ptr+SOFF("mdb_put"),"%p, %u, %"MDB_SCNy(u), &ttxn, &tdbi, &key.mv_size);
1867+ tp = findtxn(ttxn);
1868+ ptr = strchr(ptr+SOFF("mdb_put"), '[');
1869+ inhex(ptr+1, kbuf);
1870+ key.mv_data = kbuf;
1871+ ptr += key.mv_size * 2 + 2;
1872+ sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len);
1873+ if (data.mv_size > dbufsize) {
1874+ dbuf = realloc(dbuf, data.mv_size+2);
1875+ assert(dbuf != NULL);
1876+ dbufsize = data.mv_size;
1877+ }
1878+ ptr += len+1;
1879+ if (*ptr == '[') {
1880+ inhex(ptr+1, dbuf);
1881+ ptr += data.mv_size * 2 + 2;
1882+ } else {
1883+ sprintf(dbuf, "%09ld", (long)mdb_txn_id(tp->rtxn));
1884+ }
1885+ data.mv_data = dbuf;
1886+ sscanf(ptr+1, "%u", &flags);
1887+ RES(MDB_KEYEXIST,mdb_put(tp->rtxn, tdbi, &key, &data, flags));
1888+ } else if (!strncmp(ptr, SCMP("mdb_del"))) {
1889+ void *ttxn;
1890+ txnpair *tp;
1891+ unsigned int tdbi;
1892+ int len;
1893+ sscanf(ptr+SOFF("mdb_del"),"%p, %u, %"MDB_SCNy(u), &ttxn, &tdbi, &key.mv_size);
1894+ tp = findtxn(ttxn);
1895+ ptr = strchr(ptr+SOFF("mdb_del"), '[');
1896+ inhex(ptr+1, kbuf);
1897+ key.mv_data = kbuf;
1898+ ptr += key.mv_size * 2 + 2;
1899+ sscanf(ptr+1, "%"MDB_SCNy(u)"%n", &data.mv_size, &len);
1900+ if (data.mv_size > dbufsize) {
1901+ dbuf = realloc(dbuf, data.mv_size+2);
1902+ assert(dbuf != NULL);
1903+ dbufsize = data.mv_size;
1904+ }
1905+ ptr += len+1;
1906+ if (*ptr == '[') {
1907+ inhex(ptr+1, dbuf);
1908+ } else {
1909+ sprintf(dbuf, "%09ld", (long)mdb_txn_id(tp->rtxn));
1910+ }
1911+ data.mv_data = dbuf;
1912+ RES(MDB_NOTFOUND,mdb_del(tp->rtxn, tdbi, &key, &data));
1913+ }
1914+ write(1, "\n", 1);
1915+ }
1916+ exit(0);
1917+}
1918+
1919+static pidpair *addpid(int tpid)
1920+{
1921+ int fdout[2], fdin[2];
1922+ pid_t pid;
1923+ assert(npids < MAXPIDS);
1924+ pids[npids].tpid = tpid;
1925+ pipe(fdout);
1926+ pipe(fdin);
1927+ if ((pid = fork()) == 0) {
1928+ /* child */
1929+ fclose(stdin);
1930+ fclose(stdout);
1931+ dup2(fdout[0], 0);
1932+ dup2(fdin[1], 1);
1933+ stdin = fdopen(0, "r");
1934+ stdout = fdopen(1, "w");
1935+ child();
1936+ return 0; /* NOTREACHED */
1937+ } else {
1938+ pids[npids].rpid = pid;
1939+ pids[npids].fdout = fdout[1];
1940+ pids[npids].fdin = fdin[0];
1941+ lastpid = pids+npids;
1942+ npids++;
1943+ return lastpid;
1944+ }
1945+}
1946+
1947+static pidpair *findpid(int tpid)
1948+{
1949+ int i;
1950+ if (!lastpid || lastpid->tpid != tpid) {
1951+ for (i=0; i<npids; i++)
1952+ if (pids[i].tpid == tpid)
1953+ break;
1954+ if (i == npids)
1955+ return NULL;
1956+ lastpid = &pids[i];
1957+ }
1958+ return lastpid;
1959+}
1960+
1961+volatile pid_t killpid;
1962+
1963+static void delpid(int tpid)
1964+{
1965+ pidpair *pp = findpid(tpid);
1966+ if (pp) {
1967+ pid_t kpid = pp->rpid;
1968+ killpid = kpid;
1969+ write(pp->fdout, "exit\n", sizeof("exit"));
1970+ while (killpid == kpid)
1971+ usleep(10000);
1972+ }
1973+}
1974+
1975+static void reaper(int sig)
1976+{
1977+ int status, i;
1978+ pid_t pid = waitpid(-1, &status, 0);
1979+ if (pid > 0) {
1980+ fprintf(stderr, "# %s %d\n", WIFEXITED(status) ? "exited" : "killed", pid);
1981+ for (i=0; i<npids; i++)
1982+ if (pids[i].rpid == pid)
1983+ break;
1984+ assert(i < npids);
1985+ close(pids[i].fdout);
1986+ close(pids[i].fdin);
1987+ for (;i<npids-1; i++)
1988+ pids[i] = pids[i+1];
1989+ npids--;
1990+ killpid = 0;
1991+ }
1992+}
1993+
1994+int main(int argc,char * argv[])
1995+{
1996+ signal(SIGCHLD, reaper);
1997+
1998+ while (fgets(inbuf, sizeof(inbuf), stdin)) {
1999+ pidpair *pp;
2000+ int tpid, len;
2001+ char c, *ptr;
2002+ lcount++;
2003+
2004+ if (inbuf[0] == '#' && !strncmp(inbuf+1, SCMP(" killed"))) {
2005+ sscanf(inbuf+SOFF("killed"),"%d", &tpid);
2006+ delpid(tpid);
2007+ continue;
2008+ }
2009+
2010+ if (inbuf[0] != '>')
2011+ continue;
2012+ ptr = inbuf+1;
2013+ sscanf(ptr, "%d:%n", &tpid, &len);
2014+ pp = findpid(tpid);
2015+ if (!pp)
2016+ pp = addpid(tpid); /* new process */
2017+
2018+ ptr = inbuf+len+1;
2019+ len = strlen(ptr);
2020+ write(pp->fdout, ptr, len); /* send command and wait for ack */
2021+ read(pp->fdin, &c, 1);
2022+ }
2023+ while (npids)
2024+ delpid(pids[0].tpid);
2025+}
2026diff --git a/servers/lloadd/daemon.c b/servers/lloadd/daemon.c
2027index b88fd68..e048936 100644
2028--- a/servers/lloadd/daemon.c
2029+++ b/servers/lloadd/daemon.c
2030@@ -92,6 +92,11 @@ struct event_base *listener_base = NULL;
2031 LloadListener **lload_listeners = NULL;
2032 static ldap_pvt_thread_t listener_tid, *daemon_tid;
2033
2034+#ifndef RESOLV_CONF_PATH
2035+#define RESOLV_CONF_PATH "/etc/resolv.conf"
2036+#endif
2037+char *lload_resolvconf_path = RESOLV_CONF_PATH;
2038+
2039 struct event_base *daemon_base = NULL;
2040 struct evdns_base *dnsbase;
2041
2042@@ -1238,13 +1243,22 @@ lloadd_daemon( struct event_base *daemon_base )
2043
2044 assert( daemon_base != NULL );
2045
2046- dnsbase = evdns_base_new( daemon_base, EVDNS_BASE_INITIALIZE_NAMESERVERS );
2047+ dnsbase = evdns_base_new( daemon_base, 0 );
2048 if ( !dnsbase ) {
2049 Debug( LDAP_DEBUG_ANY, "lloadd startup: "
2050 "failed to set up for async name resolution\n" );
2051 return -1;
2052 }
2053
2054+ /*
2055+ * ITS#10070: Allow both operation without working DNS (test environments)
2056+ * and e.g. containers that don't have a /etc/resolv.conf but do have a
2057+ * server listening on 127.0.0.1 which is the default.
2058+ */
2059+ (void)evdns_base_resolv_conf_parse( dnsbase,
2060+ DNS_OPTION_NAMESERVERS|DNS_OPTION_HOSTSFILE,
2061+ lload_resolvconf_path );
2062+
2063 if ( lload_daemon_threads > SLAPD_MAX_DAEMON_THREADS )
2064 lload_daemon_threads = SLAPD_MAX_DAEMON_THREADS;
2065
2066diff --git a/servers/lloadd/libevent_support.c b/servers/lloadd/libevent_support.c
2067index 2f94c5e..8d7378c 100644
2068--- a/servers/lloadd/libevent_support.c
2069+++ b/servers/lloadd/libevent_support.c
2070@@ -131,6 +131,12 @@ lload_libevent_cond_timedwait(
2071 return ldap_pvt_thread_cond_wait( cond, mutex );
2072 }
2073
2074+unsigned long
2075+lload_libevent_thread_self( void )
2076+{
2077+ return (unsigned long)ldap_pvt_thread_self();
2078+}
2079+
2080 int
2081 lload_libevent_init( void )
2082 {
2083@@ -160,7 +166,7 @@ lload_libevent_init( void )
2084
2085 evthread_set_lock_callbacks( &cbs );
2086 evthread_set_condition_callbacks( &cond_cbs );
2087- evthread_set_id_callback( ldap_pvt_thread_self );
2088+ evthread_set_id_callback( lload_libevent_thread_self );
2089 return 0;
2090 }
2091
2092diff --git a/servers/lloadd/module_init.c b/servers/lloadd/module_init.c
2093index 1475538..d4eebf6 100644
2094--- a/servers/lloadd/module_init.c
2095+++ b/servers/lloadd/module_init.c
2096@@ -145,7 +145,6 @@ lload_back_initialize( BackendInfo *bi )
2097 {
2098 bi->bi_flags = SLAP_BFLAG_STANDALONE;
2099 bi->bi_open = lload_back_open;
2100- bi->bi_config = config_generic_wrapper;
2101 bi->bi_pause = lload_pause_cb;
2102 bi->bi_unpause = lload_unpause_cb;
2103 bi->bi_close = lload_back_close;
2104diff --git a/servers/lloadd/upstream.c b/servers/lloadd/upstream.c
2105index 6824fa8..5e64029 100644
2106--- a/servers/lloadd/upstream.c
2107+++ b/servers/lloadd/upstream.c
2108@@ -118,17 +118,22 @@ static int
2109 handle_unsolicited( LloadConnection *c, BerElement *ber )
2110 {
2111 CONNECTION_ASSERT_LOCKED(c);
2112- if ( c->c_state != LLOAD_C_PREPARING ) {
2113- c->c_state = LLOAD_C_CLOSING;
2114+
2115+ assert( c->c_state != LLOAD_C_INVALID );
2116+ if ( c->c_state == LLOAD_C_DYING ) {
2117+ CONNECTION_UNLOCK(c);
2118+ goto out;
2119 }
2120+ c->c_state = LLOAD_C_CLOSING;
2121
2122 Debug( LDAP_DEBUG_STATS, "handle_unsolicited: "
2123 "teardown for upstream connection connid=%lu\n",
2124 c->c_connid );
2125
2126 CONNECTION_DESTROY(c);
2127- ber_free( ber, 1 );
2128
2129+out:
2130+ ber_free( ber, 1 );
2131 return -1;
2132 }
2133
2134diff --git a/servers/slapd/aci.c b/servers/slapd/aci.c
2135index 33e6074..c8cc41d 100644
2136--- a/servers/slapd/aci.c
2137+++ b/servers/slapd/aci.c
2138@@ -39,6 +39,7 @@
2139 #include "slap.h"
2140 #include "lber_pvt.h"
2141 #include "lutil.h"
2142+#include "slap-config.h"
2143
2144 /* use most appropriate size */
2145 #define ACI_BUF_SIZE 1024
2146@@ -741,8 +742,7 @@ aci_init( void )
2147
2148 static int
2149 dynacl_aci_parse(
2150- const char *fname,
2151- int lineno,
2152+ ConfigArgs *c,
2153 const char *opts,
2154 slap_style_t sty,
2155 const char *right,
2156@@ -752,17 +752,19 @@ dynacl_aci_parse(
2157 const char *text = NULL;
2158
2159 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
2160- fprintf( stderr, "%s: line %d: "
2161- "inappropriate style \"%s\" in \"aci\" by clause\n",
2162- fname, lineno, style_strings[sty] );
2163+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2164+ "inappropriate style \"%s\" in \"aci\" by clause",
2165+ style_strings[sty] );
2166+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2167 return -1;
2168 }
2169
2170 if ( right != NULL && *right != '\0' ) {
2171 if ( slap_str2ad( right, &ad, &text ) != LDAP_SUCCESS ) {
2172- fprintf( stderr,
2173- "%s: line %d: aci \"%s\": %s\n",
2174- fname, lineno, right, text );
2175+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2176+ "aci \"%s\": %s",
2177+ right, text );
2178+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2179 return -1;
2180 }
2181
2182@@ -771,10 +773,10 @@ dynacl_aci_parse(
2183 }
2184
2185 if ( !is_at_syntax( ad->ad_type, SLAPD_ACI_SYNTAX) ) {
2186- fprintf( stderr, "%s: line %d: "
2187- "aci \"%s\": inappropriate syntax: %s\n",
2188- fname, lineno, right,
2189- ad->ad_type->sat_syntax_oid );
2190+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2191+ "aci \"%s\": inappropriate syntax: %s",
2192+ right, ad->ad_type->sat_syntax_oid );
2193+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2194 return -1;
2195 }
2196
2197diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c
2198index 60b74e3..f08de6a 100644
2199--- a/servers/slapd/aclparse.c
2200+++ b/servers/slapd/aclparse.c
2201@@ -37,6 +37,7 @@
2202 #include "slap.h"
2203 #include "lber_pvt.h"
2204 #include "lutil.h"
2205+#include "slap-config.h"
2206
2207 static const char style_base[] = "base";
2208 const char *style_strings[] = {
2209@@ -76,8 +77,7 @@ static int check_scope( BackendDB *be, AccessControl *a );
2210 #ifdef SLAP_DYNACL
2211 static int
2212 slap_dynacl_config(
2213- const char *fname,
2214- int lineno,
2215+ struct config_args_s *c,
2216 Access *b,
2217 const char *name,
2218 const char *opts,
2219@@ -89,9 +89,10 @@ slap_dynacl_config(
2220
2221 for ( da = b->a_dynacl; da; da = da->da_next ) {
2222 if ( strcasecmp( da->da_name, name ) == 0 ) {
2223- Debug( LDAP_DEBUG_ANY,
2224- "%s: line %d: dynacl \"%s\" already specified.\n",
2225- fname, lineno, name );
2226+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2227+ "dynacl \"%s\" already specified",
2228+ name );
2229+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2230 return acl_usage();
2231 }
2232 }
2233@@ -105,7 +106,7 @@ slap_dynacl_config(
2234 *tmp = *da;
2235
2236 if ( tmp->da_parse ) {
2237- rc = ( *tmp->da_parse )( fname, lineno, opts, sty, right, &tmp->da_private );
2238+ rc = ( *tmp->da_parse )( c, opts, sty, right, &tmp->da_private );
2239 if ( rc ) {
2240 ch_free( tmp );
2241 return rc;
2242@@ -119,8 +120,8 @@ slap_dynacl_config(
2243 }
2244 #endif /* SLAP_DYNACL */
2245
2246-static void
2247-regtest(const char *fname, int lineno, char *pat) {
2248+static int
2249+regtest(struct config_args_s *c, char *pat) {
2250 int e;
2251 regex_t re;
2252
2253@@ -156,25 +157,27 @@ regtest(const char *fname, int lineno, char *pat) {
2254
2255 *dp = '\0';
2256 if ( size >= (sizeof(buf) - 1) ) {
2257- Debug( LDAP_DEBUG_ANY,
2258- "%s: line %d: regular expression \"%s\" too large\n",
2259- fname, lineno, pat );
2260+ snprintf( c->cr_msg, sizeof( c->cr_msg),
2261+ "regular expression too large \"%s\"", pat);
2262+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2263 (void)acl_usage();
2264- exit( EXIT_FAILURE );
2265+ return -1;
2266 }
2267
2268- if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
2269+ if ( (e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE)) ) {
2270 char error[ SLAP_TEXT_BUFLEN ];
2271
2272 regerror(e, &re, error, sizeof(error));
2273
2274- Debug(LDAP_DEBUG_ANY,
2275- "%s: line %d: regular expression \"%s\" bad because of %s\n",
2276- fname, lineno, pat, error );
2277+ snprintf( c->cr_msg, sizeof ( c->cr_msg ),
2278+ "regular expression \"%s\" bad because of %s", pat, error);
2279+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2280 acl_usage();
2281- exit( EXIT_FAILURE );
2282+ regfree(&re);
2283+ return -1;
2284 }
2285 regfree(&re);
2286+ return 0;
2287 }
2288
2289 /*
2290@@ -212,7 +215,7 @@ check_scope( BackendDB *be, AccessControl *a )
2291 ber_len_t rebuflen;
2292 regex_t re;
2293 int rc;
2294-
2295+
2296 /* add trailing '$' to database suffix to form
2297 * a simple trial regex pattern "<suffix>$" */
2298 AC_MEMCPY( dnbuf, be->be_nsuffix[0].bv_val,
2299@@ -319,11 +322,7 @@ regex_done:;
2300
2301 int
2302 parse_acl(
2303- Backend *be,
2304- const char *fname,
2305- int lineno,
2306- int argc,
2307- char **argv,
2308+ struct config_args_s *c,
2309 int pos )
2310 {
2311 int i;
2312@@ -333,14 +332,19 @@ parse_acl(
2313 Access *b = NULL;
2314 int rc;
2315 const char *text;
2316+ Backend *be = c->be;
2317+ const char *fname = c->fname;
2318+ int lineno = c->lineno;
2319+ int argc = c->argc;
2320+ char **argv = c->argv;
2321
2322 for ( i = 1; i < argc; i++ ) {
2323 /* to clause - select which entries are protected */
2324 if ( strcasecmp( argv[i], "to" ) == 0 ) {
2325 if ( a != NULL ) {
2326- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2327- "only one to clause allowed in access line\n",
2328- fname, lineno );
2329+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2330+ "only one to clause allowed in access line" );
2331+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2332 goto fail;
2333 }
2334 a = (AccessControl *) ch_calloc( 1, sizeof(AccessControl) );
2335@@ -355,10 +359,9 @@ parse_acl(
2336 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
2337 a->acl_dn_style != ACL_STYLE_REGEX )
2338 {
2339- Debug( LDAP_DEBUG_ANY,
2340- "%s: line %d: dn pattern"
2341- " already specified in to clause.\n",
2342- fname, lineno );
2343+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2344+ "dn pattern already specified in to clause." );
2345+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2346 goto fail;
2347 }
2348
2349@@ -370,9 +373,9 @@ parse_acl(
2350 split( left, '.', &left, &style );
2351
2352 if ( right == NULL ) {
2353- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2354- "missing \"=\" in \"%s\" in to clause\n",
2355- fname, lineno, left );
2356+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2357+ "missing \"=\" in \"%s\" in to clause", left );
2358+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2359 goto fail;
2360 }
2361
2362@@ -380,10 +383,9 @@ parse_acl(
2363 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
2364 a->acl_dn_style != ACL_STYLE_REGEX )
2365 {
2366- Debug( LDAP_DEBUG_ANY,
2367- "%s: line %d: dn pattern"
2368- " already specified in to clause.\n",
2369- fname, lineno );
2370+ snprintf( c->cr_msg, sizeof( c->cr_msg),
2371+ "dn pattern already specified in to clause" );
2372+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2373 goto fail;
2374 }
2375
2376@@ -424,12 +426,12 @@ parse_acl(
2377 a->acl_dn_style = ACL_STYLE_BASE;
2378 ber_str2bv( right, 0, 1, &a->acl_dn_pat );
2379
2380- } else if ( strcmp(right, "*") == 0
2381- || strcmp(right, ".*") == 0
2382- || strcmp(right, ".*$") == 0
2383- || strcmp(right, "^.*") == 0
2384+ } else if ( strcmp(right, "*") == 0
2385+ || strcmp(right, ".*") == 0
2386+ || strcmp(right, ".*$") == 0
2387+ || strcmp(right, "^.*") == 0
2388 || strcmp(right, "^.*$") == 0
2389- || strcmp(right, ".*$$") == 0
2390+ || strcmp(right, ".*$$") == 0
2391 || strcmp(right, "^.*$$") == 0 )
2392 {
2393 ber_str2bv( "*", STRLENOF("*"), 1, &a->acl_dn_pat );
2394@@ -439,9 +441,9 @@ parse_acl(
2395 }
2396
2397 } else {
2398- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2399- "unknown dn style \"%s\" in to clause\n",
2400- fname, lineno, style );
2401+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2402+ "unknown dn style \"%s\" in to clause", style );
2403+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2404 goto fail;
2405 }
2406
2407@@ -450,9 +452,9 @@ parse_acl(
2408
2409 if ( strcasecmp( left, "filter" ) == 0 ) {
2410 if ( (a->acl_filter = str2filter( right )) == NULL ) {
2411- Debug( LDAP_DEBUG_ANY,
2412- "%s: line %d: bad filter \"%s\" in to clause\n",
2413- fname, lineno, right );
2414+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2415+ "bad filter \"%s\" in to clause", right );
2416+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2417 goto fail;
2418 }
2419
2420@@ -460,37 +462,36 @@ parse_acl(
2421 || strcasecmp( left, "attrs" ) == 0 ) /* DOCUMENTED */
2422 {
2423 if ( strcasecmp( left, "attr" ) == 0 ) {
2424- Debug( LDAP_DEBUG_ANY,
2425- "%s: line %d: \"attr\" "
2426- "is deprecated (and undocumented); "
2427- "use \"attrs\" instead.\n",
2428- fname, lineno );
2429+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2430+ "\"attr\" is deprecated (and undocumented); "
2431+ "use \"attrs\" instead");
2432+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2433 }
2434
2435 a->acl_attrs = str2anlist( a->acl_attrs,
2436 right, "," );
2437 if ( a->acl_attrs == NULL ) {
2438- Debug( LDAP_DEBUG_ANY,
2439- "%s: line %d: unknown attr \"%s\" in to clause\n",
2440- fname, lineno, right );
2441+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2442+ "unknown attr \"%s\" in to clause", right );
2443+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2444 goto fail;
2445 }
2446
2447 } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
2448 struct berval bv;
2449 char *mr;
2450-
2451+
2452 if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
2453- Debug( LDAP_DEBUG_ANY,
2454- "%s: line %d: attr val already specified in to clause.\n",
2455- fname, lineno );
2456+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2457+ "attr val already specified in to clause" );
2458+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2459 goto fail;
2460 }
2461 if ( a->acl_attrs == NULL || !BER_BVISEMPTY( &a->acl_attrs[1].an_name ) )
2462 {
2463- Debug( LDAP_DEBUG_ANY,
2464- "%s: line %d: attr val requires a single attribute.\n",
2465- fname, lineno );
2466+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2467+ "attr val requires a single attribute");
2468+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2469 goto fail;
2470 }
2471
2472@@ -504,23 +505,23 @@ parse_acl(
2473
2474 a->acl_attrval_mr = mr_find( mr );
2475 if ( a->acl_attrval_mr == NULL ) {
2476- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2477- "invalid matching rule \"%s\".\n",
2478- fname, lineno, mr );
2479+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2480+ "invalid matching rule \"%s\"", mr);
2481+ Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
2482 goto fail;
2483 }
2484
2485 if( !mr_usable_with_at( a->acl_attrval_mr, a->acl_attrs[ 0 ].an_desc->ad_type ) )
2486 {
2487- Debug(LDAP_DEBUG_ANY,
2488- "%s: line %d: matching rule \"%s\" use " "with attr \"%s\" not appropriate.\n",
2489- fname, lineno,
2490- mr,
2491- a->acl_attrs[0].an_name.bv_val );
2492+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2493+ "matching rule \"%s\" use " "with attr \"%s\" not appropriate",
2494+ mr,
2495+ a->acl_attrs[0].an_name.bv_val );
2496+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c-> log, c->cr_msg );
2497 goto fail;
2498 }
2499 }
2500-
2501+
2502 if ( style != NULL ) {
2503 if ( strcasecmp( style, "regex" ) == 0 ) {
2504 int e = regcomp( &a->acl_attrval_re, bv.bv_val,
2505@@ -529,9 +530,10 @@ parse_acl(
2506 char err[SLAP_TEXT_BUFLEN];
2507
2508 regerror( e, &a->acl_attrval_re, err, sizeof( err ) );
2509- Debug(LDAP_DEBUG_ANY,
2510- "%s: line %d: regular expression \"%s\" bad because of %s\n",
2511- fname, lineno, right, err );
2512+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2513+ "regular expression \"%s\" bad because of %s",
2514+ right, err );
2515+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2516 goto fail;
2517 }
2518 a->acl_attrval_style = ACL_STYLE_REGEX;
2519@@ -561,34 +563,31 @@ parse_acl(
2520 } else if ( !strcasecmp( style, "children" ) ) {
2521 a->acl_attrval_style = ACL_STYLE_CHILDREN;
2522 } else {
2523- Debug(LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
2524- "%s: line %d: unknown val.<style> \"%s\" for attributeType \"%s\" " "with DN syntax.\n",
2525- fname,
2526- lineno,
2527+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2528+ "unknown val.<style> \"%s\" for attributeType \"%s\" " "with DN syntax",
2529 style,
2530 a->acl_attrs[0].an_desc->ad_cname.bv_val );
2531+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
2532 goto fail;
2533 }
2534
2535 rc = dnNormalize( 0, NULL, NULL, &bv, &a->acl_attrval, NULL );
2536 if ( rc != LDAP_SUCCESS ) {
2537- Debug(LDAP_DEBUG_ANY,
2538- "%s: line %d: unable to normalize DN \"%s\" " "for attributeType \"%s\" (%d).\n",
2539- fname,
2540- lineno,
2541+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2542+ "unable to normalize DN \"%s\" " "for attributeType \"%s\" (%d)",
2543 bv.bv_val,
2544 a->acl_attrs[0].an_desc->ad_cname.bv_val,
2545 rc );
2546+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2547 goto fail;
2548 }
2549
2550 } else {
2551- Debug(LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
2552- "%s: line %d: unknown val.<style> \"%s\" for attributeType \"%s\".\n",
2553+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2554+ "unknown val.<style> \"%s\" for attributeType \"%s\"",
2555 fname,
2556- lineno,
2557- style,
2558 a->acl_attrs[0].an_desc->ad_cname.bv_val );
2559+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
2560 goto fail;
2561 }
2562 }
2563@@ -607,9 +606,10 @@ parse_acl(
2564 }
2565
2566 if ( a->acl_attrval_mr == NULL ) {
2567- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2568- "attr \"%s\" does not have an EQUALITY matching rule.\n",
2569- fname, lineno, a->acl_attrs[ 0 ].an_name.bv_val );
2570+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2571+ "attr \"%s\" does not have an EQUALITY matching rule",
2572+ a->acl_attrs[ 0 ].an_name.bv_val );
2573+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2574 goto fail;
2575 }
2576
2577@@ -622,42 +622,43 @@ parse_acl(
2578 &text,
2579 NULL );
2580 if ( rc != LDAP_SUCCESS ) {
2581- Debug(LDAP_DEBUG_ANY,
2582- "%s: line %d: %s: line %d: " " attr \"%s\" normalization failed (%d: %s).\n",
2583- fname, lineno,
2584- fname, lineno,
2585+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2586+ "attr \"%s\" normalization failed (%d: %s).\n",
2587 a->acl_attrs[0].an_name.bv_val,
2588 rc, text );
2589+ Debug(LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2590 goto fail;
2591 }
2592 }
2593
2594 } else {
2595- Debug( LDAP_DEBUG_ANY,
2596- "%s: line %d: expecting <what> got \"%s\"\n",
2597- fname, lineno, left );
2598+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2599+ "expecting <what> got \"%s\"",
2600+ left );
2601+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2602 goto fail;
2603 }
2604 }
2605
2606- if ( !BER_BVISNULL( &a->acl_dn_pat ) &&
2607+ if ( !BER_BVISNULL( &a->acl_dn_pat ) &&
2608 ber_bvccmp( &a->acl_dn_pat, '*' ) )
2609 {
2610 free( a->acl_dn_pat.bv_val );
2611 BER_BVZERO( &a->acl_dn_pat );
2612 a->acl_dn_style = ACL_STYLE_REGEX;
2613 }
2614-
2615+
2616 if ( !BER_BVISEMPTY( &a->acl_dn_pat ) ||
2617- a->acl_dn_style != ACL_STYLE_REGEX )
2618+ a->acl_dn_style != ACL_STYLE_REGEX )
2619 {
2620 if ( a->acl_dn_style != ACL_STYLE_REGEX ) {
2621 struct berval bv;
2622 rc = dnNormalize( 0, NULL, NULL, &a->acl_dn_pat, &bv, NULL);
2623 if ( rc != LDAP_SUCCESS ) {
2624- Debug( LDAP_DEBUG_ANY,
2625- "%s: line %d: bad DN \"%s\" in to DN clause\n",
2626- fname, lineno, a->acl_dn_pat.bv_val );
2627+ snprintf( c->cr_msg, sizeof(c->cr_msg ),
2628+ "bad DN \"%s\" in to DN clause",
2629+ a->acl_dn_pat.bv_val );
2630+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2631 goto fail;
2632 }
2633 free( a->acl_dn_pat.bv_val );
2634@@ -670,9 +671,10 @@ parse_acl(
2635 char err[ SLAP_TEXT_BUFLEN ];
2636
2637 regerror( e, &a->acl_dn_re, err, sizeof( err ) );
2638- Debug(LDAP_DEBUG_ANY,
2639- "%s: line %d: regular expression \"%s\" bad because of %s\n",
2640- fname, lineno, right, err );
2641+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2642+ "regular expression \"%s\" bad because of %s",
2643+ right, err );
2644+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2645 goto fail;
2646 }
2647 }
2648@@ -681,9 +683,9 @@ parse_acl(
2649 /* by clause - select who has what access to entries */
2650 } else if ( strcasecmp( argv[i], "by" ) == 0 ) {
2651 if ( a == NULL ) {
2652- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2653- "to clause required before by clause in access line\n",
2654- fname, lineno );
2655+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2656+ "to clause required before by clause in access line");
2657+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2658 goto fail;
2659 }
2660
2661@@ -692,9 +694,9 @@ parse_acl(
2662 */
2663
2664 if ( ++i == argc ) {
2665- Debug( LDAP_DEBUG_ANY,
2666- "%s: line %d: premature EOL: expecting <who>\n",
2667- fname, lineno );
2668+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2669+ "premature EOL: expecting <who>");
2670+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2671 goto fail;
2672 }
2673
2674@@ -722,16 +724,14 @@ parse_acl(
2675 if ( style_level != NULL ) {
2676 char *p = strchr( style_level, '}' );
2677 if ( p == NULL ) {
2678- Debug( LDAP_DEBUG_ANY,
2679- "%s: line %d: premature eol: "
2680- "expecting closing '}' in \"level{n}\"\n",
2681- fname, lineno );
2682+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2683+ "premature eol: expecting closing '}' in \"level{n}\"");
2684+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2685 goto fail;
2686 } else if ( p == style_level ) {
2687- Debug( LDAP_DEBUG_ANY,
2688- "%s: line %d: empty level "
2689- "in \"level{n}\"\n",
2690- fname, lineno );
2691+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2692+ "empty level in \"level{n}\"");
2693+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2694 goto fail;
2695 }
2696 p[0] = '\0';
2697@@ -762,10 +762,9 @@ parse_acl(
2698 } else if ( strcasecmp( style, "level" ) == 0 )
2699 {
2700 if ( lutil_atoi( &level, style_level ) != 0 ) {
2701- Debug( LDAP_DEBUG_ANY,
2702- "%s: line %d: unable to parse level "
2703- "in \"level{n}\"\n",
2704- fname, lineno );
2705+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2706+ "unable to parse level in \"level{n}\"");
2707+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2708 goto fail;
2709 }
2710
2711@@ -782,26 +781,25 @@ parse_acl(
2712
2713 } else if ( strcasecmp( style, "ipv6" ) == 0 ) {
2714 #ifndef LDAP_PF_INET6
2715- Debug( LDAP_DEBUG_ANY,
2716- "%s: line %d: IPv6 not supported\n",
2717- fname, lineno );
2718+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2719+ "IPv6 not supported");
2720+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2721 #endif /* ! LDAP_PF_INET6 */
2722 sty = ACL_STYLE_IPV6;
2723
2724 } else if ( strcasecmp( style, "path" ) == 0 ) {
2725 sty = ACL_STYLE_PATH;
2726 #ifndef LDAP_PF_LOCAL
2727- Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
2728- "%s: line %d: "
2729- "\"path\" style modifier is useless without local.\n",
2730- fname, lineno );
2731+ snprintf( c->cr_msg, sizeof( c->cr_msg),
2732+ "\"path\" style modifier is useless without local");
2733+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
2734 goto fail;
2735 #endif /* LDAP_PF_LOCAL */
2736
2737 } else {
2738- Debug( LDAP_DEBUG_ANY,
2739- "%s: line %d: unknown style \"%s\" in by clause\n",
2740- fname, lineno, style );
2741+ snprintf( c->cr_msg, sizeof ( c->cr_msg ),
2742+ "unknown style \"%s\" in by clause", style );
2743+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2744 goto fail;
2745 }
2746
2747@@ -810,9 +808,9 @@ parse_acl(
2748 {
2749 switch ( sty ) {
2750 case ACL_STYLE_REGEX:
2751- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2752- "\"regex\" style implies \"expand\" modifier.\n",
2753- fname, lineno );
2754+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2755+ "\"regex\" style implies \"expand\" modifier" );
2756+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2757 goto fail;
2758 break;
2759
2760@@ -903,15 +901,15 @@ parse_acl(
2761 } else {
2762 acl_regex_normalized_dn( right, &bv );
2763 if ( !ber_bvccmp( &bv, '*' ) ) {
2764- regtest( fname, lineno, bv.bv_val );
2765+ if ( regtest( c, bv.bv_val ) != 0)
2766+ goto fail;
2767 }
2768 }
2769
2770 } else if ( right == NULL || *right == '\0' ) {
2771- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2772- "missing \"=\" in (or value after) \"%s\" "
2773- "in by clause\n",
2774- fname, lineno, left );
2775+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2776+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
2777+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2778 goto fail;
2779
2780 } else {
2781@@ -924,9 +922,9 @@ parse_acl(
2782
2783 if ( !BER_BVISNULL( &bv ) ) {
2784 if ( !BER_BVISEMPTY( &bdn->a_pat ) ) {
2785- Debug( LDAP_DEBUG_ANY,
2786- "%s: line %d: dn pattern already specified.\n",
2787- fname, lineno );
2788+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2789+ "dn pattern already specified" );
2790+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2791 goto fail;
2792 }
2793
2794@@ -939,9 +937,9 @@ parse_acl(
2795 rc = dnNormalize(0, NULL, NULL,
2796 &bv, &bdn->a_pat, NULL);
2797 if ( rc != LDAP_SUCCESS ) {
2798- Debug( LDAP_DEBUG_ANY,
2799- "%s: line %d: bad DN \"%s\" in by DN clause\n",
2800- fname, lineno, bv.bv_val );
2801+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2802+ "bad DN \"%s\" in by DN clause", bv.bv_val );
2803+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2804 goto fail;
2805 }
2806 free( bv.bv_val );
2807@@ -950,10 +948,9 @@ parse_acl(
2808 && !BER_BVISNULL( &be->be_rootndn )
2809 && dn_match( &bdn->a_pat, &be->be_rootndn ) )
2810 {
2811- Debug( LDAP_DEBUG_ANY,
2812- "%s: line %d: rootdn is always granted "
2813- "unlimited privileges.\n",
2814- fname, lineno );
2815+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2816+ "rootdn is always granted unlimited privileges" );
2817+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2818 }
2819
2820 } else {
2821@@ -980,32 +977,29 @@ parse_acl(
2822 bdn->a_expand = expand;
2823
2824 } else {
2825- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2826- "\"expand\" used with no expansions in \"pattern\".\n",
2827- fname, lineno );
2828+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2829+ "\"expand\" used with no expansions in \"pattern\"");
2830+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2831 goto fail;
2832- }
2833+ }
2834 }
2835 if ( sty == ACL_STYLE_SELF ) {
2836 bdn->a_self_level = level;
2837
2838 } else {
2839 if ( level < 0 ) {
2840- Debug( LDAP_DEBUG_ANY,
2841- "%s: line %d: bad negative level \"%d\" "
2842- "in by DN clause\n",
2843- fname, lineno, level );
2844+ snprintf( c->cr_msg, sizeof( c ->cr_msg ),
2845+ "bad negative level \"%d\" in by DN clause", level );
2846+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2847 goto fail;
2848 } else if ( level == 1 ) {
2849- Debug( LDAP_DEBUG_ANY,
2850- "%s: line %d: \"onelevel\" should be used "
2851- "instead of \"level{1}\" in by DN clause\n",
2852- fname, lineno );
2853+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2854+ "\"onelevel\" should be used instead of \"level{1}\" in by DN clause" );
2855+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2856 } else if ( level == 0 && sty == ACL_STYLE_LEVEL ) {
2857- Debug( LDAP_DEBUG_ANY,
2858- "%s: line %d: \"base\" should be used "
2859- "instead of \"level{0}\" in by DN clause\n",
2860- fname, lineno );
2861+ snprintf ( c->cr_msg, sizeof( c->cr_msg ),
2862+ "\"base\" should be used instead of \"level{0}\" in by DN clause" );
2863+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2864 }
2865
2866 bdn->a_level = level;
2867@@ -1015,27 +1009,25 @@ parse_acl(
2868
2869 if ( strcasecmp( left, "dnattr" ) == 0 ) {
2870 if ( right == NULL || right[0] == '\0' ) {
2871- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2872- "missing \"=\" in (or value after) \"%s\" "
2873- "in by clause\n",
2874- fname, lineno, left );
2875+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2876+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
2877+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2878 goto fail;
2879 }
2880
2881 if( bdn->a_at != NULL ) {
2882- Debug( LDAP_DEBUG_ANY,
2883- "%s: line %d: dnattr already specified.\n",
2884- fname, lineno );
2885+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2886+ "dnattr already specified" );
2887+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2888 goto fail;
2889 }
2890
2891 rc = slap_str2ad( right, &bdn->a_at, &text );
2892
2893 if( rc != LDAP_SUCCESS ) {
2894- Debug(LDAP_DEBUG_ANY,
2895- "%s: line %d: dnattr \"%s\": %s\n",
2896- fname, lineno, right,
2897- text );
2898+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2899+ "dnattr \"%s\": %s", right, text );
2900+ Debug(LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2901 goto fail;
2902 }
2903
2904@@ -1045,18 +1037,17 @@ parse_acl(
2905 !is_at_syntax( bdn->a_at->ad_type,
2906 SLAPD_NAMEUID_SYNTAX ))
2907 {
2908- Debug(LDAP_DEBUG_ANY,
2909- "%s: line %d: dnattr \"%s\": " "inappropriate syntax: %s\n\n",
2910- fname, lineno, right,
2911- bdn->a_at->ad_type->sat_syntax_oid );
2912+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2913+ "dnattr \"%s\": " "inappropriate syntax: %s",
2914+ right, bdn->a_at->ad_type->sat_syntax_oid );
2915+ Debug(LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2916 goto fail;
2917 }
2918
2919 if( bdn->a_at->ad_type->sat_equality == NULL ) {
2920- Debug( LDAP_DEBUG_ANY,
2921- "%s: line %d: dnattr \"%s\": "
2922- "inappropriate matching (no EQUALITY)\n",
2923- fname, lineno, right );
2924+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2925+ "dnattr \"%s\": inappropriate matching (no EQUALITY)", right );
2926+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2927 goto fail;
2928 }
2929
2930@@ -1071,11 +1062,9 @@ parse_acl(
2931 switch ( sty ) {
2932 case ACL_STYLE_REGEX:
2933 /* legacy, tolerated */
2934- Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
2935- "%s: line %d: "
2936- "deprecated group style \"regex\"; "
2937- "use \"expand\" instead.\n",
2938- fname, lineno );
2939+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2940+ "deprecated group style \"regex\"; use \"expand\" instead" );
2941+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
2942 sty = ACL_STYLE_EXPAND;
2943 break;
2944
2945@@ -1087,26 +1076,23 @@ parse_acl(
2946
2947 default:
2948 /* unknown */
2949- Debug( LDAP_DEBUG_ANY,
2950- "%s: line %d: "
2951- "inappropriate style \"%s\" in by clause.\n",
2952- fname, lineno, style );
2953+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2954+ "inappropriate style \"%s\" in by clause", style );
2955+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2956 goto fail;
2957 }
2958
2959 if ( right == NULL || right[0] == '\0' ) {
2960- Debug( LDAP_DEBUG_ANY,
2961- "%s: line %d: "
2962- "missing \"=\" in (or value after) \"%s\" "
2963- "in by clause.\n",
2964- fname, lineno, left );
2965+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2966+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
2967+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2968 goto fail;
2969 }
2970
2971 if ( !BER_BVISEMPTY( &b->a_group_pat ) ) {
2972- Debug( LDAP_DEBUG_ANY,
2973- "%s: line %d: group pattern already specified.\n",
2974- fname, lineno );
2975+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
2976+ "group pattern already specified" );
2977+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2978 goto fail;
2979 }
2980
2981@@ -1123,7 +1109,8 @@ parse_acl(
2982 if ( sty == ACL_STYLE_EXPAND ) {
2983 acl_regex_normalized_dn( right, &bv );
2984 if ( !ber_bvccmp( &bv, '*' ) ) {
2985- regtest( fname, lineno, bv.bv_val );
2986+ if ( regtest( c, bv.bv_val ) != 0)
2987+ goto fail;
2988 }
2989 b->a_group_pat = bv;
2990
2991@@ -1132,9 +1119,9 @@ parse_acl(
2992 rc = dnNormalize( 0, NULL, NULL, &bv,
2993 &b->a_group_pat, NULL );
2994 if ( rc != LDAP_SUCCESS ) {
2995- Debug( LDAP_DEBUG_ANY,
2996- "%s: line %d: bad DN \"%s\".\n",
2997- fname, lineno, right );
2998+ snprintf( c->cr_msg, sizeof( c->cr_msg),
2999+ "bad DN \"%s\"", right );
3000+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3001 goto fail;
3002 }
3003 }
3004@@ -1144,10 +1131,9 @@ parse_acl(
3005 *--value = '/';
3006
3007 if ( b->a_group_oc == NULL ) {
3008- Debug( LDAP_DEBUG_ANY,
3009- "%s: line %d: group objectclass "
3010- "\"%s\" unknown.\n",
3011- fname, lineno, value );
3012+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3013+ "group objectclass \"%s\" unknown", value );
3014+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3015 goto fail;
3016 }
3017
3018@@ -1155,10 +1141,9 @@ parse_acl(
3019 b->a_group_oc = oc_find( SLAPD_GROUP_CLASS );
3020
3021 if( b->a_group_oc == NULL ) {
3022- Debug( LDAP_DEBUG_ANY,
3023- "%s: line %d: group default objectclass "
3024- "\"%s\" unknown.\n",
3025- fname, lineno, SLAPD_GROUP_CLASS );
3026+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3027+ "group default objectclass \"%s\" unknown", SLAPD_GROUP_CLASS );
3028+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3029 goto fail;
3030 }
3031 }
3032@@ -1166,20 +1151,18 @@ parse_acl(
3033 if ( is_object_subclass( slap_schema.si_oc_referral,
3034 b->a_group_oc ) )
3035 {
3036- Debug( LDAP_DEBUG_ANY,
3037- "%s: line %d: group objectclass \"%s\" "
3038- "is subclass of referral.\n",
3039- fname, lineno, value );
3040+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3041+ "group objectclass \"%s\" is subclass of referral", value );
3042+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3043 goto fail;
3044 }
3045
3046 if ( is_object_subclass( slap_schema.si_oc_alias,
3047 b->a_group_oc ) )
3048 {
3049- Debug( LDAP_DEBUG_ANY,
3050- "%s: line %d: group objectclass \"%s\" "
3051- "is subclass of alias.\n",
3052- fname, lineno, value );
3053+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3054+ "group objectclass \"%s\" is subclass of alias", value );
3055+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3056 goto fail;
3057 }
3058
3059@@ -1191,10 +1174,9 @@ parse_acl(
3060
3061 rc = slap_str2ad( attr_name, &b->a_group_at, &text );
3062 if ( rc != LDAP_SUCCESS ) {
3063- Debug(LDAP_DEBUG_ANY,
3064- "%s: line %d: group \"%s\": %s.\n",
3065- fname, lineno, right,
3066- text );
3067+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3068+ "group \"%s\": %s", right, text );
3069+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3070 goto fail;
3071 }
3072
3073@@ -1205,11 +1187,10 @@ parse_acl(
3074 && !is_at_subtype( b->a_group_at->ad_type,
3075 slap_schema.si_ad_labeledURI->ad_type ) /* e.g. memberURL */ )
3076 {
3077- Debug(LDAP_DEBUG_ANY,
3078- "%s: line %d: group \"%s\" attr \"%s\": inappropriate syntax: %s; " "must be " SLAPD_DN_SYNTAX " (DN), " SLAPD_NAMEUID_SYNTAX " (NameUID) " "or a subtype of labeledURI.\n",
3079- fname, lineno, right,
3080- attr_name,
3081- at_syntax(b->a_group_at->ad_type) );
3082+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3083+ "group \"%s\" attr \"%s\": inappropriate syntax: %s; " "must be " SLAPD_DN_SYNTAX " (DN), " SLAPD_NAMEUID_SYNTAX " (NameUID) " "or a subtype of labeledURI",
3084+ right, attr_name, at_syntax(b->a_group_at->ad_type) );
3085+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3086 goto fail;
3087 }
3088
3089@@ -1225,11 +1206,11 @@ parse_acl(
3090 ocs, NULL );
3091
3092 if( rc != 0 ) {
3093- Debug(LDAP_DEBUG_ANY,
3094- "%s: line %d: group: \"%s\" not allowed by \"%s\".\n",
3095- fname, lineno,
3096+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3097+ "group: \"%s\" not allowed by \"%s\".\n",
3098 b->a_group_at->ad_cname.bv_val,
3099 b->a_group_oc->soc_oid );
3100+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3101 goto fail;
3102 }
3103 }
3104@@ -1250,24 +1231,23 @@ parse_acl(
3105 break;
3106
3107 default:
3108- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3109- "inappropriate style \"%s\" in by clause.\n",
3110- fname, lineno, style );
3111+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3112+ "inappropriate style \"%s\" in by clause", style );
3113+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3114 goto fail;
3115 }
3116
3117 if ( right == NULL || right[0] == '\0' ) {
3118- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3119- "missing \"=\" in (or value after) \"%s\" "
3120- "in by clause.\n",
3121- fname, lineno, left );
3122+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3123+ "missing \"=\" in (or value after) \"%s\" in by clause", left);
3124+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3125 goto fail;
3126 }
3127
3128 if ( !BER_BVISEMPTY( &b->a_peername_pat ) ) {
3129- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3130- "peername pattern already specified.\n",
3131- fname, lineno );
3132+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3133+ "peername pattern already specified" );
3134+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3135 goto fail;
3136 }
3137
3138@@ -1275,7 +1255,8 @@ parse_acl(
3139 if ( sty == ACL_STYLE_REGEX ) {
3140 acl_regex_normalized_dn( right, &bv );
3141 if ( !ber_bvccmp( &bv, '*' ) ) {
3142- regtest( fname, lineno, bv.bv_val );
3143+ if ( regtest( c, bv.bv_val ) != 0)
3144+ goto fail;
3145 }
3146 b->a_peername_pat = bv;
3147
3148@@ -1293,9 +1274,9 @@ parse_acl(
3149 b->a_peername_addr = inet_addr( addr );
3150 if ( b->a_peername_addr == (unsigned long)(-1) ) {
3151 /* illegal address */
3152- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3153- "illegal peername address \"%s\".\n",
3154- fname, lineno, addr );
3155+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3156+ "illegal peername address \"%s\"", addr );
3157+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3158 goto fail;
3159 }
3160
3161@@ -1306,13 +1287,12 @@ parse_acl(
3162 (unsigned long)(-1) )
3163 {
3164 /* illegal mask */
3165- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3166- "illegal peername address mask "
3167- "\"%s\".\n",
3168- fname, lineno, mask );
3169+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3170+ "illegal peername address mask \"%s\"", mask );
3171+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3172 goto fail;
3173 }
3174- }
3175+ }
3176
3177 b->a_peername_port = -1;
3178 if ( port ) {
3179@@ -1321,10 +1301,9 @@ parse_acl(
3180 b->a_peername_port = strtol( port, &end, 10 );
3181 if ( end == port || end[0] != '}' ) {
3182 /* illegal port */
3183- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3184- "illegal peername port specification "
3185- "\"{%s}\".\n",
3186- fname, lineno, port );
3187+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3188+ "illegal peername port specification \"{%s}\"", port );
3189+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3190 goto fail;
3191 }
3192 }
3193@@ -1340,9 +1319,9 @@ parse_acl(
3194
3195 if ( inet_pton( AF_INET6, addr, &b->a_peername_addr6 ) != 1 ) {
3196 /* illegal address */
3197- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3198- "illegal peername address \"%s\".\n",
3199- fname, lineno, addr );
3200+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3201+ "illegal peername address \"%s\"", addr );
3202+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3203 goto fail;
3204 }
3205
3206@@ -1352,10 +1331,9 @@ parse_acl(
3207
3208 if ( inet_pton( AF_INET6, mask, &b->a_peername_mask6 ) != 1 ) {
3209 /* illegal mask */
3210- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3211- "illegal peername address mask "
3212- "\"%s\".\n",
3213- fname, lineno, mask );
3214+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3215+ "illegal peername address mask \"%s\"", mask );
3216+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3217 goto fail;
3218 }
3219
3220@@ -1366,10 +1344,9 @@ parse_acl(
3221 b->a_peername_port = strtol( port, &end, 10 );
3222 if ( end == port || end[0] != '}' ) {
3223 /* illegal port */
3224- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3225- "illegal peername port specification "
3226- "\"{%s}\".\n",
3227- fname, lineno, port );
3228+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3229+ "illegal peername port specification \"{%s}\"", port );
3230+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3231 goto fail;
3232 }
3233 }
3234@@ -1390,24 +1367,23 @@ parse_acl(
3235
3236 default:
3237 /* unknown */
3238- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3239- "inappropriate style \"%s\" in by clause\n",
3240- fname, lineno, style );
3241+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3242+ "inappropriate style \"%s\" in by clause", style );
3243+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3244 goto fail;
3245 }
3246
3247 if ( right == NULL || right[0] == '\0' ) {
3248- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3249- "missing \"=\" in (or value after) \"%s\" "
3250- "in by clause\n",
3251- fname, lineno, left );
3252+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3253+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
3254+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3255 goto fail;
3256 }
3257
3258 if ( !BER_BVISNULL( &b->a_sockname_pat ) ) {
3259- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3260- "sockname pattern already specified.\n",
3261- fname, lineno );
3262+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3263+ "sockname pattern already specified" );
3264+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3265 goto fail;
3266 }
3267
3268@@ -1415,10 +1391,11 @@ parse_acl(
3269 if ( sty == ACL_STYLE_REGEX ) {
3270 acl_regex_normalized_dn( right, &bv );
3271 if ( !ber_bvccmp( &bv, '*' ) ) {
3272- regtest( fname, lineno, bv.bv_val );
3273+ if ( regtest( c, bv.bv_val ) != 0)
3274+ goto fail;
3275 }
3276 b->a_sockname_pat = bv;
3277-
3278+
3279 } else {
3280 ber_str2bv( right, 0, 1, &b->a_sockname_pat );
3281 }
3282@@ -1436,11 +1413,9 @@ parse_acl(
3283 case ACL_STYLE_EXPAND:
3284 /* tolerated: means exact,expand */
3285 if ( expand ) {
3286- Debug( LDAP_DEBUG_ANY,
3287- "%s: line %d: "
3288- "\"expand\" modifier "
3289- "with \"expand\" style.\n",
3290- fname, lineno );
3291+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3292+ "\"expand\" modifier with \"expand\" style" );
3293+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3294 }
3295 sty = ACL_STYLE_BASE;
3296 expand = 1;
3297@@ -1448,24 +1423,23 @@ parse_acl(
3298
3299 default:
3300 /* unknown */
3301- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3302- "inappropriate style \"%s\" in by clause.\n",
3303- fname, lineno, style );
3304+ snprintf( c->cr_msg, sizeof( c->cr_msg),
3305+ "inappropriate style \"%s\" in by clause", style );
3306+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3307 goto fail;
3308 }
3309
3310 if ( right == NULL || right[0] == '\0' ) {
3311- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3312- "missing \"=\" in (or value after) \"%s\" "
3313- "in by clause.\n",
3314- fname, lineno, left );
3315+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3316+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
3317+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3318 goto fail;
3319 }
3320
3321 if ( !BER_BVISEMPTY( &b->a_domain_pat ) ) {
3322- Debug( LDAP_DEBUG_ANY,
3323- "%s: line %d: domain pattern already specified.\n",
3324- fname, lineno );
3325+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3326+ "domain pattern already specified" );
3327+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3328 goto fail;
3329 }
3330
3331@@ -1474,7 +1448,8 @@ parse_acl(
3332 if ( sty == ACL_STYLE_REGEX ) {
3333 acl_regex_normalized_dn( right, &bv );
3334 if ( !ber_bvccmp( &bv, '*' ) ) {
3335- regtest( fname, lineno, bv.bv_val );
3336+ if ( regtest( c, bv.bv_val ) != 0)
3337+ goto fail;
3338 }
3339 b->a_domain_pat = bv;
3340
3341@@ -1495,24 +1470,23 @@ parse_acl(
3342
3343 default:
3344 /* unknown */
3345- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3346- "inappropriate style \"%s\" in by clause.\n",
3347- fname, lineno, style );
3348+ snprintf( c->cr_msg, sizeof( c->cr_msg),
3349+ "inappropriate style \"%s\" in by clause", style );
3350+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3351 goto fail;
3352 }
3353
3354 if ( right == NULL || right[0] == '\0' ) {
3355- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3356- "missing \"=\" in (or value after) \"%s\" "
3357- "in by clause.\n",
3358- fname, lineno, left );
3359+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3360+ "missing \"=\" in (or value after) \"%s\" in by clause", left );
3361+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3362 goto fail;
3363 }
3364
3365 if ( !BER_BVISEMPTY( &b->a_sockurl_pat ) ) {
3366- Debug( LDAP_DEBUG_ANY,
3367- "%s: line %d: sockurl pattern already specified.\n",
3368- fname, lineno );
3369+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3370+ "sockurl pattern already specified" );
3371+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3372 goto fail;
3373 }
3374
3375@@ -1520,10 +1494,11 @@ parse_acl(
3376 if ( sty == ACL_STYLE_REGEX ) {
3377 acl_regex_normalized_dn( right, &bv );
3378 if ( !ber_bvccmp( &bv, '*' ) ) {
3379- regtest( fname, lineno, bv.bv_val );
3380+ if ( regtest( c, bv.bv_val ) != 0)
3381+ goto fail;
3382 }
3383 b->a_sockurl_pat = bv;
3384-
3385+
3386 } else {
3387 ber_str2bv( right, 0, 1, &b->a_sockurl_pat );
3388 }
3389@@ -1534,37 +1509,36 @@ parse_acl(
3390 switch ( sty ) {
3391 /* deprecated */
3392 case ACL_STYLE_REGEX:
3393- Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL,
3394- "%s: line %d: "
3395+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3396 "deprecated set style "
3397 "\"regex\" in <by> clause; "
3398- "use \"expand\" instead.\n",
3399- fname, lineno );
3400+ "use \"expand\" instead" );
3401+ Debug( LDAP_DEBUG_CONFIG | LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3402 sty = ACL_STYLE_EXPAND;
3403 /* FALLTHRU */
3404-
3405+
3406 case ACL_STYLE_BASE:
3407 case ACL_STYLE_EXPAND:
3408 break;
3409
3410 default:
3411- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3412- "inappropriate style \"%s\" in by clause.\n",
3413- fname, lineno, style );
3414+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3415+ "inappropriate style \"%s\" in by clause", style );
3416+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3417 goto fail;
3418 }
3419
3420 if ( !BER_BVISEMPTY( &b->a_set_pat ) ) {
3421- Debug( LDAP_DEBUG_ANY,
3422- "%s: line %d: set attribute already specified.\n",
3423- fname, lineno );
3424+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3425+ "set attribute already specified" );
3426+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3427 goto fail;
3428 }
3429
3430 if ( right == NULL || *right == '\0' ) {
3431- Debug( LDAP_DEBUG_ANY,
3432- "%s: line %d: no set is defined.\n",
3433- fname, lineno );
3434+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3435+ "no set is defined" );
3436+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3437 goto fail;
3438 }
3439
3440@@ -1581,12 +1555,12 @@ parse_acl(
3441
3442 #if 1 /* tolerate legacy "aci" <who> */
3443 if ( strcasecmp( left, "aci" ) == 0 ) {
3444- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3445+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3446 "undocumented deprecated \"aci\" directive "
3447- "is superseded by \"dynacl/aci\".\n",
3448- fname, lineno );
3449+ "is superseded by \"dynacl/aci\"" );
3450+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3451 name = "aci";
3452-
3453+
3454 } else
3455 #endif /* tolerate legacy "aci" <who> */
3456 if ( strncasecmp( left, "dynacl/", STRLENOF( "dynacl/" ) ) == 0 ) {
3457@@ -1599,10 +1573,10 @@ parse_acl(
3458 }
3459
3460 if ( name ) {
3461- if ( slap_dynacl_config( fname, lineno, b, name, opts, sty, right ) ) {
3462- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3463- "unable to configure dynacl \"%s\".\n",
3464- fname, lineno, name );
3465+ if ( slap_dynacl_config( c, b, name, opts, sty, right ) ) {
3466+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3467+ "unable to configure dynacl \"%s\"", name );
3468+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3469 goto fail;
3470 }
3471
3472@@ -1613,37 +1587,37 @@ parse_acl(
3473
3474 if ( strcasecmp( left, "ssf" ) == 0 ) {
3475 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
3476- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3477- "inappropriate style \"%s\" in by clause.\n",
3478- fname, lineno, style );
3479+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3480+ "inappropriate style \"%s\" in by clause", style );
3481+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3482 goto fail;
3483 }
3484
3485 if ( b->a_authz.sai_ssf ) {
3486- Debug( LDAP_DEBUG_ANY,
3487- "%s: line %d: ssf attribute already specified.\n",
3488- fname, lineno );
3489+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3490+ "ssf attribute already specified" );
3491+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3492 goto fail;
3493 }
3494
3495 if ( right == NULL || *right == '\0' ) {
3496- Debug( LDAP_DEBUG_ANY,
3497- "%s: line %d: no ssf is defined.\n",
3498- fname, lineno );
3499+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3500+ "no ssf is defined" );
3501+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3502 goto fail;
3503 }
3504
3505 if ( lutil_atou( &b->a_authz.sai_ssf, right ) != 0 ) {
3506- Debug( LDAP_DEBUG_ANY,
3507- "%s: line %d: unable to parse ssf value (%s).\n",
3508- fname, lineno, right );
3509+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3510+ "unable to parse ssf value (%s)", right );
3511+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3512 goto fail;
3513 }
3514
3515 if ( !b->a_authz.sai_ssf ) {
3516- Debug( LDAP_DEBUG_ANY,
3517- "%s: line %d: invalid ssf value (%s).\n",
3518- fname, lineno, right );
3519+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3520+ "invalid ssf value (%s)", right );
3521+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3522 goto fail;
3523 }
3524 continue;
3525@@ -1651,37 +1625,37 @@ parse_acl(
3526
3527 if ( strcasecmp( left, "transport_ssf" ) == 0 ) {
3528 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
3529- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3530- "inappropriate style \"%s\" in by clause.\n",
3531- fname, lineno, style );
3532+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3533+ "inappropriate style \"%s\" in by clause", style );
3534+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3535 goto fail;
3536 }
3537
3538 if ( b->a_authz.sai_transport_ssf ) {
3539- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3540- "transport_ssf attribute already specified.\n",
3541- fname, lineno );
3542+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3543+ "transport_ssf attribute already specified" );
3544+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3545 goto fail;
3546 }
3547
3548 if ( right == NULL || *right == '\0' ) {
3549- Debug( LDAP_DEBUG_ANY,
3550- "%s: line %d: no transport_ssf is defined.\n",
3551- fname, lineno );
3552+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3553+ "no transport_ssf is defined" );
3554+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3555 goto fail;
3556 }
3557
3558 if ( lutil_atou( &b->a_authz.sai_transport_ssf, right ) != 0 ) {
3559- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3560- "unable to parse transport_ssf value (%s).\n",
3561- fname, lineno, right );
3562+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3563+ "unable to parse transport_ssf value (%s)", right );
3564+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3565 goto fail;
3566 }
3567
3568 if ( !b->a_authz.sai_transport_ssf ) {
3569- Debug( LDAP_DEBUG_ANY,
3570- "%s: line %d: invalid transport_ssf value (%s).\n",
3571- fname, lineno, right );
3572+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3573+ "invalid transport_ssf value (%s)", right );
3574+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3575 goto fail;
3576 }
3577 continue;
3578@@ -1689,37 +1663,36 @@ parse_acl(
3579
3580 if ( strcasecmp( left, "tls_ssf" ) == 0 ) {
3581 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
3582- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3583- "inappropriate style \"%s\" in by clause.\n",
3584- fname, lineno, style );
3585+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3586+ "inappropriate style \"%s\" in by clause", style );
3587+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3588 goto fail;
3589 }
3590
3591 if ( b->a_authz.sai_tls_ssf ) {
3592- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3593- "tls_ssf attribute already specified.\n",
3594- fname, lineno );
3595+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3596+ "tls_ssf attribute already specified" );
3597 goto fail;
3598 }
3599
3600 if ( right == NULL || *right == '\0' ) {
3601- Debug( LDAP_DEBUG_ANY,
3602- "%s: line %d: no tls_ssf is defined\n",
3603- fname, lineno );
3604+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3605+ "no tls_ssf is defined" );
3606+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3607 goto fail;
3608 }
3609
3610 if ( lutil_atou( &b->a_authz.sai_tls_ssf, right ) != 0 ) {
3611- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3612- "unable to parse tls_ssf value (%s).\n",
3613- fname, lineno, right );
3614+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3615+ "unable to parse tls_ssf value (%s)", right );
3616+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3617 goto fail;
3618 }
3619
3620 if ( !b->a_authz.sai_tls_ssf ) {
3621- Debug( LDAP_DEBUG_ANY,
3622- "%s: line %d: invalid tls_ssf value (%s).\n",
3623- fname, lineno, right );
3624+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3625+ "invalid tls_ssf value (%s)", right );
3626+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3627 goto fail;
3628 }
3629 continue;
3630@@ -1727,37 +1700,37 @@ parse_acl(
3631
3632 if ( strcasecmp( left, "sasl_ssf" ) == 0 ) {
3633 if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
3634- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3635- "inappropriate style \"%s\" in by clause.\n",
3636- fname, lineno, style );
3637+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3638+ "inappropriate style \"%s\" in by clause", style );
3639+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3640 goto fail;
3641 }
3642
3643 if ( b->a_authz.sai_sasl_ssf ) {
3644- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3645- "sasl_ssf attribute already specified.\n",
3646- fname, lineno );
3647+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3648+ "sasl_ssf attribute already specified" );
3649+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3650 goto fail;
3651 }
3652
3653 if ( right == NULL || *right == '\0' ) {
3654- Debug( LDAP_DEBUG_ANY,
3655- "%s: line %d: no sasl_ssf is defined.\n",
3656- fname, lineno );
3657+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3658+ "no sasl_ssf is defined" );
3659+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3660 goto fail;
3661 }
3662
3663 if ( lutil_atou( &b->a_authz.sai_sasl_ssf, right ) != 0 ) {
3664- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3665- "unable to parse sasl_ssf value (%s).\n",
3666- fname, lineno, right );
3667+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3668+ "unable to parse sasl_ssf value (%s)", right );
3669+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3670 goto fail;
3671 }
3672
3673 if ( !b->a_authz.sai_sasl_ssf ) {
3674- Debug( LDAP_DEBUG_ANY,
3675- "%s: line %d: invalid sasl_ssf value (%s).\n",
3676- fname, lineno, right );
3677+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3678+ "invalid sasl_ssf value (%s)", right );
3679+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3680 goto fail;
3681 }
3682 continue;
3683@@ -1770,7 +1743,7 @@ parse_acl(
3684 break;
3685 }
3686
3687- if ( i == argc || ( strcasecmp( left, "stop" ) == 0 ) ) {
3688+ if ( i == argc || ( strcasecmp( left, "stop" ) == 0 ) ) {
3689 /* out of arguments or plain stop */
3690
3691 ACL_PRIV_ASSIGN( b->a_access_mask, ACL_PRIV_ADDITIVE );
3692@@ -1831,9 +1804,9 @@ parse_acl(
3693 }
3694
3695 if ( ACL_IS_INVALID( b->a_access_mask ) ) {
3696- Debug( LDAP_DEBUG_ANY,
3697- "%s: line %d: expecting <access> got \"%s\".\n",
3698- fname, lineno, left );
3699+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3700+ "expecting <access> got \"%s\"", left );
3701+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3702 goto fail;
3703 }
3704
3705@@ -1862,19 +1835,18 @@ parse_acl(
3706 b = NULL;
3707
3708 } else {
3709- Debug( LDAP_DEBUG_ANY,
3710- "%s: line %d: expecting \"to\" "
3711- "or \"by\" got \"%s\"\n",
3712- fname, lineno, argv[i] );
3713+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3714+ "expecting \"to\" or \"by\" got \"%s\"", argv[i] );
3715+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3716 goto fail;
3717 }
3718 }
3719
3720 /* if we have no real access clause, complain and do nothing */
3721 if ( a == NULL ) {
3722- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3723- "warning: no access clause(s) specified in access line.\n",
3724- fname, lineno );
3725+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3726+ "warning: no access clause(s) specified in access line");
3727+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3728 goto fail;
3729
3730 } else {
3731@@ -1883,53 +1855,49 @@ parse_acl(
3732 print_acl( be, a );
3733 }
3734 #endif
3735-
3736+
3737 if ( a->acl_access == NULL ) {
3738- Debug( LDAP_DEBUG_ANY, "%s: line %d: "
3739- "warning: no by clause(s) specified in access line.\n",
3740- fname, lineno );
3741+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3742+ "warning: no by clause(s) specified in access line" );
3743+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3744 goto fail;
3745 }
3746
3747 if ( be != NULL ) {
3748 if ( be->be_nsuffix == NULL ) {
3749- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3750- "scope checking needs suffix before ACLs.\n",
3751- fname, lineno );
3752+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3753+ "warning: scope checking needs suffix before ACLs" );
3754+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3755 /* go ahead, since checking is not authoritative */
3756 } else if ( !BER_BVISNULL( &be->be_nsuffix[ 1 ] ) ) {
3757- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3758- "scope checking only applies to single-valued "
3759- "suffix databases\n",
3760- fname, lineno );
3761+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3762+ "warning: scope checking only applies to single-valued suffix databases" );
3763+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3764 /* go ahead, since checking is not authoritative */
3765 } else {
3766 switch ( check_scope( be, a ) ) {
3767 case ACL_SCOPE_UNKNOWN:
3768- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3769- "cannot assess the validity of the ACL scope within "
3770- "backend naming context\n",
3771- fname, lineno );
3772+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3773+ "warning: cannot assess the validity of the ACL scope within backend naming context" );
3774+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3775 break;
3776
3777 case ACL_SCOPE_WARN:
3778- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3779- "ACL could be out of scope within backend naming context\n",
3780- fname, lineno );
3781+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3782+ "warning: ACL could be out of scope within backend naming context" );
3783+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3784 break;
3785
3786 case ACL_SCOPE_PARTIAL:
3787- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3788- "ACL appears to be partially out of scope within "
3789- "backend naming context\n",
3790- fname, lineno );
3791+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3792+ "warning: ACL appears to be partially out of scope within backend naming context" );
3793+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3794 break;
3795-
3796+
3797 case ACL_SCOPE_ERR:
3798- Debug( LDAP_DEBUG_ACL, "%s: line %d: warning: "
3799- "ACL appears to be out of scope within "
3800- "backend naming context\n",
3801- fname, lineno );
3802+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
3803+ "warning: ACL appears to be out of scope within backend naming context" );
3804+ Debug( LDAP_DEBUG_ACL, "%s: %s.\n", c->log, c->cr_msg );
3805 break;
3806
3807 default:
3808@@ -1999,7 +1967,7 @@ accessmask2str( slap_mask_t mask, char *buf, int debug )
3809 } else {
3810 ptr = lutil_strcopy( ptr, "unknown" );
3811 }
3812-
3813+
3814 if ( !debug ) {
3815 *ptr = '\0';
3816 return buf;
3817@@ -2020,7 +1988,7 @@ accessmask2str( slap_mask_t mask, char *buf, int debug )
3818 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_MANAGE) ) {
3819 none = 0;
3820 *ptr++ = 'm';
3821- }
3822+ }
3823
3824 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
3825 none = 0;
3826@@ -2033,37 +2001,37 @@ accessmask2str( slap_mask_t mask, char *buf, int debug )
3827 } else if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WDEL) ) {
3828 none = 0;
3829 *ptr++ = 'z';
3830- }
3831+ }
3832
3833 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
3834 none = 0;
3835 *ptr++ = 'r';
3836- }
3837+ }
3838
3839 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
3840 none = 0;
3841 *ptr++ = 's';
3842- }
3843+ }
3844
3845 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
3846 none = 0;
3847 *ptr++ = 'c';
3848- }
3849+ }
3850
3851 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
3852 none = 0;
3853 *ptr++ = 'x';
3854- }
3855+ }
3856
3857 if ( ACL_PRIV_ISSET(mask, ACL_PRIV_DISCLOSE) ) {
3858 none = 0;
3859 *ptr++ = 'd';
3860- }
3861+ }
3862
3863 if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
3864 none = 0;
3865 *ptr++ = '0';
3866- }
3867+ }
3868
3869 if ( none ) {
3870 ptr = buf;
3871@@ -2178,7 +2146,7 @@ str2accessmask( const char *str )
3872 }
3873
3874 static int
3875-acl_usage( void )
3876+acl_usage(void)
3877 {
3878 char *access =
3879 "<access clause> ::= access to <what> "
3880@@ -2227,7 +2195,7 @@ acl_usage( void )
3881
3882 /*
3883 * Set pattern to a "normalized" DN from src.
3884- * At present it simply eats the (optional) space after
3885+ * At present, it simply eats the (optional) space after
3886 * a RDN separator (,)
3887 * Eventually will evolve in a more complete normalization
3888 */
3889@@ -2245,10 +2213,10 @@ acl_regex_normalized_dn(
3890 for ( p = str; p && p[0]; p++ ) {
3891 /* escape */
3892 if ( p[0] == '\\' && p[1] ) {
3893- /*
3894+ /*
3895 * if escaping a hex pair we should
3896- * increment p twice; however, in that
3897- * case the second hex number does
3898+ * increment p twice; however, in that
3899+ * case the second hex number does
3900 * no harm
3901 */
3902 p++;
3903@@ -2256,7 +2224,7 @@ acl_regex_normalized_dn(
3904
3905 if ( p[0] == ',' && p[1] == ' ' ) {
3906 char *q;
3907-
3908+
3909 /*
3910 * too much space should be an error if we are pedantic
3911 */
3912@@ -2532,7 +2500,7 @@ dnaccess2text( slap_dn_access *bdn, char *ptr, int is_realdn )
3913 if ( is_realdn ) {
3914 assert( ! ber_bvccmp( &bdn->a_pat, '*' ) );
3915 }
3916-
3917+
3918 ptr = acl_safe_strbvcopy( ptr, &bdn->a_pat );
3919 if ( bdn->a_style == ACL_STYLE_SELF && bdn->a_self_level != 0 ) {
3920 char buf[SLAP_TEXT_BUFLEN];
3921@@ -2546,7 +2514,7 @@ dnaccess2text( slap_dn_access *bdn, char *ptr, int is_realdn )
3922 ptr = acl_safe_strcopy( ptr, "dn." );
3923 if ( bdn->a_style == ACL_STYLE_BASE )
3924 ptr = acl_safe_strcopy( ptr, style_base );
3925- else
3926+ else
3927 ptr = acl_safe_strcopy( ptr, style_strings[bdn->a_style] );
3928 if ( bdn->a_style == ACL_STYLE_LEVEL ) {
3929 char buf[SLAP_TEXT_BUFLEN];
3930@@ -2668,7 +2636,7 @@ access2text( Access *b, char *ptr )
3931 /* Security Strength Factors */
3932 if ( b->a_authz.sai_ssf ) {
3933 char buf[SLAP_TEXT_BUFLEN];
3934- int n = snprintf( buf, sizeof(buf), " ssf=%u",
3935+ int n = snprintf( buf, sizeof(buf), " ssf=%u",
3936 b->a_authz.sai_ssf );
3937 ptr = acl_safe_strncopy( ptr, buf, n );
3938 }
3939diff --git a/servers/slapd/back-asyncmeta/map.c b/servers/slapd/back-asyncmeta/map.c
3940index b811708..66bb8b0 100644
3941--- a/servers/slapd/back-asyncmeta/map.c
3942+++ b/servers/slapd/back-asyncmeta/map.c
3943@@ -197,16 +197,26 @@ ignore:
3944 }
3945
3946 /* DN longer than our suffix and doesn't match */
3947- if ( diff > 0 && !DN_SEPARATOR(dn->bv_val[diff-1]))
3948+ if ( osuff->bv_len != 0 && diff > 0 && !DN_SEPARATOR(dn->bv_val[diff-1]) )
3949 goto ignore;
3950
3951 /* suffix is same length as ours, but doesn't match */
3952 if ( strcasecmp( osuff->bv_val, &dn->bv_val[diff] ))
3953 goto ignore;
3954
3955+ /* if remote suffix is empty, remove or add the dn separator*/
3956+ if ( nsuff->bv_len == 0 ) {
3957+ diff--;
3958+ } else if ( osuff->bv_len == 0 ) {
3959+ diff++;
3960+ }
3961+
3962+
3963 res->bv_len = diff + nsuff->bv_len;
3964 res->bv_val = dc->op->o_tmpalloc( res->bv_len + 1, dc->memctx );
3965 strncpy( res->bv_val, dn->bv_val, diff );
3966+ if ( osuff->bv_len == 0 )
3967+ res->bv_val[diff-1] = ',';
3968 strcpy( &res->bv_val[diff], nsuff->bv_val );
3969
3970 if (pretty.bv_val)
3971diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c
3972index d6ffd1a..fece74d 100644
3973--- a/servers/slapd/back-ldap/chain.c
3974+++ b/servers/slapd/back-ldap/chain.c
3975@@ -1040,7 +1040,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
3976
3977 /* we need this to know if back-ldap returned any result */
3978 lb.lb_lc = lc;
3979- sc2.sc_next = sc->sc_next;
3980+ sc2.sc_next = sc;
3981 sc2.sc_private = &lb;
3982 sc2.sc_response = ldap_chain_cb_response;
3983 op->o_callback = &sc2;
3984diff --git a/servers/slapd/back-null/null.c b/servers/slapd/back-null/null.c
3985index 50b6fbc..c8d3292 100644
3986--- a/servers/slapd/back-null/null.c
3987+++ b/servers/slapd/back-null/null.c
3988@@ -72,8 +72,8 @@ null_back_db_open( BackendDB *be, ConfigReply *cr )
3989
3990 if ( ni->ni_dosearch ) {
3991 e = entry_alloc();
3992- e->e_name = be->be_suffix[0];
3993- e->e_nname = be->be_nsuffix[0];
3994+ ber_dupbv( &e->e_name, &be->be_suffix[0] );
3995+ ber_dupbv( &e->e_nname, &be->be_nsuffix[0] );
3996
3997 dnRdn( &e->e_nname, &bv[0] );
3998 bv[1].bv_val = strchr(bv[0].bv_val, '=') + 1;
3999diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
4000index 4c4b925..59236c4 100644
4001--- a/servers/slapd/bconfig.c
4002+++ b/servers/slapd/bconfig.c
4003@@ -2247,7 +2247,7 @@ sortval_reject:
4004 for ( a=c->be->be_acl; a; a = a->acl_next )
4005 i++;
4006 }
4007- if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) {
4008+ if ( parse_acl( c, i ) ) {
4009 if ( SLAP_CONFIG( c->be ) && !c->be->be_acl) {
4010 c->be->be_acl = defacl_parsed;
4011 }
4012@@ -2533,7 +2533,7 @@ sortval_reject:
4013
4014 #ifdef LDAP_SLAPI
4015 case CFG_PLUGIN:
4016- if(slapi_int_read_config(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx) != LDAP_SUCCESS)
4017+ if(slapi_int_read_config(c) != LDAP_SUCCESS)
4018 return(1);
4019 slapi_plugins_used++;
4020 break;
4021@@ -4360,7 +4360,8 @@ config_tls_config(ConfigArgs *c) {
4022 #endif
4023
4024 static CfEntryInfo *
4025-config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
4026+config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last,
4027+ Operation *op )
4028 {
4029 struct berval cdn;
4030 char *c;
4031@@ -4377,7 +4378,14 @@ config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
4032 for (;*c != ',';c--);
4033
4034 while(root) {
4035- *last = root;
4036+ if ( !op || access_allowed( op, root->ce_entry,
4037+ slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) {
4038+ /*
4039+ * ITS#10139: Only record the lowermost entry that the user has
4040+ * disclose access to
4041+ */
4042+ *last = root;
4043+ }
4044 for (--c;c>dn->bv_val && *c != ',';c--);
4045 cdn.bv_val = c;
4046 if ( *c == ',' )
4047@@ -5495,7 +5503,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
4048 * Databases and Overlays to be inserted. Don't do any
4049 * auto-renumbering if manageDSAit control is present.
4050 */
4051- ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
4052+ ce = config_find_base( cfb->cb_root, &e->e_nname, &last, op );
4053 if ( ce ) {
4054 if ( ( op && op->o_managedsait ) ||
4055 ( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
4056@@ -5516,14 +5524,14 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
4057 /* If last is NULL, the new entry is the root/suffix entry,
4058 * otherwise last should be the parent.
4059 */
4060- if ( last && !dn_match( &last->ce_entry->e_nname, &pdn ) ) {
4061- if ( rs ) {
4062+ if ( cfb->cb_root && ( !last || !dn_match( &last->ce_entry->e_nname, &pdn ) ) ) {
4063+ if ( last && rs ) {
4064 rs->sr_matched = last->ce_entry->e_name.bv_val;
4065 }
4066 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
4067 "DN=\"%s\" not child of DN=\"%s\"\n",
4068 log_prefix, e->e_name.bv_val,
4069- last->ce_entry->e_name.bv_val );
4070+ last ? last->ce_entry->e_name.bv_val : "" );
4071 return LDAP_NO_SUCH_OBJECT;
4072 }
4073
4074@@ -6461,7 +6469,7 @@ config_back_modify( Operation *op, SlapReply *rs )
4075
4076 cfb = (CfBackInfo *)op->o_bd->be_private;
4077
4078- ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
4079+ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
4080 if ( !ce ) {
4081 if ( last )
4082 rs->sr_matched = last->ce_entry->e_name.bv_val;
4083@@ -6569,7 +6577,7 @@ config_back_modrdn( Operation *op, SlapReply *rs )
4084
4085 cfb = (CfBackInfo *)op->o_bd->be_private;
4086
4087- ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
4088+ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
4089 if ( !ce ) {
4090 if ( last )
4091 rs->sr_matched = last->ce_entry->e_name.bv_val;
4092@@ -6785,7 +6793,7 @@ config_back_delete( Operation *op, SlapReply *rs )
4093
4094 cfb = (CfBackInfo *)op->o_bd->be_private;
4095
4096- ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
4097+ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
4098 if ( !ce ) {
4099 if ( last )
4100 rs->sr_matched = last->ce_entry->e_name.bv_val;
4101@@ -6938,7 +6946,7 @@ config_back_search( Operation *op, SlapReply *rs )
4102 cfb = (CfBackInfo *)op->o_bd->be_private;
4103
4104 ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
4105- ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
4106+ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
4107 if ( !ce ) {
4108 if ( last )
4109 rs->sr_matched = last->ce_entry->e_name.bv_val;
4110@@ -7026,7 +7034,7 @@ int config_back_entry_get(
4111 if ( !paused ) {
4112 ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
4113 }
4114- ce = config_find_base( cfb->cb_root, ndn, &last );
4115+ ce = config_find_base( cfb->cb_root, ndn, &last, op );
4116 if ( ce ) {
4117 e = ce->ce_entry;
4118 if ( e ) {
4119@@ -7332,7 +7340,7 @@ config_check_schema(Operation *op, CfBackInfo *cfb)
4120 return 0;
4121
4122 /* Make sure the main schema entry exists */
4123- ce = config_find_base( cfb->cb_root, &schema_dn, &last );
4124+ ce = config_find_base( cfb->cb_root, &schema_dn, &last, op );
4125 if ( ce ) {
4126 Attribute *a;
4127 struct berval *bv;
4128@@ -7447,7 +7455,12 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
4129 */
4130 save_access = be->bd_self->be_acl;
4131 be->bd_self->be_acl = NULL;
4132- parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 );
4133+ c.be = be->bd_self;
4134+ c.fname = "config_back_db_open";
4135+ c.lineno = 0;
4136+ c.argc = 6;
4137+ c.argv = (char **)defacl;
4138+ parse_acl( &c, 0 );
4139 defacl_parsed = be->bd_self->be_acl;
4140 if ( save_access ) {
4141 be->bd_self->be_acl = save_access;
4142@@ -8029,7 +8042,7 @@ config_tool_entry_modify( BackendDB *be, Entry *e, struct berval *text )
4143 BackendInfo *bi = cfb->cb_db.bd_info;
4144 CfEntryInfo *ce, *last;
4145
4146- ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
4147+ ce = config_find_base( cfb->cb_root, &e->e_nname, &last, NULL );
4148
4149 if ( ce && bi && bi->bi_tool_entry_modify )
4150 return bi->bi_tool_entry_modify( &cfb->cb_db, e, text );
4151@@ -8044,7 +8057,7 @@ config_tool_entry_delete( BackendDB *be, struct berval *ndn, struct berval *text
4152 BackendInfo *bi = cfb->cb_db.bd_info;
4153 CfEntryInfo *ce, *last;
4154
4155- ce = config_find_base( cfb->cb_root, ndn, &last );
4156+ ce = config_find_base( cfb->cb_root, ndn, &last, NULL );
4157
4158 if ( ce && bi && bi->bi_tool_entry_delete )
4159 return bi->bi_tool_entry_delete( &cfb->cb_db, ndn, text );
4160diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c
4161index 940ca3d..beabe44 100644
4162--- a/servers/slapd/controls.c
4163+++ b/servers/slapd/controls.c
4164@@ -17,6 +17,7 @@
4165
4166 #include <stdio.h>
4167
4168+#include <ac/ctype.h>
4169 #include <ac/string.h>
4170 #include <ac/socket.h>
4171
4172diff --git a/servers/slapd/overlays/dynlist.c b/servers/slapd/overlays/dynlist.c
4173index 10cacf9..5c38b64 100644
4174--- a/servers/slapd/overlays/dynlist.c
4175+++ b/servers/slapd/overlays/dynlist.c
4176@@ -65,6 +65,7 @@ typedef struct dynlist_info_t {
4177 typedef struct dynlist_gen_t {
4178 dynlist_info_t *dlg_dli;
4179 int dlg_memberOf;
4180+ int dlg_simple;
4181 } dynlist_gen_t;
4182
4183 #define DYNLIST_USAGE \
4184@@ -556,9 +557,8 @@ dynlist_nested_member_dg( Operation *op, SlapReply *rs )
4185 }
4186
4187 static void
4188-dynlist_nested_member( Operation *op, dynlist_member_t *dm, TAvlnode *subs )
4189+dynlist_nested_member( Operation *op, slap_overinst *on, dynlist_member_t *dm, TAvlnode *subs )
4190 {
4191- slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
4192 TAvlnode *ptr;
4193 dynlist_name_t *dyn;
4194 Entry *ne;
4195@@ -596,12 +596,12 @@ dynlist_nested_member( Operation *op, dynlist_member_t *dm, TAvlnode *subs )
4196 dynlist_urlmembers( op, dyn, &cb );
4197 }
4198 if ( dyn->dy_subs )
4199- dynlist_nested_member( op, dm, dyn->dy_subs );
4200+ dynlist_nested_member( op, on, dm, dyn->dy_subs );
4201 }
4202 }
4203
4204 static int
4205-dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli, dynlist_name_t *dyn )
4206+dynlist_prepare_entry( Operation *op, SlapReply *rs, slap_overinst *on, dynlist_info_t *dli, dynlist_name_t *dyn )
4207 {
4208 Attribute *a, *id = NULL;
4209 slap_callback cb = { 0 };
4210@@ -875,7 +875,7 @@ checkdyn:
4211 /* ensure e is modifiable */
4212 if ( e == rs->sr_entry && !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
4213 e = entry_dup( rs->sr_entry );
4214- rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
4215+ rs_replace_entry( op, rs, on, e );
4216 rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
4217 }
4218 if ( dyn->dy_subs ) {
4219@@ -888,7 +888,7 @@ checkdyn:
4220 dm.dm_mod.sm_type = dlm->dlm_member_ad->ad_cname;
4221 dm.dm_e = e;
4222 dm.dm_ad = dlm->dlm_member_ad;
4223- dynlist_nested_member( op, &dm, dyn->dy_subs );
4224+ dynlist_nested_member( op, on, &dm, dyn->dy_subs );
4225 if ( dm.dm_groups )
4226 ldap_tavl_free( dm.dm_groups, NULL );
4227 }
4228@@ -904,7 +904,7 @@ checkdyn:
4229 }
4230
4231 if ( e != rs->sr_entry ) {
4232- rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
4233+ rs_replace_entry( op, rs, on, e );
4234 rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
4235 }
4236
4237@@ -1098,7 +1098,7 @@ done:;
4238 r.sr_attrs = an;
4239
4240 o.o_acl_priv = ACL_COMPARE;
4241- dynlist_prepare_entry( &o, &r, dli, NULL );
4242+ dynlist_prepare_entry( &o, &r, on, dli, NULL );
4243 a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc );
4244
4245 ret = LDAP_NO_SUCH_ATTRIBUTE;
4246@@ -1131,6 +1131,7 @@ release:;
4247 #define WANT_MEMBER 2
4248
4249 typedef struct dynlist_search_t {
4250+ slap_overinst *ds_on;
4251 TAvlnode *ds_names;
4252 TAvlnode *ds_fnodes;
4253 dynlist_info_t *ds_dli;
4254@@ -1555,11 +1556,11 @@ dynlist_test_dynmember(Operation *op, dynlist_name_t *dyn, Entry *e)
4255 }
4256
4257 static int
4258-dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
4259+dynlist_test_membership(Operation *op, slap_overinst *on, dynlist_name_t *dyn, Entry *e)
4260 {
4261 if ( dyn->dy_staticmember ) {
4262 Entry *grp;
4263- if ( overlay_entry_get_ov( op, &dyn->dy_nname, NULL, NULL, 0, &grp, (slap_overinst *)op->o_bd->bd_info ) == LDAP_SUCCESS && grp ) {
4264+ if ( overlay_entry_get_ov( op, &dyn->dy_nname, NULL, NULL, 0, &grp, on ) == LDAP_SUCCESS && grp ) {
4265 Attribute *a = attr_find( grp->e_attrs, dyn->dy_staticmember );
4266 int rc;
4267 if ( a ) {
4268@@ -1569,7 +1570,7 @@ dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
4269 } else {
4270 rc = LDAP_COMPARE_FALSE;
4271 }
4272- overlay_entry_release_ov( op, grp, 0, (slap_overinst *)op->o_bd->bd_info );
4273+ overlay_entry_release_ov( op, grp, 0, on );
4274 return rc;
4275 }
4276 }
4277@@ -1591,7 +1592,7 @@ dynlist_add_memberOf(Operation *op, SlapReply *rs, dynlist_search_t *ds)
4278 dyn = ptr->avl_data;
4279 for ( dlm = dyn->dy_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
4280 if ( dlm->dlm_memberOf_ad ) {
4281- if ( dynlist_test_membership( op, dyn, e ) == LDAP_COMPARE_TRUE ) {
4282+ if ( dynlist_test_membership( op, ds->ds_on, dyn, e ) == LDAP_COMPARE_TRUE ) {
4283 /* ensure e is modifiable, but do not replace
4284 * sr_entry yet since we have pointers into it */
4285 if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) && e == rs->sr_entry ) {
4286@@ -1655,7 +1656,7 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
4287 dyn = ldap_tavl_find( ds->ds_names, &rs->sr_entry->e_nname, dynlist_avl_cmp );
4288 if ( dyn ) {
4289 dyn->dy_seen = 1;
4290- rc = dynlist_prepare_entry( op, rs, dyn->dy_dli, dyn );
4291+ rc = dynlist_prepare_entry( op, rs, ds->ds_on, dyn->dy_dli, dyn );
4292 } else if ( ds->ds_want )
4293 dynlist_add_memberOf( op, rs, ds );
4294 }
4295@@ -1667,7 +1668,7 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
4296 for ( dli = ds->ds_dli; dli; dli = dli->dli_next ) {
4297 if ( is_entry_objectclass_or_sub( rs->sr_entry, dli->dli_oc ) &&
4298 dynlist_check_scope( op, rs->sr_entry, dli ))
4299- rc = dynlist_prepare_entry( op, rs, dli, NULL );
4300+ rc = dynlist_prepare_entry( op, rs, ds->ds_on, dli, NULL );
4301 }
4302 }
4303 }
4304@@ -1677,7 +1678,7 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
4305 }
4306 return rc;
4307 } else if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS ) {
4308- slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
4309+ slap_overinst *on = ds->ds_on;
4310 TAvlnode *ptr, *skip = NULL;
4311 SlapReply r = *rs;
4312 dynlist_map_t *dlm = NULL;
4313@@ -1729,7 +1730,7 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
4314 r.sr_entry == NULL )
4315 goto next;
4316 r.sr_flags = REP_ENTRY_MUSTRELEASE;
4317- dynlist_prepare_entry( op, &r, dyn->dy_dli, dyn );
4318+ dynlist_prepare_entry( op, &r, on, dyn->dy_dli, dyn );
4319 if ( test_filter( op, r.sr_entry, f ) == LDAP_COMPARE_TRUE ) {
4320 r.sr_attrs = op->ors_attrs;
4321 rs->sr_err = send_search_entry( op, &r );
4322@@ -1895,6 +1896,8 @@ dynlist_search( Operation *op, SlapReply *rs )
4323 userattrs = SLAP_USERATTRS( attrflags );
4324 }
4325
4326+ if (dlg->dlg_simple)
4327+ goto simple;
4328 /* Find all groups in scope. For group expansion
4329 * we only need the groups within the search scope, but
4330 * for memberOf populating, we need all dyngroups.
4331@@ -2063,12 +2066,14 @@ dynlist_search( Operation *op, SlapReply *rs )
4332 dynlist_nestlink( op, ds );
4333 }
4334 }
4335+simple:
4336
4337 if ( dlg->dlg_dli || ds->ds_names != NULL ) {
4338 sc->sc_response = dynlist_search2resp;
4339 sc->sc_cleanup = dynlist_search_cleanup;
4340 sc->sc_next = op->o_callback;
4341 op->o_callback = sc;
4342+ ds->ds_on = on;
4343
4344 /* dynamic lists need this */
4345 ds->ds_dli = dlg->dlg_dli;
4346@@ -2145,6 +2150,13 @@ static ConfigTable dlcfg[] = {
4347 3, 3, 0, ARG_MAGIC|DL_ATTRPAIR_COMPAT, dl_cfgen,
4348 NULL, NULL, NULL },
4349 #endif
4350+ { "dynlist-simple", NULL, 0, 0, 0, ARG_OFFSET|ARG_ON_OFF,
4351+ (void *)offsetof(dynlist_gen_t, dlg_simple),
4352+ "( OLcfgOvAt:8.2 NAME 'olcDynListSimple' "
4353+ "DESC 'Simple mode - disable features added since 2.4.' "
4354+ "EQUALITY booleanMatch "
4355+ "SYNTAX OMsBoolean SINGLE-VALUE )",
4356+ NULL, NULL },
4357 { NULL, NULL, 0, 0, 0, ARG_IGNORED }
4358 };
4359
4360@@ -2153,7 +2165,7 @@ static ConfigOCs dlocs[] = {
4361 "NAME ( 'olcDynListConfig' 'olcDynamicList' ) "
4362 "DESC 'Dynamic list configuration' "
4363 "SUP olcOverlayConfig "
4364- "MAY olcDynListAttrSet )",
4365+ "MAY ( olcDynListAttrSet $ olcDynListSimple ) )",
4366 Cft_Overlay, dlcfg, NULL, NULL },
4367 { NULL, 0, NULL }
4368 };
4369@@ -2740,10 +2752,13 @@ dynlist_db_init(
4370 slap_overinst *on = (slap_overinst *)be->bd_info;
4371 dynlist_gen_t *dlg;
4372
4373- dlg = (dynlist_gen_t *)ch_malloc( sizeof( *dlg ));
4374+ if ( SLAP_ISGLOBALOVERLAY( be ) ) {
4375+ Debug( LDAP_DEBUG_ANY, "dynlist cannot be used as global overlay.\n" );
4376+ return 1;
4377+ }
4378+
4379+ dlg = (dynlist_gen_t *)ch_calloc( 1, sizeof( *dlg ));
4380 on->on_bi.bi_private = dlg;
4381- dlg->dlg_dli = NULL;
4382- dlg->dlg_memberOf = 0;
4383
4384 return 0;
4385 }
4386diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
4387index 106a371..c1364a9 100644
4388--- a/servers/slapd/proto-slap.h
4389+++ b/servers/slapd/proto-slap.h
4390@@ -100,9 +100,7 @@ LDAP_SLAPD_F (int) acl_string_expand LDAP_P((
4391 */
4392 LDAP_SLAPD_V (LDAP_CONST char *) style_strings[];
4393
4394-LDAP_SLAPD_F (int) parse_acl LDAP_P(( Backend *be,
4395- const char *fname, int lineno,
4396- int argc, char **argv, int pos ));
4397+LDAP_SLAPD_F (int) parse_acl LDAP_P(( struct config_args_s *ca, int pos ));
4398
4399 LDAP_SLAPD_F (char *) access2str LDAP_P(( slap_access_t access ));
4400 LDAP_SLAPD_F (slap_access_t) str2access LDAP_P(( const char *str ));
4401diff --git a/servers/slapd/slap-config.h b/servers/slapd/slap-config.h
4402index 3252fd7..5682204 100644
4403--- a/servers/slapd/slap-config.h
4404+++ b/servers/slapd/slap-config.h
4405@@ -196,31 +196,31 @@ typedef struct config_args_s {
4406 #define value_ndn values.v_dn.vdn_ndn
4407 #define value_ad values.v_ad
4408
4409-int config_fp_parse_line(ConfigArgs *c);
4410-
4411-int config_register_schema(ConfigTable *ct, ConfigOCs *co);
4412-int config_del_vals(ConfigTable *cf, ConfigArgs *c);
4413-int config_get_vals(ConfigTable *ct, ConfigArgs *c);
4414-int config_add_vals(ConfigTable *ct, ConfigArgs *c);
4415-
4416-int config_push_cleanup(ConfigArgs *c, ConfigDriver *cleanup);
4417-int config_run_cleanup(ConfigArgs *c);
4418-
4419-void init_config_argv( ConfigArgs *c );
4420-int init_config_attrs(ConfigTable *ct);
4421-int init_config_ocs( ConfigOCs *ocs );
4422-void config_parse_ldif( ConfigArgs *c );
4423-int config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx);
4424-int config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx);
4425-int read_config_file(const char *fname, int depth, ConfigArgs *cf,
4426+LDAP_SLAPD_F (int) config_fp_parse_line(ConfigArgs *c);
4427+
4428+LDAP_SLAPD_F (int) config_register_schema(ConfigTable *ct, ConfigOCs *co);
4429+LDAP_SLAPD_F (int) config_del_vals(ConfigTable *cf, ConfigArgs *c);
4430+LDAP_SLAPD_F (int) config_get_vals(ConfigTable *ct, ConfigArgs *c);
4431+LDAP_SLAPD_F (int) config_add_vals(ConfigTable *ct, ConfigArgs *c);
4432+
4433+LDAP_SLAPD_F (int) config_push_cleanup(ConfigArgs *c, ConfigDriver *cleanup);
4434+LDAP_SLAPD_F (int) config_run_cleanup(ConfigArgs *c);
4435+
4436+LDAP_SLAPD_F (void) init_config_argv( ConfigArgs *c );
4437+LDAP_SLAPD_F (int) init_config_attrs(ConfigTable *ct);
4438+LDAP_SLAPD_F (int) init_config_ocs( ConfigOCs *ocs );
4439+LDAP_SLAPD_F (void) config_parse_ldif( ConfigArgs *c );
4440+LDAP_SLAPD_F (int) config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx);
4441+LDAP_SLAPD_F (int) config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx);
4442+LDAP_SLAPD_F (int) read_config_file(const char *fname, int depth, ConfigArgs *cf,
4443 ConfigTable *cft );
4444
4445-ConfigTable * config_find_keyword(ConfigTable *ct, ConfigArgs *c);
4446-Entry * config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
4447+LDAP_SLAPD_F (ConfigTable *) config_find_keyword(ConfigTable *ct, ConfigArgs *c);
4448+LDAP_SLAPD_F (Entry *) config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
4449 ConfigArgs *c, struct berval *rdn, ConfigOCs *main, ConfigOCs *extra );
4450
4451-Listener *config_check_my_url(const char *url, LDAPURLDesc *lud);
4452-int config_shadow( ConfigArgs *c, slap_mask_t flag );
4453+LDAP_SLAPD_F (Listener *) config_check_my_url(const char *url, LDAPURLDesc *lud);
4454+LDAP_SLAPD_F (int) config_shadow( ConfigArgs *c, slap_mask_t flag );
4455 #define config_slurp_shadow(c) config_shadow((c), SLAP_DBFLAG_SLURP_SHADOW)
4456 #define config_sync_shadow(c) config_shadow((c), SLAP_DBFLAG_SYNC_SHADOW)
4457
4458@@ -231,7 +231,7 @@ int config_shadow( ConfigArgs *c, slap_mask_t flag );
4459 #define SLAP_X_ORDERED_FMT "{%d}"
4460
4461 LDAP_SLAPD_V (slap_verbmasks *) slap_ldap_response_code;
4462-extern int slap_ldap_response_code_register( struct berval *bv, int err );
4463+LDAP_SLAPD_F (int) slap_ldap_response_code_register( struct berval *bv, int err );
4464
4465 LDAP_SLAPD_V (ConfigTable) olcDatabaseDummy[];
4466
4467diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
4468index 5cf2f46..605a80f 100644
4469--- a/servers/slapd/slap.h
4470+++ b/servers/slapd/slap.h
4471@@ -1319,12 +1319,15 @@ typedef struct AuthorizationInformation {
4472 slap_ssf_t sai_sasl_ssf; /* SASL SSF */
4473 } AuthorizationInformation;
4474
4475+typedef struct config_args_s ConfigArgs; /* slap-config.h */
4476+typedef struct config_reply_s ConfigReply; /* slap-config.h */
4477+
4478 #ifdef SLAP_DYNACL
4479
4480 /*
4481 * "dynamic" ACL infrastructure (for ACIs and more)
4482 */
4483-typedef int (slap_dynacl_parse) LDAP_P(( const char *fname, int lineno,
4484+typedef int (slap_dynacl_parse) LDAP_P(( ConfigArgs *ca,
4485 const char *opts, slap_style_t, const char *, void **privp ));
4486 typedef int (slap_dynacl_unparse) LDAP_P(( void *priv, struct berval *bv ));
4487 typedef int (slap_dynacl_mask) LDAP_P((
4488@@ -2019,7 +2022,6 @@ typedef int (BI_config) LDAP_P((BackendInfo *bi,
4489 const char *fname, int lineno,
4490 int argc, char **argv));
4491
4492-typedef struct config_reply_s ConfigReply; /* slap-config.h */
4493 typedef int (BI_db_func) LDAP_P((Backend *bd, ConfigReply *cr));
4494 typedef BI_db_func BI_db_init;
4495 typedef BI_db_func BI_db_open;
4496diff --git a/servers/slapd/slapi/Makefile.in b/servers/slapd/slapi/Makefile.in
4497index 0e46f78..32ade0c 100644
4498--- a/servers/slapd/slapi/Makefile.in
4499+++ b/servers/slapd/slapi/Makefile.in
4500@@ -19,9 +19,6 @@ LIBRARY = libslapi.la
4501 #all-common: $(LIBRARY) $(PROGRAMS)
4502 # @touch plugin.c slapi_pblock.c slapi_utils.c slapi_ops.c slapi_ext.c
4503
4504-NT_SRCS = nt_err.c
4505-NT_OBJS = nt_err.lo
4506-
4507 LIB_DEFS = -DSLAPI_LIBRARY
4508
4509 SRCS= plugin.c slapi_pblock.c slapi_utils.c printmsg.c slapi_ops.c slapi_dn.c slapi_ext.c slapi_overlay.c \
4510@@ -31,12 +28,15 @@ OBJS= plugin.lo slapi_pblock.lo slapi_utils.lo printmsg.lo slapi_ops.lo slapi_d
4511
4512 XSRCS= version.c
4513
4514-LDAP_INCDIR= ../../../include -I.. -I.
4515-LDAP_LIBDIR= ../../../libraries
4516+LDAP_INCDIR= ../../../include -I.. -I.
4517+LDAP_LIBDIR= ../../../libraries
4518+
4519+shared_LDAP_LIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLBER_LA)
4520
4521 XLIBS = $(LIBRARY)
4522 XXLIBS =
4523-NT_LINK_LIBS = $(AC_LIBS)
4524+MOD_LIBS = $(MODULES_LIBS)
4525+NT_LINK_LIBS = $(AC_LIBS) -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
4526
4527 XINCPATH = -I$(srcdir)/.. -I$(srcdir)
4528 XDEFS = $(MODULES_CPPFLAGS)
4529diff --git a/servers/slapd/slapi/plugin.c b/servers/slapd/slapi/plugin.c
4530index de8c60d..ca5dbea 100644
4531--- a/servers/slapd/slapi/plugin.c
4532+++ b/servers/slapd/slapi/plugin.c
4533@@ -36,7 +36,7 @@
4534 #include <ltdl.h>
4535
4536 static int slapi_int_load_plugin( Slapi_PBlock *, const char *, const char *, int,
4537- SLAPI_FUNC *, lt_dlhandle * );
4538+ SLAPI_FUNC *, lt_dlhandle *, ConfigArgs *c );
4539
4540 /* pointer to link list of extended objects */
4541 static ExtendedOp *pGExtendedOps = NULL;
4542@@ -68,15 +68,15 @@ static Slapi_PBlock *
4543 plugin_pblock_new(
4544 int type,
4545 int argc,
4546- char *argv[] )
4547+ ConfigArgs *c )
4548 {
4549 Slapi_PBlock *pPlugin = NULL;
4550 Slapi_PluginDesc *pPluginDesc = NULL;
4551 lt_dlhandle hdLoadHandle;
4552 int rc;
4553 char **av2 = NULL, **ppPluginArgv;
4554- char *path = argv[2];
4555- char *initfunc = argv[3];
4556+ char *path = c->argv[2];
4557+ char *initfunc = c->argv[3];
4558
4559 pPlugin = slapi_pblock_new();
4560 if ( pPlugin == NULL ) {
4561@@ -87,7 +87,7 @@ plugin_pblock_new(
4562 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
4563 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)&argc );
4564
4565- av2 = ldap_charray_dup( argv );
4566+ av2 = ldap_charray_dup( c->argv );
4567 if ( av2 == NULL ) {
4568 rc = LDAP_NO_MEMORY;
4569 goto done;
4570@@ -102,7 +102,7 @@ plugin_pblock_new(
4571 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
4572 slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
4573
4574- rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle );
4575+ rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle, c );
4576 if ( rc != 0 ) {
4577 goto done;
4578 }
4579@@ -556,7 +556,8 @@ slapi_int_load_plugin(
4580 const char *initfunc,
4581 int doInit,
4582 SLAPI_FUNC *pInitFunc,
4583- lt_dlhandle *pLdHandle )
4584+ lt_dlhandle *pLdHandle,
4585+ ConfigArgs *c )
4586 {
4587 int rc = LDAP_SUCCESS;
4588 SLAPI_FUNC fpInitFunc = NULL;
4589@@ -570,15 +571,17 @@ slapi_int_load_plugin(
4590 /* load in the module */
4591 *pLdHandle = lt_dlopen( path );
4592 if ( *pLdHandle == NULL ) {
4593- fprintf( stderr, "failed to load plugin %s: %s\n",
4594+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "failed to load plugin %s: %s",
4595 path, lt_dlerror() );
4596+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
4597 return LDAP_LOCAL_ERROR;
4598 }
4599
4600 fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
4601 if ( fpInitFunc == NULL ) {
4602- fprintf( stderr, "failed to find symbol %s in plugin %s: %s\n",
4603+ snprintf( c->cr_msg, sizeof( c->cr_msg ), "failed to find symbol %s in plugin %s: %s",
4604 initfunc, path, lt_dlerror() );
4605+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
4606 lt_dlclose( *pLdHandle );
4607 return LDAP_LOCAL_ERROR;
4608 }
4609@@ -643,50 +646,46 @@ slapi_int_call_plugins(
4610
4611 int
4612 slapi_int_read_config(
4613- Backend *be,
4614- const char *fname,
4615- int lineno,
4616- int argc,
4617- char **argv,
4618- int index )
4619+ struct config_args_s *c )
4620 {
4621 int iType = -1;
4622 int numPluginArgc = 0;
4623
4624- if ( argc < 4 ) {
4625- fprintf( stderr,
4626- "%s: line %d: missing arguments "
4627+ if ( c->argc < 4 ) {
4628+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
4629+ "missing arguments "
4630 "in \"plugin <plugin_type> <lib_path> "
4631- "<init_function> [<arguments>]\" line\n",
4632- fname, lineno );
4633+ "<init_function> [<arguments>]\" line" );
4634+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
4635 return 1;
4636 }
4637
4638 /* automatically instantiate overlay if necessary */
4639- if ( !slapi_over_is_inst( be ) ) {
4640- ConfigReply cr = { 0 };
4641- if ( slapi_over_config( be, &cr ) != 0 ) {
4642- fprintf( stderr, "Failed to instantiate SLAPI overlay: "
4643- "err=%d msg=\"%s\"\n", cr.err, cr.msg );
4644+ if ( !slapi_over_is_inst( c->be ) ) {
4645+ if ( slapi_over_config( c->be, &c->reply ) != 0 ) {
4646+ Debug( LDAP_DEBUG_ANY, "%s: "
4647+ "Failed to instantiate SLAPI overlay: "
4648+ "err=%d msg=\"%s\"\n", c->log, c->reply.err, c->reply.msg );
4649 return -1;
4650 }
4651 }
4652
4653- if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
4654+ if ( strcasecmp( c->argv[1], "preoperation" ) == 0 ) {
4655 iType = SLAPI_PLUGIN_PREOPERATION;
4656- } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
4657+ } else if ( strcasecmp( c->argv[1], "postoperation" ) == 0 ) {
4658 iType = SLAPI_PLUGIN_POSTOPERATION;
4659- } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
4660+ } else if ( strcasecmp( c->argv[1], "extendedop" ) == 0 ) {
4661 iType = SLAPI_PLUGIN_EXTENDEDOP;
4662- } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
4663+ } else if ( strcasecmp( c->argv[1], "object" ) == 0 ) {
4664 iType = SLAPI_PLUGIN_OBJECT;
4665 } else {
4666- fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
4667- fname, lineno, argv[1] );
4668+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
4669+ "invalid plugin type \"%s\"", c->argv[1] );
4670+ Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
4671 return 1;
4672 }
4673
4674- numPluginArgc = argc - 4;
4675+ numPluginArgc = c->argc - 4;
4676
4677 if ( iType == SLAPI_PLUGIN_PREOPERATION ||
4678 iType == SLAPI_PLUGIN_EXTENDEDOP ||
4679@@ -695,23 +694,23 @@ slapi_int_read_config(
4680 int rc;
4681 Slapi_PBlock *pPlugin;
4682
4683- pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
4684+ pPlugin = plugin_pblock_new( iType, numPluginArgc, c->argv );
4685 if (pPlugin == NULL) {
4686 return 1;
4687 }
4688
4689 if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
4690- rc = slapi_int_register_extop(be, &pGExtendedOps, pPlugin);
4691+ rc = slapi_int_register_extop(c->be, &pGExtendedOps, pPlugin);
4692 if ( rc != LDAP_SUCCESS ) {
4693 slapi_pblock_destroy( pPlugin );
4694 return 1;
4695 }
4696 }
4697
4698- rc = slapi_int_register_plugin_index( be, pPlugin, index );
4699+ rc = slapi_int_register_plugin_index( c->be, pPlugin, c->valx );
4700 if ( rc != LDAP_SUCCESS ) {
4701 if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
4702- slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
4703+ slapi_int_unregister_extop( c->be, &pGExtendedOps, pPlugin );
4704 }
4705 slapi_pblock_destroy( pPlugin );
4706 return 1;
4707diff --git a/servers/slapd/slapi/printmsg.c b/servers/slapd/slapi/printmsg.c
4708index 15b6004..5251846 100644
4709--- a/servers/slapd/slapi/printmsg.c
4710+++ b/servers/slapd/slapi/printmsg.c
4711@@ -32,6 +32,10 @@
4712 #include <slap.h>
4713 #include <slapi.h>
4714
4715+#ifdef _WIN32
4716+#include <io.h>
4717+#endif
4718+
4719 #include <ldap_pvt_thread.h>
4720
4721 /* Single threads access to routine */
4722@@ -60,18 +64,30 @@ slapi_int_log_error(
4723
4724 /* for now, we log all severities */
4725 if ( level <= slapi_log_level ) {
4726+#ifdef _WIN32
4727+ intptr_t fhandle;
4728+#endif
4729 fp = fopen( slapi_log_file, "a" );
4730 if ( fp == NULL) {
4731 rc = -1;
4732 goto done;
4733 }
4734
4735+#ifdef _WIN32
4736+ fhandle = _get_osfhandle( fileno( fp ));
4737+#endif
4738 /*
4739 * FIXME: could block
4740 */
4741+#ifdef _WIN32
4742+ while ( LockFile( fhandle, 0, 0, UINT_MAX, UINT_MAX ) == 0 ) {
4743+ /* DO NOTHING */ ;
4744+ }
4745+#else
4746 while ( lockf( fileno( fp ), F_LOCK, 0 ) != 0 ) {
4747 /* DO NOTHING */ ;
4748 }
4749+#endif
4750
4751 time( &currentTime );
4752 ltm = localtime( &currentTime );
4753@@ -85,7 +101,11 @@ slapi_int_log_error(
4754 }
4755 fflush( fp );
4756
4757+#ifdef _WIN32
4758+ UnlockFile( fhandle, 0, 0, UINT_MAX, UINT_MAX );
4759+#else
4760 lockf( fileno( fp ), F_ULOCK, 0 );
4761+#endif
4762
4763 fclose( fp );
4764
4765diff --git a/servers/slapd/slapi/proto-slapi.h b/servers/slapd/slapi/proto-slapi.h
4766index 9d52510..e9eb76b 100644
4767--- a/servers/slapd/slapi/proto-slapi.h
4768+++ b/servers/slapd/slapi/proto-slapi.h
4769@@ -72,8 +72,7 @@ LDAP_SLAPI_F (int) slapi_int_register_extop LDAP_P((Backend *pBE, ExtendedOp **o
4770 LDAP_SLAPI_F (int) slapi_int_get_extop_plugin LDAP_P((struct berval *reqoid, SLAPI_FUNC *pFuncAddr ));
4771 LDAP_SLAPI_F (struct berval *) slapi_int_get_supported_extop LDAP_P(( int ));
4772 LDAP_SLAPI_F (int) slapi_int_unregister_plugins LDAP_P((Backend *be, int index));
4773-LDAP_SLAPI_F (int) slapi_int_read_config LDAP_P((Backend *be, const char *fname, int lineno,
4774- int argc, char **argv, int index ));
4775+LDAP_SLAPI_F (int) slapi_int_read_config LDAP_P(( struct config_args_s *c ));
4776 LDAP_SLAPI_F (void) slapi_int_plugin_unparse LDAP_P((Backend *be, BerVarray *out ));
4777 LDAP_SLAPI_F (int) slapi_int_initialize LDAP_P((void));
4778
4779diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c
4780index 6c1cecf..c459122 100644
4781--- a/servers/slapd/slapi/slapi_utils.c
4782+++ b/servers/slapd/slapi/slapi_utils.c
4783@@ -31,7 +31,11 @@
4784 #include <slap.h>
4785 #include <slapi.h>
4786
4787+#ifdef _WIN32
4788+#include <winsock.h>
4789+#else
4790 #include <netdb.h>
4791+#endif
4792
4793 #ifdef LDAP_SLAPI
4794
4795@@ -1971,6 +1975,8 @@ slapi_timer_current_time( void )
4796 */
4797 #else /* _WIN32 */
4798 LARGE_INTEGER now;
4799+ static LARGE_INTEGER base_time, performance_freq;
4800+ static int performance_counter_present;
4801
4802 if ( first_time ) {
4803 first_time = 0;
4804diff --git a/servers/slapd/slappasswd.c b/servers/slapd/slappasswd.c
4805index 9c2adef..e384364 100644
4806--- a/servers/slapd/slappasswd.c
4807+++ b/servers/slapd/slappasswd.c
4808@@ -250,11 +250,16 @@ slappasswd( int argc, char *argv[] )
4809 if( newpw == NULL ) {
4810 /* prompt for new password */
4811 char *cknewpw;
4812- newpw = ch_strdup(getpassphrase("New password: "));
4813+ newpw = getpassphrase("New password: ");
4814+ if ( newpw == NULL ) { /* Allow EOF to exit. */
4815+ rc = EXIT_FAILURE;
4816+ goto destroy;
4817+ }
4818+ newpw = ch_strdup(newpw);
4819 cknewpw = getpassphrase("Re-enter new password: ");
4820-
4821- if( strcmp( newpw, cknewpw )) {
4822- fprintf( stderr, "Password values do not match\n" );
4823+ if( cknewpw == NULL || strcmp( newpw, cknewpw )) {
4824+ fprintf( stderr,
4825+ "Password values do not match\n" );
4826 rc = EXIT_FAILURE;
4827 goto destroy;
4828 }
4829diff --git a/tests/progs/slapd-tester.c b/tests/progs/slapd-tester.c
4830index 7ad88b8..8f9656e 100644
4831--- a/tests/progs/slapd-tester.c
4832+++ b/tests/progs/slapd-tester.c
4833@@ -406,6 +406,9 @@ main( int argc, char **argv )
4834
4835 if ( pw_ask ) {
4836 passwd = getpassphrase( _("Enter LDAP Password: ") );
4837+ if ( passwd == NULL ) { /* Allow EOF to exit. */
4838+ exit( EXIT_FAILURE );
4839+ }
4840
4841 } else if ( pw_file ) {
4842 struct berval pw;

Subscribers

People subscribed via source and target branches