Compare commits
No commits in common. 'c9' and 'c8-stream-1.4' have entirely different histories.
c9
...
c8-stream-
@ -1,2 +1,3 @@
|
|||||||
274dec37976c1efde9cbeb458d50bbcd6b244974 SOURCES/389-ds-base-2.5.2.tar.bz2
|
bd9aab32d9cbf9231058d585479813f3420dc872 SOURCES/389-ds-base-1.4.3.39.tar.bz2
|
||||||
1c8f2d0dfbf39fa8cd86363bf3314351ab21f8d4 SOURCES/jemalloc-5.3.0.tar.bz2
|
1c8f2d0dfbf39fa8cd86363bf3314351ab21f8d4 SOURCES/jemalloc-5.3.0.tar.bz2
|
||||||
|
978b7c5e4a9e5784fddb23ba1abe4dc5a071589f SOURCES/vendor-1.4.3.39-1.tar.gz
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
SOURCES/389-ds-base-2.5.2.tar.bz2
|
SOURCES/389-ds-base-1.4.3.39.tar.bz2
|
||||||
SOURCES/jemalloc-5.3.0.tar.bz2
|
SOURCES/jemalloc-5.3.0.tar.bz2
|
||||||
|
SOURCES/vendor-1.4.3.39-1.tar.gz
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
From 0ff5aa641d619bdcc154c2c94f8f8180bcaec776 Mon Sep 17 00:00:00 2001
|
|
||||||
From: tbordaz <tbordaz@redhat.com>
|
|
||||||
Date: Thu, 29 Aug 2024 10:49:57 +0200
|
|
||||||
Subject: [PATCH] Issue 6312 - In branch 2.5, healthcheck report an invalid
|
|
||||||
warning regarding BDB deprecation (#6313)
|
|
||||||
|
|
||||||
Bug description:
|
|
||||||
during healthcheck, _lint_backend_implementation checks that
|
|
||||||
the instance is not running a BDB backend.
|
|
||||||
This check only applies for instance after 3.0.0
|
|
||||||
|
|
||||||
Fix description:
|
|
||||||
If the instance is newer than 3.0.0 the health check
|
|
||||||
just returns
|
|
||||||
|
|
||||||
relates: #6312
|
|
||||||
|
|
||||||
Reviewed by:
|
|
||||||
---
|
|
||||||
dirsrvtests/tests/suites/healthcheck/healthcheck_test.py | 1 +
|
|
||||||
src/lib389/lib389/backend.py | 4 ++--
|
|
||||||
2 files changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/dirsrvtests/tests/suites/healthcheck/healthcheck_test.py b/dirsrvtests/tests/suites/healthcheck/healthcheck_test.py
|
|
||||||
index 29cca187e..66cf3c7d3 100644
|
|
||||||
--- a/dirsrvtests/tests/suites/healthcheck/healthcheck_test.py
|
|
||||||
+++ b/dirsrvtests/tests/suites/healthcheck/healthcheck_test.py
|
|
||||||
@@ -556,6 +556,7 @@ def test_lint_backend_implementation_wrong_files(topology_st):
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(get_default_db_lib() == "mdb", reason="Not needed for mdb")
|
|
||||||
+@pytest.mark.skipif(ds_is_older("3.0.0"), reason="mdb and bdb are both supported")
|
|
||||||
def test_lint_backend_implementation(topology_st):
|
|
||||||
"""Test the lint for backend implementation mismatch
|
|
||||||
|
|
||||||
diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py
|
|
||||||
index caee88e6a..0ed00a4a7 100644
|
|
||||||
--- a/src/lib389/lib389/backend.py
|
|
||||||
+++ b/src/lib389/lib389/backend.py
|
|
||||||
@@ -14,7 +14,7 @@ from lib389._constants import DN_LDBM, DN_CHAIN, DN_PLUGIN, DEFAULT_BENAME
|
|
||||||
from lib389.properties import BACKEND_OBJECTCLASS_VALUE, BACKEND_PROPNAME_TO_ATTRNAME, BACKEND_CHAIN_BIND_DN, \
|
|
||||||
BACKEND_CHAIN_BIND_PW, BACKEND_CHAIN_URLS, BACKEND_PROPNAME_TO_ATTRNAME, BACKEND_NAME, \
|
|
||||||
BACKEND_SUFFIX, BACKEND_SAMPLE_ENTRIES, TASK_WAIT
|
|
||||||
-from lib389.utils import normalizeDN, ensure_str, assert_c
|
|
||||||
+from lib389.utils import normalizeDN, ensure_str, assert_c, ds_is_newer
|
|
||||||
from lib389 import Entry
|
|
||||||
|
|
||||||
# Need to fix this ....
|
|
||||||
@@ -513,7 +513,7 @@ class Backend(DSLdapObject):
|
|
||||||
|
|
||||||
def _lint_backend_implementation(self):
|
|
||||||
backend_impl = self._instance.get_db_lib()
|
|
||||||
- if backend_impl == 'bdb':
|
|
||||||
+ if backend_impl == 'bdb' and ds_is_newer('3.0.0', instance=self._instance):
|
|
||||||
result = DSBLE0006
|
|
||||||
result['items'] = [self.lint_uid()]
|
|
||||||
yield result
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
|||||||
|
From dddb14210b402f317e566b6387c76a8e659bf7fa Mon Sep 17 00:00:00 2001
|
||||||
|
From: progier389 <progier@redhat.com>
|
||||||
|
Date: Tue, 14 Feb 2023 13:34:10 +0100
|
||||||
|
Subject: [PATCH 1/2] issue 5647 - covscan: memory leak in audit log when
|
||||||
|
adding entries (#5650)
|
||||||
|
|
||||||
|
covscan reported an issue about "vals" variable in auditlog.c:231 and indeed a charray_free is missing.
|
||||||
|
Issue: 5647
|
||||||
|
Reviewed by: @mreynolds389, @droideck
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/auditlog.c | 71 +++++++++++++++++++----------------
|
||||||
|
1 file changed, 38 insertions(+), 33 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c
|
||||||
|
index 68cbc674d..3128e0497 100644
|
||||||
|
--- a/ldap/servers/slapd/auditlog.c
|
||||||
|
+++ b/ldap/servers/slapd/auditlog.c
|
||||||
|
@@ -177,6 +177,40 @@ write_auditfail_log_entry(Slapi_PBlock *pb)
|
||||||
|
slapi_ch_free_string(&audit_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Write the attribute values to the audit log as "comments"
|
||||||
|
+ *
|
||||||
|
+ * Slapi_Attr *entry - the attribute begin logged.
|
||||||
|
+ * char *attrname - the attribute name.
|
||||||
|
+ * lenstr *l - the audit log buffer
|
||||||
|
+ *
|
||||||
|
+ * Resulting output in the log:
|
||||||
|
+ *
|
||||||
|
+ * #ATTR: VALUE
|
||||||
|
+ * #ATTR: VALUE
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+log_entry_attr(Slapi_Attr *entry_attr, char *attrname, lenstr *l)
|
||||||
|
+{
|
||||||
|
+ Slapi_Value **vals = attr_get_present_values(entry_attr);
|
||||||
|
+ for(size_t i = 0; vals && vals[i]; i++) {
|
||||||
|
+ char log_val[256] = "";
|
||||||
|
+ const struct berval *bv = slapi_value_get_berval(vals[i]);
|
||||||
|
+ if (bv->bv_len >= 256) {
|
||||||
|
+ strncpy(log_val, bv->bv_val, 252);
|
||||||
|
+ strcpy(log_val+252, "...");
|
||||||
|
+ } else {
|
||||||
|
+ strncpy(log_val, bv->bv_val, bv->bv_len);
|
||||||
|
+ log_val[bv->bv_len] = 0;
|
||||||
|
+ }
|
||||||
|
+ addlenstr(l, "#");
|
||||||
|
+ addlenstr(l, attrname);
|
||||||
|
+ addlenstr(l, ": ");
|
||||||
|
+ addlenstr(l, log_val);
|
||||||
|
+ addlenstr(l, "\n");
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Write "requested" attributes from the entry to the audit log as "comments"
|
||||||
|
*
|
||||||
|
@@ -212,21 +246,9 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l)
|
||||||
|
for (req_attr = ldap_utf8strtok_r(display_attrs, ", ", &last); req_attr;
|
||||||
|
req_attr = ldap_utf8strtok_r(NULL, ", ", &last))
|
||||||
|
{
|
||||||
|
- char **vals = slapi_entry_attr_get_charray(entry, req_attr);
|
||||||
|
- for(size_t i = 0; vals && vals[i]; i++) {
|
||||||
|
- char log_val[256] = {0};
|
||||||
|
-
|
||||||
|
- if (strlen(vals[i]) > 256) {
|
||||||
|
- strncpy(log_val, vals[i], 252);
|
||||||
|
- strcat(log_val, "...");
|
||||||
|
- } else {
|
||||||
|
- strcpy(log_val, vals[i]);
|
||||||
|
- }
|
||||||
|
- addlenstr(l, "#");
|
||||||
|
- addlenstr(l, req_attr);
|
||||||
|
- addlenstr(l, ": ");
|
||||||
|
- addlenstr(l, log_val);
|
||||||
|
- addlenstr(l, "\n");
|
||||||
|
+ slapi_entry_attr_find(entry, req_attr, &entry_attr);
|
||||||
|
+ if (entry_attr) {
|
||||||
|
+ log_entry_attr(entry_attr, req_attr, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@@ -234,7 +256,6 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l)
|
||||||
|
for (; entry_attr; entry_attr = entry_attr->a_next) {
|
||||||
|
Slapi_Value **vals = attr_get_present_values(entry_attr);
|
||||||
|
char *attr = NULL;
|
||||||
|
- const char *val = NULL;
|
||||||
|
|
||||||
|
slapi_attr_get_type(entry_attr, &attr);
|
||||||
|
if (strcmp(attr, PSEUDO_ATTR_UNHASHEDUSERPASSWORD) == 0) {
|
||||||
|
@@ -251,23 +272,7 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l)
|
||||||
|
addlenstr(l, ": ****************************\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- for(size_t i = 0; vals && vals[i]; i++) {
|
||||||
|
- char log_val[256] = {0};
|
||||||
|
-
|
||||||
|
- val = slapi_value_get_string(vals[i]);
|
||||||
|
- if (strlen(val) > 256) {
|
||||||
|
- strncpy(log_val, val, 252);
|
||||||
|
- strcat(log_val, "...");
|
||||||
|
- } else {
|
||||||
|
- strcpy(log_val, val);
|
||||||
|
- }
|
||||||
|
- addlenstr(l, "#");
|
||||||
|
- addlenstr(l, attr);
|
||||||
|
- addlenstr(l, ": ");
|
||||||
|
- addlenstr(l, log_val);
|
||||||
|
- addlenstr(l, "\n");
|
||||||
|
- }
|
||||||
|
+ log_entry_attr(entry_attr, attr, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slapi_ch_free_string(&display_attrs);
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
From be7c2b82958e91ce08775bf6b5da3c311d3b00e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: progier389 <progier@redhat.com>
|
||||||
|
Date: Mon, 20 Feb 2023 16:14:05 +0100
|
||||||
|
Subject: [PATCH 2/2] Issue 5647 - Fix unused variable warning from previous
|
||||||
|
commit (#5670)
|
||||||
|
|
||||||
|
* issue 5647 - memory leak in audit log when adding entries
|
||||||
|
* Issue 5647 - Fix unused variable warning from previous commit
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/auditlog.c | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c
|
||||||
|
index 3128e0497..0597ecc6f 100644
|
||||||
|
--- a/ldap/servers/slapd/auditlog.c
|
||||||
|
+++ b/ldap/servers/slapd/auditlog.c
|
||||||
|
@@ -254,7 +254,6 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l)
|
||||||
|
} else {
|
||||||
|
/* Return all attributes */
|
||||||
|
for (; entry_attr; entry_attr = entry_attr->a_next) {
|
||||||
|
- Slapi_Value **vals = attr_get_present_values(entry_attr);
|
||||||
|
char *attr = NULL;
|
||||||
|
|
||||||
|
slapi_attr_get_type(entry_attr, &attr);
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -1,237 +0,0 @@
|
|||||||
From af27f433ec14bcaf070108ab0b6af64ad1153a11 Mon Sep 17 00:00:00 2001
|
|
||||||
From: progier389 <progier@redhat.com>
|
|
||||||
Date: Fri, 6 Sep 2024 18:07:17 +0200
|
|
||||||
Subject: [PATCH] Issue 6316 - lmdb reindex is broken if index type is
|
|
||||||
specified (#6318)
|
|
||||||
|
|
||||||
While reindexing using task or offline reindex, if the attribute name contains the index type (for example :eq,pres)
|
|
||||||
Then the attribute is not reindexed. Problem occurs when lmdb is used, things are working fine with bdb.
|
|
||||||
Solution: strip the index type in reindex as it is done in bdb case.
|
|
||||||
Anyway the reindex design requires that for a given attribute all the configured index types must be rebuild.
|
|
||||||
|
|
||||||
Issue: #6316
|
|
||||||
|
|
||||||
Reviewed by: @tbordaz, @droideck (Thanks!)
|
|
||||||
---
|
|
||||||
.../tests/suites/indexes/regression_test.py | 141 +++++++++++++++++-
|
|
||||||
.../slapd/back-ldbm/db-mdb/mdb_import.c | 10 +-
|
|
||||||
2 files changed, 147 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/dirsrvtests/tests/suites/indexes/regression_test.py b/dirsrvtests/tests/suites/indexes/regression_test.py
|
|
||||||
index c385f5ca4..b077b529a 100644
|
|
||||||
--- a/dirsrvtests/tests/suites/indexes/regression_test.py
|
|
||||||
+++ b/dirsrvtests/tests/suites/indexes/regression_test.py
|
|
||||||
@@ -10,6 +10,9 @@ import time
|
|
||||||
import os
|
|
||||||
import pytest
|
|
||||||
import ldap
|
|
||||||
+import logging
|
|
||||||
+import glob
|
|
||||||
+import re
|
|
||||||
from lib389._constants import DEFAULT_BENAME, DEFAULT_SUFFIX
|
|
||||||
from lib389.backend import Backend, Backends, DatabaseConfig
|
|
||||||
from lib389.cos import CosClassicDefinition, CosClassicDefinitions, CosTemplate
|
|
||||||
@@ -31,6 +34,8 @@ SUFFIX2 = 'dc=example2,dc=com'
|
|
||||||
BENAME2 = 'be2'
|
|
||||||
|
|
||||||
DEBUGGING = os.getenv("DEBUGGING", default=False)
|
|
||||||
+logging.getLogger(__name__).setLevel(logging.INFO)
|
|
||||||
+log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
|
||||||
@@ -83,6 +88,7 @@ def add_a_group_with_users(request, topo):
|
|
||||||
'cn': USER_NAME,
|
|
||||||
'uidNumber': f'{num}',
|
|
||||||
'gidNumber': f'{num}',
|
|
||||||
+ 'description': f'Description for {USER_NAME}',
|
|
||||||
'homeDirectory': f'/home/{USER_NAME}'
|
|
||||||
})
|
|
||||||
users_list.append(user)
|
|
||||||
@@ -95,9 +101,10 @@ def add_a_group_with_users(request, topo):
|
|
||||||
# If the server crashed, start it again to do the cleanup
|
|
||||||
if not topo.standalone.status():
|
|
||||||
topo.standalone.start()
|
|
||||||
- for user in users_list:
|
|
||||||
- user.delete()
|
|
||||||
- group.delete()
|
|
||||||
+ if not DEBUGGING:
|
|
||||||
+ for user in users_list:
|
|
||||||
+ user.delete()
|
|
||||||
+ group.delete()
|
|
||||||
|
|
||||||
request.addfinalizer(fin)
|
|
||||||
|
|
||||||
@@ -124,6 +131,38 @@ def set_small_idlistscanlimit(request, topo):
|
|
||||||
|
|
||||||
request.addfinalizer(fin)
|
|
||||||
|
|
||||||
+
|
|
||||||
+@pytest.fixture(scope="function")
|
|
||||||
+def set_description_index(request, topo, add_a_group_with_users):
|
|
||||||
+ """
|
|
||||||
+ Set some description values and description index without reindexing.
|
|
||||||
+ """
|
|
||||||
+ inst = topo.standalone
|
|
||||||
+ backends = Backends(inst)
|
|
||||||
+ backend = backends.get(DEFAULT_BENAME)
|
|
||||||
+ indexes = backend.get_indexes()
|
|
||||||
+ attr = 'description'
|
|
||||||
+
|
|
||||||
+ def fin(always=False):
|
|
||||||
+ if always or not DEBUGGING:
|
|
||||||
+ try:
|
|
||||||
+ idx = indexes.get(attr)
|
|
||||||
+ idx.delete()
|
|
||||||
+ except ldap.NO_SUCH_OBJECT:
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ request.addfinalizer(fin)
|
|
||||||
+ fin(always=True)
|
|
||||||
+ index = indexes.create(properties={
|
|
||||||
+ 'cn': attr,
|
|
||||||
+ 'nsSystemIndex': 'false',
|
|
||||||
+ 'nsIndexType': ['eq', 'pres', 'sub']
|
|
||||||
+ })
|
|
||||||
+ # Restart needed with lmdb (to open the dbi handle)
|
|
||||||
+ inst.restart()
|
|
||||||
+ return (indexes, attr)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
#unstable or unstatus tests, skipped for now
|
|
||||||
@pytest.mark.flaky(max_runs=2, min_passes=1)
|
|
||||||
@pytest.mark.skipif(ds_is_older("1.4.4.4"), reason="Not implemented")
|
|
||||||
@@ -347,6 +386,102 @@ def test_task_status(topo):
|
|
||||||
assert reindex_task.get_exit_code() == 0
|
|
||||||
|
|
||||||
|
|
||||||
+def count_keys(inst, bename, attr, prefix=''):
|
|
||||||
+ indexfile = os.path.join(inst.dbdir, bename, attr + '.db')
|
|
||||||
+ # (bdb - we should also accept a version number for .db suffix)
|
|
||||||
+ for f in glob.glob(f'{indexfile}*'):
|
|
||||||
+ indexfile = f
|
|
||||||
+
|
|
||||||
+ inst.stop()
|
|
||||||
+ output = inst.dbscan(None, None, args=['-f', indexfile, '-A'], stopping=False).decode()
|
|
||||||
+ inst.start()
|
|
||||||
+ count = 0
|
|
||||||
+ regexp = f'^KEY: {re.escape(prefix)}'
|
|
||||||
+ for match in re.finditer(regexp, output, flags=re.MULTILINE):
|
|
||||||
+ count += 1
|
|
||||||
+ log.info(f"count_keys found {count} keys starting with '{prefix}' in {indexfile}")
|
|
||||||
+ return count
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def test_reindex_task_with_type(topo, set_description_index):
|
|
||||||
+ """Check that reindex task works as expected when index type is specified.
|
|
||||||
+
|
|
||||||
+ :id: 0c7f2fda-69f6-11ef-9eb8-083a88554478
|
|
||||||
+ :setup: Standalone instance
|
|
||||||
+ - with 100 users having description attribute
|
|
||||||
+ - with description:eq,pres,sub index entry but not yet reindexed
|
|
||||||
+ :steps:
|
|
||||||
+ 1. Set description in suffix entry
|
|
||||||
+ 2. Count number of equality keys in description index
|
|
||||||
+ 3. Start a Reindex task on description:eq,pres and wait for completion
|
|
||||||
+ 4. Check the task status and exit code
|
|
||||||
+ 5. Count the equality, presence and substring keys in description index
|
|
||||||
+ 6. Start a Reindex task on description and wait for completion
|
|
||||||
+ 7. Check the task status and exit code
|
|
||||||
+ 8. Count the equality, presence and substring keys in description index
|
|
||||||
+
|
|
||||||
+ :expectedresults:
|
|
||||||
+ 1. Success
|
|
||||||
+ 2. Should be either no key (bdb) or a single one (lmdb)
|
|
||||||
+ 3. Success
|
|
||||||
+ 4. Success
|
|
||||||
+ 5. Should have: more equality keys than in step 2
|
|
||||||
+ one presence key
|
|
||||||
+ some substrings keys
|
|
||||||
+ 6. Success
|
|
||||||
+ 7. Success
|
|
||||||
+ 8. Should have same counts than in step 5
|
|
||||||
+ """
|
|
||||||
+ (indexes, attr) = set_description_index
|
|
||||||
+ inst = topo.standalone
|
|
||||||
+ if not inst.is_dbi_supported():
|
|
||||||
+ pytest.skip('This test requires that dbscan supports -A option')
|
|
||||||
+ # modify indexed value
|
|
||||||
+ Domain(inst, DEFAULT_SUFFIX).replace(attr, f'test_before_reindex')
|
|
||||||
+
|
|
||||||
+ keys1 = count_keys(inst, DEFAULT_BENAME, attr, prefix='=')
|
|
||||||
+ assert keys1 <= 1
|
|
||||||
+
|
|
||||||
+ tasks = Tasks(topo.standalone)
|
|
||||||
+ # completed reindex tasks MUST have a status because freeipa check it.
|
|
||||||
+
|
|
||||||
+ # Reindex attr with eq,pres types
|
|
||||||
+ log.info(f'Reindex {attr} with eq,pres types')
|
|
||||||
+ tasks.reindex(
|
|
||||||
+ suffix=DEFAULT_SUFFIX,
|
|
||||||
+ attrname=f'{attr}:eq,pres',
|
|
||||||
+ args={TASK_WAIT: True}
|
|
||||||
+ )
|
|
||||||
+ reindex_task = Task(topo.standalone, tasks.dn)
|
|
||||||
+ assert reindex_task.status()
|
|
||||||
+ assert reindex_task.get_exit_code() == 0
|
|
||||||
+
|
|
||||||
+ keys2e = count_keys(inst, DEFAULT_BENAME, attr, prefix='=')
|
|
||||||
+ keys2p = count_keys(inst, DEFAULT_BENAME, attr, prefix='+')
|
|
||||||
+ keys2s = count_keys(inst, DEFAULT_BENAME, attr, prefix='*')
|
|
||||||
+ assert keys2e > keys1
|
|
||||||
+ assert keys2p > 0
|
|
||||||
+ assert keys2s > 0
|
|
||||||
+
|
|
||||||
+ # Reindex attr without types
|
|
||||||
+ log.info(f'Reindex {attr} without types')
|
|
||||||
+ tasks.reindex(
|
|
||||||
+ suffix=DEFAULT_SUFFIX,
|
|
||||||
+ attrname=attr,
|
|
||||||
+ args={TASK_WAIT: True}
|
|
||||||
+ )
|
|
||||||
+ reindex_task = Task(topo.standalone, tasks.dn)
|
|
||||||
+ assert reindex_task.status()
|
|
||||||
+ assert reindex_task.get_exit_code() == 0
|
|
||||||
+
|
|
||||||
+ keys3e = count_keys(inst, DEFAULT_BENAME, attr, prefix='=')
|
|
||||||
+ keys3p = count_keys(inst, DEFAULT_BENAME, attr, prefix='+')
|
|
||||||
+ keys3s = count_keys(inst, DEFAULT_BENAME, attr, prefix='*')
|
|
||||||
+ assert keys3e == keys2e
|
|
||||||
+ assert keys3p == keys2p
|
|
||||||
+ assert keys3s == keys2s
|
|
||||||
+
|
|
||||||
+
|
|
||||||
def test_task_and_be(topo, add_backend_and_ldif_50K_users):
|
|
||||||
"""Check that backend is writable after finishing a tasks
|
|
||||||
|
|
||||||
diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import.c b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import.c
|
|
||||||
index d57146953..ce2151174 100644
|
|
||||||
--- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import.c
|
|
||||||
+++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import.c
|
|
||||||
@@ -1150,6 +1150,8 @@ process_db2index_attrs(Slapi_PBlock *pb, ImportCtx_t *ctx)
|
|
||||||
* TBD
|
|
||||||
*/
|
|
||||||
char **attrs = NULL;
|
|
||||||
+ char *attrname = NULL;
|
|
||||||
+ char *pt = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
slapi_pblock_get(pb, SLAPI_DB2INDEX_ATTRS, &attrs);
|
|
||||||
@@ -1157,7 +1159,13 @@ process_db2index_attrs(Slapi_PBlock *pb, ImportCtx_t *ctx)
|
|
||||||
for (i = 0; attrs && attrs[i]; i++) {
|
|
||||||
switch (attrs[i][0]) {
|
|
||||||
case 't': /* attribute type to index */
|
|
||||||
- slapi_ch_array_add(&ctx->indexAttrs, slapi_ch_strdup(attrs[i] + 1));
|
|
||||||
+ attrname = slapi_ch_strdup(attrs[i] + 1);
|
|
||||||
+ /* Strip index type */
|
|
||||||
+ pt = strchr(attrname, ':');
|
|
||||||
+ if (pt != NULL) {
|
|
||||||
+ *pt = '\0';
|
|
||||||
+ }
|
|
||||||
+ slapi_ch_array_add(&ctx->indexAttrs, attrname);
|
|
||||||
break;
|
|
||||||
case 'T': /* VLV Search to index */
|
|
||||||
slapi_ch_array_add(&ctx->indexVlvs, get_vlv_dbname(attrs[i] + 1));
|
|
||||||
--
|
|
||||||
2.46.0
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
|||||||
|
From 692c4cec6cc5c0086cf58f83bcfa690c766c9887 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Thierry Bordaz <tbordaz@redhat.com>
|
||||||
|
Date: Fri, 2 Feb 2024 14:14:28 +0100
|
||||||
|
Subject: [PATCH] Issue 5407 - sync_repl crashes if enabled while dynamic
|
||||||
|
plugin is enabled (#5411)
|
||||||
|
|
||||||
|
Bug description:
|
||||||
|
When dynamic plugin is enabled, if a MOD enables sync_repl plugin
|
||||||
|
then sync_repl init function registers the postop callback
|
||||||
|
that will be called for the MOD itself while the preop
|
||||||
|
has not been called.
|
||||||
|
postop expects preop to be called and so primary operation
|
||||||
|
to be set. When it is not set it crashes
|
||||||
|
|
||||||
|
Fix description:
|
||||||
|
If the primary operation is not set, just return
|
||||||
|
|
||||||
|
relates: #5407
|
||||||
|
---
|
||||||
|
.../suites/syncrepl_plugin/basic_test.py | 68 +++++++++++++++++++
|
||||||
|
ldap/servers/plugins/sync/sync_persist.c | 23 ++++++-
|
||||||
|
2 files changed, 90 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py b/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py
|
||||||
|
index eb3770b78..cdf35eeaa 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py
|
||||||
|
@@ -592,6 +592,74 @@ def test_sync_repl_cenotaph(topo_m2, request):
|
||||||
|
|
||||||
|
request.addfinalizer(fin)
|
||||||
|
|
||||||
|
+def test_sync_repl_dynamic_plugin(topology, request):
|
||||||
|
+ """Test sync_repl with dynamic plugin
|
||||||
|
+
|
||||||
|
+ :id: d4f84913-c18a-459f-8525-110f610ca9e6
|
||||||
|
+ :setup: install a standalone instance
|
||||||
|
+ :steps:
|
||||||
|
+ 1. reset instance to standard (no retroCL, no sync_repl, no dynamic plugin)
|
||||||
|
+ 2. Enable dynamic plugin
|
||||||
|
+ 3. Enable retroCL/content_sync
|
||||||
|
+ 4. Establish a sync_repl req
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Should succeeds
|
||||||
|
+ 2. Should succeeds
|
||||||
|
+ 3. Should succeeds
|
||||||
|
+ 4. Should succeeds
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ # Reset the instance in a default config
|
||||||
|
+ # Disable content sync plugin
|
||||||
|
+ topology.standalone.plugins.disable(name=PLUGIN_REPL_SYNC)
|
||||||
|
+
|
||||||
|
+ # Disable retro changelog
|
||||||
|
+ topology.standalone.plugins.disable(name=PLUGIN_RETRO_CHANGELOG)
|
||||||
|
+
|
||||||
|
+ # Disable dynamic plugins
|
||||||
|
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', b'off')])
|
||||||
|
+ topology.standalone.restart()
|
||||||
|
+
|
||||||
|
+ # Now start the test
|
||||||
|
+ # Enable dynamic plugins
|
||||||
|
+ try:
|
||||||
|
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', b'on')])
|
||||||
|
+ except ldap.LDAPError as e:
|
||||||
|
+ log.error('Failed to enable dynamic plugin! {}'.format(e.args[0]['desc']))
|
||||||
|
+ assert False
|
||||||
|
+
|
||||||
|
+ # Enable retro changelog
|
||||||
|
+ topology.standalone.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
|
||||||
|
+
|
||||||
|
+ # Enbale content sync plugin
|
||||||
|
+ topology.standalone.plugins.enable(name=PLUGIN_REPL_SYNC)
|
||||||
|
+
|
||||||
|
+ # create a sync repl client and wait 5 seconds to be sure it is running
|
||||||
|
+ sync_repl = Sync_persist(topology.standalone)
|
||||||
|
+ sync_repl.start()
|
||||||
|
+ time.sleep(5)
|
||||||
|
+
|
||||||
|
+ # create users
|
||||||
|
+ users = UserAccounts(topology.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ users_set = []
|
||||||
|
+ for i in range(10001, 10004):
|
||||||
|
+ users_set.append(users.create_test_user(uid=i))
|
||||||
|
+
|
||||||
|
+ time.sleep(10)
|
||||||
|
+ # delete users, that automember/memberof will generate nested updates
|
||||||
|
+ for user in users_set:
|
||||||
|
+ user.delete()
|
||||||
|
+ # stop the server to get the sync_repl result set (exit from while loop).
|
||||||
|
+ # Only way I found to acheive that.
|
||||||
|
+ # and wait a bit to let sync_repl thread time to set its result before fetching it.
|
||||||
|
+ topology.standalone.stop()
|
||||||
|
+ sync_repl.get_result()
|
||||||
|
+ sync_repl.join()
|
||||||
|
+ log.info('test_sync_repl_dynamic_plugin: PASS\n')
|
||||||
|
+
|
||||||
|
+ # Success
|
||||||
|
+ log.info('Test complete')
|
||||||
|
+
|
||||||
|
def test_sync_repl_invalid_cookie(topology, request):
|
||||||
|
"""Test sync_repl with invalid cookie
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/plugins/sync/sync_persist.c b/ldap/servers/plugins/sync/sync_persist.c
|
||||||
|
index d2210b64c..283607361 100644
|
||||||
|
--- a/ldap/servers/plugins/sync/sync_persist.c
|
||||||
|
+++ b/ldap/servers/plugins/sync/sync_persist.c
|
||||||
|
@@ -156,6 +156,17 @@ ignore_op_pl(Slapi_PBlock *pb)
|
||||||
|
* This is the same for ident
|
||||||
|
*/
|
||||||
|
prim_op = get_thread_primary_op();
|
||||||
|
+ if (prim_op == NULL) {
|
||||||
|
+ /* This can happen if the PRE_OP (sync_update_persist_betxn_pre_op) was not called.
|
||||||
|
+ * The only known case it happens is with dynamic plugin enabled and an
|
||||||
|
+ * update that enable the sync_repl plugin. In such case sync_repl registers
|
||||||
|
+ * the postop (sync_update_persist_op) that is called while the preop was not called
|
||||||
|
+ */
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "ignore_op_pl - Operation without primary op set (0x%lx)\n",
|
||||||
|
+ (ulong) op);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
ident = sync_persist_get_operation_extension(pb);
|
||||||
|
|
||||||
|
if (ident) {
|
||||||
|
@@ -232,8 +243,18 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber
|
||||||
|
|
||||||
|
|
||||||
|
prim_op = get_thread_primary_op();
|
||||||
|
+ if (prim_op == NULL) {
|
||||||
|
+ /* This can happen if the PRE_OP (sync_update_persist_betxn_pre_op) was not called.
|
||||||
|
+ * The only known case it happens is with dynamic plugin enabled and an
|
||||||
|
+ * update that enable the sync_repl plugin. In such case sync_repl registers
|
||||||
|
+ * the postop (sync_update_persist_op) that is called while the preop was not called
|
||||||
|
+ */
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "sync_update_persist_op - Operation without primary op set (0x%lx)\n",
|
||||||
|
+ (ulong) pb_op);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
ident = sync_persist_get_operation_extension(pb);
|
||||||
|
- PR_ASSERT(prim_op);
|
||||||
|
|
||||||
|
if ((ident == NULL) && operation_is_flag_set(pb_op, OP_FLAG_NOOP)) {
|
||||||
|
/* This happens for URP (add cenotaph, fixup rename, tombstone resurrect)
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,840 @@
|
|||||||
|
From 8dc61a176323f0d41df730abd715ccff3034c2be Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
Date: Sun, 27 Nov 2022 09:37:19 -0500
|
||||||
|
Subject: [PATCH] Issue 5547 - automember plugin improvements
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Rebuild task has the following improvements:
|
||||||
|
|
||||||
|
- Only one task allowed at a time
|
||||||
|
- Do not cleanup previous members by default. Add new CLI option to intentionally
|
||||||
|
cleanup memberships before rebuilding from scratch.
|
||||||
|
- Add better task logging to show fixup progress
|
||||||
|
|
||||||
|
To prevent automember from being called in a nested be_txn loop thread storage is
|
||||||
|
used to check and skip these loops.
|
||||||
|
|
||||||
|
relates: https://github.com/389ds/389-ds-base/issues/5547
|
||||||
|
|
||||||
|
Reviewed by: spichugi(Thanks!)
|
||||||
|
---
|
||||||
|
.../automember_plugin/automember_mod_test.py | 43 +++-
|
||||||
|
ldap/servers/plugins/automember/automember.c | 232 ++++++++++++++----
|
||||||
|
ldap/servers/slapd/back-ldbm/ldbm_add.c | 11 +-
|
||||||
|
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 10 +-
|
||||||
|
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 11 +-
|
||||||
|
.../lib389/cli_conf/plugins/automember.py | 10 +-
|
||||||
|
src/lib389/lib389/plugins.py | 7 +-
|
||||||
|
src/lib389/lib389/tasks.py | 9 +-
|
||||||
|
8 files changed, 250 insertions(+), 83 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py b/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py
|
||||||
|
index 8d25384bf..7a0ed3275 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py
|
||||||
|
@@ -5,12 +5,13 @@
|
||||||
|
# License: GPL (version 3 or any later version).
|
||||||
|
# See LICENSE for details.
|
||||||
|
# --- END COPYRIGHT BLOCK ---
|
||||||
|
-#
|
||||||
|
+import ldap
|
||||||
|
import logging
|
||||||
|
import pytest
|
||||||
|
import os
|
||||||
|
+import time
|
||||||
|
from lib389.utils import ds_is_older
|
||||||
|
-from lib389._constants import *
|
||||||
|
+from lib389._constants import DEFAULT_SUFFIX
|
||||||
|
from lib389.plugins import AutoMembershipPlugin, AutoMembershipDefinitions
|
||||||
|
from lib389.idm.user import UserAccounts
|
||||||
|
from lib389.idm.group import Groups
|
||||||
|
@@ -41,6 +42,11 @@ def automember_fixture(topo, request):
|
||||||
|
user_accts = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
|
||||||
|
user = user_accts.create_test_user()
|
||||||
|
|
||||||
|
+ # Create extra users
|
||||||
|
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ for i in range(0, 100):
|
||||||
|
+ users.create_test_user(uid=i)
|
||||||
|
+
|
||||||
|
# Create automember definitions and regex rules
|
||||||
|
automember_prop = {
|
||||||
|
'cn': 'testgroup_definition',
|
||||||
|
@@ -59,7 +65,7 @@ def automember_fixture(topo, request):
|
||||||
|
automemberplugin.enable()
|
||||||
|
topo.standalone.restart()
|
||||||
|
|
||||||
|
- return (user, groups)
|
||||||
|
+ return user, groups
|
||||||
|
|
||||||
|
|
||||||
|
def test_mods(automember_fixture, topo):
|
||||||
|
@@ -72,19 +78,21 @@ def test_mods(automember_fixture, topo):
|
||||||
|
2. Update user that should add it to group[1]
|
||||||
|
3. Update user that should add it to group[2]
|
||||||
|
4. Update user that should add it to group[0]
|
||||||
|
- 5. Test rebuild task correctly moves user to group[1]
|
||||||
|
+ 5. Test rebuild task adds user to group[1]
|
||||||
|
+ 6. Test rebuild task cleanups groups and only adds it to group[1]
|
||||||
|
:expectedresults:
|
||||||
|
1. Success
|
||||||
|
2. Success
|
||||||
|
3. Success
|
||||||
|
4. Success
|
||||||
|
5. Success
|
||||||
|
+ 6. Success
|
||||||
|
"""
|
||||||
|
(user, groups) = automember_fixture
|
||||||
|
|
||||||
|
# Update user which should go into group[0]
|
||||||
|
user.replace('cn', 'whatever')
|
||||||
|
- groups[0].is_member(user.dn)
|
||||||
|
+ assert groups[0].is_member(user.dn)
|
||||||
|
if groups[1].is_member(user.dn):
|
||||||
|
assert False
|
||||||
|
if groups[2].is_member(user.dn):
|
||||||
|
@@ -92,7 +100,7 @@ def test_mods(automember_fixture, topo):
|
||||||
|
|
||||||
|
# Update user0 which should go into group[1]
|
||||||
|
user.replace('cn', 'mark')
|
||||||
|
- groups[1].is_member(user.dn)
|
||||||
|
+ assert groups[1].is_member(user.dn)
|
||||||
|
if groups[0].is_member(user.dn):
|
||||||
|
assert False
|
||||||
|
if groups[2].is_member(user.dn):
|
||||||
|
@@ -100,7 +108,7 @@ def test_mods(automember_fixture, topo):
|
||||||
|
|
||||||
|
# Update user which should go into group[2]
|
||||||
|
user.replace('cn', 'simon')
|
||||||
|
- groups[2].is_member(user.dn)
|
||||||
|
+ assert groups[2].is_member(user.dn)
|
||||||
|
if groups[0].is_member(user.dn):
|
||||||
|
assert False
|
||||||
|
if groups[1].is_member(user.dn):
|
||||||
|
@@ -108,7 +116,7 @@ def test_mods(automember_fixture, topo):
|
||||||
|
|
||||||
|
# Update user which should go back into group[0] (full circle)
|
||||||
|
user.replace('cn', 'whatever')
|
||||||
|
- groups[0].is_member(user.dn)
|
||||||
|
+ assert groups[0].is_member(user.dn)
|
||||||
|
if groups[1].is_member(user.dn):
|
||||||
|
assert False
|
||||||
|
if groups[2].is_member(user.dn):
|
||||||
|
@@ -128,12 +136,24 @@ def test_mods(automember_fixture, topo):
|
||||||
|
automemberplugin.enable()
|
||||||
|
topo.standalone.restart()
|
||||||
|
|
||||||
|
- # Run rebuild task
|
||||||
|
+ # Run rebuild task (no cleanup)
|
||||||
|
task = automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=posixaccount")
|
||||||
|
+ with pytest.raises(ldap.UNWILLING_TO_PERFORM):
|
||||||
|
+ # test only one fixup task is allowed at a time
|
||||||
|
+ automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=top")
|
||||||
|
task.wait()
|
||||||
|
|
||||||
|
- # Test membership
|
||||||
|
- groups[1].is_member(user.dn)
|
||||||
|
+ # Test membership (user should still be in groups[0])
|
||||||
|
+ assert groups[1].is_member(user.dn)
|
||||||
|
+ if not groups[0].is_member(user.dn):
|
||||||
|
+ assert False
|
||||||
|
+
|
||||||
|
+ # Run rebuild task with cleanup
|
||||||
|
+ task = automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=posixaccount", cleanup=True)
|
||||||
|
+ task.wait()
|
||||||
|
+
|
||||||
|
+ # Test membership (user should only be in groups[1])
|
||||||
|
+ assert groups[1].is_member(user.dn)
|
||||||
|
if groups[0].is_member(user.dn):
|
||||||
|
assert False
|
||||||
|
if groups[2].is_member(user.dn):
|
||||||
|
@@ -148,4 +168,3 @@ if __name__ == '__main__':
|
||||||
|
# -s for DEBUG mode
|
||||||
|
CURRENT_FILE = os.path.realpath(__file__)
|
||||||
|
pytest.main(["-s", CURRENT_FILE])
|
||||||
|
-
|
||||||
|
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
|
||||||
|
index 3494d0343..419adb052 100644
|
||||||
|
--- a/ldap/servers/plugins/automember/automember.c
|
||||||
|
+++ b/ldap/servers/plugins/automember/automember.c
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
/** BEGIN COPYRIGHT BLOCK
|
||||||
|
- * Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
+ * Copyright (C) 2022 Red Hat, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* License: GPL (version 3 or any later version).
|
||||||
|
@@ -14,7 +14,7 @@
|
||||||
|
* Auto Membership Plug-in
|
||||||
|
*/
|
||||||
|
#include "automember.h"
|
||||||
|
-
|
||||||
|
+#include <pthread.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plug-in globals
|
||||||
|
@@ -22,7 +22,9 @@
|
||||||
|
static PRCList *g_automember_config = NULL;
|
||||||
|
static Slapi_RWLock *g_automember_config_lock = NULL;
|
||||||
|
static uint64_t abort_rebuild_task = 0;
|
||||||
|
-
|
||||||
|
+static pthread_key_t td_automem_block_nested;
|
||||||
|
+static PRBool fixup_running = PR_FALSE;
|
||||||
|
+static PRLock *fixup_lock = NULL;
|
||||||
|
static void *_PluginID = NULL;
|
||||||
|
static Slapi_DN *_PluginDN = NULL;
|
||||||
|
static Slapi_DN *_ConfigAreaDN = NULL;
|
||||||
|
@@ -93,9 +95,43 @@ static void automember_task_export_destructor(Slapi_Task *task);
|
||||||
|
static void automember_task_map_destructor(Slapi_Task *task);
|
||||||
|
|
||||||
|
#define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR
|
||||||
|
+#define FIXUP_PROGRESS_LIMIT 1000
|
||||||
|
static uint64_t plugin_do_modify = 0;
|
||||||
|
static uint64_t plugin_is_betxn = 0;
|
||||||
|
|
||||||
|
+/* automember_plugin fixup task and add operations should block other be_txn
|
||||||
|
+ * plugins from calling automember_post_op_mod() */
|
||||||
|
+static int32_t
|
||||||
|
+slapi_td_block_nested_post_op(void)
|
||||||
|
+{
|
||||||
|
+ int32_t val = 12345;
|
||||||
|
+
|
||||||
|
+ if (pthread_setspecific(td_automem_block_nested, (void *)&val) != 0) {
|
||||||
|
+ return PR_FAILURE;
|
||||||
|
+ }
|
||||||
|
+ return PR_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int32_t
|
||||||
|
+slapi_td_unblock_nested_post_op(void)
|
||||||
|
+{
|
||||||
|
+ if (pthread_setspecific(td_automem_block_nested, NULL) != 0) {
|
||||||
|
+ return PR_FAILURE;
|
||||||
|
+ }
|
||||||
|
+ return PR_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int32_t
|
||||||
|
+slapi_td_is_post_op_nested(void)
|
||||||
|
+{
|
||||||
|
+ int32_t *value = pthread_getspecific(td_automem_block_nested);
|
||||||
|
+
|
||||||
|
+ if (value == NULL) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Config cache locking functions
|
||||||
|
*/
|
||||||
|
@@ -317,6 +353,14 @@ automember_start(Slapi_PBlock *pb)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (fixup_lock == NULL) {
|
||||||
|
+ if ((fixup_lock = PR_NewLock()) == NULL) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_start - Failed to create fixup lock.\n");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Get the plug-in target dn from the system
|
||||||
|
* and store it for future use. */
|
||||||
|
@@ -360,6 +404,11 @@ automember_start(Slapi_PBlock *pb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (pthread_key_create(&td_automem_block_nested, NULL) != 0) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_start - pthread_key_create failed\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"automember_start - ready for service\n");
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
@@ -394,6 +443,8 @@ automember_close(Slapi_PBlock *pb __attribute__((unused)))
|
||||||
|
slapi_sdn_free(&_ConfigAreaDN);
|
||||||
|
slapi_destroy_rwlock(g_automember_config_lock);
|
||||||
|
g_automember_config_lock = NULL;
|
||||||
|
+ PR_DestroyLock(fixup_lock);
|
||||||
|
+ fixup_lock = NULL;
|
||||||
|
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"<-- automember_close\n");
|
||||||
|
@@ -1619,7 +1670,6 @@ out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* automember_update_member_value()
|
||||||
|
*
|
||||||
|
@@ -1634,7 +1684,7 @@ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char
|
||||||
|
LDAPMod *mods[2];
|
||||||
|
char *vals[2];
|
||||||
|
char *member_value = NULL;
|
||||||
|
- int rc = 0;
|
||||||
|
+ int rc = LDAP_SUCCESS;
|
||||||
|
Slapi_DN *group_sdn;
|
||||||
|
|
||||||
|
/* First thing check that the group still exists */
|
||||||
|
@@ -1653,7 +1703,7 @@ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char
|
||||||
|
"automember_update_member_value - group (default or target) can not be retrieved (%s) err=%d\n",
|
||||||
|
group_dn, rc);
|
||||||
|
}
|
||||||
|
- return rc;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If grouping_value is dn, we need to fetch the dn instead. */
|
||||||
|
@@ -1879,6 +1929,13 @@ automember_mod_post_op(Slapi_PBlock *pb)
|
||||||
|
PRCList *list = NULL;
|
||||||
|
int rc = SLAPI_PLUGIN_SUCCESS;
|
||||||
|
|
||||||
|
+ if (slapi_td_is_post_op_nested()) {
|
||||||
|
+ /* don't process op twice in the same thread */
|
||||||
|
+ return rc;
|
||||||
|
+ } else {
|
||||||
|
+ slapi_td_block_nested_post_op();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"--> automember_mod_post_op\n");
|
||||||
|
|
||||||
|
@@ -2005,6 +2062,7 @@ automember_mod_post_op(Slapi_PBlock *pb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ slapi_td_unblock_nested_post_op();
|
||||||
|
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"<-- automember_mod_post_op (%d)\n", rc);
|
||||||
|
@@ -2024,6 +2082,13 @@ automember_add_post_op(Slapi_PBlock *pb)
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"--> automember_add_post_op\n");
|
||||||
|
|
||||||
|
+ if (slapi_td_is_post_op_nested()) {
|
||||||
|
+ /* don't process op twice in the same thread */
|
||||||
|
+ return rc;
|
||||||
|
+ } else {
|
||||||
|
+ slapi_td_block_nested_post_op();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Reload config if a config entry was added. */
|
||||||
|
if ((sdn = automember_get_sdn(pb))) {
|
||||||
|
if (automember_dn_is_config(sdn)) {
|
||||||
|
@@ -2039,7 +2104,7 @@ automember_add_post_op(Slapi_PBlock *pb)
|
||||||
|
|
||||||
|
/* If replication, just bail. */
|
||||||
|
if (automember_isrepl(pb)) {
|
||||||
|
- return SLAPI_PLUGIN_SUCCESS;
|
||||||
|
+ goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the newly added entry. */
|
||||||
|
@@ -2052,7 +2117,7 @@ automember_add_post_op(Slapi_PBlock *pb)
|
||||||
|
tombstone);
|
||||||
|
slapi_value_free(&tombstone);
|
||||||
|
if (is_tombstone) {
|
||||||
|
- return SLAPI_PLUGIN_SUCCESS;
|
||||||
|
+ goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a config entry applies
|
||||||
|
@@ -2063,21 +2128,19 @@ automember_add_post_op(Slapi_PBlock *pb)
|
||||||
|
list = PR_LIST_HEAD(g_automember_config);
|
||||||
|
while (list != g_automember_config) {
|
||||||
|
config = (struct configEntry *)list;
|
||||||
|
-
|
||||||
|
/* Does the entry meet scope and filter requirements? */
|
||||||
|
if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), config->scope) &&
|
||||||
|
- (slapi_filter_test_simple(e, config->filter) == 0)) {
|
||||||
|
+ (slapi_filter_test_simple(e, config->filter) == 0))
|
||||||
|
+ {
|
||||||
|
/* Find out what membership changes are needed and make them. */
|
||||||
|
if (automember_update_membership(config, e, NULL) == SLAPI_PLUGIN_FAILURE) {
|
||||||
|
rc = SLAPI_PLUGIN_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
list = PR_NEXT_LINK(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
automember_config_unlock();
|
||||||
|
} else {
|
||||||
|
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
@@ -2098,6 +2161,7 @@ bail:
|
||||||
|
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &result);
|
||||||
|
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, &errtxt);
|
||||||
|
}
|
||||||
|
+ slapi_td_unblock_nested_post_op();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@@ -2138,6 +2202,7 @@ typedef struct _task_data
|
||||||
|
Slapi_DN *base_dn;
|
||||||
|
char *bind_dn;
|
||||||
|
int scope;
|
||||||
|
+ PRBool cleanup;
|
||||||
|
} task_data;
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -2270,6 +2335,7 @@ automember_task_abort_thread(void *arg)
|
||||||
|
* basedn: dc=example,dc=com
|
||||||
|
* filter: (uid=*)
|
||||||
|
* scope: sub
|
||||||
|
+ * cleanup: yes/on (default is off)
|
||||||
|
*
|
||||||
|
* basedn and filter are required. If scope is omitted, the default is sub
|
||||||
|
*/
|
||||||
|
@@ -2284,9 +2350,22 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr
|
||||||
|
const char *base_dn;
|
||||||
|
const char *filter;
|
||||||
|
const char *scope;
|
||||||
|
+ const char *cleanup_str;
|
||||||
|
+ PRBool cleanup = PR_FALSE;
|
||||||
|
|
||||||
|
*returncode = LDAP_SUCCESS;
|
||||||
|
|
||||||
|
+ PR_Lock(fixup_lock);
|
||||||
|
+ if (fixup_running) {
|
||||||
|
+ PR_Unlock(fixup_lock);
|
||||||
|
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_task_add - there is already a fixup task running\n");
|
||||||
|
+ rv = SLAPI_DSE_CALLBACK_ERROR;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ PR_Unlock(fixup_lock);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Grab the task params
|
||||||
|
*/
|
||||||
|
@@ -2300,6 +2379,12 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr
|
||||||
|
rv = SLAPI_DSE_CALLBACK_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+ if ((cleanup_str = slapi_entry_attr_get_ref(e, "cleanup"))) {
|
||||||
|
+ if (strcasecmp(cleanup_str, "yes") == 0 || strcasecmp(cleanup_str, "on")) {
|
||||||
|
+ cleanup = PR_TRUE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
scope = slapi_fetch_attr(e, "scope", "sub");
|
||||||
|
/*
|
||||||
|
* setup our task data
|
||||||
|
@@ -2315,6 +2400,7 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr
|
||||||
|
mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
|
||||||
|
mytaskdata->base_dn = slapi_sdn_new_dn_byval(base_dn);
|
||||||
|
mytaskdata->filter_str = slapi_ch_strdup(filter);
|
||||||
|
+ mytaskdata->cleanup = cleanup;
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
if (strcasecmp(scope, "sub") == 0) {
|
||||||
|
@@ -2334,6 +2420,9 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr
|
||||||
|
task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg);
|
||||||
|
slapi_task_set_destructor_fn(task, automember_task_destructor);
|
||||||
|
slapi_task_set_data(task, mytaskdata);
|
||||||
|
+ PR_Lock(fixup_lock);
|
||||||
|
+ fixup_running = PR_TRUE;
|
||||||
|
+ PR_Unlock(fixup_lock);
|
||||||
|
/*
|
||||||
|
* Start the task as a separate thread
|
||||||
|
*/
|
||||||
|
@@ -2345,6 +2434,9 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr
|
||||||
|
"automember_task_add - Unable to create task thread!\n");
|
||||||
|
*returncode = LDAP_OPERATIONS_ERROR;
|
||||||
|
slapi_task_finish(task, *returncode);
|
||||||
|
+ PR_Lock(fixup_lock);
|
||||||
|
+ fixup_running = PR_FALSE;
|
||||||
|
+ PR_Unlock(fixup_lock);
|
||||||
|
rv = SLAPI_DSE_CALLBACK_ERROR;
|
||||||
|
} else {
|
||||||
|
rv = SLAPI_DSE_CALLBACK_OK;
|
||||||
|
@@ -2372,6 +2464,9 @@ automember_rebuild_task_thread(void *arg)
|
||||||
|
PRCList *list = NULL;
|
||||||
|
PRCList *include_list = NULL;
|
||||||
|
int result = 0;
|
||||||
|
+ int64_t fixup_progress_count = 0;
|
||||||
|
+ int64_t fixup_progress_elapsed = 0;
|
||||||
|
+ int64_t fixup_start_time = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
/* Reset abort flag */
|
||||||
|
@@ -2380,6 +2475,7 @@ automember_rebuild_task_thread(void *arg)
|
||||||
|
if (!task) {
|
||||||
|
return; /* no task */
|
||||||
|
}
|
||||||
|
+
|
||||||
|
slapi_task_inc_refcount(task);
|
||||||
|
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"automember_rebuild_task_thread - Refcount incremented.\n");
|
||||||
|
@@ -2393,9 +2489,11 @@ automember_rebuild_task_thread(void *arg)
|
||||||
|
slapi_task_log_status(task, "Automember rebuild task starting (base dn: (%s) filter (%s)...",
|
||||||
|
slapi_sdn_get_dn(td->base_dn), td->filter_str);
|
||||||
|
/*
|
||||||
|
- * Set the bind dn in the local thread data
|
||||||
|
+ * Set the bind dn in the local thread data, and block post op mods
|
||||||
|
*/
|
||||||
|
slapi_td_set_dn(slapi_ch_strdup(td->bind_dn));
|
||||||
|
+ slapi_td_block_nested_post_op();
|
||||||
|
+ fixup_start_time = slapi_current_rel_time_t();
|
||||||
|
/*
|
||||||
|
* Take the config lock now and search the database
|
||||||
|
*/
|
||||||
|
@@ -2426,6 +2524,21 @@ automember_rebuild_task_thread(void *arg)
|
||||||
|
* Loop over the entries
|
||||||
|
*/
|
||||||
|
for (i = 0; entries && (entries[i] != NULL); i++) {
|
||||||
|
+ fixup_progress_count++;
|
||||||
|
+ if (fixup_progress_count % FIXUP_PROGRESS_LIMIT == 0 ) {
|
||||||
|
+ slapi_task_log_notice(task,
|
||||||
|
+ "Processed %ld entries in %ld seconds (+%ld seconds)",
|
||||||
|
+ fixup_progress_count,
|
||||||
|
+ slapi_current_rel_time_t() - fixup_start_time,
|
||||||
|
+ slapi_current_rel_time_t() - fixup_progress_elapsed);
|
||||||
|
+ slapi_task_log_status(task,
|
||||||
|
+ "Processed %ld entries in %ld seconds (+%ld seconds)",
|
||||||
|
+ fixup_progress_count,
|
||||||
|
+ slapi_current_rel_time_t() - fixup_start_time,
|
||||||
|
+ slapi_current_rel_time_t() - fixup_progress_elapsed);
|
||||||
|
+ slapi_task_inc_progress(task);
|
||||||
|
+ fixup_progress_elapsed = slapi_current_rel_time_t();
|
||||||
|
+ }
|
||||||
|
if (slapi_atomic_load_64(&abort_rebuild_task, __ATOMIC_ACQUIRE) == 1) {
|
||||||
|
/* The task was aborted */
|
||||||
|
slapi_task_log_notice(task, "Automember rebuild task was intentionally aborted");
|
||||||
|
@@ -2443,48 +2556,66 @@ automember_rebuild_task_thread(void *arg)
|
||||||
|
if (slapi_dn_issuffix(slapi_entry_get_dn(entries[i]), config->scope) &&
|
||||||
|
(slapi_filter_test_simple(entries[i], config->filter) == 0))
|
||||||
|
{
|
||||||
|
- /* First clear out all the defaults groups */
|
||||||
|
- for (size_t ii = 0; config->default_groups && config->default_groups[ii]; ii++) {
|
||||||
|
- if ((result = automember_update_member_value(entries[i], config->default_groups[ii],
|
||||||
|
- config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER)))
|
||||||
|
- {
|
||||||
|
- slapi_task_log_notice(task, "Automember rebuild membership task unable to delete "
|
||||||
|
- "member from default group (%s) error (%d)",
|
||||||
|
- config->default_groups[ii], result);
|
||||||
|
- slapi_task_log_status(task, "Automember rebuild membership task unable to delete "
|
||||||
|
- "member from default group (%s) error (%d)",
|
||||||
|
- config->default_groups[ii], result);
|
||||||
|
- slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
- "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n",
|
||||||
|
- config->default_groups[ii], result);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Then clear out the non-default group */
|
||||||
|
- if (config->inclusive_rules && !PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) {
|
||||||
|
- include_list = PR_LIST_HEAD((PRCList *)config->inclusive_rules);
|
||||||
|
- while (include_list != (PRCList *)config->inclusive_rules) {
|
||||||
|
- struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)include_list;
|
||||||
|
- if ((result = automember_update_member_value(entries[i], slapi_sdn_get_dn(curr_rule->target_group_dn),
|
||||||
|
- config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER)))
|
||||||
|
+ if (td->cleanup) {
|
||||||
|
+
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_rebuild_task_thread - Cleaning up groups (config %s)\n",
|
||||||
|
+ config->dn);
|
||||||
|
+ /* First clear out all the defaults groups */
|
||||||
|
+ for (size_t ii = 0; config->default_groups && config->default_groups[ii]; ii++) {
|
||||||
|
+ if ((result = automember_update_member_value(entries[i],
|
||||||
|
+ config->default_groups[ii],
|
||||||
|
+ config->grouping_attr,
|
||||||
|
+ config->grouping_value,
|
||||||
|
+ NULL, DEL_MEMBER)))
|
||||||
|
{
|
||||||
|
slapi_task_log_notice(task, "Automember rebuild membership task unable to delete "
|
||||||
|
- "member from group (%s) error (%d)",
|
||||||
|
- slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ "member from default group (%s) error (%d)",
|
||||||
|
+ config->default_groups[ii], result);
|
||||||
|
slapi_task_log_status(task, "Automember rebuild membership task unable to delete "
|
||||||
|
- "member from group (%s) error (%d)",
|
||||||
|
- slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ "member from default group (%s) error (%d)",
|
||||||
|
+ config->default_groups[ii], result);
|
||||||
|
slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
"automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n",
|
||||||
|
- slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ config->default_groups[ii], result);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- include_list = PR_NEXT_LINK(include_list);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* Then clear out the non-default group */
|
||||||
|
+ if (config->inclusive_rules && !PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) {
|
||||||
|
+ include_list = PR_LIST_HEAD((PRCList *)config->inclusive_rules);
|
||||||
|
+ while (include_list != (PRCList *)config->inclusive_rules) {
|
||||||
|
+ struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)include_list;
|
||||||
|
+ if ((result = automember_update_member_value(entries[i],
|
||||||
|
+ slapi_sdn_get_dn(curr_rule->target_group_dn),
|
||||||
|
+ config->grouping_attr,
|
||||||
|
+ config->grouping_value,
|
||||||
|
+ NULL, DEL_MEMBER)))
|
||||||
|
+ {
|
||||||
|
+ slapi_task_log_notice(task, "Automember rebuild membership task unable to delete "
|
||||||
|
+ "member from group (%s) error (%d)",
|
||||||
|
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ slapi_task_log_status(task, "Automember rebuild membership task unable to delete "
|
||||||
|
+ "member from group (%s) error (%d)",
|
||||||
|
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n",
|
||||||
|
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ include_list = PR_NEXT_LINK(include_list);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_rebuild_task_thread - Finished cleaning up groups (config %s)\n",
|
||||||
|
+ config->dn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the memberships for this entries */
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
+ "automember_rebuild_task_thread - Updating membership (config %s)\n",
|
||||||
|
+ config->dn);
|
||||||
|
if (slapi_is_shutting_down() ||
|
||||||
|
automember_update_membership(config, entries[i], NULL) == SLAPI_PLUGIN_FAILURE)
|
||||||
|
{
|
||||||
|
@@ -2508,15 +2639,22 @@ out:
|
||||||
|
slapi_task_log_notice(task, "Automember rebuild task aborted. Error (%d)", result);
|
||||||
|
slapi_task_log_status(task, "Automember rebuild task aborted. Error (%d)", result);
|
||||||
|
} else {
|
||||||
|
- slapi_task_log_notice(task, "Automember rebuild task finished. Processed (%d) entries.", (int32_t)i);
|
||||||
|
- slapi_task_log_status(task, "Automember rebuild task finished. Processed (%d) entries.", (int32_t)i);
|
||||||
|
+ slapi_task_log_notice(task, "Automember rebuild task finished. Processed (%ld) entries in %ld seconds",
|
||||||
|
+ (int64_t)i, slapi_current_rel_time_t() - fixup_start_time);
|
||||||
|
+ slapi_task_log_status(task, "Automember rebuild task finished. Processed (%ld) entries in %ld seconds",
|
||||||
|
+ (int64_t)i, slapi_current_rel_time_t() - fixup_start_time);
|
||||||
|
}
|
||||||
|
slapi_task_inc_progress(task);
|
||||||
|
slapi_task_finish(task, result);
|
||||||
|
slapi_task_dec_refcount(task);
|
||||||
|
slapi_atomic_store_64(&abort_rebuild_task, 0, __ATOMIC_RELEASE);
|
||||||
|
+ slapi_td_unblock_nested_post_op();
|
||||||
|
+ PR_Lock(fixup_lock);
|
||||||
|
+ fixup_running = PR_FALSE;
|
||||||
|
+ PR_Unlock(fixup_lock);
|
||||||
|
+
|
||||||
|
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
||||||
|
- "automember_rebuild_task_thread - Refcount decremented.\n");
|
||||||
|
+ "automember_rebuild_task_thread - task finished, refcount decremented.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
||||||
|
index ba2d73a84..ce4c314a1 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
/** BEGIN COPYRIGHT BLOCK
|
||||||
|
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
||||||
|
- * Copyright (C) 2005 Red Hat, Inc.
|
||||||
|
+ * Copyright (C) 2022 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
@@ -1264,10 +1264,6 @@ ldbm_back_add(Slapi_PBlock *pb)
|
||||||
|
goto common_return;
|
||||||
|
|
||||||
|
error_return:
|
||||||
|
- /* Revert the caches if this is the parent operation */
|
||||||
|
- if (parent_op && betxn_callback_fails) {
|
||||||
|
- revert_cache(inst, &parent_time);
|
||||||
|
- }
|
||||||
|
if (addingentry_id_assigned) {
|
||||||
|
next_id_return(be, addingentry->ep_id);
|
||||||
|
}
|
||||||
|
@@ -1376,6 +1372,11 @@ diskfull_return:
|
||||||
|
if (!not_an_error) {
|
||||||
|
rc = SLAPI_FAIL_GENERAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* Revert the caches if this is the parent operation */
|
||||||
|
+ if (parent_op && betxn_callback_fails) {
|
||||||
|
+ revert_cache(inst, &parent_time);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
common_return:
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
||||||
|
index de23190c3..27f0ac58a 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
||||||
|
@@ -1407,11 +1407,6 @@ commit_return:
|
||||||
|
goto common_return;
|
||||||
|
|
||||||
|
error_return:
|
||||||
|
- /* Revert the caches if this is the parent operation */
|
||||||
|
- if (parent_op && betxn_callback_fails) {
|
||||||
|
- revert_cache(inst, &parent_time);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (tombstone) {
|
||||||
|
if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
|
||||||
|
tomb_ep_id = tombstone->ep_id; /* Otherwise, tombstone might have been freed. */
|
||||||
|
@@ -1496,6 +1491,11 @@ error_return:
|
||||||
|
conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry, myrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Revert the caches if this is the parent operation */
|
||||||
|
+ if (parent_op && betxn_callback_fails) {
|
||||||
|
+ revert_cache(inst, &parent_time);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
common_return:
|
||||||
|
if (orig_entry) {
|
||||||
|
/* NOTE: #define SLAPI_DELETE_BEPREOP_ENTRY SLAPI_ENTRY_PRE_OP */
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
||||||
|
index 537369055..64b293001 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
/** BEGIN COPYRIGHT BLOCK
|
||||||
|
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
||||||
|
- * Copyright (C) 2005 Red Hat, Inc.
|
||||||
|
+ * Copyright (C) 2022 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
@@ -1043,11 +1043,6 @@ ldbm_back_modify(Slapi_PBlock *pb)
|
||||||
|
goto common_return;
|
||||||
|
|
||||||
|
error_return:
|
||||||
|
- /* Revert the caches if this is the parent operation */
|
||||||
|
- if (parent_op && betxn_callback_fails) {
|
||||||
|
- revert_cache(inst, &parent_time);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (postentry != NULL) {
|
||||||
|
slapi_entry_free(postentry);
|
||||||
|
postentry = NULL;
|
||||||
|
@@ -1103,6 +1098,10 @@ error_return:
|
||||||
|
if (!not_an_error) {
|
||||||
|
rc = SLAPI_FAIL_GENERAL;
|
||||||
|
}
|
||||||
|
+ /* Revert the caches if this is the parent operation */
|
||||||
|
+ if (parent_op && betxn_callback_fails) {
|
||||||
|
+ revert_cache(inst, &parent_time);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if ec is in cache, remove it, then add back e if we still have it */
|
||||||
|
diff --git a/src/lib389/lib389/cli_conf/plugins/automember.py b/src/lib389/lib389/cli_conf/plugins/automember.py
|
||||||
|
index 15b00c633..568586ad8 100644
|
||||||
|
--- a/src/lib389/lib389/cli_conf/plugins/automember.py
|
||||||
|
+++ b/src/lib389/lib389/cli_conf/plugins/automember.py
|
||||||
|
@@ -155,7 +155,7 @@ def fixup(inst, basedn, log, args):
|
||||||
|
log.info('Attempting to add task entry... This will fail if Automembership plug-in is not enabled.')
|
||||||
|
if not plugin.status():
|
||||||
|
log.error("'%s' is disabled. Rebuild membership task can't be executed" % plugin.rdn)
|
||||||
|
- fixup_task = plugin.fixup(args.DN, args.filter)
|
||||||
|
+ fixup_task = plugin.fixup(args.DN, args.filter, args.cleanup)
|
||||||
|
if args.wait:
|
||||||
|
log.info(f'Waiting for fixup task "{fixup_task.dn}" to complete. You can safely exit by pressing Control C ...')
|
||||||
|
fixup_task.wait(timeout=args.timeout)
|
||||||
|
@@ -225,8 +225,8 @@ def create_parser(subparsers):
|
||||||
|
subcommands = automember.add_subparsers(help='action')
|
||||||
|
add_generic_plugin_parsers(subcommands, AutoMembershipPlugin)
|
||||||
|
|
||||||
|
- list = subcommands.add_parser('list', help='List Automembership definitions or regex rules.')
|
||||||
|
- subcommands_list = list.add_subparsers(help='action')
|
||||||
|
+ automember_list = subcommands.add_parser('list', help='List Automembership definitions or regex rules.')
|
||||||
|
+ subcommands_list = automember_list.add_subparsers(help='action')
|
||||||
|
list_definitions = subcommands_list.add_parser('definitions', help='Lists Automembership definitions.')
|
||||||
|
list_definitions.set_defaults(func=definition_list)
|
||||||
|
list_regexes = subcommands_list.add_parser('regexes', help='List Automembership regex rules.')
|
||||||
|
@@ -269,6 +269,8 @@ def create_parser(subparsers):
|
||||||
|
fixup_task.add_argument('-f', '--filter', required=True, help='Sets the LDAP filter for entries to fix up')
|
||||||
|
fixup_task.add_argument('-s', '--scope', required=True, choices=['sub', 'base', 'one'], type=str.lower,
|
||||||
|
help='Sets the LDAP search scope for entries to fix up')
|
||||||
|
+ fixup_task.add_argument('--cleanup', action='store_true',
|
||||||
|
+ help="Clean up previous group memberships before rebuilding")
|
||||||
|
fixup_task.add_argument('--wait', action='store_true',
|
||||||
|
help="Wait for the task to finish, this could take a long time")
|
||||||
|
fixup_task.add_argument('--timeout', default=0, type=int,
|
||||||
|
@@ -279,7 +281,7 @@ def create_parser(subparsers):
|
||||||
|
fixup_status.add_argument('--dn', help="The task entry's DN")
|
||||||
|
fixup_status.add_argument('--show-log', action='store_true', help="Display the task log")
|
||||||
|
fixup_status.add_argument('--watch', action='store_true',
|
||||||
|
- help="Watch the task's status and wait for it to finish")
|
||||||
|
+ help="Watch the task's status and wait for it to finish")
|
||||||
|
|
||||||
|
abort_fixup = subcommands.add_parser('abort-fixup', help='Abort the rebuild membership task.')
|
||||||
|
abort_fixup.set_defaults(func=abort)
|
||||||
|
diff --git a/src/lib389/lib389/plugins.py b/src/lib389/lib389/plugins.py
|
||||||
|
index 52691a44c..a1ad0a45b 100644
|
||||||
|
--- a/src/lib389/lib389/plugins.py
|
||||||
|
+++ b/src/lib389/lib389/plugins.py
|
||||||
|
@@ -1141,13 +1141,15 @@ class AutoMembershipPlugin(Plugin):
|
||||||
|
def __init__(self, instance, dn="cn=Auto Membership Plugin,cn=plugins,cn=config"):
|
||||||
|
super(AutoMembershipPlugin, self).__init__(instance, dn)
|
||||||
|
|
||||||
|
- def fixup(self, basedn, _filter=None):
|
||||||
|
+ def fixup(self, basedn, _filter=None, cleanup=False):
|
||||||
|
"""Create an automember rebuild membership task
|
||||||
|
|
||||||
|
:param basedn: Basedn to fix up
|
||||||
|
:type basedn: str
|
||||||
|
:param _filter: a filter for entries to fix up
|
||||||
|
:type _filter: str
|
||||||
|
+ :param cleanup: cleanup old group memberships
|
||||||
|
+ :type cleanup: boolean
|
||||||
|
|
||||||
|
:returns: an instance of Task(DSLdapObject)
|
||||||
|
"""
|
||||||
|
@@ -1156,6 +1158,9 @@ class AutoMembershipPlugin(Plugin):
|
||||||
|
task_properties = {'basedn': basedn}
|
||||||
|
if _filter is not None:
|
||||||
|
task_properties['filter'] = _filter
|
||||||
|
+ if cleanup:
|
||||||
|
+ task_properties['cleanup'] = "yes"
|
||||||
|
+
|
||||||
|
task.create(properties=task_properties)
|
||||||
|
|
||||||
|
return task
|
||||||
|
diff --git a/src/lib389/lib389/tasks.py b/src/lib389/lib389/tasks.py
|
||||||
|
index 1a16bbb83..193805780 100644
|
||||||
|
--- a/src/lib389/lib389/tasks.py
|
||||||
|
+++ b/src/lib389/lib389/tasks.py
|
||||||
|
@@ -1006,12 +1006,13 @@ class Tasks(object):
|
||||||
|
return exitCode
|
||||||
|
|
||||||
|
def automemberRebuild(self, suffix=DEFAULT_SUFFIX, scope='sub',
|
||||||
|
- filterstr='objectclass=top', args=None):
|
||||||
|
+ filterstr='objectclass=top', cleanup=False, args=None):
|
||||||
|
'''
|
||||||
|
- @param suffix - The suffix the task should examine - defualt is
|
||||||
|
+ @param suffix - The suffix the task should examine - default is
|
||||||
|
"dc=example,dc=com"
|
||||||
|
@param scope - The scope of the search to find entries
|
||||||
|
- @param fitlerstr - THe search filter to find entries
|
||||||
|
+ @param fitlerstr - The search filter to find entries
|
||||||
|
+ @param cleanup - reset/clear the old group mmeberships prior to rebuilding
|
||||||
|
@param args - is a dictionary that contains modifier of the task
|
||||||
|
wait: True/[False] - If True, waits for the completion of
|
||||||
|
the task before to return
|
||||||
|
@@ -1027,6 +1028,8 @@ class Tasks(object):
|
||||||
|
entry.setValues('basedn', suffix)
|
||||||
|
entry.setValues('filter', filterstr)
|
||||||
|
entry.setValues('scope', scope)
|
||||||
|
+ if cleanup:
|
||||||
|
+ entry.setValues('cleanup', 'yes')
|
||||||
|
|
||||||
|
# start the task and possibly wait for task completion
|
||||||
|
try:
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,83 @@
|
|||||||
|
From 9319d5b022918f14cacb00e3faef85a6ab730a26 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon Pichugin <spichugi@redhat.com>
|
||||||
|
Date: Tue, 27 Feb 2024 16:30:47 -0800
|
||||||
|
Subject: [PATCH] Issue 3527 - Support HAProxy and Instance on the same machine
|
||||||
|
configuration (#6107)
|
||||||
|
|
||||||
|
Description: Improve how we handle HAProxy connections to work better when
|
||||||
|
the DS and HAProxy are on the same machine.
|
||||||
|
Ensure the client and header destination IPs are checked against the trusted IP list.
|
||||||
|
|
||||||
|
Additionally, this change will also allow configuration having
|
||||||
|
HAProxy is listening on a different subnet than the one used to forward the request.
|
||||||
|
|
||||||
|
Related: https://github.com/389ds/389-ds-base/issues/3527
|
||||||
|
|
||||||
|
Reviewed by: @progier389, @jchapma (Thanks!)
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/connection.c | 35 +++++++++++++++++++++++++--------
|
||||||
|
1 file changed, 27 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
|
||||||
|
index d28a39bf7..10a8cc577 100644
|
||||||
|
--- a/ldap/servers/slapd/connection.c
|
||||||
|
+++ b/ldap/servers/slapd/connection.c
|
||||||
|
@@ -1187,6 +1187,8 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int *
|
||||||
|
char str_ip[INET6_ADDRSTRLEN + 1] = {0};
|
||||||
|
char str_haproxy_ip[INET6_ADDRSTRLEN + 1] = {0};
|
||||||
|
char str_haproxy_destip[INET6_ADDRSTRLEN + 1] = {0};
|
||||||
|
+ int trusted_matches_ip_found = 0;
|
||||||
|
+ int trusted_matches_destip_found = 0;
|
||||||
|
struct berval **bvals = NULL;
|
||||||
|
int proxy_connection = 0;
|
||||||
|
|
||||||
|
@@ -1245,21 +1247,38 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int *
|
||||||
|
normalize_IPv4(conn->cin_addr, buf_ip, sizeof(buf_ip), str_ip, sizeof(str_ip));
|
||||||
|
normalize_IPv4(&pr_netaddr_dest, buf_haproxy_destip, sizeof(buf_haproxy_destip),
|
||||||
|
str_haproxy_destip, sizeof(str_haproxy_destip));
|
||||||
|
+ size_t ip_len = strlen(buf_ip);
|
||||||
|
+ size_t destip_len = strlen(buf_haproxy_destip);
|
||||||
|
|
||||||
|
/* Now, reset RC and set it to 0 only if a match is found */
|
||||||
|
haproxy_rc = -1;
|
||||||
|
|
||||||
|
- /* Allow only:
|
||||||
|
- * Trusted IP == Original Client IP == HAProxy Header Destination IP */
|
||||||
|
+ /*
|
||||||
|
+ * We need to allow a configuration where DS instance and HAProxy are on the same machine.
|
||||||
|
+ * In this case, we need to check if
|
||||||
|
+ * the HAProxy client IP (which will be a loopback address) matches one of the the trusted IP addresses,
|
||||||
|
+ * while still checking that
|
||||||
|
+ * the HAProxy header destination IP address matches one of the trusted IP addresses.
|
||||||
|
+ * Additionally, this change will also allow configuration having
|
||||||
|
+ * HAProxy listening on a different subnet than one used to forward the request.
|
||||||
|
+ */
|
||||||
|
for (size_t i = 0; bvals[i] != NULL; ++i) {
|
||||||
|
- if ((strlen(bvals[i]->bv_val) == strlen(buf_ip)) &&
|
||||||
|
- (strlen(bvals[i]->bv_val) == strlen(buf_haproxy_destip)) &&
|
||||||
|
- (strncasecmp(bvals[i]->bv_val, buf_ip, strlen(buf_ip)) == 0) &&
|
||||||
|
- (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, strlen(buf_haproxy_destip)) == 0)) {
|
||||||
|
- haproxy_rc = 0;
|
||||||
|
- break;
|
||||||
|
+ size_t bval_len = strlen(bvals[i]->bv_val);
|
||||||
|
+
|
||||||
|
+ /* Check if the Client IP (HAProxy's machine IP) address matches the trusted IP address */
|
||||||
|
+ if (!trusted_matches_ip_found) {
|
||||||
|
+ trusted_matches_ip_found = (bval_len == ip_len) && (strncasecmp(bvals[i]->bv_val, buf_ip, ip_len) == 0);
|
||||||
|
+ }
|
||||||
|
+ /* Check if the HAProxy header destination IP address matches the trusted IP address */
|
||||||
|
+ if (!trusted_matches_destip_found) {
|
||||||
|
+ trusted_matches_destip_found = (bval_len == destip_len) && (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, destip_len) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (trusted_matches_ip_found && trusted_matches_destip_found) {
|
||||||
|
+ haproxy_rc = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (haproxy_rc == -1) {
|
||||||
|
slapi_log_err(SLAPI_LOG_CONNS, "connection_read_operation", "HAProxy header received from unknown source.\n");
|
||||||
|
disconnect_server_nomutex(conn, conn->c_connid, -1, SLAPD_DISCONNECT_PROXY_UNKNOWN, EPROTO);
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,108 @@
|
|||||||
|
From 016a2b6bd3e27cbff36609824a75b020dfd24823 Mon Sep 17 00:00:00 2001
|
||||||
|
From: James Chapman <jachapma@redhat.com>
|
||||||
|
Date: Wed, 1 May 2024 15:01:33 +0100
|
||||||
|
Subject: [PATCH] CVE-2024-2199
|
||||||
|
|
||||||
|
---
|
||||||
|
.../tests/suites/password/password_test.py | 56 +++++++++++++++++++
|
||||||
|
ldap/servers/slapd/modify.c | 8 ++-
|
||||||
|
2 files changed, 62 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/password/password_test.py b/dirsrvtests/tests/suites/password/password_test.py
|
||||||
|
index 38079476a..b3ff08904 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/password/password_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/password/password_test.py
|
||||||
|
@@ -65,6 +65,62 @@ def test_password_delete_specific_password(topology_st):
|
||||||
|
log.info('test_password_delete_specific_password: PASSED')
|
||||||
|
|
||||||
|
|
||||||
|
+def test_password_modify_non_utf8(topology_st):
|
||||||
|
+ """Attempt a modify of the userPassword attribute with
|
||||||
|
+ an invalid non utf8 value
|
||||||
|
+
|
||||||
|
+ :id: a31af9d5-d665-42b9-8d6e-fea3d0837d36
|
||||||
|
+ :setup: Standalone instance
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Add a user if it doesnt exist and set its password
|
||||||
|
+ 2. Verify password with a bind
|
||||||
|
+ 3. Modify userPassword attr with invalid value
|
||||||
|
+ 4. Attempt a bind with invalid password value
|
||||||
|
+ 5. Verify original password with a bind
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. The user with userPassword should be added successfully
|
||||||
|
+ 2. Operation should be successful
|
||||||
|
+ 3. Server returns ldap.UNWILLING_TO_PERFORM
|
||||||
|
+ 4. Server returns ldap.INVALID_CREDENTIALS
|
||||||
|
+ 5. Operation should be successful
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ log.info('Running test_password_modify_non_utf8...')
|
||||||
|
+
|
||||||
|
+ # Create user and set password
|
||||||
|
+ standalone = topology_st.standalone
|
||||||
|
+ users = UserAccounts(standalone, DEFAULT_SUFFIX)
|
||||||
|
+ if not users.exists(TEST_USER_PROPERTIES['uid'][0]):
|
||||||
|
+ user = users.create(properties=TEST_USER_PROPERTIES)
|
||||||
|
+ else:
|
||||||
|
+ user = users.get(TEST_USER_PROPERTIES['uid'][0])
|
||||||
|
+ user.set('userpassword', PASSWORD)
|
||||||
|
+
|
||||||
|
+ # Verify password
|
||||||
|
+ try:
|
||||||
|
+ user.bind(PASSWORD)
|
||||||
|
+ except ldap.LDAPError as e:
|
||||||
|
+ log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc'])
|
||||||
|
+ assert False
|
||||||
|
+
|
||||||
|
+ # Modify userPassword with an invalid value
|
||||||
|
+ password = b'tes\x82t-password' # A non UTF-8 encoded password
|
||||||
|
+ with pytest.raises(ldap.UNWILLING_TO_PERFORM):
|
||||||
|
+ user.replace('userpassword', password)
|
||||||
|
+
|
||||||
|
+ # Verify a bind fails with invalid pasword
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ user.bind(password)
|
||||||
|
+
|
||||||
|
+ # Verify we can still bind with original password
|
||||||
|
+ try:
|
||||||
|
+ user.bind(PASSWORD)
|
||||||
|
+ except ldap.LDAPError as e:
|
||||||
|
+ log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc'])
|
||||||
|
+ assert False
|
||||||
|
+
|
||||||
|
+ log.info('test_password_modify_non_utf8: PASSED')
|
||||||
|
+
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Run isolated
|
||||||
|
# -s for DEBUG mode
|
||||||
|
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
|
||||||
|
index 5ca78539c..669bb104c 100644
|
||||||
|
--- a/ldap/servers/slapd/modify.c
|
||||||
|
+++ b/ldap/servers/slapd/modify.c
|
||||||
|
@@ -765,8 +765,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
|
||||||
|
* flagged - leave mod attributes alone */
|
||||||
|
if (!repl_op && !skip_modified_attrs && lastmod) {
|
||||||
|
modify_update_last_modified_attr(pb, &smods);
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_MODIFY_MODS, slapi_mods_get_ldapmods_byref(&smods));
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
if (0 == slapi_mods_get_num_mods(&smods)) {
|
||||||
|
/* nothing to do - no mods - this is not an error - just
|
||||||
|
send back LDAP_SUCCESS */
|
||||||
|
@@ -933,8 +935,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
|
||||||
|
|
||||||
|
/* encode password */
|
||||||
|
if (pw_encodevals_ext(pb, sdn, va)) {
|
||||||
|
- slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s.\n", slapi_entry_get_dn_const(e));
|
||||||
|
- send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to store attribute \"userPassword\" correctly\n", 0, NULL);
|
||||||
|
+ slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s, "
|
||||||
|
+ "check value is utf8 string.\n", slapi_entry_get_dn_const(e));
|
||||||
|
+ send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to hash \"userPassword\" attribute, "
|
||||||
|
+ "check value is utf8 string.\n", 0, NULL);
|
||||||
|
valuearray_free(&va);
|
||||||
|
goto free_and_return;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,213 @@
|
|||||||
|
From d5bbe52fbe84a7d3b5938bf82d5c4af15061a8e2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre Rogier <progier@redhat.com>
|
||||||
|
Date: Wed, 17 Apr 2024 18:18:04 +0200
|
||||||
|
Subject: [PATCH] CVE-2024-3657
|
||||||
|
|
||||||
|
---
|
||||||
|
.../tests/suites/filter/large_filter_test.py | 34 +++++-
|
||||||
|
ldap/servers/slapd/back-ldbm/index.c | 111 ++++++++++--------
|
||||||
|
2 files changed, 92 insertions(+), 53 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/filter/large_filter_test.py b/dirsrvtests/tests/suites/filter/large_filter_test.py
|
||||||
|
index ecc7bf979..40526bb16 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/filter/large_filter_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/filter/large_filter_test.py
|
||||||
|
@@ -13,19 +13,29 @@ verify and testing Filter from a search
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
+import ldap
|
||||||
|
|
||||||
|
-from lib389._constants import PW_DM
|
||||||
|
+from lib389._constants import PW_DM, DEFAULT_SUFFIX, ErrorLog
|
||||||
|
from lib389.topologies import topology_st as topo
|
||||||
|
from lib389.idm.user import UserAccounts, UserAccount
|
||||||
|
from lib389.idm.account import Accounts
|
||||||
|
from lib389.backend import Backends
|
||||||
|
from lib389.idm.domain import Domain
|
||||||
|
+from lib389.utils import get_ldapurl_from_serverid
|
||||||
|
|
||||||
|
SUFFIX = 'dc=anuj,dc=com'
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.tier1
|
||||||
|
|
||||||
|
|
||||||
|
+def open_new_ldapi_conn(dsinstance):
|
||||||
|
+ ldapurl, certdir = get_ldapurl_from_serverid(dsinstance)
|
||||||
|
+ assert 'ldapi://' in ldapurl
|
||||||
|
+ conn = ldap.initialize(ldapurl)
|
||||||
|
+ conn.sasl_interactive_bind_s("", ldap.sasl.external())
|
||||||
|
+ return conn
|
||||||
|
+
|
||||||
|
+
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def _create_entries(request, topo):
|
||||||
|
"""
|
||||||
|
@@ -160,6 +170,28 @@ def test_large_filter(topo, _create_entries, real_value):
|
||||||
|
assert len(Accounts(conn, SUFFIX).filter(real_value)) == 3
|
||||||
|
|
||||||
|
|
||||||
|
+def test_long_filter_value(topo):
|
||||||
|
+ """Exercise large eq filter with dn syntax attributes
|
||||||
|
+
|
||||||
|
+ :id: b069ef72-fcc3-11ee-981c-482ae39447e5
|
||||||
|
+ :setup: Standalone
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Try to pass filter rules as per the condition.
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Pass
|
||||||
|
+ """
|
||||||
|
+ inst = topo.standalone
|
||||||
|
+ conn = open_new_ldapi_conn(inst.serverid)
|
||||||
|
+ inst.config.loglevel(vals=(ErrorLog.DEFAULT,ErrorLog.TRACE,ErrorLog.SEARCH_FILTER))
|
||||||
|
+ filter_value = "a\x1Edmin" * 1025
|
||||||
|
+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
|
||||||
|
+ filter_value = "aAdmin" * 1025
|
||||||
|
+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
|
||||||
|
+ filter_value = "*"
|
||||||
|
+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
|
||||||
|
+ inst.config.loglevel(vals=(ErrorLog.DEFAULT,))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
if __name__ == '__main__':
|
||||||
|
CURRENT_FILE = os.path.realpath(__file__)
|
||||||
|
pytest.main("-s -v %s" % CURRENT_FILE)
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
|
||||||
|
index 410db23d1..30fa09ebb 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/index.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/index.c
|
||||||
|
@@ -71,6 +71,32 @@ typedef struct _index_buffer_handle index_buffer_handle;
|
||||||
|
#define INDEX_BUFFER_FLAG_SERIALIZE 1
|
||||||
|
#define INDEX_BUFFER_FLAG_STATS 2
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * space needed to encode a byte:
|
||||||
|
+ * 0x00-0x31 and 0x7f-0xff requires 3 bytes: \xx
|
||||||
|
+ * 0x22 and 0x5C requires 2 bytes: \" and \\
|
||||||
|
+ * other requires 1 byte: c
|
||||||
|
+ */
|
||||||
|
+static char encode_size[] = {
|
||||||
|
+ /* 0x00 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0x10 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0x20 */ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
+ /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
+ /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
+ /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
|
||||||
|
+ /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
+ /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
|
||||||
|
+ /* 0x80 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0x90 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xA0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xB0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xC0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xD0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xE0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+ /* 0xF0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/* Index buffering functions */
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -799,65 +825,46 @@ index_add_mods(
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a 'struct berval' into a displayable ASCII string
|
||||||
|
+ * returns the printable string
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
-#define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"')
|
||||||
|
-
|
||||||
|
const char *
|
||||||
|
encode(const struct berval *data, char buf[BUFSIZ])
|
||||||
|
{
|
||||||
|
- char *s;
|
||||||
|
- char *last;
|
||||||
|
- if (data == NULL || data->bv_len == 0)
|
||||||
|
- return "";
|
||||||
|
- last = data->bv_val + data->bv_len - 1;
|
||||||
|
- for (s = data->bv_val; s < last; ++s) {
|
||||||
|
- if (SPECIAL(*s)) {
|
||||||
|
- char *first = data->bv_val;
|
||||||
|
- char *bufNext = buf;
|
||||||
|
- size_t bufSpace = BUFSIZ - 4;
|
||||||
|
- while (1) {
|
||||||
|
- /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */
|
||||||
|
- if (bufSpace < (size_t)(s - first))
|
||||||
|
- s = first + bufSpace - 1;
|
||||||
|
- if (s != first) {
|
||||||
|
- memcpy(bufNext, first, s - first);
|
||||||
|
- bufNext += (s - first);
|
||||||
|
- bufSpace -= (s - first);
|
||||||
|
- }
|
||||||
|
- do {
|
||||||
|
- if (bufSpace) {
|
||||||
|
- *bufNext++ = '\\';
|
||||||
|
- --bufSpace;
|
||||||
|
- }
|
||||||
|
- if (bufSpace < 2) {
|
||||||
|
- memcpy(bufNext, "..", 2);
|
||||||
|
- bufNext += 2;
|
||||||
|
- goto bail;
|
||||||
|
- }
|
||||||
|
- if (*s == '\\' || *s == '"') {
|
||||||
|
- *bufNext++ = *s;
|
||||||
|
- --bufSpace;
|
||||||
|
- } else {
|
||||||
|
- sprintf(bufNext, "%02x", (unsigned)*(unsigned char *)s);
|
||||||
|
- bufNext += 2;
|
||||||
|
- bufSpace -= 2;
|
||||||
|
- }
|
||||||
|
- } while (++s <= last && SPECIAL(*s));
|
||||||
|
- if (s > last)
|
||||||
|
- break;
|
||||||
|
- first = s;
|
||||||
|
- while (!SPECIAL(*s) && s <= last)
|
||||||
|
- ++s;
|
||||||
|
- }
|
||||||
|
- bail:
|
||||||
|
- *bufNext = '\0';
|
||||||
|
- /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */
|
||||||
|
+ if (!data || !data->bv_val) {
|
||||||
|
+ strcpy(buf, "<NULL>");
|
||||||
|
+ return buf;
|
||||||
|
+ }
|
||||||
|
+ char *endbuff = &buf[BUFSIZ-4]; /* Reserve space to append "...\0" */
|
||||||
|
+ char *ptout = buf;
|
||||||
|
+ unsigned char *ptin = (unsigned char*) data->bv_val;
|
||||||
|
+ unsigned char *endptin = ptin+data->bv_len;
|
||||||
|
+
|
||||||
|
+ while (ptin < endptin) {
|
||||||
|
+ if (ptout >= endbuff) {
|
||||||
|
+ /*
|
||||||
|
+ * BUFSIZ(8K) > SLAPI_LOG_BUFSIZ(2K) so the error log message will be
|
||||||
|
+ * truncated anyway. So there is no real interrest to test if the original
|
||||||
|
+ * data contains no special characters and return it as is.
|
||||||
|
+ */
|
||||||
|
+ strcpy(endbuff, "...");
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
+ switch (encode_size[*ptin]) {
|
||||||
|
+ case 1:
|
||||||
|
+ *ptout++ = *ptin++;
|
||||||
|
+ break;
|
||||||
|
+ case 2:
|
||||||
|
+ *ptout++ = '\\';
|
||||||
|
+ *ptout++ = *ptin++;
|
||||||
|
+ break;
|
||||||
|
+ case 3:
|
||||||
|
+ sprintf(ptout, "\\%02x", *ptin++);
|
||||||
|
+ ptout += 3;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */
|
||||||
|
- return data->bv_val;
|
||||||
|
+ *ptout = 0;
|
||||||
|
+ return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,143 @@
|
|||||||
|
From 6e5f03d5872129963106024f53765234a282406c Mon Sep 17 00:00:00 2001
|
||||||
|
From: James Chapman <jachapma@redhat.com>
|
||||||
|
Date: Fri, 16 Feb 2024 11:13:16 +0000
|
||||||
|
Subject: [PATCH] Issue 6096 - Improve connection timeout error logging (#6097)
|
||||||
|
|
||||||
|
Bug description: When a paged result search is run with a time limit,
|
||||||
|
if the time limit is exceed the server closes the connection with
|
||||||
|
closed IO timeout (nsslapd-ioblocktimeout) - T2. This error message
|
||||||
|
is incorrect as the reason the connection has been closed was because
|
||||||
|
the specified time limit on a paged result search has been exceeded.
|
||||||
|
|
||||||
|
Fix description: Correct error message
|
||||||
|
|
||||||
|
Relates: https://github.com/389ds/389-ds-base/issues/6096
|
||||||
|
|
||||||
|
Reviewed by: @tbordaz (Thank you)
|
||||||
|
---
|
||||||
|
ldap/admin/src/logconv.pl | 24 ++++++++++++++++++-
|
||||||
|
ldap/servers/slapd/daemon.c | 4 ++--
|
||||||
|
ldap/servers/slapd/disconnect_error_strings.h | 1 +
|
||||||
|
ldap/servers/slapd/disconnect_errors.h | 2 +-
|
||||||
|
4 files changed, 27 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
|
||||||
|
index 7698c383a..2a933c4a3 100755
|
||||||
|
--- a/ldap/admin/src/logconv.pl
|
||||||
|
+++ b/ldap/admin/src/logconv.pl
|
||||||
|
@@ -267,7 +267,7 @@ my $optimeAvg = 0;
|
||||||
|
my %cipher = ();
|
||||||
|
my @removefiles = ();
|
||||||
|
|
||||||
|
-my @conncodes = qw(A1 B1 B4 T1 T2 B2 B3 R1 P1 P2 U1);
|
||||||
|
+my @conncodes = qw(A1 B1 B4 T1 T2 T3 B2 B3 R1 P1 P2 U1);
|
||||||
|
my %conn = ();
|
||||||
|
map {$conn{$_} = $_} @conncodes;
|
||||||
|
|
||||||
|
@@ -355,6 +355,7 @@ $connmsg{"B1"} = "Bad Ber Tag Encountered";
|
||||||
|
$connmsg{"B4"} = "Server failed to flush data (response) back to Client";
|
||||||
|
$connmsg{"T1"} = "Idle Timeout Exceeded";
|
||||||
|
$connmsg{"T2"} = "IO Block Timeout Exceeded or NTSSL Timeout";
|
||||||
|
+$connmsg{"T3"} = "Paged Search Time Limit Exceeded";
|
||||||
|
$connmsg{"B2"} = "Ber Too Big";
|
||||||
|
$connmsg{"B3"} = "Ber Peek";
|
||||||
|
$connmsg{"R1"} = "Revents";
|
||||||
|
@@ -1723,6 +1724,10 @@ if ($usage =~ /j/i || $verb eq "yes"){
|
||||||
|
print "\n $recCount. You have some coonections that are being closed by the ioblocktimeout setting. You may want to increase the ioblocktimeout.\n";
|
||||||
|
$recCount++;
|
||||||
|
}
|
||||||
|
+ if (defined($conncount->{"T3"}) and $conncount->{"T3"} > 0){
|
||||||
|
+ print "\n $recCount. You have some connections that are being closed because a paged result search limit has been exceeded. You may want to increase the search time limit.\n";
|
||||||
|
+ $recCount++;
|
||||||
|
+ }
|
||||||
|
# compare binds to unbinds, if the difference is more than 30% of the binds, then report a issue
|
||||||
|
if (($bindCount - $unbindCount) > ($bindCount*.3)){
|
||||||
|
print "\n $recCount. You have a significant difference between binds and unbinds. You may want to investigate this difference.\n";
|
||||||
|
@@ -2366,6 +2371,7 @@ sub parseLineNormal
|
||||||
|
$brokenPipeCount++;
|
||||||
|
if (m/- T1/){ $hashes->{rc}->{"T1"}++; }
|
||||||
|
elsif (m/- T2/){ $hashes->{rc}->{"T2"}++; }
|
||||||
|
+ elsif (m/- T3/){ $hashes->{rc}->{"T3"}++; }
|
||||||
|
elsif (m/- A1/){ $hashes->{rc}->{"A1"}++; }
|
||||||
|
elsif (m/- B1/){ $hashes->{rc}->{"B1"}++; }
|
||||||
|
elsif (m/- B4/){ $hashes->{rc}->{"B4"}++; }
|
||||||
|
@@ -2381,6 +2387,7 @@ sub parseLineNormal
|
||||||
|
$connResetByPeerCount++;
|
||||||
|
if (m/- T1/){ $hashes->{src}->{"T1"}++; }
|
||||||
|
elsif (m/- T2/){ $hashes->{src}->{"T2"}++; }
|
||||||
|
+ elsif (m/- T3/){ $hashes->{src}->{"T3"}++; }
|
||||||
|
elsif (m/- A1/){ $hashes->{src}->{"A1"}++; }
|
||||||
|
elsif (m/- B1/){ $hashes->{src}->{"B1"}++; }
|
||||||
|
elsif (m/- B4/){ $hashes->{src}->{"B4"}++; }
|
||||||
|
@@ -2396,6 +2403,7 @@ sub parseLineNormal
|
||||||
|
$resourceUnavailCount++;
|
||||||
|
if (m/- T1/){ $hashes->{rsrc}->{"T1"}++; }
|
||||||
|
elsif (m/- T2/){ $hashes->{rsrc}->{"T2"}++; }
|
||||||
|
+ elsif (m/- T3/){ $hashes->{rsrc}->{"T3"}++; }
|
||||||
|
elsif (m/- A1/){ $hashes->{rsrc}->{"A1"}++; }
|
||||||
|
elsif (m/- B1/){ $hashes->{rsrc}->{"B1"}++; }
|
||||||
|
elsif (m/- B4/){ $hashes->{rsrc}->{"B4"}++; }
|
||||||
|
@@ -2494,6 +2502,20 @@ sub parseLineNormal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (m/- T3/){
|
||||||
|
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
|
||||||
|
+ $exc = "no";
|
||||||
|
+ $ip = getIPfromConn($1, $serverRestartCount);
|
||||||
|
+ for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
|
||||||
|
+ if ($ip eq $excludeIP[$xxx]){$exc = "yes";}
|
||||||
|
+ }
|
||||||
|
+ if ($exc ne "yes"){
|
||||||
|
+ $hashes->{T3}->{$ip}++;
|
||||||
|
+ $hashes->{conncount}->{"T3"}++;
|
||||||
|
+ $connCodeCount++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
if (m/- B2/){
|
||||||
|
if ($_ =~ /conn= *([0-9A-Z]+)/i) {
|
||||||
|
$exc = "no";
|
||||||
|
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
|
||||||
|
index 5a48aa66f..bb80dae36 100644
|
||||||
|
--- a/ldap/servers/slapd/daemon.c
|
||||||
|
+++ b/ldap/servers/slapd/daemon.c
|
||||||
|
@@ -1599,9 +1599,9 @@ setup_pr_read_pds(Connection_Table *ct)
|
||||||
|
int add_fd = 1;
|
||||||
|
/* check timeout for PAGED RESULTS */
|
||||||
|
if (pagedresults_is_timedout_nolock(c)) {
|
||||||
|
- /* Exceeded the timelimit; disconnect the client */
|
||||||
|
+ /* Exceeded the paged search timelimit; disconnect the client */
|
||||||
|
disconnect_server_nomutex(c, c->c_connid, -1,
|
||||||
|
- SLAPD_DISCONNECT_IO_TIMEOUT,
|
||||||
|
+ SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT,
|
||||||
|
0);
|
||||||
|
connection_table_move_connection_out_of_active_list(ct,
|
||||||
|
c);
|
||||||
|
diff --git a/ldap/servers/slapd/disconnect_error_strings.h b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
index f7a31d728..c2d9e283b 100644
|
||||||
|
--- a/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
+++ b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
@@ -27,6 +27,7 @@ ER2(SLAPD_DISCONNECT_BER_FLUSH, "B4")
|
||||||
|
ER2(SLAPD_DISCONNECT_IDLE_TIMEOUT, "T1")
|
||||||
|
ER2(SLAPD_DISCONNECT_REVENTS, "R1")
|
||||||
|
ER2(SLAPD_DISCONNECT_IO_TIMEOUT, "T2")
|
||||||
|
+ER2(SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT, "T3")
|
||||||
|
ER2(SLAPD_DISCONNECT_PLUGIN, "P1")
|
||||||
|
ER2(SLAPD_DISCONNECT_UNBIND, "U1")
|
||||||
|
ER2(SLAPD_DISCONNECT_POLL, "P2")
|
||||||
|
diff --git a/ldap/servers/slapd/disconnect_errors.h b/ldap/servers/slapd/disconnect_errors.h
|
||||||
|
index a0484f1c2..e118f674c 100644
|
||||||
|
--- a/ldap/servers/slapd/disconnect_errors.h
|
||||||
|
+++ b/ldap/servers/slapd/disconnect_errors.h
|
||||||
|
@@ -35,6 +35,6 @@
|
||||||
|
#define SLAPD_DISCONNECT_SASL_FAIL SLAPD_DISCONNECT_ERROR_BASE + 12
|
||||||
|
#define SLAPD_DISCONNECT_PROXY_INVALID_HEADER SLAPD_DISCONNECT_ERROR_BASE + 13
|
||||||
|
#define SLAPD_DISCONNECT_PROXY_UNKNOWN SLAPD_DISCONNECT_ERROR_BASE + 14
|
||||||
|
-
|
||||||
|
+#define SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT SLAPD_DISCONNECT_ERROR_BASE + 15
|
||||||
|
|
||||||
|
#endif /* __DISCONNECT_ERRORS_H_ */
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From a112394af3a20787755029804684d57a9c3ffa9a Mon Sep 17 00:00:00 2001
|
||||||
|
From: James Chapman <jachapma@redhat.com>
|
||||||
|
Date: Wed, 21 Feb 2024 12:43:03 +0000
|
||||||
|
Subject: [PATCH] Issue 6103 - New connection timeout error breaks errormap
|
||||||
|
(#6104)
|
||||||
|
|
||||||
|
Bug description: A recent addition to the connection disconnect error
|
||||||
|
messaging, conflicts with how errormap.c maps error codes/strings.
|
||||||
|
|
||||||
|
Fix description: errormap expects error codes/strings to be in ascending
|
||||||
|
order. Moved the new error code to the bottom of the list.
|
||||||
|
|
||||||
|
Relates: https://github.com/389ds/389-ds-base/issues/6103
|
||||||
|
|
||||||
|
Reviewed by: @droideck. @progier389 (Thank you)
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/disconnect_error_strings.h | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/disconnect_error_strings.h b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
index c2d9e283b..f603a08ce 100644
|
||||||
|
--- a/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
+++ b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
@@ -14,7 +14,8 @@
|
||||||
|
/* disconnect_error_strings.h
|
||||||
|
*
|
||||||
|
* Strings describing the errors used in logging the reason a connection
|
||||||
|
- * was closed.
|
||||||
|
+ * was closed. Ensure definitions are in the same order as the error codes
|
||||||
|
+ * defined in disconnect_errors.h
|
||||||
|
*/
|
||||||
|
#ifndef __DISCONNECT_ERROR_STRINGS_H_
|
||||||
|
#define __DISCONNECT_ERROR_STRINGS_H_
|
||||||
|
@@ -35,6 +36,6 @@ ER2(SLAPD_DISCONNECT_NTSSL_TIMEOUT, "T2")
|
||||||
|
ER2(SLAPD_DISCONNECT_SASL_FAIL, "S1")
|
||||||
|
ER2(SLAPD_DISCONNECT_PROXY_INVALID_HEADER, "P3")
|
||||||
|
ER2(SLAPD_DISCONNECT_PROXY_UNKNOWN, "P4")
|
||||||
|
-
|
||||||
|
+ER2(SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT, "T3")
|
||||||
|
|
||||||
|
#endif /* __DISCONNECT_ERROR_STRINGS_H_ */
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From edd9abc8901604dde1d739d87ca2906734d53dd3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Viktor Ashirov <vashirov@redhat.com>
|
||||||
|
Date: Thu, 13 Jun 2024 13:35:09 +0200
|
||||||
|
Subject: [PATCH] Issue 6103 - New connection timeout error breaks errormap
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Remove duplicate SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT error code.
|
||||||
|
|
||||||
|
Fixes: https://github.com/389ds/389-ds-base/issues/6103
|
||||||
|
|
||||||
|
Reviewed by: @tbordaz (Thanks!)
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/disconnect_error_strings.h | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/disconnect_error_strings.h b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
index f603a08ce..d49cc79a2 100644
|
||||||
|
--- a/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
+++ b/ldap/servers/slapd/disconnect_error_strings.h
|
||||||
|
@@ -28,7 +28,6 @@ ER2(SLAPD_DISCONNECT_BER_FLUSH, "B4")
|
||||||
|
ER2(SLAPD_DISCONNECT_IDLE_TIMEOUT, "T1")
|
||||||
|
ER2(SLAPD_DISCONNECT_REVENTS, "R1")
|
||||||
|
ER2(SLAPD_DISCONNECT_IO_TIMEOUT, "T2")
|
||||||
|
-ER2(SLAPD_DISCONNECT_PAGED_SEARCH_LIMIT, "T3")
|
||||||
|
ER2(SLAPD_DISCONNECT_PLUGIN, "P1")
|
||||||
|
ER2(SLAPD_DISCONNECT_UNBIND, "U1")
|
||||||
|
ER2(SLAPD_DISCONNECT_POLL, "P2")
|
||||||
|
--
|
||||||
|
2.45.0
|
||||||
|
|
@ -0,0 +1,220 @@
|
|||||||
|
From 8cf981c00ae18d3efaeb10819282cd991621e9a2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: tbordaz <tbordaz@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 11:29:05 +0200
|
||||||
|
Subject: [PATCH] Issue 6172 - RFE: improve the performance of evaluation of
|
||||||
|
filter component when tested against a large valueset (like group members)
|
||||||
|
(#6173)
|
||||||
|
|
||||||
|
Bug description:
|
||||||
|
Before returning an entry (to a SRCH) the server checks that the entry matches the SRCH filter.
|
||||||
|
If a filter component (equality) is testing the value (ava) against a
|
||||||
|
large valueset (like uniquemember values), it takes a long time because
|
||||||
|
of the large number of values and required normalization of the values.
|
||||||
|
This can be improved taking benefit of sorted valueset. Those sorted
|
||||||
|
valueset were created to improve updates of large valueset (groups) but
|
||||||
|
at that time not implemented in SRCH path.
|
||||||
|
|
||||||
|
Fix description:
|
||||||
|
In case of LDAP_FILTER_EQUALITY component, the server can get
|
||||||
|
benefit of the sorted valuearray.
|
||||||
|
To limit the risk of regression, we use the sorted valuearray
|
||||||
|
only for the DN syntax attribute. Indeed the sorted valuearray was
|
||||||
|
designed for those type of attribute.
|
||||||
|
With those two limitations, there is no need of a toggle and
|
||||||
|
the call to plugin_call_syntax_filter_ava can be replaced by
|
||||||
|
a call to slapi_valueset_find.
|
||||||
|
In both cases, sorted valueset and plugin_call_syntax_filter_ava, ava and
|
||||||
|
values are normalized.
|
||||||
|
In sorted valueset, the values have been normalized to insert the index
|
||||||
|
in the sorted array and then comparison is done on normalized values.
|
||||||
|
In plugin_call_syntax_filter_ava, all values in valuearray (of valueset) are normalized
|
||||||
|
before comparison.
|
||||||
|
|
||||||
|
relates: #6172
|
||||||
|
|
||||||
|
Reviewed by: Pierre Rogier, Simon Pichugin (Big Thanks !!!)
|
||||||
|
---
|
||||||
|
.../tests/suites/filter/filter_test.py | 125 ++++++++++++++++++
|
||||||
|
ldap/servers/slapd/filterentry.c | 22 ++-
|
||||||
|
2 files changed, 146 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/filter/filter_test.py b/dirsrvtests/tests/suites/filter/filter_test.py
|
||||||
|
index d6bfa5a3b..4baaf04a7 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/filter/filter_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/filter/filter_test.py
|
||||||
|
@@ -9,7 +9,11 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
+import time
|
||||||
|
+from lib389.dirsrv_log import DirsrvAccessLog
|
||||||
|
from lib389.tasks import *
|
||||||
|
+from lib389.backend import Backends, Backend
|
||||||
|
+from lib389.dbgen import dbgen_users, dbgen_groups
|
||||||
|
from lib389.topologies import topology_st
|
||||||
|
from lib389._constants import PASSWORD, DEFAULT_SUFFIX, DN_DM, SUFFIX
|
||||||
|
from lib389.utils import *
|
||||||
|
@@ -304,6 +308,127 @@ def test_extended_search(topology_st):
|
||||||
|
ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
|
||||||
|
assert len(ents) == 1
|
||||||
|
|
||||||
|
+def test_match_large_valueset(topology_st):
|
||||||
|
+ """Test that when returning a big number of entries
|
||||||
|
+ and that we need to match the filter from a large valueset
|
||||||
|
+ we get benefit to use the sorted valueset
|
||||||
|
+
|
||||||
|
+ :id: 7db5aa88-50e0-4c31-85dd-1d2072cb674c
|
||||||
|
+
|
||||||
|
+ :setup: Standalone instance
|
||||||
|
+
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Create a users and groups backends and tune them
|
||||||
|
+ 2. Generate a test ldif (2k users and 1K groups with all users)
|
||||||
|
+ 3. Import test ldif file using Offline import (ldif2db).
|
||||||
|
+ 4. Prim the 'groups' entrycache with a "fast" search
|
||||||
|
+ 5. Search the 'groups' with a difficult matching value
|
||||||
|
+ 6. check that etime from step 5 is less than a second
|
||||||
|
+
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Create a users and groups backends should PASS
|
||||||
|
+ 2. Generate LDIF should PASS.
|
||||||
|
+ 3. Offline import should PASS.
|
||||||
|
+ 4. Priming should PASS.
|
||||||
|
+ 5. Performance search should PASS.
|
||||||
|
+ 6. Etime of performance search should PASS.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ log.info('Running test_match_large_valueset...')
|
||||||
|
+ #
|
||||||
|
+ # Test online/offline LDIF imports
|
||||||
|
+ #
|
||||||
|
+ inst = topology_st.standalone
|
||||||
|
+ inst.start()
|
||||||
|
+ backends = Backends(inst)
|
||||||
|
+ users_suffix = "ou=users,%s" % DEFAULT_SUFFIX
|
||||||
|
+ users_backend = 'users'
|
||||||
|
+ users_ldif = 'users_import.ldif'
|
||||||
|
+ groups_suffix = "ou=groups,%s" % DEFAULT_SUFFIX
|
||||||
|
+ groups_backend = 'groups'
|
||||||
|
+ groups_ldif = 'groups_import.ldif'
|
||||||
|
+ groups_entrycache = '200000000'
|
||||||
|
+ users_number = 2000
|
||||||
|
+ groups_number = 1000
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ # For priming the cache we just want to be fast
|
||||||
|
+ # taking the first value in the valueset is good
|
||||||
|
+ # whether the valueset is sorted or not
|
||||||
|
+ priming_user_rdn = "user0001"
|
||||||
|
+
|
||||||
|
+ # For performance testing, this is important to use
|
||||||
|
+ # user1000 rather then user0001
|
||||||
|
+ # Because user0001 is the first value in the valueset
|
||||||
|
+ # whether we use the sorted valuearray or non sorted
|
||||||
|
+ # valuearray the performance will be similar.
|
||||||
|
+ # With middle value user1000, the performance boost of
|
||||||
|
+ # the sorted valuearray will make the difference.
|
||||||
|
+ perf_user_rdn = "user1000"
|
||||||
|
+
|
||||||
|
+ # Step 1. Prepare the backends and tune the groups entrycache
|
||||||
|
+ try:
|
||||||
|
+ be_users = backends.create(properties={'parent': DEFAULT_SUFFIX, 'nsslapd-suffix': users_suffix, 'name': users_backend})
|
||||||
|
+ be_groups = backends.create(properties={'parent': DEFAULT_SUFFIX, 'nsslapd-suffix': groups_suffix, 'name': groups_backend})
|
||||||
|
+
|
||||||
|
+ # set the entry cache to 200Mb as the 1K groups of 2K users require at least 170Mb
|
||||||
|
+ be_groups.replace('nsslapd-cachememsize', groups_entrycache)
|
||||||
|
+ except:
|
||||||
|
+ raise
|
||||||
|
+
|
||||||
|
+ # Step 2. Generate a test ldif (10k users entries)
|
||||||
|
+ log.info("Generating users LDIF...")
|
||||||
|
+ ldif_dir = inst.get_ldif_dir()
|
||||||
|
+ users_import_ldif = "%s/%s" % (ldif_dir, users_ldif)
|
||||||
|
+ groups_import_ldif = "%s/%s" % (ldif_dir, groups_ldif)
|
||||||
|
+ dbgen_users(inst, users_number, users_import_ldif, suffix=users_suffix, generic=True, parent=users_suffix)
|
||||||
|
+
|
||||||
|
+ # Generate a test ldif (800 groups with 10k members) that fit in 700Mb entry cache
|
||||||
|
+ props = {
|
||||||
|
+ "name": "group",
|
||||||
|
+ "suffix": groups_suffix,
|
||||||
|
+ "parent": groups_suffix,
|
||||||
|
+ "number": groups_number,
|
||||||
|
+ "numMembers": users_number,
|
||||||
|
+ "createMembers": False,
|
||||||
|
+ "memberParent": users_suffix,
|
||||||
|
+ "membershipAttr": "uniquemember",
|
||||||
|
+ }
|
||||||
|
+ dbgen_groups(inst, groups_import_ldif, props)
|
||||||
|
+
|
||||||
|
+ # Step 3. Do the both offline imports
|
||||||
|
+ inst.stop()
|
||||||
|
+ if not inst.ldif2db(users_backend, None, None, None, users_import_ldif):
|
||||||
|
+ log.fatal('test_basic_import_export: Offline users import failed')
|
||||||
|
+ assert False
|
||||||
|
+ if not inst.ldif2db(groups_backend, None, None, None, groups_import_ldif):
|
||||||
|
+ log.fatal('test_basic_import_export: Offline groups import failed')
|
||||||
|
+ assert False
|
||||||
|
+ inst.start()
|
||||||
|
+
|
||||||
|
+ # Step 4. first prime the cache
|
||||||
|
+ # Just request the 'DN'. We are interested by the time of matching not by the time of transfert
|
||||||
|
+ entries = topology_st.standalone.search_s(groups_suffix, ldap.SCOPE_SUBTREE, "(&(objectclass=groupOfUniqueNames)(uniquemember=uid=%s,%s))" % (priming_user_rdn, users_suffix), ['dn'])
|
||||||
|
+ assert len(entries) == groups_number
|
||||||
|
+
|
||||||
|
+ # Step 5. Now do the real performance checking it should take less than a second
|
||||||
|
+ # Just request the 'DN'. We are interested by the time of matching not by the time of transfert
|
||||||
|
+ search_start = time.time()
|
||||||
|
+ entries = topology_st.standalone.search_s(groups_suffix, ldap.SCOPE_SUBTREE, "(&(objectclass=groupOfUniqueNames)(uniquemember=uid=%s,%s))" % (perf_user_rdn, users_suffix), ['dn'])
|
||||||
|
+ duration = time.time() - search_start
|
||||||
|
+ log.info("Duration of the search was %f", duration)
|
||||||
|
+
|
||||||
|
+ # Step 6. Gather the etime from the access log
|
||||||
|
+ inst.stop()
|
||||||
|
+ access_log = DirsrvAccessLog(inst)
|
||||||
|
+ search_result = access_log.match(".*RESULT err=0 tag=101 nentries=%s.*" % groups_number)
|
||||||
|
+ log.info("Found patterns are %s", search_result[0])
|
||||||
|
+ log.info("Found patterns are %s", search_result[1])
|
||||||
|
+ etime = float(search_result[1].split('etime=')[1])
|
||||||
|
+ log.info("Duration of the search from access log was %f", etime)
|
||||||
|
+ assert len(entries) == groups_number
|
||||||
|
+ assert (etime < 1)
|
||||||
|
+
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Run isolated
|
||||||
|
# -s for DEBUG mode
|
||||||
|
diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c
|
||||||
|
index fd8fdda9f..cae5c7edc 100644
|
||||||
|
--- a/ldap/servers/slapd/filterentry.c
|
||||||
|
+++ b/ldap/servers/slapd/filterentry.c
|
||||||
|
@@ -296,7 +296,27 @@ test_ava_filter(
|
||||||
|
rc = -1;
|
||||||
|
for (; a != NULL; a = a->a_next) {
|
||||||
|
if (slapi_attr_type_cmp(ava->ava_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
|
||||||
|
- rc = plugin_call_syntax_filter_ava(a, ftype, ava);
|
||||||
|
+ if ((ftype == LDAP_FILTER_EQUALITY) &&
|
||||||
|
+ (slapi_attr_is_dn_syntax_type(a->a_type))) {
|
||||||
|
+ /* This path is for a performance improvement */
|
||||||
|
+
|
||||||
|
+ /* In case of equality filter we can get benefit of the
|
||||||
|
+ * sorted valuearray (from valueset).
|
||||||
|
+ * This improvement is limited to DN syntax attributes for
|
||||||
|
+ * which the sorted valueset was designed.
|
||||||
|
+ */
|
||||||
|
+ Slapi_Value *sval = NULL;
|
||||||
|
+ sval = slapi_value_new_berval(&ava->ava_value);
|
||||||
|
+ if (slapi_valueset_find((const Slapi_Attr *)a, &a->a_present_values, sval)) {
|
||||||
|
+ rc = 0;
|
||||||
|
+ }
|
||||||
|
+ slapi_value_free(&sval);
|
||||||
|
+ } else {
|
||||||
|
+ /* When sorted valuearray optimization cannot be used
|
||||||
|
+ * lets filter the value according to its syntax
|
||||||
|
+ */
|
||||||
|
+ rc = plugin_call_syntax_filter_ava(a, ftype, ava);
|
||||||
|
+ }
|
||||||
|
if (rc == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
@ -0,0 +1,163 @@
|
|||||||
|
From 57051154bafaf50b83fc27dadbd89a49fd1c8c36 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre Rogier <progier@redhat.com>
|
||||||
|
Date: Fri, 14 Jun 2024 13:27:10 +0200
|
||||||
|
Subject: [PATCH] Security fix for CVE-2024-5953
|
||||||
|
|
||||||
|
Description:
|
||||||
|
A denial of service vulnerability was found in the 389 Directory Server.
|
||||||
|
This issue may allow an authenticated user to cause a server denial
|
||||||
|
of service while attempting to log in with a user with a malformed hash
|
||||||
|
in their password.
|
||||||
|
|
||||||
|
Fix Description:
|
||||||
|
To prevent buffer overflow when a bind request is processed, the bind fails
|
||||||
|
if the hash size is not coherent without even attempting to process further
|
||||||
|
the hashed password.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- https://nvd.nist.gov/vuln/detail/CVE-2024-5953
|
||||||
|
- https://access.redhat.com/security/cve/CVE-2024-5953
|
||||||
|
- https://bugzilla.redhat.com/show_bug.cgi?id=2292104
|
||||||
|
---
|
||||||
|
.../tests/suites/password/regression_test.py | 54 ++++++++++++++++++-
|
||||||
|
ldap/servers/plugins/pwdstorage/md5_pwd.c | 9 +++-
|
||||||
|
ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c | 6 +++
|
||||||
|
3 files changed, 66 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py
|
||||||
|
index 8f1facb6d..1fa581643 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/password/regression_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/password/regression_test.py
|
||||||
|
@@ -7,12 +7,14 @@
|
||||||
|
#
|
||||||
|
import pytest
|
||||||
|
import time
|
||||||
|
+import glob
|
||||||
|
+import base64
|
||||||
|
from lib389._constants import PASSWORD, DN_DM, DEFAULT_SUFFIX
|
||||||
|
from lib389._constants import SUFFIX, PASSWORD, DN_DM, DN_CONFIG, PLUGIN_RETRO_CHANGELOG, DEFAULT_SUFFIX, DEFAULT_CHANGELOG_DB
|
||||||
|
from lib389 import Entry
|
||||||
|
from lib389.topologies import topology_m1 as topo_supplier
|
||||||
|
-from lib389.idm.user import UserAccounts
|
||||||
|
-from lib389.utils import ldap, os, logging, ensure_bytes, ds_is_newer
|
||||||
|
+from lib389.idm.user import UserAccounts, UserAccount
|
||||||
|
+from lib389.utils import ldap, os, logging, ensure_bytes, ds_is_newer, ds_supports_new_changelog
|
||||||
|
from lib389.topologies import topology_st as topo
|
||||||
|
from lib389.idm.organizationalunit import OrganizationalUnits
|
||||||
|
|
||||||
|
@@ -39,6 +41,13 @@ TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1',
|
||||||
|
TEST_PASSWORDS2 = (
|
||||||
|
'CN12pwtest31', 'SN3pwtest231', 'UID1pwtest123', 'MAIL2pwtest12@redhat.com', '2GN1pwtest123', 'People123')
|
||||||
|
|
||||||
|
+SUPPORTED_SCHEMES = (
|
||||||
|
+ "{SHA}", "{SSHA}", "{SHA256}", "{SSHA256}",
|
||||||
|
+ "{SHA384}", "{SSHA384}", "{SHA512}", "{SSHA512}",
|
||||||
|
+ "{crypt}", "{NS-MTA-MD5}", "{clear}", "{MD5}",
|
||||||
|
+ "{SMD5}", "{PBKDF2_SHA256}", "{PBKDF2_SHA512}",
|
||||||
|
+ "{GOST_YESCRYPT}", "{PBKDF2-SHA256}", "{PBKDF2-SHA512}" )
|
||||||
|
+
|
||||||
|
def _check_unhashed_userpw(inst, user_dn, is_present=False):
|
||||||
|
"""Check if unhashed#user#password attribute is present or not in the changelog"""
|
||||||
|
unhashed_pwd_attribute = 'unhashed#user#password'
|
||||||
|
@@ -319,6 +328,47 @@ def test_unhashed_pw_switch(topo_supplier):
|
||||||
|
# Add debugging steps(if any)...
|
||||||
|
pass
|
||||||
|
|
||||||
|
+@pytest.mark.parametrize("scheme", SUPPORTED_SCHEMES )
|
||||||
|
+def test_long_hashed_password(topo, create_user, scheme):
|
||||||
|
+ """Check that hashed password with very long value does not cause trouble
|
||||||
|
+
|
||||||
|
+ :id: 252a1f76-114b-11ef-8a7a-482ae39447e5
|
||||||
|
+ :setup: standalone Instance
|
||||||
|
+ :parametrized: yes
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Add a test user user
|
||||||
|
+ 2. Set a long password with requested scheme
|
||||||
|
+ 3. Bind on that user using a wrong password
|
||||||
|
+ 4. Check that instance is still alive
|
||||||
|
+ 5. Remove the added user
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Success
|
||||||
|
+ 2. Success
|
||||||
|
+ 3. Should get ldap.INVALID_CREDENTIALS exception
|
||||||
|
+ 4. Success
|
||||||
|
+ 5. Success
|
||||||
|
+ """
|
||||||
|
+ inst = topo.standalone
|
||||||
|
+ inst.simple_bind_s(DN_DM, PASSWORD)
|
||||||
|
+ users = UserAccounts(inst, DEFAULT_SUFFIX)
|
||||||
|
+ # Make sure that server is started as this test may crash it
|
||||||
|
+ inst.start()
|
||||||
|
+ # Adding Test user (It may already exists if previous test failed)
|
||||||
|
+ user2 = UserAccount(inst, dn='uid=test_user_1002,ou=People,dc=example,dc=com')
|
||||||
|
+ if not user2.exists():
|
||||||
|
+ user2 = users.create_test_user(uid=1002, gid=2002)
|
||||||
|
+ # Setting hashed password
|
||||||
|
+ passwd = 'A'*4000
|
||||||
|
+ hashed_passwd = scheme.encode('utf-8') + base64.b64encode(passwd.encode('utf-8'))
|
||||||
|
+ user2.replace('userpassword', hashed_passwd)
|
||||||
|
+ # Bind on that user using a wrong password
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ conn = user2.bind(PASSWORD)
|
||||||
|
+ # Check that instance is still alive
|
||||||
|
+ assert inst.status()
|
||||||
|
+ # Remove the added user
|
||||||
|
+ user2.delete()
|
||||||
|
+
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Run isolated
|
||||||
|
diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c b/ldap/servers/plugins/pwdstorage/md5_pwd.c
|
||||||
|
index 1e2cf58e7..b9a48d5ca 100644
|
||||||
|
--- a/ldap/servers/plugins/pwdstorage/md5_pwd.c
|
||||||
|
+++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c
|
||||||
|
@@ -37,6 +37,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
|
||||||
|
unsigned char hash_out[MD5_HASH_LEN];
|
||||||
|
unsigned char b2a_out[MD5_HASH_LEN * 2]; /* conservative */
|
||||||
|
SECItem binary_item;
|
||||||
|
+ size_t dbpwd_len = strlen(dbpwd);
|
||||||
|
|
||||||
|
ctx = PK11_CreateDigestContext(SEC_OID_MD5);
|
||||||
|
if (ctx == NULL) {
|
||||||
|
@@ -45,6 +46,12 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
|
||||||
|
goto loser;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (dbpwd_len >= sizeof b2a_out) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
|
||||||
|
+ "The hashed password stored in the user entry is longer than any valid md5 hash");
|
||||||
|
+ goto loser;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* create the hash */
|
||||||
|
PK11_DigestBegin(ctx);
|
||||||
|
PK11_DigestOp(ctx, (const unsigned char *)userpwd, strlen(userpwd));
|
||||||
|
@@ -57,7 +64,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
|
||||||
|
bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, &binary_item);
|
||||||
|
/* bver points to b2a_out upon success */
|
||||||
|
if (bver) {
|
||||||
|
- rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd));
|
||||||
|
+ rc = slapi_ct_memcmp(bver, dbpwd, dbpwd_len);
|
||||||
|
} else {
|
||||||
|
slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
|
||||||
|
"Could not base64 encode hashed value for password compare");
|
||||||
|
diff --git a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
|
||||||
|
index dcac4fcdd..82b8c9501 100644
|
||||||
|
--- a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
|
||||||
|
+++ b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
|
||||||
|
@@ -255,6 +255,12 @@ pbkdf2_sha256_pw_cmp(const char *userpwd, const char *dbpwd)
|
||||||
|
passItem.data = (unsigned char *)userpwd;
|
||||||
|
passItem.len = strlen(userpwd);
|
||||||
|
|
||||||
|
+ if (pwdstorage_base64_decode_len(dbpwd, dbpwd_len) > sizeof dbhash) {
|
||||||
|
+ /* Hashed value is too long and cannot match any value generated by pbkdf2_sha256_hash */
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to base64 decode dbpwd value. (hashed value is too long)\n");
|
||||||
|
+ return result;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Decode the DBpwd to bytes from b64 */
|
||||||
|
if (PL_Base64Decode(dbpwd, dbpwd_len, dbhash) == NULL) {
|
||||||
|
slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to base64 decode dbpwd value\n");
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
#Type Name ID GECOS Home directory Shell
|
|
||||||
g dirsrv 389
|
|
||||||
u dirsrv 389:389 "user for 389-ds-base" /usr/share/dirsrv/ /sbin/nologin
|
|
@ -0,0 +1,933 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.7.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cbindgen"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9daec6140ab4dcd38c3dd57e580b59a621172a526ac79f1527af760a55afeafd"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"tempfile",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.34.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"strsim",
|
||||||
|
"textwrap",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "concread"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcc9816f5ac93ebd51c37f7f9a6bf2b40dfcd42978ad2aea5d542016e9244cf6"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"crossbeam",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lru",
|
||||||
|
"parking_lot",
|
||||||
|
"rand",
|
||||||
|
"smallvec",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.3.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "entryuuid"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"paste",
|
||||||
|
"slapi_r_plugin",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "entryuuid_syntax"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"paste",
|
||||||
|
"slapi_r_plugin",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fernet"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93804560e638370a8be6d59ce71ed803e55e230abdbf42598e666b41adda9b1f"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"byteorder",
|
||||||
|
"getrandom",
|
||||||
|
"openssl",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.28.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "librnsslapd"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cbindgen",
|
||||||
|
"libc",
|
||||||
|
"slapd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "librslapd"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cbindgen",
|
||||||
|
"concread",
|
||||||
|
"libc",
|
||||||
|
"slapd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lru"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.32.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.62"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.2.16",
|
||||||
|
"smallvec",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
|
||||||
|
dependencies = [
|
||||||
|
"paste-impl",
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste-impl"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-hack"
|
||||||
|
version = "0.5.20+deprecated"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.76"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pwdchan"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"openssl",
|
||||||
|
"paste",
|
||||||
|
"slapi_r_plugin",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rsds"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.195"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.195"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.111"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slapd"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"fernet",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slapi_r_plugin"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"paste",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand",
|
||||||
|
"redox_syscall 0.4.1",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.35.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize_derive"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue