Diff for /servers/slapd/modify.c between versions 1.227 and 1.227.2.24

version 1.227, 2004/12/04 18:26:22 version 1.227.2.24, 2006/02/13 19:50:35
Line 1 Line 1
 /* $OpenLDAP: pkg/ldap/servers/slapd/modify.c,v 1.226 2004/10/06 03:51:39 hyc Exp $ */  /* $OpenLDAP: pkg/ldap/servers/slapd/modify.c,v 1.227.2.23 2006/01/17 19:37:20 kurt Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 1998-2004 The OpenLDAP Foundation.   * Copyright 1998-2006 The OpenLDAP Foundation.
  * All rights reserved.   * All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 32 Line 32
 #include <ac/time.h>  #include <ac/time.h>
   
 #include "slap.h"  #include "slap.h"
 #ifdef LDAP_SLAPI  
 #include "slapi/slapi.h"  
 #endif  
 #include "lutil.h"  #include "lutil.h"
   
   
Line 50  do_modify( Line 47  do_modify(
         Modifications   *modlist = NULL;          Modifications   *modlist = NULL;
         Modifications   **modtail = &modlist;          Modifications   **modtail = &modlist;
         int             increment = 0;          int             increment = 0;
           char            textbuf[ SLAP_TEXT_BUFLEN ];
           size_t          textlen = sizeof( textbuf );
   
         Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );          Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
   
Line 91  do_modify( Line 90  do_modify(
   
                 tmp.sml_nvalues = NULL;                  tmp.sml_nvalues = NULL;
   
                 if ( ber_scanf( op->o_ber, "{i{m[W]}}", &mop,                  if ( ber_scanf( op->o_ber, "{e{m[W]}}", &mop,
                     &tmp.sml_type, &tmp.sml_values ) == LBER_ERROR )                      &tmp.sml_type, &tmp.sml_values ) == LBER_ERROR )
                 {                  {
                         send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR,                          send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR,
Line 102  do_modify( Line 101  do_modify(
   
                 mod = (Modifications *) ch_malloc( sizeof(Modifications) );                  mod = (Modifications *) ch_malloc( sizeof(Modifications) );
                 mod->sml_op = mop;                  mod->sml_op = mop;
                   mod->sml_flags = 0;
                 mod->sml_type = tmp.sml_type;                  mod->sml_type = tmp.sml_type;
                 mod->sml_values = tmp.sml_values;                  mod->sml_values = tmp.sml_values;
                 mod->sml_nvalues = NULL;                  mod->sml_nvalues = NULL;
Line 140  do_modify( Line 140  do_modify(
                                         goto cleanup;                                          goto cleanup;
                                 }                                  }
   
                                 if( mod->sml_values[1].bv_val ) {                                  if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) {
                                         Debug( LDAP_DEBUG_ANY, "do_modify: modify/increment "                                          Debug( LDAP_DEBUG_ANY, "do_modify: modify/increment "
                                                 "operation (%ld) requires single value\n",                                                  "operation (%ld) requires single value\n",
                                                 (long) mop, 0, 0 );                                                  (long) mop, 0, 0 );
Line 184  do_modify( Line 184  do_modify(
                 goto cleanup;                  goto cleanup;
         }          }
   
         /* FIXME: temporary */          rs->sr_err = slap_mods_check( modlist,
                   &rs->sr_text, textbuf, textlen, NULL );
   
           if ( rs->sr_err != LDAP_SUCCESS ) {
                   send_ldap_result( op, rs );
                   goto cleanup;
           }
   
           /* FIXME: needs review */
         op->orm_modlist = modlist;          op->orm_modlist = modlist;
         op->orm_increment = increment;          op->orm_increment = increment;
   
Line 192  do_modify( Line 200  do_modify(
         rs->sr_err = frontendDB->be_modify( op, rs );          rs->sr_err = frontendDB->be_modify( op, rs );
   
 cleanup:  cleanup:
         slap_graduate_commit_csn( op );  
   
         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );          op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );          op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
         if ( modlist != NULL ) slap_mods_free( modlist );          if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 );
   
         return rs->sr_err;          return rs->sr_err;
 }  }
