Makefile.am | 13
Makefile.in | 50 +
ldap/ldif/template-dse.ldif.in | 11
ldap/servers/plugins/replication/repl5.h | 10
ldap/servers/plugins/replication/repl5_connection.c | 26
ldap/servers/plugins/replication/repl5_replica_config.c | 257 +++++-
ldap/servers/plugins/replication/repl_extop.c | 91 +-
ldap/servers/plugins/rootdn_access/rootdn_access.c | 663 ++++++++++++++++
ldap/servers/plugins/rootdn_access/rootdn_access.h | 57 +
ldap/servers/slapd/auditlog.c | 6
ldap/servers/slapd/back-ldbm/cache.c | 8
ldap/servers/slapd/back-ldbm/dblayer.c | 9
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 1
ldap/servers/slapd/bind.c | 34
ldap/servers/slapd/pblock.c | 14
ldap/servers/slapd/plugin.c | 11
ldap/servers/slapd/slap.h | 2
ldap/servers/slapd/slapi-plugin.h | 3
18 files changed, 1178 insertions(+), 88 deletions(-)
New commits:
commit ff11cccbba3f60761ca949a2feacc9d0b35451e7
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Jun 1 17:26:34 2012 -0600
Ticket #389 - ADD operations not in audit log
https://fedorahosted.org/389/ticket/389
Resolves: Ticket #389
Bug Description: ADD operations not in audit log
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Re-add code that was previously deleted. Also, log the
unnormalized, raw DN for operations.
Platforms tested: RHEL6 x86_64, Fedora 17
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c
index 79cd407..9c5ffad 100644
--- a/ldap/servers/slapd/auditlog.c
+++ b/ldap/servers/slapd/auditlog.c
@@ -82,6 +82,9 @@ write_audit_log_entry( Slapi_PBlock *pb )
case SLAPI_OPERATION_MODIFY:
slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &change );
break;
+ case SLAPI_OPERATION_ADD:
+ slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &change );
+ break;
case SLAPI_OPERATION_DELETE:
{
char * deleterDN = NULL;
@@ -99,7 +102,8 @@ write_audit_log_entry( Slapi_PBlock *pb )
return; /* Unsupported operation type. */
}
curtime = current_time();
- dn = slapi_sdn_get_dn(sdn);
+ /* log the raw, unnormalized DN */
+ dn = slapi_sdn_get_udn(sdn);
write_audit_file( operation_get_type(op), dn, change, flag, curtime );
}
commit 44cdc84ddc75b40a2e9b9578468db903b28dfb6b
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri May 25 12:39:09 2012 -0600
fix coverity issues with uninit vals, no return checking
12766 Uninitialized pointer read
In _entryrdn_replace_suffix_id(): Reads an uninitialized pointer or its target
12765 Uninitialized pointer read
In txn_test_threadmain(): Reads an uninitialized pointer or its target
12764 Unchecked return value
In txn_test_threadmain(): Value returned from a function is not checked for errors
before being used
12763 Unchecked return value
In entrycache_replace(): Value returned from a function is not checked for errors
before being used
12762 Unchecked return value
In entrycache_add_int(): Value returned from a function is not checked for errors
before being used
Reviewed by: mreynolds (Thanks!)
(cherry picked from commit 98784ec829061e969c84b3cd5882326a0376ebd6)
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 045b1eb..de84700 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1058,7 +1058,9 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
}
if (!add_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID), newe, NULL)) {
LOG("entry cache replace: can't add id\n", 0, 0, 0);
- remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn));
+ if (remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn))) {
+ LOG("entry cache replace: can't remove dn after add id
failed\n", 0, 0, 0);
+ }
PR_Unlock(cache->c_mutex);
return 1;
}
@@ -1357,7 +1359,9 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
PR_Unlock(cache->c_mutex);
return 0;
}
- remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn));
+ if (remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn))) {
+ LOG("=>= entrycache_add_int could not remove existing id from dn
cache\n", 0, 0, 0);
+ }
e->ep_state |= ENTRY_STATE_NOTINCACHE;
PR_Unlock(cache->c_mutex);
return -1;
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c
b/ldap/servers/slapd/back-ldbm/dblayer.c
index 09d10a0..90e48af 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -3897,12 +3897,12 @@ static int txn_test_threadmain(void *param)
INCR_THREAD_COUNT(priv);
+ txn_test_init_cfg(&cfg);
+
if (!priv->dblayer_enable_transactions) {
goto end;
}
- txn_test_init_cfg(&cfg);
-
wait_for_init:
free_ttilist(&ttilist, &tticnt);
DS_Sleep(PR_MillisecondsToInterval(1000));
@@ -3941,9 +3941,8 @@ wait_for_init:
object_release(inst_obj);
goto wait_for_init;
}
- dblayer_get_index_file(be, ai, &db, 0);
- if (NULL == db) {
- if (strcasecmp(*idx, TXN_TEST_IDX_OK_IF_NULL)) {
+ if (dblayer_get_index_file(be, ai, &db, 0) || (NULL == db)) {
+ if ((NULL == db) && strcasecmp(*idx,
TXN_TEST_IDX_OK_IF_NULL)) {
object_release(inst_obj);
goto wait_for_init;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 449e02a..0541543 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -2179,6 +2179,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata,
size_t curr_childnum = 0;
int db_retry = 0;
+ memset(&moddata, 0, sizeof(moddata));
/* temporary id added for the non exisiting suffix */
/* Let's replace it with the real entry ID */
/* SELF */
commit 1b4b9d53d2cfec92802f6fd4fdbc0101e987c6ee
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Wed May 16 11:28:01 2012 -0400
Ticket 368 - Make the cleanAllRUV task one step
Bug Description: The first version of this fix required a second releaseRUV step.
Fix Description: Created a new "monitoring" thread that checks all the
replicas RUV's
to see if the rid was cleaned. Once they are cleaned, we
automatically
release the RID for reuse.
I also refined the logging so it easy to track the status of the
task.
https://fedorahosted.org/389/ticket/368
reviewed by: richm (Thanks Rich!)
(cherry picked from commit 507b593fa47efeb8a4fc3c2d6b75428e7a69a480)
diff --git a/ldap/servers/plugins/replication/repl5.h
b/ldap/servers/plugins/replication/repl5.h
index d3feeb0..b04d9c4 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -439,6 +439,9 @@ long conn_get_timeout(Repl_Connection *conn);
void conn_set_agmt_changed(Repl_Connection *conn);
ConnResult conn_read_result(Repl_Connection *conn, int *message_id);
ConnResult conn_read_result_ex(Repl_Connection *conn, char **retoidp, struct berval
**retdatap, LDAPControl ***returned_controls, int send_msgid, int *resp_msgid, int
noblock);
+LDAP * conn_get_ldap(Repl_Connection *conn);
+void conn_lock(Repl_Connection *conn);
+void conn_unlock(Repl_Connection *conn);
/* In repl5_protocol.c */
typedef struct repl_protocol Repl_Protocol;
@@ -598,9 +601,16 @@ void set_released_rid(int rid);
int is_released_rid(int rid);
int is_already_released_rid();
void delete_released_rid();
+void replica_cleanallruv_monitor_thread(void *arg);
#define ALREADY_RELEASED -1
+typedef struct _cleanruv_data
+{
+ Object *repl_obj;
+ ReplicaId rid;
+} cleanruv_data;
+
/* replutil.c */
LDAPControl* create_managedsait_control ();
LDAPControl* create_backend_control(Slapi_DN *sdn);
diff --git a/ldap/servers/plugins/replication/repl5_connection.c
b/ldap/servers/plugins/replication/repl5_connection.c
index a074a9f..5fdc601 100644
--- a/ldap/servers/plugins/replication/repl5_connection.c
+++ b/ldap/servers/plugins/replication/repl5_connection.c
@@ -1710,6 +1710,16 @@ conn_get_timeout(Repl_Connection *conn)
return retval;
}
+LDAP *
+conn_get_ldap(Repl_Connection *conn)
+{
+ if(conn){
+ return conn->ld;
+ } else {
+ return NULL;
+ }
+}
+
void conn_set_agmt_changed(Repl_Connection *conn)
{
PR_ASSERT(NULL != conn);
@@ -1908,3 +1918,19 @@ repl5_debug_timeout_callback(time_t when, void *arg)
"repl5_debug_timeout_callback: set debug level to %d at %ld\n",
s_debug_level, when);
}
+
+void
+conn_lock(Repl_Connection *conn)
+{
+ if(conn){
+ PR_Lock(conn->lock);
+ }
+}
+
+void
+conn_unlock(Repl_Connection *conn)
+{
+ if(conn){
+ PR_Unlock(conn->lock);
+ }
+}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c
b/ldap/servers/plugins/replication/repl5_replica_config.c
index 5a3ed07..ca646e9 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -81,12 +81,12 @@ static int replica_execute_cl2ldif_task (Object *r, char
*returntext);
static int replica_execute_ldif2cl_task (Object *r, char *returntext);
static int replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext);
static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char
*returntext);
-static int replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext);
+static int replica_execute_release_ruv_task(Object *r, ReplicaId rid);
static struct berval *create_ruv_payload(char *value);
static int replica_cleanup_task (Object *r, const char *task_name, char *returntext, int
apply_mods);
static int replica_task_done(Replica *replica);
-
static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry
*e);
+int g_get_shutdown();
/*
* Note: internal add/modify/delete operations should not be run while
@@ -860,21 +860,6 @@ static int replica_execute_task (Object *r, const char *task_name,
char *returnt
else
return LDAP_SUCCESS;
}
- else if (strncasecmp (task_name, RELEASERUV, RELEASERUVLEN) == 0)
- {
- int temprid = atoi(&(task_name[RELEASERUVLEN]));
- if (temprid <= 0 || temprid >= READ_ONLY_REPLICA_ID){
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid replica id for task -
%s", task_name);
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,"replica_execute_task:
%s\n", returntext);
- return LDAP_OPERATIONS_ERROR;
- }
- if (apply_mods)
- {
- return replica_execute_release_ruv_task(r, (ReplicaId)temprid, returntext);
- }
- else
- return LDAP_SUCCESS;
- }
else
{
PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "unsupported replica task
- %s", task_name);
@@ -1177,7 +1162,6 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char
*returntext /* not
* Clean the changelog RUV's, and set the rids
*/
cl5CleanRUV(rid);
- set_cleaned_rid(rid);
delete_released_rid();
if (rc != RUV_SUCCESS){
@@ -1191,19 +1175,22 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char
*returntext /* not
static int
replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char *returntext)
{
+ PRThread *thread = NULL;
Repl_Connection *conn;
Replica *replica = (Replica*)object_get_data (r);
Object *agmt_obj;
Repl_Agmt *agmt;
ConnResult crc;
+ cleanruv_data *data = NULL;
const Slapi_DN *dn = NULL;
struct berval *payload = NULL;
char *ridstr = NULL;
int send_msgid = 0;
+ int agmt_count = 0;
int rc = 0;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: cleaning rid
(%d)...\n",(int)rid);
-
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: cleaning rid
(%d)...\n",(int)rid);
+ set_cleaned_rid(rid);
/*
* Create payload
*/
@@ -1245,8 +1232,9 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, char
*returntext)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to
send "
"cleanruv extended op to repl agmt (%s), error %d\n",
slapi_sdn_get_dn(dn), crc);
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task:
successfully sent "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task:
successfully sent "
"cleanruv extended op to (%s)\n",slapi_sdn_get_dn(dn));
+ agmt_count++;
}
conn_start_linger(conn);
}
@@ -1270,17 +1258,218 @@ done:
*/
replica_execute_cleanruv_task (r, rid, returntext);
- if(rc == 0){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: operation
successful\n");
+ if(rc == 0 && agmt_count > 0){ /* success, but we need to check our replicas
*/
+ /*
+ * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will
release the rid
+ */
+ data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
+ if (data == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to
allocate "
+ "cleanruv_data. Aborting task.\n");
+ return -1;
+ }
+ data->repl_obj = r;
+ data->rid = rid;
+
+ thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_monitor_thread,
+ (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: unable to
create cleanAllRUV "
+ "monitoring thread. Aborting task.\n");
+ }
+
+ } else if(r == 0){ /* success */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully
Finished.\n");
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: operation
failed (%d)\n",rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Task failed
(%d)\n",rc);
}
return rc;
}
+/*
+ * After all the cleanAllRUV extended ops have been sent, we need to monitoring those
replicas'
+ * RUVs. Once the rid is cleaned, then we need to release it, and push this
"release"
+ * to the other replicas
+ */
+void
+replica_cleanallruv_monitor_thread(void *arg)
+{
+ Object *agmt_obj;
+ LDAP *ld;
+ Repl_Connection *conn;
+ Repl_Agmt *agmt;
+ Replica *replica;;
+ cleanruv_data *data = arg;
+ LDAPMessage *result, *entry;
+ BerElement *ber;
+ time_t start_time;
+ struct berval **vals;
+ char *rid_text;
+ char *attrs[2];
+ char *attr;
+ int replicas_cleaned = 0;
+ int found = 0;
+ int crc;
+ int rc = 0;
+ int i;
+
+ /*
+ * Initialize our settings
+ */
+ attrs[0] = "nsds50ruv";
+ attrs[1] = NULL;
+ rid_text = slapi_ch_smprintf("{replica %d ldap", data->rid);
+ replica = (Replica*)object_get_data (data->repl_obj);
+ start_time = current_time();
+
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Waiting for
all the replicas to get cleaned...\n");
+
+ while(!g_get_shutdown())
+ {
+ DS_Sleep(PR_SecondsToInterval(10));
+ found = 0;
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ while (agmt_obj){
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt)){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ continue;
+ }
+ /*
+ * Get the replication connection
+ */
+ conn = (Repl_Connection *)agmt_get_connection(agmt);
+ crc = conn_connect(conn);
+ if (CONN_OPERATION_FAILED == crc ){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor
thread failed to connect "
+ "to repl agreement connection (%s), error %d\n","",
ACQUIRE_TRANSIENT_ERROR);
+ continue;
+ } else if (CONN_SSL_NOT_ENABLED == crc){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor
thread failed to acquire "
+ "repl agmt connection (%s), error %d\n","",
ACQUIRE_FATAL_ERROR);
+ continue;
+ }
+ /*
+ * Get the LDAP connection handle from the conn
+ */
+ ld = conn_get_ldap(conn);
+ if(ld == NULL){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor
thread failed to get LDAP "
+ "handle from the replication agmt (%s). Moving on to the next
agmt.\n",agmt_get_long_name(agmt));
+ continue;
+ }
+ /*
+ * Search this replica for its tombstone/ruv entry
+ */
+ conn_cancel_linger(conn);
+ conn_lock(conn);
+ rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(agmt_get_replarea(agmt)),
LDAP_SCOPE_SUBTREE,
+ "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))",
+ attrs, 0, NULL, NULL, NULL, 0, &result);
+ if(rc != LDAP_SUCCESS){
+ /*
+ * Couldn't contact ldap server, what should we do?
+ *
+ * Skip it and move on! It's the admin's job to make sure all the replicas
are up and running
+ */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: monitor
thread failed to contact "
+ "agmt (%s), moving on to the next agmt.\n", agmt_get_long_name(agmt));
+ conn_unlock(conn);
+ conn_start_linger(conn);
+ continue;
+ }
+ /*
+ * There is only one entry. Check its "nsds50ruv" for our cleaned rid
+ */
+ entry = ldap_first_entry( ld, result );
+ if ( entry != NULL ) {
+ for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr =
ldap_next_attribute( ld, entry, ber ) ){
+ /* make sure the attribute is nsds50ruv */
+ if(strcasecmp(attr,"nsds50ruv") != 0){
+ continue;
+ }
+ if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) {
+ for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) {
+ /* look for this replica */
+ if(strstr(rid_text, vals[i]->bv_val)){
+ /* rid has not been cleaned yet, start over */
+ found = 1;
+ break;
+ }
+ }
+ ldap_value_free_len(vals);
+ }
+ ldap_memfree( attr );
+ }
+ if ( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ }
+ ldap_msgfree( result );
+ /*
+ * Unlock the connection, and start the linger timer
+ */
+ conn_unlock(conn);
+ conn_start_linger(conn);
+
+ if(found){
+ /*
+ * If we've been trying to clean these replicas for over an hour, just quit
+ */
+ if( (current_time() - start_time) > 3600){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: timed out
checking if replicas have "
+ "been cleaned. The rid has not been released, you need to rerun the
task.\n");
+ goto done;
+ }
+ /*
+ * a rid has not been cleaned yet, go back to sleep and check them again
+ */
+ break;
+ }
+
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ }
+ if(!found){
+ /*
+ * The replicas have been cleaned! Next, release the rid
+ */
+ replicas_cleaned = 1;
+ break;
+ }
+ } /* while */
+
+ /*
+ * If the replicas are cleaned, release the rid
+ */
+ if(replicas_cleaned){
+ rc = replica_execute_release_ruv_task(data->repl_obj, data->rid);
+ if(rc == 0){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task:
Successfully Finished. All active "
+ "replicas have been cleaned.\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed:
Replica ID was not released (%d) "
+ "You will need to rerun the task.\n", rc);
+ }
+ } else {
+ /*
+ * Shutdown
+ */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: slapd
shutting down, you will need to rerun the task.\n");
+ }
+
+done:
+ slapi_ch_free((void **)&rid_text);
+ slapi_ch_free((void **)&data);
+}
+
+/*
+ * This function releases the cleaned rid so that it can be reused.
+ * We send this operation to all the known active replicas.
+ */
static int
-replica_execute_release_ruv_task(Object *r, ReplicaId rid, char *returntext)
+replica_execute_release_ruv_task(Object *r, ReplicaId rid)
{
Repl_Connection *conn;
Replica *replica = (Replica*)object_get_data (r);
@@ -1293,7 +1482,7 @@ replica_execute_release_ruv_task(Object *r, ReplicaId rid, char
*returntext)
int send_msgid = 0;
int rc = 0;
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: releasing rid
(%d)...\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: releasing rid
(%d)...\n", rid);
/*
* Set the released rid, and trigger cl trimmming
@@ -1339,18 +1528,18 @@ replica_execute_release_ruv_task(Object *r, ReplicaId rid, char
*returntext)
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_RELEASERUV_OID, payload, NULL,
&send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: failed to
send "
- "releaseruv extended op to repl agmt (%s), error %d\n",
slapi_sdn_get_dn(dn), crc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to
send "
+ "releaseRUV extended op to repl agmt (%s), error %d\n",
slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: successfully
sent "
- "extended op to (%s)\n",slapi_sdn_get_dn(dn));
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task:
successfully sent "
+ "releaseRUV extended op to (%s)\n",slapi_sdn_get_dn(dn));
}
conn_start_linger(conn);
}
if(crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: replica (%s)
has not "
- "been cleaned. You will need to rerun the RELEASERUV task on this
replica\n",
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica
(%s) has not "
+ "been released. You will need to rerun the task\n",
slapi_sdn_get_dn(dn));
rc = crc;
}
@@ -1364,9 +1553,9 @@ done:
if(rc == 0){
set_released_rid(ALREADY_RELEASED);
delete_cleaned_rid();
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseRUV_task: Successfully
released rid (%d)\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully
released rid (%d)\n", rid);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_task: Failed to
release rid (%d), error (%d)\n", rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed to
release rid (%d), error (%d)\n", rid, rc);
}
if(payload)
diff --git a/ldap/servers/plugins/replication/repl_extop.c
b/ldap/servers/plugins/replication/repl_extop.c
index e4abde0..f6378d2 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1388,18 +1388,21 @@ free_and_return:
int
multimaster_extop_cleanruv(Slapi_PBlock *pb){
multimaster_mtnode_extension *mtnode_ext;
+ PRThread *thread = NULL;
Repl_Connection *conn;
const Slapi_DN *dn;
Replica *r = NULL;
Object *agmt_obj;
Repl_Agmt *agmt;
ConnResult crc;
+ cleanruv_data *data = NULL;
struct berval *extop_value;
char *extop_oid;
char *repl_root;
char *payload = NULL;
char *iter;
int send_msgid = 0;
+ int agmt_count = 0;
int rid = 0;
int rc = 0;
@@ -1411,41 +1414,39 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
/* something is wrong, error out */
return -1;
}
-
/*
* Extract the rid and repl_root from the payload
*/
if(decode_cleanruv_payload(extop_value, &payload)){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to
decode payload. Aborting ext op\n");
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
decode payload. Aborting ext op\n");
return -1;
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaning rid
(%d)...\n",rid);
-
/*
* If we already cleaned this server, just return success
*/
if(is_cleaned_rid(rid)){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: rid (%d) has
already been cleaned, skipping\n",rid);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_extop: rid (%d) has
already been cleaned, skipping\n",rid);
return rc;
} else {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaning rid
(%d)...\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: cleaning
rid (%d)...\n", rid);
+ set_cleaned_rid(rid);
}
/*
* Get the node, so we can get the replica and its agreements
*/
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to get
replication node "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
get replication node "
"from (%s), aborting operation\n", repl_root);
return -1;
}
if (mtnode_ext->replica)
object_acquire (mtnode_ext->replica);
if (mtnode_ext->replica == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: replica is
missing from (%s), "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica is
missing from (%s), "
"aborting operation\n",repl_root);
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
@@ -1466,36 +1467,37 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
/* no connection for this agreement, move on to the next agmt */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: the replica
(%s), is "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: the
replica (%s), is "
"missing the connection. This replica will not be cleaned.\n",
slapi_sdn_get_dn(dn));
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
continue;
}
crc = conn_connect(conn);
if (CONN_OPERATION_FAILED == crc ){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to
connect "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
connect "
"to repl agreement connection (%s), error %d\n",slapi_sdn_get_dn(dn),
ACQUIRE_TRANSIENT_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else if (CONN_SSL_NOT_ENABLED == crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to
acquire "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
acquire "
"repl agmt connection (%s), error %d\n",slapi_sdn_get_dn(dn),
ACQUIRE_FATAL_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else {
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, extop_value, NULL,
&send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to
send "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
send "
"clean_ruv extended op to repl agmt (%s), error %d\n",
slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
/* success */
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: successfully
sent "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop:
successfully sent "
"extended op to (%s)\n",slapi_sdn_get_dn(dn) );
+ agmt_count++;
}
conn_start_linger(conn);
}
if(crc != CONN_OPERATION_SUCCESS){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: replica (%s)
has not "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica
(%s) has not "
"been cleaned. You will need to rerun the CLEANALLRUV task on this
replica\n",
slapi_sdn_get_dn(dn) );
rc = LDAP_OPERATIONS_ERROR;
@@ -1508,10 +1510,30 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb){
free_and_return:
- if(rc == 0){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_extop: cleaned rid
(%d)\n", rid);
+ if(rc == 0 && agmt_count > 0){
+ /*
+ * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will
release the rid
+ */
+ data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data));
+ if (data == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
allocate "
+ "cleanruv_Data\n");
+ return -1;
+ }
+ data->repl_obj = mtnode_ext->replica;
+ data->rid = rid;
+
+ thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_monitor_thread,
+ (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: unable to
create cleanAllRUV "
+ "monitoring thread. Aborting task.\n");
+ }
+ } else if (rc == 0){
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop:
Successfully Finished.\n");
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanruv_extop: failed to
clean rid (%d), error (%d)\n",rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanALLRUV_extop: failed to
clean rid (%d), error (%d)\n",rid, rc);
}
if (mtnode_ext->replica)
@@ -1558,34 +1580,34 @@ multimaster_extop_releaseruv(Slapi_PBlock *pb){
}
if(decode_cleanruv_payload(extop_value, &payload)){
- slapi_log_error(SLAPI_LOG_FATAL,repl_plugin_name, "releaseruv_extop: failed to
decode payload, aborting ext op\n");
+ slapi_log_error(SLAPI_LOG_FATAL,repl_plugin_name, "releaseRUV_extop: failed to
decode payload, aborting ext op.\n");
return -1;
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
repl_root = ldap_utf8strtok_r(iter, ":", &iter);
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: releasing rid
(%d)...\n",rid);
/*
* If we already released this ruv, just return.
*/
if(is_released_rid(rid) || is_already_released_rid()){
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: rid (%d) has
already been released, skipping\n",rid);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_extop: rid (%d) has
already been released, skipping.\n",rid);
return 0;
} else {
/* set the released rid, and trigger trimming */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: releasing
rid (%d)...\n", rid);
set_released_rid((int)rid);
trigger_cl_trimming();
}
if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to
get node "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to
get node "
"from replication root dn(%s), aborting operation.\n", repl_root);
return -1;
}
if (mtnode_ext->replica)
object_acquire (mtnode_ext->replica);
if (mtnode_ext->replica == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: replica is
missing from (%s), "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: replica is
missing from (%s), "
"aborting operation.\n", repl_root);
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
@@ -1606,38 +1628,38 @@ multimaster_extop_releaseruv(Slapi_PBlock *pb){
conn = (Repl_Connection *)agmt_get_connection(agmt);
if(conn == NULL){
/* no connection for this agreement, log error, and move on */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: the replica
(%s), is "
- "missing the connection. This replica will not be cleaned.\n",
slapi_sdn_get_dn(dn));
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: the
replica (%s), is "
+ "missing the connection. This replica will not be released.\n",
slapi_sdn_get_dn(dn));
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
continue;
}
crc = conn_connect(conn);
if (CONN_OPERATION_FAILED == crc ){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to
connect "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to
connect "
"to repl agreement connection (%s), error %d\n",slapi_sdn_get_dn(dn),
ACQUIRE_TRANSIENT_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else if (CONN_SSL_NOT_ENABLED == crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to
acquire "
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseRUV_extop: failed to
acquire "
"repl agmt connection (%s), error %d\n",slapi_sdn_get_dn(dn),
ACQUIRE_FATAL_ERROR);
rc = LDAP_OPERATIONS_ERROR;
} else {
conn_cancel_linger(conn);
crc = conn_send_extended_operation(conn, REPL_RELEASERUV_OID, extop_value, NULL,
&send_msgid);
if (CONN_OPERATION_SUCCESS != crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to
send "
- "releaseruv extended op to repl agmt (%s), error
%d\n", slapi_sdn_get_dn(dn), crc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: failed to
send "
+ "releaseRUV extended op to repl agmt (%s), error
%d\n", slapi_sdn_get_dn(dn), crc);
rc = LDAP_OPERATIONS_ERROR;
} else {
/* success */
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop:
successfully sent "
- "extended op to (%s)\n",slapi_sdn_get_dn(dn) );
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop:
successfully sent "
+ "releaseRUV extended op to (%s)\n",slapi_sdn_get_dn(dn) );
rc = 0;
}
conn_start_linger(conn);
}
if(crc){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: replica
(%s) has not "
- "been cleaned. You will need to rerun the RELEASERUV task on this
replica\n",
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: replica
(%s) has not "
+ "been released. You will need to rerun the task.\n",
slapi_sdn_get_dn(dn) );
}
agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj);
@@ -1650,9 +1672,10 @@ free_and_return:
if(rc == 0){
set_released_rid(ALREADY_RELEASED);
delete_cleaned_rid();
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "releaseruv_extop: released rid
(%d) successfully\n", rid);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop:
Successfully released rid (%d)\n", rid);
} else {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "releaseruv_extop: failed to
release rid(%d), error (%d), please retry the task\n",rid, rc);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_extop: Failed to
release rid(%d), error (%d), "
+ "please retry the task.\n",rid, rc);
}
if(mtnode_ext->replica)
commit 8f17da54a0bddbf6f01549cfdadbce66a52aae37
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri May 25 12:26:02 2012 -0400
Ticket #110 - RFE limiting root DN by host, IP, time of day, day of week
RFE Description: There is no way to restrict when and where some one can attempt
root DN binds. An intruder can brute force guess the password all
day long until they succeed, especailly if the DS is publicly
available.
Fix Description: Created a new plugin, type "internalpreoperation" and an
internal
preop bind function. You can configure the plugin with some basic
access control:
rootdn-open-time: 0800
rootdn-close-time: 1700
rootdn-days-allowed: Mon, Tue, Wed, Thu, Fri
rootdn-allow-host: *.redhat.com
rootdn-allow-host: *.fedora.com
rootdn-deny-host:
dangerous.boracle.com
rootdn-allow-ip: 127.0.0.1
rootdn-allow-ip: 2000:db8:de30::11
rootdn-deny-ip: 192.168.1.*
As with our other ACL code, deny's always override the
allow rules.
https://fedorahosted.org/389/ticket/110
Reviewed by: richm(Thanks Rich!)
(cherry picked from commit c61ee8e16c3e3ca91ffef725fadbeb0a62fb5e80)
diff --git a/Makefile.am b/Makefile.am
index cf91842..d90cd4b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -205,7 +205,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la
\
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
- libacctusability-plugin.la $(LIBACCTPOLICY_PLUGIN) \
+ libacctusability-plugin.la librootdn-access-plugin.la $(LIBACCTPOLICY_PLUGIN) \
$(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
$(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
@@ -822,6 +822,17 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# librootdn-access-plugin
+#------------------------
+#
+librootdn_access_plugin_la_SOURCES = ldap/servers/plugins/rootdn_access/rootdn_access.c
+
+librootdn_access_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+librootdn_access_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+librootdn_access_plugin_la_LDFLAGS = -avoid-version
+
+
+#------------------------
# libautomember-plugin
#------------------------
libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
diff --git a/Makefile.in b/Makefile.in
index ab2f657..915e978 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -581,6 +581,15 @@ libroles_plugin_la_OBJECTS = $(am_libroles_plugin_la_OBJECTS)
libroles_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libroles_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
+librootdn_access_plugin_la_DEPENDENCIES = libslapd.la \
+ $(am__DEPENDENCIES_1)
+am_librootdn_access_plugin_la_OBJECTS =
ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo
+librootdn_access_plugin_la_OBJECTS = \
+ $(am_librootdn_access_plugin_la_OBJECTS)
+librootdn_access_plugin_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(librootdn_access_plugin_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
libschemareload_plugin_la_DEPENDENCIES = libslapd.la \
$(am__DEPENDENCIES_1)
am_libschemareload_plugin_la_OBJECTS =
ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo
@@ -1001,6 +1010,7 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libreferint_plugin_la_SOURCES) \
$(libreplication_plugin_la_SOURCES) \
$(libretrocl_plugin_la_SOURCES) $(libroles_plugin_la_SOURCES) \
+ $(librootdn_access_plugin_la_SOURCES) \
$(libschemareload_plugin_la_SOURCES) $(libslapd_la_SOURCES) \
$(libstatechange_plugin_la_SOURCES) \
$(libsyntax_plugin_la_SOURCES) $(libusn_plugin_la_SOURCES) \
@@ -1033,6 +1043,7 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libreferint_plugin_la_SOURCES) \
$(libreplication_plugin_la_SOURCES) \
$(libretrocl_plugin_la_SOURCES) $(libroles_plugin_la_SOURCES) \
+ $(librootdn_access_plugin_la_SOURCES) \
$(libschemareload_plugin_la_SOURCES) \
$(am__libslapd_la_SOURCES_DIST) \
$(libstatechange_plugin_la_SOURCES) \
@@ -1411,7 +1422,7 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la
\
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
- libacctusability-plugin.la $(LIBACCTPOLICY_PLUGIN) \
+ libacctusability-plugin.la librootdn-access-plugin.la $(LIBACCTPOLICY_PLUGIN) \
$(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
$(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
@@ -1968,6 +1979,15 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# librootdn-access-plugin
+#------------------------
+#
+librootdn_access_plugin_la_SOURCES = ldap/servers/plugins/rootdn_access/rootdn_access.c
+librootdn_access_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+librootdn_access_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+librootdn_access_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libautomember-plugin
#------------------------
libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
@@ -3784,6 +3804,17 @@ ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo: \
ldap/servers/plugins/roles/$(DEPDIR)/$(am__dirstamp)
libroles-plugin.la: $(libroles_plugin_la_OBJECTS) $(libroles_plugin_la_DEPENDENCIES)
$(libroles_plugin_la_LINK) -rpath $(serverplugindir) $(libroles_plugin_la_OBJECTS)
$(libroles_plugin_la_LIBADD) $(LIBS)
+ldap/servers/plugins/rootdn_access/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/rootdn_access
+ @: > ldap/servers/plugins/rootdn_access/$(am__dirstamp)
+ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/rootdn_access/$(DEPDIR)
+ @: > ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo: \
+ ldap/servers/plugins/rootdn_access/$(am__dirstamp) \
+ ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+librootdn-access-plugin.la: $(librootdn_access_plugin_la_OBJECTS)
$(librootdn_access_plugin_la_DEPENDENCIES)
+ $(librootdn_access_plugin_la_LINK) -rpath $(serverplugindir)
$(librootdn_access_plugin_la_OBJECTS) $(librootdn_access_plugin_la_LIBADD) $(LIBS)
ldap/servers/plugins/schema_reload/$(am__dirstamp):
@$(MKDIR_P) ldap/servers/plugins/schema_reload
@: > ldap/servers/plugins/schema_reload/$(am__dirstamp)
@@ -5017,6 +5048,8 @@ mostlyclean-compile:
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_cache.lo
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.$(OBJEXT)
-rm -f ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo
+ -rm -f
ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.$(OBJEXT)
+ -rm -f ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo
-rm -f
ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.$(OBJEXT)
-rm -f ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo
-rm -f ldap/servers/plugins/statechange/libstatechange_plugin_la-statechange.$(OBJEXT)
@@ -5714,6 +5747,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/rever/$(DEPDIR)/libdes_plugin_la-rever.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_cache.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/roles/$(DEPDIR)/libroles_plugin_la-roles_plugin.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/statechange/$(DEPDIR)/libstatechange_plugin_la-statechange.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@
@am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-bin.Plo(a)am__quote@
@@ -7758,6 +7792,13 @@ ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo:
ldap/servers/plug
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp)
@AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS)
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
$(libroles_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o
ldap/servers/plugins/roles/libroles_plugin_la-roles_plugin.lo `test -f
'ldap/servers/plugins/roles/roles_plugin.c' || echo
'$(srcdir)/'`ldap/servers/plugins/roles/roles_plugin.c
+ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo:
ldap/servers/plugins/rootdn_access/rootdn_access.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS)
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
$(librootdn_access_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT
ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo -MD -MP -MF
ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Tpo
-c -o ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo `test
-f 'ldap/servers/plugins/rootdn_access/rootdn_access.c' || echo
'$(srcdir)/'`ldap/servers/plugins/rootdn_access/rootdn_access.c
+@am__fastdepCC_TRUE@ $(am__mv)
ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Tpo
ldap/servers/plugins/rootdn_access/$(DEPDIR)/librootdn_access_plugin_la-rootdn_access.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/rootdn_access/rootdn_access.c'
object='ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo'
libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp)
@AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS)
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
$(librootdn_access_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o
ldap/servers/plugins/rootdn_access/librootdn_access_plugin_la-rootdn_access.lo `test -f
'ldap/servers/plugins/rootdn_access/rootdn_access.c' || echo
'$(srcdir)/'`ldap/servers/plugins/rootdn_access/rootdn_access.c
+
ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo:
ldap/servers/plugins/schema_reload/schema_reload.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS)
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
$(libschemareload_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT
ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo -MD -MP -MF
ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Tpo
-c -o ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo `test
-f 'ldap/servers/plugins/schema_reload/schema_reload.c' || echo
'$(srcdir)/'`ldap/servers/plugins/schema_reload/schema_reload.c
@am__fastdepCC_TRUE@ $(am__mv)
ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Tpo
ldap/servers/plugins/schema_reload/$(DEPDIR)/libschemareload_plugin_la-schema_reload.Plo
@@ -9779,6 +9820,7 @@ clean-libtool:
-rm -rf ldap/servers/plugins/retrocl/.libs ldap/servers/plugins/retrocl/_libs
-rm -rf ldap/servers/plugins/rever/.libs ldap/servers/plugins/rever/_libs
-rm -rf ldap/servers/plugins/roles/.libs ldap/servers/plugins/roles/_libs
+ -rm -rf ldap/servers/plugins/rootdn_access/.libs
ldap/servers/plugins/rootdn_access/_libs
-rm -rf ldap/servers/plugins/schema_reload/.libs
ldap/servers/plugins/schema_reload/_libs
-rm -rf ldap/servers/plugins/statechange/.libs ldap/servers/plugins/statechange/_libs
-rm -rf ldap/servers/plugins/syntaxes/.libs ldap/servers/plugins/syntaxes/_libs
@@ -10425,6 +10467,8 @@ distclean-generic:
-rm -f ldap/servers/plugins/rever/$(am__dirstamp)
-rm -f ldap/servers/plugins/roles/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/roles/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/rootdn_access/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/rootdn_access/$(am__dirstamp)
-rm -f ldap/servers/plugins/schema_reload/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/schema_reload/$(am__dirstamp)
-rm -f ldap/servers/plugins/statechange/$(DEPDIR)/$(am__dirstamp)
@@ -10475,7 +10519,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool
clean-local \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR)
ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR)
ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR)
ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR)
ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR)
ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR)
ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR)
ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR)
ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR)
ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR)
ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR)
ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR)
ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR)
ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR)
ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR)
ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR)
ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR)
ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR)
lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR)
ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR)
ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR)
ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR)
ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR)
ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR)
ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR)
ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR)
ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR)
ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR)
ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR)
ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR)
ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/rootdn_access/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR)
ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR)
ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR)
ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR)
ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR)
ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR)
lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -10531,7 +10575,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR)
ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR)
ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR)
ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR)
ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR)
ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR)
ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR)
ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR)
ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR)
ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR)
ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR)
ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR)
ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR)
ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR)
ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR)
ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR)
ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR)
ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR)
lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acct_usability/$(DEPDIR)
ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR)
ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR)
ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR)
ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR)
ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR)
ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR)
ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR)
ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR)
ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR)
ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR)
ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR)
ldap/servers/plugins/roles/$(DEPDIR)
ldap/servers/plugins/rootdn_access/$(DEPDIR)
ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR)
ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR)
ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR)
ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR)
ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR)
ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR)
lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index 5107d72..ddf2b35 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -734,6 +734,17 @@ nsslapd-plugintype: object
nsslapd-pluginenabled: off
nsslapd-plugin-depends-on-type: database
+dn: cn=RootDN Access Control,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: RootDN Access Control
+nsslapd-pluginpath: librootdn-access-plugin.so
+nsslapd-plugininitfunc: rootdn_init
+nsslapd-plugintype: internalpreoperation
+nsslapd-pluginenabled: off
+nsslapd-plugin-depends-on-type: database
+
dn: cn=ldbm database,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
diff --git a/ldap/servers/plugins/rootdn_access/rootdn_access.c
b/ldap/servers/plugins/rootdn_access/rootdn_access.c
new file mode 100644
index 0000000..7fb5615
--- /dev/null
+++ b/ldap/servers/plugins/rootdn_access/rootdn_access.c
@@ -0,0 +1,663 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked
combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Root DN Access Control plug-in
+ */
+#include "rootdn_access.h"
+#include <nspr.h>
+#include <time.h>
+#include <ctype.h>
+
+/*
+ * Add an entry like the following to dse.ldif to enable this plugin:
+ *
+ * dn: cn=RootDN Access Control,cn=plugins,cn=config
+ * objectclass: top
+ * objectclass: nsSlapdPlugin
+ * objectclass: extensibleObject
+ * cn: RootDN Access Control
+ * nsslapd-pluginpath: librootdn-access-plugin.so
+ * nsslapd-plugininitfunc: rootdn_init
+ * nsslapd-plugintype: rootdnpreoperation
+ * nsslapd-pluginenabled: on
+ * nsslapd-plugin-depends-on-type: database
+ * nsslapd-pluginid: rootdn-access-control
+ * rootdn-open-time: 0800
+ * rootdn-close-time: 1700
+ * rootdn-days-allowed: Mon, Tue, Wed, Thu, Fri
+ * rootdn-allow-host: *.redhat.com
+ * rootdn-allow-host: *.fedora.com
+ * rootdn-deny-host:
dangerous.boracle.com
+ * rootdn-allow-ip: 127.0.0.1
+ * rootdn-allow-ip: 2000:db8:de30::11
+ * rootdn-deny-ip: 192.168.1.*
+ *
+ */
+
+/*
+ * Plugin Functions
+ */
+int rootdn_init(Slapi_PBlock *pb);
+static int rootdn_start(Slapi_PBlock *pb);
+static int rootdn_load_config(Slapi_PBlock *pb);
+static int rootdn_check_access(Slapi_PBlock *pb);
+static int rootdn_check_host_wildcard(char *host, char *client_host);
+static int rootdn_check_ip_wildcard(char *ip, char *client_ip);
+static int rootdn_preop_bind_init(Slapi_PBlock *pb);
+char * strToLower(char *str);
+
+/*
+ * Plug-in globals
+ */
+static void *_PluginID = NULL;
+static char *_PluginDN = NULL;
+static int g_plugin_started = 0;
+static int open_time = 0;
+static int close_time = 0;
+static char *daysAllowed = NULL;
+static char **hosts = NULL;
+static char **hosts_to_deny = NULL;
+static char **ips = NULL;
+static char **ips_to_deny = NULL;
+
+static Slapi_PluginDesc pdesc = { ROOTDN_FEATURE_DESC,
+ VENDOR,
+ DS_PACKAGE_VERSION,
+ ROOTDN_PLUGIN_DESC };
+
+/*
+ * Plugin identity functions
+ */
+void
+rootdn_set_plugin_id(void *pluginID)
+{
+ _PluginID = pluginID;
+}
+
+void *
+rootdn_get_plugin_id()
+{
+ return _PluginID;
+}
+
+void
+rootdn_set_plugin_dn(char *pluginDN)
+{
+ _PluginDN = pluginDN;
+}
+
+char *
+rootdn_get_plugin_dn()
+{
+ return _PluginDN;
+}
+
+
+int
+rootdn_init(Slapi_PBlock *pb){
+ int status = 0;
+ char *plugin_identity = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, ROOTDN_PLUGIN_SUBSYSTEM,
+ "--> rootdn_init\n");
+
+ /* Store the plugin identity for later use. Used for internal operations. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
+ PR_ASSERT(plugin_identity);
+ rootdn_set_plugin_id(plugin_identity);
+
+ /* Register callbacks */
+ if(slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) rootdn_start) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0 )
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM, "rootdn_init:
failed to register plugin\n");
+ status = -1;
+ }
+
+ /* for this plugin we don't want to skip over root dn's when binding */
+ slapi_set_plugin_open_rootdn_bind(pb);
+
+ if (!status &&
+ slapi_register_plugin("internalpreoperation", /* op type */
+ 1, /* Enabled */
+ "rootdn_preop_bind_init", /* this function desc
*/
+ rootdn_preop_bind_init, /* init func */
+ ROOTDN_PLUGIN_DESC, /* plugin desc */
+ NULL, /* ? */
+ plugin_identity /* access control */
+ )) {
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
+ "rootdn_init: failed to register rootdn preoperation
plugin\n");
+ status = -1;
+ }
+
+ /*
+ * Load the config
+ */
+ if(rootdn_load_config(pb) != 0){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
+ "rootdn_start: unable to load plug-in configuration\n");
+ return -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,"<--
rootdn_init\n");
+ return status;
+}
+
+static int
+rootdn_preop_bind_init(Slapi_PBlock *pb)
+{
+ if(slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN, (void *)
rootdn_check_access) != 0){
+ slapi_log_error(SLAPI_LOG_FATAL,
ROOTDN_PLUGIN_SUBSYSTEM,"rootdn_preop_bind_init: "
+ "failed to register function\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+rootdn_start(Slapi_PBlock *pb){
+ /* Check if we're already started */
+ if (g_plugin_started) {
+ goto done;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "-->
rootdn_start\n");
+
+ g_plugin_started = 1;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "<--
rootdn_start\n");
+
+done:
+ return 0;
+}
+
+static int
+rootdn_load_config(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = NULL;
+ char *openTime, *closeTime;
+ char hour[3], min[3];
+ int result = 0;
+ int i;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "-->
rootdn_load_config\n");
+
+ if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &e) == 0) && e){
+ /*
+ * Grab our plugin settings
+ */
+ openTime = slapi_entry_attr_get_charptr(e, "rootdn-open-time");
+ closeTime = slapi_entry_attr_get_charptr(e, "rootdn-close-time");
+ daysAllowed = slapi_entry_attr_get_charptr(e, "rootdn-days-allowed");
+ hosts = slapi_entry_attr_get_charray(e, "rootdn-allow-host");
+ hosts_to_deny = slapi_entry_attr_get_charray(e, "rootdn-deny-host");
+ ips = slapi_entry_attr_get_charray(e, "rootdn-allow-ip");
+ ips_to_deny = slapi_entry_attr_get_charray(e, "rootdn-deny-ip");
+ /*
+ * Validate out settings
+ */
+ if(daysAllowed){
+ if(strcspn(daysAllowed,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ,")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "invalid rootdn-days-allowed value (%s), must be all letters,
and comma separators\n",closeTime);
+ slapi_ch_free_string(&daysAllowed);
+ return -1;
+ }
+ daysAllowed = strToLower(daysAllowed);
+ }
+ if(openTime){
+ if (strcspn(openTime, "0123456789")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "invalid rootdn-open-time value (%s), must be all
digits\n",openTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ if(strlen(openTime) != 4){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "invalid format for rootdn-open-time value (%s). Should be
HHMM\n", openTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ /*
+ * convert the time to all seconds
+ */
+ strncpy(hour, openTime,2);
+ strncpy(min, openTime+2,2);
+ open_time = (atoi(hour) * 3600) + (atoi(min) * 60);
+ }
+ if(closeTime){
+ if (strcspn(closeTime, "0123456789")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "invalid rootdn-open-time value (%s), must be all digits, and
should be HHMM\n",closeTime);
+ slapi_ch_free_string(&closeTime);
+ return -1;
+ }
+ if(strlen(closeTime) != 4){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "invalid format for rootdn-open-time value (%s), should be
HHMM\n", closeTime);
+ slapi_ch_free_string(&closeTime);
+ return -1;
+ }
+ /*
+ * convert the time to all seconds
+ */
+
+ strncpy(hour, closeTime,2);
+ strncpy(min, closeTime+2,2);
+ close_time = (atoi(hour) * 3600) + (atoi(min) * 60);
+ }
+ if((openTime && closeTime == NULL) || (openTime == NULL &&
closeTime)){
+ /* If you are using TOD access control, you must have a open and close time
*/
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "there must be a open and a close time\n");
+ slapi_ch_free_string(&closeTime);
+ slapi_ch_free_string(&openTime);
+ return -1;
+ }
+ if(close_time && open_time && close_time <= open_time){
+ /* Make sure the closing time is greater than the open time */
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "the close time must be greater than the open time\n");
+ result = -1;
+ }
+ if(hosts){
+ for(i = 0; hosts[i] != NULL; i++){
+ if(strcspn(hosts[i],
"0123456789.*-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "hostname (%s) contians invalid characters,
skipping\n",hosts[i]);
+ slapi_ch_free_string(&hosts[i]);
+ hosts[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ if(hosts_to_deny){
+ for(i = 0; hosts_to_deny[i] != NULL; i++){
+ if(strcspn(hosts_to_deny[i],
"0123456789.*-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "hostname (%s) contians invalid characters,
skipping\n",hosts_to_deny[i]);
+ slapi_ch_free_string(&hosts_to_deny[i]);
+ hosts_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ if(ips){
+ for(i = 0; ips[i] != NULL; i++){
+ if(strcspn(ips[i], "0123456789:ABCDEFabcdef.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "IP address contains invalid characters (%s),
skipping\n", ips[i]);
+ slapi_ch_free_string(&ips[i]);
+ ips[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ if(strstr(ips[i],":") == 0){
+ /*
+ * IPv4 - make sure it's just numbers, dots, and wildcard
+ */
+ if(strcspn(ips[i], "0123456789.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "IPv4 address contains invalid characters (%s),
skipping\n", ips[i]);
+ slapi_ch_free_string(&ips[i]);
+ ips[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ }
+ if(ips_to_deny){
+ for(i = 0; ips_to_deny[i] != NULL; i++){
+ if(strcspn(ips_to_deny[i], "0123456789:ABCDEFabcdef.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "IP address contains invalid characters (%s),
skipping\n", ips_to_deny[i]);
+ slapi_ch_free_string(&ips_to_deny[i]);
+ ips_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ if(strstr(ips_to_deny[i],":") == 0){
+ /*
+ * IPv4 - make sure it's just numbers, dots, and wildcard
+ */
+ if(strcspn(ips_to_deny[i], "0123456789.*")){
+ slapi_log_error(SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_load_config: "
+ "IPv4 address contains invalid characters (%s),
skipping\n", ips_to_deny[i]);
+ slapi_ch_free_string(&ips_to_deny[i]);
+ ips_to_deny[i] = slapi_ch_strdup("!invalid");
+ continue;
+ }
+ }
+ }
+ }
+ slapi_ch_free_string(&openTime);
+ slapi_ch_free_string(&closeTime);
+ } else {
+ /* failed to get the plugin entry */
+ result = -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM, "<--
rootdn_load_config (%d)\n", result);
+
+ return result;
+}
+
+
+static int
+rootdn_check_access(Slapi_PBlock *pb){
+ PRNetAddr *client_addr = NULL;
+ PRHostEnt *host_entry = NULL;
+ time_t curr_time;
+ struct tm *timeinfo;
+ char *dnsName = NULL;
+ int isRoot = 0;
+ int rc = 0;
+ int i;
+
+ /*
+ * Verify this is a root DN
+ */
+ slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
+ if(!isRoot){
+ return 0;
+ }
+ /*
+ * grab the current time/info if we need it
+ */
+ if(open_time || daysAllowed){
+ time(&curr_time);
+ timeinfo = localtime(&curr_time);
+ }
+ /*
+ * First check TOD restrictions, continue through if we are in the open
"window"
+ */
+ if(open_time){
+ int curr_total;
+
+ curr_total = (timeinfo->tm_hour * 3600) + (timeinfo->tm_min * 60);
+
+ if((curr_total < open_time) || (curr_total >= close_time)){
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: bind not in the "
+ "allowed time window\n");
+ return -1;
+ }
+ }
+ /*
+ * Check if today is an allowed day
+ */
+ if(daysAllowed){
+ char *timestr;
+ char day[4];
+ char *today = day;
+
+ timestr = asctime(timeinfo); // DDD MMM dd hh:mm:ss YYYY
+ memmove(day, timestr, 3); // we only want the day
+ today = strToLower(today);
+
+ if(!strstr(today, daysAllowed)){
+ slapi_log_error(SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: bind not allowed for today\n");
+ return -1;
+ }
+ }
+ /*
+ * Check the host restrictions, deny always overrides allow
+ */
+ if(hosts || hosts_to_deny){
+ char buf[PR_NETDB_BUF_SIZE];
+ char *host;
+
+ /*
+ * Get the client address
+ */
+ client_addr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
+ if ( slapi_pblock_get( pb, SLAPI_CONN_CLIENTNETADDR, client_addr ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: Could not get client address for hosts.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ /*
+ * Get the hostname from the client address
+ */
+ host_entry = (PRHostEnt *)slapi_ch_malloc( sizeof(PRHostEnt) );
+ if ( PR_GetHostByAddr(client_addr, buf, sizeof(buf), host_entry ) == PR_SUCCESS )
{
+ if ( host_entry->h_name != NULL ) {
+ /* copy the hostname */
+ dnsName = slapi_ch_strdup( host_entry->h_name );
+ } else {
+ /* no hostname */
+ slapi_log_error( SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: client address missing hostname\n");
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ slapi_log_error( SLAPI_LOG_PLUGIN, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: client IP address could not be resolved\n");
+ rc = -1;
+ goto free_and_return;
+ }
+ /*
+ * Now we have our hostname, now do our checks
+ */
+ if(hosts_to_deny){
+ for(i = 0; hosts_to_deny[i] != NULL; i++){
+ host = hosts_to_deny[i];
+ /* check for wild cards */
+ if(host[0] == '*'){
+ if(rootdn_check_host_wildcard(host, dnsName) == 0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(host,dnsName) == 0){
+ /* we have a match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = 0;
+ }
+ if(hosts){
+ for(i = 0; hosts[i] != NULL; i++){
+ host = hosts[i];
+ /* check for wild cards */
+ if(host[0] == '*'){
+ if(rootdn_check_host_wildcard(host, dnsName) == 0){
+ /* match */
+ rc = 0;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(host,dnsName) == 0){
+ /* we have a match, */
+ rc = 0;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = -1;
+ }
+ }
+ /*
+ * Check the IP address restrictions, deny always overrides allow
+ */
+ if(ips || ips_to_deny){
+ char ip_str[256];
+ char *ip;
+ int ip_len, i;
+
+ if(client_addr == NULL){
+ client_addr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
+ if ( slapi_pblock_get( pb, SLAPI_CONN_CLIENTNETADDR, client_addr ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: Could not get client address for IP.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ /*
+ * Check if we are IPv4, so we can grab the correct IP addr for
"ip_str"
+ */
+ if ( PR_IsNetAddrType( client_addr, PR_IpAddrV4Mapped ) ) {
+ PRNetAddr v4addr;
+ memset( &v4addr, 0, sizeof( v4addr ) );
+ v4addr.inet.family = PR_AF_INET;
+ v4addr.inet.ip = client_addr->ipv6.ip.pr_s6_addr32[3];
+ if( PR_NetAddrToString( &v4addr, ip_str, sizeof( ip_str )) !=
PR_SUCCESS){
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: Could not get IPv4 from client address.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if( PR_NetAddrToString(client_addr, ip_str, sizeof(ip_str)) != PR_SUCCESS){
+ slapi_log_error( SLAPI_LOG_FATAL, ROOTDN_PLUGIN_SUBSYSTEM,
"rootdn_check_access: Could not get IPv6 from client address.\n" );
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ /*
+ * Now we have our IP address, do our checks
+ */
+ if(ips_to_deny){
+ for(i = 0; ips_to_deny[i] != NULL; i++){
+ ip = ips_to_deny[i];
+ ip_len = strlen(ip);
+ if(ip[ip_len - 1] == '*'){
+ if(rootdn_check_ip_wildcard(ips_to_deny[i], ip_str) == 0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(ip_str, ip)==0){
+ /* match, return failure */
+ rc = -1;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = 0;
+ }
+ if(ips){
+ for(i = 0; ips[i] != NULL; i++){
+ ip = ips[i];
+ ip_len = strlen(ip);
+ if(ip[ip_len - 1] == '*'){
+ if(rootdn_check_ip_wildcard(ip, ip_str) == 0){
+ /* match, return success */
+ rc = 0;
+ goto free_and_return;
+ }
+ } else {
+ if(strcasecmp(ip_str, ip)==0){
+ /* match, return success */
+ rc = 0;
+ goto free_and_return;
+ }
+ }
+ }
+ rc = -1;
+ }
+ }
+
+free_and_return:
+ slapi_ch_free((void **)&client_addr);
+ slapi_ch_free((void **)&host_entry);
+ slapi_ch_free_string(&dnsName);
+
+ return rc;
+}
+
+static int
+rootdn_check_host_wildcard(char *host, char *client_host)
+{
+ int host_len = strlen(host);
+ int client_len = strlen(client_host);
+ int i, j;
+ /*
+ * Start at the end of the string and move backwards, and skip the first char
"*"
+ */
+ if(client_len < host_len){
+ /* this can't be a match */
+ return -1;
+ }
+ for(i = host_len - 1, j = client_len - 1; i > 0; i--, j--){
+ if(host[i] != client_host[j]){
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+rootdn_check_ip_wildcard(char *ip, char *client_ip)
+{
+ int ip_len = strlen(ip);
+ int i;
+ /*
+ * Start at the beginning of the string and move forward, and skip the last char
"*"
+ */
+ if(strlen(client_ip) < ip_len){
+ /* this can't be a match */
+ return -1;
+ }
+ for(i = 0; i < ip_len - 1; i++){
+ if(ip[i] != client_ip[i]){
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+char *
+strToLower(char *str){
+ int i;
+
+ for(i = 0; i < strlen(str); i++){
+ str[i] = tolower(str[i]);
+ }
+ return str;
+}
+
+
diff --git a/ldap/servers/plugins/rootdn_access/rootdn_access.h
b/ldap/servers/plugins/rootdn_access/rootdn_access.h
new file mode 100644
index 0000000..80b8d4a
--- /dev/null
+++ b/ldap/servers/plugins/rootdn_access/rootdn_access.h
@@ -0,0 +1,57 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked
combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Root DN access control plug-in header file
+ */
+#include "slapi-plugin.h"
+#include <nspr.h>
+#include <time.h>
+#include <ctype.h>
+
+#define ROOTDN_PLUGIN_SUBSYSTEM "rootdn-access-control-plugin"
+#define ROOTDN_FEATURE_DESC "Root DN Access Control"
+#define ROOTDN_PLUGIN_DESC "Root DN Access Control plugin"
+#define ROOTDN_PLUGIN_TYPE_DESC "Root DN Access Control plugin"
+
+
+
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index d725d5c..d4d3b49 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -614,21 +614,41 @@ do_bind( Slapi_PBlock *pb )
Slapi_Value cv;
slapi_value_init_berval(&cv,&cred);
- /* right dn and passwd - authorize */
+ /*
+ * Call pre bind root dn plugin for checking root dn access control.
+ *
+ * Do this before checking the password so that we give a consistent error,
+ * regardless if the password is correct or not. Or else it would still be
+ * possible to brute force guess the password even though access would
still
+ * be denied.
+ */
+ if (plugin_call_plugins(pb, SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN) != 0){
+ send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "RootDN access control violation", 0, NULL );
+
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
+ value_done(&cv);
+ goto free_and_return;
+ }
+ /*
+ * Check the dn and password
+ */
if ( is_root_dn_pw( slapi_sdn_get_ndn(sdn), &cv )) {
- bind_credentials_set( pb->pb_conn, SLAPD_AUTH_SIMPLE,
- slapi_ch_strdup( slapi_sdn_get_ndn(sdn) ),
+ /*
+ * right dn and passwd - authorize
+ */
+ bind_credentials_set( pb->pb_conn, SLAPD_AUTH_SIMPLE,
slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
NULL, NULL, NULL , NULL);
-
- /* right dn, wrong passwd - reject with invalid creds */
} else {
- send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL,
- NULL, 0, NULL );
+ /*
+ * right dn, wrong passwd - reject with invalid credentials
+ */
+ send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
/* increment BindSecurityErrorcount */
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
value_done(&cv);
goto free_and_return;
}
+
value_done(&cv);
}
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 76c031a..4be8efd 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1062,6 +1062,14 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
(*(IFP *)value) = pblock->pb_plugin->plg_internal_post_delete;
break;
+ /* rootDN pre bind operation plugin */
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_INTERNAL_PREOPERATION) {
+ return( -1 );
+ }
+ (*(IFP *)value) = pblock->pb_plugin->plg_internal_pre_bind;
+ break;
+
/* backend pre txn operation plugin */
case SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN:
if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BETXNPREOPERATION) {
@@ -2620,6 +2628,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
}
pblock->pb_plugin->plg_internal_pre_delete = (IFP) value;
break;
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
+ if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_INTERNAL_PREOPERATION) {
+ return( -1 );
+ }
+ pblock->pb_plugin->plg_internal_pre_bind = (IFP) value;
+ break;
/* internal postoperation plugin */
case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 8aa95ac..436cc02 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -363,6 +363,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
+ case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
plugin_list_number= PLUGIN_LIST_INTERNAL_PREOPERATION;
break;
case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
@@ -387,6 +388,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction )
do_op = 1; /* always allow backend callbacks (even during startup) */
break;
}
+
if(plugin_list_number!=-1 && do_op)
{
/* We stash the pblock plugin pointer to preserve the callers context */
@@ -1705,7 +1707,7 @@ plugin_get_type_and_list(
} else if ( strcasecmp( plugintype, "index" ) == 0 ) {
*type = SLAPI_PLUGIN_INDEX;
plugin_list_index= PLUGIN_LIST_INDEX;
- } else {
+ } else {
return( 1 ); /* unknown plugin type - pass to backend */
}
@@ -3205,3 +3207,10 @@ slapi_get_plugin_default_config(char *type, Slapi_ValueSet
**valueset)
return rc;
}
+
+void
+slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb){
+ struct pluginconfig *config = &pb->pb_plugin->plg_conf;
+
+ ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_BIND_ROOT);
+}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b896755..7ca9a35 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1004,11 +1004,13 @@ struct slapdplugin {
IFP plg_un_internal_pre_modrdn; /* modrdn */
IFP plg_un_internal_pre_add; /* add */
IFP plg_un_internal_pre_delete; /* delete */
+ IFP plg_un_internal_pre_bind; /* bind */
} plg_un_internal_pre;
#define plg_internal_pre_modify plg_un.plg_un_internal_pre.plg_un_internal_pre_modify
#define plg_internal_pre_modrdn plg_un.plg_un_internal_pre.plg_un_internal_pre_modrdn
#define plg_internal_pre_add plg_un.plg_un_internal_pre.plg_un_internal_pre_add
#define plg_internal_pre_delete plg_un.plg_un_internal_pre.plg_un_internal_pre_delete
+#define plg_internal_pre_bind plg_un.plg_un_internal_pre.plg_un_internal_pre_bind
/* internal post-operation plugin structure */
struct plg_un_internal_post_operation {
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 659ac61..0aa764d 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6296,6 +6296,7 @@ typedef struct slapi_plugindesc {
#define SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN 421
#define SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN 422
#define SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN 423
+#define SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN 424
/* preoperation plugin to the backend */
#define SLAPI_PLUGIN_BE_PRE_ADD_FN 450
@@ -7069,6 +7070,8 @@ uint32_t slapi_str_to_u32(const char *s);
*/
uint64_t slapi_str_to_u64(const char *s);
+void slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb);
+
#ifdef __cplusplus
}
#endif