/* ldapdiff Copyright (C) 2000-2006 Thomas.Reith@rhoen.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "ldapdiff.h" static int addentry(LDAP *ld,char *dnval,struct s_modentry *smodentry) { LDAPMod **lma; struct s_modentry *psmodentry; struct s_ldifval *psmodentryval; int numval; int rc; int count = 0; int retval = 0; int numattr = 0; psmodentry = smodentry; while(psmodentry != NULL){ numattr++; psmodentry = psmodentry->next; } lma = LDALLOC(numattr + 1,sizeof(LDAPMod*)); psmodentry = smodentry; while(psmodentry != NULL){ lma[count] = LDALLOC(1,sizeof(LDAPMod)); lma[count]->mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES; lma[count]->mod_type = psmodentry->var; numval = 0; psmodentryval = psmodentry->vallist; while(psmodentryval != NULL){ numval++; psmodentryval = psmodentryval->next; } lma[count]->mod_vals.modv_bvals = LDALLOC(numval+1,sizeof(struct berval*)); numval = 0; psmodentryval = psmodentry->vallist; while(psmodentryval != NULL){ lma[count]->mod_vals.modv_bvals[numval] = LDALLOC(1,sizeof(struct berval)); lma[count]->mod_vals.modv_bvals[numval]->bv_val = psmodentryval->val; lma[count]->mod_vals.modv_bvals[numval]->bv_len = psmodentryval->val_len; numval++; psmodentryval = psmodentryval->next; } count++; psmodentry = psmodentry->next; } #ifndef USE_DEPRECATED_API if((rc = ldap_add_ext_s(ld,dnval,lma,NULL,NULL)) != LDAP_SUCCESS){ #else if((rc = ldap_add_s(ld,dnval,lma)) != LDAP_SUCCESS){ #endif ldiflog(LOG1,"error: onlineadd of %s",dnval); ldiflog(LOG1,"ldap_err2string(): %s",ldap_err2string(rc)); retval = 1; } else{ ldiflog(LOG2,"success: add %s",dnval); } numattr = 0; psmodentry = smodentry; while(psmodentry != NULL){ numval = 0; psmodentryval = psmodentry->vallist; while(psmodentryval != NULL){ free(lma[numattr]->mod_vals.modv_bvals[numval]); numval++; psmodentryval = psmodentryval->next; } free(lma[numattr]->mod_vals.modv_bvals); free(lma[numattr]); numattr++; psmodentry = psmodentry->next; } free(lma); return retval; } static int delentry(LDAP *ld,char *dnval) { int rc; int retval = 0; #ifndef USE_DEPRECATED_API if((rc = ldap_delete_ext_s(ld,dnval,NULL,NULL)) != LDAP_SUCCESS){ #else if((rc = ldap_delete_s(ld,dnval)) != LDAP_SUCCESS){ #endif ldiflog(LOG1,"error: onlinedelete of %s",dnval); ldiflog(LOG1,"ldap_err2string(): %s",ldap_err2string(rc)); retval = 1; } else{ ldiflog(LOG2,"success: delete %s",dnval); } return retval; } static int modattr(LDAP *ld,char *dnval,char *var,struct s_ldifval *vallist,int mod_op, char *mod_txt) { LDAPMod **lma; struct s_ldifval *psmodentryval; int rc; int retval = 0; int numval; switch(mod_op){ case LDAP_MOD_REPLACE: /* no break */ case LDAP_MOD_DELETE: /* no break */ case LDAP_MOD_ADD: if(var != NULL){ lma = LDALLOC(2,sizeof(LDAPMod*)); lma[0] = LDALLOC(1,sizeof(LDAPMod)); lma[0]->mod_op = mod_op|LDAP_MOD_BVALUES; lma[0]->mod_type = var; lma[0]->mod_vals.modv_bvals = NULL; if(vallist != NULL){ numval = 0; psmodentryval = vallist; while(psmodentryval != NULL){ numval++; psmodentryval = psmodentryval->next; } lma[0]->mod_vals.modv_bvals = LDALLOC(numval+1,sizeof(struct berval*)); numval = 0; psmodentryval = vallist; while(psmodentryval != NULL){ lma[0]->mod_vals.modv_bvals[numval] = LDALLOC(1,sizeof(struct berval)); lma[0]->mod_vals.modv_bvals[numval]->bv_val = psmodentryval->val; lma[0]->mod_vals.modv_bvals[numval]->bv_len = psmodentryval->val_len; numval++; psmodentryval = psmodentryval->next; } } #ifndef USE_DEPRECATED_API if((rc = ldap_modify_ext_s(ld,dnval,lma,NULL,NULL)) != LDAP_SUCCESS){ #else if((rc = ldap_modify_s(ld,dnval,lma)) != LDAP_SUCCESS){ #endif ldiflog(LOG1,"error: onlinemodify of %s",dnval); psmodentryval = vallist; while(psmodentryval != NULL){ ldiflogval(LOG1," %s: %s",var,psmodentryval->val,psmodentryval->val_len); psmodentryval = psmodentryval->next; } ldiflog(LOG1,"ldap_err2string(): %s",ldap_err2string(rc)); retval = 1; } else{ ldiflog(LOG2,"success: %-7s %s",mod_txt,dnval); psmodentryval = vallist; while(psmodentryval != NULL){ ldiflogval(LOG2," %s: %s",var,psmodentryval->val,psmodentryval->val_len); psmodentryval = psmodentryval->next; } if(vallist == NULL){ ldiflog(LOG2," %s: [no deletion value]",var); } } numval = 0; psmodentryval = vallist; while(psmodentryval != NULL){ free(lma[0]->mod_vals.modv_bvals[numval]); numval++; psmodentryval = psmodentryval->next; } free(lma[0]->mod_vals.modv_bvals); free(lma[0]); free(lma); } break; default: ldiflog(LOG0,"fatal error: file %s line %d",__FILE__,__LINE__); exit(EXITLDERROR); } return retval; } int ldifmodify(LDAP *ld,struct s_mod *smod,struct s_schema *sschema) { struct s_mod *psmod; struct s_modentry *psmodentry; int errcount = 0; int rc = 0; psmod = smod; while(psmod != NULL){ switch(psmod->modtype){ case MODADD: errcount += addentry(ld,psmod->dnval,psmod->attrlist); break; case MODMODIFY: psmodentry = psmod->attrlist; while(psmodentry != NULL){ switch(psmodentry->modtype){ case MODATTRADD: errcount += modattr(ld,psmod->dnval,psmodentry->var,psmodentry->vallist,LDAP_MOD_ADD,"add"); break; case MODATTRREPLACE: errcount += modattr(ld,psmod->dnval,psmodentry->var,psmodentry->vallist,LDAP_MOD_REPLACE,"replace"); break; case MODATTRDELETE: if(ldifschemaequal(sschema,psmodentry->var) == 1){ errcount += modattr(ld,psmod->dnval,psmodentry->var,psmodentry->vallist,LDAP_MOD_DELETE,"delete"); } else{ errcount += modattr(ld,psmod->dnval,psmodentry->var,NULL,LDAP_MOD_DELETE,"delete"); } break; } psmodentry = psmodentry->next; } break; case MODDELETE: errcount += delentry(ld,psmod->dnval); break; } psmod = psmod->next; } ldiflog(LOG1,"write: %10d online transactions failed",errcount); if(errcount > 0){ if(strcmp(ldifgetgconf(CONFONLINEERRFATAL),"yes") == 0){ exit(EXITLDERROR); } rc = 1; } return rc; }