Line 209  fe_op_modify( Operation *op, SlapReply * Line 215  fe_op_modify( Operation *op, SlapReply *
 #endif  #endif
         int             manageDSAit;          int             manageDSAit;
         Modifications   *modlist = op->orm_modlist;          Modifications   *modlist = op->orm_modlist;
         Modifications   **modtail = &modlist;  
 #ifdef LDAP_SLAPI  
         LDAPMod         **modv = NULL;  
 #endif  
         int             increment = op->orm_increment;          int             increment = op->orm_increment;
           BackendDB *op_be, *bd = op->o_bd;
           char            textbuf[ SLAP_TEXT_BUFLEN ];
           size_t          textlen = sizeof( textbuf );
                   
         if( op->o_req_ndn.bv_len == 0 ) {          if( BER_BVISEMPTY( &op->o_req_ndn ) ) {
                 Debug( LDAP_DEBUG_ANY, "do_modify: root dse!\n", 0, 0, 0 );                  Debug( LDAP_DEBUG_ANY, "do_modify: root dse!\n", 0, 0, 0 );
   
                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,                  send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
Line 243  fe_op_modify( Operation *op, SlapReply * Line 248  fe_op_modify( Operation *op, SlapReply *
                 if ( tmp->sml_values == NULL ) {                  if ( tmp->sml_values == NULL ) {
                         Debug( LDAP_DEBUG_ARGS, "%s\n",                          Debug( LDAP_DEBUG_ARGS, "%s\n",
                            "\t\tno values", NULL, NULL );                             "\t\tno values", NULL, NULL );
                 } else if ( tmp->sml_values[0].bv_val == NULL ) {                  } else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) {
                         Debug( LDAP_DEBUG_ARGS, "%s\n",                          Debug( LDAP_DEBUG_ARGS, "%s\n",
                            "\t\tzero values", NULL, NULL );                             "\t\tzero values", NULL, NULL );
                 } else if ( tmp->sml_values[1].bv_val == NULL ) {                  } else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) {
                         Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n",                          Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n",
                            "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL );                             "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL );
                 } else {                  } else {
Line 299  fe_op_modify( Operation *op, SlapReply * Line 304  fe_op_modify( Operation *op, SlapReply *
          */           */
         op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );          op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 1 );
         if ( op->o_bd == NULL ) {          if ( op->o_bd == NULL ) {
                   op->o_bd = bd;
                 rs->sr_ref = referral_rewrite( default_referral,                  rs->sr_ref = referral_rewrite( default_referral,
                         NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );                          NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
                 if (!rs->sr_ref) rs->sr_ref = default_referral;                  if (!rs->sr_ref) rs->sr_ref = default_referral;
Line 315  fe_op_modify( Operation *op, SlapReply * Line 321  fe_op_modify( Operation *op, SlapReply *
                 goto cleanup;                  goto cleanup;
         }          }
   
           /* If we've got a glued backend, check the real backend */
           op_be = op->o_bd;
           if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
                   op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
           }
   
         /* check restrictions */          /* check restrictions */
         if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {          if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                 send_ldap_result( op, rs );                  send_ldap_result( op, rs );
Line 326  fe_op_modify( Operation *op, SlapReply * Line 338  fe_op_modify( Operation *op, SlapReply *
                 goto cleanup;                  goto cleanup;
         }          }
   
           rs->sr_err = slap_mods_obsolete_check( op, modlist,
                   &rs->sr_text, textbuf, textlen );
           if ( rs->sr_err != LDAP_SUCCESS ) {
                   send_ldap_result( op, rs );
                   goto cleanup;
           }
   
         /* check for modify/increment support */          /* check for modify/increment support */
         if( increment && !SLAP_INCREMENT( op->o_bd ) ) {          if( increment && !SLAP_INCREMENT( op->o_bd ) ) {
                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,                  send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                         "modify/increment not supported in context" );                          "modify/increment not supported in context" );
         }          }
   
 #if defined( LDAP_SLAPI )  
 #define pb      op->o_pb  
         if ( pb ) {  
                 slapi_int_pblock_set_operation( pb, op );  
                 slapi_pblock_set( pb, SLAPI_MODIFY_TARGET, (void *)op->o_req_dn.bv_val );  
                 slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)manageDSAit );  
                 modv = slapi_int_modifications2ldapmods( &modlist );  
                 slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)modv );  
   
                 rs->sr_err = slapi_int_call_plugins( op->o_bd,  
                         SLAPI_PLUGIN_PRE_MODIFY_FN, pb );  
   
                 /*  
                  * It's possible that the preoperation plugin changed the  
                  * modification array, so we need to convert it back to  
                  * a Modification list.  
                  *  
                  * Calling slapi_int_modifications2ldapmods() destroyed modlist so  
                  * we don't need to free it.  
                  */  
                 slapi_pblock_get( pb, SLAPI_MODIFY_MODS, (void **)&modv );  
                 modlist = slapi_int_ldapmods2modifications( modv );  
   
                 if ( rs->sr_err < 0 ) {  
                         /*  
                          * A preoperation plugin failure will abort the  
                          * entire operation.  
                          */  
                         Debug(LDAP_DEBUG_TRACE,  
                                 "do_modify: modify preoperation plugin failed.\n",  
                                 0, 0, 0);  
                         if ( ( slapi_pblock_get( op->o_pb, SLAPI_RESULT_CODE,  
                                 (void *)&rs->sr_err ) != 0 ) || rs->sr_err == LDAP_SUCCESS )  
                         {  
                                 rs->sr_err = LDAP_OTHER;  
                         }  
                         slapi_int_free_ldapmods( modv );  
                         modv = NULL;  
                         goto cleanup;  
                 }  
         }  
   
         /*  
          * NB: it is valid for the plugin to return no modifications  
          * (for example, a plugin might store some attributes elsewhere  
          * and remove them from the modification list; if only those  
          * attribute types were included in the modification request,  
          * then slapi_int_ldapmods2modifications() above will return  
          * NULL).  
          *  
          * However, the post-operation plugin should still be   
          * called.  
          */  
 #endif /* defined( LDAP_SLAPI ) */  
   
         /*          /*
          * do the modify if 1 && (2 || 3)           * do the modify if 1 && (2 || 3)
          * 1) there is a modify function implemented in this backend;           * 1) there is a modify function implemented in this backend;
Line 404  fe_op_modify( Operation *op, SlapReply * Line 368  fe_op_modify( Operation *op, SlapReply *
                 if ( !SLAP_SHADOW(op->o_bd) || repl_user )                  if ( !SLAP_SHADOW(op->o_bd) || repl_user )
 #endif  #endif
                 {                  {
                         int update = op->o_bd->be_update_ndn.bv_len;                          int             update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
                         char textbuf[SLAP_TEXT_BUFLEN];                          slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
                         size_t textlen = sizeof textbuf;  
                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };  
   
                         rs->sr_err = slap_mods_check( modlist, update, &rs->sr_text,                          op->o_bd = op_be;
                                 textbuf, textlen, NULL );  
   
                         if( rs->sr_err != LDAP_SUCCESS ) {                          if ( !update ) {
                                 send_ldap_result( op, rs );                                  rs->sr_err = slap_mods_no_user_mod_check( op, modlist,
                                 goto cleanup;                                          &rs->sr_text, textbuf, textlen );
                         }                                  if ( rs->sr_err != LDAP_SUCCESS ) {
   
                         if ( !repl_user ) {  
                                 for( modtail = &modlist;  
                                         *modtail != NULL;  
                                         modtail = &(*modtail)->sml_next )  
                                 {  
                                         /* empty */  
                                 }  
   
                                 rs->sr_err = slap_mods_opattrs( op, modlist, modtail,  
                                         &rs->sr_text, textbuf, textlen, 1 );  
                                 if( rs->sr_err != LDAP_SUCCESS ) {  
                                         send_ldap_result( op, rs );                                          send_ldap_result( op, rs );
                                         goto cleanup;                                          goto cleanup;
                                 }                                  }
