[Fedora-directory-commits] ldapserver/ldap/servers/plugins/dna Makefile, NONE, 1.1 addentries.sh, NONE, 1.1 config.sh, NONE, 1.1 del_test_entries.dns, NONE, 1.1 delentries.sh, NONE, 1.1 dna.c, NONE, 1.1 dna.ldif, NONE, 1.1 editentries.sh, NONE, 1.1 oneentry.sh, NONE, 1.1 posix.ldif, NONE, 1.1 posix_one.ldif, NONE, 1.1 posix_test.ldif, NONE, 1.1 seeconfig.sh, NONE, 1.1 seeentries.sh, NONE, 1.1 subtest.ldif, NONE, 1.1

Pete Rowley (prowley) fedora-directory-commits at redhat.com
Wed Jan 31 22:49:27 UTC 2007


Author: prowley

Update of /cvs/dirsec/ldapserver/ldap/servers/plugins/dna
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv24292/ldap/servers/plugins/dna

Added Files:
	Makefile addentries.sh config.sh del_test_entries.dns 
	delentries.sh dna.c dna.ldif editentries.sh oneentry.sh 
	posix.ldif posix_one.ldif posix_test.ldif seeconfig.sh 
	seeentries.sh subtest.ldif 
Log Message:
Distributed numeric assignment plugin - initial check in



--- NEW FILE Makefile ---
#
# 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) 2007 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#
LDAP_SRC = ../../..
BUILD_ROOT = ../../../..

NOSTDCLEAN=true # don't let nsconfig.mk define target clean
NOSTDSTRIP=true # don't let nsconfig.mk define target strip

OBJDEST = $(OBJDIR)/lib/libdna
LIBDIR = $(LDAP_PLUGIN_RELDIR)

include $(BUILD_ROOT)/nsdefs.mk
include $(BUILD_ROOT)/nsconfig.mk
include $(LDAP_SRC)/nsldap.mk

ifeq ($(ARCH), WINNT)
DEF_FILE:=./dna.def
endif

DNA_OBJS =	dna.o
OBJS = $(addprefix $(OBJDEST)/, $(DNA_OBJS)) 

DNA_DLL = libdna-plugin

INCLUDES += -I../http -I../../slapd  -I../../../include  
CFLAGS+=$(SLCFLAGS) -DSLAPD_LOGGING

ifeq ($(ARCH), WINNT)
EXTRA_LIBS_DEP +=   $(LIBSLAPD) $(NSPR_DEP) $(LDAPSDK_DEP)
EXTRA_LIBS_DEP +=   $(LDAP_COMMON_LIBS_DEP)
EXTRA_LIBS += $(NSPRLINK)  $(LIBSLAPD) $(LDAP_SDK_LIBLDAP_DLL)
EXTRA_LIBS += $(LDAP_COMMON_LIBS)
DNA_DLL_OBJ = $(addprefix $(OBJDEST)/, dllmain.o)
endif

ifeq ($(ARCH), AIX)
EXTRA_LIBS_DEP +=   $(LIBSLAPD) $(NSPR_DEP) $(LDAPSDK_DEP)
EXTRA_LIBS_DEP +=   $(LDAP_COMMON_LIBS_DEP)
EXTRA_LIBS += $(LIBSLAPDLINK)  $(NSPRLINK)  $(LDAP_SDK_LIBLDAP_DLL)
EXTRA_LIBS += $(LDAP_COMMON_LIBS)
LD=ld
endif

ifeq ($(ARCH), HPUX)
EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAPSDK_DEP) $(NSPR_DEP) $(SECURITY_DEP)
EXTRA_LIBS_DEP +=   $(LDAP_COMMON_LIBS_DEP)
EXTRA_LIBS += $(LDAPLINK) $(SECURITYLINK) $(NSPRLINK) $(ICULINK)
EXTRA_LIBS += $(LDAP_COMMON_LIBS)
endif

DNA=	$(addprefix $(LIBDIR)/, $(DNA_DLL).$(DLL_SUFFIX))

clientSDK: 

all:	$(OBJDEST) $(LIBDIR) $(DNA)

ifeq ($(ARCH), WINNT)
$(DNA): $(OBJS) $(DNA_DLL_OBJ) $(DEF_FILE)
	$(LINK_DLL) $(DNA_DLL_OBJ) $(EXTRA_LIBS) /DEF:$(DEF_FILE)
else
$(DNA): $(OBJS) $(DNA_DLL_OBJ) 
	$(LINK_DLL) $(DNA_DLL_OBJ) $(EXTRA_LIBS)
