]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slapmodify.c
Happy New Year
[openldap] / servers / slapd / slapmodify.c
index 878188eb1a92835333411ad3be1a7a86d14ed2d1..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
@@ -74,6 +76,7 @@ slapmodify( int argc, char **argv )
        memset( &opbuf, 0, sizeof(opbuf) );
        op = &opbuf.ob_op;
        op->o_hdr = &opbuf.ob_hdr;
+       op->o_bd = be;
 
        if ( !be->be_entry_open ||
                !be->be_entry_close ||
@@ -97,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 ) {
@@ -131,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;
@@ -178,20 +184,23 @@ slapmodify( int argc, char **argv )
                        request = "modify";
                        break;
 
-               case LDAP_REQ_MODRDN:
                case LDAP_REQ_DELETE:
+                       if ( be->be_entry_delete )
+                       {
+                               request = "delete";
+                               break;
+                       }
+                       /* 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:
-                       fprintf( stderr, "%s: unknown request 0x%lx (line=%lu)\n",
-                               progname, (unsigned long)lr.lr_op, lineno );
-                       rc = EXIT_FAILURE;
-                       if( continuemode ) continue;
-                       goto done;
+                       /* record skipped e.g. version: or comment or something we don't handle yet */
+                       goto cleanup;
                }
 
                local_rc = dnNormalize( 0, NULL, NULL, &lr.lr_dn, &ndn, NULL );
@@ -199,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 */
@@ -228,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 */
@@ -262,190 +267,190 @@ 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 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;
+               /* 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;
                }
 
-               for ( n = 0; lr.lrop_mods[ n ] != NULL; n++ ) {
-                       LDAPMod *mod = lr.lrop_mods[ n ];
-                       Modification mods = { 0 };
-                       unsigned i = 0;
-                       int bin = (mod->mod_op & LDAP_MOD_BVALUES);
-                       int pretty = 0;
-                       int normalize = 0;
-
-                       local_rc = slap_str2ad( mod->mod_type, &mods.sm_desc, &text );
-                       if ( local_rc != LDAP_SUCCESS ) {
-                               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;
-                       }
+               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;
+               }
 
-                       mods.sm_type = mods.sm_desc->ad_cname;
+               if ( lr.lrop_mods ) {
+                       for ( n = 0; lr.lrop_mods && lr.lrop_mods[ n ] != NULL; n++ ) {
+                               LDAPMod *mod = lr.lrop_mods[ n ];
+                               Modification mods = { 0 };
+                               unsigned i = 0;
+                               int bin = (mod->mod_op & LDAP_MOD_BVALUES);
+                               int pretty = 0;
+                               int normalize = 0;
 
-                       if ( mods.sm_desc->ad_type->sat_syntax->ssyn_pretty ) {
-                               pretty = 1;
+                               local_rc = slap_str2ad( mod->mod_type, &mods.sm_desc, &text );
+                               if ( local_rc != LDAP_SUCCESS ) {
+                                       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;
+                                       goto cleanup;
+                               }
 
-                       } else {
-                               assert( mods.sm_desc->ad_type->sat_syntax->ssyn_validate != NULL );
-                       }
+                               mods.sm_type = mods.sm_desc->ad_cname;
 
-                       if ( mods.sm_desc->ad_type->sat_equality &&
-                               mods.sm_desc->ad_type->sat_equality->smr_normalize )
-                       {
-                               normalize = 1;
-                       }
+                               if ( mods.sm_desc->ad_type->sat_syntax->ssyn_pretty ) {
+                                       pretty = 1;
 
-                       if ( bin && mod->mod_bvalues ) {
-                               for ( i = 0; mod->mod_bvalues[ i ] != NULL; i++ )
-                                       ;
+                               } else {
+                                       assert( mods.sm_desc->ad_type->sat_syntax->ssyn_validate != NULL );
+                               }
 
-                       } else if ( !bin && mod->mod_values ) {
-                               for ( i = 0; mod->mod_values[ i ] != NULL; i++ )
-                                       ;
-                       }
+                               if ( mods.sm_desc->ad_type->sat_equality &&
+                                       mods.sm_desc->ad_type->sat_equality->smr_normalize )
+                               {
+                                       normalize = 1;
+                               }
 
-                       mods.sm_values = SLAP_CALLOC( sizeof( struct berval ), i + 1 );
-                       if ( normalize ) {
-                               mods.sm_nvalues = SLAP_CALLOC( sizeof( struct berval ), i + 1 );
-                       } else {
-                               mods.sm_nvalues = NULL;
-                       }
-                       mods.sm_numvals = i;
+                               if ( bin && mod->mod_bvalues ) {
+                                       for ( i = 0; mod->mod_bvalues[ i ] != NULL; i++ )
+                                               ;
 
-                       for ( i = 0; i < mods.sm_numvals; i++ ) {
-                               struct berval bv;
+                               } else if ( !bin && mod->mod_values ) {
+                                       for ( i = 0; mod->mod_values[ i ] != NULL; i++ )
+                                               ;
+                               }
 
-                               if ( bin ) {
-                                       bv = *mod->mod_bvalues[ i ];
-                               } else {
-                                       ber_str2bv( mod->mod_values[ i ], 0, 0, &bv );
+                               if ( i != 0 )
+                               {
+                                       mods.sm_values = SLAP_CALLOC( sizeof( struct berval ), i + 1 );
+                                       if ( normalize ) {
+                                               mods.sm_nvalues = SLAP_CALLOC( sizeof( struct berval ), i + 1 );
+                                       } else {
+                                               mods.sm_nvalues = NULL;
+                                       }
                                }
+                               mods.sm_numvals = i;
 
-                               if ( pretty ) {
-                                       local_rc = ordered_value_pretty( mods.sm_desc,
-                                       &bv, &mods.sm_values[i], NULL );
+                               for ( i = 0; i < mods.sm_numvals; i++ ) {
+                                       struct berval bv;
 
-                               } else {
-                                       local_rc = ordered_value_validate( mods.sm_desc,
-                                               &bv, 0 );
-                               }
+                                       if ( bin ) {
+                                               bv = *mod->mod_bvalues[ i ];
+                                       } else {
+                                               ber_str2bv( mod->mod_values[ i ], 0, 0, &bv );
+                                       }
 
-                               if ( local_rc != LDAP_SUCCESS ) {
-                                       fprintf( stderr, "%s: DN=\"%s\": unable to %s attr=%s value #%d\n",
-                                               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;
-                               }
+                                       if ( pretty ) {
+                                               local_rc = ordered_value_pretty( mods.sm_desc,
+                                               &bv, &mods.sm_values[i], NULL );
 
-                               if ( !pretty ) {
-                                       ber_dupbv( &mods.sm_values[i], &bv );
-                               }
+                                       } else {
+                                               local_rc = ordered_value_validate( mods.sm_desc,
+                                                       &bv, 0 );
+                                       }
 
-                               if ( normalize ) {
-                                       local_rc = ordered_value_normalize(
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               mods.sm_desc,
-                                               mods.sm_desc->ad_type->sat_equality,
-                                               &mods.sm_values[i], &mods.sm_nvalues[i],
-                                               NULL );
                                        if ( local_rc != LDAP_SUCCESS ) {
-                                               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 );
+                                               fprintf( stderr, "%s: DN=\"%s\": unable to %s attr=%s value #%d\n",
+                                                       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;
                                        }
-                               }
-                       }
 
-                       mods.sm_op = (mod->mod_op & ~LDAP_MOD_BVALUES);
-                       mods.sm_flags = 0;
-
-                       if ( mods.sm_desc == slap_schema.si_ad_objectClass ) {
-                               is_oc = 1;
-                       }
+                                       if ( !pretty ) {
+                                               ber_dupbv( &mods.sm_values[i], &bv );
+                                       }
 
-                       switch ( mods.sm_op ) {
-                       case LDAP_MOD_ADD:
-                               local_rc = modify_add_values( e, &mods,
-                                       0, &text, textbuf, textlen );
-                               break;
+                                       if ( normalize ) {
+                                               local_rc = ordered_value_normalize(
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       mods.sm_desc,
+                                                       mods.sm_desc->ad_type->sat_equality,
+                                                       &mods.sm_values[i], &mods.sm_nvalues[i],
+                                                       NULL );
+                                               if ( local_rc != LDAP_SUCCESS ) {
+                                                       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 */
+                                                       rc = EXIT_FAILURE;
+                                                       ber_bvarray_free( mods.sm_values );
+                                                       ber_bvarray_free( mods.sm_nvalues );
+                                                       goto cleanup;
+                                               }
+                                       }
+                               }
 