Line 438  fe_op_modify( Operation *op, SlapReply * Line 387  fe_op_modify( Operation *op, SlapReply *
                         if ( !repl_user )                          if ( !repl_user )
 #endif  #endif
                         {                          {
                                 /* but we log only the ones not from a replicator user */                                  /* but multimaster slapd logs only the ones 
                                    * not from a replicator user */
                                 cb.sc_next = op->o_callback;                                  cb.sc_next = op->o_callback;
                                 op->o_callback = &cb;                                  op->o_callback = &cb;
                         }                          }
Line 453  fe_op_modify( Operation *op, SlapReply * Line 403  fe_op_modify( Operation *op, SlapReply *
                                 rs->sr_ref = referral_rewrite( defref,                                  rs->sr_ref = referral_rewrite( defref,
                                         NULL, &op->o_req_dn,                                          NULL, &op->o_req_dn,
                                         LDAP_SCOPE_DEFAULT );                                          LDAP_SCOPE_DEFAULT );
                                 if (!rs->sr_ref) rs->sr_ref = defref;                                  if ( rs->sr_ref == NULL ) {
                                           /* FIXME: must duplicate, because
                                            * overlays may muck with it */
                                           rs->sr_ref = defref;
                                   }
                                 rs->sr_err = LDAP_REFERRAL;                                  rs->sr_err = LDAP_REFERRAL;
                                 send_ldap_result( op, rs );                                  send_ldap_result( op, rs );
                                 if (rs->sr_ref != defref) {                                  if ( rs->sr_ref != defref ) {
                                         ber_bvarray_free( rs->sr_ref );                                          ber_bvarray_free( rs->sr_ref );
                                 }                                  }
   
                         } else {                          } else {
                                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,                                  send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                                         "shadow context; no update referral" );                                          "shadow context; no update referral" );
Line 470  fe_op_modify( Operation *op, SlapReply * Line 425  fe_op_modify( Operation *op, SlapReply *
                     "operation not supported within namingContext" );                      "operation not supported within namingContext" );
         }          }
   
 #if defined( LDAP_SLAPI )  cleanup:;
         if ( pb != NULL && slapi_int_call_plugins( op->o_bd,          op->o_bd = bd;
                 SLAPI_PLUGIN_POST_MODIFY_FN, pb ) < 0 )          return rs->sr_err;
         {  }
                 Debug(LDAP_DEBUG_TRACE,  
                         "do_modify: modify postoperation plugins failed.\n", 0, 0, 0);  /*
    * Obsolete constraint checking.
    */
   int
   slap_mods_obsolete_check(
           Operation *op,
           Modifications *ml,
           const char **text,
           char *textbuf,
           size_t textlen )
   {
           if( get_manageDIT( op ) ) return LDAP_SUCCESS;
   
           for ( ; ml != NULL; ml = ml->sml_next ) {
                   if ( is_at_obsolete( ml->sml_desc->ad_type ) &&
                           (( ml->sml_op != LDAP_MOD_REPLACE &&
                                   ml->sml_op != LDAP_MOD_DELETE ) ||
                                           ml->sml_values != NULL ))
                   {
                           /*
                            * attribute is obsolete,
                            * only allow replace/delete with no values
                            */
                           snprintf( textbuf, textlen,
                                   "%s: attribute is obsolete",
                                   ml->sml_type.bv_val );
                           *text = textbuf;
                           return LDAP_CONSTRAINT_VIOLATION;
                   }
         }          }
 #endif /* defined( LDAP_SLAPI ) */  
   
 cleanup:;          return LDAP_SUCCESS;
 #if defined( LDAP_SLAPI )  }
         if ( modv != NULL ) slapi_int_free_ldapmods( modv );  
 #endif  
   
         return rs->sr_err;  /*
    * No-user-modification constraint checking.
    */
   int
   slap_mods_no_user_mod_check(
           Operation *op,
           Modifications *ml,
           const char **text,
           char *textbuf,
           size_t textlen )
   {
           for ( ; ml != NULL; ml = ml->sml_next ) {
                   if ( !is_at_no_user_mod( ml->sml_desc->ad_type ) ) continue;
   
                   if ( get_manageDIT( op ) ) {
                           if ( ml->sml_desc->ad_type->sat_flags & SLAP_AT_MANAGEABLE ) {
                                   ml->sml_flags |= SLAP_MOD_MANAGING;
                                   continue;
                           }
   
                           /* attribute not manageable */
                           snprintf( textbuf, textlen,
                                   "%s: no-user-modification attribute not manageable",
                                   ml->sml_type.bv_val );
   
                   } else {
                           /* user modification disallowed */
                           snprintf( textbuf, textlen,
                                   "%s: no user modification allowed",
                                   ml->sml_type.bv_val );
                   }
   
                   *text = textbuf;
                   return LDAP_CONSTRAINT_VIOLATION;
           }
   
           return LDAP_SUCCESS;
   }
   
   int
   slap_mods_no_repl_user_mod_check(
           Operation *op,
           Modifications *ml,
           const char **text,
           char *textbuf,
           size_t textlen )
   {
           Modifications *mods;
           Modifications *modp;
   
           for ( mods = ml; mods != NULL; mods = mods->sml_next ) {
                   assert( mods->sml_op == LDAP_MOD_ADD );
   
                   /* check doesn't already appear */
                   for ( modp = ml; modp != NULL; modp = modp->sml_next ) {
                           if ( mods->sml_desc == modp->sml_desc && mods != modp ) {
                                   snprintf( textbuf, textlen,
                                           "attribute '%s' provided more than once",
                                           mods->sml_desc->ad_cname.bv_val );
                                   *text = textbuf;
                                   return LDAP_TYPE_OR_VALUE_EXISTS;
                           }
                   }
           }
   
           return LDAP_SUCCESS;
 }  }
   
 /*  /*
Line 492  cleanup:; Line 537  cleanup:;
  */   */
 int slap_mods_check(  int slap_mods_check(
         Modifications *ml,          Modifications *ml,
         int update,  
         const char **text,          const char **text,
         char *textbuf,          char *textbuf,
         size_t textlen,          size_t textlen,
Line 504  int slap_mods_check( Line 548  int slap_mods_check(
                 AttributeDescription *ad = NULL;                  AttributeDescription *ad = NULL;
   
                 /* convert to attribute description */                  /* convert to attribute description */
                 rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );                  if ( ml->sml_desc == NULL ) {
                           rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
                 if( rc != LDAP_SUCCESS ) {                          if( rc != LDAP_SUCCESS ) {
                         snprintf( textbuf, textlen, "%s: %s",                                  snprintf( textbuf, textlen, "%s: %s",
                                 ml->sml_type.bv_val, *text );                                          ml->sml_type.bv_val, *text );
                         *text = textbuf;                                  *text = textbuf;
                         return rc;                                  return rc;
                           }
                 }                  }
   
                 ad = ml->sml_desc;                  ad = ml->sml_desc;
Line 546  int slap_mods_check( Line 591  int slap_mods_check(
                         return LDAP_UNDEFINED_TYPE;                          return LDAP_UNDEFINED_TYPE;
                 }                  }
   
                 if (!update && is_at_no_user_mod( ad->ad_type )) {  #if 0
                         /* user modification disallowed */  
                         snprintf( textbuf, textlen,  
                                 "%s: no user modification allowed",  
                                 ml->sml_type.bv_val );  
                         *text = textbuf;  
                         return LDAP_CONSTRAINT_VIOLATION;  
                 }  
   
                 if ( is_at_obsolete( ad->ad_type ) &&                  if ( is_at_obsolete( ad->ad_type ) &&
                         (( ml->sml_op != LDAP_MOD_REPLACE &&                          (( ml->sml_op != LDAP_MOD_REPLACE &&
                                 ml->sml_op != LDAP_MOD_DELETE ) ||                                  ml->sml_op != LDAP_MOD_DELETE ) ||
Line 570  int slap_mods_check( Line 607  int slap_mods_check(
                         *text = textbuf;                          *text = textbuf;
                         return LDAP_CONSTRAINT_VIOLATION;                          return LDAP_CONSTRAINT_VIOLATION;
                 }                  }
   #endif
   
                 if ( ml->sml_op == LDAP_MOD_INCREMENT &&                  if ( ml->sml_op == LDAP_MOD_INCREMENT &&
 #ifdef SLAPD_REAL_SYNTAX  #ifdef SLAPD_REAL_SYNTAX
Line 611  int slap_mods_check( Line 649  int slap_mods_check(
                          * check that each value is valid per syntax                           * check that each value is valid per syntax
                          *      and pretty if appropriate                           *      and pretty if appropriate
                          */                           */
                         for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {                          for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
                                 struct berval pval;                                  struct berval pval;
                                 if( pretty ) {  
                                   if ( pretty ) {
   #ifdef SLAP_ORDERED_PRETTYNORM
                                           rc = ordered_value_pretty( ad,
                                                   &ml->sml_values[nvals], &pval, ctx );
   #else /* ! SLAP_ORDERED_PRETTYNORM */
                                         rc = pretty( ad->ad_type->sat_syntax,                                          rc = pretty( ad->ad_type->sat_syntax,
                                                 &ml->sml_values[nvals], &pval, ctx );                                                  &ml->sml_values[nvals], &pval, ctx );
   #endif /* ! SLAP_ORDERED_PRETTYNORM */
                                 } else {                                  } else {
   #ifdef SLAP_ORDERED_PRETTYNORM
                                           rc = ordered_value_validate( ad,
                                                   &ml->sml_values[nvals], ml->sml_op );
   #else /* ! SLAP_ORDERED_PRETTYNORM */
                                         rc = validate( ad->ad_type->sat_syntax,                                          rc = validate( ad->ad_type->sat_syntax,
                                                 &ml->sml_values[nvals] );                                                  &ml->sml_values[nvals] );
   #endif /* ! SLAP_ORDERED_PRETTYNORM */
                                 }                                  }
   
                                 if( rc != 0 ) {                                  if( rc != 0 ) {
Line 663  int slap_mods_check( Line 712  int slap_mods_check(
                                 ml->sml_nvalues = ber_memalloc_x(                                  ml->sml_nvalues = ber_memalloc_x(
                                         (nvals+1)*sizeof(struct berval), ctx );                                          (nvals+1)*sizeof(struct berval), ctx );
   
                                 for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {                                  for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) {
   #ifdef SLAP_ORDERED_PRETTYNORM
                                           rc = ordered_value_normalize(
                                                   SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
                                                   ad,
                                                   ad->ad_type->sat_equality,
                                                   &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
   #else /* ! SLAP_ORDERED_PRETTYNORM */
                                         rc = ad->ad_type->sat_equality->smr_normalize(                                          rc = ad->ad_type->sat_equality->smr_normalize(
                                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,                                                  SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
                                                 ad->ad_type->sat_syntax,                                                  ad->ad_type->sat_syntax,
                                                 ad->ad_type->sat_equality,                                                  ad->ad_type->sat_equality,
                                                 &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );                                                  &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx );
                                         if( rc ) {  #endif /* ! SLAP_ORDERED_PRETTYNORM */
                                           if ( rc ) {
                                                 Debug( LDAP_DEBUG_ANY,                                                  Debug( LDAP_DEBUG_ANY,
                                                         "<= str2entry NULL (ssyn_normalize %d)\n",                                                          "<= str2entry NULL (ssyn_normalize %d)\n",
                                                         rc, 0, 0 );                                                          rc, 0, 0 );
Line 681  int slap_mods_check( Line 738  int slap_mods_check(
                                         }                                          }
                                 }                                  }
   
                                 ml->sml_nvalues[nvals].bv_val = NULL;                                  BER_BVZERO( &ml->sml_nvalues[nvals] );
                                 ml->sml_nvalues[nvals].bv_len = 0;  
                         }                          }
   
                         if( nvals ) {                          /* check for duplicates, but ignore Deletes.
                                 /* check for duplicates */                           */
                                 int             i, j;                          if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) {
                                   int             i, j, rc, match;
                                 MatchingRule *mr = ad->ad_type->sat_equality;                                  MatchingRule *mr = ad->ad_type->sat_equality;
   
                                 /* check if the values we're adding already exist */                                  for ( i = 1; i < nvals ; i++ ) {
                                 if( mr == NULL || !mr->smr_match ) {                                          /* test asserted values against themselves */
                                         for ( i = 1; ml->sml_values[i].bv_val != NULL; i++ ) {                                          for( j = 0; j < i; j++ ) {
                                                 /* test asserted values against themselves */                                                  rc = ordered_value_match( &match, ml->sml_desc, mr,
                                                 for( j = 0; j < i; j++ ) {                                                          SLAP_MR_EQUALITY
                                                         if ( bvmatch( &ml->sml_values[i],                                                                  | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
                                                                 &ml->sml_values[j] ) )                                                                  | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
                                                         {                                                                  | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
                                                                 /* value exists already */                                                          ml->sml_nvalues
                                                                 snprintf( textbuf, textlen,                                                                  ? &ml->sml_nvalues[i]
                                                                         "%s: value #%d provided more than once",                                                                  : &ml->sml_values[i],
                                                                         ml->sml_desc->ad_cname.bv_val, j );                                                          ml->sml_nvalues
                                                                 *text = textbuf;                                                                  ? &ml->sml_nvalues[j]
                                                                 return LDAP_TYPE_OR_VALUE_EXISTS;                                                                  : &ml->sml_values[j],
                                                         }                                                          text );
                                                 }                                                  if ( rc == LDAP_SUCCESS && match == 0 ) {
                                         }                                                          /* value exists already */
                                                           snprintf( textbuf, textlen,
                                 } else {                                                                  "%s: value #%d provided more than once",
                                         int rc;                                                                  ml->sml_desc->ad_cname.bv_val, j );
                                         int match;                                                          *text = textbuf;
                                                           return LDAP_TYPE_OR_VALUE_EXISTS;
   
                                         for ( i = 1; ml->sml_values[i].bv_val != NULL; i++ ) {                                                  } else if ( rc != LDAP_SUCCESS ) {
                                                 /* test asserted values against themselves */                                                          return rc;
                                                 for( j = 0; j < i; j++ ) {  
                                                         rc = value_match( &match, ml->sml_desc, mr,  
                                                                 SLAP_MR_EQUALITY  
                                                                         | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX  
                                                                         | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH  
                                                                         | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,  
                                                                 ml->sml_nvalues  
                                                                         ? &ml->sml_nvalues[i]  
                                                                         : &ml->sml_values[i],  
                                                                 ml->sml_nvalues  
                                                                         ? &ml->sml_nvalues[j]  
                                                                         : &ml->sml_values[j],  
                                                                 text );  
                                                         if ( rc == LDAP_SUCCESS && match == 0 ) {  
                                                                 /* value exists already */  
                                                                 snprintf( textbuf, textlen,  
                                                                         "%s: value #%d provided more than once",  
                                                                         ml->sml_desc->ad_cname.bv_val, j );  
                                                                 *text = textbuf;  
                                                                 return LDAP_TYPE_OR_VALUE_EXISTS;  
   
                                                         } else if ( rc != LDAP_SUCCESS ) {  
                                                                 return rc;  
                                                         }  
                                                 }                                                  }
                                         }                                          }
                                 }                                  }
Line 749  int slap_mods_check( Line 783  int slap_mods_check(
         return LDAP_SUCCESS;          return LDAP_SUCCESS;
 }  }
   
 int slap_mods_opattrs(  /* Enter with bv->bv_len = sizeof buffer, returns with
         Operation *op,   * actual length of string
         Modifications *mods,   */
         Modifications **modtail,  void slap_timestamp( time_t *tm, struct berval *bv )
         const char **text,  
         char *textbuf, size_t textlen,  
         int manage_ctxcsn )  
 {  {
         struct berval name, timestamp, csn;          struct tm *ltm;
         struct berval nname;  
         char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];  
         char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];  
         Modifications *mod;  
   
         int mop = op->o_tag == LDAP_REQ_ADD  
                 ? LDAP_MOD_ADD : LDAP_MOD_REPLACE;  
   
         assert( modtail != NULL );  
         assert( *modtail == NULL );  
   
         if ( SLAP_LASTMOD( op->o_bd )) {  
                 struct tm *ltm;  
 #ifdef HAVE_GMTIME_R  #ifdef HAVE_GMTIME_R
                 struct tm ltm_buf;          struct tm ltm_buf;
 #endif  
                 time_t now = slap_get_time();  
   
 #ifdef HAVE_GMTIME_R          ltm = gmtime_r( tm, &ltm_buf );
                 ltm = gmtime_r( &now, &ltm_buf );  
 #else  #else
                 ldap_pvt_thread_mutex_lock( &gmtime_mutex );          ldap_pvt_thread_mutex_lock( &gmtime_mutex );
                 ltm = gmtime( &now );          ltm = gmtime( tm );
 #endif /* HAVE_GMTIME_R */  #endif
                 lutil_gentime( timebuf, sizeof(timebuf), ltm );  
   
                 slap_get_csn( op, csnbuf, sizeof(csnbuf), &csn, manage_ctxcsn );          bv->bv_len = lutil_gentime( bv->bv_val, bv->bv_len, ltm );
   
 #ifndef HAVE_GMTIME_R  #ifndef HAVE_GMTIME_R
                 ldap_pvt_thread_mutex_unlock( &gmtime_mutex );          ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
 #endif  #endif
   }
   
   /* Called for all modify and modrdn ops. If the current op was replicated
    * from elsewhere, all of the attrs should already be present.
    */
   void slap_mods_opattrs(
           Operation *op,
           Modifications **modsp,
           int manage_ctxcsn )
   {
           struct berval name, timestamp, csn = BER_BVNULL;
           struct berval nname;
           char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
           char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
           Modifications *mod, **modtail, *modlast;
           int gotcsn = 0, gotmname = 0, gotmtime = 0;
   
           if ( SLAP_LASTMOD( op->o_bd ) ) {
                   char *ptr;
                 timestamp.bv_val = timebuf;                  timestamp.bv_val = timebuf;
                 timestamp.bv_len = strlen(timebuf);                  for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
                           if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
                                   (*modtail)->sml_op != LDAP_MOD_REPLACE ) continue;
                           if ( (*modtail)->sml_desc == slap_schema.si_ad_entryCSN ) {
                                   csn = (*modtail)->sml_values[0];
                                   gotcsn = 1;
                           } else
                           if ( (*modtail)->sml_desc == slap_schema.si_ad_modifiersName ) {
                                   gotmname = 1;
                           } else
                           if ( (*modtail)->sml_desc == slap_schema.si_ad_modifyTimestamp ) {
                                   gotmtime = 1;
                           }
                   }
                   if ( BER_BVISEMPTY( &op->o_csn )) {
                           if ( !gotcsn ) {
                                   csn.bv_val = csnbuf;
                                   csn.bv_len = sizeof( csnbuf );
                                   slap_get_csn( op, &csn, manage_ctxcsn );
                           } else {
                                   if ( manage_ctxcsn )
                                           slap_queue_csn( op, &csn );
                           }
                   } else {
                           csn = op->o_csn;
                   }
                   ptr = ber_bvchr( &csn, '#' );
                   if ( ptr && ptr < &csn.bv_val[csn.bv_len] ) {
                           timestamp.bv_len = ptr - csn.bv_val;
                           if ( timestamp.bv_len >= sizeof( timebuf ))
                                   timestamp.bv_len = sizeof( timebuf ) - 1;
                           strncpy( timebuf, csn.bv_val, timestamp.bv_len );
                           timebuf[timestamp.bv_len] = '\0';
                   } else {
                           time_t now = slap_get_time();
   
                           timestamp.bv_len = sizeof(timebuf);
   
                 if( op->o_dn.bv_len == 0 ) {                          slap_timestamp( &now, &timestamp );
                   }
   
                   if ( BER_BVISEMPTY( &op->o_dn ) ) {
                         BER_BVSTR( &name, SLAPD_ANONYMOUS );                          BER_BVSTR( &name, SLAPD_ANONYMOUS );
                         nname = name;                          nname = name;
                 } else {                  } else {
                         name = op->o_dn;                          name = op->o_dn;
                         nname = op->o_ndn;                          nname = op->o_ndn;
                 }                  }
         }  
   
         if( op->o_tag == LDAP_REQ_ADD ) {  
                 struct berval tmpval;  
   
                 if( global_schemacheck ) {  
                         int rc = mods_structural_class( mods, &tmpval,  
                                 text, textbuf, textlen );  
                         if( rc != LDAP_SUCCESS ) return rc;  
   
                   if ( !gotcsn ) {
                         mod = (Modifications *) ch_malloc( sizeof( Modifications ) );                          mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
                         mod->sml_op = mop;                          mod->sml_op = LDAP_MOD_REPLACE;
                         mod->sml_type.bv_val = NULL;                          mod->sml_flags = SLAP_MOD_INTERNAL;
                         mod->sml_desc = slap_schema.si_ad_structuralObjectClass;                          mod->sml_next = NULL;
                         mod->sml_values =                          BER_BVZERO( &mod->sml_type );
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );                          mod->sml_desc = slap_schema.si_ad_entryCSN;
                         ber_dupbv( &mod->sml_values[0], &tmpval );                          mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                         mod->sml_values[1].bv_len = 0;                          ber_dupbv( &mod->sml_values[0], &csn );
                         mod->sml_values[1].bv_val = NULL;                          BER_BVZERO( &mod->sml_values[1] );
                         assert( mod->sml_values[0].bv_val );                          assert( !BER_BVISNULL( &mod->sml_values[0] ) );
                         mod->sml_nvalues =                          mod->sml_nvalues = NULL;
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                         ber_dupbv( &mod->sml_nvalues[0], &tmpval );  
                         mod->sml_nvalues[1].bv_len = 0;  
                         mod->sml_nvalues[1].bv_val = NULL;  
                         assert( mod->sml_nvalues[0].bv_val );  
                         *modtail = mod;                          *modtail = mod;
                           modlast = mod;
                         modtail = &mod->sml_next;                          modtail = &mod->sml_next;
                 }                  }
   
                 if ( SLAP_LASTMOD( op->o_bd )) {                  if ( !gotmname ) {
                         char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];  
   
                         tmpval.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );  
                         tmpval.bv_val = uuidbuf;  
                   
                         mod = (Modifications *) ch_malloc( sizeof( Modifications ) );                          mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
                         mod->sml_op = mop;                          mod->sml_op = LDAP_MOD_REPLACE;
                         mod->sml_type.bv_val = NULL;                          mod->sml_flags = SLAP_MOD_INTERNAL;
                         mod->sml_desc = slap_schema.si_ad_entryUUID;                          mod->sml_next = NULL;
                         mod->sml_values =                          BER_BVZERO( &mod->sml_type );
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );                          mod->sml_desc = slap_schema.si_ad_modifiersName;
                         ber_dupbv( &mod->sml_values[0], &tmpval );                          mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                         mod->sml_values[1].bv_len = 0;  
                         mod->sml_values[1].bv_val = NULL;  
                         assert( mod->sml_values[0].bv_val );  
                         mod->sml_nvalues =  
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                         (*mod->sml_desc->ad_type->sat_equality->smr_normalize)(  
                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,  
                                         mod->sml_desc->ad_type->sat_syntax,  
                                         mod->sml_desc->ad_type->sat_equality,  
                                         mod->sml_values, mod->sml_nvalues, NULL );  
                         mod->sml_nvalues[1].bv_len = 0;  
                         mod->sml_nvalues[1].bv_val = NULL;  
                         *modtail = mod;  
                         modtail = &mod->sml_next;  
   
                         mod = (Modifications *) ch_malloc( sizeof( Modifications ) );  
                         mod->sml_op = mop;  
                         mod->sml_type.bv_val = NULL;  
                         mod->sml_desc = slap_schema.si_ad_creatorsName;  
                         mod->sml_values =  
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                         ber_dupbv( &mod->sml_values[0], &name );                          ber_dupbv( &mod->sml_values[0], &name );
                         mod->sml_values[1].bv_len = 0;                          BER_BVZERO( &mod->sml_values[1] );
                         mod->sml_values[1].bv_val = NULL;                          assert( !BER_BVISNULL( &mod->sml_values[0] ) );
                         assert( mod->sml_values[0].bv_val );  
                         mod->sml_nvalues =                          mod->sml_nvalues =
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );                                  (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                         ber_dupbv( &mod->sml_nvalues[0], &nname );                          ber_dupbv( &mod->sml_nvalues[0], &nname );
                         mod->sml_nvalues[1].bv_len = 0;                          BER_BVZERO( &mod->sml_nvalues[1] );
                         mod->sml_nvalues[1].bv_val = NULL;                          assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) );
                         assert( mod->sml_nvalues[0].bv_val );  
                         *modtail = mod;                          *modtail = mod;
                         modtail = &mod->sml_next;                          modtail = &mod->sml_next;
                   }
   
                   if ( !gotmtime ) {
                         mod = (Modifications *) ch_malloc( sizeof( Modifications ) );                          mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
                         mod->sml_op = mop;                          mod->sml_op = LDAP_MOD_REPLACE;
                         mod->sml_type.bv_val = NULL;                          mod->sml_flags = SLAP_MOD_INTERNAL;
                         mod->sml_desc = slap_schema.si_ad_createTimestamp;                          mod->sml_next = NULL;
                         mod->sml_values =                          BER_BVZERO( &mod->sml_type );
                                 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );                          mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
                           mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
                         ber_dupbv( &mod->sml_values[0], &timestamp );                          ber_dupbv( &mod->sml_values[0], &timestamp );
                         mod->sml_values[1].bv_len = 0;                          BER_BVZERO( &mod->sml_values[1] );
                         mod->sml_values[1].bv_val = NULL;                          assert( !BER_BVISNULL( &mod->sml_values[0] ) );
                         assert( mod->sml_values[0].bv_val );  
                         mod->sml_nvalues = NULL;                          mod->sml_nvalues = NULL;
                         *modtail = mod;                          *modtail = mod;
                         modtail = &mod->sml_next;                          modtail = &mod->sml_next;
                 }                  }
         }          }
   
         if ( SLAP_LASTMOD( op->o_bd )) {  
                 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );  
                 mod->sml_op = mop;  
                 mod->sml_type.bv_val = NULL;  
                 mod->sml_desc = slap_schema.si_ad_entryCSN;  
                 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                 ber_dupbv( &mod->sml_values[0], &csn );  
                 mod->sml_values[1].bv_len = 0;  
                 mod->sml_values[1].bv_val = NULL;  
                 assert( mod->sml_values[0].bv_val );  
                 mod->sml_nvalues = NULL;  
                 *modtail = mod;  
                 modtail = &mod->sml_next;  
   
                 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );  
                 mod->sml_op = mop;  
                 mod->sml_type.bv_val = NULL;  
                 mod->sml_desc = slap_schema.si_ad_modifiersName;  
                 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                 ber_dupbv( &mod->sml_values[0], &name );  
                 mod->sml_values[1].bv_len = 0;  
                 mod->sml_values[1].bv_val = NULL;  
                 assert( mod->sml_values[0].bv_val );  
                 mod->sml_nvalues =  
                         (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                 ber_dupbv( &mod->sml_nvalues[0], &nname );  
                 mod->sml_nvalues[1].bv_len = 0;  
                 mod->sml_nvalues[1].bv_val = NULL;  
                 assert( mod->sml_nvalues[0].bv_val );  
                 *modtail = mod;  
                 modtail = &mod->sml_next;  
   
                 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );  
                 mod->sml_op = mop;  
                 mod->sml_type.bv_val = NULL;  
                 mod->sml_desc = slap_schema.si_ad_modifyTimestamp;  
                 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );  
                 ber_dupbv( &mod->sml_values[0], &timestamp );  
                 mod->sml_values[1].bv_len = 0;  
                 mod->sml_values[1].bv_val = NULL;  
                 assert( mod->sml_values[0].bv_val );  
                 mod->sml_nvalues = NULL;  
                 *modtail = mod;  
                 modtail = &mod->sml_next;  
         }  
   
         *modtail = NULL;  
         return LDAP_SUCCESS;  
 }  }
   

Removed from v.1.227  
changed lines
  Added in v.1.227.2.24


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org