endif


veryclean: clean

clean:
	$(RM) $(OBJS)
ifeq ($(ARCH), WINNT)
	$(RM) $(DNA_DLL_OBJ)
endif
	$(RM) $(DNA)

$(OBJDEST):
	$(MKDIR) $(OBJDEST)

$(LIBDIR):
	$(MKDIR) $(LIBDIR)


--- NEW FILE addentries.sh ---
#!/bin/sh
ldapadd -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f posix_test.ldif -c


--- NEW FILE config.sh ---
#!/bin/sh
ldapadd -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f dna.ldif -c
ldapadd -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f posix.ldif -c
ldapadd -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f subtest.ldif -c



--- NEW FILE del_test_entries.dns ---
uid=add_has_magic_number, dc=example, dc=com
uid=add_second_has_magic_number, dc=example, dc=com
uid=no_uid_number, dc=example, dc=com
uid=add_has_uid_number_550, dc=example, dc=com
uid=add_is_sub, ou=sub, dc=example, dc=com
ou=sub, dc=example, dc=com


--- NEW FILE delentries.sh ---
#!/bin/sh
ldapdelete -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f del_test_entries.dns -c


--- NEW FILE dna.c ---
/** 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) 2007 Red Hat, Inc.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


/**
 * Distributed Numeric Assignment plug-in 
 */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "portable.h"
#include "nspr.h"
#include "slapi-private.h"
#include "dirlite_strings.h"
#include "dirver.h"
#include "prclist.h"
#include "ldif.h"

/* get file mode flags for unix */
#ifndef _WIN32
#include <sys/stat.h>
#endif

#define DNA_PLUGIN_SUBSYSTEM			"dna-plugin"
#define DNA_PLUGIN_VERSION				0x00010000

#define DNA_DN							"cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config" /* temporary */

#define DNA_SUCCESS					0
#define DNA_FAILURE					-1

/**
 * DNA config types
 */
#define DNA_TYPE	"dnaType"
#define DNA_PREFIX	"dnaPrefix"
#define DNA_NEXTVAL	"dnaNextValue"
#define DNA_INTERVAL	"dnaInterval"
#define DNA_GENERATE	"dnaMagicRegen"
#define DNA_FILTER	"dnaFilter"
#define DNA_SCOPE	"dnaScope"

#define FEATURE_DESC	"Distributed Numeric Assignment"
#define PLUGIN_DESC	"Distributed Numeric Assignment plugin"

static Slapi_PluginDesc pdesc = { 	FEATURE_DESC,
				  	PLUGIN_MAGIC_VENDOR_STR,
				  	PRODUCTTEXT,
					PLUGIN_DESC };


/**
 * linked list of config entries
 */

struct _defs {
	PRCList list;
	char *dn;
	char *type;
	char *prefix;
	unsigned long nextval;
	unsigned long interval;
	struct slapi_filter *filter;
	char *generate;
	char *scope;
} dna_anchor;
typedef struct _defs configEntry;
static PRCList *config;
static PRRWLock *g_dna_cache_lock;

static void *_PluginID					= NULL;
static char *_PluginDN					= NULL;


/*
 * new value lock
 */
static Slapi_Mutex *g_new_value_lock;

/**
 *	
 * DNA plug-in management functions
 *
 */
int dna_init(Slapi_PBlock *pb); 
static int dna_start(Slapi_PBlock *pb);
static int dna_close(Slapi_PBlock *pb);
static int dna_postop_init(Slapi_PBlock *pb);

/**
 *	
 * Local operation functions
 *
 */
static int loadPluginConfig();
static int parseConfigEntry(Slapi_Entry *e);
static void deleteConfig();
static void freeConfigEntry(configEntry **entry);

/**
 *
 * helpers
 *
 */
static char *dna_get_dn(Slapi_PBlock *pb);
static int dna_dn_is_config(char *dn);
static int dna_get_next_value(configEntry *config_entry, char **next_value_ret);

/**
 *
 * the ops (where the real work is done)
 *
 */
static int dna_config_check_post_op(Slapi_PBlock *pb);
static int dna_pre_op( Slapi_PBlock *pb, int modtype );
static int dna_mod_pre_op( Slapi_PBlock *pb );
static int dna_add_pre_op( Slapi_PBlock *pb );

/**
 * debug functions - global, for the debugger
 */
void dnaDumpConfig();
void dnaDumpConfigEntry(configEntry *);

/**
 * set the debug level
 */
#ifdef _WIN32
int *module_ldap_debug = 0;

