/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2013 The OpenLDAP Foundation.
* Portions Copyright 2006 Howard Chu.
* Portions Copyright 1998-2003 Kurt D. Zeilenga.
* Portions Copyright 1998-2001 Net Boolean Incorporated.
#include "lutil_ldap.h"
#include "ldif.h"
#include "ldap_defaults.h"
-#include "ldap_log.h"
#include "ldap_pvt.h"
#include "lber_pvt.h"
#include "common.h"
-static int ldapadd, force = 0;
+static int ldapadd;
static char *rejfile = NULL;
static LDAP *ld = NULL;
#define M_SEP 0x7f
-/* strings found in replog/LDIF entries (mostly lifted from slurpd/slurp.h) */
+/* strings found in LDIF entries */
static struct berval BV_VERSION = BER_BVC("version");
-static struct berval BV_REPLICA = BER_BVC("replica");
static struct berval BV_DN = BER_BVC("dn");
static struct berval BV_CONTROL = BER_BVC("control");
static struct berval BV_CHANGETYPE = BER_BVC("changetype");
static struct berval BV_MODOPREPLACE = BER_BVC("replace");
static struct berval BV_MODOPDELETE = BER_BVC("delete");
static struct berval BV_MODOPINCREMENT = BER_BVC("increment");
-static struct berval BV_MODSEP = BER_BVC("-");
static struct berval BV_NEWRDN = BER_BVC("newrdn");
static struct berval BV_DELETEOLDRDN = BER_BVC("deleteoldrdn");
static struct berval BV_NEWSUP = BER_BVC("newsuperior");
-#define BVICMP(a,b) ((a)->bv_len != (b)->bv_len ? \
- (a)->bv_len - (b)->bv_len : strcasecmp((a)->bv_val, (b)->bv_val))
+#define BV_CASEMATCH(a, b) \
+ ((a)->bv_len == (b)->bv_len && 0 == strcasecmp((a)->bv_val, (b)->bv_val))
-static int process_ldif_rec LDAP_P(( char *rbuf, int lineno ));
+static int process_ldif_rec LDAP_P(( char *rbuf, unsigned long lineno ));
static int parse_ldif_control LDAP_P(( struct berval *val, LDAPControl ***pctrls ));
static int domodify LDAP_P((
const char *dn,
fprintf( stderr, _("Add or modify options:\n"));
fprintf( stderr, _(" -a add values (%s)\n"),
(ldapadd ? _("default") : _("default is to replace")));
+ fprintf( stderr, _(" -c continuous operation mode (do not stop on errors)\n"));
fprintf( stderr, _(" -E [!]ext=extparam modify extensions"
" (! indicate s criticality)\n"));
+ fprintf( stderr, _(" -f file read operations from `file'\n"));
+ fprintf( stderr, _(" -M enable Manage DSA IT control (-MM to make critical)\n"));
+ fprintf( stderr, _(" -P version protocol version (default: 3)\n"));
#ifdef LDAP_X_TXN
fprintf( stderr,
_(" [!]txn=<commit|abort> (transaction)\n"));
#endif
- fprintf( stderr, _(" -F force all changes records to be used\n"));
fprintf( stderr, _(" -S file write skipped modifications to `file'\n"));
tool_common_usage();
}
-const char options[] = "aE:FrS:"
- "cd:D:e:f:h:H:IkKMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
+const char options[] = "aE:rS:"
+ "cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
int
handle_private_option( int i )
ldapadd = 1;
break;
- case 'F': /* force all changes records to be used */
- force = 1;
- break;
-
case 'r': /* replace (obsolete) */
break;
{
char *rbuf = NULL, *rejbuf = NULL;
FILE *rejfp;
- struct LDIFFP *ldiffp, ldifdummy = {0};
+ struct LDIFFP *ldiffp = NULL, ldifdummy = {0};
char *matched_msg, *error_msg;
- int rc, retval;
+ int rc, retval, ldifrc;
int len;
- int i = 0;
- int lineno, nextline = 0, lmax = 0;
+ int i = 0, lmax = 0;
+ unsigned long lineno, nextline = 0;
LDAPControl c[1];
prog = lutil_progname( "ldapmodify", argc, argv );
if ( rejfile != NULL ) {
if (( rejfp = fopen( rejfile, "w" )) == NULL ) {
perror( rejfile );
- return( EXIT_FAILURE );
+ retval = EXIT_FAILURE;
+ goto fail;
}
} else {
rejfp = NULL;
if ( infile != NULL ) {
if (( ldiffp = ldif_open( infile, "r" )) == NULL ) {
perror( infile );
- return( EXIT_FAILURE );
+ retval = EXIT_FAILURE;
+ goto fail;
}
} else {
ldifdummy.fp = stdin;
ld = tool_conn_setup( dont, 0 );
if ( !dont ) {
- if ( pw_file || want_bindpw ) {
- if ( pw_file ) {
- rc = lutil_get_filed_password( pw_file, &passwd );
- if( rc ) return EXIT_FAILURE;
- } else {
- passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") );
- passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
- }
- }
tool_bind( ld );
}
rc = ldap_txn_start_s( ld, NULL, NULL, &txn_id );
if( rc != LDAP_SUCCESS ) {
tool_perror( "ldap_txn_start_s", rc, NULL, NULL, NULL, NULL );
- if( txn > 1 ) return EXIT_FAILURE;
+ if( txn > 1 ) {
+ retval = EXIT_FAILURE;
+ goto fail;
+ }
txn = 0;
}
}
rc = 0;
retval = 0;
lineno = 1;
- while (( rc == 0 || contoper ) && ldif_read_record( ldiffp, &nextline,
- &rbuf, &lmax ))
+ while (( rc == 0 || contoper ) && ( ldifrc = ldif_read_record( ldiffp, &nextline,
+ &rbuf, &lmax )) > 0 )
{
if ( rejfp ) {
len = strlen( rbuf );
if (( rejbuf = (char *)ber_memalloc( len+1 )) == NULL ) {
perror( "malloc" );
- exit( EXIT_FAILURE );
+ retval = EXIT_FAILURE;
+ goto fail;
}
memcpy( rejbuf, rbuf, len+1 );
}
fprintf( rejfp, "\n%s\n", rejbuf );
}
- if (rejfp) free( rejbuf );
+ if (rejfp) ber_memfree( rejbuf );
}
- free( rbuf );
+ ber_memfree( rbuf );
+
+ if ( ldifrc < 0 )
+ retval = LDAP_OTHER;
#ifdef LDAP_X_TXN
if( retval == 0 && txn ) {
}
#endif
- if ( !dont ) {
- tool_unbind( ld );
- }
-
+fail:;
if ( rejfp != NULL ) {
fclose( rejfp );
}
- tool_destroy();
- return( retval );
+ if ( ldiffp != NULL && ldiffp != &ldifdummy ) {
+ ldif_close( ldiffp );
+ }
+
+ tool_exit( ld, retval );
}
static int
-process_ldif_rec( char *rbuf, int linenum )
+process_ldif_rec( char *rbuf, unsigned long linenum )
{
char *line, *dn, *newrdn, *newsup;
- int rc, modop, replicaport;
+ int rc, modop;
int expect_modop, expect_sep;
int deleteoldrdn;
- int saw_replica, use_record, new_entry, delete_entry, got_all;
+ int new_entry, delete_entry, got_all;
LDAPMod **pmods, *lm = NULL;
int version;
LDAPControl **pctrls;
new_entry = ldapadd;
- rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0;
+ rc = got_all = delete_entry = modop = expect_modop = 0;
expect_sep = 0;
version = 0;
deleteoldrdn = 1;
- use_record = force;
pmods = NULL;
pctrls = NULL;
dn = newrdn = newsup = NULL;
lines = ldif_countlines( rbuf );
btype = ber_memcalloc( 1, (lines+1)*2*sizeof(struct berval)+lines );
+ if ( !btype )
+ return LDAP_NO_MEMORY;
+
vals = btype+lines+1;
freeval = (char *)(vals+lines+1);
i = -1;
}
if ( ( rc = ldif_parse_line2( line, btype+i, vals+i, &freev ) ) < 0 ) {
- fprintf( stderr, _("%s: invalid format (line %d) entry: \"%s\"\n"),
+ fprintf( stderr, _("%s: invalid format (line %lu) entry: \"%s\"\n"),
prog, linenum+i, dn == NULL ? "" : dn );
rc = LDAP_PARAM_ERROR;
- break;
+ goto leave;
}
freeval[i] = freev;
if ( dn == NULL ) {
- if ( !use_record && !BVICMP( btype+i, &BV_REPLICA )) {
- char *p;
- ++saw_replica;
- if (( p = strchr( vals[i].bv_val, ':' )) == NULL ) {
- replicaport = 0;
- } else {
- *p++ = '\0';
- if ( lutil_atoi( &replicaport, p ) != 0 ) {
- fprintf( stderr, _("%s: unable to parse replica port \"%s\" (line %d) entry: \"%s\"\n"),
- prog, p, linenum+i, dn == NULL ? "" : dn );
- rc = LDAP_PARAM_ERROR;
- break;
- }
- }
- if ( ldaphost != NULL &&
- strcasecmp( vals[i].bv_val, ldaphost ) == 0 &&
- replicaport == ldapport )
- {
- use_record = 1;
- }
- } else if ( linenum+i == 1 && !BVICMP( btype+i, &BV_VERSION )) {
+ if ( linenum+i == 1 && BV_CASEMATCH( btype+i, &BV_VERSION )) {
int v;
if( vals[i].bv_len == 0 || lutil_atoi( &v, vals[i].bv_val) != 0 || v != 1 ) {
fprintf( stderr,
- _("%s: invalid version %s, line %d (ignored)\n"),
+ _("%s: invalid version %s, line %lu (ignored)\n"),
prog, vals[i].bv_val, linenum );
}
version++;
- } else if ( !BVICMP( btype+i, &BV_DN )) {
+ } else if ( BV_CASEMATCH( btype+i, &BV_DN )) {
dn = vals[i].bv_val;
idn = i;
- if ( !use_record && saw_replica ) {
- printf(_("%s: skipping change record for entry: %s at line %d\n"),
- prog, dn, linenum+i);
- printf(_("\t(LDAP host/port does not match replica: lines)\n"));
- rc = 0;
- goto leave;
- }
}
/* skip all lines until we see "dn:" */
}
i = idn+1;
/* Check for "control" tag after dn and before changetype. */
- if (!BVICMP( btype+i, &BV_CONTROL)) {
+ if ( BV_CASEMATCH( btype+i, &BV_CONTROL )) {
/* Parse and add it to the list of controls */
rc = parse_ldif_control( vals+i, &pctrls );
if (rc != 0) {
fprintf( stderr,
- _("%s: Error processing %s line, line %d: %s\n"),
+ _("%s: Error processing %s line, line %lu: %s\n"),
prog, BV_CONTROL.bv_val, linenum+i, ldap_err2string(rc) );
}
i++;
if ( i>= lines ) {
short_input:
fprintf( stderr,
- _("%s: Expecting more input after %s line, line %d\n"),
+ _("%s: Expecting more input after %s line, line %lu\n"),
prog, btype[i-1].bv_val, linenum+i );
rc = LDAP_PARAM_ERROR;
}
/* Check for changetype */
- if ( !BVICMP( btype+i, &BV_CHANGETYPE )) {
+ if ( BV_CASEMATCH( btype+i, &BV_CHANGETYPE )) {
#ifdef LIBERAL_CHANGETYPE_MODOP
/* trim trailing spaces (and log warning ...) */
int icnt;
if ( ++icnt != vals[i].bv_len ) {
fprintf( stderr, _("%s: illegal trailing space after"
- " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
+ " \"%s: %s\" trimmed (line %lu, entry \"%s\")\n"),
prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn );
vals[i].bv_val[icnt] = '\0';
}
#endif /* LIBERAL_CHANGETYPE_MODOP */
- if ( BVICMP( vals+i, &BV_MODIFYCT ) == 0 ) {
+ if ( BV_CASEMATCH( vals+i, &BV_MODIFYCT )) {
new_entry = 0;
expect_modop = 1;
- } else if ( BVICMP( vals+i, &BV_ADDCT ) == 0 ) {
+ } else if ( BV_CASEMATCH( vals+i, &BV_ADDCT )) {
new_entry = 1;
modop = LDAP_MOD_ADD;
- } else if ( BVICMP( vals+i, &BV_MODRDNCT ) == 0
- || BVICMP( vals+i, &BV_MODDNCT ) == 0
- || BVICMP( vals+i, &BV_RENAMECT ) == 0)
+ } else if ( BV_CASEMATCH( vals+i, &BV_MODRDNCT )
+ || BV_CASEMATCH( vals+i, &BV_MODDNCT )
+ || BV_CASEMATCH( vals+i, &BV_RENAMECT ))
{
i++;
if ( i >= lines )
goto short_input;
- if ( BVICMP( btype+i, &BV_NEWRDN )) {
+ if ( !BV_CASEMATCH( btype+i, &BV_NEWRDN )) {
fprintf( stderr, _("%s: expecting \"%s:\" but saw"
- " \"%s:\" (line %d, entry \"%s\")\n"),
+ " \"%s:\" (line %lu, entry \"%s\")\n"),
prog, BV_NEWRDN.bv_val, btype[i].bv_val, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
i++;
if ( i >= lines )
goto short_input;
- if ( BVICMP( btype+i, &BV_DELETEOLDRDN )) {
+ if ( !BV_CASEMATCH( btype+i, &BV_DELETEOLDRDN )) {
fprintf( stderr, _("%s: expecting \"%s:\" but saw"
- " \"%s:\" (line %d, entry \"%s\")\n"),
+ " \"%s:\" (line %lu, entry \"%s\")\n"),
prog, BV_DELETEOLDRDN.bv_val, btype[i].bv_val, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
deleteoldrdn = ( vals[i].bv_val[0] == '0' ) ? 0 : 1;
i++;
if ( i < lines ) {
- if ( BVICMP( btype+i, &BV_NEWSUP )) {
+ if ( !BV_CASEMATCH( btype+i, &BV_NEWSUP )) {
fprintf( stderr, _("%s: expecting \"%s:\" but saw"
- " \"%s:\" (line %d, entry \"%s\")\n"),
+ " \"%s:\" (line %lu, entry \"%s\")\n"),
prog, BV_NEWSUP.bv_val, btype[i].bv_val, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
i++;
}
got_all = 1;
- } else if ( BVICMP( vals+i, &BV_DELETECT ) == 0 ) {
+ } else if ( BV_CASEMATCH( vals+i, &BV_DELETECT )) {
got_all = delete_entry = 1;
} else {
fprintf( stderr,
- _("%s: unknown %s \"%s\" (line %d, entry \"%s\")\n"),
+ _("%s: unknown %s \"%s\" (line %lu, entry \"%s\")\n"),
prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
if ( got_all ) {
if ( i < lines ) {
fprintf( stderr,
- _("%s: extra lines at end (line %d, entry \"%s\")\n"),
+ _("%s: extra lines at end (line %lu, entry \"%s\")\n"),
prog, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
/* Make sure all attributes with multiple values are contiguous */
for (; i<lines; i++) {
for (j=i+1; j<lines; j++) {
- if ( !BVICMP( btype+i, btype+j )) {
+ if ( !btype[j].bv_val ) {
+ fprintf( stderr,
+ _("%s: missing attributeDescription (line %lu, entry \"%s\")\n"),
+ prog, linenum+j, dn );
+ rc = LDAP_PARAM_ERROR;
+ goto leave;
+ }
+ if ( BV_CASEMATCH( btype+i, btype+j )) {
nmods--;
/* out of order, move intervening attributes down */
if ( j != i+1 ) {
k = -1;
BER_BVZERO(&bv);
for (i=idn; i<lines; i++) {
- if ( !BVICMP( btype+i, &BV_DN )) {
+ if ( BV_CASEMATCH( btype+i, &BV_DN )) {
fprintf( stderr, _("%s: attributeDescription \"%s\":"
" (possible missing newline"
- " after line %d, entry \"%s\"?)\n"),
+ " after line %lu, entry \"%s\"?)\n"),
prog, btype[i].bv_val, linenum+i - 1, dn );
}
- if ( BVICMP(btype+i,&bv)) {
+ if ( !BV_CASEMATCH( btype+i, &bv )) {
bvl[k++] = NULL;
bv = btype[i];
lm[j].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
if ( ++icnt != vals[i].bv_len ) {
fprintf( stderr, _("%s: illegal trailing space after"
- " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
+ " \"%s: %s\" trimmed (line %lu, entry \"%s\")\n"),
prog, type, vals[i].bv_val, linenum+i, dn );
vals[i].bv_val[icnt] = '\0';
}
expect_modop = 0;
expect_sep = 1;
- if ( BVICMP( btype+i, &BV_MODOPADD ) == 0 ) {
+ if ( BV_CASEMATCH( btype+i, &BV_MODOPADD )) {
modop = LDAP_MOD_ADD;
mops[i] = M_SEP;
nmods--;
- } else if ( BVICMP( btype+i, &BV_MODOPREPLACE ) == 0 ) {
+ } else if ( BV_CASEMATCH( btype+i, &BV_MODOPREPLACE )) {
/* defer handling these since they might have no values.
* Use the BVALUES flag to signal that these were
* deferred. If values are provided later, this
modop = LDAP_MOD_REPLACE;
mops[i] = modop | LDAP_MOD_BVALUES;
btype[i] = vals[i];
- } else if ( BVICMP( btype+i, &BV_MODOPDELETE ) == 0 ) {
+ } else if ( BV_CASEMATCH( btype+i, &BV_MODOPDELETE )) {
modop = LDAP_MOD_DELETE;
mops[i] = modop | LDAP_MOD_BVALUES;
btype[i] = vals[i];
- } else if ( BVICMP( btype+i, &BV_MODOPINCREMENT ) == 0 ) {
+ } else if ( BV_CASEMATCH( btype+i, &BV_MODOPINCREMENT )) {
modop = LDAP_MOD_INCREMENT;
mops[i] = M_SEP;
nmods--;
} else { /* no modify op: invalid LDIF */
fprintf( stderr, _("%s: modify operation type is missing at"
- " line %d, entry \"%s\"\n"),
+ " line %lu, entry \"%s\"\n"),
prog, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
expect_modop = 1;
nmods--;
} else {
- if ( BVICMP( btype+i, &bv )) {
+ if ( !BV_CASEMATCH( btype+i, &bv )) {
fprintf( stderr, _("%s: wrong attributeType at"
- " line %d, entry \"%s\"\n"),
+ " line %lu, entry \"%s\"\n"),
prog, linenum+i, dn );
rc = LDAP_PARAM_ERROR;
goto leave;
/* If prev op was deferred and matches this type,
* clear the flag
*/
- if ( (mops[i-1]&LDAP_MOD_BVALUES) && !BVICMP(btype+i,
- btype+i-1)) {
+ if ( (mops[i-1] & LDAP_MOD_BVALUES)
+ && BV_CASEMATCH( btype+i, btype+i-1 ))
+ {
mops[i-1] = M_SEP;
nmods--;
}
for (j=i+1; j<lines; j++) {
if ( mops[j] == M_SEP || mops[i] != mops[j] )
continue;
- if ( !BVICMP( btype+i, btype+j )) {
+ if ( BV_CASEMATCH( btype+i, btype+j )) {
nmods--;
/* out of order, move intervening attributes down */
if ( j != i+1 ) {
for (i=idn; i<lines; i++) {
if ( mops[i] == M_SEP )
continue;
- if ( mops[i] != mops[i-1] || BVICMP(btype+i,&bv)) {
+ if ( mops[i] != mops[i-1] || !BV_CASEMATCH( btype+i, &bv )) {
bvl[k++] = NULL;
bv = btype[i];
lm[j].mod_op = mops[i] | LDAP_MOD_BVALUES;
char *s, *oidStart;
LDAPControl *newctrl = NULL;
LDAPControl **pctrls = NULL;
- struct berval type, bv;
- int freeval;
+ struct berval type, bv = BER_BVNULL;
+ int freeval = 0;
if (ppctrls) pctrls = *ppctrls;
/* OID should come first. Validate and extract it. */
+ s = bval->bv_val;
if (*s == 0) return ( LDAP_PARAM_ERROR );
oidStart = s;
while (isdigit((unsigned char)*s) || *s == '.') {
tool_perror( newentry ? "ldap_add" : "ldap_modify",
rc, NULL, NULL, NULL, NULL );
goto done;
- } else if ( verbose ) {
- printf( _("modify complete\n") );
}
-
rc = process_response( ld, msgid,
newentry ? LDAP_RES_ADD : LDAP_RES_MODIFY, dn );
+ if ( verbose && rc == LDAP_SUCCESS ) {
+ printf( _("modify complete\n") );
+ }
+
} else {
rc = LDAP_SUCCESS;
}
fprintf( stderr, _("%s: delete failed: %s\n"), prog, dn );
tool_perror( "ldap_delete", rc, NULL, NULL, NULL, NULL );
goto done;
- } else if ( verbose ) {
- printf( _("delete complete") );
}
-
rc = process_response( ld, msgid, LDAP_RES_DELETE, dn );
+ if ( verbose && rc == LDAP_SUCCESS ) {
+ printf( _("delete complete\n") );
+ }
} else {
rc = LDAP_SUCCESS;
}
fprintf( stderr, _("%s: rename failed: %s\n"), prog, dn );
tool_perror( "ldap_rename", rc, NULL, NULL, NULL, NULL );
goto done;
- } else {
- printf( _("rename completed\n") );
}
-
rc = process_response( ld, msgid, LDAP_RES_RENAME, dn );
+ if ( verbose && rc == LDAP_SUCCESS ) {
+ printf( _("rename complete\n") );
+ }
} else {
rc = LDAP_SUCCESS;
}
if ( rc == -1 ) {
ldap_get_option( ld, LDAP_OPT_RESULT_CODE, &rc );
+ tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
return rc;
}
if ( text ) ldap_memfree( text );
if ( matched ) ldap_memfree( matched );
- if ( text ) ber_memvfree( (void **)refs );
+ if ( refs ) ber_memvfree( (void **)refs );
- if ( ctrls != NULL ) {
+ if ( ctrls ) {
tool_print_ctrls( ld, ctrls );
ldap_controls_free( ctrls );
}