-                       case LDAP_MOD_DELETE:
-                               local_rc = modify_delete_values( e, &mods,
-                                       0, &text, textbuf, textlen );
-                               break;
+                               mods.sm_op = (mod->mod_op & ~LDAP_MOD_BVALUES);
+                               mods.sm_flags = 0;
 
-                       case LDAP_MOD_REPLACE:
-                               local_rc = modify_replace_values( e, &mods,
-                                       0, &text, textbuf, textlen );
-                               break;
+                               if ( mods.sm_desc == slap_schema.si_ad_objectClass ) {
+                                       is_oc = 1;
+                               }
 
-                       case LDAP_MOD_INCREMENT:
-                               local_rc = modify_increment_values( e, &mods,
-                                       0, &text, textbuf, textlen );
-                               break;
-                       }
+                               switch ( mods.sm_op ) {
+                               case LDAP_MOD_ADD:
+                                       local_rc = modify_add_values( e, &mods,
+                                               0, &text, textbuf, textlen );
+                                       break;
+
+                               case LDAP_MOD_DELETE:
+                                       local_rc = modify_delete_values( e, &mods,
+                                               0, &text, textbuf, textlen );
+                                       break;
+
+                               case LDAP_MOD_REPLACE:
+                                       local_rc = modify_replace_values( e, &mods,
+                                               0, &text, textbuf, textlen );
+                                       break;
+
+                               case LDAP_MOD_INCREMENT:
+                                       local_rc = modify_increment_values( e, &mods,
+                                               0, &text, textbuf, textlen );
+                                       break;
+                               }
 
-                       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;
+
+                               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;
+                                       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;
+                       rc = slap_tool_entry_check( progname, op, e, lineno, &text, textbuf, textlen );
+                       if ( rc != LDAP_SUCCESS ) {
+                               rc = EXIT_FAILURE;
+                               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 ];
@@ -482,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 );
@@ -494,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 );
@@ -546,47 +551,53 @@ slapmodify( int argc, char **argv )
                        }
                }
 
-               if ( mod_err ) break;
-
                /* check schema, objectClass etc */
 
                if ( !dryrun ) {
                        switch ( lr.lr_op ) {
                        case LDAP_REQ_ADD:
                                id = be->be_entry_put( be, e, &bvtext );
+                               rc = (id == NOID);
                                break;
 
                        case LDAP_REQ_MODIFY:
                                id = be->be_entry_modify( be, e, &bvtext );
+                               rc = (id == NOID);
+                               break;
+
+                       case LDAP_REQ_DELETE:
+                               rc = be->be_entry_delete( be, &ndn, &bvtext );
                                break;
 
                        }
 
-                       if( id == NOID ) {
+                       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;