void plugin_init_debug_level(int *level_ptr)
{
	module_ldap_debug = level_ptr;
}
#endif

/**
 *
 * Deal with cache locking
 *
 */
void dna_read_lock()
{
        PR_RWLock_Rlock(g_dna_cache_lock);
}

void dna_write_lock()
{
        PR_RWLock_Wlock(g_dna_cache_lock);
}

void dna_unlock()
{
        PR_RWLock_Unlock(g_dna_cache_lock);
}

/**
 *	
 * Get the dna plug-in version
 *
 */
int dna_version()
{
	return DNA_PLUGIN_VERSION;
}

/**
 * Plugin identity mgmt
 */
void setPluginID(void * pluginID) 
{
	_PluginID=pluginID;
}

void * getPluginID()
{
	return _PluginID;
}

void setPluginDN(char *pluginDN)
{
	_PluginDN = pluginDN;
}

char * getPluginDN()
{
	return _PluginDN;
}

/* 
	dna_init
	-------------
	adds our callbacks to the list
*/
int dna_init( Slapi_PBlock *pb )
{
	int status = DNA_SUCCESS;
	char * plugin_identity=NULL;

	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_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);
	setPluginID(plugin_identity);

	if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
	    	SLAPI_PLUGIN_VERSION_01 ) != 0 ||
		slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
        	     (void *) dna_start ) != 0 ||
	    	slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
        	     (void *) dna_close ) != 0 ||
		slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
             		(void *)&pdesc ) != 0 ||
	        slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
        	         (void *) dna_mod_pre_op ) != 0 ||
	        slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN,
        	         (void *) dna_add_pre_op ) != 0 ||
		/* the config change checking post op */
		slapi_register_plugin(
			"postoperation",	/* op type */
			1, 			/* Enabled */ 
			"dna_init", 		/* this function desc */
			dna_postop_init,	/* init func for post op */ 
			PLUGIN_DESC,		/* plugin desc */
			NULL,			/* ? */
			plugin_identity		/* access control */
			)
	)
	{
		slapi_log_error( SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                     "dna_init: failed to register plugin\n" );
		status = DNA_FAILURE;
	}

	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_init\n");
    return status;
}


static int dna_postop_init(Slapi_PBlock *pb)
{
        int status = DNA_SUCCESS;

        if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
                SLAPI_PLUGIN_VERSION_01 ) != 0 ||
                slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
                        (void *)&pdesc ) != 0 ||
                slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
                         (void *) dna_config_check_post_op ) != 0 ||
                slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
                         (void *) dna_config_check_post_op ) != 0 ||
                slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
                         (void *) dna_config_check_post_op ) != 0 ||
                slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
                         (void *) dna_config_check_post_op ) != 0
		)
        {
                slapi_log_error( SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                     "dna_postop_init: failed to register plugin\n" );
                status = DNA_FAILURE;
        }

	return status;
}

/*
	dna_start
	--------------
	Kicks off the config cache.
	It is called after dna_init.
*/
static int dna_start( Slapi_PBlock *pb )
{
	char * plugindn = NULL;
	char * httpRootDir = NULL;

	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_start\n");

	config = &dna_anchor.list;
        g_dna_cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "dna");
	g_new_value_lock = slapi_new_mutex();

	if(!g_dna_cache_lock || !g_new_value_lock)
	{
                slapi_log_error( SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
	           "dna_start: lock creation failed\n" );

		return DNA_FAILURE;
	}

	/**
	 *	Get the plug-in target dn from the system
	 *	and store it for future use. This should avoid 
	 *	hardcoding of DN's in the code. 
	 */
	slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn);
	if (plugindn == NULL || strlen(plugindn) == 0)
	{
		slapi_log_error( SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM , 
			"dna_start: had to use hard coded config dn\n");
		plugindn = DNA_DN;
	}
	else
	{
		slapi_log_error( SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM ,
                        "dna_start: config at %s\n", plugindn);

	}

	setPluginDN(plugindn);	

	/**
	 * Load the config for our plug-in
	 */
	PR_INIT_CLIST(config);
	if (loadPluginConfig() != DNA_SUCCESS)
	{
		slapi_log_error( SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
    	   "dna_start: unable to load plug-in configuration\n" );
		return DNA_FAILURE;
	}

	slapi_log_error( SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM , "dna: ready for service\n");
	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_start\n");

	return DNA_SUCCESS;
}

/*
	dna_close
	--------------
	closes down the cache
*/
static int dna_close( Slapi_PBlock *pb )
{
	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_close\n");

	deleteConfig();

	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_close\n");

	return DNA_SUCCESS;
}

/* 
 * config looks like this
 * - cn=myplugin
 * --- ou=posix
 * ------ cn=accounts
 * ------ cn=groups
 * --- cn=samba
 * --- cn=etc
 * ------ cn=etc etc
 */
static int loadPluginConfig()
{
	int status = DNA_SUCCESS;
	int result;
	int i;
	Slapi_PBlock *search_pb;
	Slapi_Entry **entries = NULL;

	slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> loadPluginConfig\n");

	dna_write_lock();
	deleteConfig();

	search_pb = slapi_pblock_new();

	slapi_search_internal_set_pb(search_pb, DNA_DN, LDAP_SCOPE_SUBTREE,
		"objectclass=*", NULL, 0, NULL, NULL, getPluginID(), 0);
	slapi_search_internal_pb(search_pb);
	slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);

	if (status != DNA_SUCCESS)
	{
		status = DNA_SUCCESS;
		goto cleanup;
	}
	
	slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
	if (NULL == entries || entries[0] == NULL)
	{
		status = DNA_SUCCESS;
		goto cleanup;
	}

	for (i = 0; (entries[i] != NULL); i++)
	{
		status = parseConfigEntry(entries[i]);
	}

cleanup:
    	slapi_free_search_results_internal(search_pb);
    	slapi_pblock_destroy(search_pb);
	dna_unlock();
        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- loadPluginConfig\n");

	return status;
}

static int parseConfigEntry(Slapi_Entry *e)
{
	char *key			= NULL;
	char *value			= NULL;
	configEntry *entry	= NULL;
	configEntry *config_entry = NULL;
	Slapi_Attr *attr	= NULL;
	PRCList *list = NULL;
	int entry_added = 0;

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> parseConfigEntry\n");

	entry = (configEntry*) slapi_ch_calloc(1, sizeof(configEntry));
	if(0 == entry)
		goto bail;

        value = slapi_entry_get_ndn(e);
        if(value) {
                entry->dn = strdup(value);
        }

        slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dn [%s] \n",entry->dn,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_TYPE);
	if(value) {
		entry->type = value;
	}
	else
		goto bail;

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaType [%s] \n",entry->type,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
	if (value) {
		entry->nextval = strtoul(value,0,0);
		slapi_ch_free_string(&value);
		value = 0;
	}
	else
		goto bail;

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaNextValue [%d] \n",entry->nextval,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_PREFIX);
	if (value) {
		entry->prefix = value;
	}

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaPrefix [%s] \n",entry->prefix,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
	if (value) {
		entry->interval = strtoul(value,0,0);
		slapi_ch_free_string(&value);
		value = 0;
	}
	else
		goto bail;

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaInterval [%s] \n",value,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_GENERATE);
	if (value) {
		entry->generate = value;
	}

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaMagicRegen [%s] \n",entry->generate,0,0);

	value = slapi_entry_attr_get_charptr(e, DNA_FILTER);
	if (value) {
		entry->filter = slapi_str2filter(value);
	}
	else
		goto bail;

	slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaFilter [%s] \n",value,0,0);

	slapi_ch_free_string(&value);
	value = 0;

        value = slapi_entry_attr_get_charptr(e, DNA_SCOPE);
        if (value) {
		char *canonical_dn = slapi_dn_normalize(value);
                entry->scope = canonical_dn;
        }

        slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "----------> dnaScope [%s] \n",entry->scope,0,0);


	/**
	 * Finally add the entry to the list
	 * we group by type then by filter
	 * and finally sort by dn length with longer dn's
	 * first - this allows the scope checking
	 * code to be simple and quick and
	 * cunningly linear
	 */
        if(!PR_CLIST_IS_EMPTY(config))
        {
                list = PR_LIST_HEAD(config);
                while(list != config)
                {
                        config_entry = (configEntry*)list;
			
			if(slapi_attr_type_cmp(config_entry->type, entry->type,1))
				goto next;

			if(slapi_filter_compare(config_entry->filter, entry->filter))
				goto next;

			if(slapi_dn_issuffix(entry->scope,config_entry->scope))
			{
				PR_INSERT_BEFORE(&(entry->list), list);
				slapi_log_error( SLAPI_LOG_CONFIG,
					DNA_PLUGIN_SUBSYSTEM , 
					"store [%s] before [%s] \n",entry->scope,config_entry->scope,0);
				entry_added = 1;
				break;
			}

next:
                        list = PR_NEXT_LINK (list);

			if(config == list)
			{
				/* add to tail */
				PR_INSERT_BEFORE(&(entry->list), list);
				slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "store [%s] at tail\n",entry->scope,0,0);
				entry_added = 1;
				break;
			}
                }
	}
	else
	{
		/* first entry */
		PR_INSERT_LINK(&(entry->list), config);
                slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM , "store [%s] at head \n",entry->scope,0,0);
		entry_added = 1;
	}

