]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slapmodify.c
ITS#8845 Recognise control-exop compatibility
[openldap] / servers / slapd / slapmodify.c
index 72b0493ca085a643a7f52387dde6abef896ac828..fd578a68f2837c149ec6a2ea2585880a39993a62 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2014 The OpenLDAP Foundation.
+ * Copyright 1998-2018 The OpenLDAP Foundation.
  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
  * Portions Copyright 2003 IBM Corporation.
  * All rights reserved.
@@ -38,6 +38,8 @@
 
 #include "slapcommon.h"
 
+extern int slap_DN_strict;     /* dn.c */
+
 static char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
 
 int
@@ -98,9 +100,12 @@ slapmodify( int argc, char **argv )
        lmax = 0;
        nextline = 0;
 
-       /* enforce schema checking unless not disabled */
+       /* enforce schema checking unless not disabled and allow unknown
+        * attributes otherwise */
        if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) {
                SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK);
+       } else {
+               slap_DN_strict = 0;
        }
 
        if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) {
@@ -132,10 +137,10 @@ slapmodify( int argc, char **argv )
                lineno=nextline+1 )
        {
                BackendDB *bd;
-               Entry *e;
+               Entry *e_orig = NULL, *e = NULL;
                struct berval rbuf;
                LDIFRecord lr;
-               struct berval ndn;
+               struct berval ndn = BER_BVNULL;
                int n;
                int is_oc = 0;
                int local_rc;
@@ -185,18 +190,17 @@ slapmodify( int argc, char **argv )
                                request = "delete";
                                break;
                        }
-                       /* backend does not support delete, fallthrough */
+                       /* backend does not support delete, fallthru */
 
                case LDAP_REQ_MODRDN:
                        fprintf( stderr, "%s: request 0x%lx not supported (line=%lu)\n",
                                progname, (unsigned long)lr.lr_op, lineno );
                        rc = EXIT_FAILURE;
-                       if( continuemode ) continue;
-                       goto done;
+                       goto cleanup;
 
                default:
                        /* record skipped e.g. version: or comment or something we don't handle yet */
-                       continue;
+                       goto cleanup;
                }
 
                local_rc = dnNormalize( 0, NULL, NULL, &lr.lr_dn, &ndn, NULL );
@@ -204,8 +208,7 @@ slapmodify( int argc, char **argv )
                        fprintf( stderr, "%s: DN=\"%s\" normalization failed (line=%lu)\n",
                                progname, lr.lr_dn.bv_val, lineno );
                        rc = EXIT_FAILURE;
-                       if( continuemode ) continue;
-                       break;
+                       goto cleanup;
                }
 
                /* make sure the DN is not empty */
@@ -233,10 +236,7 @@ slapmodify( int argc, char **argv )
                        }
                        fprintf( stderr, "\n" );
                        rc = EXIT_FAILURE;
-                       SLAP_FREE( ndn.bv_val );
-                       ldap_ldif_record_done( &lr );
-                       if( continuemode ) continue;
-                       break;
+                       goto cleanup;
                }
 
                /* check backend */
@@ -267,19 +267,36 @@ slapmodify( int argc, char **argv )
                        }
                        fprintf( stderr, "\n" );
                        rc = EXIT_FAILURE;
-                       SLAP_FREE( ndn.bv_val );
-                       ldap_ldif_record_done( &lr );
-                       if( continuemode ) continue;
-                       break;
+                       goto cleanup;
+               }
+
+               /* get id and/or entry */
+               switch ( lr.lr_op ) {
+                       case LDAP_REQ_ADD:
+                               e = entry_alloc();
+                               ber_dupbv( &e->e_name, &lr.lr_dn );
+                               ber_dupbv( &e->e_nname, &ndn );
+                               break;
+
+                       //case LDAP_REQ_MODRDN:
+                       case LDAP_REQ_DELETE:
+                       case LDAP_REQ_MODIFY:
+                               id = be->be_dn2id_get( be, &ndn );
+                               rc = (id == NOID);
+                               if ( rc == LDAP_SUCCESS && lr.lr_op != LDAP_REQ_DELETE ) {
+                                       e_orig = be->be_entry_get( be, id );
+                                       if ( e_orig )
+                                               e = entry_dup( e_orig );
+                                       rc = (e == NULL);
+                               }
+                               break;
                }
 
-               /* get entry */
-               id = be->be_dn2id_get( be, &ndn );
-               e = be->be_entry_get( be, id );
-               if ( e != NULL ) {
-                       Entry *e_tmp = entry_dup( e );
-                       /* FIXME: release? */
-                       e = e_tmp;
+               if ( rc != LDAP_SUCCESS ) {
+                       fprintf( stderr, "%s: no such entry \"%s\" in database (lineno=%lu)\n",
+                               progname, ndn.bv_val, lineno );
+                       rc = EXIT_FAILURE;
+                       goto cleanup;
                }
 
                if ( lr.lrop_mods ) {
@@ -296,12 +313,7 @@ slapmodify( int argc, char **argv )
                                        fprintf( stderr, "%s: slap_str2ad(\"%s\") failed for entry \"%s\" (%d: %s, lineno=%lu)\n",
                                                progname, mod->mod_type, lr.lr_dn.bv_val, local_rc, text, lineno );
                                        rc = EXIT_FAILURE;
-                                       mod_err = 1;
-                                       if( continuemode ) continue;
-                                       SLAP_FREE( ndn.bv_val );
-                                       ldap_ldif_record_done( &lr );
-                                       entry_free( e );
-                                       goto done;
+                                       goto cleanup;
                                }
 
                                mods.sm_type = mods.sm_desc->ad_cname;
@@ -362,15 +374,10 @@ slapmodify( int argc, char **argv )
                                                        progname, e->e_dn, pretty ? "prettify" : "validate",
                                                        mods.sm_desc->ad_cname.bv_val, i );
                                                /* handle error */
