]> git.sur5r.net Git - openldap/commitdiff
Add additional args to send_ldap_result calls.
authorKurt Zeilenga <kurt@openldap.org>
Fri, 9 Jul 1999 20:02:57 +0000 (20:02 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Fri, 9 Jul 1999 20:02:57 +0000 (20:02 +0000)
37 files changed:
servers/slapd/back-bdb2/add.c [new file with mode: 0644]
servers/slapd/back-bdb2/alias.c [new file with mode: 0644]
servers/slapd/back-bdb2/bind.c [new file with mode: 0644]
servers/slapd/back-bdb2/compare.c [new file with mode: 0644]
servers/slapd/back-bdb2/delete.c [new file with mode: 0644]
servers/slapd/back-bdb2/modify.c [new file with mode: 0644]
servers/slapd/back-bdb2/modrdn.c [new file with mode: 0644]
servers/slapd/back-bdb2/search.c
servers/slapd/back-ldap/bind.c [new file with mode: 0644]
servers/slapd/back-ldap/search.c
servers/slapd/back-passwd/search.c
servers/slapd/back-perl/add.c [new file with mode: 0644]
servers/slapd/back-perl/compare.c [new file with mode: 0644]
servers/slapd/back-perl/delete.c [new file with mode: 0644]
servers/slapd/back-perl/modify.c [new file with mode: 0644]
servers/slapd/back-perl/modrdn.c [new file with mode: 0644]
servers/slapd/back-perl/search.c [new file with mode: 0644]
servers/slapd/back-perl/unbind.c [new file with mode: 0644]
servers/slapd/back-shell/add.c
servers/slapd/back-shell/bind.c
servers/slapd/back-shell/compare.c
servers/slapd/back-shell/delete.c
servers/slapd/back-shell/modify.c
servers/slapd/back-shell/modrdn.c
servers/slapd/back-shell/result.c
servers/slapd/back-shell/search.c
servers/slapd/back-shell/unbind.c
servers/slapd/back-tcl/tcl_add.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_bind.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_compare.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_delete.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_modify.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_modrdn.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_search.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_unbind.c [new file with mode: 0644]
servers/slapd/back-tcl/tcl_util.c [new file with mode: 0644]
servers/slapd/result.c

diff --git a/servers/slapd/back-bdb2/add.c b/servers/slapd/back-bdb2/add.c
new file mode 100644 (file)
index 0000000..da41b7d
--- /dev/null
@@ -0,0 +1,294 @@
+/* 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;
+}
+
+
diff --git a/servers/slapd/back-bdb2/alias.c b/servers/slapd/back-bdb2/alias.c
new file mode 100644 (file)
index 0000000..107b5bc
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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;
+}
diff --git a/servers/slapd/back-bdb2/bind.c b/servers/slapd/back-bdb2/bind.c
new file mode 100644 (file)
index 0000000..6bb6006
--- /dev/null
@@ -0,0 +1,298 @@
+/* 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 );
+}
+
+
diff --git a/servers/slapd/back-bdb2/compare.c b/servers/slapd/back-bdb2/compare.c
new file mode 100644 (file)
index 0000000..0da11c9
--- /dev/null
@@ -0,0 +1,101 @@
+/* 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 );
+}
+
+
diff --git a/servers/slapd/back-bdb2/delete.c b/servers/slapd/back-bdb2/delete.c
new file mode 100644 (file)
index 0000000..04a508a
--- /dev/null
@@ -0,0 +1,176 @@
+/* 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 );
+}
+
+
diff --git a/servers/slapd/back-bdb2/modify.c b/servers/slapd/back-bdb2/modify.c
new file mode 100644 (file)
index 0000000..61a3a72
--- /dev/null
@@ -0,0 +1,347 @@
+/* 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( &currenttime );
+       strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
+#else
+       ltm = localtime( &currenttime );
+       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 );
+}
diff --git a/servers/slapd/back-bdb2/modrdn.c b/servers/slapd/back-bdb2/modrdn.c
new file mode 100644 (file)
index 0000000..0aca35b
--- /dev/null
@@ -0,0 +1,462 @@
+/* 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 );
+}
+
+
index 9ae5992917918bf92e703b34d9864b5a806eb301..49335a61ad1fbff6ca5f51c284293e7803ff81e5 100644 (file)
@@ -50,9 +50,8 @@ bdb2i_back_search_internal(
        ID              id;
        Entry           *e;
        Attribute       *ref;
+       struct berval **refs;
        char            *matched = NULL;
-       int             rmaxsize, nrefs;
-       char            *rbuf, *rcur;
        int             nentries = 0;
        char            *realBase;
 
@@ -108,8 +107,8 @@ bdb2i_back_search_internal(
                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 );
                }
@@ -118,7 +117,7 @@ bdb2i_back_search_internal(
 
        /* 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 );
                }
@@ -132,12 +131,8 @@ bdb2i_back_search_internal(
                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 */
@@ -145,7 +140,7 @@ bdb2i_back_search_internal(
                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 );
                        }