bail:
	if(0 == entry_added)
	{
		slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM ,
			"config entry [%s] skipped\n",entry->dn,0,0);
		freeConfigEntry(&entry);	
	}

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- parseConfigEntry\n");

	return DNA_SUCCESS;
}

static void freeConfigEntry(configEntry **entry)
{
	configEntry *e = *entry;

	if(e->dn)
	{
		slapi_log_error( SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM ,
                        "freeing config entry [%s]\n",e->dn,0,0);
		slapi_ch_free_string(&e->dn);
	}

        if(e->type)
		slapi_ch_free_string(&e->type);

        if(e->prefix)
		slapi_ch_free_string(&e->prefix);

        if(e->filter)
		slapi_filter_free(e->filter,1);

        if(e->generate)
		slapi_ch_free_string(&e->generate);

        if(e->scope)
		slapi_ch_free_string(&e->scope);

	slapi_ch_free((void**)entry);
}

static void deleteConfigEntry(PRCList *entry)
{
	PR_REMOVE_LINK(entry);
	freeConfigEntry((configEntry**)&entry);
}

static void deleteConfig()
{
	PRCList *list;

	while(!PR_CLIST_IS_EMPTY(config))
	{
		list = PR_LIST_HEAD(config);
		deleteConfigEntry(list);
	}

	return;
}


/****************************************************
	Helpers
****************************************************/

static char *dna_get_dn(Slapi_PBlock *pb)
{
	char *dn = 0;
        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_get_dn\n");

        if(slapi_pblock_get( pb, SLAPI_TARGET_DN, &dn ))
        {
                slapi_log_error( SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, "dna_get_dn: failed to get dn of changed entry");
                goto bail;
        }

/*        slapi_dn_normalize( dn );
*/
bail:
        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_get_dn\n");

	return dn;
}

/* config check
        matching config dn or a descendent reloads config
*/
static int dna_dn_is_config(char *dn)
{
        int ret = 0;

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_is_config\n");

        if(slapi_dn_issuffix(dn, getPluginDN()))
        {
                ret=1;
        }

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_is_config\n");

        return ret;
}


/****************************************************
        Functions that actually do things other
        than config and startup
****************************************************/


/*
 * Perform ldap operationally atomic increment
 * Return the next value to be assigned
 * Method:
 * 1. retrieve entry
 * 2. remove current value, add new value in one operation
 * 3. if failed, and less than 3 times, goto 1
 */
