]> git.sur5r.net Git - openldap/blobdiff - clients/tools/ldapdelete.c
ITS#2128, setvbuf is unreliable
[openldap] / clients / tools / ldapdelete.c
index 7be56175c141577b5151736b21a20e31e4df005f..bc9d057dda9af71130307bbf8f2eb6b4a79d3aeb 100644 (file)
@@ -1,7 +1,7 @@
 /* ldapdelete.c - simple program to delete an entry using LDAP */
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -17,6 +17,7 @@
 #include <ac/unistd.h>
 
 #include <ldap.h>
+#include "lutil.h"
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
@@ -61,6 +62,9 @@ usage( const char *s )
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -68,18 +72,19 @@ usage( const char *s )
 "  -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 search\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 user    SASL authentication identity (username)\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 id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
+"  -y file    Read passwd from file\n"
 "  -Y mech    SASL mechanism\n"
 "  -Z         Start TLS request (-ZZ to require successful response)\n"
 ,              s );
@@ -93,26 +98,55 @@ main( int argc, char **argv )
 {
        char            buf[ 4096 ];
        FILE            *fp;
-       int             i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit;
+       int             i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit, noop, crit;
+       char    *pw_file;
+       char    *control, *cvalue;
 
-    not = verbose = contoper = want_bindpw = debug = manageDSAit = referrals = 0;
+    not = verbose = contoper = want_bindpw = debug
+               = manageDSAit = noop = referrals = 0;
     fp = NULL;
     authmethod = -1;
        version = -1;
+       pw_file = NULL;
 
-    prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1;
+    prog = lutil_progname( "ldapdelete", argc, argv );
 
     while (( i = getopt( argc, argv, "cf:r"
-               "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z" )) != EOF )
+               "Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
        {
        switch( i ) {
        /* Delete Specific Options */
        case 'c':       /* continuous operation mode */
            ++contoper;
            break;
+       case 'E': /* delete controls */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               /* should be extended to support comma separated list of
+                *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
+                */
+
+               crit = 0;
+               cvalue = NULL;
+               if( optarg[0] == '!' ) {
+                       crit = 1;
+                       optarg++;
+               }
+
+               control = strdup( optarg );
+               if ( (cvalue = strchr( control, '=' )) != NULL ) {
+                       *cvalue++ = '\0';
+               }
+               fprintf( stderr, "Invalid delete control name: %s\n", control );
+               usage(prog);
+               return EXIT_FAILURE;
        case 'f':       /* read DNs from a file */
                if( fp != NULL ) {
-                       fprintf( stderr, "%s: -f previously specified\n" );
+                       fprintf( stderr, "%s: -f previously specified\n", prog );
                        return EXIT_FAILURE;
                }
            if (( fp = fopen( optarg, "r" )) == NULL ) {
@@ -133,33 +167,91 @@ main( int argc, char **argv )
            break;
        case 'D':       /* bind DN */
                if( binddn != NULL ) {
-                       fprintf( stderr, "%s: -D previously specified\n" );
+                       fprintf( stderr, "%s: -D previously specified\n", prog );
                        return EXIT_FAILURE;
                }
            binddn = strdup( optarg );
            break;
+       case 'e': /* general controls */
+               if( version == LDAP_VERSION2 ) {
+                       fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+                               prog, version );
+                       return EXIT_FAILURE;
+               }
+
+               /* should be extended to support comma separated list of
+                *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
+                */
+
+               crit = 0;
+               cvalue = NULL;
+               if( optarg[0] == '!' ) {
+                       crit = 1;
+                       optarg++;
+               }
+
+               control = strdup( optarg );
+               if ( (cvalue = strchr( control, '=' )) != NULL ) {
+                       *cvalue++ = '\0';
+               }
+
+               if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+                       if( manageDSAit ) {
+                               fprintf( stderr, "manageDSAit control previously specified");
+                               return EXIT_FAILURE;
+                       }
+                       if( cvalue != NULL ) {
+                               fprintf( stderr, "manageDSAit: no control value expected" );
+                               usage(prog);
+                               return EXIT_FAILURE;
+                       }
+
+                       manageDSAit = 1 + crit;
+                       free( control );
+                       break;
+                       
+               } else if ( strcasecmp( control, "noop" ) == 0 ) {
+                       if( noop ) {
+                               fprintf( stderr, "noop control previously specified");
+                               return EXIT_FAILURE;
+                       }
+                       if( cvalue != NULL ) {
+                               fprintf( stderr, "noop: no control value expected" );
+                               usage(prog);
+                               return EXIT_FAILURE;
+                       }
+
+                       noop = 1 + crit;
+                       free( control );
+                       break;
+
+               } else {
+                       fprintf( stderr, "Invalid general control name: %s\n", control );
+                       usage(prog);
+                       return EXIT_FAILURE;
+               }
        case 'h':       /* ldap host */
                if( ldapuri != NULL ) {
-                       fprintf( stderr, "%s: -h incompatible with -H\n" );
+                       fprintf( stderr, "%s: -h incompatible with -H\n", prog );
                        return EXIT_FAILURE;
                }
                if( ldaphost != NULL ) {
-                       fprintf( stderr, "%s: -h previously specified\n" );
+                       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" );
+                       fprintf( stderr, "%s: -H incompatible with -h\n", prog );
                        return EXIT_FAILURE;
                }
                if( ldapport ) {
-                       fprintf( stderr, "%s: -H incompatible with -p\n" );
+                       fprintf( stderr, "%s: -H incompatible with -p\n", prog );
                        return EXIT_FAILURE;
                }
                if( ldapuri != NULL ) {
-                       fprintf( stderr, "%s: -H previously specified\n" );
+                       fprintf( stderr, "%s: -H previously specified\n", prog );
                        return EXIT_FAILURE;
                }
            ldapuri = strdup( optarg );
@@ -241,7 +333,7 @@ main( int argc, char **argv )
        case 'O':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_secprops != NULL ) {
-                       fprintf( stderr, "%s: -O previously specified\n" );
+                       fprintf( stderr, "%s: -O previously specified\n", prog );
                        return EXIT_FAILURE;
                }
                if( version == LDAP_VERSION2 ) {
@@ -265,7 +357,7 @@ main( int argc, char **argv )
                break;
        case 'p':
                if( ldapport ) {
-                       fprintf( stderr, "%s: -p previously specified\n" );
+                       fprintf( stderr, "%s: -p previously specified\n", prog );
                        return EXIT_FAILURE;
                }
            ldapport = atoi( optarg );
@@ -319,7 +411,7 @@ main( int argc, char **argv )
        case 'R':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_realm != NULL ) {
-                       fprintf( stderr, "%s: -R previously specified\n" );
+                       fprintf( stderr, "%s: -R previously specified\n", prog );
                        return EXIT_FAILURE;
                }
                if( version == LDAP_VERSION2 ) {
@@ -345,7 +437,7 @@ main( int argc, char **argv )
        case 'U':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_authc_id != NULL ) {
-                       fprintf( stderr, "%s: -U previously specified\n" );
+                       fprintf( stderr, "%s: -U previously specified\n", prog );
                        return EXIT_FAILURE;
                }
                if( version == LDAP_VERSION2 ) {
@@ -376,7 +468,7 @@ main( int argc, char **argv )
                {
                        char* p;
 
-                       for( p = optarg; *p == '\0'; p++ ) {
+                       for( p = optarg; *p != '\0'; p++ ) {
                                *p = '\0';
                        }
                }
@@ -385,10 +477,13 @@ main( int argc, char **argv )
        case 'W':
                want_bindpw++;
                break;
+       case 'y':
+               pw_file = optarg;
+               break;
        case 'Y':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_mech != NULL ) {
-                       fprintf( stderr, "%s: -Y previously specified\n" );
+                       fprintf( stderr, "%s: -Y previously specified\n", prog );
                        return EXIT_FAILURE;
                }
                if( version == LDAP_VERSION2 ) {
@@ -420,7 +515,7 @@ main( int argc, char **argv )
        case 'X':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_authz_id != NULL ) {
-                       fprintf( stderr, "%s: -X previously specified\n" );
+                       fprintf( stderr, "%s: -X previously specified\n", prog );
                        return EXIT_FAILURE;
                }
                if( version == LDAP_VERSION2 ) {
@@ -458,7 +553,7 @@ main( int argc, char **argv )
 #endif
                break;
        default:
-               fprintf( stderr, "%s: unrecongized option -%c\n",
+               fprintf( stderr, "%s: unrecognized option -%c\n",
                        prog, optopt );
                usage( prog );
                return( EXIT_FAILURE );
@@ -504,7 +599,7 @@ main( int argc, char **argv )
 
                ld = ldap_init( ldaphost, ldapport );
                if( ld == NULL ) {
-                       perror("ldapsearch: ldap_init");
+                       perror("ldapdelete: ldap_init");
                        return EXIT_FAILURE;
                }
 
@@ -545,17 +640,21 @@ main( int argc, char **argv )
                return EXIT_FAILURE;
        }
 
-       if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
+       if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
+               ldap_perror( ld, "ldap_start_tls" );
                if ( use_tls > 1 ) {
-                       ldap_perror( ld, "ldap_start_tls" );
                        return EXIT_FAILURE;
                }
-               fprintf( stderr, "WARNING: could not start TLS\n" );
        }
 
-       if (want_bindpw) {
-               passwd.bv_val = getpassphrase("Enter LDAP Password: ");
-               passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
+       if ( pw_file || want_bindpw ) {
+               if ( pw_file ) {
+                       rc = lutil_get_filed_password( pw_file, &passwd );
+                       if( rc ) return EXIT_FAILURE;
+               } else {
+                       passwd.bv_val = getpassphrase( "Enter LDAP Password: " );
+                       passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
+               }
        }
 
        if ( authmethod == LDAP_AUTH_SASL ) {
@@ -591,7 +690,7 @@ main( int argc, char **argv )
                }
 #else
                fprintf( stderr, "%s: not compiled with SASL support\n",
-                       argv[0] );
+                       prog );
                return( EXIT_FAILURE );
 #endif
        }
@@ -603,42 +702,60 @@ main( int argc, char **argv )
                }
        }
 