@@ -155,11 +150,10 @@ bdb2i_back_search_internal(
 
                /* 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 );
                        }
@@ -183,27 +177,8 @@ bdb2i_back_search_internal(
                        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 {
@@ -234,11 +209,10 @@ bdb2i_back_search_internal(
                                        /* 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 );
@@ -278,7 +252,7 @@ bdb2i_back_search_internal(
                                                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 );
@@ -298,14 +272,12 @@ bdb2i_back_search_internal(
                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 );
@@ -339,8 +311,8 @@ bdb2_back_search(
        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 );
 
        }
diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c
new file mode 100644 (file)
index 0000000..a0352f1
--- /dev/null
@@ -0,0 +1,119 @@
+/* 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 );
+}
index 7654bd3b2dcfd1660300dd409384e179a24ddf47..b0f0930ad43536c5f79766e535382659ef6e3638 100644 (file)
@@ -116,7 +116,7 @@ fail:               return( ldap_back_op_result(lc, op) );
        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)
index 11c1d8e7192424712a5acd60e0e9f6592fc0a722..752517c1ca40e7c81c7d0c92406b813186dddb44 100644 (file)
@@ -1,18 +1,23 @@
 /* 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(
@@ -30,10 +35,17 @@ 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;
@@ -41,81 +53,154 @@ passwd_back_search(
        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( &currenttime_mutex );
-               time( &currenttime );
-               if ( currenttime > stoptime ) {
-                       pthread_mutex_unlock( &currenttime_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( &currenttime_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];
@@ -126,28 +211,69 @@ pw2entry( Backend *be, struct passwd *pw )
        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 );
 }
diff --git a/servers/slapd/back-perl/add.c b/servers/slapd/back-perl/add.c
new file mode 100644 (file)
index 0000000..4e9fa2d
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *      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 );
+}
diff --git a/servers/slapd/back-perl/compare.c b/servers/slapd/back-perl/compare.c
new file mode 100644 (file)
index 0000000..d66d94f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *      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);
+}
+
diff --git a/servers/slapd/back-perl/delete.c b/servers/slapd/back-perl/delete.c
new file mode 100644 (file)
index 0000000..f32b38e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *      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 );
+}
diff --git a/servers/slapd/back-perl/modify.c b/servers/slapd/back-perl/modify.c
new file mode 100644 (file)
index 0000000..19a83c4
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *      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 );
+}
+
diff --git a/servers/slapd/back-perl/modrdn.c b/servers/slapd/back-perl/modrdn.c
new file mode 100644 (file)
index 0000000..125bd71
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *      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 );
+}
+
+
diff --git a/servers/slapd/back-perl/search.c b/servers/slapd/back-perl/search.c
new file mode 100644 (file)
index 0000000..b8451e7
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *      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 );
+       }
+}
+
diff --git a/servers/slapd/back-perl/unbind.c b/servers/slapd/back-perl/unbind.c
new file mode 100644 (file)
index 0000000..9d97219
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *   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;
+}
+
index 89f054cc9c3d78d76f380d202f26613f595ab448..10c51b02c7c104ebb31ab9d73674996517a9d61d 100644 (file)
@@ -1,16 +1,16 @@
 /* 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,
@@ -24,27 +24,28 @@ shell_back_add(
 
        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 );
 }
index dea149e4106fc4779706c3a065000fd7e976a1e5..ffb3542181f903309b1732d50da06263420fa5f1 100644 (file)
@@ -1,9 +1,12 @@
 /* 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"
 
@@ -14,33 +17,37 @@ shell_back_bind(
     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 );
 
index 48dfbb553be6719c9b9c9e9d858a5f80e2996f3f..780fea125693eb641a571d1939dc40a91d0b4aaa 100644 (file)
@@ -1,13 +1,16 @@
 /* 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,
@@ -21,20 +24,20 @@ shell_back_compare(
 
        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 );
@@ -44,4 +47,5 @@ shell_back_compare(
        read_and_send_results( be, conn, op, rfp, NULL, 0 );
 
        fclose( rfp );
+       return( 0 );
 }
index 0dc3439c008ce53ea77a642f8cafa2313585a2f6..dc0617d86514c67b3c9a648df1a4faf04f4530f9 100644 (file)
@@ -1,13 +1,16 @@
 /* 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,
@@ -20,20 +23,20 @@ shell_back_delete(
 
        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 );
@@ -41,4 +44,5 @@ shell_back_delete(
        /* read in the results and send them along */
        read_and_send_results( be, conn, op, rfp, NULL, 0 );
        fclose( rfp );
+       return( 0 );
 }