static int dna_get_next_value(configEntry *config_entry, char **next_value_ret)
{
	int ret = LDAP_SUCCESS;
	Slapi_DN *dn = 0;
	char *attrlist[3];
	Slapi_Entry *e = 0;
	int attempts = 0;

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_get_next_value\n");

	/* get pre-requisites to search */
	dn = slapi_sdn_new_dn_byref(config_entry->dn);
	attrlist[0] = DNA_NEXTVAL;
	attrlist[1] = DNA_INTERVAL;
	attrlist[2] = 0;


	/* the operation is constructed such that race conditions
	 * to increment the value are detected and avoided - one wins,
	 * one loses - however, there is no need for the server to compete
	 * with itself so we lock here
	 */

	slapi_lock_mutex(g_new_value_lock);	

	while(attempts < 3 && LDAP_SUCCESS == ret)
	{
		attempts++;

		/* do update */
	        if(e)
		{
	                slapi_entry_free(e);
			e = 0;
		}

		ret = slapi_search_internal_get_entry( dn, attrlist, &e,getPluginID());
		if(LDAP_SUCCESS == ret)
		{
			char *old_value;
						
			old_value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
			if(old_value)
			{
			        LDAPMod mod_add;
				LDAPMod mod_delete;
        			LDAPMod *mods[3];
				Slapi_PBlock *pb = slapi_pblock_new();
				char *delete_val[2];
				char *add_val[2];
                                char new_value[16];
				char *interval = 0;

				mods[0] = &mod_delete;
				mods[1] = &mod_add;
				mods[2] = 0;

				if(0 == pb)
					goto bail;

				interval = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
				if(0 == interval)
				{
					slapi_pblock_destroy(pb);
					slapi_ch_free_string(&old_value);	
					goto bail;
				}

				/* perform increment */

				sprintf(new_value, "%lu",
					strtoul(interval,0,0) +
					strtoul(old_value,0,0));

				delete_val[0] = old_value;
				delete_val[1] = 0;
				
				mod_delete.mod_op = LDAP_MOD_DELETE;
				mod_delete.mod_type = DNA_NEXTVAL;
				mod_delete.mod_values = delete_val;

                                add_val[0] = new_value;
                                add_val[1] = 0;

                                mod_add.mod_op = LDAP_MOD_ADD;
                                mod_add.mod_type = DNA_NEXTVAL;
                                mod_add.mod_values = add_val;


				mods[0] = &mod_delete;
				mods[1] = &mod_add;
				mods[2] = 0; 
		
				slapi_modify_internal_set_pb(
					pb, config_entry->dn,
        				mods, 0, 0,
        				getPluginID(), 0);

				slapi_modify_internal_pb(pb);

				slapi_pblock_get(pb,
					SLAPI_PLUGIN_INTOP_RESULT,
					&ret);

				slapi_pblock_destroy(pb);
				slapi_ch_free_string(&interval);

				if(LDAP_SUCCESS == ret)
				{
					*next_value_ret = old_value;
					break;
        			}
				else
				{
                                	slapi_ch_free_string(&old_value);
					if(LDAP_NO_SUCH_ATTRIBUTE != ret)
					{
						/* not the result of a race
						   to change the value
						*/
						break;
					}
					else
						/* we lost the race to mod
						   try again
						*/
						ret = LDAP_SUCCESS;
				}
			}
			else
				break;
		}
		else
			break;
	}

bail:

        slapi_unlock_mutex(g_new_value_lock);

	if(dn)
		slapi_sdn_free(&dn);

	if(e)
		slapi_entry_free(e);

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_get_next_value\n");

	return ret;
}

/* for mods and adds:
	where dn's are supplied, the closest in scope
	is used as long as the type and filter
	are identical - otherwise all matches count
*/

static int dna_pre_op(Slapi_PBlock *pb,  int modtype)
{
        char *dn = 0;
        PRCList *list = 0;
        configEntry *config_entry = 0;
        struct slapi_entry *e = 0;
        char *last_type = 0;
        char *value = 0;
        int generate = 0;
	Slapi_Mods *smods = 0;
	Slapi_Mod *smod = 0;
	LDAPMod **mods;
 	int free_entry = 0;
	int ret = 0;

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_pre_op\n");

        if(0 == (dn = dna_get_dn(pb)))
                goto bail;

        if(dna_dn_is_config(dn))
                goto bail;

	if(LDAP_CHANGETYPE_ADD == modtype)
	{
		slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e);
	}
	else
	{
		/* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
		 * available but it turns out that is only true if you are
		 * a dbm backend pre-op plugin - lucky dbm backend pre-op
		 * plugins.
		 * I think that is wrong since the entry is useful for filter
		 * tests and schema checks and this plugin shouldn't be limited
		 * to a single backend type, but I don't want that fight right
		 * now so we go get the entry here
		 *
        	slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
		*/
		Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn);
		if(tmp_dn)
		{
			slapi_search_internal_get_entry( 
				tmp_dn, 0, &e,getPluginID());
			slapi_sdn_free(&tmp_dn);
			free_entry = 1;
		}

		/* grab the mods - we'll put them back later with
		 * our modifications appended
		 */	
		slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods);
		smods = slapi_mods_new();
		slapi_mods_init_passin(smods, mods);
	}

	if(0 == e)
		goto bailmod;

        dna_read_lock();

        if(!PR_CLIST_IS_EMPTY(config))
        {
                list = PR_LIST_HEAD(config);

                while(list != config && LDAP_SUCCESS == ret)
                {
                        config_entry = (configEntry*)list;

                        /* did we already service this type? */
                        if(last_type)
                        {
                                if(!slapi_attr_type_cmp(config_entry->type, last_type,1))
                                        goto next;
                        }

                        /* is the entry in scope? */
                        if(config_entry->scope)
                        {
                                if(!slapi_dn_issuffix(dn, config_entry->scope))
                                        goto next;
                        }

                        /* does the entry match the filter? */
                        if(config_entry->filter)
                        {
                                if(LDAP_SUCCESS != slapi_vattr_filter_test(pb,
                                        e,
                                        config_entry->filter,0))
                                        goto next;
                        }


                        if(LDAP_CHANGETYPE_ADD == modtype)
                        {
                                /* does attribute contain the magic value
				   or is the type not there?
				*/
				value = slapi_entry_attr_get_charptr(
					e, config_entry->type);
                                if((value &&
					!slapi_utf8casecmp(
						config_entry->generate, 
						value)) ||
					0 == value)
                                {
                                        generate = 1;
                                }
                        }
                        else
                        {
				/* check mods for magic value */
				Slapi_Mod *next_mod = slapi_mod_new();
				smod = slapi_mods_get_first_smod(
					smods,
					next_mod);
				while(smod)
				{
					char *type = (char *) 
						slapi_mod_get_type(smod);
					
					if(slapi_attr_types_equivalent(
						type,
						config_entry->type))
					{
						struct berval *bv = 
						slapi_mod_get_first_value(
								smod);
						int len = strlen(
							config_entry->
							generate);

							
						if(len == bv->bv_len)
						{
							if(!slapi_utf8ncasecmp(
								bv->bv_val,
								config_entry->
								generate,
								len))

							generate = 1;
							break;
						}
					}

					slapi_mod_done(next_mod);
					smod = slapi_mods_get_next_smod(
						smods,
						next_mod);
				}

				slapi_mod_free(&next_mod);
                        }

                        if(generate)
                        {
                                char *new_value;
                                int len;

                                /* create the value to add */
                                if(ret = dna_get_next_value(config_entry,&value))
                                        break;

                                len = strlen(value) + 1;
                                if(config_entry->prefix)
                                {
                                        len += strlen(config_entry->prefix);
                                }

                                new_value = slapi_ch_malloc(len);

                                if(config_entry->prefix)
                                {
                                        strcpy(new_value,
                                                config_entry->prefix);
                                        strcat(new_value, value);
                                }
                                else
                                        strcpy(new_value, value);

                                /* do the mod */
				if(LDAP_CHANGETYPE_ADD == modtype)
				{
					/* add - add to entry */
					slapi_entry_attr_set_charptr(
						e,
						config_entry->type,
						new_value);
				}
				else
				{
					/* mod - add to mods */
					slapi_mods_add_string(
						smods,
						LDAP_MOD_REPLACE,
						config_entry->type,
						new_value);
				}

				/* free up */
                                slapi_ch_free_string(&value);
                                slapi_ch_free_string(&new_value);

                                /* make sure we don't generate for this 
				 * type again
				 */
                                if(LDAP_SUCCESS == ret)
                                {
                                        last_type = config_entry->type;
                                }

                                generate = 0;
                        }
next:
                        list = PR_NEXT_LINK (list);
                }
        }

        dna_unlock();

