int main( int argc, char **argv ) { char *rbuf = NULL, *rejbuf = NULL; FILE *rejfp; struct LDIFFP *ldiffp, ldifdummy = {0}; char *matched_msg, *error_msg; int rc, retval; int len; int i = 0; int lineno, nextline = 0, lmax = 0; LDAPControl c[1]; prog = lutil_progname( "ldapmodify", argc, argv ); /* strncmp instead of strcmp since NT binaries carry .exe extension */ ldapadd = ( strncasecmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 ); tool_init( ldapadd ? TOOL_ADD : TOOL_MODIFY ); tool_args( argc, argv ); if ( argc != optind ) usage(); if ( rejfile != NULL ) { if (( rejfp = fopen( rejfile, "w" )) == NULL ) { perror( rejfile ); return( EXIT_FAILURE ); } } else { rejfp = NULL; } if ( infile != NULL ) { if (( ldiffp = ldif_open( infile, "r" )) == NULL ) { perror( infile ); return( EXIT_FAILURE ); } } else { ldifdummy.fp = stdin; ldiffp = &ldifdummy; } if ( debug ) ldif_debug = debug; 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: "******"ldap_txn_start_s", rc, NULL, NULL, NULL, NULL ); if( txn > 1 ) return EXIT_FAILURE; txn = 0; } } #endif if ( 0 #ifdef LDAP_X_TXN || txn #endif ) { #ifdef LDAP_X_TXN if( txn ) { c[i].ldctl_oid = LDAP_CONTROL_X_TXN_SPEC; c[i].ldctl_value = *txn_id; c[i].ldctl_iscritical = 1; i++; } #endif } tool_server_controls( ld, c, i ); rc = 0; retval = 0; lineno = 1; while (( rc == 0 || contoper ) && ldif_read_record( ldiffp, &nextline, &rbuf, &lmax )) { if ( rejfp ) { len = strlen( rbuf ); if (( rejbuf = (char *)ber_memalloc( len+1 )) == NULL ) { perror( "malloc" ); exit( EXIT_FAILURE ); } memcpy( rejbuf, rbuf, len+1 ); } rc = process_ldif_rec( rbuf, lineno ); lineno = nextline+1; if ( rc ) retval = rc; if ( rc && rejfp ) { fprintf(rejfp, _("# Error: %s (%d)"), ldap_err2string(rc), rc); matched_msg = NULL; ldap_get_option(ld, LDAP_OPT_MATCHED_DN, &matched_msg); if ( matched_msg != NULL ) { if ( *matched_msg != '\0' ) { fprintf( rejfp, _(", matched DN: %s"), matched_msg ); } ldap_memfree( matched_msg ); } error_msg = NULL; ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &error_msg); if ( error_msg != NULL ) { if ( *error_msg != '\0' ) { fprintf( rejfp, _(", additional info: %s"), error_msg ); } ldap_memfree( error_msg ); } fprintf( rejfp, "\n%s\n", rejbuf ); } if (rejfp) ber_memfree( rejbuf ); } ber_memfree( rbuf ); #ifdef LDAP_X_TXN if( retval == 0 && txn ) { rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL ); if ( rc != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not unset controls for ldap_txn_end\n"); } /* create transaction */ rc = ldap_txn_end_s( ld, !txnabort, txn_id, NULL, NULL, NULL ); if( rc != LDAP_SUCCESS ) { tool_perror( "ldap_txn_end_s", rc, NULL, NULL, NULL, NULL ); retval = rc; } } #endif if ( !dont ) { tool_unbind( ld ); } if ( rejfp != NULL ) { fclose( rejfp ); } tool_destroy(); return( retval ); }
/* * Read the entries specified in fname and merge the attributes * to the user defined baseObject entry. Note that if we find any errors * what so ever, we will discard the entire entries, print an * error message and return. */ static int read_baseObject( BackendDB *be, const char *fname ) { backsql_info *bi = (backsql_info *)be->be_private; LDIFFP *fp; int rc = 0, lmax = 0, ldifrc; unsigned long lineno = 0; char *buf = NULL; assert( fname != NULL ); fp = ldif_open( fname, "r" ); if ( fp == NULL ) { Debug( LDAP_DEBUG_ANY, "could not open back-sql baseObject " "attr file \"%s\" - absolute path?\n", fname, 0, 0 ); perror( fname ); return LDAP_OTHER; } bi->sql_baseObject = entry_alloc(); if ( bi->sql_baseObject == NULL ) { Debug( LDAP_DEBUG_ANY, "read_baseObject_file: entry_alloc failed", 0, 0, 0 ); ldif_close( fp ); return LDAP_NO_MEMORY; } bi->sql_baseObject->e_name = be->be_suffix[0]; bi->sql_baseObject->e_nname = be->be_nsuffix[0]; bi->sql_baseObject->e_attrs = NULL; while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) { Entry *e = str2entry( buf ); Attribute *a; if( e == NULL ) { fprintf( stderr, "back-sql baseObject: " "could not parse entry (line=%lu)\n", lineno ); rc = LDAP_OTHER; break; } /* make sure the DN is the database's suffix */ if ( !be_issuffix( be, &e->e_nname ) ) { fprintf( stderr, "back-sql: invalid baseObject - " "dn=\"%s\" (line=%lu)\n", e->e_name.bv_val, lineno ); entry_free( e ); rc = LDAP_OTHER; break; } /* * we found a valid entry, so walk thru all the attributes in the * entry, and add each attribute type and description to baseObject */ for ( a = e->e_attrs; a != NULL; a = a->a_next ) { if ( attr_merge( bi->sql_baseObject, a->a_desc, a->a_vals, ( a->a_nvals == a->a_vals ) ? NULL : a->a_nvals ) ) { rc = LDAP_OTHER; break; } } entry_free( e ); if ( rc ) { break; } } if ( ldifrc < 0 ) rc = LDAP_OTHER; if ( rc ) { entry_free( bi->sql_baseObject ); bi->sql_baseObject = NULL; } ch_free( buf ); ldif_close( fp ); Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n", fname, 0, 0 ); return rc; }
int slapadd( int argc, char **argv ) { char *buf = NULL; const char *text; char textbuf[SLAP_TEXT_BUFLEN] = { '\0' }; size_t textlen = sizeof textbuf; const char *progname = "slapadd"; struct berval csn; struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ]; unsigned long sid; struct berval bvtext; Attribute *attr; Entry *ctxcsn_e; ID ctxcsn_id, id; OperationBuffer opbuf; Operation *op; int match; int checkvals; int lineno, nextline; int lmax; int rc = EXIT_SUCCESS; int manage = 0; /* default "000" */ csnsid = 0; slap_tool_init( progname, SLAPADD, argc, argv ); memset( &opbuf, 0, sizeof(opbuf) ); op = &opbuf.ob_op; op->o_hdr = &opbuf.ob_hdr; if( !be->be_entry_open || !be->be_entry_close || !be->be_entry_put || (update_ctxcsn && (!be->be_dn2id_get || !be->be_entry_get || !be->be_entry_modify)) ) { fprintf( stderr, "%s: database doesn't support necessary operations.\n", progname ); if ( dryrun ) { fprintf( stderr, "\t(dry) continuing...\n" ); } else { exit( EXIT_FAILURE ); } } checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1; lmax = 0; nextline = 0; /* enforce schema checking unless not disabled */ if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK); } if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) { fprintf( stderr, "%s: could not open database.\n", progname ); exit( EXIT_FAILURE ); } if ( update_ctxcsn ) { maxcsn[ 0 ].bv_val = maxcsnbuf; for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) { maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE; maxcsn[ sid ].bv_len = 0; } } /* nextline is the line number of the end of the current entry */ for( lineno=1; ldif_read_record( ldiffp, &nextline, &buf, &lmax ); lineno=nextline+1 ) { Entry *e; if ( lineno < jumpline ) continue; e = str2entry2( buf, checkvals ); /* * Initialize text buffer */ bvtext.bv_len = textlen; bvtext.bv_val = textbuf; bvtext.bv_val[0] = '\0'; if( e == NULL ) { fprintf( stderr, "%s: could not parse entry (line=%d)\n", progname, lineno ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } /* make sure the DN is not empty */ if( BER_BVISEMPTY( &e->e_nname ) && !BER_BVISEMPTY( be->be_nsuffix )) { fprintf( stderr, "%s: empty dn=\"%s\" (line=%d)\n", progname, e->e_dn, lineno ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } /* check backend */ if( select_backend( &e->e_nname, nosubordinates ) != be ) { fprintf( stderr, "%s: line %d: " "database (%s) not configured to hold \"%s\"\n", progname, lineno, be ? be->be_suffix[0].bv_val : "<none>", e->e_dn ); fprintf( stderr, "%s: line %d: " "database (%s) not configured to hold \"%s\"\n", progname, lineno, be ? be->be_nsuffix[0].bv_val : "<none>", e->e_ndn ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } { Attribute *oc = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); if( oc == NULL ) { fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n", progname, e->e_dn, lineno, "no objectClass attribute"); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } /* check schema */ op->o_bd = be; if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { rc = entry_schema_check( op, e, NULL, manage, 1, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n", progname, e->e_dn, lineno, rc, text ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } textbuf[ 0 ] = '\0'; } } if ( SLAP_LASTMOD(be) ) { time_t now = slap_get_time(); char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; struct berval vals[ 2 ]; struct berval name, timestamp; struct berval nvals[ 2 ]; struct berval nname; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; vals[1].bv_len = 0; vals[1].bv_val = NULL; nvals[1].bv_len = 0; nvals[1].bv_val = NULL; csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 ); csn.bv_val = csnbuf; timestamp.bv_val = timebuf; timestamp.bv_len = sizeof(timebuf); slap_timestamp( &now, ×tamp ); if ( BER_BVISEMPTY( &be->be_rootndn ) ) { BER_BVSTR( &name, SLAPD_ANONYMOUS ); nname = name; } else { name = be->be_rootdn; nname = be->be_rootndn; } if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID ) == NULL ) { 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 ); } if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName ) == NULL ) { vals[0] = name; nvals[0] = nname; attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals ); } if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp ) == NULL ) { vals[0] = timestamp; attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL ); } if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN ) == NULL ) { vals[0] = csn; attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL ); } if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName ) == NULL ) { vals[0] = name; nvals[0] = nname; attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals ); } if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp ) == NULL ) { vals[0] = timestamp; attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL ); } if ( update_ctxcsn ) { int rc_sid; attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN ); assert( attr != NULL ); rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] ); if ( rc_sid < 0 ) { Debug( LDAP_DEBUG_ANY, "%s: could not " "extract SID from entryCSN=%s\n", progname, attr->a_nvals[ 0 ].bv_val, 0 ); } else { assert( rc_sid <= SLAP_SYNC_SID_MAX ); sid = (unsigned)rc_sid; if ( maxcsn[ sid ].bv_len != 0 ) { match = 0; value_match( &match, slap_schema.si_ad_entryCSN, slap_schema.si_ad_entryCSN->ad_type->sat_ordering, SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, &maxcsn[ sid ], &attr->a_nvals[0], &text ); } else { match = -1; } if ( match < 0 ) { strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val ); maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len; } } } } if ( !dryrun ) { id = be->be_entry_put( be, e, &bvtext ); if( id == NOID ) { fprintf( stderr, "%s: could not add entry dn=\"%s\" " "(line=%d): %s\n", progname, e->e_dn, lineno, bvtext.bv_val ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } if ( verbose ) fprintf( stderr, "added: \"%s\" (%08lx)\n", e->e_dn, (long) id ); } else { if ( verbose ) fprintf( stderr, "added: \"%s\"\n", e->e_dn ); } entry_free( e ); } bvtext.bv_len = textlen; bvtext.bv_val = textbuf; bvtext.bv_val[0] = '\0'; if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) { ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix ); if ( ctxcsn_id == NOID ) { fprintf( stderr, "%s: context entry is missing\n", progname ); rc = EXIT_FAILURE; } else { ctxcsn_e = be->be_entry_get( be, ctxcsn_id ); if ( ctxcsn_e != NULL ) { Entry *e = entry_dup( ctxcsn_e ); int change; attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN ); if ( attr ) { int i; change = 0; for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) { int rc_sid; rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] ); if ( rc_sid < 0 ) { Debug( LDAP_DEBUG_ANY, "%s: unable to extract SID " "from #%d contextCSN=%s\n", progname, i, attr->a_nvals[ i ].bv_val ); continue; } assert( rc_sid <= SLAP_SYNC_SID_MAX ); sid = (unsigned)rc_sid; if ( maxcsn[ sid ].bv_len == 0 ) { match = -1; } else { value_match( &match, slap_schema.si_ad_entryCSN, slap_schema.si_ad_entryCSN->ad_type->sat_ordering, SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, &maxcsn[ sid ], &attr->a_nvals[i], &text ); } if ( match > 0 ) { change = 1; } else { AC_MEMCPY( maxcsn[ sid ].bv_val, attr->a_nvals[ i ].bv_val, attr->a_nvals[ i ].bv_len ); maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0'; maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len; } } if ( change ) { if ( attr->a_nvals != attr->a_vals ) { ber_bvarray_free( attr->a_nvals ); } attr->a_nvals = NULL; ber_bvarray_free( attr->a_vals ); attr->a_vals = NULL; attr->a_numvals = 0; } } else { change = 1; } if ( change ) { for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) { if ( maxcsn[ sid ].bv_len ) { attr_merge_one( e, slap_schema.si_ad_contextCSN, &maxcsn[ sid], NULL ); } } ctxcsn_id = be->be_entry_modify( be, e, &bvtext ); if( ctxcsn_id == NOID ) { fprintf( stderr, "%s: could not modify ctxcsn\n", progname); rc = EXIT_FAILURE; } else if ( verbose ) { fprintf( stderr, "modified: \"%s\" (%08lx)\n", e->e_dn, (long) ctxcsn_id ); } } entry_free( e ); } } } ch_free( buf ); if ( !dryrun ) { if( be->be_entry_close( be ) ) { rc = EXIT_FAILURE; } if( be->be_sync ) { be->be_sync( be ); } } slap_tool_destroy(); return rc; }