Back to index

openldap  2.4.31
modify.c
Go to the documentation of this file.
00001 /* modify.c - ldap backend modify function */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1999-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1999-2003 Howard Chu.
00007  * Portions Copyright 2000-2003 Pierangelo Masarati.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* ACKNOWLEDGEMENTS:
00019  * This work was initially developed by the Howard Chu for inclusion
00020  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00021  * Masarati.
00022  */
00023 
00024 #include "portable.h"
00025 
00026 #include <stdio.h>
00027 
00028 #include <ac/string.h>
00029 #include <ac/socket.h>
00030 
00031 #include "slap.h"
00032 #include "back-ldap.h"
00033 
00034 int
00035 ldap_back_modify(
00036               Operation     *op,
00037               SlapReply     *rs )
00038 {
00039        ldapinfo_t           *li = (ldapinfo_t *)op->o_bd->be_private;
00040 
00041        ldapconn_t           *lc = NULL;
00042        LDAPMod                     **modv = NULL,
00043                             *mods = NULL;
00044        Modifications        *ml;
00045        int                  i, j, rc;
00046        ber_int_t            msgid;
00047        int                  isupdate;
00048        ldap_back_send_t     retrying = LDAP_BACK_RETRYING;
00049        LDAPControl          **ctrls = NULL;
00050 
00051        if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
00052               return rs->sr_err;
00053        }
00054 
00055        for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next )
00056               /* just count mods */ ;
00057 
00058        modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * )
00059                      + i*sizeof( LDAPMod ) );
00060        if ( modv == NULL ) {
00061               rc = LDAP_NO_MEMORY;
00062               goto cleanup;
00063        }
00064        mods = (LDAPMod *)&modv[ i + 1 ];
00065 
00066        isupdate = be_shadow_update( op );
00067        for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) {
00068               if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
00069               {
00070                      continue;
00071               }
00072 
00073               modv[ i ] = &mods[ i ];
00074               mods[ i ].mod_op = ( ml->sml_op | LDAP_MOD_BVALUES );
00075               mods[ i ].mod_type = ml->sml_desc->ad_cname.bv_val;
00076 
00077               if ( ml->sml_values != NULL ) {
00078                      if ( ml->sml_values == NULL ) {    
00079                             continue;
00080                      }
00081 
00082                      for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
00083                             /* just count mods */ ;
00084                      mods[ i ].mod_bvalues =
00085                             (struct berval **)ch_malloc( ( j + 1 )*sizeof( struct berval * ) );
00086                      for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ )
00087                      {
00088                             mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ];
00089                      }
00090                      mods[ i ].mod_bvalues[ j ] = NULL;
00091 
00092               } else {
00093                      mods[ i ].mod_bvalues = NULL;
00094               }
00095 
00096               i++;
00097        }
00098        modv[ i ] = 0;
00099 
00100 retry:;
00101        ctrls = op->o_ctrls;
00102        rc = ldap_back_controls_add( op, rs, lc, &ctrls );
00103        if ( rc != LDAP_SUCCESS ) {
00104               send_ldap_result( op, rs );
00105               rc = -1;
00106               goto cleanup;
00107        }
00108 
00109        rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_dn.bv_val, modv,
00110                      ctrls, NULL, &msgid );
00111        rc = ldap_back_op_result( lc, op, rs, msgid,
00112               li->li_timeout[ SLAP_OP_MODIFY ],
00113               ( LDAP_BACK_SENDRESULT | retrying ) );
00114        if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
00115               retrying &= ~LDAP_BACK_RETRYING;
00116               if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
00117                      /* if the identity changed, there might be need to re-authz */
00118                      (void)ldap_back_controls_free( op, rs, &ctrls );
00119                      goto retry;
00120               }
00121        }
00122 
00123 cleanup:;
00124        (void)ldap_back_controls_free( op, rs, &ctrls );
00125 
00126        for ( i = 0; modv[ i ]; i++ ) {
00127               ch_free( modv[ i ]->mod_bvalues );
00128        }
00129        ch_free( modv );
00130 
00131        if ( lc != NULL ) {
00132               ldap_back_release_conn( li, lc );
00133        }
00134 
00135        return rc;
00136 }
00137