bailmod:
        if(LDAP_CHANGETYPE_MODIFY == modtype)
	{
		/* these are the mods you made, really, 
		 * I didn't change them, honest, just had a quick look
		 */
		mods = slapi_mods_get_ldapmods_passout(smods);
		slapi_pblock_set( pb, SLAPI_MODIFY_MODS, mods);
		slapi_mods_free(&smods);
	}

bail:

	if(free_entry && e)
		slapi_entry_free(e);

	if(ret)
		slapi_log_error( SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM , "dna_pre_op: operation failure [%d]\n", ret);

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_pre_op\n");

        return ret;
}


static int dna_add_pre_op( Slapi_PBlock *pb )
{
        return dna_pre_op(pb, LDAP_CHANGETYPE_ADD);
}

static int dna_mod_pre_op( Slapi_PBlock *pb )
{
        return dna_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
}

static int dna_config_check_post_op(Slapi_PBlock *pb)
{
        char *dn;

        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "--> dna_config_check_post_op\n");

        if(dn = dna_get_dn(pb))
	{
		if(dna_dn_is_config(dn))
			loadPluginConfig();
	}

bail:
        slapi_log_error( SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM , "<-- dna_config_check_post_op\n");

	return 0;
}

/****************************************************
	End of
	Functions that actually do things other
	than config and startup
****************************************************/

/**
 * debug functions to print config
 */
void dnaDumpConfig()
{
	PRCList *list;

	dna_read_lock();

	if(!PR_CLIST_IS_EMPTY(config))
	{
		list = PR_LIST_HEAD(config);
		while(list != config)
		{
			dnaDumpConfigEntry((configEntry*)list);
			list = PR_NEXT_LINK (list);
		}
	}				

	dna_unlock();
}


void dnaDumpConfigEntry(configEntry *entry)
{
	printf("<- type --------------> %s\n", entry->type);
	printf("<---- prefix ---------> %s\n", entry->prefix);
	printf("<---- next value -----> %lu\n", entry->nextval);
	printf("<---- interval -------> %lu\n", entry->interval);
	printf("<---- filter ---------> %s\n", entry->filter);
	printf("<---- generate flag --> %s\n", entry->generate);
}




