]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/passwd.c
Added bdb_attribute and bdb_group ACL support routines
[openldap] / servers / slapd / back-bdb / passwd.c
index 1639a62979978f6ae3f5916d2bc90e453ab8f8d8..3642eacfc568cb844a58b89273e685e80dd5e895 100644 (file)
 
 int
 bdb_exop_passwd(
-    Backend            *be,
-    Connection         *conn,
-    Operation          *op,
+       Backend         *be,
+       Connection              *conn,
+       Operation               *op,
        const char              *reqoid,
-    struct berval      *reqdata,
+       struct berval   *reqdata,
        char                    **rspoid,
-    struct berval      **rspdata,
+       struct berval   **rspdata,
        LDAPControl             *** rspctrls,
        const char              **text,
-    struct berval      *** refs
-)
+       struct berval   *** refs )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        int rc;
        Entry *e = NULL;
        struct berval *hash = NULL;
-       DB_TXN *ltid;
+       DB_TXN *ltid = NULL;
+       struct bdb_op_info opinfo;
+       char textbuf[SLAP_TEXT_BUFLEN];
+       size_t textlen = sizeof textbuf;
 
        struct berval *id = NULL;
        struct berval *new = NULL;
@@ -73,7 +75,7 @@ bdb_exop_passwd(
 
        dn = id ? id->bv_val : op->o_dn;
 
-       Debug( LDAP_DEBUG_TRACE, "passwd: \"%s\"%s\n",
+       Debug( LDAP_DEBUG_TRACE, "bdb_exop_passwd: \"%s\"%s\n",
                dn, id ? " (proxy)" : "", 0 );
 
        if( dn == NULL || dn[0] == '\0' ) {
@@ -82,22 +84,55 @@ bdb_exop_passwd(
                goto done;
        }
 
-       /* fetch entry */
-       rc = dn2entry_w( be, NULL, dn, &e, NULL );
+       if (0) {
+retry: /* transaction retry */
+               Debug( LDAP_DEBUG_TRACE, "bdb_exop_passwd: retrying...\n", 0, 0, 0 );
+               rc = txn_abort( ltid );
+               ltid = NULL;
+               op->o_private = NULL;
+               if( rc != 0 ) {
+                       rc = LDAP_OTHER;
+                       *text = "internal error";
+                       goto done;
+               }
+       }
+
+       /* begin transaction */
+       rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
+       *text = NULL;
+       if( rc != 0 ) {
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_exop_passwd: txn_begin failed: %s (%d)\n",
+                       db_strerror(rc), rc, 0 );
+               rc = LDAP_OTHER;
+               *text = "internal error";
+               goto done;
+       }
+
+       opinfo.boi_bdb = be;
+       opinfo.boi_txn = ltid;
+       opinfo.boi_err = 0;
+       op->o_private = &opinfo;
+
+       /* get entry */
+       rc = bdb_dn2entry( be, ltid, dn, &e, NULL, 0 );
 
        switch(rc) {
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto retry;
        case DB_NOTFOUND:
        case 0:
                break;
        default:
-               send_ldap_result( conn, op, rc=LDAP_OTHER,
-                   NULL, "internal error", NULL, NULL );
-               return rc;
+               rc = LDAP_OTHER;
+               *text = "internal error";
+               goto done;
        }
 
        if( e == NULL ) {
                *text = "could not locate authorization entry";
-               rc = LDAP_OPERATIONS_ERROR;
+               rc = LDAP_NO_SUCH_OBJECT;
                goto done;
        }
 
@@ -108,11 +143,11 @@ bdb_exop_passwd(
                goto done;
        }
 
-       rc = LDAP_OPERATIONS_ERROR;
 
        if( is_entry_referral( e ) ) {
                /* entry is an referral, don't allow operation */
                *text = "authorization entry is referral";
+               rc = LDAP_OPERATIONS_ERROR;
                goto done;
        }
 
@@ -128,19 +163,40 @@ bdb_exop_passwd(
                ml.sml_op = LDAP_MOD_REPLACE;
                ml.sml_next = NULL;
 
-               rc = bdb_modify_internal( be,
-                       conn, op, op->o_ndn, &ml, e, text );
+               rc = bdb_modify_internal( be, conn, op, ltid,
+                       &ml, e, text, textbuf, textlen );
+
+               switch(rc) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       *text = NULL;
+                       bdb_entry_return( be, e );
+                       e = NULL;
+                       goto retry;
+               case 0:
+                       break;
+               default:
+                       rc = LDAP_OTHER;
+                       *text = "entry modify failed";
+                       goto done;
+               }
 
        }
 
-       if( rc == LDAP_SUCCESS ) {
-               /* change the entry itself */
-               if( bdb_id2entry_add( be, ltid, e ) != 0 ) {
-                       *text = "entry update failed";
-                       rc = LDAP_OTHER;
+       /* change the entry itself */
+       rc = bdb_id2entry_update( be, ltid, e );
+       if( rc != 0 ) {
+               switch(rc) {
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       bdb_entry_return( be, e );
+                       e = NULL;
+                       goto retry;
                }
+               *text = "entry update failed";
+               rc = LDAP_OTHER;
        }
-       
+
 done:
        if( e != NULL ) {
                bdb_entry_return( be, e );
@@ -158,5 +214,10 @@ done:
                ber_bvfree( hash );
        }
 
+       if( ltid != NULL ) {
+               txn_abort( ltid );
+               op->o_private = NULL;
+       }
+
        return rc;
 }