mirror of
https://git.centos.org/rpms/389-ds-base.git
synced 2025-02-23 16:22:54 +00:00
import 389-ds-base-1.3.4.0-32.el7_2
This commit is contained in:
parent
ed61979b35
commit
f5000ecbbb
6 changed files with 1687 additions and 2 deletions
|
@ -0,0 +1,103 @@
|
|||
From ce824731f4839f7812109b8c04ce704a56eeca4b Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Wed, 10 Feb 2016 11:36:32 -0800
|
||||
Subject: [PATCH 90/93] Ticket #48492 - heap corruption at schema replication.
|
||||
|
||||
Description: 389-ds-base-1.3.2 and newer uses openldap schema parser,
|
||||
which is more strict with the definition. For instance, the older
|
||||
389-ds-base could have a schema such as SINTAX OID in single quotes,
|
||||
which is not acceptable on the newer version. There was a bug to
|
||||
handle the error case that caused a crash.
|
||||
|
||||
This patch adds
|
||||
1) the null reference check to attr_syntax_free (attrsyntax.c),
|
||||
2) a null init to the output arg in parse_at_str and parse_oc_str
|
||||
(schema.c) and
|
||||
3) an error logging to schema_berval_to_atlist & schema_berval_to_oclist
|
||||
(schema.c) for troubleshooting.
|
||||
|
||||
https://fedorahosted.org/389/ticket/48492
|
||||
|
||||
Reviewed by wibrown@redhat.com and mreynolds@redhat.com (Thank you, William and Mark!)
|
||||
|
||||
(cherry picked from commit b5bfa2a0386e168ce2196a077169382ae53a94b4)
|
||||
(cherry picked from commit 9bd53c297683e691fef174bf1aed6842f475fb9f)
|
||||
---
|
||||
ldap/servers/slapd/attrsyntax.c | 3 +++
|
||||
ldap/servers/slapd/schema.c | 16 +++++++++++++++-
|
||||
2 files changed, 18 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c
|
||||
index 4cdcf86..8b2a77a 100644
|
||||
--- a/ldap/servers/slapd/attrsyntax.c
|
||||
+++ b/ldap/servers/slapd/attrsyntax.c
|
||||
@@ -189,6 +189,9 @@ attr_syntax_check_oids()
|
||||
void
|
||||
attr_syntax_free( struct asyntaxinfo *a )
|
||||
{
|
||||
+ if (!a) {
|
||||
+ return;
|
||||
+ }
|
||||
cool_charray_free( a->asi_aliases );
|
||||
slapi_ch_free_string(&a->asi_name );
|
||||
slapi_ch_free_string(&a->asi_desc );
|
||||
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
|
||||
index 65cbad5..dd56599 100644
|
||||
--- a/ldap/servers/slapd/schema.c
|
||||
+++ b/ldap/servers/slapd/schema.c
|
||||
@@ -263,6 +263,9 @@ static PRCallOnceType schema_dse_mandatory_init_callonce = { 0, 0, 0 };
|
||||
static int parse_at_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize,
|
||||
PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote)
|
||||
{
|
||||
+ if (asipp) {
|
||||
+ *asipp = NULL;
|
||||
+ }
|
||||
#ifdef USE_OPENLDAP
|
||||
return parse_attr_str(input, asipp, errorbuf, errorbufsize, schema_flags, is_user_defined,schema_ds4x_compat,is_remote);
|
||||
#else
|
||||
@@ -274,6 +277,9 @@ static int parse_oc_str(const char *input, struct objclass **oc, char *errorbuf,
|
||||
size_t errorbufsize, PRUint32 schema_flags, int is_user_defined,
|
||||
int schema_ds4x_compat, struct objclass* private_schema )
|
||||
{
|
||||
+ if (oc) {
|
||||
+ *oc = NULL;
|
||||
+ }
|
||||
#ifdef USE_OPENLDAP
|
||||
return parse_objclass_str (input, oc, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat, private_schema );
|
||||
#else
|
||||
@@ -7146,11 +7152,15 @@ schema_berval_to_oclist(struct berval **oc_berval)
|
||||
oc_list = NULL;
|
||||
oc_tail = NULL;
|
||||
if (oc_berval != NULL) {
|
||||
+ errorbuf[0] = '\0';
|
||||
for (i = 0; oc_berval[i] != NULL; i++) {
|
||||
/* parse the objectclass value */
|
||||
if (LDAP_SUCCESS != (rc = parse_oc_str(oc_berval[i]->bv_val, &oc,
|
||||
errorbuf, sizeof (errorbuf), DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_USE_PRIV_SCHEMA, 0,
|
||||
schema_ds4x_compat, oc_list))) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "schema",
|
||||
+ "parse_oc_str returned error: %s\n",
|
||||
+ errorbuf[0]?errorbuf:"unknown");
|
||||
oc_free(&oc);
|
||||
rc = 1;
|
||||
break;
|
||||
@@ -7184,11 +7194,15 @@ schema_berval_to_atlist(struct berval **at_berval)
|
||||
schema_ds4x_compat = config_get_ds4_compatible_schema();
|
||||
|
||||
if (at_berval != NULL) {
|
||||
+ errorbuf[0] = '\0';
|
||||
for (i = 0; at_berval[i] != NULL; i++) {
|
||||
/* parse the objectclass value */
|
||||
rc = parse_at_str(at_berval[i]->bv_val, &at, errorbuf, sizeof (errorbuf),
|
||||
DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_USE_PRIV_SCHEMA, 0, schema_ds4x_compat, 0);
|
||||
- if(rc){
|
||||
+ if (rc) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "schema",
|
||||
+ "parse_oc_str returned error: %s\n",
|
||||
+ errorbuf[0]?errorbuf:"unknown");
|
||||
attr_syntax_free(at);
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.4.11
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
From bc3328ebbe1b8279f77ad1020bce9fb638d4c94c Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Fri, 8 Apr 2016 14:17:12 -0700
|
||||
Subject: [PATCH 91/93] Ticket #48492 - heap corruption at schema replication.
|
||||
|
||||
Bug Description: If nsslapd-enquote-sup-oc is on, the server is supposed to
|
||||
handle the quoted SYNTAX values although the spec is deprecated. Currently,
|
||||
if nsslapd-enquote-sup-oc is on, it wraps SYNTAX values with quotes, but the
|
||||
information is not passed to the openldap schema parser where the parsing the
|
||||
schema fails.
|
||||
|
||||
Fix Description: This patch passes the info (flag LDAP_SCHEMA_ALLOW_QUOTED)
|
||||
to the openldap API ldap_str2attributetype if nsslapd-enquote-sup-oc is on.
|
||||
|
||||
Additionally, to support the old style quoted SYNTAX values in the schema
|
||||
files, loading the schema has to get the enquote information prior to the
|
||||
configuration parameters evaluated. To pass the information, this patch
|
||||
accepts the environment variable LDAP_SCHEMA_ALLOW_QUOTED. If it is defined
|
||||
with any value, old style schema files are processed.
|
||||
|
||||
To set the environment variable, add
|
||||
LDAP_SCHEMA_ALLOW_QUOTED="on"
|
||||
to /etc/sysconfig/dirsrv-INSTANCE.
|
||||
|
||||
https://fedorahosted.org/389/ticket/48492
|
||||
|
||||
Reviewed by firstyear@redhat.com (Thank you, William!!)
|
||||
|
||||
(cherry picked from commit 955dc66d42511c2cc8d6ff18cf030508f6da2770)
|
||||
(cherry picked from commit 7927e4420fb185ae328d56cfd4741583ae1f667b)
|
||||
---
|
||||
ldap/servers/slapd/schema.c | 66 ++++++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 51 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c
|
||||
index dd56599..806c38d 100644
|
||||
--- a/ldap/servers/slapd/schema.c
|
||||
+++ b/ldap/servers/slapd/schema.c
|
||||
@@ -1638,6 +1638,16 @@ schema_attr_enum_callback(struct asyntaxinfo *asip, void *arg)
|
||||
}
|
||||
|
||||
if ( !aew->schema_ds4x_compat ) {
|
||||
+#if defined (USE_OPENLDAP)
|
||||
+ /*
|
||||
+ * These values in quotes are not supported by the openldap parser.
|
||||
+ * Even if nsslapd-enquote-sup-oc is on, quotes should not be added.
|
||||
+ */
|
||||
+ outp += put_tagged_oid( outp, "SUP ", asip->asi_superior, NULL, 0 );
|
||||
+ outp += put_tagged_oid( outp, "EQUALITY ", asip->asi_mr_equality, NULL, 0 );
|
||||
+ outp += put_tagged_oid( outp, "ORDERING ", asip->asi_mr_ordering, NULL, 0 );
|
||||
+ outp += put_tagged_oid( outp, "SUBSTR ", asip->asi_mr_substring, NULL, 0 );
|
||||
+#else
|
||||
outp += put_tagged_oid( outp, "SUP ",
|
||||
asip->asi_superior, NULL, aew->enquote_sup_oc );
|
||||
outp += put_tagged_oid( outp, "EQUALITY ",
|
||||
@@ -1646,6 +1656,7 @@ schema_attr_enum_callback(struct asyntaxinfo *asip, void *arg)
|
||||
asip->asi_mr_ordering, NULL, aew->enquote_sup_oc );
|
||||
outp += put_tagged_oid( outp, "SUBSTR ",
|
||||
asip->asi_mr_substring, NULL, aew->enquote_sup_oc );
|
||||
+#endif
|
||||
}
|
||||
|
||||
outp += put_tagged_oid( outp, "SYNTAX ", syntaxoid, syntaxlengthbuf,
|
||||
@@ -4105,7 +4116,7 @@ parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
|
||||
char **attr_names = NULL;
|
||||
unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
|
||||
/* If we ever accept openldap schema directly, then make parser_flags configurable */
|
||||
- const int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
||||
+ unsigned int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
||||
int invalid_syntax_error;
|
||||
int syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
|
||||
int num_names = 0;
|
||||
@@ -4113,6 +4124,17 @@ parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
|
||||
int rc = 0;
|
||||
int a, aa;
|
||||
|
||||
+ if (config_get_enquote_sup_oc()) {
|
||||
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
||||
+ } else if (getenv("LDAP_SCHEMA_ALLOW_QUOTED")) {
|
||||
+ char ebuf[SLAPI_DSE_RETURNTEXT_SIZE];
|
||||
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
||||
+ if (config_set_enquote_sup_oc(CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, "on", ebuf, CONFIG_APPLY)) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "schema", "Failed to enable %s: %s\n",
|
||||
+ CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, ebuf);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* OpenLDAP AttributeType struct
|
||||
*
|
||||
@@ -4159,7 +4181,7 @@ parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf,
|
||||
/* trim any leading spaces */
|
||||
input++;
|
||||
}
|
||||
- if((atype = ldap_str2attributetype(input, &rc, &errp, parser_flags )) == NULL){
|
||||
+ if((atype = ldap_str2attributetype(input, &rc, &errp, (const unsigned int)parser_flags )) == NULL){
|
||||
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, input,
|
||||
"Failed to parse attribute, error(%d - %s) at (%s)", rc, ldap_scherr2str(rc), errp );
|
||||
return invalid_syntax_error;
|
||||
@@ -4478,12 +4500,23 @@ parse_objclass_str ( const char *input, struct objclass **oc, char *errorbuf,
|
||||
char **OrigRequiredAttrsArray, **OrigAllowedAttrsArray;
|
||||
char *first_oc_name = NULL;
|
||||
/* If we ever accept openldap schema directly, then make parser_flags configurable */
|
||||
- const int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
||||
+ unsigned int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
||||
PRUint8 flags = 0;
|
||||
int invalid_syntax_error;
|
||||
int i, j;
|
||||
int rc = 0;
|
||||
|
||||
+ if (config_get_enquote_sup_oc()) {
|
||||
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
||||
+ } else if (getenv("LDAP_SCHEMA_ALLOW_QUOTED")) {
|
||||
+ char ebuf[SLAPI_DSE_RETURNTEXT_SIZE];
|
||||
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
||||
+ if (config_set_enquote_sup_oc(CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, "on", ebuf, CONFIG_APPLY)) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "schema", "Failed to enable %s: %s\n",
|
||||
+ CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, ebuf);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* openLDAP Objectclass struct
|
||||
*
|
||||
@@ -4521,10 +4554,10 @@ parse_objclass_str ( const char *input, struct objclass **oc, char *errorbuf,
|
||||
* Parse the input and create the openLdap objectclass structure
|
||||
*/
|
||||
while(isspace(*input)){
|
||||
- /* trim any leading spaces */
|
||||
+ /* trim any leading spaces */
|
||||
input++;
|
||||
}
|
||||
- if((objClass = ldap_str2objectclass(input, &rc, &errp, parser_flags )) == NULL){
|
||||
+ if((objClass = ldap_str2objectclass(input, &rc, &errp, (const unsigned int)parser_flags )) == NULL){
|
||||
schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_oc, input,
|
||||
"Failed to parse objectclass, error(%d) at (%s)", rc, errp );
|
||||
return invalid_syntax_error;
|
||||
@@ -5592,7 +5625,7 @@ get_tagged_oid( const char *tag, const char **inputp,
|
||||
PR_ASSERT( NULL != *inputp );
|
||||
PR_ASSERT( NULL != tag );
|
||||
PR_ASSERT( '\0' != tag[ 0 ] );
|
||||
- if('(' !=tag[0])
|
||||
+ if('(' !=tag[0])
|
||||
PR_ASSERT((' ' == tag[ strlen( tag ) - 1 ]) || ('(' == tag[ strlen( tag ) - 1 ]));
|
||||
|
||||
if ( NULL == strstr_fn ) {
|
||||
@@ -5611,8 +5644,8 @@ get_tagged_oid( const char *tag, const char **inputp,
|
||||
/* skip past the leading single quote, if present */
|
||||
if ( *startp == '\'' ) {
|
||||
++startp;
|
||||
- /* skip past any extra white space */
|
||||
- startp = skipWS( startp );
|
||||
+ /* skip past any extra white space */
|
||||
+ startp = skipWS( startp );
|
||||
}
|
||||
|
||||
/* locate the end of the OID */
|
||||
@@ -7155,6 +7188,7 @@ schema_berval_to_oclist(struct berval **oc_berval)
|
||||
errorbuf[0] = '\0';
|
||||
for (i = 0; oc_berval[i] != NULL; i++) {
|
||||
/* parse the objectclass value */
|
||||
+ oc = NULL;
|
||||
if (LDAP_SUCCESS != (rc = parse_oc_str(oc_berval[i]->bv_val, &oc,
|
||||
errorbuf, sizeof (errorbuf), DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_USE_PRIV_SCHEMA, 0,
|
||||
schema_ds4x_compat, oc_list))) {
|
||||
@@ -7197,12 +7231,13 @@ schema_berval_to_atlist(struct berval **at_berval)
|
||||
errorbuf[0] = '\0';
|
||||
for (i = 0; at_berval[i] != NULL; i++) {
|
||||
/* parse the objectclass value */
|
||||
+ at = NULL;
|
||||
rc = parse_at_str(at_berval[i]->bv_val, &at, errorbuf, sizeof (errorbuf),
|
||||
DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_USE_PRIV_SCHEMA, 0, schema_ds4x_compat, 0);
|
||||
if (rc) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, "schema",
|
||||
- "parse_oc_str returned error: %s\n",
|
||||
- errorbuf[0]?errorbuf:"unknown");
|
||||
+ "schema_berval_to_atlist: parse_at_str(%s) failed - %s\n",
|
||||
+ at_berval[i]->bv_val, errorbuf[0]?errorbuf:"unknown");
|
||||
attr_syntax_free(at);
|
||||
break;
|
||||
}
|
||||
@@ -7217,6 +7252,7 @@ schema_berval_to_atlist(struct berval **at_berval)
|
||||
}
|
||||
if (rc) {
|
||||
schema_atlist_free(head);
|
||||
+ head = NULL;
|
||||
}
|
||||
|
||||
return head;
|
||||
@@ -7319,12 +7355,12 @@ schema_attributetypes_superset_check(struct berval **remote_schema, char *type)
|
||||
static void
|
||||
modify_schema_internal_mod(Slapi_DN *sdn, Slapi_Mods *smods)
|
||||
{
|
||||
- Slapi_PBlock *newpb;
|
||||
+ Slapi_PBlock *newpb;
|
||||
int op_result;
|
||||
- CSN *schema_csn;
|
||||
+ CSN *schema_csn;
|
||||
|
||||
- /* allocate internal mod components: pblock*/
|
||||
- newpb = slapi_pblock_new();
|
||||
+ /* allocate internal mod components: pblock*/
|
||||
+ newpb = slapi_pblock_new();
|
||||
|
||||
slapi_modify_internal_set_pb_ext (
|
||||
newpb,
|
||||
@@ -7333,7 +7369,7 @@ modify_schema_internal_mod(Slapi_DN *sdn, Slapi_Mods *smods)
|
||||
NULL, /* Controls */
|
||||
NULL,
|
||||
(void *)plugin_get_default_component_id(),
|
||||
- 0);
|
||||
+ 0);
|
||||
|
||||
/* do modify */
|
||||
slapi_modify_internal_pb (newpb);
|
||||
--
|
||||
2.4.11
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From 39a14eaab84e7eac940d1d707cabc9610ef570c6 Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Tue, 26 Apr 2016 13:53:02 -0700
|
||||
Subject: [PATCH 92/93] Ticket #48808 - Paged results search returns the blank
|
||||
list of entries
|
||||
|
||||
Bug Description: When a simple paged results slot in a connection is
|
||||
discarded due to an error, e.g., SIZELIMIT_EXCEEDED, the slot was not
|
||||
properly cleaned up. Then, if the slot was reused, the leftover flag
|
||||
confused the code and ended up returning the 0 search result.
|
||||
|
||||
Fix Description: This patch adds the clean up code when a slot is re-
|
||||
used.
|
||||
|
||||
https://fedorahosted.org/389/ticket/48808
|
||||
|
||||
Reviewed by wibrown@redhat.com (Thank you, William!!)
|
||||
|
||||
(cherry picked from commit 09180b25570696d24c86e3a046fb497c15549c64)
|
||||
(cherry picked from commit a8486ab3b364a9ae088d6404d025058b04ac358d)
|
||||
---
|
||||
ldap/servers/slapd/pagedresults.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
|
||||
index d394dab..52d2158 100644
|
||||
--- a/ldap/servers/slapd/pagedresults.c
|
||||
+++ b/ldap/servers/slapd/pagedresults.c
|
||||
@@ -124,6 +124,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
|
||||
prp = conn->c_pagedresults.prl_list;
|
||||
for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) {
|
||||
if (!prp->pr_current_be) { /* unused slot; take it */
|
||||
+ _pr_cleanup_one_slot(prp);
|
||||
prp->pr_current_be = be;
|
||||
*index = i;
|
||||
break;
|
||||
--
|
||||
2.4.11
|
||||
|
370
SOURCES/0093-Ticket-48808-Add-test-case.patch
Normal file
370
SOURCES/0093-Ticket-48808-Add-test-case.patch
Normal file
|
@ -0,0 +1,370 @@
|
|||
From fc0ca25b9f143083528cc5f87dc89fe69baf38fd Mon Sep 17 00:00:00 2001
|
||||
From: Simon Pichugin <spichugi@redhat.com>
|
||||
Date: Thu, 28 Apr 2016 11:49:24 +0200
|
||||
Subject: [PATCH 93/93] Ticket 48808 - Add test case
|
||||
|
||||
Description: Add test case for paged results search returns the blank
|
||||
list of entries issue.
|
||||
|
||||
Bug description: After series of actions, paged result search that
|
||||
should returns list of entries returns blank list of entries. It is
|
||||
hardly reproducible manually, but it is easy to reproduce with python
|
||||
automation.
|
||||
|
||||
https://fedorahosted.org/389/ticket/48808
|
||||
|
||||
Reviewed by: nhosoi and wbrown (Thanks!)
|
||||
|
||||
(cherry picked from commit 91f3e592713ea58602412ed773a497583f2ebd6c)
|
||||
(cherry picked from commit 99b5048b09e64cea6f8bf5e7d524679960ce0a44)
|
||||
---
|
||||
dirsrvtests/tests/tickets/ticket48808_test.py | 337 ++++++++++++++++++++++++++
|
||||
1 file changed, 337 insertions(+)
|
||||
create mode 100644 dirsrvtests/tests/tickets/ticket48808_test.py
|
||||
|
||||
diff --git a/dirsrvtests/tests/tickets/ticket48808_test.py b/dirsrvtests/tests/tickets/ticket48808_test.py
|
||||
new file mode 100644
|
||||
index 0000000..3dbceac
|
||||
--- /dev/null
|
||||
+++ b/dirsrvtests/tests/tickets/ticket48808_test.py
|
||||
@@ -0,0 +1,337 @@
|
||||
+import time
|
||||
+import ldap
|
||||
+import logging
|
||||
+import pytest
|
||||
+from random import sample
|
||||
+from ldap.controls import SimplePagedResultsControl
|
||||
+from lib389 import DirSrv, Entry, tools, tasks
|
||||
+from lib389.tools import DirSrvTools
|
||||
+from lib389._constants import *
|
||||
+from lib389.properties import *
|
||||
+from lib389.tasks import *
|
||||
+from lib389.utils import *
|
||||
+
|
||||
+logging.getLogger(__name__).setLevel(logging.DEBUG)
|
||||
+log = logging.getLogger(__name__)
|
||||
+
|
||||
+TEST_USER_NAME = 'simplepaged_test'
|
||||
+TEST_USER_DN = 'uid=%s,%s' % (TEST_USER_NAME, DEFAULT_SUFFIX)
|
||||
+TEST_USER_PWD = 'simplepaged_test'
|
||||
+
|
||||
+
|
||||
+class TopologyStandalone(object):
|
||||
+ def __init__(self, standalone):
|
||||
+ standalone.open()
|
||||
+ self.standalone = standalone
|
||||
+
|
||||
+
|
||||
+@pytest.fixture(scope="module")
|
||||
+def topology(request):
|
||||
+ # Creating standalone instance ...
|
||||
+ standalone = DirSrv(verbose=False)
|
||||
+ args_instance[SER_HOST] = HOST_STANDALONE
|
||||
+ args_instance[SER_PORT] = PORT_STANDALONE
|
||||
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
||||
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
||||
+ args_standalone = args_instance.copy()
|
||||
+ standalone.allocate(args_standalone)
|
||||
+ instance_standalone = standalone.exists()
|
||||
+ if instance_standalone:
|
||||
+ standalone.delete()
|
||||
+ standalone.create()
|
||||
+ standalone.open()
|
||||
+
|
||||
+ # Delete each instance in the end
|
||||
+ def fin():
|
||||
+ standalone.delete()
|
||||
+ request.addfinalizer(fin)
|
||||
+
|
||||
+ # Clear out the tmp dir
|
||||
+ standalone.clearTmpDir(__file__)
|
||||
+
|
||||
+ return TopologyStandalone(standalone)
|
||||
+
|
||||
+
|
||||
+@pytest.fixture(scope="module")
|
||||
+def test_user(topology):
|
||||
+ """User for binding operation"""
|
||||
+
|
||||
+ try:
|
||||
+ topology.standalone.add_s(Entry((TEST_USER_DN, {
|
||||
+ 'objectclass': 'top person'.split(),
|
||||
+ 'objectclass': 'organizationalPerson',
|
||||
+ 'objectclass': 'inetorgperson',
|
||||
+ 'cn': TEST_USER_NAME,
|
||||
+ 'sn': TEST_USER_NAME,
|
||||
+ 'userpassword': TEST_USER_PWD,
|
||||
+ 'mail': '%s@redhat.com' % TEST_USER_NAME,
|
||||
+ 'uid': TEST_USER_NAME
|
||||
+ })))
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
|
||||
+ e.message['desc']))
|
||||
+ raise e
|
||||
+
|
||||
+
|
||||
+def add_users(topology, users_num):
|
||||
+ """Add users to the default suffix
|
||||
+ and return a list of added user DNs.
|
||||
+ """
|
||||
+
|
||||
+ users_list = []
|
||||
+ log.info('Adding %d users' % users_num)
|
||||
+ for num in sample(range(1000), users_num):
|
||||
+ num_ran = int(round(num))
|
||||
+ USER_NAME = 'test%05d' % num_ran
|
||||
+ USER_DN = 'uid=%s,%s' % (USER_NAME, DEFAULT_SUFFIX)
|
||||
+ users_list.append(USER_DN)
|
||||
+ try:
|
||||
+ topology.standalone.add_s(Entry((USER_DN, {
|
||||
+ 'objectclass': 'top person'.split(),
|
||||
+ 'objectclass': 'organizationalPerson',
|
||||
+ 'objectclass': 'inetorgperson',
|
||||
+ 'cn': USER_NAME,
|
||||
+ 'sn': USER_NAME,
|
||||
+ 'userpassword': 'pass%s' % num_ran,
|
||||
+ 'mail': '%s@redhat.com' % USER_NAME,
|
||||
+ 'uid': USER_NAME
|
||||
+ })))
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.error('Failed to add user (%s): error (%s)' % (USER_DN,
|
||||
+ e.message['desc']))
|
||||
+ raise e
|
||||
+ return users_list
|
||||
+
|
||||
+
|
||||
+def del_users(topology, users_list):
|
||||
+ """Delete users with DNs from given list"""
|
||||
+
|
||||
+ log.info('Deleting %d users' % len(users_list))
|
||||
+ for user_dn in users_list:
|
||||
+ try:
|
||||
+ topology.standalone.delete_s(user_dn)
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.error('Failed to delete user (%s): error (%s)' % (user_dn,
|
||||
+ e.message['desc']))
|
||||
+ raise e
|
||||
+
|
||||
+
|
||||
+def change_conf_attr(topology, suffix, attr_name, attr_value):
|
||||
+ """Change configurational attribute in the given suffix.
|
||||
+ Funtion returns previous attribute value.
|
||||
+ """
|
||||
+
|
||||
+ try:
|
||||
+ entries = topology.standalone.search_s(suffix, ldap.SCOPE_BASE,
|
||||
+ 'objectclass=top',
|
||||
+ [attr_name])
|
||||
+ attr_value_bck = entries[0].data.get(attr_name)
|
||||
+ log.info('Set %s to %s. Previous value - %s. Modified suffix - %s.' % (
|
||||
+ attr_name, attr_value, attr_value_bck, suffix))
|
||||
+ if attr_value is None:
|
||||
+ topology.standalone.modify_s(suffix, [(ldap.MOD_DELETE,
|
||||
+ attr_name,
|
||||
+ attr_value)])
|
||||
+ else:
|
||||
+ topology.standalone.modify_s(suffix, [(ldap.MOD_REPLACE,
|
||||
+ attr_name,
|
||||
+ attr_value)])
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.error('Failed to change attr value (%s): error (%s)' % (attr_name,
|
||||
+ e.message['desc']))
|
||||
+ raise e
|
||||
+
|
||||
+ return attr_value_bck
|
||||
+
|
||||
+
|
||||
+def paged_search(topology, controls, search_flt, searchreq_attrlist):
|
||||
+ """Search at the DEFAULT_SUFFIX with ldap.SCOPE_SUBTREE
|
||||
+ using Simple Paged Control(should the first item in the
|
||||
+ list controls.
|
||||
+ Return the list with results summarized from all pages
|
||||
+ """
|
||||
+
|
||||
+ pages = 0
|
||||
+ pctrls = []
|
||||
+ all_results = []
|
||||
+ req_ctrl = controls[0]
|
||||
+ msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
|
||||
+ ldap.SCOPE_SUBTREE,
|
||||
+ search_flt,
|
||||
+ searchreq_attrlist,
|
||||
+ serverctrls=controls)
|
||||
+ while True:
|
||||
+ log.info('Getting page %d' % (pages,))
|
||||
+ rtype, rdata, rmsgid, rctrls = topology.standalone.result3(msgid)
|
||||
+ all_results.extend(rdata)
|
||||
+ pages += 1
|
||||
+ pctrls = [
|
||||
+ c
|
||||
+ for c in rctrls
|
||||
+ if c.controlType == SimplePagedResultsControl.controlType
|
||||
+ ]
|
||||
+
|
||||
+ if pctrls:
|
||||
+ if pctrls[0].cookie:
|
||||
+ # Copy cookie from response control to request control
|
||||
+ req_ctrl.cookie = pctrls[0].cookie
|
||||
+ msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
|
||||
+ ldap.SCOPE_SUBTREE,
|
||||
+ search_flt,
|
||||
+ searchreq_attrlist,
|
||||
+ serverctrls=controls)
|
||||
+ else:
|
||||
+ break # no more pages available
|
||||
+ else:
|
||||
+ break
|
||||
+
|
||||
+ assert not pctrls[0].cookie
|
||||
+ return all_results
|
||||
+
|
||||
+
|
||||
+def test_ticket48808(topology, test_user):
|
||||
+ log.info('Run multiple paging controls on a single connection')
|
||||
+ users_num = 100
|
||||
+ page_size = 30
|
||||
+ users_list = add_users(topology, users_num)
|
||||
+ search_flt = r'(uid=test*)'
|
||||
+ searchreq_attrlist = ['dn', 'sn']
|
||||
+
|
||||
+ log.info('Set user bind')
|
||||
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
||||
+
|
||||
+ log.info('Create simple paged results control instance')
|
||||
+ req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
|
||||
+ controls = [req_ctrl]
|
||||
+
|
||||
+ for ii in xrange(3):
|
||||
+ log.info('Iteration %d' % ii)
|
||||
+ msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
|
||||
+ ldap.SCOPE_SUBTREE,
|
||||
+ search_flt,
|
||||
+ searchreq_attrlist,
|
||||
+ serverctrls=controls)
|
||||
+ rtype, rdata, rmsgid, rctrls = topology.standalone.result3(msgid)
|
||||
+ pctrls = [
|
||||
+ c
|
||||
+ for c in rctrls
|
||||
+ if c.controlType == SimplePagedResultsControl.controlType
|
||||
+ ]
|
||||
+
|
||||
+ req_ctrl.cookie = pctrls[0].cookie
|
||||
+ msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
|
||||
+ ldap.SCOPE_SUBTREE,
|
||||
+ search_flt,
|
||||
+ searchreq_attrlist,
|
||||
+ serverctrls=controls)
|
||||
+ log.info('Set Directory Manager bind back')
|
||||
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
||||
+ del_users(topology, users_list)
|
||||
+
|
||||
+ log.info('Abandon the search')
|
||||
+ users_num = 10
|
||||
+ page_size = 0
|
||||
+ users_list = add_users(topology, users_num)
|
||||
+ search_flt = r'(uid=test*)'
|
||||
+ searchreq_attrlist = ['dn', 'sn']
|
||||
+
|
||||
+ log.info('Set user bind')
|
||||
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
||||
+
|
||||
+ log.info('Create simple paged results control instance')
|
||||
+ req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
|
||||
+ controls = [req_ctrl]
|
||||
+
|
||||
+ msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
|
||||
+ ldap.SCOPE_SUBTREE,
|
||||
+ search_flt,
|
||||
+ searchreq_attrlist,
|
||||
+ serverctrls=controls)
|
||||
+ rtype, rdata, rmsgid, rctrls = topology.standalone.result3(msgid)
|
||||
+ pctrls = [
|
||||
+ c
|
||||
+ for c in rctrls
|
||||
+ if c.controlType == SimplePagedResultsControl.controlType
|
||||
+ ]
|
||||
+ assert not pctrls[0].cookie
|
||||
+
|
||||
+ log.info('Set Directory Manager bind back')
|
||||
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
||||
+ del_users(topology, users_list)
|
||||
+
|
||||
+ log.info("Search should fail with 'nsPagedSizeLimit = 5'"
|
||||
+ "and 'nsslapd-pagedsizelimit = 15' with 10 users")
|
||||
+ conf_attr = '15'
|
||||
+ user_attr = '5'
|
||||
+ expected_rs = ldap.SIZELIMIT_EXCEEDED
|
||||
+ users_num = 10
|
||||
+ page_size = 10
|
||||
+ users_list = add_users(topology, users_num)
|
||||
+ search_flt = r'(uid=test*)'
|
||||
+ searchreq_attrlist = ['dn', 'sn']
|
||||
+ conf_attr_bck = change_conf_attr(topology, DN_CONFIG,
|
||||
+ 'nsslapd-pagedsizelimit', conf_attr)
|
||||
+ user_attr_bck = change_conf_attr(topology, TEST_USER_DN,
|
||||
+ 'nsPagedSizeLimit', user_attr)
|
||||
+
|
||||
+ log.info('Set user bind')
|
||||
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
||||
+
|
||||
+ log.info('Create simple paged results control instance')
|
||||
+ req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
|
||||
+ controls = [req_ctrl]
|
||||
+
|
||||
+ log.info('Expect to fail with SIZELIMIT_EXCEEDED')
|
||||
+ with pytest.raises(expected_rs):
|
||||
+ all_results = paged_search(topology, controls,
|
||||
+ search_flt, searchreq_attrlist)
|
||||
+
|
||||
+ log.info('Set Directory Manager bind back')
|
||||
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
||||
+ del_users(topology, users_list)
|
||||
+ change_conf_attr(topology, DN_CONFIG,
|
||||
+ 'nsslapd-pagedsizelimit', conf_attr_bck)
|
||||
+ change_conf_attr(topology, TEST_USER_DN,
|
||||
+ 'nsPagedSizeLimit', user_attr_bck)
|
||||
+
|
||||
+ log.info("Search should pass with 'nsPagedSizeLimit = 15'"
|
||||
+ "and 'nsslapd-pagedsizelimit = 5' with 10 users")
|
||||
+ conf_attr = '5'
|
||||
+ user_attr = '15'
|
||||
+ users_num = 10
|
||||
+ page_size = 10
|
||||
+ users_list = add_users(topology, users_num)
|
||||
+ search_flt = r'(uid=test*)'
|
||||
+ searchreq_attrlist = ['dn', 'sn']
|
||||
+ conf_attr_bck = change_conf_attr(topology, DN_CONFIG,
|
||||
+ 'nsslapd-pagedsizelimit', conf_attr)
|
||||
+ user_attr_bck = change_conf_attr(topology, TEST_USER_DN,
|
||||
+ 'nsPagedSizeLimit', user_attr)
|
||||
+
|
||||
+ log.info('Set user bind')
|
||||
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
||||
+
|
||||
+ log.info('Create simple paged results control instance')
|
||||
+ req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
|
||||
+ controls = [req_ctrl]
|
||||
+
|
||||
+ log.info('Search should PASS')
|
||||
+ all_results = paged_search(topology, controls,
|
||||
+ search_flt, searchreq_attrlist)
|
||||
+ log.info('%d results' % len(all_results))
|
||||
+ assert len(all_results) == len(users_list)
|
||||
+
|
||||
+ log.info('Set Directory Manager bind back')
|
||||
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
||||
+ del_users(topology, users_list)
|
||||
+ change_conf_attr(topology, DN_CONFIG,
|
||||
+ 'nsslapd-pagedsizelimit', conf_attr_bck)
|
||||
+ change_conf_attr(topology, TEST_USER_DN,
|
||||
+ 'nsPagedSizeLimit', user_attr_bck)
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ # Run isolated
|
||||
+ # -s for DEBUG mode
|
||||
+ CURRENT_FILE = os.path.realpath(__file__)
|
||||
+ pytest.main("-s %s" % CURRENT_FILE)
|
||||
--
|
||||
2.4.11
|
||||
|
|
@ -0,0 +1,936 @@
|
|||
From 72562d03b0f758902e0ee858fd43d5bcfbef379b Mon Sep 17 00:00:00 2001
|
||||
From: Mark Reynolds <mreynolds@redhat.com>
|
||||
Date: Tue, 7 Jun 2016 10:02:42 -0400
|
||||
Subject: [PATCH] Ticket 48862 - At startup DES to AES password conversion
|
||||
causes timeout in start script
|
||||
|
||||
Bug Description: At server start all the backends are searches for entries that contain
|
||||
DES password attributes as defined in the plugin. These are typically
|
||||
unindexed searches, and if there is a very large backend this can cause
|
||||
the server startup to timeout.
|
||||
|
||||
Fix Description: At startup only check "cn=config" for entries with DES password attributes.
|
||||
A new "conversion" task has been created that can be run after startup
|
||||
to search all backends(if a suffix is not specified), or specific backends.
|
||||
|
||||
dn: cn=convertPasswords, cn=des2aes,cn=tasks,cn=config
|
||||
objectclass: top
|
||||
objectclass: extensibleObject
|
||||
suffix: dc=example,dc=com
|
||||
suffix: dc=other,dc=suffix
|
||||
|
||||
Another bug was discovered in pw_rever_encode() in pw.c where a "for" loop
|
||||
counter was accidentially reused by a second "for" loop. This could lead
|
||||
to an infinite loop/hang.
|
||||
|
||||
Updated the CI test to perform the conversion task.
|
||||
|
||||
https://fedorahosted.org/389/ticket/48862
|
||||
|
||||
Reviewed by: nhosoi(Thanks!)
|
||||
|
||||
(cherry picked from commit 11f55f3dd2a2c44ddf7b5be54273401add13b1bc)
|
||||
(cherry picked from commit c0ad918939c40779e463b71c41ab106e7ee890e2)
|
||||
---
|
||||
dirsrvtests/tickets/ticket47462_test.py | 133 ++++++++----
|
||||
ldap/servers/slapd/daemon.c | 195 +++++-------------
|
||||
ldap/servers/slapd/pw.c | 4 +-
|
||||
ldap/servers/slapd/task.c | 346 +++++++++++++++++++++++++++++++-
|
||||
4 files changed, 493 insertions(+), 185 deletions(-)
|
||||
|
||||
diff --git a/dirsrvtests/tickets/ticket47462_test.py b/dirsrvtests/tickets/ticket47462_test.py
|
||||
index 17854fa..2d2c507 100644
|
||||
--- a/dirsrvtests/tickets/ticket47462_test.py
|
||||
+++ b/dirsrvtests/tickets/ticket47462_test.py
|
||||
@@ -32,6 +32,7 @@ AGMT_DN = ''
|
||||
USER_DN = 'cn=test_user,' + DEFAULT_SUFFIX
|
||||
USER1_DN = 'cn=test_user1,' + DEFAULT_SUFFIX
|
||||
TEST_REPL_DN = 'cn=test repl,' + DEFAULT_SUFFIX
|
||||
+DES2AES_TASK_DN = 'cn=convert,cn=des2aes,cn=tasks,cn=config'
|
||||
|
||||
|
||||
class TopologyMaster1Master2(object):
|
||||
@@ -134,6 +135,11 @@ def topology(request):
|
||||
# clear the tmp directory
|
||||
master1.clearTmpDir(__file__)
|
||||
|
||||
+ def fin():
|
||||
+ master1.delete()
|
||||
+ master2.delete()
|
||||
+ request.addfinalizer(fin)
|
||||
+
|
||||
return TopologyMaster1Master2(master1, master2)
|
||||
|
||||
|
||||
@@ -144,11 +150,9 @@ def test_ticket47462(topology):
|
||||
"""
|
||||
|
||||
#
|
||||
- # First set config as if it's an older version. Set DES to use libdes-plugin,
|
||||
- # MMR to depend on DES, delete the existing AES plugin, and set a DES password
|
||||
- # for the replication agreement.
|
||||
- #
|
||||
-
|
||||
+ # First set config as if it's an older version. Set DES to use
|
||||
+ # libdes-plugin, MMR to depend on DES, delete the existing AES plugin,
|
||||
+ # and set a DES password for the replication agreement.
|
||||
#
|
||||
# Add an extra attribute to the DES plugin args
|
||||
#
|
||||
@@ -168,7 +172,9 @@ def test_ticket47462(topology):
|
||||
|
||||
try:
|
||||
topology.master1.modify_s(MMR_PLUGIN,
|
||||
- [(ldap.MOD_DELETE, 'nsslapd-plugin-depends-on-named', 'AES')])
|
||||
+ [(ldap.MOD_DELETE,
|
||||
+ 'nsslapd-plugin-depends-on-named',
|
||||
+ 'AES')])
|
||||
|
||||
except ldap.NO_SUCH_ATTRIBUTE:
|
||||
pass
|
||||
@@ -194,7 +200,8 @@ def test_ticket47462(topology):
|
||||
# Get the agmt dn, and set the password
|
||||
#
|
||||
try:
|
||||
- entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'objectclass=nsDS5ReplicationAgreement')
|
||||
+ entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE,
|
||||
+ 'objectclass=nsDS5ReplicationAgreement')
|
||||
if entry:
|
||||
agmt_dn = entry[0].dn
|
||||
log.info('Found agmt dn (%s)' % agmt_dn)
|
||||
@@ -207,7 +214,8 @@ def test_ticket47462(topology):
|
||||
|
||||
try:
|
||||
properties = {RA_BINDPW: "password"}
|
||||
- topology.master1.agreement.setProperties(None, agmt_dn, None, properties)
|
||||
+ topology.master1.agreement.setProperties(None, agmt_dn, None,
|
||||
+ properties)
|
||||
log.info('Successfully modified replication agreement')
|
||||
except ValueError:
|
||||
log.error('Failed to update replica agreement: ' + AGMT_DN)
|
||||
@@ -220,12 +228,14 @@ def test_ticket47462(topology):
|
||||
topology.master1.add_s(Entry((USER1_DN,
|
||||
{'objectclass': "top person".split(),
|
||||
'sn': 'sn',
|
||||
+ 'description': 'DES value to convert',
|
||||
'cn': 'test_user'})))
|
||||
loop = 0
|
||||
ent = None
|
||||
while loop <= 10:
|
||||
try:
|
||||
- ent = topology.master2.getEntry(USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)")
|
||||
+ ent = topology.master2.getEntry(USER1_DN, ldap.SCOPE_BASE,
|
||||
+ "(objectclass=*)")
|
||||
break
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
time.sleep(1)
|
||||
@@ -250,7 +260,8 @@ def test_ticket47462(topology):
|
||||
# Check that the restart converted existing DES credentials
|
||||
#
|
||||
try:
|
||||
- entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'nsDS5ReplicaCredentials=*')
|
||||
+ entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE,
|
||||
+ 'nsDS5ReplicaCredentials=*')
|
||||
if entry:
|
||||
val = entry[0].getValue('nsDS5ReplicaCredentials')
|
||||
if val.startswith('{AES-'):
|
||||
@@ -259,22 +270,25 @@ def test_ticket47462(topology):
|
||||
log.fatal('Failed to convert credentials from DES to AES!')
|
||||
assert False
|
||||
else:
|
||||
- log.fatal('Failed to find any entries with nsDS5ReplicaCredentials ')
|
||||
+ log.fatal('Failed to find entries with nsDS5ReplicaCredentials')
|
||||
assert False
|
||||
except ldap.LDAPError, e:
|
||||
log.fatal('Failed to search for replica credentials: ' + e.message['desc'])
|
||||
assert False
|
||||
|
||||
#
|
||||
- # Check that the AES plugin exists, and has all the attributes listed in DES plugin.
|
||||
- # The attributes might not be in the expected order so check all the attributes.
|
||||
+ # Check that the AES plugin exists, and has all the attributes listed in
|
||||
+ # DES plugin. The attributes might not be in the expected order so check
|
||||
+ # all the attributes.
|
||||
#
|
||||
try:
|
||||
- entry = topology.master1.search_s(AES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
|
||||
+ entry = topology.master1.search_s(AES_PLUGIN, ldap.SCOPE_BASE,
|
||||
+ 'objectclass=*')
|
||||
if not entry[0].hasValue('nsslapd-pluginarg0', 'description') and \
|
||||
not entry[0].hasValue('nsslapd-pluginarg1', 'description') and \
|
||||
not entry[0].hasValue('nsslapd-pluginarg2', 'description'):
|
||||
- log.fatal('The AES plugin did not have the DES attribute copied over correctly')
|
||||
+ log.fatal('The AES plugin did not have the DES attribute copied ' +
|
||||
+ 'over correctly')
|
||||
assert False
|
||||
else:
|
||||
log.info('The AES plugin was correctly setup')
|
||||
@@ -286,7 +300,8 @@ def test_ticket47462(topology):
|
||||
# Check that the MMR plugin was updated
|
||||
#
|
||||
try:
|
||||
- entry = topology.master1.search_s(MMR_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
|
||||
+ entry = topology.master1.search_s(MMR_PLUGIN, ldap.SCOPE_BASE,
|
||||
+ 'objectclass=*')
|
||||
if not entry[0].hasValue('nsslapd-plugin-depends-on-named', 'AES'):
|
||||
log.fatal('The MMR Plugin was not correctly updated')
|
||||
assert False
|
||||
@@ -300,7 +315,8 @@ def test_ticket47462(topology):
|
||||
# Check that the DES plugin was correctly updated
|
||||
#
|
||||
try:
|
||||
- entry = topology.master1.search_s(DES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
|
||||
+ entry = topology.master1.search_s(DES_PLUGIN, ldap.SCOPE_BASE,
|
||||
+ 'objectclass=*')
|
||||
if not entry[0].hasValue('nsslapd-pluginPath', 'libpbe-plugin'):
|
||||
log.fatal('The DES Plugin was not correctly updated')
|
||||
assert False
|
||||
@@ -322,7 +338,8 @@ def test_ticket47462(topology):
|
||||
ent = None
|
||||
while loop <= 10:
|
||||
try:
|
||||
- ent = topology.master2.getEntry(USER_DN, ldap.SCOPE_BASE, "(objectclass=*)")
|
||||
+ ent = topology.master2.getEntry(USER_DN, ldap.SCOPE_BASE,
|
||||
+ "(objectclass=*)")
|
||||
break
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
time.sleep(1)
|
||||
@@ -336,30 +353,66 @@ def test_ticket47462(topology):
|
||||
log.fatal('Failed to add test user: ' + e.message['desc'])
|
||||
assert False
|
||||
|
||||
+ # Check the entry
|
||||
+ log.info('Entry before running task...')
|
||||
+ try:
|
||||
+ entry = topology.master1.search_s(USER1_DN,
|
||||
+ ldap.SCOPE_BASE,
|
||||
+ 'objectclass=*')
|
||||
+ if entry:
|
||||
+ print(str(entry))
|
||||
+ else:
|
||||
+ log.fatal('Failed to find entries')
|
||||
+ assert False
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.fatal('Failed to search for entries: ' +
|
||||
+ e.message['desc'])
|
||||
+ assert False
|
||||
|
||||
-def test_ticket47462_final(topology):
|
||||
- topology.master1.delete()
|
||||
- topology.master2.delete()
|
||||
- log.info('Testcase PASSED')
|
||||
-
|
||||
-
|
||||
-def run_isolated():
|
||||
- '''
|
||||
- run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
|
||||
- To run isolated without py.test, you need to
|
||||
- - edit this file and comment '@pytest.fixture' line before 'topology' function.
|
||||
- - set the installation prefix
|
||||
- - run this program
|
||||
- '''
|
||||
- global installation1_prefix
|
||||
- global installation2_prefix
|
||||
- installation1_prefix = None
|
||||
- installation2_prefix = None
|
||||
+ #
|
||||
+ # Test the DES2AES Task on USER1_DN
|
||||
+ #
|
||||
+ try:
|
||||
+ topology.master1.add_s(Entry((DES2AES_TASK_DN,
|
||||
+ {'objectclass': ['top',
|
||||
+ 'extensibleObject'],
|
||||
+ 'suffix': DEFAULT_SUFFIX,
|
||||
+ 'cn': 'convert'})))
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.fatal('Failed to add task entry: ' + e.message['desc'])
|
||||
+ assert False
|
||||
|
||||
- topo = topology(True)
|
||||
- test_ticket47462(topo)
|
||||
- test_ticket47462_final(topo)
|
||||
+ # Wait for task
|
||||
+ task_entry = Entry(DES2AES_TASK_DN)
|
||||
+ (done, exitCode) = topology.master1.tasks.checkTask(task_entry, True)
|
||||
+ if exitCode:
|
||||
+ log.fatal("Error: des2aes task exited with %d" % (exitCode))
|
||||
+ assert False
|
||||
|
||||
+ # Check the entry
|
||||
+ try:
|
||||
+ entry = topology.master1.search_s(USER1_DN,
|
||||
+ ldap.SCOPE_BASE,
|
||||
+ 'objectclass=*')
|
||||
+ if entry:
|
||||
+ val = entry[0].getValue('description')
|
||||
+ print(str(entry[0]))
|
||||
+ if val.startswith('{AES-'):
|
||||
+ log.info('Task: DES credentials have been converted to AES')
|
||||
+ else:
|
||||
+ log.fatal('Task: Failed to convert credentials from DES to ' +
|
||||
+ 'AES! (%s)' % (val))
|
||||
+ assert False
|
||||
+ else:
|
||||
+ log.fatal('Failed to find entries')
|
||||
+ assert False
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.fatal('Failed to search for entries: ' +
|
||||
+ e.message['desc'])
|
||||
+ assert False
|
||||
|
||||
if __name__ == '__main__':
|
||||
- run_isolated()
|
||||
+ # Run isolated
|
||||
+ # -s for DEBUG mode
|
||||
+ CURRENT_FILE = os.path.realpath(__file__)
|
||||
+ pytest.main("-s %s" % CURRENT_FILE)
|
||||
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
|
||||
index d702129..29562ae 100644
|
||||
--- a/ldap/servers/slapd/daemon.c
|
||||
+++ b/ldap/servers/slapd/daemon.c
|
||||
@@ -692,14 +692,12 @@ convert_pbe_des_to_aes()
|
||||
Slapi_Entry **entries = NULL;
|
||||
struct slapdplugin *plugin = NULL;
|
||||
char **attrs = NULL;
|
||||
- char **backends = NULL;
|
||||
char *val = NULL;
|
||||
int converted_des_passwd = 0;
|
||||
- int disable_des = 1;
|
||||
int result = -1;
|
||||
int have_aes = 0;
|
||||
int have_des = 0;
|
||||
- int i = 0, ii = 0, be_idx = 0;
|
||||
+ int i = 0, ii = 0;
|
||||
|
||||
/*
|
||||
* Check that AES plugin is enabled, and grab all the unique
|
||||
@@ -733,94 +731,56 @@ convert_pbe_des_to_aes()
|
||||
|
||||
if(have_aes && have_des){
|
||||
/*
|
||||
- * Build a list of all the backend dn's
|
||||
+ * Find any entries in cn=config that contain DES passwords and convert
|
||||
+ * them to AES
|
||||
*/
|
||||
- Slapi_Backend *be = NULL;
|
||||
- struct suffixlist *list;
|
||||
- char *cookie = NULL;
|
||||
-
|
||||
- LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes: "
|
||||
- "Checking for DES passwords to convert to AES...\n",0,0,0);
|
||||
-
|
||||
- be = slapi_get_first_backend(&cookie);
|
||||
- while (be){
|
||||
- int suffix_idx = 0;
|
||||
- int count = slapi_counter_get_value(be->be_suffixcounter);
|
||||
-
|
||||
- list = be->be_suffixlist;
|
||||
- for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) {
|
||||
- char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix);
|
||||
- if(charray_inlist(backends, suffix) || strlen(suffix) == 0){
|
||||
- list = list->next;
|
||||
- continue;
|
||||
- }
|
||||
- charray_add(&backends, slapi_ch_strdup(suffix));
|
||||
- list = list->next;
|
||||
- }
|
||||
- be = slapi_get_next_backend (cookie);
|
||||
- }
|
||||
- slapi_ch_free ((void **)&cookie);
|
||||
+ slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes",
|
||||
+ "Converting DES passwords to AES...\n");
|
||||
|
||||
- /*
|
||||
- * Search for the password attributes
|
||||
- */
|
||||
for (i = 0; attrs && attrs[i]; i++){
|
||||
char *filter = PR_smprintf("%s=*", attrs[i]);
|
||||
- /*
|
||||
- * Loop over all the backends looking for the password attribute
|
||||
- */
|
||||
- for(be_idx = 0; backends && backends[be_idx]; be_idx++){
|
||||
- pb = slapi_pblock_new();
|
||||
- slapi_search_internal_set_pb(pb, backends[be_idx],
|
||||
- LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
|
||||
- (void *)plugin_get_default_component_id(),
|
||||
- SLAPI_OP_FLAG_IGNORE_UNINDEXED);
|
||||
- slapi_search_internal_pb(pb);
|
||||
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
||||
- if (LDAP_SUCCESS != result) {
|
||||
- slapi_log_error(SLAPI_LOG_TRACE, "convert_pbe_des_to_aes: ",
|
||||
- "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
|
||||
- attrs[i], result, backends[be_idx]);
|
||||
- slapi_free_search_results_internal(pb);
|
||||
- slapi_pblock_destroy(pb);
|
||||
- pb = NULL;
|
||||
- continue;
|
||||
- }
|
||||
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
- for (ii = 0; entries && entries[ii]; ii++){
|
||||
- if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
|
||||
- if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
|
||||
- /*
|
||||
- * We have a DES encoded password, convert it AES
|
||||
- */
|
||||
- Slapi_PBlock *mod_pb = NULL;
|
||||
- Slapi_Value *sval = NULL;
|
||||
- LDAPMod mod_replace;
|
||||
- LDAPMod *mods[2];
|
||||
- char *replace_val[2];
|
||||
- char *passwd = NULL;
|
||||
-
|
||||
- /* decode the DES password */
|
||||
- if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
- "Failed to decode existing DES password for (%s)\n",
|
||||
- slapi_entry_get_dn(entries[ii]), 0, 0);
|
||||
- disable_des = 0;
|
||||
- goto done;
|
||||
- }
|
||||
|
||||
- /* encode the password */
|
||||
+ pb = slapi_pblock_new();
|
||||
+ slapi_search_internal_set_pb(pb, "cn=config",
|
||||
+ LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
|
||||
+ (void *)plugin_get_default_component_id(),
|
||||
+ SLAPI_OP_FLAG_IGNORE_UNINDEXED);
|
||||
+ slapi_search_internal_pb(pb);
|
||||
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
+ for (ii = 0; entries && entries[ii]; ii++){
|
||||
+ if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
|
||||
+ if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
|
||||
+ /*
|
||||
+ * We have a DES encoded password, convert it to AES
|
||||
+ */
|
||||
+ Slapi_PBlock *mod_pb = NULL;
|
||||
+ Slapi_Value *sval = NULL;
|
||||
+ LDAPMod mod_replace;
|
||||
+ LDAPMod *mods[2];
|
||||
+ char *replace_val[2];
|
||||
+ char *passwd = NULL;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ /* decode the DES password */
|
||||
+ if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL ,"convert_pbe_des_to_aes",
|
||||
+ "Failed to decode existing DES password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ rc = -1;
|
||||
+ }
|
||||
+
|
||||
+ /* encode the password */
|
||||
+ if (rc == 0){
|
||||
sval = slapi_value_new_string(passwd);
|
||||
if(pw_rever_encode(&sval, attrs[i]) == -1){
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes",
|
||||
"failed to encode AES password for (%s)\n",
|
||||
- slapi_entry_get_dn(entries[ii]), 0, 0);
|
||||
- slapi_ch_free_string(&passwd);
|
||||
- slapi_value_free(&sval);
|
||||
- disable_des = 0;
|
||||
- goto done;
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ rc = -1;
|
||||
}
|
||||
+ }
|
||||
|
||||
+ if (rc == 0){
|
||||
/* replace the attribute in the entry */
|
||||
replace_val[0] = (char *)slapi_value_get_string(sval);
|
||||
replace_val[1] = NULL;
|
||||
@@ -837,83 +797,34 @@ convert_pbe_des_to_aes()
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
||||
if (LDAP_SUCCESS != result) {
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes"
|
||||
"Failed to convert password for (%s) error (%d)\n",
|
||||
- slapi_entry_get_dn(entries[ii]), result, 0);
|
||||
- disable_des = 0;
|
||||
+ slapi_entry_get_dn(entries[ii]), result);
|
||||
} else {
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
+ slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes",
|
||||
"Successfully converted password for (%s)\n",
|
||||
- slapi_entry_get_dn(entries[ii]), result, 0);
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
converted_des_passwd = 1;
|
||||
}
|
||||
- slapi_ch_free_string(&passwd);
|
||||
- slapi_value_free(&sval);
|
||||
- slapi_pblock_destroy(mod_pb);
|
||||
}
|
||||
- slapi_ch_free_string(&val);
|
||||
+ slapi_ch_free_string(&passwd);
|
||||
+ slapi_value_free(&sval);
|
||||
+ slapi_pblock_destroy(mod_pb);
|
||||
}
|
||||
+ slapi_ch_free_string(&val);
|
||||
}
|
||||
- slapi_free_search_results_internal(pb);
|
||||
- slapi_pblock_destroy(pb);
|
||||
- pb = NULL;
|
||||
}
|
||||
+ slapi_free_search_results_internal(pb);
|
||||
+ slapi_pblock_destroy(pb);
|
||||
+ pb = NULL;
|
||||
slapi_ch_free_string(&filter);
|
||||
}
|
||||
if (!converted_des_passwd){
|
||||
- slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes",
|
||||
+ slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes",
|
||||
"No DES passwords found to convert.\n");
|
||||
}
|
||||
}
|
||||
-
|
||||
-done:
|
||||
charray_free(attrs);
|
||||
- charray_free(backends);
|
||||
- slapi_free_search_results_internal(pb);
|
||||
- slapi_pblock_destroy(pb);
|
||||
-
|
||||
- if (have_aes && have_des){
|
||||
- /*
|
||||
- * If a conversion attempt did not fail then we can disable the DES plugin
|
||||
- */
|
||||
- if(converted_des_passwd && disable_des){
|
||||
- /*
|
||||
- * Disable the DES plugin - this also prevents potentially expensive
|
||||
- * searches at every server startup.
|
||||
- */
|
||||
- LDAPMod mod_replace;
|
||||
- LDAPMod *mods[2];
|
||||
- char *replace_val[2];
|
||||
- char *des_dn = "cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config";
|
||||
-
|
||||
- replace_val[0] = "off";
|
||||
- replace_val[1] = NULL;
|
||||
- mod_replace.mod_op = LDAP_MOD_REPLACE;
|
||||
- mod_replace.mod_type = "nsslapd-pluginEnabled";
|
||||
- mod_replace.mod_values = replace_val;
|
||||
- mods[0] = &mod_replace;
|
||||
- mods[1] = 0;
|
||||
-
|
||||
- pb = slapi_pblock_new();
|
||||
- slapi_modify_internal_set_pb(pb, des_dn, mods, 0, 0,
|
||||
- (void *)plugin_get_default_component_id(), 0);
|
||||
- slapi_modify_internal_pb(pb);
|
||||
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
||||
- if (LDAP_SUCCESS != result) {
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
- "Failed to disable DES plugin (%s), error (%d)\n",
|
||||
- des_dn, result, 0);
|
||||
- } else {
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
- "Successfully disabled DES plugin (%s)\n",
|
||||
- des_dn, 0, 0);
|
||||
- }
|
||||
- slapi_pblock_destroy(pb);
|
||||
- LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
|
||||
- "All DES passwords have been converted to AES.\n",
|
||||
- 0, 0, 0);
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NUNC_STANS
|
||||
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
|
||||
index 4e222d7..883ef80 100644
|
||||
--- a/ldap/servers/slapd/pw.c
|
||||
+++ b/ldap/servers/slapd/pw.c
|
||||
@@ -516,10 +516,10 @@ pw_rever_encode(Slapi_Value **vals, char * attr_name)
|
||||
for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
|
||||
{
|
||||
char *L_attr = NULL;
|
||||
- int i = 0;
|
||||
+ int i = 0, ii = 0;
|
||||
|
||||
/* Get the appropriate encoding function */
|
||||
- for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
|
||||
+ for ( L_attr = p->plg_argv[ii]; ii<p->plg_argc; L_attr = p->plg_argv[++ii] )
|
||||
{
|
||||
if (slapi_attr_types_equivalent(L_attr, attr_name))
|
||||
{
|
||||
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
|
||||
index db3c222..405f0bf 100644
|
||||
--- a/ldap/servers/slapd/task.c
|
||||
+++ b/ldap/servers/slapd/task.c
|
||||
@@ -53,6 +53,8 @@ static int shutting_down = 0;
|
||||
#define TASK_TOMBSTONE_FIXUP_BACKEND "backend"
|
||||
#define TASK_TOMBSTONE_FIXUP_SUFFIX "suffix"
|
||||
#define TASK_TOMBSTONE_FIXUP_STRIPCSN "stripcsn"
|
||||
+#define TASK_DES2AES "des2aes task"
|
||||
+
|
||||
|
||||
#define LOG_BUFFER 256
|
||||
/* if the cumul. log gets larger than this, it's truncated: */
|
||||
@@ -83,8 +85,10 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
|
||||
const char *default_val);
|
||||
static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn);
|
||||
static void modify_internal_entry(char *dn, LDAPMod **mods);
|
||||
-
|
||||
static void fixup_tombstone_task_destructor(Slapi_Task *task);
|
||||
+static void task_des2aes_thread(void *arg);
|
||||
+static void des2aes_task_destructor(Slapi_Task *task);
|
||||
+
|
||||
|
||||
/***********************************
|
||||
* Public Functions
|
||||
@@ -2425,6 +2429,345 @@ fixup_tombstone_task_destructor(Slapi_Task *task)
|
||||
"fixup_tombstone_task_destructor <--\n" );
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * des2aes Task
|
||||
+ *
|
||||
+ * Convert any DES passwords to AES
|
||||
+ *
|
||||
+ * dn: cn=convertPasswords, cn=des2aes,cn=tasks,cn=config
|
||||
+ * objectclass: top
|
||||
+ * objectclass: extensibleObject
|
||||
+ * suffix: dc=example,dc=com (If empty all backends are checked)
|
||||
+ * suffix: dc=other,dc=suffix
|
||||
+ */
|
||||
+struct task_des2aes_data
|
||||
+{
|
||||
+ char **suffixes;
|
||||
+ Slapi_Task *task;
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+task_des2aes(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
|
||||
+ int *returncode, char *returntext, void *arg)
|
||||
+{
|
||||
+ struct task_des2aes_data *task_data = NULL;
|
||||
+ PRThread *thread = NULL;
|
||||
+ Slapi_Task *task = NULL;
|
||||
+ char **suffix = NULL;
|
||||
+ char **bases = NULL;
|
||||
+ int rc = SLAPI_DSE_CALLBACK_OK;
|
||||
+
|
||||
+ /* Get the suffixes */
|
||||
+ if((suffix = slapi_entry_attr_get_charray(e, "suffix"))){
|
||||
+ int i;
|
||||
+ for (i = 0; suffix && suffix[i]; i++){
|
||||
+ /* Make sure "suffix" is NUL terminated string */
|
||||
+ char *dn = slapi_create_dn_string("%s", suffix[i]);
|
||||
+
|
||||
+ if(dn){
|
||||
+ if(slapi_dn_syntax_check(pb, dn, 1)){
|
||||
+ /* invalid suffix name */
|
||||
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
|
||||
+ "Invalid DN syntax (%s) specified for \"suffix\"\n",
|
||||
+ suffix[i]);
|
||||
+ *returncode = LDAP_INVALID_DN_SYNTAX;
|
||||
+ slapi_ch_free_string(&dn);
|
||||
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
||||
+ goto error;
|
||||
+ } else {
|
||||
+ slapi_ch_array_add(&bases, dn);
|
||||
+ }
|
||||
+ } else{
|
||||
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
|
||||
+ "Invalid DN (%s) specified for \"suffix\"\n", suffix[i]);
|
||||
+ *returncode = LDAP_INVALID_DN_SYNTAX;
|
||||
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
||||
+ goto error;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Build the task data and fire off a thread to perform the conversion */
|
||||
+ task = slapi_new_task(slapi_entry_get_ndn(e));
|
||||
+
|
||||
+ /* register our destructor for cleaning up our private data */
|
||||
+ slapi_task_set_destructor_fn(task, des2aes_task_destructor);
|
||||
+ task_data = (struct task_des2aes_data *)slapi_ch_calloc(1, sizeof(struct task_des2aes_data));
|
||||
+ task_data->suffixes = bases;
|
||||
+ task_data->task = task;
|
||||
+
|
||||
+ /* Start the conversion thread */
|
||||
+ thread = PR_CreateThread(PR_USER_THREAD, task_des2aes_thread,
|
||||
+ (void *)task_data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
||||
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
|
||||
+ if (thread == NULL) {
|
||||
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
|
||||
+ "unable to create des2aes thread!\n");
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "unable to create des2aes thread!\n");
|
||||
+ *returncode = LDAP_OPERATIONS_ERROR;
|
||||
+ slapi_task_finish(task, *returncode);
|
||||
+ rc = SLAPI_DSE_CALLBACK_ERROR;
|
||||
+ }
|
||||
+
|
||||
+error:
|
||||
+ if (rc == SLAPI_DSE_CALLBACK_ERROR){
|
||||
+ slapi_ch_array_free(bases);
|
||||
+ slapi_ch_array_free(suffix);
|
||||
+ slapi_ch_free((void **)&task_data);
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+task_des2aes_thread(void *arg)
|
||||
+{
|
||||
+ struct task_des2aes_data *task_data = arg;
|
||||
+ Slapi_PBlock *pb = NULL;
|
||||
+ Slapi_Entry **entries = NULL;
|
||||
+ Slapi_Task *task = task_data->task;
|
||||
+ struct slapdplugin *plugin = NULL;
|
||||
+ char **attrs = NULL;
|
||||
+ char **backends = NULL;
|
||||
+ char *val = NULL;
|
||||
+ int converted_des_passwd = 0;
|
||||
+ int result = -1;
|
||||
+ int have_aes = 0;
|
||||
+ int have_des = 0;
|
||||
+ int i = 0, ii = 0, be_idx = 0;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Check that AES plugin is enabled, and grab all the unique
|
||||
+ * password attributes.
|
||||
+ */
|
||||
+ for ( plugin = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME);
|
||||
+ plugin != NULL;
|
||||
+ plugin = plugin->plg_next )
|
||||
+ {
|
||||
+ char *plugin_arg = NULL;
|
||||
+
|
||||
+ if(plugin->plg_started && strcasecmp(plugin->plg_name, "AES") == 0){
|
||||
+ /* We have the AES plugin, and its enabled */
|
||||
+ have_aes = 1;
|
||||
+ }
|
||||
+ if(plugin->plg_started && strcasecmp(plugin->plg_name, "DES") == 0){
|
||||
+ /* We have the DES plugin, and its enabled */
|
||||
+ have_des = 1;
|
||||
+ }
|
||||
+ /* Gather all the unique password attributes from all the PBE plugins */
|
||||
+ for ( i = 0, plugin_arg = plugin->plg_argv[i];
|
||||
+ i < plugin->plg_argc;
|
||||
+ plugin_arg = plugin->plg_argv[++i] )
|
||||
+ {
|
||||
+ if(charray_inlist(attrs, plugin_arg)){
|
||||
+ continue;
|
||||
+ }
|
||||
+ charray_add(&attrs, slapi_ch_strdup(plugin_arg));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(have_aes && have_des){
|
||||
+ if(task_data->suffixes == NULL){
|
||||
+ /*
|
||||
+ * Build a list of all the backend dn's
|
||||
+ */
|
||||
+ Slapi_Backend *be = NULL;
|
||||
+ struct suffixlist *list;
|
||||
+ char *cookie = NULL;
|
||||
+
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "Checking for DES passwords to convert to AES...\n");
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "Checking for DES passwords to convert to AES...\n");
|
||||
+
|
||||
+ be = slapi_get_first_backend(&cookie);
|
||||
+ while (be){
|
||||
+ int suffix_idx = 0;
|
||||
+ int count = slapi_counter_get_value(be->be_suffixcounter);
|
||||
+
|
||||
+ list = be->be_suffixlist;
|
||||
+ for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) {
|
||||
+ char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix);
|
||||
+ if(charray_inlist(backends, suffix) || strlen(suffix) == 0){
|
||||
+ list = list->next;
|
||||
+ continue;
|
||||
+ }
|
||||
+ charray_add(&backends, slapi_ch_strdup(suffix));
|
||||
+ list = list->next;
|
||||
+ }
|
||||
+ be = slapi_get_next_backend (cookie);
|
||||
+ }
|
||||
+ slapi_ch_free ((void **)&cookie);
|
||||
+ } else {
|
||||
+ backends = task_data->suffixes;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Search for the password attributes
|
||||
+ */
|
||||
+ for (i = 0; attrs && attrs[i]; i++){
|
||||
+ char *filter = PR_smprintf("%s=*", attrs[i]);
|
||||
+ /*
|
||||
+ * Loop over all the backends looking for the password attribute
|
||||
+ */
|
||||
+ for(be_idx = 0; backends && backends[be_idx]; be_idx++){
|
||||
+ pb = slapi_pblock_new();
|
||||
+ slapi_search_internal_set_pb(pb, backends[be_idx],
|
||||
+ LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
|
||||
+ (void *)plugin_get_default_component_id(),
|
||||
+ SLAPI_OP_FLAG_IGNORE_UNINDEXED);
|
||||
+ slapi_search_internal_pb(pb);
|
||||
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
||||
+ if (LDAP_SUCCESS != result) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes: ",
|
||||
+ "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
|
||||
+ attrs[i], result, backends[be_idx]);
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
|
||||
+ attrs[i], result, backends[be_idx]);
|
||||
+ slapi_free_search_results_internal(pb);
|
||||
+ slapi_pblock_destroy(pb);
|
||||
+ pb = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
+ for (ii = 0; entries && entries[ii]; ii++){
|
||||
+ if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
|
||||
+ if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
|
||||
+ /*
|
||||
+ * We have a DES encoded password, convert it AES
|
||||
+ */
|
||||
+ Slapi_PBlock *mod_pb = NULL;
|
||||
+ Slapi_Value *sval = NULL;
|
||||
+ LDAPMod mod_replace;
|
||||
+ LDAPMod *mods[2];
|
||||
+ char *replace_val[2];
|
||||
+ char *passwd = NULL;
|
||||
+
|
||||
+ /* Decode the DES password */
|
||||
+ if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "Failed to decode existing DES password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "Failed to decode existing DES password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ rc = 1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Encode the password */
|
||||
+ sval = slapi_value_new_string(passwd);
|
||||
+ if(pw_rever_encode(&sval, attrs[i]) == -1){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "failed to encode AES password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "failed to encode AES password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ slapi_ch_free_string(&passwd);
|
||||
+ slapi_value_free(&sval);
|
||||
+ rc = 1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Replace the attribute in the entry */
|
||||
+ replace_val[0] = (char *)slapi_value_get_string(sval);
|
||||
+ replace_val[1] = NULL;
|
||||
+ mod_replace.mod_op = LDAP_MOD_REPLACE;
|
||||
+ mod_replace.mod_type = attrs[i];
|
||||
+ mod_replace.mod_values = replace_val;
|
||||
+ mods[0] = &mod_replace;
|
||||
+ mods[1] = 0;
|
||||
+
|
||||
+ mod_pb = slapi_pblock_new();
|
||||
+ slapi_modify_internal_set_pb(mod_pb, slapi_entry_get_dn(entries[ii]),
|
||||
+ mods, 0, 0, (void *)plugin_get_default_component_id(), 0);
|
||||
+ slapi_modify_internal_pb(mod_pb);
|
||||
+
|
||||
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
||||
+ if (LDAP_SUCCESS != result) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "Failed to convert password for (%s) error (%d)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]), result);
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "Failed to convert password for (%s) error (%d)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]), result);
|
||||
+ rc = 1;
|
||||
+ } else {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "Successfully converted password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ slapi_task_log_notice(task,
|
||||
+ "Successfully converted password for (%s)\n",
|
||||
+ slapi_entry_get_dn(entries[ii]));
|
||||
+ converted_des_passwd = 1;
|
||||
+ }
|
||||
+ slapi_ch_free_string(&passwd);
|
||||
+ slapi_value_free(&sval);
|
||||
+ slapi_pblock_destroy(mod_pb);
|
||||
+ }
|
||||
+ slapi_ch_free_string(&val);
|
||||
+ }
|
||||
+ }
|
||||
+ slapi_free_search_results_internal(pb);
|
||||
+ slapi_pblock_destroy(pb);
|
||||
+ pb = NULL;
|
||||
+ }
|
||||
+ slapi_ch_free_string(&filter);
|
||||
+ }
|
||||
+ if (!converted_des_passwd){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "No DES passwords found to convert.\n");
|
||||
+ slapi_task_log_notice(task, "No DES passwords found to convert.\n");
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* No AES/DES */
|
||||
+ if (!have_des){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "DES plugin not enabled\n");
|
||||
+ slapi_task_log_notice(task, "DES plugin not enabled\n");
|
||||
+ }
|
||||
+ if (!have_aes){
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "AES plugin not enabled\n");
|
||||
+ slapi_task_log_notice(task, "AES plugin not enabled\n");
|
||||
+ }
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
|
||||
+ "Unable to convert passwords\n");
|
||||
+ slapi_task_log_notice(task, "Unable to convert passwords\n");
|
||||
+ rc = 1;
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ charray_free(attrs);
|
||||
+ charray_free(backends);
|
||||
+ slapi_free_search_results_internal(pb);
|
||||
+ slapi_pblock_destroy(pb);
|
||||
+ slapi_task_finish(task, rc);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+des2aes_task_destructor(Slapi_Task *task)
|
||||
+{
|
||||
+ slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES,
|
||||
+ "des2aes_task_destructor -->\n" );
|
||||
+ if (task) {
|
||||
+ struct task_des2aes_data *task_data = (struct task_des2aes_data *)slapi_task_get_data(task);
|
||||
+ while (slapi_task_get_refcount(task) > 0) {
|
||||
+ /* Yield to wait for the task to finish. */
|
||||
+ DS_Sleep (PR_MillisecondsToInterval(100));
|
||||
+ }
|
||||
+ if (task_data) {
|
||||
+ slapi_ch_array_free(task_data->suffixes);
|
||||
+ slapi_ch_free((void **)&task_data);
|
||||
+ }
|
||||
+ }
|
||||
+ slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES,
|
||||
+ "des2aes_task_destructor <--\n" );
|
||||
+}
|
||||
+
|
||||
/* cleanup old tasks that may still be in the DSE from a previous session
|
||||
* (this can happen if the server crashes [no matter how unlikely we like
|
||||
* to think that is].)
|
||||
@@ -2506,6 +2849,7 @@ void task_init(void)
|
||||
slapi_task_register_handler("upgradedb", task_upgradedb_add);
|
||||
slapi_task_register_handler("sysconfig reload", task_sysconfig_reload_add);
|
||||
slapi_task_register_handler("fixup tombstones", task_fixup_tombstones_add);
|
||||
+ slapi_task_register_handler("des2aes", task_des2aes);
|
||||
}
|
||||
|
||||
/* called when the server is shutting down -- abort all existing tasks */
|
||||
--
|
||||
2.4.11
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
Summary: 389 Directory Server (base)
|
||||
Name: 389-ds-base
|
||||
Version: 1.3.4.0
|
||||
Release: %{?relprefix}30%{?prerel}%{?dist}
|
||||
Release: %{?relprefix}32%{?prerel}%{?dist}
|
||||
License: GPLv3+
|
||||
URL: http://port389.org/
|
||||
Group: System Environment/Daemons
|
||||
|
@ -212,6 +212,11 @@ Patch85: 0086-Ticket-48445-keep-alive-entries-can-break-replicatio.patc
|
|||
Patch86: 0087-Ticket-48420-change-severity-of-some-messages-relate.patch
|
||||
Patch87: 0088-Ticket-48757-License-tag-does-not-match-actual-licen.patch
|
||||
Patch88: 0089-Ticket-47888-DES-to-AES-password-conversion-fails-if.patch
|
||||
Patch89: 0090-Ticket-48492-heap-corruption-at-schema-replication.patch
|
||||
Patch90: 0091-Ticket-48492-heap-corruption-at-schema-replication.patch
|
||||
Patch91: 0092-Ticket-48808-Paged-results-search-returns-the-blank-.patch
|
||||
Patch92: 0093-Ticket-48808-Add-test-case.patch
|
||||
Patch93: 0094-Ticket-48862-At-startup-DES-to-AES-password-conversi.patch
|
||||
|
||||
%description
|
||||
389 Directory Server is an LDAPv3 compliant server. The base package includes
|
||||
|
@ -364,6 +369,11 @@ cp %{SOURCE2} README.devel
|
|||
%patch86 -p1
|
||||
%patch87 -p1
|
||||
%patch88 -p1
|
||||
%patch89 -p1
|
||||
%patch90 -p1
|
||||
%patch91 -p1
|
||||
%patch92 -p1
|
||||
%patch93 -p1
|
||||
|
||||
%build
|
||||
%if %{use_nunc_stans}
|
||||
|
@ -554,10 +564,19 @@ fi
|
|||
%{_libdir}/%{pkgname}/libslapd.so.*
|
||||
%{_libdir}/%{pkgname}/libns-dshttpd.so*
|
||||
%if %{use_nunc_stans}
|
||||
%{_libdir}/%{pkgname}/libnunc-stans.so*
|
||||
%{_libdir}/%{pkgname}/libnunc-stans.so.*
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Jun 9 2016 Noriko Hosoi <nhosoi@redhat.com> - 1.3.4.0-32
|
||||
- release 1.3.4.0-32
|
||||
- Resolves: bug 1344293 - At startup DES to AES password conversion causes timeout in start script (DS 48862)
|
||||
|
||||
* Thu May 12 2016 Noriko Hosoi <nhosoi@redhat.com> - 1.3.4.0-31
|
||||
- release 1.3.4.0-31
|
||||
- Resolves: bug 1335423 - heap corruption at schema replication. (DS 48492)
|
||||
- Resolves: bug 1335107 - Paged results search returns the blank list of entries (DS 48808)
|
||||
|
||||
* Wed Mar 30 2016 Noriko Hosoi <nhosoi@redhat.com> - 1.3.4.0-30
|
||||
- release 1.3.4.0-30
|
||||
- Resolves: bug 1321891 - DES to AES password conversion fails if a backend is empty (DS 48777)
|
||||
|
|
Loading…
Add table
Reference in a new issue