-       if ( manageDSAit ) {
-               int err;
-               LDAPControl c;
-               LDAPControl *ctrls[2];
-               ctrls[0] = &c;
-               ctrls[1] = NULL;
+       if ( manageDSAit || noop ) {
+               int err, i = 0;
+               LDAPControl c1, c2;
+               LDAPControl *ctrls[3];
+
+               if ( manageDSAit ) {
+                       ctrls[i++] = &c1;
+                       ctrls[i] = NULL;
+                       c1.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+                       c1.ldctl_value.bv_val = NULL;
+                       c1.ldctl_value.bv_len = 0;
+                       c1.ldctl_iscritical = manageDSAit > 1;
+               }
 
-               c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-               c.ldctl_value.bv_val = NULL;
-               c.ldctl_value.bv_len = 0;
-               c.ldctl_iscritical = manageDSAit > 1;
+               if ( noop ) {
+                       ctrls[i++] = &c2;
+                       ctrls[i] = NULL;
 
+                       c2.ldctl_oid = LDAP_CONTROL_NOOP;
+                       c2.ldctl_value.bv_val = NULL;
+                       c2.ldctl_value.bv_len = 0;
+                       c2.ldctl_iscritical = noop > 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 );
+                       fprintf( stderr, "Could not set %scontrols\n",
+                               (c1.ldctl_iscritical || c2.ldctl_iscritical)
+                               ? "critical " : "" );
+                       if ( c1.ldctl_iscritical && c2.ldctl_iscritical ) {
+                               return EXIT_FAILURE;
                        }
                }
        }
 
        rc = 0;
+
     if ( fp == NULL ) {
-       for ( ; optind < argc; ++optind ) {
-           rc = dodelete( ld, argv[ optind ] );
-       }
-    } 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 );
-           }
+               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 );