From 1833df239736ea84d1b16cc27ab49710af16d042 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga <kurt@openldap.org> Date: Sun, 28 Jul 2002 21:04:29 +0000 Subject: [PATCH] progname, etc. --- clients/tools/ldapcompare.c | 715 ++++++++++++++++++++++++++++++ clients/tools/ldapdelete.c | 835 +++++++++++++++++++++++++++++++----- clients/tools/ldapmodify.c | 11 +- clients/tools/ldapmodrdn.c | 782 ++++++++++++++++++++++++++++----- clients/tools/ldappasswd.c | 4 +- clients/tools/ldapsearch.c | 15 +- clients/tools/ldapwhoami.c | 4 +- 7 files changed, 2143 insertions(+), 223 deletions(-) create mode 100644 clients/tools/ldapcompare.c diff --git a/clients/tools/ldapcompare.c b/clients/tools/ldapcompare.c new file mode 100644 index 0000000000..3b731f9346 --- /dev/null +++ b/clients/tools/ldapcompare.c @@ -0,0 +1,715 @@ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/ctype.h> +#include <ac/signal.h> +#include <ac/string.h> +#include <ac/unistd.h> +#include <ac/errno.h> +#include <sys/stat.h> + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_IO_H +#include <io.h> +#endif + +#include <ldap.h> + +#include "ldif.h" +#include "lutil.h" +#include "lutil_ldap.h" +#include "ldap_defaults.h" + +static void +usage( const char *s ) +{ + fprintf( stderr, +"usage: %s [options] DN <attr:value|attr::b64value>\n" +"where:\n" +" DN\tDistinguished Name\n" +" attr\tassertion attribute\n" +" value\tassertion value\n" +" b64value\tbase64 encoding of assertion value\n" + +"Common options:\n" +" -d level set LDAP debugging level to `level'\n" +" -D binddn bind DN\n" +" -h host LDAP server\n" +" -H URI LDAP Uniform Resource Indentifier(s)\n" +" -I use SASL Interactive mode\n" +" -k use Kerberos authentication\n" +" -K like -k, but do only step 1 of the Kerberos bind\n" +" -M enable Manage DSA IT control (-MM to make critical)\n" +" -n show what would be done but don't actually compare\n" +" -O props SASL security properties\n" +" -p port port on LDAP server\n" +" -P version procotol version (default: 3)\n" +" -z Quiet mode, don't print anything, use return values\n" +" -Q use SASL Quiet mode\n" +" -R realm SASL realm\n" +" -U authcid SASL authentication identity\n" +" -v run in verbose mode (diagnostics to standard output)\n" +" -w passwd bind passwd (for simple authentication)\n" +" -W prompt for bind passwd\n" +" -x Simple authentication\n" +" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n" +" -Y mech SASL mechanism\n" +" -Z Start TLS request (-ZZ to require successful response)\n" +, s ); + + exit( EXIT_FAILURE ); +} + +static int docompare LDAP_P(( + LDAP *ld, + char *dn, + char *attr, + struct berval *bvalue, + int quiet, + LDAPControl **sctrls, + LDAPControl **cctrls)); + +static char *prog = NULL; +static char *binddn = NULL; +static struct berval passwd = { 0, NULL }; +static char *ldaphost = NULL; +static char *ldapuri = NULL; +static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LDAP_SASL_AUTOMATIC; +static char *sasl_realm = NULL; +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static char *sasl_secprops = NULL; +#endif +static int use_tls = 0; +static int verbose, not; + +int +main( int argc, char **argv ) +{ + char *compdn = NULL, *attrs = NULL; + char *sep; + int rc, i, manageDSAit, quiet; + int referrals, debug; + int authmethod, version, want_bindpw; + LDAP *ld = NULL; + struct berval bvalue = { 0, NULL }; + + debug = verbose = not = referrals = + manageDSAit = want_bindpw = quiet = 0; + + version = -1; + + authmethod = -1; + + prog = lutil_progname( "ldapcompare", argc, argv ); + + while (( i = getopt( argc, argv, + "Cd:D:h:H:IkKMnO:p:P:qQR:U:vw:WxX:Y:zZ")) != EOF ) + { + switch( i ) { + + /* Common Options */ + case 'C': + referrals++; + break; + case 'd': + debug |= atoi( optarg ); + break; + case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n", prog ); + return EXIT_FAILURE; + } + binddn = strdup( optarg ); + break; + case 'h': /* ldap host */ + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -h incompatible with -H\n", prog ); + return EXIT_FAILURE; + } + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n", prog ); + return EXIT_FAILURE; + } + ldaphost = strdup( optarg ); + break; + case 'H': /* ldap URI */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -H incompatible with -h\n", prog ); + return EXIT_FAILURE; + } + if( ldapport ) { + fprintf( stderr, "%s: -H incompatible with -p\n", prog ); + return EXIT_FAILURE; + } + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -H previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapuri = strdup( optarg ); + break; + case 'I': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -I incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_INTERACTIVE; + break; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'k': /* kerberos bind */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + + if( authmethod != -1 ) { + fprintf( stderr, "%s: -k incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV4; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return EXIT_FAILURE; +#endif + break; + case 'K': /* kerberos bind, part one only */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV41; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'M': + /* enable Manage DSA IT */ + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -M incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + manageDSAit++; + version = LDAP_VERSION3; + break; + case 'n': /* print compares, don't actually do them */ + ++not; + break; + case 'O': +#ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapport = atoi( optarg ); + break; + case 'P': + switch( atoi(optarg) ) { + case 2: + if( version == LDAP_VERSION3 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION2; + break; + case 3: + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + break; + default: + fprintf( stderr, "%s: protocol version should be 2 or 3\n", + prog ); + usage( prog ); + return( EXIT_FAILURE ); + } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_QUIET; + break; +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -U incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authc_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'v': /* verbose mode */ + verbose++; + break; + case 'w': /* password */ + passwd.bv_val = strdup( optarg ); + { + char* p; + + for( p = optarg; *p != '\0'; p++ ) { + *p = '\0'; + } + } + passwd.bv_len = strlen( passwd.bv_val ); + break; + case 'W': + want_bindpw++; + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Y incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'x': + if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SIMPLE; + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: -X incompatible with " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authz_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'z': + quiet++; + break; + case 'Z': +#ifdef HAVE_TLS + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Z incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + use_tls++; +#else + fprintf( stderr, "%s: not compiled with TLS support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + default: + fprintf( stderr, "%s: unrecognized option -%c\n", + prog, optopt ); + usage( argv[0] ); + } + } + + if (version == -1) { + version = LDAP_VERSION3; + } + if (authmethod == -1 && version > LDAP_VERSION2) { +#ifdef HAVE_CYRUS_SASL + authmethod = LDAP_AUTH_SASL; +#else + authmethod = LDAP_AUTH_SIMPLE; +#endif + } + + if ( argc - optind != 2 ) { + usage( argv[ 0 ] ); + } + + compdn = argv[optind++]; + attrs = argv[optind++]; + + /* user passed in only 2 args, the last one better be in + * the form attr:value or attr::b64value + */ + sep = strchr(attrs, ':'); + if (!sep) { + usage( argv[ 0 ] ); + } + + *sep++='\0'; + if ( *sep != ':' ) { + bvalue.bv_val = strdup( sep ); + bvalue.bv_len = strlen( bvalue.bv_val ); + + } else { + /* it's base64 encoded. */ + bvalue.bv_val = malloc( strlen( &sep[1] )); + bvalue.bv_len = lutil_b64_pton( &sep[1], + bvalue.bv_val, strlen( &sep[1] )); + + if (bvalue.bv_len == -1) { + fprintf(stderr, "base64 decode error\n"); + exit(-1); + } + } + + if ( debug ) { + if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) + != LBER_OPT_SUCCESS ) + { + fprintf( stderr, + "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); + } + if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) + != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, + "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); + } + ldif_debug = debug; + } + +#ifdef SIGPIPE + (void) SIGNAL( SIGPIPE, SIG_IGN ); +#endif + + if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) { + if ( verbose ) { + fprintf( stderr, "ldap_init( %s, %d )\n", + ldaphost != NULL ? ldaphost : "<DEFAULT>", + ldapport ); + } + + ld = ldap_init( ldaphost, ldapport ); + if( ld == NULL ) { + perror("ldapcompare: ldap_init"); + return EXIT_FAILURE; + } + + } else { + if ( verbose ) { + fprintf( stderr, "ldap_initialize( %s )\n", + ldapuri != NULL ? ldapuri : "<DEFAULT>" ); + } + + rc = ldap_initialize( &ld, ldapuri ); + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "Could not create LDAP session handle (%d): %s\n", + rc, ldap_err2string(rc) ); + return EXIT_FAILURE; + } + } + + + /* referrals */ + if (ldap_set_option( ld, LDAP_OPT_REFERRALS, + referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n", + referrals ? "on" : "off" ); + return EXIT_FAILURE; + } + + if (version == -1 ) { + version = LDAP_VERSION3; + } + + if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) + != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", + version ); + return EXIT_FAILURE; + } + + if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) { + ldap_perror( ld, "ldap_start_tls" ); + if ( use_tls > 1 ) { + return EXIT_FAILURE; + } + } + + if (want_bindpw) { + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; + } + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + void *defaults; + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return EXIT_FAILURE; + } + } + + defaults = lutil_sasl_defaults( ld, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL, + sasl_flags, lutil_sasl_interact, defaults ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); + return EXIT_FAILURE; + } +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog, argv[0] ); + return EXIT_FAILURE; +#endif + } else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return EXIT_FAILURE; + } + } + + if ( manageDSAit ) { + int err; + LDAPControl c; + LDAPControl *ctrls[2]; + ctrls[0] = &c; + ctrls[1] = NULL; + + c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; + c.ldctl_value.bv_val = NULL; + c.ldctl_value.bv_len = 0; + c.ldctl_iscritical = manageDSAit > 1; + + err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); + + if( err != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set ManageDSAit %scontrol\n", + c.ldctl_iscritical ? "critical " : "" ); + if( c.ldctl_iscritical ) { + return EXIT_FAILURE; + } + } + } + + if ( verbose ) { + fprintf( stderr, "DN:%s, attr:%s, value:%s\n", + compdn, attrs, sep ); + } + + rc = docompare( ld, compdn, attrs, &bvalue, quiet, NULL, NULL ); + + free( bvalue.bv_val ); + + ldap_unbind( ld ); + + return rc; +} + + +static int docompare( + LDAP *ld, + char *dn, + char *attr, + struct berval *bvalue, + int quiet, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + int rc; + + if ( not ) { + return LDAP_SUCCESS; + } + + rc = ldap_compare_ext_s( ld, dn, attr, bvalue, + sctrls, cctrls ); + + if ( rc == -1 ) { + ldap_perror( ld, "ldap_result" ); + return( rc ); + } + + /* if we were told to be quiet, use the return value. */ + if ( !quiet ) { + if ( rc == LDAP_COMPARE_TRUE ) { + rc = 0; + printf("TRUE\n"); + } else if ( rc == LDAP_COMPARE_FALSE ) { + rc = 0; + printf("FALSE\n"); + } else { + ldap_perror( ld, "ldap_compare" ); + } + } + + return( rc ); +} + diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index 3054cfb54f..bc04de2b5b 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -1,156 +1,797 @@ /* ldapdelete.c - simple program to delete an entry using LDAP */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" #include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <lber.h> -#include <ldap.h> -#include "ldapconfig.h" +#include <ac/stdlib.h> +#include <ac/ctype.h> -static char *binddn = LDAPDELETE_BINDDN; -static char *base = LDAPDELETE_BASE; -static char *passwd = NULL; -static char *ldaphost = LDAPHOST; -static int ldapport = LDAP_PORT; -static int not, verbose, contoper; -static LDAP *ld; +#include <ac/signal.h> +#include <ac/string.h> +#include <ac/unistd.h> + +#include <ldap.h> +#include "lutil.h" +#include "lutil_ldap.h" +#include "ldap_defaults.h" -#ifdef LDAP_DEBUG -extern int ldap_debug, lber_debug; -#endif /* LDAP_DEBUG */ +static char *prog; +static char *binddn = NULL; +static struct berval passwd = { 0, NULL }; +static char *ldapuri = NULL; +static char *ldaphost = NULL; +static int ldapport = 0; +static int prune = 0; +#ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LDAP_SASL_AUTOMATIC; +static char *sasl_mech = NULL; +static char *sasl_realm = NULL; +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_secprops = NULL; +#endif +static int use_tls = 0; +static int not, verbose, contoper; +static LDAP *ld = NULL; -#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \ - realloc( ptr, size )) +static int dodelete LDAP_P(( + LDAP *ld, + const char *dn)); +static int deletechildren LDAP_P(( + LDAP *ld, + const char *dn )); -main( argc, argv ) - int argc; - char **argv; +static void +usage( const char *s ) { - char *usage = "usage: %s [-n] [-v] [-k] [-d debug-level] [-f file] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n"; - char *p, buf[ 4096 ]; - FILE *fp; - int i, rc, kerberos, linenum, authmethod; + fprintf( stderr, +"Delete entries from an LDAP server\n\n" +"usage: %s [options] [dn]...\n" +" dn: list of DNs to delete. If not given, it will be readed from stdin\n" +" or from the file specified with \"-f file\".\n" +"Delete Options:\n" +" -r delete recursively\n" - extern char *optarg; - extern int optind; +"Common options:\n" +" -d level set LDAP debugging level to `level'\n" +" -D binddn bind DN\n" +" -f file read operations from `file'\n" +" -h host LDAP server\n" +" -H URI LDAP Uniform Resource Indentifier(s)\n" +" -I use SASL Interactive mode\n" +" -k use Kerberos authentication\n" +" -K like -k, but do only step 1 of the Kerberos bind\n" +" -M enable Manage DSA IT control (-MM to make critical)\n" +" -n show what would be done but don't actually do it\n" +" -O props SASL security properties\n" +" -p port port on LDAP server\n" +" -P version procotol version (default: 3)\n" +" -Q use SASL Quiet mode\n" +" -R realm SASL realm\n" +" -U authcid SASL authentication identity\n" +" -v run in verbose mode (diagnostics to standard output)\n" +" -w passwd bind passwd (for simple authentication)\n" +" -W prompt for bind passwd\n" +" -x Simple authentication\n" +" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n" +" -Y mech SASL mechanism\n" +" -Z Start TLS request (-ZZ to require successful response)\n" +, s ); + + exit( EXIT_FAILURE ); +} - kerberos = not = verbose = contoper = 0; + +int +main( int argc, char **argv ) +{ + char buf[ 4096 ]; + FILE *fp; + int i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit; + + not = verbose = contoper = want_bindpw = debug = manageDSAit = referrals = 0; fp = NULL; + authmethod = -1; + version = -1; + + prog = lutil_progname( "ldapdelete", argc, argv ); - while (( i = getopt( argc, argv, "nvkKch:p:D:w:d:f:" )) != EOF ) { + while (( i = getopt( argc, argv, "cf:r" + "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z" )) != EOF ) + { switch( i ) { - case 'k': /* kerberos bind */ - kerberos = 2; - break; - case 'K': /* kerberos bind, part one only */ - kerberos = 1; - break; + /* Delete Specific Options */ case 'c': /* continuous operation mode */ ++contoper; break; - case 'h': /* ldap host */ - ldaphost = strdup( optarg ); - break; - case 'D': /* bind DN */ - binddn = strdup( optarg ); - break; - case 'w': /* password */ - passwd = strdup( optarg ); - break; case 'f': /* read DNs from a file */ + if( fp != NULL ) { + fprintf( stderr, "%s: -f previously specified\n", prog ); + return EXIT_FAILURE; + } if (( fp = fopen( optarg, "r" )) == NULL ) { perror( optarg ); - exit( 1 ); + exit( EXIT_FAILURE ); } break; + case 'r': + prune = 1; + break; + + /* Common Options */ + case 'C': + referrals++; + break; case 'd': -#ifdef LDAP_DEBUG - ldap_debug = lber_debug = atoi( optarg ); /* */ -#else /* LDAP_DEBUG */ - fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" ); -#endif /* LDAP_DEBUG */ + debug |= atoi( optarg ); break; - case 'p': - ldapport = atoi( optarg ); + case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n", prog ); + return EXIT_FAILURE; + } + binddn = strdup( optarg ); break; + case 'h': /* ldap host */ + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -h incompatible with -H\n", prog ); + return EXIT_FAILURE; + } + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n", prog ); + return EXIT_FAILURE; + } + ldaphost = strdup( optarg ); + break; + case 'H': /* ldap URI */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -H incompatible with -h\n", prog ); + return EXIT_FAILURE; + } + if( ldapport ) { + fprintf( stderr, "%s: -H incompatible with -p\n", prog ); + return EXIT_FAILURE; + } + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -H previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapuri = strdup( optarg ); + break; + case 'I': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -I incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_INTERACTIVE; + break; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'k': /* kerberos bind */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + + if( authmethod != -1 ) { + fprintf( stderr, "%s: -k incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV4; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return EXIT_FAILURE; +#endif + break; + case 'K': /* kerberos bind, part one only */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV41; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'M': + /* enable Manage DSA IT */ + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -M incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + manageDSAit++; + version = LDAP_VERSION3; + break; case 'n': /* print deletes, don't actually do them */ ++not; break; + case 'O': +#ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapport = atoi( optarg ); + break; + case 'P': + switch( atoi(optarg) ) { + case 2: + if( version == LDAP_VERSION3 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION2; + break; + case 3: + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + break; + default: + fprintf( stderr, "%s: protocol version should be 2 or 3\n", + prog ); + usage( prog ); + return( EXIT_FAILURE ); + } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_QUIET; + break; +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -U incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authc_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'v': /* verbose mode */ verbose++; break; + case 'w': /* password */ + passwd.bv_val = strdup( optarg ); + { + char* p; + + for( p = optarg; *p != '\0'; p++ ) { + *p = '\0'; + } + } + passwd.bv_len = strlen( passwd.bv_val ); + break; + case 'W': + want_bindpw++; + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Y incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'x': + if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SIMPLE; + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: -X incompatible with " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authz_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Z incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + use_tls++; +#else + fprintf( stderr, "%s: not compiled with TLS support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; default: - fprintf( stderr, usage, argv[0] ); - exit( 1 ); + fprintf( stderr, "%s: unrecognized option -%c\n", + prog, optopt ); + usage( prog ); + return( EXIT_FAILURE ); } } + if (version == -1) { + version = LDAP_VERSION3; + } + if (authmethod == -1 && version > LDAP_VERSION2) { +#ifdef HAVE_CYRUS_SASL + authmethod = LDAP_AUTH_SASL; +#else + authmethod = LDAP_AUTH_SIMPLE; +#endif + } + if ( fp == NULL ) { if ( optind >= argc ) { fp = stdin; } } - if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) { - perror( "ldap_open" ); - exit( 1 ); - } + if ( debug ) { + if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); + } + if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); + } + } - ld->ld_deref = LDAP_DEREF_NEVER; /* prudent, but probably unnecessary */ +#ifdef SIGPIPE + (void) SIGNAL( SIGPIPE, SIG_IGN ); +#endif - if ( !kerberos ) { - authmethod = LDAP_AUTH_SIMPLE; - } else if ( kerberos == 1 ) { - authmethod = LDAP_AUTH_KRBV41; - } else { - authmethod = LDAP_AUTH_KRBV4; - } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - exit( 1 ); - } + if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) { + if ( verbose ) { + fprintf( stderr, "ldap_init( %s, %d )\n", + ldaphost != NULL ? ldaphost : "<DEFAULT>", + ldapport ); + } - if ( fp == NULL ) { - for ( ; optind < argc; ++optind ) { - rc = dodelete( ld, argv[ optind ] ); + ld = ldap_init( ldaphost, ldapport ); + if( ld == NULL ) { + perror("ldapdelete: ldap_init"); + return EXIT_FAILURE; + } + + } else { + if ( verbose ) { + fprintf( stderr, "ldap_initialize( %s )\n", + ldapuri != NULL ? ldapuri : "<DEFAULT>" ); + } + + rc = ldap_initialize( &ld, ldapuri ); + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Could not create LDAP session handle (%d): %s\n", + rc, ldap_err2string(rc) ); + return EXIT_FAILURE; + } + } + + { + /* this seems prudent for searches below */ + int deref = LDAP_DEREF_NEVER; + ldap_set_option( ld, LDAP_OPT_DEREF, &deref ); + } + + /* chase referrals */ + if( ldap_set_option( ld, LDAP_OPT_REFERRALS, + referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n", + referrals ? "on" : "off" ); + return EXIT_FAILURE; } - } else { + + if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) + != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", + version ); + return EXIT_FAILURE; + } + + if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) { + ldap_perror( ld, "ldap_start_tls" ); + if ( use_tls > 1 ) { + return EXIT_FAILURE; + } + } + + if (want_bindpw) { + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; + } + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + void *defaults; + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } + } + + defaults = lutil_sasl_defaults( ld, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL, + sasl_flags, lutil_sasl_interact, defaults ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } + + if ( manageDSAit ) { + int err; + LDAPControl c; + LDAPControl *ctrls[2]; + ctrls[0] = &c; + ctrls[1] = NULL; + + c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; + c.ldctl_value.bv_val = NULL; + c.ldctl_value.bv_len = 0; + c.ldctl_iscritical = manageDSAit > 1; + + err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); + + if( err != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set ManageDSAit %scontrol\n", + c.ldctl_iscritical ? "critical " : "" ); + if( c.ldctl_iscritical ) { + exit( EXIT_FAILURE ); + } + } + } + rc = 0; - while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { - buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */ - if ( *buf != '\0' ) { - rc = dodelete( ld, buf ); - } + + if ( fp == NULL ) { + for ( ; optind < argc; ++optind ) { + rc = dodelete( ld, argv[ optind ] ); + + /* Stop on error and no -c option */ + if( rc != 0 && contoper == 0) break; + } + } else { + while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { + buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */ + + if ( *buf != '\0' ) { + rc = dodelete( ld, buf ); + } + } } - } ldap_unbind( ld ); - exit( rc ); + return( rc ); } -dodelete( ld, dn ) - LDAP *ld; - char *dn; +static int dodelete( + LDAP *ld, + const char *dn) { - int rc; + int id; + int rc, code; + char *matcheddn = NULL, *text = NULL, **refs = NULL; + LDAPMessage *res; - if ( verbose ) { - printf( "%sdeleting entry %s\n", not ? "!" : "", dn ); - } - if ( not ) { - rc = LDAP_SUCCESS; - } else { - if (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_delete" ); - } else if ( verbose ) { - printf( "entry removed\n" ); + if ( verbose ) { + printf( "%sdeleting entry \"%s\"\n", + (not ? "!" : ""), dn ); + } + + if ( not ) { + return LDAP_SUCCESS; + } + + /* If prune is on, remove a whole subtree. Delete the children of the + * DN recursively, then the DN requested. + */ + if ( prune ) deletechildren( ld, dn ); + + rc = ldap_delete_ext( ld, dn, NULL, NULL, &id ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: ldap_delete_ext: %s (%d)\n", + prog, ldap_err2string( rc ), rc ); + return rc; + } + + rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res ); + if ( rc < 0 ) { + ldap_perror( ld, "ldapdelete: ldap_result" ); + return rc; + } + + rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", + prog, ldap_err2string( rc ), rc ); + return rc; + } + + if( verbose || code != LDAP_SUCCESS || + (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) + { + printf( "Delete Result: %s (%d)\n", ldap_err2string( code ), code ); + + if( text && *text ) { + printf( "Additional info: %s\n", text ); + } + + if( matcheddn && *matcheddn ) { + printf( "Matched DN: %s\n", matcheddn ); + } + + if( refs ) { + int i; + for( i=0; refs[i]; i++ ) { + printf("Referral: %s\n", refs[i] ); + } + } + } + + ber_memfree( text ); + ber_memfree( matcheddn ); + ber_memvfree( (void **) refs ); + + return code; +} + +/* + * Delete all the children of an entry recursively until leaf nodes are reached. + * + */ +static int deletechildren( + LDAP *ld, + const char *dn ) +{ + LDAPMessage *res, *e; + int entries; + int rc; + static char *attrs[] = { "1.1", NULL }; + + if ( verbose ) printf ( "deleting children of: %s\n", dn ); + /* + * Do a one level search at dn for children. For each, delete its children. + */ + + rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1, + NULL, NULL, NULL, -1, &res ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search" ); + return( rc ); + } + + entries = ldap_count_entries( ld, res ); + + if ( entries > 0 ) { + int i; + + for (e = ldap_first_entry( ld, res ), i = 0; e != NULL; + e = ldap_next_entry( ld, e ), i++ ) + { + char *dn = ldap_get_dn( ld, e ); + + if( dn == NULL ) { + ldap_perror( ld, "ldap_prune" ); + ldap_get_option( ld, LDAP_OPT_ERROR_NUMBER, &rc ); + ber_memfree( dn ); + return rc; + } + + rc = deletechildren( ld, dn ); + if ( rc == -1 ) { + ldap_perror( ld, "ldap_prune" ); + ber_memfree( dn ); + return rc; + } + + if ( verbose ) { + printf( "\tremoving %s\n", dn ); + } + + rc = ldap_delete_s( ld, dn ); + if ( rc == -1 ) { + ldap_perror( ld, "ldap_delete" ); + ber_memfree( dn ); + return rc; + + } + + if ( verbose ) { + printf( "\t%s removed\n", dn ); + } + + ber_memfree( dn ); + } } - } - return( rc ); + ldap_msgfree( res ); + return rc; } diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index 427952c5fa..ed73a57b29 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -29,6 +29,7 @@ #include <ldap.h> +#include "lutil.h" #include "lutil_ldap.h" #include "ldif.h" #include "ldap_defaults.h" @@ -146,11 +147,7 @@ main( int argc, char **argv ) int rc, i, authmethod, version, want_bindpw, debug, manageDSAit, referrals; int count, len; - if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) { - prog = argv[ 0 ]; - } else { - ++prog; - } + prog = lutil_progname( "ldapmodify", argc, argv ); /* Print usage when no parameters */ if( argc < 2 ) usage( prog ); @@ -582,10 +579,6 @@ main( int argc, char **argv ) (void) SIGNAL( SIGPIPE, SIG_IGN ); #endif -#ifdef NEW_LOGGING - lutil_log_initialize( argc, argv ); -#endif - if ( !not ) { if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) { if ( verbose ) { diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index 69d99e7f5a..b5d2d59283 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -1,144 +1,671 @@ -/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP. + * + * Support for MODIFYDN REQUEST V3 (newSuperior) by: + * + * Copyright 1999, Juan C. Gomez, All rights reserved. + * This software is not subject to any license of Silicon Graphics + * Inc. or Purdue University. + * + * Redistribution and use in source and binary forms are permitted + * without restriction or fee of any kind as long as this notice + * is preserved. + * + */ + +#include "portable.h" #include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <lber.h> -#include <ldap.h> -#include "ldapconfig.h" +#include <ac/stdlib.h> + +#include <ac/ctype.h> +#include <ac/signal.h> +#include <ac/string.h> +#include <ac/unistd.h> + +#include <ldap.h> +#include "lutil.h" +#include "lutil_ldap.h" +#include "ldap_defaults.h" -static char *binddn = LDAPMODRDN_BINDDN; -static char *base = LDAPMODRDN_BASE; -static char *passwd = NULL; -static char *ldaphost = LDAPHOST; -static int ldapport = LDAP_PORT; +static char *prog = NULL; +static char *binddn = NULL; +static struct berval passwd = { 0, NULL }; +static char *ldapuri = NULL; +static char *ldaphost = NULL; +static int ldapport = 0; +#ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LDAP_SASL_AUTOMATIC; +static char *sasl_realm = NULL; +static char *sasl_authc_id = NULL; +static char *sasl_authz_id = NULL; +static char *sasl_mech = NULL; +static char *sasl_secprops = NULL; +#endif +static int use_tls = 0; static int not, verbose, contoper; -static LDAP *ld; +static LDAP *ld = NULL; -#ifdef LDAP_DEBUG -extern int ldap_debug, lber_debug; -#endif /* LDAP_DEBUG */ +static int domodrdn( + LDAP *ld, + char *dn, + char *rdn, + char *newSuperior, + int remove ); /* flag: remove old RDN */ -#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \ - realloc( ptr, size )) +static void +usage( const char *s ) +{ + fprintf( stderr, +"Rename LDAP entries\n\n" +"usage: %s [options] [dn rdn]\n" +" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n" +" If not given, the list of modifications is read from stdin or\n" +" from the file specified by \"-f file\" (see man page).\n" +"Rename options:\n" +" -c continuous operation mode (do not stop on errors)\n" +" -f file read operations from `file'\n" +" -r remove old RDN\n" +" -s newsup new superior entry\n" + +"Common options:\n" +" -d level set LDAP debugging level to `level'\n" +" -D binddn bind DN\n" +" -f file read operations from `file'\n" +" -h host LDAP server\n" +" -H URI LDAP Uniform Resource Indentifier(s)\n" +" -I use SASL Interactive mode\n" +" -k use Kerberos authentication\n" +" -K like -k, but do only step 1 of the Kerberos bind\n" +" -M enable Manage DSA IT control (-MM to make critical)\n" +" -n show what would be done but don't actually update\n" +" -O props SASL security properties\n" +" -p port port on LDAP server\n" +" -P version procotol version (default: 3)\n" +" -Q use SASL Quiet mode\n" +" -R realm SASL realm\n" +" -U authzid SASL authentication identity\n" +" -v run in verbose mode (diagnostics to standard output)\n" +" -w passwd bind passwd (for simple authentication)\n" +" -W prompt for bind passwd\n" +" -x Simple authentication\n" +" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n" +" -Y mech SASL mechanism\n" +" -Z Start TLS request (-ZZ to require successful response)\n" +, s ); + exit( EXIT_FAILURE ); +} -main( argc, argv ) - int argc; - char **argv; +int +main(int argc, char **argv) { - char *usage = "usage: %s [-nvkc] [-d debug-level] [-h ldaphost] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ]\n"; - char *myname,*infile, *p, *entrydn, *rdn, buf[ 4096 ]; + char *infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ]; FILE *fp; - int rc, i, kerberos, remove, havedn, authmethod; - LDAPMod **pmods; - - extern char *optarg; - extern int optind; + int rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit; + int referrals; + char *newSuperior=NULL; infile = NULL; - kerberos = not = contoper = verbose = remove = 0; + not = contoper = verbose = remove = want_bindpw = + debug = manageDSAit = referrals = 0; + authmethod = -1; + version = -1; - myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname; + prog = lutil_progname( "ldapmodrdn", argc, argv ); - while (( i = getopt( argc, argv, "kKcnvrh:p:D:w:d:f:" )) != EOF ) { + while (( i = getopt( argc, argv, "cf:rs:" + "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z" )) != EOF ) + { switch( i ) { - case 'k': /* kerberos bind */ - kerberos = 2; + /* Modrdn Options */ + case 'c': + contoper++; + break; + case 'f': /* read from file */ + if( infile != NULL ) { + fprintf( stderr, "%s: -f previously specified\n", prog ); + return EXIT_FAILURE; + } + infile = strdup( optarg ); break; - case 'K': /* kerberos bind, part one only */ - kerberos = 1; + case 'r': /* remove old RDN */ + remove++; break; - case 'c': /* continuous operation mode */ - ++contoper; + case 's': /* newSuperior */ + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + newSuperior = strdup( optarg ); + version = LDAP_VERSION3; break; - case 'h': /* ldap host */ - ldaphost = strdup( optarg ); + + /* Common Options */ + case 'C': + referrals++; + break; + case 'd': + debug |= atoi( optarg ); break; case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n", prog ); + return EXIT_FAILURE; + } binddn = strdup( optarg ); break; - case 'w': /* password */ - passwd = strdup( optarg ); + case 'h': /* ldap host */ + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -h incompatible with -H\n", prog ); + return EXIT_FAILURE; + } + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n", prog ); + return EXIT_FAILURE; + } + ldaphost = strdup( optarg ); break; - case 'd': -#ifdef LDAP_DEBUG - ldap_debug = lber_debug = atoi( optarg ); /* */ -#else /* LDAP_DEBUG */ - fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" ); -#endif /* LDAP_DEBUG */ + case 'H': /* ldap URI */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -H incompatible with -h\n", prog ); + return EXIT_FAILURE; + } + if( ldapport ) { + fprintf( stderr, "%s: -H incompatible with -p\n", prog ); + return EXIT_FAILURE; + } + if( ldapuri != NULL ) { + fprintf( stderr, "%s: -H previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapuri = strdup( optarg ); break; - case 'f': /* read from file */ - infile = strdup( optarg ); + case 'I': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -I incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_INTERACTIVE; + break; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'k': /* kerberos bind */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + + if( authmethod != -1 ) { + fprintf( stderr, "%s: -k incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV4; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return EXIT_FAILURE; +#endif break; - case 'p': - ldapport = atoi( optarg ); + case 'K': /* kerberos bind, part one only */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV41; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return( EXIT_FAILURE ); +#endif break; - case 'n': /* print adds, don't actually do them */ + case 'M': + /* enable Manage DSA IT */ + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -M incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + manageDSAit++; + version = LDAP_VERSION3; + break; + case 'n': /* print deletes, don't actually do them */ ++not; break; + case 'O': +#ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n", prog ); + return EXIT_FAILURE; + } + ldapport = atoi( optarg ); + break; + case 'P': + switch( atoi(optarg) ) { + case 2: + if( version == LDAP_VERSION3 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION2; + break; + case 3: + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + break; + default: + fprintf( stderr, "%s: protocol version should be 2 or 3\n", + prog ); + usage( prog ); + return( EXIT_FAILURE ); + } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LDAP_SASL_QUIET; + break; +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'U': +#ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -U incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authc_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'v': /* verbose mode */ verbose++; break; - case 'r': /* remove old RDN */ - remove++; + case 'w': /* password */ + passwd.bv_val = strdup( optarg ); + { + char* p; + + for( p = optarg; *p != '\0'; p++ ) { + *p = '\0'; + } + } + passwd.bv_len = strlen( passwd.bv_val ); break; + case 'W': + want_bindpw++; + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Y incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'x': + if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SIMPLE; + break; + case 'X': +#ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n", prog ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: -X incompatible with " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authz_id = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'Z': +#ifdef HAVE_TLS + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Z incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + use_tls++; +#else + fprintf( stderr, "%s: not compiled with TLS support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; default: - fprintf( stderr, usage, argv[0] ); - exit( 1 ); + fprintf( stderr, "%s: unrecognized option -%c\n", + prog, optopt ); + usage( prog ); + return( EXIT_FAILURE ); } } + if (version == -1) { + version = LDAP_VERSION3; + } + if (authmethod == -1 && version > LDAP_VERSION2) { +#ifdef HAVE_CYRUS_SASL + authmethod = LDAP_AUTH_SASL; +#else + authmethod = LDAP_AUTH_SIMPLE; +#endif + } + havedn = 0; if (argc - optind == 2) { if (( rdn = strdup( argv[argc - 1] )) == NULL ) { perror( "strdup" ); - exit( 1 ); + return( EXIT_FAILURE ); } if (( entrydn = strdup( argv[argc - 2] )) == NULL ) { perror( "strdup" ); - exit( 1 ); + return( EXIT_FAILURE ); } ++havedn; } else if ( argc - optind != 0 ) { - fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname); - fprintf( stderr, usage, argv[0] ); - exit( 1 ); + fprintf( stderr, "%s: invalid number of arguments (%d), " + "only two allowed\n", prog, argc-optind ); + usage( prog ); + return( EXIT_FAILURE ); } if ( infile != NULL ) { if (( fp = fopen( infile, "r" )) == NULL ) { perror( infile ); - exit( 1 ); + return( EXIT_FAILURE ); } } else { fp = stdin; } - if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) { - perror( "ldap_open" ); - exit( 1 ); - } + if ( debug ) { + if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); + } + if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); + } + } - ld->ld_deref = LDAP_DEREF_NEVER; /* this seems prudent */ +#ifdef SIGPIPE + (void) SIGNAL( SIGPIPE, SIG_IGN ); +#endif - if ( !kerberos ) { - authmethod = LDAP_AUTH_SIMPLE; - } else if ( kerberos == 1 ) { - authmethod = LDAP_AUTH_KRBV41; - } else { - authmethod = LDAP_AUTH_KRBV4; - } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - exit( 1 ); - } + if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) { + if ( verbose ) { + fprintf( stderr, "ldap_init( %s, %d )\n", + ldaphost != NULL ? ldaphost : "<DEFAULT>", + ldapport ); + } + + ld = ldap_init( ldaphost, ldapport ); + if( ld == NULL ) { + perror("ldapmodify: ldap_init"); + return EXIT_FAILURE; + } + + } else { + if ( verbose ) { + fprintf( stderr, "ldap_initialize( %s )\n", + ldapuri != NULL ? ldapuri : "<DEFAULT>" ); + } + + rc = ldap_initialize( &ld, ldapuri ); + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Could not create LDAP session handle (%d): %s\n", + rc, ldap_err2string(rc) ); + return EXIT_FAILURE; + } + } + + /* referrals */ + if( ldap_set_option( ld, LDAP_OPT_REFERRALS, + referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n", + referrals ? "on" : "off" ); + return EXIT_FAILURE; + } + + if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) + != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", + version ); + return EXIT_FAILURE; + } + + if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) { + ldap_perror( ld, "ldap_start_tls" ); + if ( use_tls > 1 ) { + return( EXIT_FAILURE ); + } + } + + if (want_bindpw) { + passwd.bv_val = getpassphrase("Enter LDAP Password: "); + passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; + } + + if ( authmethod == LDAP_AUTH_SASL ) { +#ifdef HAVE_CYRUS_SASL + void *defaults; + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } + } + + defaults = lutil_sasl_defaults( ld, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL, + sasl_flags, lutil_sasl_interact, defaults ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } + + if ( manageDSAit ) { + int err; + LDAPControl c; + LDAPControl *ctrls[2]; + ctrls[0] = &c; + ctrls[1] = NULL; + + c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; + c.ldctl_value.bv_val = NULL; + c.ldctl_value.bv_len = 0; + c.ldctl_iscritical = manageDSAit > 1; + + err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); + + if( err != LDAP_OPT_SUCCESS ) { + fprintf( stderr, "Could not set ManageDSAit %scontrol\n", + c.ldctl_iscritical ? "critical " : "" ); + if( c.ldctl_iscritical ) { + exit( EXIT_FAILURE ); + } + } + } rc = 0; if (havedn) - rc = domodrdn(ld, entrydn, rdn, remove); + rc = domodrdn( ld, entrydn, rdn, newSuperior, remove ); else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { if ( *buf != '\0' ) { /* blank lines optional, skip */ buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ @@ -146,14 +673,14 @@ main( argc, argv ) if ( havedn ) { /* have DN, get RDN */ if (( rdn = strdup( buf )) == NULL ) { perror( "strdup" ); - exit( 1 ); + return( EXIT_FAILURE ); } - rc = domodrdn(ld, entrydn, rdn, remove); + rc = domodrdn(ld, entrydn, rdn, newSuperior, remove ); havedn = 0; } else if ( !havedn ) { /* don't have DN yet */ if (( entrydn = strdup( buf )) == NULL ) { perror( "strdup" ); - exit( 1 ); + return( EXIT_FAILURE ); } ++havedn; } @@ -162,35 +689,80 @@ main( argc, argv ) ldap_unbind( ld ); - exit( rc ); + /* UNREACHABLE */ + return( rc ); } -domodrdn( ld, dn, rdn, remove ) - LDAP *ld; - char *dn; - char *rdn; - int remove; /* flag: remove old RDN */ +static int domodrdn( + LDAP *ld, + char *dn, + char *rdn, + char *newSuperior, + int remove ) /* flag: remove old RDN */ { - int i; + int rc, code, id; + char *matcheddn=NULL, *text=NULL, **refs=NULL; + LDAPMessage *res; if ( verbose ) { - printf( "modrdn %s:\n\t%s\n", dn, rdn ); - if (remove) - printf("removing old RDN\n"); - else - printf("keeping old RDN\n"); - } + printf( "Renaming \"%s\"\n", dn ); + printf( "\tnew rdn=\"%s\" (%s old rdn)\n", + rdn, remove ? "delete" : "keep" ); + if( newSuperior != NULL ) { + printf("\tnew parent=\"%s\"\n", newSuperior); + } + } + + if( not ) return LDAP_SUCCESS; - if ( !not ) { - i = ldap_modrdn2_s( ld, dn, rdn, remove ); - if ( i != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_modrdn2_s" ); - } else if ( verbose ) { - printf( "modrdn complete\n" ); + rc = ldap_rename( ld, dn, rdn, newSuperior, remove, + NULL, NULL, &id ); + + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: ldap_rename: %s (%d)\n", + prog, ldap_err2string( rc ), rc ); + return rc; } - } else { - i = LDAP_SUCCESS; - } - return( i ); + rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res ); + if ( rc < 0 ) { + ldap_perror( ld, "ldapmodrdn: ldap_result" ); + return rc; + } + + rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 ); + + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", + prog, ldap_err2string( rc ), rc ); + return rc; + } + + if( verbose || code != LDAP_SUCCESS || + (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) + { + printf( "Rename Result: %s (%d)\n", + ldap_err2string( code ), code ); + + if( text && *text ) { + printf( "Additional info: %s\n", text ); + } + + if( matcheddn && *matcheddn ) { + printf( "Matched DN: %s\n", matcheddn ); + } + + if( refs ) { + int i; + for( i=0; refs[i]; i++ ) { + printf("Referral: %s\n", refs[i] ); + } + } + } + + ber_memfree( text ); + ber_memfree( matcheddn ); + ber_memvfree( (void **) refs ); + + return code; } diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 838eb0288e..f78d5ce5c4 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -18,7 +18,7 @@ #include <ac/unistd.h> #include <ldap.h> - +#include "lutil.h" #include "lutil_ldap.h" #include "ldap_defaults.h" @@ -107,7 +107,7 @@ main( int argc, char *argv[] ) char *retoid = NULL; struct berval *retdata = NULL; - prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1; + prog = lutil_progname( "ldappasswd", argc, argv ); while( (i = getopt( argc, argv, "Aa:Ss:" "Cd:D:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF ) diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index 1ab31acdaa..0b3393e3c6 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -167,10 +167,8 @@ urlize(char *url) { char *p; - if (*LDAP_DIRSEP != '/') - { - for (p = url; *p; p++) - { + if (*LDAP_DIRSEP != '/') { + for (p = url; *p; p++) { if (*p == *LDAP_DIRSEP) *p = '/'; } @@ -196,6 +194,8 @@ main( int argc, char **argv ) debug = verbose = not = vals2tmp = referrals = valuesReturnFilter = attrsonly = manageDSAit = ldif = want_bindpw = 0; + prog = lutil_progname( "ldapsearch", argc, argv ); + lutil_log_initialize(argc, argv); deref = sizelimit = timelimit = version = -1; @@ -225,8 +225,6 @@ main( int argc, char **argv ) urlize( def_urlpre ); - prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1; - while (( i = getopt( argc, argv, "Aa:b:E:F:f:Ll:S:s:T:tuz:" "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z")) != EOF ) { @@ -1193,7 +1191,8 @@ print_entry( { int tmpfd; /* write value to file */ - sprintf( tmpfname, "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX", + snprintf( tmpfname, sizeof tmpfname, + "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX", tmpdir, a ); tmpfp = NULL; @@ -1219,7 +1218,7 @@ print_entry( fclose( tmpfp ); - sprintf( url, "%s%s", urlpre, + snprintf( url, sizeof url, "%s%s", urlpre, &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] ); urlize( url ); diff --git a/clients/tools/ldapwhoami.c b/clients/tools/ldapwhoami.c index d69e35faa4..58d926fb34 100644 --- a/clients/tools/ldapwhoami.c +++ b/clients/tools/ldapwhoami.c @@ -18,7 +18,7 @@ #include <ac/unistd.h> #include <ldap.h> - +#include "lutil.h" #include "lutil_ldap.h" #include "ldap_defaults.h" @@ -100,7 +100,7 @@ main( int argc, char *argv[] ) char *retoid = NULL; struct berval *retdata = NULL; - prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1; + prog = lutil_progname( "ldapwhoami", argc, argv ); while( (i = getopt( argc, argv, "Aa:Ss:" "Cd:D:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF ) -- GitLab