index d05b79639df7f024d2c95461e996608f6aefa6fe..ac6cefaed708ee1c4497a121061035f8423c2d27 100644 (file)
@@ -1,19 +1,22 @@
 /* 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;
@@ -22,41 +25,41 @@ shell_back_modify(
 
        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 );
@@ -64,4 +67,6 @@ shell_back_modify(
        /* read in the results and send them along */
        read_and_send_results( be, conn, op, rfp, NULL, 0 );
        fclose( rfp );
+       return( 0 );
+
 }
index 9fd793317d19e6de0f0cf1d64722c60f4047512e..b208d606a30d1c1bbcd1a61f8a10f610bfe07736 100644 (file)
@@ -1,20 +1,37 @@
 /* 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;
@@ -22,27 +39,31 @@ shell_back_modrdn(
 
        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 );
 }
index 675aa1f144ced8a90503c7992ba1ab3c10d18605..b15d3f3e8dc4bd9d5b17c7d13909b2a3bdf89f6c 100644 (file)
@@ -1,14 +1,16 @@
 /* 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,
@@ -57,7 +59,7 @@ read_and_send_results(
                                    buf, 0, 0 );
                        } else {
                                send_search_entry( be, conn, op, e, attrs,
-                                   attrsonly );
+                                   attrsonly, 0 );
                                entry_free( e );
                        }
 
@@ -68,7 +70,7 @@ read_and_send_results(
 
        /* 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 );
index 749b112a9401238704bb7b9c4fc5606483ef1cc7..ae2aba312c8f93eb55fbf8948f9e9265e32500e7 100644 (file)
@@ -1,15 +1,16 @@
 /* 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,
@@ -33,20 +34,20 @@ shell_back_search(
 
        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 );
@@ -66,4 +67,5 @@ shell_back_search(
        read_and_send_results( be, conn, op, rfp, attrs, attrsonly );
 
        fclose( rfp );
+       return( 0 );
 }
index 649fe96c137703e0759a2992aa6663f11622e19f..63d628eacdcbb531a0d0fcf02f2957f9d5f14e1d 100644 (file)
@@ -1,20 +1,20 @@
 /* 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;
@@ -22,24 +22,26 @@ shell_back_unbind(
 
        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;
 }
diff --git a/servers/slapd/back-tcl/tcl_add.c b/servers/slapd/back-tcl/tcl_add.c
new file mode 100644 (file)
index 0000000..7224df0
--- /dev/null
@@ -0,0 +1,70 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_bind.c b/servers/slapd/back-tcl/tcl_bind.c
new file mode 100644 (file)
index 0000000..dd8d66d
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_compare.c b/servers/slapd/back-tcl/tcl_compare.c
new file mode 100644 (file)
index 0000000..1352100
--- /dev/null
@@ -0,0 +1,70 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_delete.c b/servers/slapd/back-tcl/tcl_delete.c
new file mode 100644 (file)
index 0000000..a8e2a86
--- /dev/null
@@ -0,0 +1,66 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_modify.c b/servers/slapd/back-tcl/tcl_modify.c
new file mode 100644 (file)
index 0000000..3c81584
--- /dev/null
@@ -0,0 +1,117 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_modrdn.c b/servers/slapd/back-tcl/tcl_modrdn.c
new file mode 100644 (file)
index 0000000..e5dde6a
--- /dev/null
@@ -0,0 +1,91 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_search.c b/servers/slapd/back-tcl/tcl_search.c
new file mode 100644 (file)
index 0000000..f01104a
--- /dev/null
@@ -0,0 +1,87 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_unbind.c b/servers/slapd/back-tcl/tcl_unbind.c
new file mode 100644 (file)
index 0000000..7872da4
--- /dev/null
@@ -0,0 +1,58 @@
+/* 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);
+}
diff --git a/servers/slapd/back-tcl/tcl_util.c b/servers/slapd/back-tcl/tcl_util.c
new file mode 100644 (file)
index 0000000..994b24a
--- /dev/null
@@ -0,0 +1,190 @@
+/* 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;
+       }
+}
index 8ebb81bab863735f81b2c916d606016e4e6bb49f..f1496e4ca5ed5809879cbfb5b0c39f63cdf1a8c2 100644 (file)
@@ -161,7 +161,7 @@ send_ldap_response(
                        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 ) {