--- /dev/null
+/* add.c - ldap bdb2 back-end add routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static DB_LOCK lock;
+
+
+static int
+bdb2i_back_add_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *pdn;
+ Entry *p = NULL;
+ int rc;
+ struct timeval time1;
+
+ Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0);
+
+ if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
+ entry_free( e );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
+ 0, 0, 0 );
+
+ entry_free( e );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ /*
+ * Get the parent dn and see if the corresponding entry exists.
+ * If the parent does not exist, only allow the "root" user to
+ * add the entry.
+ */
+
+ pdn = dn_parent( be, e->e_ndn );
+
+ if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
+ char *matched = NULL;
+
+ assert( *pdn != '\0' );
+
+ /* get parent with writer lock */
+ if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+
+ if ( matched != NULL ) {
+ free( matched );
+ }
+
+ entry_free( e );
+ free( pdn );
+ return -1;
+ }
+
+ free(pdn);
+
+ if ( matched != NULL ) {
+ free( matched );
+ }
+
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ entry_free( e );
+ return -1;
+ }
+
+ } else {
+ if(pdn != NULL) {
+ assert( *pdn == '\0' );
+ free(pdn);
+ }
+
+ /* no parent, must be adding entry to root */
+ if ( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
+ pdn == NULL ? "suffix" : "entry at root",
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+ }
+
+ e->e_id = bdb2i_next_id( be );
+
+ /*
+ * Try to add the entry to the cache, assign it a new dnid.
+ */
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ rc = bdb2i_cache_add_entry_rw( &li->li_cache, e, CACHE_WRITE_LOCK );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-CACHE", conn, op );
+
+ if ( rc != 0 ) {
+ if( p != NULL) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
+ 0 );
+
+ /* return the id */
+ bdb2i_next_id_return( be, e->e_id );
+
+ /* free the entry */
+ entry_free( e );
+
+ if(rc > 0) {
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ } else {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ }
+
+ return( -1 );
+ }
+
+ rc = -1;
+
+ /*
+ * add it to the id2children index for the parent
+ */
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
+
+ /*
+ * Add the entry to the attribute indexes, then add it to
+ * the id2children index, dn2id index, and the id2entry index.
+ */
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* attribute indexes */
+ if ( bdb2i_index_add_entry( be, e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* dn2id index */
+ if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ /* id2entry index */
+ if ( bdb2i_id2entry_add( be, e ) != 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
+ 0, 0 );
+ (void) bdb2i_dn2id_delete( be, e->e_ndn );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
+
+ goto return_results;
+ }
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
+
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if (p != NULL) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+ }
+
+ if ( rc ) {
+ /* free entry and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+ }
+
+ return( rc );
+}
+
+
+int
+bdb2_back_add(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+ return( -1 );
+
+ }
+
+ /* check, if a new default attribute index will be created,
+ in which case we have to open the index file BEFORE TP */
+ switch ( slapMode ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TIMEDSERVER_MODE:
+ case SLAP_TOOL_MODE:
+ case SLAP_TOOLID_MODE:
+ bdb2i_check_default_attr_index_add( li, e );
+ break;
+ }
+
+ ret = bdb2i_back_add_internal( be, conn, op, e );
+
+ /* if the operation was successful, we will delay the unlock */
+ if ( ret )
+ (void) bdb2i_leave_backend_w( lock );
+
+ bdb2i_stop_timing( be->bd_info, time1, "ADD", conn, op );
+
+ return( ret );
+}
+
+
+int
+bdb2i_release_add_lock( void )
+{
+ (void) bdb2i_leave_backend_w( lock );
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to ITSD, Government of BC. The name of ITSD
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+/*
+ * given an alias object, dereference it to its end point.
+ * Entry returned has reader lock or is NULL. Starting entry is not released.
+ */
+Entry *bdb2i_derefAlias_r ( BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e)
+{
+ /* to free cache entries */
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Attribute *a;
+ int depth;
+ char *matched;
+ Entry *origDN = e;
+
+ if (!e) return NULL; /* be sure we have a starting entry */
+
+ Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
+
+ /*
+ * try to deref fully, up to a maximum depth. If the max depth exceeded
+ * then send an error
+ */
+ for ( depth = 0;
+ ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
+ ( depth < be->be_maxDerefDepth );
+ ++depth)
+ {
+
+ /*
+ * make sure there is a defined aliasedobjectname.
+ * can only have one value so just use first value (0) in the attr list.
+ */
+ if (a->a_vals[0] && a->a_vals[0]->bv_val) {
+ char *newDN, *oldDN;
+
+ Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
+ e->e_dn, a->a_vals[0]->bv_val, 0 );
+ newDN = ch_strdup (a->a_vals[0]->bv_val);
+ oldDN = ch_strdup (e->e_ndn);
+
+ /*
+ * release past lock if not original
+ */
+ if ( (depth > 0) && e ) {
+ bdb2i_cache_return_entry_r(&li->li_cache, e);
+ }
+
+ /* make sure new and old DN are not same to avoid loops */
+ dn_normalize_case (newDN);
+ if ( strcmp (newDN, oldDN) == 0 ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s alias is same as current %s\n",
+ oldDN, newDN, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "circular alias", NULL );
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ /* make sure new and original are not same to avoid deadlocks */
+ if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s alias is same as original %s\n",
+ oldDN, origDN->e_ndn, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "circular alias", NULL );
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ /*
+ * ok, so what happens if there is an alias in the DN of a dereferenced
+ * alias object?
+ */
+ if ( (e = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL ) {
+ /* could not deref return error */
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s is a dangling alias to %s\n",
+ oldDN, newDN, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "dangling alias", NULL );
+
+ if(matched != NULL) free(matched);
+ free (newDN);
+ free (oldDN);
+ break;
+ }
+
+ free (newDN);
+ free (oldDN);
+ }
+ else {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ * this can't happen, right?
+ */
+ Debug( LDAP_DEBUG_TRACE,
+ "<= %s has no data in aliasedobjectname attribute\n",
+ (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, "alias missing aliasedObjectname", NULL );
+ break;
+ }
+ }
+
+ /*
+ * warn if we pulled out due to exceeding the maximum deref depth
+ */
+ if ( depth >= be->be_maxDerefDepth ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
+ origDN->e_dn ? origDN->e_dn : "(null)",
+ be->be_maxDerefDepth,
+ (e && e->e_ndn) ? e->e_ndn : "(null)");
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "maximum alias dereference depth exceeded", NULL );
+ }
+
+ return e;
+}
+
+/*
+ * given a DN fully deref it and return the real DN or original DN if it fails
+ * This involves finding the last matched part then reconstructing forward
+ * e.g.
+ * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
+ * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
+ * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
+ * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
+ * remainder is ou=MyOU
+ * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
+ * release lock on o=MyAliasedOrg,c=MyCountry entry
+ * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
+ * release lock on o=MyOrg,c=MyCountry entry
+ */
+char *bdb2i_derefDN ( BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched = 0;
+ char *newDN = NULL;
+ int depth, i;
+ Entry *eMatched;
+ Entry *eDeref;
+ Entry *eNew;
+
+ if (!dn) return NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "<= dereferencing dn: \"%s\"\n",
+ dn, 0, 0 );
+
+ newDN = ch_strdup ( dn );
+
+ /* while we don't have a matched dn, deref the DN */
+ for ( depth = 0;
+ ( (eMatched = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL) &&
+ (depth < be->be_maxDerefDepth);
+ ++depth ) {
+
+ if ((matched != NULL) && *matched) {
+ char *submatch;
+
+ /*
+ * make sure there actually is an entry for the matched part
+ */
+ if ( (eMatched = bdb2i_dn2entry_r( be, matched, &submatch )) != NULL) {
+ char *remainder; /* part before the aliased part */
+ int rlen = strlen(newDN) - strlen(matched);
+
+ Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
+
+ remainder = ch_malloc (rlen + 1);
+ strncpy ( remainder, newDN, rlen );
+ remainder[rlen] = '\0';
+
+ Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
+
+ if ((eNew = bdb2i_derefAlias_r( be, conn, op, eMatched )) == NULL) {
+ free (matched);
+ matched = NULL;
+ free (newDN);
+ newDN = NULL;
+ free (remainder);
+ remainder = NULL;
+
+ bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
+ eMatched = NULL;
+ break; /* no associated entry, dont deref */
+ }
+ else {
+
+ Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
+
+ i = strcasecmp (matched, eNew->e_dn);
+ /* free reader lock */
+ bdb2i_cache_return_entry_r(&li->li_cache, eNew);
+
+ free (matched);
+ matched = NULL;
+
+ if (! i) {
+ /* newDN same as old so not an alias, no need to go further */
+ free (newDN);
+ newDN = NULL;
+ free (remainder);
+
+ bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
+ eMatched = NULL;
+ break;
+ }
+
+ /*
+ * we have dereferenced the aliased part so put
+ * the new dn together
+ */
+ free (newDN);
+ newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
+ strcpy (newDN, remainder);
+ strcat (newDN, eMatched->e_dn);
+ Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
+
+ free (remainder);
+ }
+ /* free reader lock */
+ bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
+ }
+ else {
+ if(submatch != NULL) free(submatch);
+ break; /* there was no entry for the matched part */
+ }
+ }
+ else {
+ break; /* there was no matched part */
+ }
+ }
+
+ /* release lock if a match terminated the loop, there should be no
+ * outstanding locks at this point
+ */
+ if(eMatched != NULL) {
+ /* free reader lock */
+ bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
+ }
+
+ /*
+ * the final part of the DN might be an alias so try to dereference it.
+ * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
+ * and the above loop complete but we would still be left with an aliased DN.
+ */
+ if (newDN != NULL) {
+ if ( (eNew = bdb2i_dn2entry_r( be, newDN, &matched )) != NULL) {
+ if ((eDeref = bdb2i_derefAlias_r( be, conn, op, eNew )) != NULL) {
+ free (newDN);
+ newDN = ch_strdup (eDeref->e_dn);
+ /* free reader lock */
+ bdb2i_cache_return_entry_r(&li->li_cache, eDeref);
+ }
+ /* free reader lock */
+ bdb2i_cache_return_entry_r(&li->li_cache, eNew);
+ }
+ }
+ if (matched != NULL) free(matched);
+
+ /*
+ * warn if we exceeded the max depth as the resulting DN may not be dereferenced
+ */
+ if (depth >= be->be_maxDerefDepth) {
+ if (newDN) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
+ dn, newDN, 0 );
+ free (newDN);
+ newDN = NULL;
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
+ dn, 0, 0 );
+ }
+ send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM,
+ NULL, "maximum alias dereference depth exceeded for base", NULL );
+ }
+
+ if (newDN == NULL) {
+ newDN = ch_strdup ( dn );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
+
+ return newDN;
+}
--- /dev/null
+/* bind.c - bdb2 backend bind and unbind routines */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+#include <lutil.h>
+
+#ifdef HAVE_KERBEROS
+extern int bdb2i_krbv4_ldap_auth();
+#endif
+
+static int
+crypted_value_find(
+ struct berval **vals,
+ struct berval *v,
+ int syntax,
+ int normalize,
+ struct berval *cred
+)
+{
+ int i;
+ for ( i = 0; vals[i] != NULL; i++ ) {
+ if ( syntax != SYNTAX_BIN ) {
+ int result;
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
+#endif
+
+ result = lutil_passwd(
+ (char*) cred->bv_val,
+ (char*) vals[i]->bv_val,
+ NULL );
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+#endif
+
+ return result;
+
+ } else {
+ if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
+ return( 0 );
+ }
+ }
+ }
+
+ return( 1 );
+}
+
+static int
+bdb2i_back_bind_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ int method,
+ char *mech,
+ struct berval *cred,
+ char** edn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e;
+ Attribute *a;
+ int rc;
+ char *matched;
+#ifdef HAVE_KERBEROS
+ char krbname[MAX_K_NAME_SZ + 1];
+ AUTH_DAT ad;
+#endif
+
+ Debug(LDAP_DEBUG_ARGS, "==> bdb2_back_bind: dn: %s\n", dn, 0, 0);
+
+ *edn = NULL;
+
+ /* get entry with reader lock */
+ if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
+ /* allow noauth binds */
+ rc = 1;
+ if ( method == LDAP_AUTH_SIMPLE ) {
+ if( cred->bv_len == 0 ) {
+ /* SUCCESS */
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+
+ } else if ( be_isroot_pw( be, dn, cred ) ) {
+ /* front end will send result */
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0;
+
+ } else {
+ send_ldap_result( conn, op,
+ LDAP_NO_SUCH_OBJECT, matched, NULL, NULL );
+ }
+
+ } else if ( method == LDAP_AUTH_SASL ) {
+ if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
+ /* insert DIGEST calls here */
+ send_ldap_result( conn, op,
+ LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op,
+ LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL, NULL );
+ }
+
+ } else {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ rc = 1;
+ }
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ return( rc );
+ }
+
+ *edn = ch_strdup( e->e_dn );
+
+ /* check for deleted */
+
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ switch ( method ) {
+ case LDAP_AUTH_SIMPLE:
+ if ( cred->bv_len == 0 ) {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+ }
+
+ /* check for root dn/passwd */
+ if ( be_isroot_pw( be, dn, cred ) ) {
+ /* front end will send result */
+ if( *edn != NULL ) free( *edn );
+ *edn = ch_strdup( be_root_dn( be ) );
+ rc = 0;
+ goto return_results;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "userpassword", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL);
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
+ NULL, NULL, NULL);
+
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
+ {
+ send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL);
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+ }
+ rc = 0;
+ break;
+
+#ifdef HAVE_KERBEROS
+ case LDAP_AUTH_KRBV41:
+ if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL);
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ "krbname", NULL, ACL_AUTH ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL);
+ rc = 1;
+ goto return_results;
+ }
+
+ sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
+ : "", ad.pinst, ad.prealm );
+
+ if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
+ /*
+ * no krbName values present: check against DN
+ */
+ if ( strcasecmp( dn, krbname ) == 0 ) {
+ rc = 0; /* XXX wild ass guess */
+ break;
+ }
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
+ NULL, NULL, NULL);
+ rc = 1;
+ goto return_results;
+ } else { /* look for krbName match */
+ struct berval krbval;
+
+ krbval.bv_val = krbname;
+ krbval.bv_len = strlen( krbname );
+
+ if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL);
+ rc = 1;
+ goto return_results;
+ }
+ }
+ rc = 0;
+ break;
+
+ case LDAP_AUTH_KRBV42:
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ /* stop front end from sending result */
+ rc = 1;
+ goto return_results;
+#endif
+
+ case LDAP_AUTH_SASL:
+ /* insert sasl code here */
+
+ default:
+ send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
+ NULL, "auth method not supported", NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+return_results:;
+ /* free entry and reader lock */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ /* front end with send result on success (rc==0) */
+ return( rc );
+}
+
+
+int
+bdb2_back_bind(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ int method,
+ char *mech,
+ struct berval *cred,
+ char** edn
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return( 1 );
+ }
+
+ ret = bdb2i_back_bind_internal( be, conn, op, dn, method, mech, cred, edn );
+
+ (void) bdb2i_leave_backend_r( lock );
+
+ bdb2i_stop_timing( be->bd_info, time1, "BIND", conn, op );
+
+ return( ret );
+}
+
+
--- /dev/null
+/* compare.c - bdb2 backend compare routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static int
+bdb2i_back_compare_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ Ava *ava
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched;
+ Entry *e;
+ Attribute *a;
+ int rc;
+
+ /* get entry with reader lock */
+ if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+
+ if(matched == NULL) free(matched);
+ return( 1 );
+ }
+
+ /* check for deleted */
+ if ( ! access_allowed( be, conn, op, e,
+ ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
+ {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+ NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+ NULL, NULL, NULL );
+ else
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+ NULL, NULL, NULL );
+
+ rc = 0;
+
+return_results:;
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ return( rc );
+}
+
+
+int
+bdb2_back_compare(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ Ava *ava
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return( 1 );
+
+ }
+
+ ret = bdb2i_back_compare_internal( be, conn, op, dn, ava );
+ (void) bdb2i_leave_backend_r( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "CMP", conn, op );
+
+ return( ret );
+}
+
+
--- /dev/null
+/* delete.c - bdb2 backend delete routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static int
+bdb2i_back_delete_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched = NULL;
+ char *pdn = NULL;
+ Entry *e, *p = NULL;
+ int rc = -1;
+
+ Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
+
+ /* get entry with writer lock */
+ if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ return( -1 );
+ }
+
+ /* check for deleted */
+
+ if ( bdb2i_has_children( be, e ) ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: insufficient access %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+#endif
+
+ /* delete from parent's id2children entry */
+ if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
+ if( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ } else {
+ /* no parent, must be root to delete */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+ }
+
+ if ( bdb2i_id2children_remove( be, p, e ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* delete from dn2id mapping */
+ if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* delete from disk and cache */
+ if ( bdb2i_id2entry_delete( be, e ) != 0 ) {
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb2i_back_delete: operations error %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ rc = 0;
+
+return_results:;
+ if ( pdn != NULL ) free(pdn);
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ }
+
+ /* free entry and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+ if ( matched != NULL ) free(matched);
+
+ return rc;
+}
+
+
+int
+bdb2_back_delete(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return( -1 );
+
+ }
+
+ ret = bdb2i_back_delete_internal( be, conn, op, dn );
+ (void) bdb2i_leave_backend_w( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "DEL", conn, op );
+
+ return( ret );
+}
+
+
--- /dev/null
+/* modify.c - bdb2 backend modify routine */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+
+static void add_lastmods(Operation *op, LDAPModList **ml);
+
+
+static void
+add_lastmods( Operation *op, LDAPModList **modlist )
+{
+ char buf[22];
+ struct berval bv;
+ struct berval *bvals[2];
+ LDAPModList **m;
+ LDAPModList *tmp;
+ struct tm *ltm;
+ time_t currenttime;
+
+ Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
+
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ /* remove any attempts by the user to modify these attrs */
+ for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) {
+ if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "add_lastmods: found no user mod attr: %s\n",
+ (*m)->ml_type, 0, 0 );
+ tmp = *m;
+ *m = (*m)->ml_next;
+ free( tmp->ml_type );
+ if ( tmp->ml_bvalues != NULL ) {
+ ber_bvecfree( tmp->ml_bvalues );
+ }
+ free( tmp );
+ if (!*m)
+ break;
+ }
+ }
+
+ if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
+ bv.bv_val = "NULLDN";
+ bv.bv_len = strlen( bv.bv_val );
+ } else {
+ bv.bv_val = op->o_dn;
+ bv.bv_len = strlen( bv.bv_val );
+ }
+ tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ tmp->ml_type = ch_strdup( "modifiersname" );
+ tmp->ml_op = LDAP_MOD_REPLACE;
+ tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ tmp->ml_bvalues[0] = ber_bvdup( &bv );
+ tmp->ml_next = *modlist;
+ *modlist = tmp;
+
+ currenttime = slap_get_time();
+ ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+#ifndef LDAP_LOCALTIME
+ ltm = gmtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+ ltm = localtime( ¤ttime );
+ strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
+#endif
+ ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
+ bv.bv_val = buf;
+ bv.bv_len = strlen( bv.bv_val );
+ tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
+ tmp->ml_type = ch_strdup( "modifytimestamp" );
+ tmp->ml_op = LDAP_MOD_REPLACE;
+ tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
+ tmp->ml_bvalues[0] = ber_bvdup( &bv );
+ tmp->ml_next = *modlist;
+ *modlist = tmp;
+
+}
+
+int
+bdb2i_back_modify_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist,
+ Entry *e
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ LDAPModList *ml;
+ int err;
+
+ Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
+
+ if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
+ LDAPMod *mod = &ml->ml_mod;
+
+ switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_ADD:
+ err = bdb2i_add_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_DELETE:
+ err = bdb2i_delete_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_REPLACE:
+ err = bdb2i_replace_values( e, mod, op->o_ndn );
+ break;
+
+ case LDAP_MOD_SOFTADD:
+ /* Avoid problems in index_add_mods()
+ * We need to add index if necessary.
+ */
+ mod->mod_op = LDAP_MOD_ADD;
+ if ( (err = bdb2i_add_values( e, mod, op->o_ndn ))
+ == LDAP_TYPE_OR_VALUE_EXISTS ) {
+
+ err = LDAP_SUCCESS;
+ mod->mod_op = LDAP_MOD_SOFTADD;
+
+ }
+ break;
+ }
+
+ if ( err != LDAP_SUCCESS ) {
+ /* unlock entry, delete from cache */
+ send_ldap_result( conn, op, err, NULL, NULL, NULL );
+ goto error_return;
+ }
+ }
+
+ /* check that the entry still obeys the schema */
+ if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto error_return;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* modify indexes */
+ if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto error_return;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* change the entry itself */
+ if ( bdb2i_id2entry_add( be, e ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto error_return;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+ return( 0 );
+
+error_return:;
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+ return( -1 );
+}
+
+
+int
+bdb2_back_modify(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+ char *matched;
+ Entry *e;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return( -1 );
+ }
+
+ /* check, if a new default attribute index will be created,
+ in which case we have to open the index file BEFORE TP */
+ switch ( slapMode ) {
+ case SLAP_SERVER_MODE:
+ case SLAP_TIMEDSERVER_MODE:
+ case SLAP_TOOL_MODE:
+ case SLAP_TOOLID_MODE:
+ bdb2i_check_default_attr_index_mod( li, modlist );
+ break;
+ }
+
+ if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ return( -1 );
+ }
+
+ ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+ (void) bdb2i_leave_backend_w( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );
+
+ return( ret );
+}
+
+
+int
+bdb2i_add_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ int i;
+ Attribute *a;
+
+ /* check if the values we're adding already exist */
+ if ( (a = attr_find( e->e_attrs, mod->mod_type )) != NULL ) {
+ for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
+ if ( value_find( a->a_vals, mod->mod_bvalues[i],
+ a->a_syntax, 3 ) == 0 ) {
+ return( LDAP_TYPE_OR_VALUE_EXISTS );
+ }
+ }
+ }
+
+ /* no - add them */
+ if( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
+ return( LDAP_CONSTRAINT_VIOLATION );
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+int
+bdb2i_delete_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ int i, j, k, found;
+ Attribute *a;
+
+ /* delete the entire attribute */
+ if ( mod->mod_bvalues == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n",
+ mod->mod_type, 0, 0 );
+ return( attr_delete( &e->e_attrs, mod->mod_type ) ?
+ LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS );
+ }
+
+ /* delete specific values - find the attribute first */
+ if ( (a = attr_find( e->e_attrs, mod->mod_type )) == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "could not find attribute %s\n",
+ mod->mod_type, 0, 0 );
+ return( LDAP_NO_SUCH_ATTRIBUTE );
+ }
+
+ /* find each value to delete */
+ for ( i = 0; mod->mod_bvalues[i] != NULL; i++ ) {
+ found = 0;
+ for ( j = 0; a->a_vals[j] != NULL; j++ ) {
+ if ( value_cmp( mod->mod_bvalues[i], a->a_vals[j],
+ a->a_syntax, 3 ) != 0 ) {
+ continue;
+ }
+ found = 1;
+
+ /* found a matching value - delete it */
+ ber_bvfree( a->a_vals[j] );
+ for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
+ a->a_vals[k - 1] = a->a_vals[k];
+ }
+ a->a_vals[k - 1] = NULL;
+ break;
+ }
+
+ /* looked through them all w/o finding it */
+ if ( ! found ) {
+ Debug( LDAP_DEBUG_ARGS,
+ "could not find value for attr %s\n",
+ mod->mod_type, 0, 0 );
+ return( LDAP_NO_SUCH_ATTRIBUTE );
+ }
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+int
+bdb2i_replace_values(
+ Entry *e,
+ LDAPMod *mod,
+ char *dn
+)
+{
+ (void) attr_delete( &e->e_attrs, mod->mod_type );
+
+ if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
+ return( LDAP_CONSTRAINT_VIOLATION );
+ }
+
+ return( LDAP_SUCCESS );
+}
--- /dev/null
+/* modrdn.c - bdb2 backend modrdn routine */
+
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-bdb2.h"
+#include "proto-back-bdb2.h"
+
+static int
+bdb2i_back_modrdn_internal(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ char *newrdn,
+ int deleteoldrdn,
+ char *newSuperior
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ char *matched = NULL;
+ char *p_dn = NULL, *p_ndn = NULL;
+ char *new_dn = NULL, *new_ndn = NULL;
+ char sep[2];
+ Entry *e, *p = NULL;
+ int rc = -1;
+ /* Added to support LDAP v2 correctly (deleteoldrdn thing) */
+ char *new_rdn_val = NULL; /* Val of new rdn */
+ char *new_rdn_type = NULL; /* Type of new rdn */
+ char *old_rdn; /* Old rdn's attr type & val */
+ char *old_rdn_type = NULL; /* Type of old rdn attr. */
+ char *old_rdn_val = NULL; /* Old rdn attribute value */
+ struct berval add_bv; /* Stores new rdn att */
+ struct berval *add_bvals[2]; /* Stores new rdn att */
+ struct berval del_bv; /* Stores old rdn att */
+ struct berval *del_bvals[2]; /* Stores old rdn att */
+ LDAPModList mod[2]; /* Used to delete old rdn */
+ /* Added to support newSuperior */
+ Entry *np = NULL; /* newSuperior Entry */
+ char *np_dn = NULL; /* newSuperior dn */
+ char *np_ndn = NULL; /* newSuperior ndn */
+ char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
+
+ Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
+ (newSuperior ? newSuperior : "NULL"),
+ 0, 0 );
+
+ /* get entry with writer lock */
+ if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
+ matched, NULL, NULL );
+ if ( matched != NULL ) {
+ free( matched );
+ }
+ return( -1 );
+ }
+
+#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+#endif
+
+ if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
+ /* parent + rdn + separator(s) + null */
+ if( (p = bdb2i_dn2entry_w( be, p_ndn, &matched )) == NULL) {
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check parent for "children" acl */
+ if ( ! access_allowed( be, conn, op, p,
+ "children", NULL, ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ p_dn = dn_parent( be, e->e_dn );
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
+ p_dn, 0, 0 );
+
+
+ } else {
+ /* no parent, modrdn entry directly under root */
+ if( ! be_isroot( be, op->o_ndn ) ) {
+ Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
+ 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no parent!, working on root\n",
+ 0, 0, 0 );
+
+ }
+
+ new_parent_dn = p_dn; /* New Parent unless newSuperior given */
+
+ if ( (np_dn = newSuperior) != NULL) {
+
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new parent requested...\n",
+ 0, 0, 0 );
+
+ np_ndn = dn_normalize_case( ch_strdup( np_dn ) );
+
+ /* newSuperior == oldParent?, if so ==> ERROR */
+
+ /* newSuperior == entry being moved?, if so ==> ERROR */
+
+ /* Get Entry with dn=newSuperior. Does newSuperior exist? */
+
+ if( (np = bdb2i_dn2entry_w( be, np_ndn, &matched )) == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
+ np_ndn, 0, 0);
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent OK np=%p, id=%d\n",
+ np, np->e_id, 0 );
+
+ /* check newSuperior for "children" acl */
+ if ( !access_allowed( be, conn, op, np, "children", NULL,
+ ACL_WRITE ) )
+ {
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: no wr to newSup children\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: wr to new parent's children OK\n",
+ 0, 0 , 0 );
+
+
+ new_parent_dn = np_dn;
+
+ }
+
+ /* Build target dn and make sure target entry doesn't exist already. */
+
+ build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
+
+
+ new_ndn = dn_normalize_case( ch_strdup( new_dn ) );
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
+ new_ndn, 0, 0 );
+
+ if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) {
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ goto return_results;
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* delete old one */
+ if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ (void) bdb2i_cache_delete_entry( &li->li_cache, e );
+ free( e->e_dn );
+ free( e->e_ndn );
+ e->e_dn = new_dn;
+ e->e_ndn = new_ndn;
+
+
+ /* add new one */
+ if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
+ */
+
+ if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out type of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out val of newrdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: new_rdn_val=%s, new_rdn_type=%s\n",
+ new_rdn_val, new_rdn_type, 0 );
+
+ /* Retrieve the old rdn from the entry's dn */
+
+ if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn from dn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out the old_rdn type\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+ }
+
+ if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
+
+ /* Not a big deal but we may say something */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
+ old_rdn_type, new_rdn_type, 0 );
+
+ }
+
+ if ( dn_type( old_rdn ) == DN_X500 ) {
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
+ 0, 0, 0 );
+
+ /* Add new attribute value to the entry.
+ */
+
+ add_bvals[0] = &add_bv; /* Array of bervals */
+ add_bvals[1] = NULL;
+
+ add_bv.bv_val = new_rdn_val;
+ add_bv.bv_len = strlen(new_rdn_val);
+
+ mod[0].ml_type = new_rdn_type;
+ mod[0].ml_bvalues = add_bvals;
+ mod[0].ml_op = LDAP_MOD_SOFTADD;
+ mod[0].ml_next = NULL;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: adding new rdn attr val =%s\n",
+ new_rdn_val, 0, 0 );
+
+ /* Remove old rdn value if required */
+
+ if (deleteoldrdn) {
+
+ del_bvals[0] = &del_bv; /* Array of bervals */
+ del_bvals[1] = NULL;
+ /* Get value of old rdn */
+
+ if ((old_rdn_val = rdn_attr_value( old_rdn ))
+ == NULL) {
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results;
+
+
+ }
+
+ /* Remove old value of rdn as an attribute. */
+
+ del_bv.bv_val = old_rdn_val;
+ del_bv.bv_len = strlen(old_rdn_val);
+
+ mod[0].ml_next = &mod[1];
+ mod[1].ml_type = old_rdn_type;
+ mod[1].ml_bvalues = del_bvals;
+ mod[1].ml_op = LDAP_MOD_DELETE;
+ mod[1].ml_next = NULL;
+
+
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: removing old_rdn_val=%s\n",
+ old_rdn_val, 0, 0 );
+
+ }/* if (deleteoldrdn) */
+
+ } else {
+
+
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
+ 0, 0, 0 );
+ /* XXXV3: not sure of what to do here */
+ Debug( LDAP_DEBUG_TRACE,
+ "ldbm_back_modrdn: not fully implemented...\n",
+ 0, 0, 0 );
+
+ }
+
+ /* modify memory copy of entry */
+ if ( bdb2i_back_modify_internal( be, conn, op, dn, &mod[0], e )
+ != 0 ) {
+
+ goto return_results;
+
+ }
+
+ (void) bdb2i_cache_update_entry( &li->li_cache, e );
+
+ /* NOTE: after this you must not free new_dn or new_ndn!
+ * They are used by cache.
+ */
+
+ /* id2entry index */
+ if ( bdb2i_id2entry_add( be, e ) != 0 ) {
+ entry_free( e );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ goto return_results_after;
+ }
+
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ rc = 0;
+ goto return_results_after;
+
+return_results:
+ if( new_dn != NULL ) free( new_dn );
+ if( new_ndn != NULL ) free( new_ndn );
+return_results_after:
+ /* NOTE:
+ * new_dn and new_ndn are not deallocated because they are used by
+ * the cache entry.
+ */
+ if( p_dn != NULL ) free( p_dn );
+ if( p_ndn != NULL ) free( p_ndn );
+
+ if( matched != NULL ) free( matched );
+
+ /* LDAP v2 supporting correct attribute handling. */
+ if( new_rdn_type != NULL ) free(new_rdn_type);
+ if( new_rdn_val != NULL ) free(new_rdn_val);
+ if( old_rdn != NULL ) free(old_rdn);
+ if( old_rdn_type != NULL ) free(old_rdn_type);
+ if( old_rdn_val != NULL ) free(old_rdn_val);
+
+ /* LDAP v3 Support */
+ if ( np_dn != NULL ) free( np_dn );
+ if ( np_ndn != NULL ) free( np_ndn );
+
+ if( p != NULL ) {
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ }
+
+ /* free entry and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+ return( rc );
+}
+
+
+int
+bdb2_back_modrdn(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ char *newrdn,
+ int deleteoldrdn,
+ char *newSuperior
+)
+{
+ DB_LOCK lock;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ struct timeval time1;
+ int ret;
+
+ bdb2i_start_timing( be->bd_info, &time1 );
+
+ if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
+ return( -1 );
+
+ }
+
+ ret = bdb2i_back_modrdn_internal( be, conn, op, dn,
+ newrdn, deleteoldrdn,
+ newSuperior );
+
+ (void) bdb2i_leave_backend_w( lock );
+ bdb2i_stop_timing( be->bd_info, time1, "MODRDN", conn, op );
+
+ return( ret );
+}
+
+
ID id;
Entry *e;
Attribute *ref;
+ struct berval **refs;
char *matched = NULL;
- int rmaxsize, nrefs;
- char *rbuf, *rcur;
int nentries = 0;
char *realBase;
break;
default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
- "Bad scope" );
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "Bad scope", NULL );
if( realBase != NULL) {
free( realBase );
}
/* null candidates means we could not find the base object */
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, "" );
+ send_ldap_result( conn, op, err, matched, NULL, NULL );
if ( matched != NULL ) {
free( matched );
}
free( matched );
}
- rmaxsize = 0;
- nrefs = 0;
- rbuf = rcur = NULL;
- MAKE_SPACE( sizeof("Referral:") + 1 );
- strcpy( rbuf, "Referral:" );
- rcur = strchr( rbuf, '\0' );
+ refs = NULL;
+
for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
id = bdb2i_idl_nextid( candidates, id ) ) {
/* check for abandon */
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
bdb2i_idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
}
/* check time limit */
if ( tlimit != -1 && slap_get_time() > stoptime ) {
- send_search_result( conn, op,
- LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
- NULL, nentries );
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, refs, nentries );
bdb2i_idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
}
strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
(ref = attr_find( e->e_attrs, "ref" )) != NULL )
{
- int i;
-
- if ( ref->a_vals == NULL ) {
- Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
- e->e_dn, 0, 0 );
- } else {
- if( op->o_protocol < LDAP_VERSION3 ) {
- for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
- /* referral + newline + null */
- MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
- *rcur++ = '\n';
- strncpy( rcur, ref->a_vals[i]->bv_val,
- ref->a_vals[i]->bv_len );
- rcur = rcur + ref->a_vals[i]->bv_len;
- *rcur = '\0';
- nrefs++;
- }
- } else {
- send_search_reference( conn, op, ref->a_vals );
- }
- }
+ send_search_reference( be, conn, op,
+ e, ref->a_vals, &refs );
/* otherwise it's an entry - see if it matches the filter */
} else {
/* check size limit */
if ( --slimit == -1 ) {
bdb2i_cache_return_entry_r( &li->li_cache, e );
- send_search_result( conn, op,
- LDAP_SIZELIMIT_EXCEEDED, NULL,
- nrefs > 0 ? rbuf : NULL, nentries );
+ send_search_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
+ NULL, NULL, refs, nentries );
bdb2i_idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
case -1: /* connection closed */
bdb2i_cache_return_entry_r( &li->li_cache, e );
bdb2i_idl_free( candidates );
- free( rbuf );
+ ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
ldap_pvt_thread_yield();
}
bdb2i_idl_free( candidates );
- if ( nrefs > 0 ) {
- send_search_result( conn, op, LDAP_REFERRALS, NULL,
- rbuf, nentries );
- } else {
- send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
- nentries );
- }
- free( rbuf );
+
+ send_search_result( conn, op,
+ refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, refs, nentries );
+
+ ber_bvecfree( refs );
if( realBase != NULL) {
free( realBase );
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL );
return( -1 );
}
--- /dev/null
+/* bind.c - ldap backend bind function */
+
+/*
+ * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits should appear in the documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-ldap.h"
+
+int
+ldap_back_bind(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ int method,
+ char *mech,
+ struct berval *cred,
+ char **edn
+)
+{
+ struct ldapinfo *li = (struct ldapinfo *) be->be_private;
+ struct ldapconn *lc;
+
+ *edn = NULL;
+
+ lc = ldap_back_getconn(li, conn, op);
+ if (!lc)
+ return( -1 );
+
+ if (ldap_bind_s(lc->ld, dn, cred->bv_val, method) != LDAP_SUCCESS)
+ return( ldap_back_op_result(lc, op) );
+
+ lc->bound = 1;
+ return( 0 );
+}
+
+struct ldapconn *
+ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op)
+{
+ struct ldapconn *lc;
+ LDAP *ld;
+
+ ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+ for (lc = li->lcs; lc; lc=lc->next)
+ if (lc->conn == conn)
+ break;
+ ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+
+ /* Looks like we didn't get a bind. Open a new session... */
+ if (!lc) {
+ ld = ldap_init(li->host, li->port);
+ if (!ld) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "ldap_init failed", NULL );
+ return( NULL );
+ }
+ lc = (struct ldapconn *)ch_malloc(sizeof(struct ldapconn));
+ lc->conn = conn;
+ lc->ld = ld;
+ lc->bound = 0;
+ ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+ lc->next = li->lcs;
+ li->lcs = lc;
+ ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+ }
+ return( lc );
+}
+
+ldap_back_dobind(struct ldapconn *lc, Operation *op)
+{
+ if (lc->bound)
+ return;
+
+ if (ldap_bind_s(lc->ld, lc->conn->c_cdn, NULL, LDAP_AUTH_SIMPLE) !=
+ LDAP_SUCCESS)
+ ldap_back_op_result(lc, op);
+ else
+ lc->bound = 1;
+}
+
+ldap_back_op_result(struct ldapconn *lc, Operation *op)
+{
+ int err;
+ char *msg;
+ char *match;
+
+ ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &err);
+ ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &msg);
+ ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
+ send_ldap_result( lc->conn, op, err, match, msg, NULL );
+ free(match);
+ free(msg);
+ return( (err==LDAP_SUCCESS) ? 0 : -1 );
+}
if (rc == -1)
goto fail;
- send_search_result( conn, op, sres, match, err, i );
+ send_search_result( conn, op, sres, match, err, NULL, i );
if (match)
free(match);
if (err)
/* search.c - /etc/passwd backend search function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/ctype.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
#include <pwd.h>
-#include "portable.h"
-#include "slap.h"
-extern time_t currenttime;
-extern pthread_mutex_t currenttime_mutex;
+#include "slap.h"
+#include "external.h"
-static Entry *pw2entry();
+static Entry *pw2entry(
+ Backend *be,
+ struct passwd *pw,
+ char *rdn);
int
passwd_back_search(
int attrsonly
)
{
+ int sent = 0;
struct passwd *pw;
Entry *e;
char *s;
time_t stoptime;
+ int err = LDAP_NO_SUCH_OBJECT;
+
+ char *rdn = NULL;
+ char *parent = NULL;
+ char *matched = NULL;
+ char *user = NULL;
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ? be->be_timelimit
: tlimit;
slimit = (slimit > be->be_sizelimit || slimit < 1) ? be->be_sizelimit
: slimit;
+ endpwent();
+
#ifdef HAVE_SETPWFILE
if ( be->be_private != NULL ) {
- endpwent();
(void) setpwfile( (char *) be->be_private );
}
#endif /* HAVE_SETPWFILE */
- if ( scope == LDAP_SCOPE_BASE ) {
- if ( (s = strchr( base, '@' )) != NULL ) {
- *s = '\0';
- }
+ /* Handle a query for the base of this backend */
+ if ( be_issuffix( be, base ) ) {
+ struct berval val, *vals[2];
- if ( (pw = getpwnam( base )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- s != NULL ? s + 1 : NULL, NULL );
- return( -1 );
+ vals[0] = &val;
+ vals[1] = NULL;
+
+ /* Create an entry corresponding to the base DN */
+ e = (Entry *) ch_calloc(1, sizeof(Entry));
+ e->e_attrs = NULL;
+ e->e_dn = strdup(base);
+
+ /* Use the first attribute of the DN
+ * as an attribute within the entry itself.
+ */
+ rdn = dn_rdn(NULL, base);
+
+ if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) {
+ err = LDAP_INVALID_DN_SYNTAX;
+ goto done;
}
- e = pw2entry( be, pw );
+ val.bv_val = rdn_attr_value(rdn);
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, rdn_attr_type(rdn), vals );
+
+ free(rdn);
+ rdn = NULL;
+
+ /* Every entry needs an objectclass. We don't really
+ * know if our hardcoded choice here agrees with the
+ * DN that was configured for this backend, but it's
+ * better than nothing.
+ *
+ * should be a configuratable item
+ */
+ val.bv_val = "organizationalUnit";
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "objectClass", vals );
+
if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- send_search_entry( be, conn, op, e, attrs, attrsonly );
+ send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+ matched = strdup( be->be_suffix[0] );
+ sent++;
}
- entry_free( e );
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ if ( scope != LDAP_SCOPE_BASE ) {
+ /* check all our "children" */
- return( 0 );
- }
+ for ( pw = getpwent(); pw != NULL; pw = getpwent() ) {
+ /* check for abandon */
+ ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+ if ( op->o_abandon ) {
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+ endpwent();
+ return( -1 );
+ }
+ ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
+
+ /* check time limit */
+ if ( slap_get_time() > stoptime ) {
+ send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, NULL );
+ endpwent();
+ return( 0 );
+ }
+
+ e = pw2entry( be, pw, NULL );
- for ( pw = getpwent(); pw != NULL; pw = getpwent() ) {
- /* check for abandon */
- pthread_mutex_lock( &op->o_abandonmutex );
- if ( op->o_abandon ) {
- pthread_mutex_unlock( &op->o_abandonmutex );
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
+ NULL, NULL, NULL );
+ endpwent();
+ return( 0 );
+ }
+
+ send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+ sent++;
+ }
+
+ entry_free( e );
+ }
endpwent();
- return( -1 );
}
- pthread_mutex_unlock( &op->o_abandonmutex );
- /* check size limit */
- if ( --slimit == -1 ) {
- send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
- NULL, NULL );
- endpwent();
- return( 0 );
+ } else {
+ parent = dn_parent( be, base );
+
+ /* This backend is only one layer deep. Don't answer requests for
+ * anything deeper than that.
+ */
+ if( !be_issuffix( be, parent ) ) {
+ goto done;
}
- /* check time limit */
- pthread_mutex_lock( ¤ttime_mutex );
- time( ¤ttime );
- if ( currenttime > stoptime ) {
- pthread_mutex_unlock( ¤ttime_mutex );
- send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
- NULL, NULL );
- endpwent();
- return( 0 );
+ rdn = dn_rdn( NULL, base );
+
+ if ( (user = rdn_attr_value(rdn)) == NULL) {
+ err = LDAP_INVALID_DN_SYNTAX;
+ goto done;
+ }
+
+ for( s = user; *s ; s++ ) {
+ *s = TOLOWER( *s );
+ }
+
+ if ( (pw = getpwnam( user )) == NULL ) {
+ goto done;
}
- pthread_mutex_unlock( ¤ttime_mutex );
- e = pw2entry( be, pw );
+ e = pw2entry( be, pw, rdn );
if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- send_search_entry( be, conn, op, e, attrs, attrsonly );
+ send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+ sent++;
}
entry_free( e );
}
- endpwent();
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+
+done:
+ if( sent ) {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, err, matched, NULL, NULL);
+ }
+
+ if( matched != NULL ) free( matched );
+ if( parent != NULL ) free( parent );
+ if( rdn != NULL ) free( rdn );
+ if( user != NULL ) free( user );
return( 0 );
}
static Entry *
-pw2entry( Backend *be, struct passwd *pw )
+pw2entry( Backend *be, struct passwd *pw, char *rdn )
{
Entry *e;
char buf[256];
vals[1] = NULL;
/*
- * from pw we get pw_name and make it uid and cn and sn and
- * we get pw_gecos and make it cn and we give it an objectclass
- * of person.
+ * from pw we get pw_name and make it cn
+ * give it an objectclass of person.
*/
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
e->e_attrs = NULL;
- sprintf( buf, "%s@%s", pw->pw_name, be->be_suffix[0] );
- e->e_dn = strdup( buf );
+ /* rdn attribute type should be a configuratable item */
+ sprintf( buf, "uid=%s,%s", pw->pw_name, be->be_suffix[0] );
+ e->e_dn = ch_strdup( buf );
+ e->e_ndn = dn_normalize_case( ch_strdup( buf ) );
val.bv_val = pw->pw_name;
val.bv_len = strlen( pw->pw_name );
- attr_merge( e, "cn", vals );
- attr_merge( e, "sn", vals );
- attr_merge( e, "uid", vals );
- val.bv_val = pw->pw_gecos;
- val.bv_len = strlen( pw->pw_gecos );
- attr_merge( e, "cn", vals );
+ attr_merge( e, "uid", vals ); /* required by uidObject */
+ attr_merge( e, "cn", vals ); /* required by person */
+ attr_merge( e, "sn", vals ); /* required by person */
+
+#ifdef HAVE_PW_GECOS
+ /*
+ * if gecos is present, add it as a cn. first process it
+ * according to standard BSD usage. If the processed cn has
+ * a space, use the tail as the surname.
+ */
+ if (pw->pw_gecos[0]) {
+ char *s;
+
+ val.bv_val = pw->pw_gecos;
+ val.bv_len = strlen(val.bv_val);
+ attr_merge(e, "description", vals);
+
+ s = strchr(val.bv_val, ',');
+ if (s)
+ *s = '\0';
+ s = strchr(val.bv_val, '&');
+ if (s) {
+ int i = s - val.bv_val;
+ strncpy(buf, val.bv_val, i);
+ s = buf+i;
+ strcpy(s, pw->pw_name);
+ if (islower(*s))
+ *s = toupper(*s);
+ strcat(s, val.bv_val+i+1);
+ val.bv_val = buf;
+ }
+ val.bv_len = strlen(val.bv_val);
+ if ( strcmp( val.bv_val, pw->pw_name ))
+ attr_merge( e, "cn", vals );
+ if ( (s=strrchr(val.bv_val, ' '))) {
+ val.bv_val = s + 1;
+ val.bv_len = strlen(val.bv_val);
+ attr_merge(e, "sn", vals);
+ }
+ }
+#endif
+
+ /* objectclasses should be configuratable items */
val.bv_val = "person";
val.bv_len = strlen( val.bv_val );
attr_merge( e, "objectclass", vals );
+ val.bv_val = "uidObject";
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "objectclass", vals );
return( e );
}
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+int
+perl_back_add(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e
+)
+{
+ int len;
+ int count;
+ int return_code;
+
+ PerlBackend *perl_back = (PerlBackend *) be->be_private;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp);
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( entry2str( e, &len, 0 ), 0 )));
+
+ PUTBACK;
+
+ count = perl_call_method("add", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in back_search\n");
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "Here ADD\n", 0, 0, 0 );
+ return( 0 );
+}
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+/**********************************************************
+ *
+ * Compare
+ *
+ **********************************************************/
+
+perl_back_compare(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ Ava *ava
+)
+{
+ int return_code;
+ int count;
+
+ PerlBackend *perl_back = (PerlBackend *)be->be_private;
+
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+ NULL, "not yet implemented", NULL );
+
+#ifdef notdef
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp);
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( dn , 0)));
+ /* XPUSHs(sv_2mortal(newSVpv( cred->bv_val , cred->bv_len))); */
+ PUTBACK;
+
+ count = perl_call_method("bind", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in back_search\n");
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE, NULL, NULL );
+ }
+#endif
+
+ Debug( LDAP_DEBUG_ANY, "Here BIND\n", 0, 0, 0 );
+
+ return (0);
+}
+
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+#include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+perl_back_delete(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn
+)
+{
+ int len;
+ int count;
+ int return_code;
+
+ PerlBackend *perl_back = (PerlBackend *) be->be_private;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp);
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( dn , 0 )));
+
+ PUTBACK;
+
+ count = perl_call_method("delete", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in perl-back_delete\n");
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "Here DELETE\n", 0, 0, 0 );
+ return( 0 );
+}
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+int
+perl_back_modify(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ LDAPModList *modlist
+)
+{
+ char test[500];
+ int return_code;
+ int count;
+ int i;
+ int err = 0;
+ char *matched = NULL, *info = NULL;
+
+ PerlBackend *perl_back = (PerlBackend *)be->be_private;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp);
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( dn , 0)));
+
+ for (; modlist != NULL; modlist = modlist->ml_next ) {
+ LDAPMod *mods = &modlist->ml_mod;
+
+ switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
+ case LDAP_MOD_ADD:
+ XPUSHs(sv_2mortal(newSVpv("ADD", 0 )));
+ break;
+
+ case LDAP_MOD_DELETE:
+ XPUSHs(sv_2mortal(newSVpv("DELETE", 0 )));
+ break;
+
+ case LDAP_MOD_REPLACE:
+ XPUSHs(sv_2mortal(newSVpv("REPLACE", 0 )));
+ break;
+ }
+
+
+ XPUSHs(sv_2mortal(newSVpv( mods->mod_type, 0 )));
+
+ for ( i = 0;
+ mods->mod_bvalues != NULL && mods->mod_bvalues[i] != NULL;
+ i++ )
+ {
+ XPUSHs(sv_2mortal(newSVpv( mods->mod_bvalues[i]->bv_val, 0 )));
+ }
+ }
+
+ PUTBACK;
+
+ count = perl_call_method("modify", G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1) {
+ croak("Big trouble in back_search\n");
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "Perl MODIFY\n", 0, 0, 0 );
+ return( 0 );
+}
+
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+int
+perl_back_modrdn(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *dn,
+ char *newrdn,
+ int deleteoldrdn,
+ char *newSuperior
+)
+{
+ int len;
+ int count;
+ int return_code;
+
+ PerlBackend *perl_back = (PerlBackend *) be->be_private;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp) ;
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( dn , 0 )));
+ XPUSHs(sv_2mortal(newSVpv( newrdn , 0 )));
+ XPUSHs(sv_2mortal(newSViv( deleteoldrdn )));
+ if ( newSuperior != NULL ) {
+ XPUSHs(sv_2mortal(newSVpv( newSuperior , 0 )));
+ }
+ PUTBACK ;
+
+ count = perl_call_method("modrdn", G_SCALAR);
+
+ SPAGAIN ;
+
+ if (count != 1) {
+ croak("Big trouble in back_search\n") ;
+ }
+
+ return_code = POPi;
+
+ PUTBACK; FREETMPS; LEAVE ;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ }
+
+ Debug( LDAP_DEBUG_ANY, "Perl MODRDN\n", 0, 0, 0 );
+ return( 0 );
+}
+
+
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+/**********************************************************
+ *
+ * Search
+ *
+ **********************************************************/
+int
+perl_back_search(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *base,
+ int scope,
+ int deref,
+ int sizelimit,
+ int timelimit,
+ Filter *filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+ )
+{
+ char test[500];
+ int count ;
+ int err = 0;
+ char *matched = NULL, *info = NULL;
+ PerlBackend *perl_back = (PerlBackend *)be->be_private;
+ Entry *e;
+ char *buf;
+ int i;
+ int return_code;
+
+ ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
+
+ {
+ dSP; ENTER; SAVETMPS;
+
+ PUSHMARK(sp) ;
+ XPUSHs( perl_back->pb_obj_ref );
+ XPUSHs(sv_2mortal(newSVpv( filterstr , 0)));
+ XPUSHs(sv_2mortal(newSViv( sizelimit )));
+ XPUSHs(sv_2mortal(newSViv( timelimit )));
+ XPUSHs(sv_2mortal(newSViv( attrsonly )));
+
+ for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
+ XPUSHs(sv_2mortal(newSVpv( attrs[i] , 0)));
+ }
+ PUTBACK;
+
+ count = perl_call_method("search", G_ARRAY );
+
+ SPAGAIN;
+
+ if (count < 1) {
+ croak("Big trouble in back_search\n") ;
+ }
+
+ if ( count > 1 ) {
+
+ for ( i = 1; i < count; i++ ) {
+
+ buf = POPp;
+
+ if ( (e = str2entry( buf )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", buf, 0, 0 );
+
+ } else {
+ send_search_entry( be,
+ conn,
+ op,
+ e,
+ attrs,
+ attrsonly,
+ 0 );
+
+ entry_free( e );
+ }
+ }
+ }
+
+ /*
+ * We grab the return code last because the stack comes
+ * from perl in reverse order.
+ *
+ * ex perl: return ( 0, $res_1, $res_2 );
+ *
+ * ex stack: <$res_2> <$res_1> <0>
+ */
+
+ return_code = POPi;
+
+
+
+ PUTBACK; FREETMPS; LEAVE;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
+
+ if( return_code != 0 ) {
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
+
+ } else {
+ send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
+ }
+}
+
--- /dev/null
+/*
+ * Copyright 1999, John C. Quillan, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+ /* init.c - initialize shell backend */
+
+#include <stdio.h>
+/* #include <ac/types.h>
+ #include <ac/socket.h>
+*/
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#include "slap.h"
+#include "perl_back.h"
+
+
+/**********************************************************
+ *
+ * UnBind
+ *
+ **********************************************************/
+int
+perl_back_unbind(
+ Backend *be,
+ Connection *conn,
+ Operation *op
+)
+{
+ Debug( LDAP_DEBUG_TRACE, "Perl UNBIND\n", 0, 0, 0 );
+ return 0;
+}
+
/* add.c - shell backend add function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-extern pthread_mutex_t entry2str_mutex;
-extern char *entry2str();
-
-void
+int
shell_back_add(
Backend *be,
Connection *conn,
if ( si->si_add == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "add not implemented" );
- return;
+ "add not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_add, &rfp, &wfp )) == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_add, &rfp, &wfp )) == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the add process */
fprintf( wfp, "ADD\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
- pthread_mutex_lock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
fprintf( wfp, "%s", entry2str( e, &len, 0 ) );
- pthread_mutex_unlock( &entry2str_mutex );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
fclose( wfp );
/* read in the result and send it along */
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
}
/* bind.c - shell backend bind function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "shell.h"
Operation *op,
char *dn,
int method,
- struct berval *cred
+ char *mech,
+ struct berval *cred,
+ char **edn
)
{
struct shellinfo *si = (struct shellinfo *) be->be_private;
FILE *rfp, *wfp;
int rc;
+ *edn = NULL;
+
if ( si->si_bind == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "bind not implemented" );
- return;
+ "bind not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_bind, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_bind, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the bind process */
fprintf( wfp, "BIND\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "dn: %s\n", dn );
fprintf( wfp, "method: %d\n", method );
- fprintf( wfp, "credlen: %d\n", cred->bv_len );
+ fprintf( wfp, "credlen: %lu\n", cred->bv_len );
fprintf( wfp, "cred: %s\n", cred->bv_val ); /* XXX */
fclose( wfp );
/* compare.c - shell backend compare function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-void
+int
shell_back_compare(
Backend *be,
Connection *conn,
if ( si->si_compare == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "compare not implemented" );
- return;
+ "compare not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_compare, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_compare, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the compare process */
fprintf( wfp, "COMPARE\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "dn: %s\n", dn );
fprintf( wfp, "%s: %s\n", ava->ava_type, ava->ava_value.bv_val );
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
}
/* delete.c - shell backend delete function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-void
+int
shell_back_delete(
Backend *be,
Connection *conn,
if ( si->si_delete == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "delete not implemented" );
- return;
+ "delete not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_delete, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_delete, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the delete process */
fprintf( wfp, "DELETE\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "dn: %s\n", dn );
fclose( wfp );
/* read in the results and send them along */
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
}
/* modify.c - shell backend modify function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
#include "slap.h"
#include "shell.h"
-void
+int
shell_back_modify(
Backend *be,
Connection *conn,
Operation *op,
char *dn,
- LDAPMod *mods
+ LDAPModList *ml
)
{
struct shellinfo *si = (struct shellinfo *) be->be_private;
if ( si->si_modify == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modify not implemented" );
- return;
+ "modify not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_modify, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_modify, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the modify process */
fprintf( wfp, "MODIFY\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "dn: %s\n", dn );
- for ( ; mods != NULL; mods = mods->mod_next ) {
- switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
+ for ( ; ml != NULL; ml = ml->ml_next ) {
+ switch ( ml->ml_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_ADD:
- fprintf( wfp, "add: %s", mods->mod_type );
+ fprintf( wfp, "add: %s\n", ml->ml_type );
break;
case LDAP_MOD_DELETE:
- fprintf( wfp, "delete: %s", mods->mod_type );
+ fprintf( wfp, "delete: %s\n", ml->ml_type );
break;
case LDAP_MOD_REPLACE:
- fprintf( wfp, "replace: %s", mods->mod_type );
+ fprintf( wfp, "replace: %s\n", ml->ml_type );
break;
}
- for ( i = 0; mods->mod_bvalues != NULL && mods->mod_bvalues[i]
+ for ( i = 0; ml->ml_bvalues != NULL && ml->ml_bvalues[i]
!= NULL; i++ ) {
- fprintf( wfp, "%s: %s\n", mods->mod_type,
- mods->mod_bvalues[i]->bv_val );
+ fprintf( wfp, "%s: %s\n", ml->ml_type,
+ ml->ml_bvalues[i]->bv_val );
}
}
fclose( wfp );
/* read in the results and send them along */
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
+
}
/* modrdn.c - shell backend modrdn function */
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "shell.h"
-void
+int
shell_back_modrdn(
Backend *be,
Connection *conn,
Operation *op,
char *dn,
char *newrdn,
- int deleteoldrdn
+ int deleteoldrdn,
+ char *newSuperior
)
{
struct shellinfo *si = (struct shellinfo *) be->be_private;
if ( si->si_modrdn == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modrdn not implemented" );
- return;
+ "modrdn not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_modrdn, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_modrdn, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the modrdn process */
fprintf( wfp, "MODRDN\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "dn: %s\n", dn );
fprintf( wfp, "newrdn: %s\n", newrdn );
fprintf( wfp, "deleteoldrdn: %d\n", deleteoldrdn ? 1 : 0 );
+ if (newSuperior != NULL) {
+ fprintf( wfp, "newSuperior: %s\n", newSuperior );
+ }
fclose( wfp );
/* read in the results and send them along */
read_and_send_results( be, conn, op, rfp, NULL, 0 );
fclose( rfp );
+ return( 0 );
}
/* result.c - shell backend result reading function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
#include "slap.h"
#include "shell.h"
-extern Entry *str2entry();
-
int
read_and_send_results(
Backend *be,
buf, 0, 0 );
} else {
send_search_entry( be, conn, op, e, attrs,
- attrsonly );
+ attrsonly, 0 );
entry_free( e );
}
/* otherwise, front end will send this result */
if ( err != 0 || op->o_tag != LDAP_REQ_BIND ) {
- send_ldap_result( conn, op, err, matched, info );
+ send_ldap_result( conn, op, err, matched, info, NULL );
}
free( buf );
/* search.c - shell backend search function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "shell.h"
-extern Entry *str2entry();
-
-void
+int
shell_back_search(
Backend *be,
Connection *conn,
if ( si->si_search == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "search not implemented" );
- return;
+ "search not implemented", NULL );
+ return( -1 );
}
- if ( (op->o_private = forkandexec( si->si_search, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_search, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return( -1 );
}
/* write out the request to the search process */
fprintf( wfp, "SEARCH\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
fprintf( wfp, "base: %s\n", base );
fprintf( wfp, "scope: %d\n", scope );
read_and_send_results( be, conn, op, rfp, attrs, attrsonly );
fclose( rfp );
+ return( 0 );
}
/* unbind.c - shell backend unbind function */
+#include "portable.h"
+
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
#include "slap.h"
#include "shell.h"
-void
+int
shell_back_unbind(
Backend *be,
Connection *conn,
- Operation *op,
- char *dn,
- int method,
- struct berval *cred
+ Operation *op
)
{
struct shellinfo *si = (struct shellinfo *) be->be_private;
if ( si->si_unbind == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "unbind not implemented" );
- return;
+ "unbind not implemented", NULL );
+ return 0;
}
- if ( (op->o_private = forkandexec( si->si_unbind, &rfp, &wfp ))
- == -1 ) {
+ if ( (op->o_private = (void *) forkandexec( si->si_unbind, &rfp, &wfp ))
+ == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
- return;
+ "could not fork/exec", NULL );
+ return 0;
}
/* write out the request to the unbind process */
fprintf( wfp, "UNBIND\n" );
- fprintf( wfp, "msgid: %d\n", op->o_msgid );
+ fprintf( wfp, "msgid: %ld\n", op->o_msgid );
print_suffixes( wfp, be );
- fprintf( wfp, "dn: %s\n", dn );
+ fprintf( wfp, "dn: %s\n", (conn->c_dn ? conn->c_dn : "") );
fclose( wfp );
/* no response to unbind */
fclose( rfp );
+
+ return 0;
}
--- /dev/null
+/* add.c - tcl add routine
+ *
+ * $Id: tcl_add.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_add (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ Entry * e
+)
+{
+ char *command, *suf_tcl, *entrystr, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_add == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "add not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ entrystr = tcl_clean_entry (e);
+
+ command = (char *) ch_malloc (strlen (ti->ti_add) + strlen
+ (suf_tcl) +
+ strlen (entrystr) + 32);
+ sprintf (command, "%s ADD {%ld} {%s} {%s}",
+ ti->ti_add, op->o_msgid, suf_tcl, entrystr);
+ Tcl_Free (suf_tcl);
+ free (entrystr);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_add_error: %s\n", results, 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* bind.c - tcl bind routines
+ *
+ * $Id: tcl_bind.c,v 1.6 1999/06/29 01:29:27 kdz Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_bind (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ int method,
+ char *mech,
+ struct berval *cred,
+ char **edn
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ *edn = NULL;
+
+ if (ti->ti_bind == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "bind not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_bind) + strlen
+ (suf_tcl) +
+ strlen (dn) + strlen (cred->bv_val) + 64);
+ sprintf (command, "%s BIND {%ld} {%s} {%s} {%d} {%lu} {%s}",
+ ti->ti_bind, op->o_msgid, suf_tcl, dn, method, cred->bv_len,
+ cred->bv_val);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_bind_error: %s\n", results, 0, 0);
+ } else {
+ err = interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* compare.c - tcl compare routines
+ *
+ * $Id: tcl_compare.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_compare (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ Ava * ava
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_compare == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "compare not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_compare) +
+ strlen (suf_tcl) + strlen (dn) + strlen (ava->ava_type) +
+ strlen (ava->ava_value.bv_val) + 64);
+ sprintf (command, "%s COMPARE {%ld} {%s} {%s} {%s: %s}",
+ ti->ti_compare, op->o_msgid, suf_tcl, dn, ava->ava_type,
+ ava->ava_value.bv_val);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_compare_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* delete.c - tcl delete routines
+ *
+ * $Id: tcl_delete.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+tcl_back_delete (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_delete == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "delete not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_delete) + strlen (suf_tcl)
+ + strlen (dn) + 64);
+ sprintf (command, "%s DELETE {%ld} {%s} {%s}",
+ ti->ti_delete, op->o_msgid, suf_tcl, dn);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_delete_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* modify.c - tcl modify routines
+ *
+ * $Id: tcl_modify.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_modify (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ LDAPModList * modlist
+)
+{
+ char *command, *suf_tcl, *bp, *tcl_mods, *results;
+ int i, code, err = 0, len, bsize;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_modify == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "modify not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ tcl_mods = (char *) ch_malloc (BUFSIZ);
+ tcl_mods[0] = '\0';
+ bsize = BUFSIZ;
+ bp = tcl_mods;
+
+ for (; modlist != NULL; modlist = modlist->ml_next) {
+ LDAPMod *mods = &modlist->ml_mod;
+ char *op = NULL;
+
+ switch (mods->mod_op & ~LDAP_MOD_BVALUES) {
+ case LDAP_MOD_ADD:
+ op = "add";
+ break;
+ case LDAP_MOD_DELETE:
+ op = "delete";
+ break;
+ case LDAP_MOD_REPLACE:
+ op = "replace";
+ break;
+ }
+
+ len = strlen (mods->mod_type) + strlen (op) + 7;
+ while (bp + len - tcl_mods > bsize) {
+ bsize += BUFSIZ;
+ tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
+ }
+ sprintf (bp, "{ {%s: %s} ", op, mods->mod_type);
+ bp += len;
+ for (i = 0;
+ mods->mod_bvalues != NULL && mods->mod_bvalues[i]
+ != NULL;
+ i++) {
+ len = strlen (mods->mod_type) + strlen (
+ mods->mod_bvalues[i]->bv_val) + 5 +
+ (mods->mod_bvalues[i + 1] == NULL ? 2 : 0);
+ while (bp + len - tcl_mods > bsize) {
+ bsize += BUFSIZ;
+ tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
+ }
+ sprintf (bp, "{%s: %s} %s", mods->mod_type,
+ mods->mod_bvalues[i]->bv_val,
+ mods->mod_bvalues[i + 1] ==
+ NULL ? "} " : "");
+ bp += len;
+ }
+ }
+
+ command = (char *) ch_malloc (strlen (ti->ti_modify) + strlen (suf_tcl)
+ + strlen (dn) + strlen (tcl_mods) + 64);
+ /* This space is simply for aesthetics--\ */
+ sprintf (command, "%s MODIFY {%ld} {%s} {%s} { %s}",
+ ti->ti_modify, op->o_msgid, suf_tcl, dn, tcl_mods);
+ Tcl_Free (suf_tcl);
+ free (tcl_mods);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_modify_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* modrdn.c - tcl modify rdn routines
+ *
+ * $Id: tcl_modrdn.c,v 1.7 1999/03/05 18:21:35 gomez Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/*
+ * LDAP v3 newSuperior support.
+ *
+ * Copyright 1999, Juan C. Gomez, All rights reserved.
+ * This software is not subject to any license of Silicon Graphics
+ * Inc. or Purdue University.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * without restriction or fee of any kind as long as this notice
+ * is preserved.
+ *
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_modrdn (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *dn,
+ char *newrdn,
+ int deleteoldrdn,
+ char *newSuperior
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_modrdn == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "modrdn not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_modrdn) + strlen (suf_tcl)
+ + strlen (dn) + strlen (newrdn)
+ + (newSuperior ? strlen(newSuperior) : 0) + 64);
+ if ( newSuperior ) {
+ sprintf (command, "%s MODRDN {%ld} {%s} {%s} {%s} %d {%s}",
+ ti->ti_add, op->o_msgid, suf_tcl, dn, newrdn,
+ deleteoldrdn ? 1 : 0, newSuperior );
+ } else {
+ sprintf (command, "%s MODRDN {%ld} {%s} {%s} {%s} %d",
+ ti->ti_add, op->o_msgid, suf_tcl, dn, newrdn,
+ deleteoldrdn ? 1 : 0 );
+ }
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_modrdn_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* search.c - tcl search routines
+ *
+ * $Id: tcl_search.c,v 1.5 1999/02/28 04:55:49 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_search (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *base,
+ int scope,
+ int deref,
+ int sizelimit,
+ int timelimit,
+ Filter * filter,
+ char *filterstr,
+ char **attrs,
+ int attrsonly
+)
+{
+ char *attrs_tcl = NULL, *suf_tcl, *results, *command;
+ int i, err = 0, code;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+ Entry *e;
+
+ if (ti->ti_search == NULL) {
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "search not implemented", NULL );
+ return (-1);
+ }
+
+ for (i = 0; attrs != NULL && attrs[i] != NULL; i++);
+ if (i > 0)
+ attrs_tcl = Tcl_Merge (i, attrs);
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_search) + strlen (suf_tcl)
+ + strlen (base) + 40 + strlen (filterstr) + (attrs_tcl ==
+ NULL ? 5
+ : strlen (attrs_tcl)) + 72);
+ sprintf (command,
+ "%s SEARCH {%ld} {%s} {%s} {%d} {%d} {%d} {%d} {%s} {%d} {%s}",
+ ti->ti_search, op->o_msgid, suf_tcl, base, scope, deref,
+ sizelimit, timelimit, filterstr, attrsonly ? 1 : 0,
+ attrs_tcl ==
+ NULL ? "{all}" : attrs_tcl);
+ Tcl_Free (attrs_tcl);
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ err = LDAP_OPERATIONS_ERROR;
+ Debug (LDAP_DEBUG_SHELL, "tcl_search_error: %s\n", results,
+ 0, 0);
+ } else {
+ interp_send_results (be, conn, op, results, NULL, 0);
+ }
+
+ if (err != LDAP_SUCCESS)
+ send_ldap_result (conn, op, err, NULL,
+ "internal backend error", NULL );
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* unbind.c - tcl unbind routines
+ *
+ * $Id: tcl_unbind.c,v 1.5 1999/02/28 04:55:49 bcollins Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+tcl_back_unbind (
+ Backend * be,
+ Connection * conn,
+ Operation * op
+)
+{
+ char *command, *suf_tcl, *results;
+ int i, code, err = 0;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ if (ti->ti_unbind == NULL) {
+ return (-1);
+ }
+
+ for (i = 0; be->be_suffix[i] != NULL; i++);
+ suf_tcl = Tcl_Merge (i, be->be_suffix);
+
+ command = (char *) ch_malloc (strlen (ti->ti_unbind) + strlen (suf_tcl)
+ + strlen (conn->c_dn ? conn->c_dn : "") + 64);
+ sprintf (command, "%s UNBIND {%ld} {%s} {%s}",
+ ti->ti_unbind, op->o_msgid, suf_tcl, conn->c_dn ?
+ conn->c_dn : "");
+ Tcl_Free (suf_tcl);
+
+ ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
+ code = Tcl_GlobalEval (ti->ti_ii->interp, command);
+ results = (char *) ch_strdup (ti->ti_ii->interp->result);
+ ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
+ free (command);
+
+ if (code != TCL_OK) {
+ Debug (LDAP_DEBUG_SHELL, "tcl_unbind_error: %s\n", results,
+ 0, 0);
+ }
+
+ free (results);
+ return (err);
+}
--- /dev/null
+/* result.c - tcl backend utility functions
+ *
+ * $Id: tcl_util.c,v 1.6 1999/07/07 16:51:41 kdz Exp $
+ *
+ * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "tcl_back.h"
+
+int
+interp_send_results (
+ Backend * be,
+ Connection * conn,
+ Operation * op,
+ char *result,
+ char **attrs,
+ int attrsonly
+)
+{
+ int bsize, len, argcPtr, i, err, code;
+ char *buf, *bp, **argvPtr, *line, *matched, *info;
+ Entry *e;
+ struct tclinfo *ti = (struct tclinfo *) be->be_private;
+
+ /*
+ * read in the result and send it along
+ */
+ buf = (char *) ch_malloc (BUFSIZ);
+ buf[0] = '\0';
+ bsize = BUFSIZ;
+ bp = buf;
+ code = Tcl_SplitList (ti->ti_ii->interp, result, &argcPtr, &argvPtr);
+ if (code != TCL_OK) {
+ argcPtr = 0;
+ send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "internal backend error", NULL );
+ return -1;
+ }
+ for (i = 0; i < argcPtr; i++) {
+ line = argvPtr[i];
+
+ /*
+ * ignore lines beginning with DEBUG:
+ */
+ if (strncasecmp (line, "DEBUG:", 6) == 0) {
+ continue;
+ }
+ len = strlen (line) + 1;
+ while (bp + len - buf > bsize) {
+ bsize += BUFSIZ;
+ buf = (char *) ch_realloc (buf, bsize);
+ }
+ sprintf (bp, "%s\n", line);
+ bp += len;
+
+ /*
+ * line marked the end of an entry or result
+ */
+ if (line[0] == '\0') {
+ if (strncasecmp (buf, "RESULT", 6) == 0) {
+ break;
+ }
+ if ((e = str2entry (buf)) == NULL) {
+ Debug (LDAP_DEBUG_SHELL,
+ "str2entry(%s) failed\n",
+ buf, 0, 0);
+ } else {
+ send_search_entry (be, conn, op, e, attrs,
+ attrsonly, 0 );
+ entry_free (e);
+ }
+
+ bp = buf;
+ }
+ }
+
+ (void) str2result (buf, &err, &matched, &info);
+
+ /*
+ * otherwise, front end will send this result
+ */
+ if (err != 0 || op->o_tag != LDAP_REQ_BIND) {
+ send_ldap_result (conn, op, err, matched, info, NULL );
+ }
+
+ free (buf);
+ Tcl_Free ((char *) argvPtr);
+ return (err);
+}
+
+char *
+tcl_clean_entry (
+ Entry * e
+)
+{
+ char *entrystr, *mark1, *mark2, *buf, *bp, *dup;
+ int len, bsize;
+
+ pthread_mutex_lock (&entry2str_mutex);
+ entrystr = entry2str (e, &len, 0);
+ pthread_mutex_unlock (&entry2str_mutex);
+
+ buf = (char *) ch_malloc (BUFSIZ);
+ buf[0] = '\0';
+ bsize = BUFSIZ;
+ bp = buf;
+ bp++[0] = ' ';
+
+ mark1 = entrystr;
+ do {
+ if (mark1[0] == '\n') {
+ mark1++;
+ }
+ dup = (char *) ch_strdup (mark1);
+ if (dup[0] != '\0') {
+ if ((mark2 = (char *) strchr (dup, '\n')) != NULL) {
+ mark2[0] = '\0';
+ }
+ len = strlen (dup) + 3;
+ while (bp + len - buf > bsize) {
+ bsize += BUFSIZ;
+ buf = (char *) ch_realloc (buf, bsize);
+ }
+ if (mark1[0] == '\0') {
+ sprintf (bp, "{} ");
+ } else {
+ sprintf (bp, "{%s} ", dup);
+ }
+ bp += len;
+ if (mark2 != NULL) {
+ mark2[0] = '\n';
+ }
+ }
+ free (dup);
+ } while ((mark1 = (char *) strchr (mark1, '\n')) != NULL);
+ return buf;
+}
+
+int
+tcl_ldap_debug (
+ ClientData clientData,
+ Tcl_Interp * interp,
+ int argc,
+ char *argv[]
+)
+{
+ if (argv[1] != NULL) {
+ Debug (LDAP_DEBUG_SHELL, "tcl_debug: %s\n", argv[1], 0, 0);
+ }
+ return TCL_OK;
+}
+
+void
+readtclscript (
+ char *script,
+ Tcl_Interp * my_tcl)
+{
+ int code;
+ FILE *f;
+
+ f = fopen (script, "r");
+ if (f == NULL) {
+ Debug (LDAP_DEBUG_SHELL, "Could not open scriptpath %s\n", script,
+ 0, 0);
+ return;
+ }
+ fclose (f);
+ code = Tcl_EvalFile (my_tcl, script);
+ if (code != TCL_OK) {
+ Debug (LDAP_DEBUG_SHELL, "%s: %s\n", script,
+ Tcl_GetVar (my_tcl, "errorInfo", TCL_GLOBAL_ONLY), 0);
+ Debug (LDAP_DEBUG_SHELL, "%s: error at line\n", script,
+ my_tcl->errorLine, 0);
+ return;
+ }
+}
text == NULL ? "" : text );
if( rc != -1 && ref != NULL ) {
- rc = ber_printf( ber, "{v}", ref );
+ rc = ber_printf( ber, "{V}", ref );
}
if( rc != -1 && resoid != NULL ) {