X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=clients%2Ftools%2Fldapsearch.c;h=885bfc36a03669a90722e1637f44fe4c60fee087;hb=d912c2c711b2de7f9ca498aca25bea5627140614;hp=a7d55c44b667f33922fcaf8e5c334c5d36afd290;hpb=b4368db948428698e567c9d2bb94cd060a2a9b58;p=openldap diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index a7d55c44b6..885bfc36a0 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -1,6 +1,6 @@ /* $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 */ @@ -33,6 +33,10 @@ #include "lutil.h" #include "lutil_ldap.h" #include "ldap_defaults.h" +#include "ldap_log.h" + +static char *def_tmpdir; +static char *def_urlpre; static void usage( const char *s ) @@ -50,6 +54,9 @@ usage( const char *s ) " -a deref one of never (default), always, search, or find\n" " -A retrieve attribute names only (no values)\n" " -b basedn base dn for search\n" +" -E [!][=] search controls (! indicates criticality)\n" +" [!]mv= (matched values filter)\n" +" -F prefix URL prefix for files (default: %s)\n" " -l limit time limit (in seconds) for search\n" " -L print responses in LDIFv1 format\n" " -LL print responses in LDIF format without comments\n" @@ -59,15 +66,16 @@ usage( const char *s ) " -S attr sort the results by attribute `attr'\n" " -t write binary values to files in temporary directory\n" " -tt write all values to files in temporary directory\n" -" -T path write files to directory specified by path (default:\n" -" " LDAP_TMPDIR ")\n" +" -T path write files to directory specified by path (default: %s)\n" " -u include User Friendly entry names in the output\n" -" -V prefix URL prefix for files (default: \"" LDAP_FILE_URI_PREFIX ")\n" " -z limit size limit (in entries) for search\n" "Common options:\n" " -d level set LDAP debugging level to `level'\n" " -D binddn bind DN\n" +" -e [!][=] 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" @@ -81,15 +89,16 @@ usage( const char *s ) " -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:\" or \"u:\")\n" +" -X authzid SASL authorization identity (\"dn:\" or \"u:\")\n" +" -y file Read passwd from file\n" " -Y mech SASL mechanism\n" " -Z Start TLS request (-ZZ to require successful response)\n" -, s ); +, s, def_urlpre, def_tmpdir ); exit( EXIT_FAILURE ); } @@ -135,12 +144,11 @@ static int dosearch LDAP_P(( int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, - struct timeval *timelimit, + struct timeval *timeout, int sizelimit )); static char *tmpdir = NULL; static char *urlpre = NULL; - static char *prog = NULL; static char *binddn = NULL; static struct berval passwd = { 0, NULL }; @@ -160,20 +168,40 @@ static int use_tls = 0; static char *sortattr = NULL; static int verbose, not, includeufn, vals2tmp, ldif; +static void +urlize(char *url) +{ + char *p; + + if (*LDAP_DIRSEP != '/') { + for (p = url; *p; p++) { + if (*p == *LDAP_DIRSEP) + *p = '/'; + } + } +} + int main( int argc, char **argv ) { char *infile, *filtpattern, **attrs = NULL, line[BUFSIZ]; FILE *fp = NULL; - FILE *log = NULL; - int rc, i, first, scope, deref, attrsonly, manageDSAit; + int rc, i, first, scope, deref, attrsonly, manageDSAit, noop, crit; int referrals, timelimit, sizelimit, debug; int authmethod, version, want_bindpw; LDAP *ld = NULL; + int valuesReturnFilter; + BerElement *ber = NULL; + struct berval *bvalp = NULL; + char *vrFilter = NULL, *control = NULL, *cvalue; + char *pw_file = NULL; + infile = NULL; - debug = verbose = not = vals2tmp = referrals = - attrsonly = manageDSAit = ldif = want_bindpw = 0; + debug = verbose = not = vals2tmp = referrals = valuesReturnFilter = + attrsonly = manageDSAit = noop = ldif = want_bindpw = 0; + + prog = lutil_progname( "ldapsearch", argc, argv ); lutil_log_initialize(argc, argv); @@ -182,10 +210,30 @@ main( int argc, char **argv ) scope = LDAP_SCOPE_SUBTREE; authmethod = -1; - prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1; + if((def_tmpdir = getenv("TMPDIR")) == NULL && + (def_tmpdir = getenv("TMP")) == NULL && + (def_tmpdir = getenv("TEMP")) == NULL ) + { + def_tmpdir = LDAP_TMPDIR; + } + + if ( !*def_tmpdir ) + def_tmpdir = LDAP_TMPDIR; - while (( i = getopt( argc, argv, "Aa:b:f:Ll:S:s:T:tuV:z:" - "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z")) != EOF ) + def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) ); + + if( def_urlpre == NULL ) { + perror( "malloc" ); + return EXIT_FAILURE; + } + + sprintf( def_urlpre, "file:///%s/", + def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir ); + + urlize( def_urlpre ); + + while (( i = getopt( argc, argv, "Aa:b:E:F:f:Ll:S:s:T:tuz:" + "Cd:e:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z")) != EOF ) { switch( i ) { /* Search Options */ @@ -200,7 +248,7 @@ main( int argc, char **argv ) deref = LDAP_DEREF_ALWAYS; } else { fprintf( stderr, "alias deref should be never, search, find, or always\n" ); - usage( argv[ 0 ] ); + usage(prog); } break; case 'A': /* retrieve attribute names only -- no values */ @@ -209,6 +257,52 @@ main( int argc, char **argv ) case 'b': /* search base */ base = strdup( optarg ); break; + case 'E': /* search 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, "mv" ) == 0 ) { + /* ValuesReturnFilter control */ + if (valuesReturnFilter!=0) { + fprintf( stderr, "ValuesReturnFilter previously specified"); + return EXIT_FAILURE; + } + valuesReturnFilter= 1 + crit; + + if ( cvalue == NULL ) { + fprintf( stderr, + "missing filter in ValuesReturnFilter control\n"); + return EXIT_FAILURE; + } + + vrFilter = cvalue; + version = LDAP_VERSION3; + break; + + } else { + fprintf( stderr, "Invalid control name: %s\n", control ); + usage(prog); + return EXIT_FAILURE; + } case 'f': /* input file */ if( infile != NULL ) { fprintf( stderr, "%s: -f previously specified\n", prog ); @@ -216,8 +310,17 @@ main( int argc, char **argv ) } infile = strdup( optarg ); break; + case 'F': /* uri prefix */ + if( urlpre ) free( urlpre ); + urlpre = strdup( optarg ); + break; case 'l': /* time limit */ timelimit = atoi( optarg ); + if( timelimit < 0 ) { + fprintf( stderr, "%s: invalid timelimit (%d) specified\n", + prog, timelimit ); + return EXIT_FAILURE; + } break; case 'L': /* print entries in LDIF format */ ++ldif; @@ -231,7 +334,7 @@ main( int argc, char **argv ) scope = LDAP_SCOPE_SUBTREE; } else { fprintf( stderr, "scope should be base, one, or sub\n" ); - usage( argv[ 0 ] ); + usage(prog); } break; case 'S': /* sort attribute */ @@ -247,10 +350,6 @@ main( int argc, char **argv ) if( tmpdir ) free( tmpdir ); tmpdir = strdup( optarg ); break; - case 'V': /* uri prefix */ - if( urlpre ) free( urlpre ); - urlpre = strdup( optarg ); - break; case 'z': /* size limit */ sizelimit = atoi( optarg ); break; @@ -269,6 +368,56 @@ main( int argc, char **argv ) } 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( 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( 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", prog ); @@ -507,7 +656,7 @@ main( int argc, char **argv ) { char* p; - for( p = optarg; *p == '\0'; p++ ) { + for( p = optarg; *p != '\0'; p++ ) { *p = '\0'; } } @@ -516,6 +665,9 @@ 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 ) { @@ -591,7 +743,7 @@ main( int argc, char **argv ) default: fprintf( stderr, "%s: unrecognized option -%c\n", prog, optopt ); - usage( argv[0] ); + usage(prog); } } @@ -615,7 +767,7 @@ main( int argc, char **argv ) filtpattern = strdup( argv[optind++] ); } - if ( (argv[optind] != NULL) && (sortattr == NULL || *sortattr == '\0') ) { + if ( argv[optind] != NULL ) { attrs = &argv[optind]; } @@ -628,12 +780,11 @@ main( int argc, char **argv ) } } - if( tmpdir == NULL - && (tmpdir = getenv("TMPDIR")) == NULL - && (tmpdir = getenv("TMP")) == NULL - && (tmpdir = getenv("TEMP")) == NULL ) - { - tmpdir = LDAP_TMPDIR; + if ( tmpdir == NULL ) { + tmpdir = def_tmpdir; + + if ( urlpre == NULL ) + urlpre = def_urlpre; } if( urlpre == NULL ) { @@ -645,9 +796,9 @@ main( int argc, char **argv ) } sprintf( urlpre, "file:///%s/", - tmpdir[0] == '/' ? &tmpdir[1] : tmpdir ); + tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir ); - /* urlpre should be URLized.... */ + urlize( urlpre ); } if ( debug ) { @@ -731,18 +882,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 ) { @@ -778,7 +932,7 @@ main( int argc, char **argv ) } #else fprintf( stderr, "%s: not compiled with SASL support\n", - prog, argv[0] ); + prog); return( EXIT_FAILURE ); #endif } else { @@ -789,25 +943,57 @@ main( int argc, char **argv ) } } - if ( manageDSAit ) { + if ( manageDSAit || valuesReturnFilter ) { int err; - LDAPControl c; - LDAPControl *ctrls[2]; - ctrls[0] = &c; - ctrls[1] = NULL; + int 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; + } + + if ( valuesReturnFilter ) { + ctrls[i++]=&c2; + ctrls[i] = NULL; + + c2.ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER; + c2.ldctl_iscritical = valuesReturnFilter > 1; + + if (( ber = ber_alloc_t(LBER_USE_DER)) == NULL ) { + return EXIT_FAILURE; + } + + if ( ( err = ldap_put_vrFilter( ber, vrFilter ) ) == -1 ) { + ber_free( ber, 1 ); + fprintf( stderr, "Bad ValuesReturnFilter: %s\n", vrFilter ); + return EXIT_FAILURE; + } + + if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) { + return EXIT_FAILURE; + } - c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; - c.ldctl_value.bv_val = NULL; - c.ldctl_value.bv_len = 0; - c.ldctl_iscritical = manageDSAit > 1; + c2.ldctl_value=(*bvalp); + } err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); + ber_bvfree(bvalp); + ber_free( ber, 1 ); + 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; } } } @@ -827,12 +1013,15 @@ main( int argc, char **argv ) fprintf( stderr, "\n" ); } - if (ldif < 3 ) { - printf( "version: %d\n\n", ldif ? 1 : 2 ); + if ( ldif == 0 ) { + printf( "# extended LDIF\n" ); + } else if ( ldif < 3 ) { + printf( "version: %d\n\n", 1 ); } if (ldif < 2 ) { - printf( "#\n# filter%s: %s\n# requesting: ", + printf( "#\n# LDAPv%d\n# filter%s: %s\n# requesting: ", + version, infile != NULL ? " pattern" : "", filtpattern ); @@ -889,10 +1078,10 @@ static int dosearch( int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, - struct timeval *timelimit, + struct timeval *timeout, int sizelimit ) { - char filter[ BUFSIZ ]; + char *filter; int rc; int nresponses; int nentries; @@ -903,10 +1092,16 @@ static int dosearch( ber_int_t msgid; if( filtpatt != NULL ) { + filter = malloc( strlen( filtpatt ) + strlen( value ) ); + if( filter == NULL ) { + perror( "malloc" ); + return EXIT_FAILURE; + } + sprintf( filter, filtpatt, value ); if ( verbose ) { - fprintf( stderr, "filter is: (%s)\n", filter ); + fprintf( stderr, "filter: %s\n", filter ); } if( ldif < 2 ) { @@ -914,7 +1109,7 @@ static int dosearch( } } else { - sprintf( filter, "%s", value ); + filter = value; } if ( not ) { @@ -922,7 +1117,11 @@ static int dosearch( } rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, - sctrls, cctrls, timelimit, sizelimit, &msgid ); + sctrls, cctrls, timeout, sizelimit, &msgid ); + + if ( filtpatt != NULL ) { + free( filter ); + } if( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: ldap_search_ext: %s (%d)\n", @@ -1061,16 +1260,14 @@ 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; - if ( mktemp( tmpfname ) == NULL ) { - perror( tmpfname ); - continue; - } + tmpfd = mkstemp( tmpfname ); - if (( tmpfd = open( tmpfname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) == -1 ) { + if ( tmpfd < 0 ) { perror( tmpfname ); continue; } @@ -1090,9 +1287,10 @@ 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 ); write_ldif( LDIF_PUT_URL, a, url, strlen( url )); } else {