--- NEW FILE dna.ldif ---
# --- 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) 2007 Red Hat, Inc.
# All rights reserved.
# --- END COPYRIGHT BLOCK ---

# plugin configuration entry
dn: cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
objectclass: extensibleObject
objectclass: nsContainer
cn: Distributed Numeric Assignment Plugin
nsslapd-plugininitfunc: dna_init
nsslapd-plugintype: preoperation
nsslapd-pluginenabled: on
nsslapd-plugindescription: Distributed Numeric Assignment plugin
nsslapd-pluginvendor: Fedora Project
nsslapd-pluginVersion: 1.1
nsslapd-pluginId: distributed-numeric-assignment
nsslapd-pluginPath: /home/prowley/srv/lib/fedora-ds/plugins/libdna-plugin.so




--- NEW FILE editentries.sh ---
#!/bin/sh
ldapvi -D "cn=Directory Manager" -w secret123 -h localhost:3389 -b "dc=example, dc=com" "(objectclass=posixaccount)"


--- NEW FILE oneentry.sh ---
#!/bin/sh
ldapadd -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -f posix_one.ldif -c


--- NEW FILE posix.ldif ---
# --- 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) 2007 Red Hat, Inc.
# All rights reserved.
# --- END COPYRIGHT BLOCK ---

# add plugin configuration for posix users

dn: cn=Posix,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: nsContainer
objectclass: extensibleObject
cn: Posix

dn: cn=Accounts,cn=Posix,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: extensibleObject
cn: Accounts
dnaType: uidNumber
dnaNextValue: 500
dnaInterval: 4
dnaMagicRegen: 499
dnaFilter: (objectclass=posixAccount)

# add plugin configuration for posix groups

dn: cn=Groups,cn=Posix,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: extensibleObject
cn: Groups
dnaType: gidNumber
dnaNextValue: 500
dnaInterval: 4
dnaMagicRegen: 499
dnaFilter: (objectclass=posixGroup)



--- NEW FILE posix_one.ldif ---
dn: uid=add_has_magic_number, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 1
sn: test
uid: add_has_uid_number
uidNumber: 499
gidNumber: 550
homeDirectory: /


--- NEW FILE posix_test.ldif ---
dn: uid=add_has_magic_number, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 1
sn: test
uid: add_has_uid_number
uidNumber: 499
gidNumber: 550
homeDirectory: /

dn: uid=add_second_has_magic_number, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 2
sn: test
uid: add_second_has_magic_number
uidNumber: 499
gidNumber: 550
homeDirectory: /

dn: uid=no_uid_number, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 3
sn: test
uid: no_uid_number
gidNumber: 550
homeDirectory: /

dn: uid=add_has_uid_number_550, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 4
sn: test
uid: add_has_uid_number
uidNumber: 550
gidNumber: 550
homeDirectory: /

dn: ou=sub, dc=example, dc=com
objectclass: top
objectclass: organizationalunit
ou: sub

dn: uid=add_is_sub, ou=sub, dc=example, dc=com
objectclass: top
objectclass: organizationalperson
objectclass: posixaccount
cn: 4
sn: test
uidNumber: 499
gidNumber: 550
homeDirectory: /



--- NEW FILE seeconfig.sh ---
#!/bin/sh
ldapsearch -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -b "cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config" "(objectclass=*)"


--- NEW FILE seeentries.sh ---
#!/bin/sh
ldapsearch -x -D "cn=Directory Manager" -w secret123 -h localhost -p 3389 -b "dc=example, dc=com" "(objectclass=posixaccount)"


--- NEW FILE subtest.ldif ---
# --- 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) 2007 Red Hat, Inc.
# All rights reserved.
# --- END COPYRIGHT BLOCK ---

# add Samba SIDs

dn: cn=Example top level,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: extensibleObject
dnaType: title
dnaPrefix: example-
dnaNextValue: 600
dnaInterval: 4
dnaMagicRegen: assign
dnaFilter: (objectclass=organizationalperson)
dnaScope: dc=example, dc=com

dn: cn=Example sub level,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
objectclass: top
objectclass: extensibleObject
dnaType: title
dnaPrefix: sub-example-
dnaNextValue: 600
dnaInterval: 4
dnaMagicRegen: assign
dnaFilter: (objectclass=organizationalperson)
dnaScope: ou=sub, dc=example, dc=com




More information about the Fedora-directory-commits mailing list