Gentoo Archives: gentoo-commits

From: Patrice Clement <monsieurp@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: net-nds/389-ds-base/, net-nds/389-ds-base/files/
Date: Mon, 05 Feb 2018 21:50:19
Message-Id: 1517867403.e71df7341cdaa0a4cc2aeff56496ce1724b921d2.monsieurp@gentoo
1 commit: e71df7341cdaa0a4cc2aeff56496ce1724b921d2
2 Author: Wes Cilldhaire <wes <AT> sol1 <DOT> com <DOT> au>
3 AuthorDate: Mon Feb 5 01:07:25 2018 +0000
4 Commit: Patrice Clement <monsieurp <AT> gentoo <DOT> org>
5 CommitDate: Mon Feb 5 21:50:03 2018 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=e71df734
7
8 net-nds/389-ds-base: patch against CVE-2017-15135 in 1.3.6.8.
9
10 * Patch and revbump to 1.3.6.8 to address CVE-2017-15135
11 * Update copyright line in all versions for 2018
12
13 Bug: https://bugs.gentoo.org/645706
14
15 Acked-by: wibrown <AT> redhat.com
16 Package-Manager: Portage-2.3.20, Repoman-2.3.6
17 Closes: https://github.com/gentoo/gentoo/pull/7078
18
19 net-nds/389-ds-base/389-ds-base-1.3.5.19.ebuild | 2 +-
20 ....3.6.8.ebuild => 389-ds-base-1.3.6.8-r1.ebuild} | 4 +-
21 net-nds/389-ds-base/389-ds-base-9999.ebuild | 2 +-
22 ...-base-1.3.6-backport-invalid-password-mig.patch | 376 +++++++++++++++++++++
23 4 files changed, 381 insertions(+), 3 deletions(-)
24
25 diff --git a/net-nds/389-ds-base/389-ds-base-1.3.5.19.ebuild b/net-nds/389-ds-base/389-ds-base-1.3.5.19.ebuild
26 index 6fddd0315a5..e36a909ca91 100644
27 --- a/net-nds/389-ds-base/389-ds-base-1.3.5.19.ebuild
28 +++ b/net-nds/389-ds-base/389-ds-base-1.3.5.19.ebuild
29 @@ -1,4 +1,4 @@
30 -# Copyright 1999-2017 Gentoo Foundation
31 +# Copyright 1999-2018 Gentoo Foundation
32 # Distributed under the terms of the GNU General Public License v2
33
34 EAPI=5
35
36 diff --git a/net-nds/389-ds-base/389-ds-base-1.3.6.8.ebuild b/net-nds/389-ds-base/389-ds-base-1.3.6.8-r1.ebuild
37 similarity index 96%
38 rename from net-nds/389-ds-base/389-ds-base-1.3.6.8.ebuild
39 rename to net-nds/389-ds-base/389-ds-base-1.3.6.8-r1.ebuild
40 index 6fddd0315a5..0232cdec1d4 100644
41 --- a/net-nds/389-ds-base/389-ds-base-1.3.6.8.ebuild
42 +++ b/net-nds/389-ds-base/389-ds-base-1.3.6.8-r1.ebuild
43 @@ -1,4 +1,4 @@
44 -# Copyright 1999-2017 Gentoo Foundation
45 +# Copyright 1999-2018 Gentoo Foundation
46 # Distributed under the terms of the GNU General Public License v2
47
48 EAPI=5
49 @@ -53,6 +53,8 @@ src_prepare() {
50 # as per 389 documentation, when 64bit, export USE_64
51 use amd64 && export USE_64=1
52
53 + epatch "${FILESDIR}/389-ds-base-1.3.6-backport-invalid-password-mig.patch"
54 +
55 eautoreconf
56
57 append-lfs-flags
58
59 diff --git a/net-nds/389-ds-base/389-ds-base-9999.ebuild b/net-nds/389-ds-base/389-ds-base-9999.ebuild
60 index 463fd580d5d..046375125af 100644
61 --- a/net-nds/389-ds-base/389-ds-base-9999.ebuild
62 +++ b/net-nds/389-ds-base/389-ds-base-9999.ebuild
63 @@ -1,4 +1,4 @@
64 -# Copyright 1999-2017 Gentoo Foundation
65 +# Copyright 1999-2018 Gentoo Foundation
66 # Distributed under the terms of the GNU General Public License v2
67
68 EAPI=5
69
70 diff --git a/net-nds/389-ds-base/files/389-ds-base-1.3.6-backport-invalid-password-mig.patch b/net-nds/389-ds-base/files/389-ds-base-1.3.6-backport-invalid-password-mig.patch
71 new file mode 100644
72 index 00000000000..b4ba70a2fb5
73 --- /dev/null
74 +++ b/net-nds/389-ds-base/files/389-ds-base-1.3.6-backport-invalid-password-mig.patch
75 @@ -0,0 +1,376 @@
76 +From cefec5714cf0fdec4aa582a5fe020ef80d6024cd Mon Sep 17 00:00:00 2001
77 +From: William Brown <firstyear@××××××.com>
78 +Date: Thu, 18 Jan 2018 11:27:58 +1000
79 +Subject: [PATCH] Ticket bz1525628 1.3.6 backport - invalid password migration
80 + causes unauth bind
81 +
82 +Bug Description: Slapi_ct_memcmp expects both inputs to be
83 +at LEAST size n. If they are not, we only compared UP to n.
84 +
85 +Invalid migrations of passwords (IE {CRYPT}XX) would create
86 +a pw which is just salt and no hash. ct_memcmp would then
87 +only verify the salt bits and would allow the authentication.
88 +
89 +This relies on an administrative mistake both of allowing
90 +password migration (nsslapd-allow-hashed-passwords) and then
91 +subsequently migrating an INVALID password to the server.
92 +
93 +Fix Description: slapi_ct_memcmp now access n1, n2 size
94 +and will FAIL if they are not the same, but will still compare
95 +n bytes, where n is the "longest" memory, to the first byte
96 +of the other to prevent length disclosure of the shorter
97 +value (generally the mis-migrated password)
98 +
99 +https://bugzilla.redhat.com/show_bug.cgi?id=1525628
100 +
101 +Author: wibrown
102 +
103 +Review by: ???
104 +---
105 + .../bz1525628_ct_memcmp_invalid_hash_test.py | 56 ++++++++++++++++++++
106 + ldap/servers/plugins/pwdstorage/clear_pwd.c | 4 +-
107 + ldap/servers/plugins/pwdstorage/crypt_pwd.c | 4 +-
108 + ldap/servers/plugins/pwdstorage/md5_pwd.c | 36 ++++++-------
109 + ldap/servers/plugins/pwdstorage/sha_pwd.c | 18 +++++--
110 + ldap/servers/plugins/pwdstorage/smd5_pwd.c | 60 +++++++++++-----------
111 + ldap/servers/slapd/ch_malloc.c | 36 +++++++++++--
112 + ldap/servers/slapd/slapi-plugin.h | 2 +-
113 + 8 files changed, 155 insertions(+), 61 deletions(-)
114 + create mode 100644 dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
115 +
116 +diff --git a/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
117 +new file mode 100644
118 +index 0000000..2f38384
119 +--- /dev/null
120 ++++ b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
121 +@@ -0,0 +1,56 @@
122 ++# --- BEGIN COPYRIGHT BLOCK ---
123 ++# Copyright (C) 2018 Red Hat, Inc.
124 ++# All rights reserved.
125 ++#
126 ++# License: GPL (version 3 or any later version).
127 ++# See LICENSE for details.
128 ++# --- END COPYRIGHT BLOCK ---
129 ++#
130 ++
131 ++import ldap
132 ++import pytest
133 ++import logging
134 ++from lib389.topologies import topology_st
135 ++from lib389._constants import PASSWORD, DEFAULT_SUFFIX
136 ++
137 ++from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
138 ++
139 ++logging.getLogger(__name__).setLevel(logging.DEBUG)
140 ++log = logging.getLogger(__name__)
141 ++
142 ++def test_invalid_hash_fails(topology_st):
143 ++ """When given a malformed hash from userpassword migration
144 ++ slapi_ct_memcmp would check only to the length of the shorter
145 ++ field. This affects some values where it would ONLY verify
146 ++ the salt is valid, and thus would allow any password to bind.
147 ++
148 ++ :id: 8131c029-7147-47db-8d03-ec5db2a01cfb
149 ++ :setup: Standalone Instance
150 ++ :steps:
151 ++ 1. Create a user
152 ++ 2. Add an invalid password hash (truncated)
153 ++ 3. Attempt to bind
154 ++ :expectedresults:
155 ++ 1. User is added
156 ++ 2. Invalid pw hash is added
157 ++ 3. Bind fails
158 ++ """
159 ++ log.info("Running invalid hash test")
160 ++
161 ++ # Allow setting raw password hashes for migration.
162 ++ topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
163 ++
164 ++ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
165 ++ user = users.create(properties=TEST_USER_PROPERTIES)
166 ++ user.set('userPassword', '{CRYPT}XX')
167 ++
168 ++ # Attempt to bind. This should fail.
169 ++ with pytest.raises(ldap.INVALID_CREDENTIALS):
170 ++ user.bind(PASSWORD)
171 ++ with pytest.raises(ldap.INVALID_CREDENTIALS):
172 ++ user.bind('XX')
173 ++ with pytest.raises(ldap.INVALID_CREDENTIALS):
174 ++ user.bind('{CRYPT}XX')
175 ++
176 ++ log.info("PASSED")
177 ++
178 +diff --git a/ldap/servers/plugins/pwdstorage/clear_pwd.c b/ldap/servers/plugins/pwdstorage/clear_pwd.c
179 +index b9b362d..050e60d 100644
180 +--- a/ldap/servers/plugins/pwdstorage/clear_pwd.c
181 ++++ b/ldap/servers/plugins/pwdstorage/clear_pwd.c
182 +@@ -39,7 +39,7 @@ clear_pw_cmp( const char *userpwd, const char *dbpwd )
183 + * However, even if the first part of userpw matches dbpwd, but len !=, we
184 + * have already failed anyawy. This prevents substring matching.
185 + */
186 +- if (slapi_ct_memcmp(userpwd, dbpwd, len_dbp) != 0) {
187 ++ if (slapi_ct_memcmp(userpwd, dbpwd, len_user, len_dbp) != 0) {
188 + result = 1;
189 + }
190 + } else {
191 +@@ -51,7 +51,7 @@ clear_pw_cmp( const char *userpwd, const char *dbpwd )
192 + * dbpwd to itself. We have already got result == 1 if we are here, so we are
193 + * just trying to take up time!
194 + */
195 +- if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp)) {
196 ++ if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp, len_dbp)) {
197 + /* Do nothing, we have the if to fix a coverity check. */
198 + }
199 + }
200 +diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
201 +index dfd5af9..5fcff13 100644
202 +--- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c
203 ++++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
204 +@@ -56,13 +56,13 @@ crypt_close(Slapi_PBlock *pb __attribute__((unused)))
205 + int
206 + crypt_pw_cmp( const char *userpwd, const char *dbpwd )
207 + {
208 +- int rc;
209 ++ int32_t rc;
210 + char *cp;
211 + PR_Lock(cryptlock);
212 + /* we use salt (first 2 chars) of encoded password in call to crypt() */
213 + cp = crypt( userpwd, dbpwd );
214 + if (cp) {
215 +- rc= slapi_ct_memcmp( dbpwd, cp, strlen(dbpwd));
216 ++ rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd), strlen(cp));
217 + } else {
218 + rc = -1;
219 + }
220 +diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c b/ldap/servers/plugins/pwdstorage/md5_pwd.c
221 +index b279946..2e1c472 100644
222 +--- a/ldap/servers/plugins/pwdstorage/md5_pwd.c
223 ++++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c
224 +@@ -30,13 +30,13 @@
225 + int
226 + md5_pw_cmp( const char *userpwd, const char *dbpwd )
227 + {
228 +- int rc=-1;
229 +- char * bver;
230 +- PK11Context *ctx=NULL;
231 +- unsigned int outLen;
232 +- unsigned char hash_out[MD5_HASH_LEN];
233 +- unsigned char b2a_out[MD5_HASH_LEN*2]; /* conservative */
234 +- SECItem binary_item;
235 ++ int32_t rc = -1;
236 ++ char *bver;
237 ++ PK11Context *ctx = NULL;
238 ++ unsigned int outLen;
239 ++ unsigned char hash_out[MD5_HASH_LEN];
240 ++ unsigned char b2a_out[MD5_HASH_LEN * 2]; /* conservative */
241 ++ SECItem binary_item;
242 +
243 + ctx = PK11_CreateDigestContext(SEC_OID_MD5);
244 + if (ctx == NULL) {
245 +@@ -51,17 +51,17 @@ md5_pw_cmp( const char *userpwd, const char *dbpwd )
246 + PK11_DigestFinal(ctx, hash_out, &outLen, sizeof hash_out);
247 + PK11_DestroyContext(ctx, 1);
248 +
249 +- /* convert the binary hash to base64 */
250 +- binary_item.data = hash_out;
251 +- binary_item.len = outLen;
252 +- bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, &binary_item);
253 +- /* bver points to b2a_out upon success */
254 +- if (bver) {
255 +- rc = slapi_ct_memcmp(bver,dbpwd, strlen(dbpwd));
256 +- } else {
257 +- slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
258 +- "Could not base64 encode hashed value for password compare");
259 +- }
260 ++ /* convert the binary hash to base64 */
261 ++ binary_item.data = hash_out;
262 ++ binary_item.len = outLen;
263 ++ bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, &binary_item);
264 ++ /* bver points to b2a_out upon success */
265 ++ if (bver) {
266 ++ rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd), strlen(bver));
267 ++ } else {
268 ++ slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
269 ++ "Could not base64 encode hashed value for password compare");
270 ++ }
271 + loser:
272 + return rc;
273 + }
274 +diff --git a/ldap/servers/plugins/pwdstorage/sha_pwd.c b/ldap/servers/plugins/pwdstorage/sha_pwd.c
275 +index 5f41c5b..c9db896 100644
276 +--- a/ldap/servers/plugins/pwdstorage/sha_pwd.c
277 ++++ b/ldap/servers/plugins/pwdstorage/sha_pwd.c
278 +@@ -49,7 +49,7 @@ sha_pw_cmp (const char *userpwd, const char *dbpwd, unsigned int shaLen )
279 + char userhash[MAX_SHA_HASH_SIZE];
280 + char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3];
281 + char *dbhash = quick_dbhash;
282 +- struct berval salt;
283 ++ struct berval salt = {0};
284 + PRUint32 hash_len;
285 + unsigned int secOID;
286 + char *schemeName;
287 +@@ -120,10 +120,20 @@ sha_pw_cmp (const char *userpwd, const char *dbpwd, unsigned int shaLen )
288 + }
289 +
290 + /* the proof is in the comparison... */
291 +- if ( hash_len >= shaLen ) {
292 +- result = slapi_ct_memcmp( userhash, dbhash, shaLen );
293 ++ if (hash_len >= shaLen) {
294 ++ /*
295 ++ * This say "if the hash has a salt IE >, OR if they are equal, check the hash component ONLY.
296 ++ * This is why we repeat shaLen twice, even though it seems odd. If you have a dbhast of ssha
297 ++ * it's len is 28, and the userpw is 20, but 0 - 20 is the sha, and 21-28 is the salt, which
298 ++ * has already been processed into userhash.
299 ++ * The case where dbpwd is truncated is handled above in "invalid base64" arm.
300 ++ */
301 ++ result = slapi_ct_memcmp(userhash, dbhash, shaLen, shaLen);
302 + } else {
303 +- result = slapi_ct_memcmp( userhash, dbhash + OLD_SALT_LENGTH, hash_len - OLD_SALT_LENGTH );
304 ++ /* This case is for if the salt is at the START, which only applies to DS40B1 case.
305 ++ * May never be a valid check...
306 ++ */
307 ++ result = slapi_ct_memcmp(userhash, dbhash + OLD_SALT_LENGTH, shaLen, hash_len - OLD_SALT_LENGTH);
308 + }
309 +
310 + loser:
311 +diff --git a/ldap/servers/plugins/pwdstorage/smd5_pwd.c b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
312 +index 2e9d195..f6b4bb4 100644
313 +--- a/ldap/servers/plugins/pwdstorage/smd5_pwd.c
314 ++++ b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
315 +@@ -52,35 +52,37 @@ smd5_pw_cmp( const char *userpwd, const char *dbpwd )
316 + /*
317 + * Decode hash stored in database.
318 + */
319 +- hash_len = pwdstorage_base64_decode_len(dbpwd, 0);
320 +- if ( hash_len >= sizeof(quick_dbhash) ) { /* get more space: */
321 +- dbhash = (char*) slapi_ch_calloc( hash_len + 1, sizeof(char) );
322 +- if ( dbhash == NULL ) goto loser;
323 +- } else {
324 +- memset( quick_dbhash, 0, sizeof(quick_dbhash) );
325 +- }
326 +-
327 +- hashresult = PL_Base64Decode( dbpwd, 0, dbhash );
328 +- if (NULL == hashresult) {
329 +- slapi_log_err(SLAPI_LOG_PLUGIN, SALTED_MD5_SUBSYSTEM_NAME,
330 +- "smd5_pw_cmp: userPassword \"%s\" is the wrong length "
331 +- "or is not properly encoded BASE64\n", dbpwd );
332 +- goto loser;
333 +- }
334 +-
335 +- salt.bv_val = (void*)(dbhash + MD5_LENGTH); /* salt starts after hash value */
336 +- salt.bv_len = hash_len - MD5_LENGTH; /* remaining bytes must be salt */
337 +-
338 +- /* create the hash */
339 +- memset( userhash, 0, sizeof(userhash) );
340 +- PK11_DigestBegin(ctx);
341 +- PK11_DigestOp(ctx, (const unsigned char *)userpwd, strlen(userpwd));
342 +- PK11_DigestOp(ctx, (unsigned char*)(salt.bv_val), salt.bv_len);
343 +- PK11_DigestFinal(ctx, userhash, &outLen, sizeof userhash);
344 +- PK11_DestroyContext(ctx, 1);
345 +-
346 +- /* Compare everything up to the salt. */
347 +- rc = slapi_ct_memcmp( userhash, dbhash, MD5_LENGTH );
348 ++ hash_len = pwdstorage_base64_decode_len(dbpwd, 0);
349 ++ if (hash_len >= sizeof(quick_dbhash)) { /* get more space: */
350 ++ dbhash = (char *)slapi_ch_calloc(hash_len + 1, sizeof(char));
351 ++ if (dbhash == NULL)
352 ++ goto loser;
353 ++ } else {
354 ++ memset(quick_dbhash, 0, sizeof(quick_dbhash));
355 ++ }
356 ++
357 ++ hashresult = PL_Base64Decode(dbpwd, 0, dbhash);
358 ++ if (NULL == hashresult) {
359 ++ slapi_log_err(SLAPI_LOG_PLUGIN, SALTED_MD5_SUBSYSTEM_NAME,
360 ++ "smd5_pw_cmp: userPassword \"%s\" is the wrong length "
361 ++ "or is not properly encoded BASE64\n",
362 ++ dbpwd);
363 ++ goto loser;
364 ++ }
365 ++
366 ++ salt.bv_val = (void *)(dbhash + MD5_LENGTH); /* salt starts after hash value */
367 ++ salt.bv_len = hash_len - MD5_LENGTH; /* remaining bytes must be salt */
368 ++
369 ++ /* create the hash */
370 ++ memset(userhash, 0, sizeof(userhash));
371 ++ PK11_DigestBegin(ctx);
372 ++ PK11_DigestOp(ctx, (const unsigned char *)userpwd, strlen(userpwd));
373 ++ PK11_DigestOp(ctx, (unsigned char *)(salt.bv_val), salt.bv_len);
374 ++ PK11_DigestFinal(ctx, userhash, &outLen, sizeof userhash);
375 ++ PK11_DestroyContext(ctx, 1);
376 ++
377 ++ /* Compare everything up to the salt. */
378 ++ rc = slapi_ct_memcmp(userhash, dbhash, MD5_LENGTH, MD5_LENGTH);
379 +
380 + loser:
381 + if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free_string( (char **)&dbhash );
382 +diff --git a/ldap/servers/slapd/ch_malloc.c b/ldap/servers/slapd/ch_malloc.c
383 +index 52ccb64..66cb692 100644
384 +--- a/ldap/servers/slapd/ch_malloc.c
385 ++++ b/ldap/servers/slapd/ch_malloc.c
386 +@@ -343,8 +343,8 @@ slapi_ch_smprintf(const char *fmt, ...)
387 +
388 + /* Constant time memcmp. Does not shortcircuit on failure! */
389 + /* This relies on p1 and p2 both being size at least n! */
390 +-int
391 +-slapi_ct_memcmp( const void *p1, const void *p2, size_t n)
392 ++int32_t
393 ++slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2)
394 + {
395 + int result = 0;
396 + const unsigned char *_p1 = (const unsigned char *)p1;
397 +@@ -354,9 +354,35 @@ slapi_ct_memcmp( const void *p1, const void *p2, size_t n)
398 + return 2;
399 + }
400 +
401 +- for (size_t i = 0; i < n; i++) {
402 +- if (_p1[i] ^ _p2[i]) {
403 +- result = 1;
404 ++ if (n1 == n2) {
405 ++ for (size_t i = 0; i < n1; i++) {
406 ++ if (_p1[i] ^ _p2[i]) {
407 ++ result = 1;
408 ++ }
409 ++ }
410 ++ } else {
411 ++ const unsigned char *_pa;
412 ++ const unsigned char *_pb;
413 ++ size_t nl;
414 ++ if (n2 > n1) {
415 ++ _pa = _p2;
416 ++ _pb = _p2;
417 ++ nl = n2;
418 ++ } else {
419 ++ _pa = _p1;
420 ++ _pb = _p1;
421 ++ nl = n1;
422 ++ }
423 ++ /* We already fail as n1 != n2 */
424 ++ result = 3;
425 ++ for (size_t i = 0; i < nl; i++) {
426 ++ if (_pa[i] ^ _pb[i]) {
427 ++ /*
428 ++ * If we don't mutate result here, dead code elimination
429 ++ * we remove for loop.
430 ++ */
431 ++ result = 4;
432 ++ }
433 + }
434 + }
435 + return result;
436 +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
437 +index d37bc63..2c5c4ce 100644
438 +--- a/ldap/servers/slapd/slapi-plugin.h
439 ++++ b/ldap/servers/slapd/slapi-plugin.h
440 +@@ -5859,7 +5859,7 @@ char * slapi_ch_smprintf(const char *fmt, ...)
441 + * \param n length in bytes of the content of p1 AND p2.
442 + * \return 0 on match. 1 on non-match. 2 on presence of NULL pointer in p1 or p2.
443 + */
444 +-int slapi_ct_memcmp( const void *p1, const void *p2, size_t n);
445 ++int32_t slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2);
446 +
447 + /*
448 + * syntax plugin routines
449 +--
450 +1.8.3.1
451 +