X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=clients%2Ftools%2Fldapmodify.c;h=86343417ce105bbf48d86cd471c1256dc143a872;hb=ebfe58344c63a5fd99caf37f72a6acf02e6afc0e;hp=52c8f52aca74a667c0f0d9260fc89eace07b6950;hpb=df8f7cbb9b79be3be9205d116d1dd0b263d6861a;p=openldap diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index 52c8f52aca..86343417ce 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -1,5 +1,6 @@ +/* $OpenLDAP$ */ /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* ldapmodify.c - generic program to modify or add entries using LDAP */ @@ -15,7 +16,9 @@ #include #include +#ifdef HAVE_SYS_STAT_H #include +#endif #ifdef HAVE_SYS_FILE_H #include @@ -35,6 +38,14 @@ static char *binddn = NULL; static char *passwd = NULL; static char *ldaphost = NULL; static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static int sasl_integrity = 0; +static int sasl_privacy = 0; +#endif +static int use_tls = 0; static int new, replace, not, verbose, contoper, force, valsfromfiles; static LDAP *ld; @@ -60,7 +71,7 @@ static LDAP *ld; #define T_NEWSUPSTR "newsuperior" -static void usage LDAP_P(( const char *prog )); +static void usage LDAP_P(( const char *prog )) LDAP_GCCATTR((noreturn)); static int process_ldapmod_rec LDAP_P(( char *rbuf )); static int process_ldif_rec LDAP_P(( char *rbuf, int count )); static void addmodifyop LDAP_P(( LDAPMod ***pmodsp, int modop, char *attr, @@ -75,23 +86,34 @@ static void usage( const char *prog ) { fprintf( stderr, - "Add or modify entries from an LDAP server\n\n" - "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n" - " [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n" - " a - add values (default%s)\n" - " b - read values from files (for binary attributes)\n" - " c - continuous operation\n" - " D - bind DN\n" - " M - enable Manage DSA IT control (-MM for critical)\n" - " d - debug level\n" - " f - read from file\n" - " F - force all changes records to be used\n" - " h - ldap host\n" - " n - print adds, don't actually do them\n" - " p - LDAP port\n" - " r - replace values\n" - " v - verbose mode\n" - " w - password\n" +"Add or modify entries from an LDAP server\n\n" +"usage: %s [options]\n" +" The list of desired operations are read from stdin or from the file\n" +" specified by \"-f file\".\n" +"options:\n" +" -a\t\tadd values (default%s)\n" +" -b\t\tread values from files (for binary attributes)\n" +" -c\t\tcontinuous operation\n" +" -d level\tset LDAP debugging level to `level'\n" +" -D dn\t\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -f file\t\tperform sequence of operations listed in file\n" +" -F\t\tforce all changes records to be used\n" +" -h host\t\tLDAP server\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -k\t\tuse Kerberos authentication\n" +" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" +" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" +" -n\t\tprint adds, don't actually do them\n" +" -p port\t\tport on LDAP server\n" +" -r\t\treplace values\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\tverbose mode\n" +" -w passwd\tbind password (for Simple authentication)\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") ); exit( EXIT_FAILURE ); } @@ -122,7 +144,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) { + while (( i = getopt( argc, argv, "abcD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'a': /* add */ new = 1; @@ -137,20 +159,18 @@ main( int argc, char **argv ) replace = 1; break; case 'k': /* kerberos bind */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; case 'K': /* kerberos bind, part 1 only */ -#ifdef HAVE_KERBEROS +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -209,6 +229,67 @@ main( int argc, char **argv ) usage( argv[0] ); } break; + case 'I': +#ifdef HAVE_CYRUS_SASL + sasl_integrity++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'E': +#ifdef HAVE_CYRUS_SASL + sasl_privacy++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = strdup( optarg ); + } + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = strdup( optarg ); + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage( prog ); } @@ -217,6 +298,38 @@ main( int argc, char **argv ) if ( argc != optind ) usage( prog ); + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION2; + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); + } + version = LDAP_VERSION3; + } + + if( manageDSAit ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "manage DSA control requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + + if( use_tls ) { + if( version != -1 && version != LDAP_VERSION3 ) { + fprintf(stderr, "Start TLS requires LDAPv3\n"); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + } + if ( infile != NULL ) { if (( fp = fopen( infile, "r" )) == NULL ) { perror( infile ); @@ -251,20 +364,71 @@ main( int argc, char **argv ) int deref = LDAP_DEREF_NEVER; ldap_set_option( ld, LDAP_OPT_DEREF, &deref); } - - if (want_bindpw) - passwd = getpass("Enter LDAP Password: "); + /* don't chase referrals */ + ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); if (version != -1 && ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS) { - fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); + fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION to %d\n", version ); } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } } + + if (want_bindpw) + passwd = getpass("Enter LDAP Password: "); + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + int minssf = 0, maxssf = 0; + + if ( sasl_integrity > 0 ) + maxssf = 1; + if ( sasl_integrity > 1 ) + minssf = 1; + if ( sasl_privacy > 0 ) + maxssf = 100000; /* Something big value */ + if ( sasl_privacy > 1 ) + minssf = 56; + + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, + (void *)&minssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, + (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" + "%d\n", minssf); + return( EXIT_FAILURE ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } + } rc = 0; @@ -300,10 +464,14 @@ main( int argc, char **argv ) * has a colon that appears to the left of any equal signs, OR * if the first line consists entirely of digits (an entry id) */ +#ifdef LDAP_LDIF + use_ldif = 1; +#else use_ldif = ( *rbuf == '#' ) || (( p = strchr( rbuf, ':' )) != NULL && ( q = strchr( rbuf, '\n' )) != NULL && p < q && (( q = strchr( rbuf, '=' )) == NULL || p < q )); +#endif start = rbuf; @@ -354,7 +522,7 @@ process_ldif_rec( char *rbuf, int count ) new_entry = new; - rc = got_all = saw_replica = delete_entry = expect_modop = 0; + rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0; expect_deleteoldrdn = expect_newrdn = expect_newsup = 0; expect_sep = expect_ct = 0; linenum = 0; @@ -389,7 +557,7 @@ process_ldif_rec( char *rbuf, int count ) *p++ = '\0'; replicaport = atoi( p ); } - if ( strcasecmp( value, ldaphost ) == 0 && + if ( ldaphost != NULL && strcasecmp( value, ldaphost ) == 0 && replicaport == ldapport ) { use_record = 1; } @@ -403,21 +571,24 @@ process_ldif_rec( char *rbuf, int count ) version++; } else if ( strcasecmp( type, T_DN_STR ) == 0 ) { - if (( dn = strdup( value )) == NULL ) { + if (( dn = strdup( value ? value : "" )) == NULL ) { perror( "strdup" ); exit( EXIT_FAILURE ); } expect_ct = 1; } - continue; /* skip all lines until we see "dn:" */ + goto end_line; /* skip all lines until we see "dn:" */ } if ( expect_ct ) { expect_ct = 0; if ( !use_record && saw_replica ) { - printf( "%s: skipping change record for entry: %s\n\t(LDAP host/port does not match replica: lines)\n", + printf( "%s: skipping change record for entry: %s\n" + "\t(LDAP host/port does not match replica: lines)\n", prog, dn ); free( dn ); + ber_memfree( type ); + ber_memfree( value ); return( 0 ); } @@ -436,11 +607,11 @@ process_ldif_rec( char *rbuf, int count ) got_all = delete_entry = 1; } else { fprintf( stderr, - "%s: unknown %s \"%s\" (line %d of entry: %s)\n", + "%s: unknown %s \"%s\" (line %d of entry \"%s\")\n", prog, T_CHANGETYPESTR, value, linenum, dn ); rc = LDAP_PARAM_ERROR; } - continue; + goto end_line; } else if ( new ) { /* missing changetype => add */ new_entry = 1; modop = LDAP_MOD_ADD; @@ -454,14 +625,15 @@ process_ldif_rec( char *rbuf, int count ) expect_sep = 1; if ( strcasecmp( type, T_MODOPADDSTR ) == 0 ) { modop = LDAP_MOD_ADD; - continue; + goto end_line; } else if ( strcasecmp( type, T_MODOPREPLACESTR ) == 0 ) { modop = LDAP_MOD_REPLACE; - continue; + addmodifyop( &pmods, modop, value, NULL, 0 ); + goto end_line; } else if ( strcasecmp( type, T_MODOPDELETESTR ) == 0 ) { modop = LDAP_MOD_DELETE; addmodifyop( &pmods, modop, value, NULL, 0 ); - continue; + goto end_line; } else { /* no modify op: use default */ modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD; } @@ -476,7 +648,7 @@ process_ldif_rec( char *rbuf, int count ) expect_deleteoldrdn = 1; expect_newrdn = 0; } else { - fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n", + fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n", prog, T_NEWRDNSTR, type, linenum, dn ); rc = LDAP_PARAM_ERROR; } @@ -487,7 +659,7 @@ process_ldif_rec( char *rbuf, int count ) expect_newsup = 1; got_all = 1; } else { - fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n", + fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n", prog, T_DELETEOLDRDNSTR, type, linenum, dn ); rc = LDAP_PARAM_ERROR; } @@ -499,18 +671,22 @@ process_ldif_rec( char *rbuf, int count ) } expect_newsup = 0; } else { - fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry %s)\n", + fprintf( stderr, "%s: expecting \"%s:\" but saw \"%s:\" (line %d of entry \"%s\")\n", prog, T_NEWSUPSTR, type, linenum, dn ); rc = LDAP_PARAM_ERROR; } } else if ( got_all ) { fprintf( stderr, - "%s: extra lines at end (line %d of entry %s)\n", + "%s: extra lines at end (line %d of entry \"%s\")\n", prog, linenum, dn ); rc = LDAP_PARAM_ERROR; } else { addmodifyop( &pmods, modop, type, value, vlen ); } + +end_line: + ber_memfree( type ); + ber_memfree( value ); } if( linenum == 0 ) { @@ -614,7 +790,7 @@ process_ldapmod_rec( char *rbuf ) } if ( value == NULL && new ) { - fprintf( stderr, "%s: missing value on line %d (attr is %s)\n", + fprintf( stderr, "%s: missing value on line %d (attr=\"%s\")\n", prog, linenum, attr ); rc = LDAP_PARAM_ERROR; } else { @@ -743,7 +919,7 @@ domodify( char *dn, LDAPMod **pmods, int newentry ) struct berval *bvp; if ( pmods == NULL ) { - fprintf( stderr, "%s: no attributes to change or add (entry %s)\n", + fprintf( stderr, "%s: no attributes to change or add (entry=\"%s\")\n", prog, dn ); return( LDAP_PARAM_ERROR ); } @@ -775,9 +951,9 @@ domodify( char *dn, LDAPMod **pmods, int newentry ) } if ( newentry ) { - printf( "%sadding new entry %s\n", not ? "!" : "", dn ); + printf( "%sadding new entry \"%s\"\n", not ? "!" : "", dn ); } else { - printf( "%smodifying entry %s\n", not ? "!" : "", dn ); + printf( "%smodifying entry \"%s\"\n", not ? "!" : "", dn ); } if ( !not ) { @@ -806,7 +982,7 @@ dodelete( char *dn ) { int rc; - printf( "%sdeleting entry %s\n", not ? "!" : "", dn ); + printf( "%sdeleting entry \"%s\"\n", not ? "!" : "", dn ); if ( !not ) { if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_delete" ); @@ -828,12 +1004,12 @@ domodrdn( char *dn, char *newrdn, int deleteoldrdn ) { int rc; + + printf( "%smodifying rdn of entry \"%s\"\n", not ? "!" : "", dn ); if ( verbose ) { - printf( "new RDN: %s (%skeep existing values)\n", + printf( "\tnew RDN: \"%s\" (%skeep existing values)\n", newrdn, deleteoldrdn ? "do not " : "" ); } - - printf( "%smodifying rdn of entry %s\n", not ? "!" : "", dn ); if ( !not ) { if (( rc = ldap_modrdn2_s( ld, dn, newrdn, deleteoldrdn )) != LDAP_SUCCESS ) {