-                                               mod_err = 1;
                                                rc = EXIT_FAILURE;
                                                ber_bvarray_free( mods.sm_values );
                                                ber_bvarray_free( mods.sm_nvalues );
-                                               if( continuemode ) continue;
-                                               SLAP_FREE( ndn.bv_val );
-                                               ldap_ldif_record_done( &lr );
-                                               entry_free( e );
-                                               goto done;
+                                               goto cleanup;
                                        }
 
                                        if ( !pretty ) {
@@ -388,15 +395,10 @@ slapmodify( int argc, char **argv )
                                                        fprintf( stderr, "%s: DN=\"%s\": unable to normalize attr=%s value #%d\n",
                                                                progname, e->e_dn, mods.sm_desc->ad_cname.bv_val, i );
                                                        /* handle error */
-                                                       mod_err = 1;
                                                        rc = EXIT_FAILURE;
                                                        ber_bvarray_free( mods.sm_values );
                                                        ber_bvarray_free( mods.sm_nvalues );
-                                                       if( continuemode ) continue;
-                                                       SLAP_FREE( ndn.bv_val );
-                                                       ldap_ldif_record_done( &lr );
-                                                       entry_free( e );
-                                                       goto done;
+                                                       goto cleanup;
                                                }
                                        }
                                }
@@ -430,32 +432,25 @@ slapmodify( int argc, char **argv )
                                        break;
                                }
 
+                               ber_bvarray_free( mods.sm_values );
+                               ber_bvarray_free( mods.sm_nvalues );
+
                                if ( local_rc != LDAP_SUCCESS ) {
                                        fprintf( stderr, "%s: DN=\"%s\": unable to modify attr=%s\n",
                                                progname, e->e_dn, mods.sm_desc->ad_cname.bv_val );
                                        rc = EXIT_FAILURE;
-                                       ber_bvarray_free( mods.sm_values );
-                                       ber_bvarray_free( mods.sm_nvalues );
-                                       if( continuemode ) continue;
-                                       SLAP_FREE( ndn.bv_val );
-                                       ldap_ldif_record_done( &lr );
-                                       entry_free( e );
-                                       goto done;
+                                       goto cleanup;
                                }
                        }
 
                        rc = slap_tool_entry_check( progname, op, e, lineno, &text, textbuf, textlen );
                        if ( rc != LDAP_SUCCESS ) {
                                rc = EXIT_FAILURE;
-                               SLAP_FREE( ndn.bv_val );
-                               ldap_ldif_record_done( &lr );
-                               if( continuemode ) continue;
-                               entry_free( e );
-                               break;
+                               goto cleanup;
                        }
                }
 
-               if ( SLAP_LASTMOD(be) ) {
+               if ( SLAP_LASTMOD(be) && e != NULL ) {
                        time_t now = slap_get_time();
                        char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
                        struct berval vals[ 2 ];
@@ -492,8 +487,6 @@ slapmodify( int argc, char **argv )
 
                        a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
                        if ( a != NULL ) {
-                               vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
-                               vals[0].bv_val = uuidbuf;
                                if ( a->a_vals != a->a_nvals ) {
                                        SLAP_FREE( a->a_nvals[0].bv_val );
                                        SLAP_FREE( a->a_nvals );
@@ -504,6 +497,8 @@ slapmodify( int argc, char **argv )
                                a->a_nvals = NULL;
                                a->a_numvals = 0;
                        }
+                       vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
+                       vals[0].bv_val = uuidbuf;
                        attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, vals, NULL );
 
                        a = attr_find( e->e_attrs, slap_schema.si_ad_creatorsName );
@@ -556,8 +551,6 @@ slapmodify( int argc, char **argv )
                        }
                }
 
-               if ( mod_err ) break;
-
                /* check schema, objectClass etc */
 
                if ( !dryrun ) {
@@ -573,36 +566,38 @@ slapmodify( int argc, char **argv )
                                break;
 
                        case LDAP_REQ_DELETE:
-                               rc = be->be_entry_delete( be, id, &bvtext );
+                               rc = be->be_entry_delete( be, &ndn, &bvtext );
                                break;
 
                        }
 
                        if( rc != LDAP_SUCCESS ) {
                                fprintf( stderr, "%s: could not %s entry dn=\"%s\" "
-                                       "(line=%lu): %s\n", progname, request, e->e_dn,
+                                       "(line=%lu): %s\n", progname, request, ndn.bv_val,
                                        lineno, bvtext.bv_val );
                                rc = EXIT_FAILURE;
-                               entry_free( e );
-                               if( continuemode ) continue;
-                               break;
+                               goto cleanup;
                        }
 
                        sid = slap_tool_update_ctxcsn_check( progname, e );
 
                        if ( verbose )
                                fprintf( stderr, "%s: \"%s\" (%08lx)\n",
-                                       request, e->e_dn, (long) id );
+                                       request, ndn.bv_val, (long) id );
                } else {
                        if ( verbose )
                                fprintf( stderr, "%s: \"%s\"\n",
-                                       request, e->e_dn );
+                                       request, ndn.bv_val );
                }
 
-               entry_free( e );
+cleanup:;
+               ldap_ldif_record_done( &lr );
+               SLAP_FREE( ndn.bv_val );
+               if ( e ) entry_free( e );
+               if ( e_orig ) be_entry_release_w( op, e_orig );
+               if ( rc != LDAP_SUCCESS && !continuemode ) break;
        }
 
-done:;
        if ( ldifrc < 0 )
                rc = EXIT_FAILURE;