|
|
dc8c34 |
From fa6fba4d7716cb2ce4cd5446e0af790d765d71e2 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
dc8c34 |
Date: Wed, 5 Mar 2014 15:55:31 -0500
|
|
|
dc8c34 |
Subject: [PATCH] Ticket 417, 458, 47522 - Password Administrator Backport
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Description: Backported all the fixes needed to implement the feature.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/417
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/458
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47522
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug 985270 - [RFE] Add Password adminstrators to RHDS 9 as in
|
|
|
dc8c34 |
http://directory.fedoraproject.org/wiki/Password_Administrator (edit)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by: nhosoi(Thanks!)
|
|
|
dc8c34 |
(cherry picked from commit 096d8958a81ee57d3486d8260430cbfab81a0bbc)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/schema/02common.ldif | 3 +-
|
|
|
dc8c34 |
ldap/servers/slapd/entry.c | 45 ++++++++++----
|
|
|
dc8c34 |
ldap/servers/slapd/libglobs.c | 24 +++++++-
|
|
|
dc8c34 |
ldap/servers/slapd/modify.c | 25 ++++----
|
|
|
dc8c34 |
ldap/servers/slapd/pblock.c | 6 ++
|
|
|
dc8c34 |
ldap/servers/slapd/proto-slap.h | 1 +
|
|
|
dc8c34 |
ldap/servers/slapd/pw.c | 123 ++++++++++++++++++++++++++++++++++++--
|
|
|
dc8c34 |
ldap/servers/slapd/pw.h | 1 +
|
|
|
dc8c34 |
ldap/servers/slapd/slap.h | 3 +
|
|
|
dc8c34 |
ldap/servers/slapd/slapi-plugin.h | 32 ++++++++++
|
|
|
dc8c34 |
10 files changed, 233 insertions(+), 30 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
|
|
|
dc8c34 |
index ffec7ce..92feb49 100644
|
|
|
dc8c34 |
--- a/ldap/schema/02common.ldif
|
|
|
dc8c34 |
+++ b/ldap/schema/02common.ldif
|
|
|
dc8c34 |
@@ -95,6 +95,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2081 NAME ( 'passwordMaxRepeats' 'pwdMax
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.2082 NAME ( 'passwordMinCategories' 'pwdMinCategories' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.2083 NAME ( 'passwordMinTokenLength' 'pwdMinTokenLength' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.2140 NAME ( 'passwordTrackUpdateTime' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
+attributeTypes: ( 2.16.840.1.113730.3.1.2153 NAME ( 'passwordAdminDN' 'pwdAdminDN' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.198 NAME 'memberURL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
@@ -164,7 +165,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' )
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' )
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
-objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
+objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordAdminDN $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
index 785256f..8b7766e 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
@@ -2630,25 +2630,46 @@ slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
|
|
|
dc8c34 |
char **
|
|
|
dc8c34 |
slapi_entry_attr_get_charray( const Slapi_Entry* e, const char *type)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- char **parray = NULL;
|
|
|
dc8c34 |
- Slapi_Attr* attr = NULL;
|
|
|
dc8c34 |
+ int ignore;
|
|
|
dc8c34 |
+ return slapi_entry_attr_get_charray_ext(e, type, &ignore);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * The extension also gathers the number of values.
|
|
|
dc8c34 |
+ * The caller must free with slapi_ch_array_free
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+char **
|
|
|
dc8c34 |
+slapi_entry_attr_get_charray_ext( const Slapi_Entry* e, const char *type, int *numVals)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ char **parray = NULL;
|
|
|
dc8c34 |
+ Slapi_Attr* attr = NULL;
|
|
|
dc8c34 |
+ int count = 0;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if(numVals == NULL){
|
|
|
dc8c34 |
+ return NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
slapi_entry_attr_find(e, type, &attr);
|
|
|
dc8c34 |
- if(attr!=NULL)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if(attr!=NULL){
|
|
|
dc8c34 |
int hint;
|
|
|
dc8c34 |
Slapi_Value *v = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
for (hint = slapi_attr_first_value(attr, &v);
|
|
|
dc8c34 |
hint != -1;
|
|
|
dc8c34 |
hint = slapi_attr_next_value(attr, hint, &v))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
const struct berval *bvp = slapi_value_get_berval(v);
|
|
|
dc8c34 |
char *p = slapi_ch_malloc(bvp->bv_len + 1);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
memcpy(p, bvp->bv_val, bvp->bv_len);
|
|
|
dc8c34 |
p[bvp->bv_len]= '\0';
|
|
|
dc8c34 |
charray_add(&parray, p);
|
|
|
dc8c34 |
+ count++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- return parray;
|
|
|
dc8c34 |
+ *numVals = count;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return parray;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
char *
|
|
|
dc8c34 |
@@ -2660,16 +2681,18 @@ slapi_entry_attr_get_charptr( const Slapi_Entry* e, const char *type)
|
|
|
dc8c34 |
if(attr!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_Value *v;
|
|
|
dc8c34 |
- const struct berval *bvp;
|
|
|
dc8c34 |
+ const struct berval *bvp;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
slapi_valueset_first_value( &attr->a_present_values, &v);
|
|
|
dc8c34 |
- bvp = slapi_value_get_berval(v);
|
|
|
dc8c34 |
- p= slapi_ch_malloc(bvp->bv_len + 1);
|
|
|
dc8c34 |
- memcpy(p, bvp->bv_val, bvp->bv_len);
|
|
|
dc8c34 |
- p[bvp->bv_len]= '\0';
|
|
|
dc8c34 |
+ bvp = slapi_value_get_berval(v);
|
|
|
dc8c34 |
+ p= slapi_ch_malloc(bvp->bv_len + 1);
|
|
|
dc8c34 |
+ memcpy(p, bvp->bv_val, bvp->bv_len);
|
|
|
dc8c34 |
+ p[bvp->bv_len]= '\0';
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- return p;
|
|
|
dc8c34 |
+ return p;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
slapi_entry_attr_get_int( const Slapi_Entry* e, const char *type)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
|
|
|
dc8c34 |
index 8103133..b7dadcd 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/libglobs.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/libglobs.c
|
|
|
dc8c34 |
@@ -248,6 +248,9 @@ static struct config_get_and_set {
|
|
|
dc8c34 |
{CONFIG_PWPOLICY_LOCAL_ATTRIBUTE, config_set_pwpolicy_local,
|
|
|
dc8c34 |
NULL, 0,
|
|
|
dc8c34 |
(void**)&global_slapdFrontendConfig.pwpolicy_local, CONFIG_ON_OFF, NULL},
|
|
|
dc8c34 |
+ {CONFIG_PW_ADMIN_DN_ATTRIBUTE, config_set_pw_admin_dn,
|
|
|
dc8c34 |
+ NULL, 0,
|
|
|
dc8c34 |
+ (void**)&global_slapdFrontendConfig.pw_policy.pw_admin, CONFIG_STRING, NULL},
|
|
|
dc8c34 |
{CONFIG_AUDITLOG_MAXLOGDISKSPACE_ATTRIBUTE, NULL,
|
|
|
dc8c34 |
log_set_maxdiskspace, SLAPD_AUDIT_LOG,
|
|
|
dc8c34 |
(void**)&global_slapdFrontendConfig.auditlog_maxdiskspace, CONFIG_INT, NULL},
|
|
|
dc8c34 |
@@ -685,8 +688,7 @@ static struct config_get_and_set {
|
|
|
dc8c34 |
{CONFIG_DISK_THRESHOLD, config_set_disk_threshold,
|
|
|
dc8c34 |
NULL, 0,
|
|
|
dc8c34 |
(void**)&global_slapdFrontendConfig.disk_threshold,
|
|
|
dc8c34 |
- CONFIG_LONG_LONG, (ConfigGetFunc)config_get_disk_threshold,
|
|
|
dc8c34 |
- DEFAULT_DISK_THRESHOLD},
|
|
|
dc8c34 |
+ CONFIG_LONG_LONG, (ConfigGetFunc)config_get_disk_threshold},
|
|
|
dc8c34 |
{CONFIG_DISK_GRACE_PERIOD, config_set_disk_grace_period,
|
|
|
dc8c34 |
NULL, 0,
|
|
|
dc8c34 |
(void**)&global_slapdFrontendConfig.disk_grace_period,
|
|
|
dc8c34 |
@@ -1122,9 +1124,11 @@ FrontendConfig_init () {
|
|
|
dc8c34 |
cfg->disk_grace_period = 60; /* 1 hour */
|
|
|
dc8c34 |
cfg->disk_logging_critical = LDAP_OFF;
|
|
|
dc8c34 |
cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ cfg->pw_policy.pw_admin = NULL;
|
|
|
dc8c34 |
+ cfg->pw_policy.pw_admin_user = NULL;
|
|
|
dc8c34 |
cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
|
|
|
dc8c34 |
cfg->ignore_time_skew = LDAP_OFF;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
#if defined(LINUX)
|
|
|
dc8c34 |
cfg->malloc_mxfast = DEFAULT_MALLOC_UNSET;
|
|
|
dc8c34 |
cfg->malloc_trim_threshold = DEFAULT_MALLOC_UNSET;
|
|
|
dc8c34 |
@@ -2837,6 +2841,20 @@ config_set_dn_validate_strict( const char *attrname, char *value, char *errorbuf
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
+config_set_pw_admin_dn( const char *attrname, char *value, char *errorbuf, int apply ) {
|
|
|
dc8c34 |
+ int retVal = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if ( apply ) {
|
|
|
dc8c34 |
+ CFG_LOCK_WRITE(slapdFrontendConfig);
|
|
|
dc8c34 |
+ slapi_sdn_free(&slapdFrontendConfig->pw_policy.pw_admin);
|
|
|
dc8c34 |
+ slapdFrontendConfig->pw_policy.pw_admin = slapi_sdn_new_dn_byval(value);
|
|
|
dc8c34 |
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ return retVal;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
config_set_ds4_compatible_schema( const char *attrname, char *value, char *errorbuf, int apply ) {
|
|
|
dc8c34 |
int retVal = LDAP_SUCCESS;
|
|
|
dc8c34 |
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
|
|
|
dc8c34 |
index 817f17c..90c9f8c 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/modify.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/modify.c
|
|
|
dc8c34 |
@@ -1227,11 +1227,9 @@ static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old
|
|
|
dc8c34 |
slapi_pblock_set( pb, SLAPI_BACKEND, slapi_be_select( &sdn ) );
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Check if ACIs allow password to be changed */
|
|
|
dc8c34 |
- if ( (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS) {
|
|
|
dc8c34 |
- if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- if (proxydn)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if ( !pw_is_pwp_admin(pb, pwpolicy) && (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS){
|
|
|
dc8c34 |
+ if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS)){
|
|
|
dc8c34 |
+ if (proxydn){
|
|
|
dc8c34 |
proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1243,16 +1241,23 @@ static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Write access is denied to userPassword by ACIs */
|
|
|
dc8c34 |
if ( pwresponse_req == 1 ) {
|
|
|
dc8c34 |
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
|
|
|
dc8c34 |
- LDAP_PWPOLICY_PWDMODNOTALLOWED );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- send_ldap_result(pb, res, NULL, errtxt, 0, NULL);
|
|
|
dc8c34 |
+ slapi_pwpolicy_make_response_control ( pb, -1, -1, LDAP_PWPOLICY_PWDMODNOTALLOWED );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ send_ldap_result(pb, res, NULL, errtxt, 0, NULL);
|
|
|
dc8c34 |
slapi_ch_free_string(&errtxt);
|
|
|
dc8c34 |
rc = -1;
|
|
|
dc8c34 |
goto done;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * If this mod is being performed by a password administrator/rootDN,
|
|
|
dc8c34 |
+ * just return success.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if(pw_is_pwp_admin(pb, pwpolicy)){
|
|
|
dc8c34 |
+ rc = 1;
|
|
|
dc8c34 |
+ goto done;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* Check if password policy allows users to change their passwords.*/
|
|
|
dc8c34 |
if (!pb->pb_op->o_isroot && slapi_sdn_compare(&sdn, &pb->pb_op->o_sdn)==0 &&
|
|
|
dc8c34 |
!pb->pb_conn->c_needpw && !pwpolicy->pw_change)
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
|
|
|
dc8c34 |
index 9b59e7b..849c20e 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/pblock.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/pblock.c
|
|
|
dc8c34 |
@@ -1803,6 +1803,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ case SLAPI_REQUESTOR_SDN:
|
|
|
dc8c34 |
+ if(pblock->pb_op != NULL){
|
|
|
dc8c34 |
+ (*(Slapi_DN **)value) = &pblock->pb_op->o_sdn;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
case SLAPI_OPERATION_AUTHTYPE:
|
|
|
dc8c34 |
if (pblock->pb_op != NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
|
|
|
dc8c34 |
index 954cfd2..8c9f0fb 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/proto-slap.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/proto-slap.h
|
|
|
dc8c34 |
@@ -347,6 +347,7 @@ int config_set_return_exact_case(const char *attrname, char *value, char *error
|
|
|
dc8c34 |
int config_set_result_tweak(const char *attrname, char *value, char *errorbuf, int apply );
|
|
|
dc8c34 |
int config_set_referral_mode(const char *attrname, char *url, char *errorbuf, int apply);
|
|
|
dc8c34 |
int config_set_conntablesize(const char *attrname, char *url, char *errorbuf, int apply);
|
|
|
dc8c34 |
+int config_set_pw_admin_dn( const char *attrname, char *value, char *errorbuf, int apply );
|
|
|
dc8c34 |
int config_set_maxbersize(const char *attrname, char *value, char *errorbuf, int apply );
|
|
|
dc8c34 |
int config_set_maxsasliosize(const char *attrname, char *value, char *errorbuf, int apply );
|
|
|
dc8c34 |
int config_set_versionstring(const char *attrname, char *versionstring, char *errorbuf, int apply );
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
|
|
|
dc8c34 |
index 6f3d436..cf400a1 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/pw.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/pw.c
|
|
|
dc8c34 |
@@ -73,6 +73,8 @@ static int update_pw_history( Slapi_PBlock *pb, const Slapi_DN *sdn, char *old_p
|
|
|
dc8c34 |
static int check_trivial_words (Slapi_PBlock *, Slapi_Entry *, Slapi_Value **,
|
|
|
dc8c34 |
char *attrtype, int toklen, Slapi_Mods *smods );
|
|
|
dc8c34 |
static int pw_boolean_str2value (const char *str);
|
|
|
dc8c34 |
+static void pw_get_admin_users(passwdPolicy *pwp);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* static LDAPMod* pw_malloc_mod (char* name, char* value, int mod_op); */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -588,7 +590,7 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
|
|
|
dc8c34 |
char *timestr;
|
|
|
dc8c34 |
time_t pw_exp_date;
|
|
|
dc8c34 |
time_t cur_time;
|
|
|
dc8c34 |
- const char *dn;
|
|
|
dc8c34 |
+ const char *target_dn, *bind_dn;
|
|
|
dc8c34 |
Slapi_DN *sdn = NULL;
|
|
|
dc8c34 |
passwdPolicy *pwpolicy = NULL;
|
|
|
dc8c34 |
int internal_op = 0;
|
|
|
dc8c34 |
@@ -598,10 +600,11 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
|
|
|
dc8c34 |
internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
cur_time = current_time();
|
|
|
dc8c34 |
+ slapi_pblock_get( pb, SLAPI_REQUESTOR_NDN, &bind_dn);
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
|
|
|
dc8c34 |
- dn = slapi_sdn_get_dn(sdn);
|
|
|
dc8c34 |
+ target_dn = slapi_sdn_get_dn(sdn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- pwpolicy = new_passwdPolicy(pb, dn);
|
|
|
dc8c34 |
+ pwpolicy = new_passwdPolicy(pb, target_dn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* update passwordHistory */
|
|
|
dc8c34 |
if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
|
|
|
dc8c34 |
@@ -643,7 +646,8 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
|
|
|
dc8c34 |
* we stuff the actual user who initiated the password change in pb_conn. We check
|
|
|
dc8c34 |
* for this special case to ensure we reset the expiration date properly. */
|
|
|
dc8c34 |
if ((internal_op && pwpolicy->pw_must_change && (!pb->pb_conn || slapi_dn_isroot(pb->pb_conn->c_dn))) ||
|
|
|
dc8c34 |
- (!internal_op && pwpolicy->pw_must_change && (pb->pb_requestor_isroot == 1))) {
|
|
|
dc8c34 |
+ (!internal_op && pwpolicy->pw_must_change &&
|
|
|
dc8c34 |
+ ((target_dn && bind_dn && strcasecmp(target_dn, bind_dn)) && pw_is_pwp_admin(pb, pwpolicy)))){
|
|
|
dc8c34 |
pw_exp_date = NO_TIME;
|
|
|
dc8c34 |
} else if ( pwpolicy->pw_exp == 1 ) {
|
|
|
dc8c34 |
Slapi_Entry *pse = NULL;
|
|
|
dc8c34 |
@@ -836,7 +840,7 @@ check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
|
|
|
dc8c34 |
* case for the password modify extended operation. */
|
|
|
dc8c34 |
if (slapi_is_encoded((char *)slapi_value_get_string(vals[i]))) {
|
|
|
dc8c34 |
if ((!is_replication && ((internal_op && pb->pb_conn && !slapi_dn_isroot(pb->pb_conn->c_dn)) ||
|
|
|
dc8c34 |
- (!internal_op && !pb->pb_requestor_isroot)))) {
|
|
|
dc8c34 |
+ (!internal_op && !pw_is_pwp_admin(pb, pwpolicy))))) {
|
|
|
dc8c34 |
PR_snprintf( errormsg, BUFSIZ,
|
|
|
dc8c34 |
"invalid password syntax - passwords with storage scheme are not allowed");
|
|
|
dc8c34 |
if ( pwresponse_req == 1 ) {
|
|
|
dc8c34 |
@@ -1527,6 +1531,97 @@ pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change) {
|
|
|
dc8c34 |
slapi_ch_free((void **) &aci_pw);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Slapi_DN *bind_sdn = NULL;
|
|
|
dc8c34 |
+ int i;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* first check if it's root */
|
|
|
dc8c34 |
+ if(pb->pb_requestor_isroot){
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /* now check if it's a Password Policy Administrator */
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_SDN, &bind_sdn);
|
|
|
dc8c34 |
+ if(bind_sdn == NULL){
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ for(i = 0; pwp->pw_admin_user && pwp->pw_admin_user[i]; i++){
|
|
|
dc8c34 |
+ if(slapi_sdn_compare(bind_sdn, pwp->pw_admin_user[i]) == 0){
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+static void
|
|
|
dc8c34 |
+pw_get_admin_users(passwdPolicy *pwp)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ Slapi_PBlock *pb = NULL;
|
|
|
dc8c34 |
+ const Slapi_DN *sdn = pwp->pw_admin;
|
|
|
dc8c34 |
+ char **uniquemember_vals = NULL;
|
|
|
dc8c34 |
+ char **member_vals = NULL;
|
|
|
dc8c34 |
+ const char *binddn = slapi_sdn_get_dn(sdn);
|
|
|
dc8c34 |
+ int uniquemember_count = 0;
|
|
|
dc8c34 |
+ int member_count = 0;
|
|
|
dc8c34 |
+ int nentries = 0;
|
|
|
dc8c34 |
+ int count = 0;
|
|
|
dc8c34 |
+ int res;
|
|
|
dc8c34 |
+ int i;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if(binddn == NULL){
|
|
|
dc8c34 |
+ return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ pb = slapi_pblock_new();
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Check if the DN exists and has "group" objectclasses
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,"(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
|
|
|
dc8c34 |
+ NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
|
|
|
dc8c34 |
+ slapi_search_internal_pb(pb);
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res;;
|
|
|
dc8c34 |
+ if (res != LDAP_SUCCESS) {
|
|
|
dc8c34 |
+ slapi_pblock_destroy(pb);
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - Password Policy Administrators can not be set\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(sdn), res, 0);
|
|
|
dc8c34 |
+ return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Ok, we know we have a valid DN, and nentries will tell us if its a group or a user
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_NENTRIES, &nentries);
|
|
|
dc8c34 |
+ if ( nentries > 0 ){
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * It's a group DN, gather all the members
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ Slapi_Entry **entries = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
|
dc8c34 |
+ uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
|
|
|
dc8c34 |
+ member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
|
|
|
dc8c34 |
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1), sizeof(Slapi_DN *));
|
|
|
dc8c34 |
+ if(uniquemember_count > 0){
|
|
|
dc8c34 |
+ for(i = 0; i < uniquemember_count; i++){
|
|
|
dc8c34 |
+ pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if(member_count > 0){
|
|
|
dc8c34 |
+ for(i = 0; i < member_count; i++){
|
|
|
dc8c34 |
+ pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(member_vals[i]);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free((void**)&uniquemember_vals);
|
|
|
dc8c34 |
+ slapi_ch_free((void**)&member_vals);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* It's a single user */
|
|
|
dc8c34 |
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc(2, sizeof(Slapi_DN *));
|
|
|
dc8c34 |
+ pwp->pw_admin_user[0] = slapi_sdn_dup(sdn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_free_search_results_internal(pb);
|
|
|
dc8c34 |
+ slapi_pblock_destroy(pb);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* This function creates a passwdPolicy structure, loads it from either
|
|
|
dc8c34 |
* slapdFrontendconfig or the entry pointed by pwdpolicysubentry and
|
|
|
dc8c34 |
* returns the structure.
|
|
|
dc8c34 |
@@ -1831,6 +1926,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
|
|
|
dc8c34 |
pw_boolean_str2value(slapi_value_get_string(*sval));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ else
|
|
|
dc8c34 |
+ if (!strcasecmp(attr_name, "passwordAdminDN")) {
|
|
|
dc8c34 |
+ if ((sval = attr_get_present_values(attr))) {
|
|
|
dc8c34 |
+ pwdpolicy->pw_admin = slapi_sdn_new_dn_byval(slapi_value_get_string(*sval));
|
|
|
dc8c34 |
+ pw_get_admin_users(pwdpolicy);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
} /* end of for() loop */
|
|
|
dc8c34 |
if (pw_entry) {
|
|
|
dc8c34 |
slapi_entry_free(pw_entry);
|
|
|
dc8c34 |
@@ -1851,6 +1953,8 @@ done:
|
|
|
dc8c34 |
*pwdscheme = *slapdFrontendConfig->pw_storagescheme;
|
|
|
dc8c34 |
pwdscheme->pws_name = strdup( slapdFrontendConfig->pw_storagescheme->pws_name );
|
|
|
dc8c34 |
pwdpolicy->pw_storagescheme = pwdscheme;
|
|
|
dc8c34 |
+ pwdpolicy->pw_admin = slapi_sdn_dup(slapdFrontendConfig->pw_policy.pw_admin);
|
|
|
dc8c34 |
+ pw_get_admin_users(pwdpolicy);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
return pwdpolicy;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1861,6 +1965,15 @@ delete_passwdPolicy( passwdPolicy **pwpolicy)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if (pwpolicy && *pwpolicy) {
|
|
|
dc8c34 |
free_pw_scheme( (*(*pwpolicy)).pw_storagescheme );
|
|
|
dc8c34 |
+ slapi_sdn_free(&(*(*pwpolicy)).pw_admin);
|
|
|
dc8c34 |
+ if((*(*pwpolicy)).pw_admin_user){
|
|
|
dc8c34 |
+ int i = 0;
|
|
|
dc8c34 |
+ while((*(*pwpolicy)).pw_admin_user[i]){
|
|
|
dc8c34 |
+ slapi_sdn_free(&(*(*pwpolicy)).pw_admin_user[i]);
|
|
|
dc8c34 |
+ i++;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free((void **)&(*(*pwpolicy)).pw_admin_user);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
slapi_ch_free((void **)pwpolicy);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h
|
|
|
dc8c34 |
index a470fdd..9bb5cc7 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/pw.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/pw.h
|
|
|
dc8c34 |
@@ -86,6 +86,7 @@ int pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals
|
|
|
dc8c34 |
int checkPrefix(char *cipher, char *schemaName, char **encrypt);
|
|
|
dc8c34 |
struct passwordpolicyarray *new_passwdPolicy ( Slapi_PBlock *pb, const char *dn );
|
|
|
dc8c34 |
void delete_passwdPolicy( struct passwordpolicyarray **pwpolicy);
|
|
|
dc8c34 |
+int pw_is_pwp_admin(Slapi_PBlock *pb, struct passwordpolicyarray *pwp);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* function for checking the values of fine grained password policy attributes */
|
|
|
dc8c34 |
int check_pw_duration_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf );
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
|
|
|
dc8c34 |
index ca30d2a..33cfeb4 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slap.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slap.h
|
|
|
dc8c34 |
@@ -2018,6 +2018,7 @@ typedef struct _slapdEntryPoints {
|
|
|
dc8c34 |
#define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size"
|
|
|
dc8c34 |
#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size"
|
|
|
dc8c34 |
#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
|
|
|
dc8c34 |
+#define CONFIG_PW_ADMIN_DN_ATTRIBUTE "passwordAdminDN"
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* getenv alternative */
|
|
|
dc8c34 |
#define CONFIG_MALLOC_MXFAST "nsslapd-malloc-mxfast"
|
|
|
dc8c34 |
@@ -2081,6 +2082,8 @@ typedef struct passwordpolicyarray {
|
|
|
dc8c34 |
int pw_is_legacy;
|
|
|
dc8c34 |
int pw_track_update_time;
|
|
|
dc8c34 |
struct pw_scheme *pw_storagescheme;
|
|
|
dc8c34 |
+ Slapi_DN *pw_admin;
|
|
|
dc8c34 |
+ Slapi_DN **pw_admin_user;
|
|
|
dc8c34 |
} passwdPolicy;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
typedef struct _slapdFrontendConfig {
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
index 9e85dc0..c13a1a8 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
@@ -1618,6 +1618,38 @@ int slapi_entry_attr_delete( Slapi_Entry *e, const char *type );
|
|
|
dc8c34 |
* be \c NULL terminated so that they can be used safely in a string context. If there
|
|
|
dc8c34 |
* are no values, \c NULL will be returned. Because the array is \c NULL terminated,
|
|
|
dc8c34 |
* the usage should be similar to the sample shown below:
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \code
|
|
|
dc8c34 |
+ * char **ary = slapi_entry_attr_get_charray(e, someattr);
|
|
|
dc8c34 |
+ * int ii;
|
|
|
dc8c34 |
+ * for (ii = 0; ary && ary[ii]; ++ii) {
|
|
|
dc8c34 |
+ * char *strval = ary[ii];
|
|
|
dc8c34 |
+ * ...
|
|
|
dc8c34 |
+ * }
|
|
|
dc8c34 |
+ * slapi_ch_array_free(ary);
|
|
|
dc8c34 |
+ * \endcode
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \param e Entry from which you want to get the values.
|
|
|
dc8c34 |
+ * \param type Attribute type from which you want to get the values.
|
|
|
dc8c34 |
+ * \param numVals The number of attribute values will be stored in this variable.
|
|
|
dc8c34 |
+ * \return A copy of all the values of the attribute.
|
|
|
dc8c34 |
+ * \return \c NULL if the entry does not contain the attribute or if the attribute
|
|
|
dc8c34 |
+ * has no values.
|
|
|
dc8c34 |
+ * \warning When you are done working with the values, free them from memory by calling
|
|
|
dc8c34 |
+ * the slapi_ch_array_free() function.
|
|
|
dc8c34 |
+ * \see slapi_entry_attr_get_charptr()
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+char **slapi_entry_attr_get_charray_ext( const Slapi_Entry* e, const char *type, int *numVals);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/**
|
|
|
dc8c34 |
+ * Gets the values of a multi-valued attribute of an entry.
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * This function is very similar to slapi_entry_attr_get_charptr(), except that it
|
|
|
dc8c34 |
+ * returns a <tt>char **</tt> array for multi-valued attributes. The array and all
|
|
|
dc8c34 |
+ * values are copies. Even if the attribute values are not strings, they will still
|
|
|
dc8c34 |
+ * be \c NULL terminated so that they can be used safely in a string context. If there
|
|
|
dc8c34 |
+ * are no values, \c NULL will be returned. Because the array is \c NULL terminated,
|
|
|
dc8c34 |
+ * the usage should be similar to the sample shown below:
|
|
|
dc8c34 |
*
|
|
|
dc8c34 |
* \code
|
|
|
dc8c34 |
* char **ary = slapi_entry_attr_get_charray(e, someattr);
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|