X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=clients%2Ftools%2Fldapsearch.c;h=885bfc36a03669a90722e1637f44fe4c60fee087;hb=d912c2c711b2de7f9ca498aca25bea5627140614;hp=0ae11544ece6e44dbf75b74204f1abd9bb98b88b;hpb=b73b0c61582166d37d55a90067c5783d2164af39;p=openldap diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index 0ae11544ec..885bfc36a0 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -1,3 +1,9 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + #include "portable.h" #include @@ -8,59 +14,91 @@ #include #include #include +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif #include -#include +#include "ldif.h" +#include "lutil.h" +#include "lutil_ldap.h" #include "ldap_defaults.h" +#include "ldap_log.h" -#define DEFSEP "=" +static char *def_tmpdir; +static char *def_urlpre; static void -usage( char *s ) +usage( const char *s ) { fprintf( stderr, -"usage: %s [options] filter [attributes...]\nwhere:\n" -" filter\tRFC-1558 compliant LDAP search filter\n" -" attributes\twhitespace-separated list of attributes to retrieve\n" -"\t\t1.1 -- no attributes\n" -"\t\t* -- all user attributes\n" -"\t\t+ -- all operational attributes\n" -"\t\tempty list -- all non-operational attributes\n" -"options:\n" -" -n\t\tshow what would be done but don't actually search\n" -" -v\t\trun in verbose mode (diagnostics to standard output)\n" -" -t\t\twrite binary values to files in TMPDIR\n" -" -tt\t\twrite all values to files in TMPDIR\n" -" -T path\twrite files to directory specified by path (default: \"/tmp\")\n" -" -V prefix\tURL prefix for files (default: \"file://tmp/\"\n" -" -u\t\tinclude User Friendly entry names in the output\n" -" -A\t\tretrieve attribute names only (no values)\n" -" -B\t\tdo not suppress printing of binary values\n" -" -F sep\tprint `sep' instead of `=' between attribute names and values\n" -" -L\t\tprint entries in LDIF format (implies -B)\n" -" -LL\t\tprint entries in LDIF format without comments\n" -" -LLL\t\tprint entries in LDIF format without comments and version\n" -" -M\t\tenable Manage DSA IT control (-MM to make critical)\n" -" -R\t\tdo not automatically follow referrals\n" -" -S attr\tsort the results by attribute `attr'\n" -" -d level\tset LDAP debugging level to `level'\n" -" -f file\tperform sequence of searches listed in `file'\n" -" -b basedn\tbase dn for search\n" -" -s scope\tone of base, one, or sub (search scope)\n" -" -a deref\tone of never, always, search, or find (alias dereferencing)\n" -" -l limit\ttime limit (in seconds) for search\n" -" -z limit\tsize limit (in entries) for search\n" -" -D binddn\tbind dn\n" -" -w passwd\tbind passwd (for simple authentication)\n" -" -W\t\tprompt for bind passwd\n" -#ifdef HAVE_KERBEROS -" -k\t\tuse Kerberos instead of Simple Password authentication\n" -#endif -" -h host\tldap server\n" -" -p port\tport on ldap server\n" -" -P version\tprocotol version (2 or 3)\n" -, s ); +"usage: %s [options] [filter [attributes...]]\nwhere:\n" +" filter\tRFC-2254 compliant LDAP search filter\n" +" attributes\twhitespace-separated list of attribute descriptions\n" +" which may include:\n" +" 1.1 no attributes\n" +" * all user attributes\n" +" + all operational attributes\n" + +"Search options:\n" +" -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" +" -LLL print responses in LDIF format without comments\n" +" and version\n" +" -s scope one of base, one, or sub (search scope)\n" +" -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: %s)\n" +" -u include User Friendly entry names in the output\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" +" -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 search\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:\" 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, def_urlpre, def_tmpdir ); exit( EXIT_FAILURE ); } @@ -70,6 +108,26 @@ static void print_entry LDAP_P(( LDAPMessage *entry, int attrsonly)); +static void print_reference( + LDAP *ld, + LDAPMessage *reference ); + +static void print_extended( + LDAP *ld, + LDAPMessage *extended ); + +static void print_partial( + LDAP *ld, + LDAPMessage *partial ); + +static int print_result( + LDAP *ld, + LDAPMessage *result, + int search ); + +static void print_ctrls( + LDAPControl **ctrls ); + static int write_ldif LDAP_P(( int type, char *name, @@ -80,213 +138,637 @@ static int dosearch LDAP_P(( LDAP *ld, char *base, int scope, + char *filtpatt, + char *value, char **attrs, int attrsonly, - char *filtpatt, - char *value)); - -#define TMPDIR "/tmp" -#define URLPRE "file:/tmp/" + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit )); static char *tmpdir = NULL; static char *urlpre = NULL; - +static char *prog = NULL; static char *binddn = NULL; -static char *passwd = NULL; +static struct berval passwd = { 0, NULL }; static char *base = NULL; static char *ldaphost = NULL; +static char *ldapuri = NULL; static int ldapport = 0; -static char *sep = DEFSEP; +#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 char *sortattr = NULL; -static int skipsortattr = 0; -static int verbose, not, includeufn, binary, vals2tmp, ldif; +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, line[ BUFSIZ ]; - FILE *fp; - int rc, i, first, scope, deref, attrsonly, manageDSAit; + char *infile, *filtpattern, **attrs = NULL, line[BUFSIZ]; + FILE *fp = NULL; + int rc, i, first, scope, deref, attrsonly, manageDSAit, noop, crit; int referrals, timelimit, sizelimit, debug; int authmethod, version, want_bindpw; - LDAP *ld; + 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 = binary = not = vals2tmp = - attrsonly = manageDSAit = ldif = want_bindpw = 0; + debug = verbose = not = vals2tmp = referrals = valuesReturnFilter = + attrsonly = manageDSAit = noop = ldif = want_bindpw = 0; - deref = referrals = sizelimit = timelimit = version = -1; + prog = lutil_progname( "ldapsearch", argc, argv ); + + lutil_log_initialize(argc, argv); + + deref = sizelimit = timelimit = version = -1; scope = LDAP_SCOPE_SUBTREE; - authmethod = LDAP_AUTH_SIMPLE; + authmethod = -1; - while (( i = getopt( argc, argv, - "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:T:V:")) != EOF ) + 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; + + 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 ) { - case 'n': /* do Not do any searches */ - ++not; - break; - case 'v': /* verbose mode */ - ++verbose; - break; - case 'd': - debug |= atoi( optarg ); - break; - case 'k': /* use kerberos bind */ -#ifdef HAVE_KERBEROS - authmethod = LDAP_AUTH_KRBV4; -#else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); -#endif - break; - case 'K': /* use kerberos bind, 1st part only */ -#ifdef HAVE_KERBEROS - authmethod = LDAP_AUTH_KRBV41; -#else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); -#endif + /* Search Options */ + case 'a': /* set alias deref option */ + if ( strcasecmp( optarg, "never" ) == 0 ) { + deref = LDAP_DEREF_NEVER; + } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) { + deref = LDAP_DEREF_SEARCHING; + } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) { + deref = LDAP_DEREF_FINDING; + } else if ( strcasecmp( optarg, "always" ) == 0 ) { + deref = LDAP_DEREF_ALWAYS; + } else { + fprintf( stderr, "alias deref should be never, search, find, or always\n" ); + usage(prog); + } break; - case 'u': /* include UFN */ - ++includeufn; + case 'A': /* retrieve attribute names only -- no values */ + ++attrsonly; break; - case 't': /* write attribute values to /tmp files */ - ++vals2tmp; + case 'b': /* search base */ + base = strdup( optarg ); break; - case 'M': - /* enable Manage DSA IT */ - manageDSAit++; + 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 ); + return EXIT_FAILURE; + } + infile = strdup( optarg ); break; - case 'R': /* don't automatically chase referrals */ - referrals = (int) LDAP_OPT_OFF; + case 'F': /* uri prefix */ + if( urlpre ) free( urlpre ); + urlpre = strdup( optarg ); break; - case 'A': /* retrieve attribute names only -- no values */ - ++attrsonly; + 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; - /* fall through -- always allow binary when outputting LDIF */ - case 'B': /* allow binary values to be printed */ - ++binary; break; case 's': /* search scope */ if ( strcasecmp( optarg, "base" ) == 0 ) { scope = LDAP_SCOPE_BASE; - } else if ( strcasecmp( optarg, "one" ) == 0 ) { + } else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) { scope = LDAP_SCOPE_ONELEVEL; - } else if ( strcasecmp( optarg, "sub" ) == 0 ) { + } else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) { scope = LDAP_SCOPE_SUBTREE; } else { fprintf( stderr, "scope should be base, one, or sub\n" ); - usage( argv[ 0 ] ); - } - break; - - case 'a': /* set alias deref option */ - if ( strcasecmp( optarg, "never" ) == 0 ) { - deref = LDAP_DEREF_NEVER; - } else if ( strcasecmp( optarg, "search" ) == 0 ) { - deref = LDAP_DEREF_SEARCHING; - } else if ( strcasecmp( optarg, "find" ) == 0 ) { - deref = LDAP_DEREF_FINDING; - } else if ( strcasecmp( optarg, "always" ) == 0 ) { - deref = LDAP_DEREF_ALWAYS; - } else { - fprintf( stderr, "alias deref should be never, search, find, or always\n" ); - usage( argv[ 0 ] ); + usage(prog); } break; - - case 'T': /* field separator */ - if( tmpdir ) free( tmpdir ); - tmpdir = strdup( optarg ); + case 'S': /* sort attribute */ + sortattr = strdup( optarg ); break; - case 'V': /* field separator */ - if( urlpre ) free( urlpre ); - urlpre = strdup( optarg ); + case 'u': /* include UFN */ + ++includeufn; break; - case 'F': /* field separator */ - sep = strdup( optarg ); + case 't': /* write attribute values to TMPDIR files */ + ++vals2tmp; break; - case 'f': /* input file */ - infile = strdup( optarg ); + case 'T': /* tmpdir */ + if( tmpdir ) free( tmpdir ); + tmpdir = strdup( optarg ); break; - case 'h': /* ldap host */ - ldaphost = strdup( optarg ); + case 'z': /* size limit */ + sizelimit = atoi( optarg ); break; - case 'b': /* searchbase */ - base = strdup( optarg ); + + /* Common Options */ + case 'C': + referrals++; break; + case 'd': + debug |= atoi( optarg ); + break; case 'D': /* bind DN */ - binddn = strdup( optarg ); - break; - case 'p': /* ldap port */ - ldapport = atoi( optarg ); - break; - case 'w': /* bind password */ - passwd = strdup( optarg ); - { - char* p; + if( binddn != NULL ) { + 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; + } - for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + /* 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 ); + 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; - case 'l': /* time limit */ - timelimit = atoi( optarg ); - break; - case 'z': /* size limit */ - sizelimit = atoi( optarg ); - break; - case 'S': /* sort attribute */ - sortattr = strdup( optarg ); +#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 'W': - want_bindpw++; + 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 ) ) - { + 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, "protocol version should be 2 or 3\n" ); - usage( argv[0] ); + 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': + pw_file = optarg; + 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: - usage( argv[0] ); + fprintf( stderr, "%s: unrecognized option -%c\n", + prog, optopt ); + usage(prog); } } - if ( argc - optind < 1 ) { - 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 } - filtpattern = strdup( argv[ optind ] ); - - if ( argv[ optind + 1 ] == NULL ) { - attrs = NULL; - } else if ( sortattr == NULL || *sortattr == '\0' ) { - attrs = &argv[ optind + 1 ]; + if (( argc - optind < 1 ) || + ( *argv[optind] != '(' /*')'*/ && + ( strchr( argv[optind], '=' ) == NULL ) ) ) + { + filtpattern = "(objectclass=*)"; } else { - for ( i = optind + 1; i < argc; i++ ) { - if ( strcasecmp( argv[ i ], sortattr ) == 0 ) { - break; - } - } - if ( i == argc ) { - skipsortattr = 1; - argv[ optind ] = sortattr; - } else { - optind++; - } - attrs = &argv[ optind ]; + filtpattern = strdup( argv[optind++] ); + } + + if ( argv[optind] != NULL ) { + attrs = &argv[optind]; } if ( infile != NULL ) { @@ -298,16 +780,15 @@ main( int argc, char **argv ) } } - if( tmpdir == NULL - && (tmpdir = getenv("TMPDIR")) == NULL - && (tmpdir = getenv("TMP")) == NULL - && (tmpdir = getenv("TEMP")) == NULL ) - { - tmpdir = "/tmp"; + if ( tmpdir == NULL ) { + tmpdir = def_tmpdir; + + if ( urlpre == NULL ) + urlpre = def_urlpre; } if( urlpre == NULL ) { - urlpre = malloc( sizeof("file:///") + strlen(tmpdir) ); + urlpre = malloc( sizeof("file:////") + strlen(tmpdir) ); if( urlpre == NULL ) { perror( "malloc" ); @@ -315,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 ) { @@ -334,84 +815,196 @@ main( int argc, char **argv ) (void) SIGNAL( SIGPIPE, SIG_IGN ); #endif - if ( verbose ) { - fprintf( stderr, "ldap_init( %s, %d )\n", - (ldaphost != NULL) ? ldaphost : "", - ldapport ); - } + if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) { + if ( verbose ) { + fprintf( stderr, "ldap_init( %s, %d )\n", + ldaphost != NULL ? ldaphost : "", + ldapport ); + } - if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) { - perror( "ldap_init" ); - return( EXIT_FAILURE ); + ld = ldap_init( ldaphost, ldapport ); + if( ld == NULL ) { + perror("ldapsearch: ldap_init"); + return EXIT_FAILURE; + } + + } else { + if ( verbose ) { + fprintf( stderr, "ldap_initialize( %s )\n", + ldapuri != NULL ? ldapuri : "" ); + } + + 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; + } } if (deref != -1 && ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref ); + return EXIT_FAILURE; } if (timelimit != -1 && ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit ); + return EXIT_FAILURE; } if (sizelimit != -1 && ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit ); + return EXIT_FAILURE; } - if (referrals != -1 && - ldap_set_option( ld, LDAP_OPT_REFERRALS, - (referrals ? LDAP_OPT_ON : LDAP_OPT_OFF) ) != LDAP_OPT_SUCCESS ) + + /* 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 (version != -1 && - ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS ) + 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 ); + 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 = getpass("Enter LDAP Password: "); + 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 ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); + 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 ) { + 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; + } - c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; - c.ldctl_value.bv_val = NULL; - c.ldctl_value.bv_len = 0; - c.ldctl_iscritical = manageDSAit > 1; + if ( valuesReturnFilter ) { + ctrls[i++]=&c2; + ctrls[i] = NULL; - err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls ); + 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; + } + + 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 Manage DSA IT Control\n" ); - 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; } } } if ( verbose ) { - fprintf( stderr, "filter%s: %s\nreturning: ", + fprintf( stderr, "filter%s: %s\nrequesting: ", infile != NULL ? " pattern" : "", filtpattern ); if ( attrs == NULL ) { - printf( "ALL" ); + fprintf( stderr, "ALL" ); } else { for ( i = 0; attrs[ i ] != NULL; ++i ) { fprintf( stderr, "%s ", attrs[ i ] ); @@ -420,43 +1013,50 @@ main( int argc, char **argv ) fprintf( stderr, "\n" ); } - if ( ldif ) { - if (ldif < 3 ) { - /* TEMPORARILY put the version in a comment many tools cannot yet a version attribute */ - printf( "# version: 1\n"); - } + 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# returning: ", - infile != NULL ? " pattern" : "", - filtpattern ); + if (ldif < 2 ) { + printf( "#\n# LDAPv%d\n# filter%s: %s\n# requesting: ", + version, + infile != NULL ? " pattern" : "", + filtpattern ); - if ( attrs == NULL ) { - printf( "ALL" ); - } else { - for ( i = 0; attrs[ i ] != NULL; ++i ) { - printf( "%s ", attrs[ i ] ); - } + if ( attrs == NULL ) { + printf( "ALL" ); + } else { + for ( i = 0; attrs[ i ] != NULL; ++i ) { + printf( "%s ", attrs[ i ] ); } - printf( "\n#\n\n" ); } + + if ( manageDSAit ) { + printf("\n# with manageDSAit %scontrol", + manageDSAit > 1 ? "critical " : "" ); + } + + printf( "\n#\n\n" ); } if ( infile == NULL ) { - rc = dosearch( ld, base, scope, attrs, attrsonly, NULL, filtpattern ); + rc = dosearch( ld, base, scope, NULL, filtpattern, + attrs, attrsonly, NULL, NULL, NULL, -1 ); } else { rc = 0; first = 1; - while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) { + while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) { line[ strlen( line ) - 1 ] = '\0'; if ( !first ) { putchar( '\n' ); } else { first = 0; } - rc = dosearch( ld, base, scope, attrs, attrsonly, - filtpattern, line ); + rc = dosearch( ld, base, scope, filtpattern, line, + attrs, attrsonly, NULL, NULL, NULL, -1 ); } if ( fp != stdin ) { fclose( fp ); @@ -472,92 +1072,136 @@ static int dosearch( LDAP *ld, char *base, int scope, + char *filtpatt, + char *value, char **attrs, int attrsonly, - char *filtpatt, - char *value) + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit ) { - char filter[ BUFSIZ ]; - int rc, first, matches; - LDAPMessage *res, *e; + char *filter; + int rc; + int nresponses; + int nentries; + int nreferences; + int nextended; + int npartial; + LDAPMessage *res, *msg; + 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 == 1 ) { + if( ldif < 2 ) { printf( "#\n# filter: %s\n#\n", filter ); } } else { - sprintf( filter, "%s", value ); + filter = value; } if ( not ) { - return( LDAP_SUCCESS ); + return LDAP_SUCCESS; } - if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) { - int ld_errno; - ldap_perror( ld, "ldap_search" ); + rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, + sctrls, cctrls, timeout, sizelimit, &msgid ); - ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno); - return( ld_errno ); + if ( filtpatt != NULL ) { + free( filter ); } - matches = 0; - first = 1; - res = NULL; - while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res )) - == LDAP_RES_SEARCH_ENTRY ) { - matches++; - e = ldap_first_entry( ld, res ); - if ( !first ) { - putchar( '\n' ); - } else { - first = 0; + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "%s: ldap_search_ext: %s (%d)\n", + prog, ldap_err2string( rc ), rc ); + return( rc ); } - print_entry( ld, e, attrsonly ); - ldap_msgfree( res ); + + nresponses = nentries = nreferences = nextended = npartial = 0; + res = NULL; - } - if ( rc == -1 ) { - ldap_perror( ld, "ldap_result" ); - return( rc ); - } - if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_search" ); - } - if ( sortattr != NULL ) { - (void) ldap_sort_entries( ld, &res, - ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp ); - matches = 0; - first = 1; - for ( e = ldap_first_entry( ld, res ); e != NULL; - e = ldap_next_entry( ld, e ) ) { - matches++; - if ( !first ) { - putchar( '\n' ); - } else { - first = 0; + + while ((rc = ldap_result( ld, LDAP_RES_ANY, + sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE, + NULL, &res )) > 0 ) + { + if( sortattr ) { + (void) ldap_sort_entries( ld, &res, + ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp ); } - print_entry( ld, e, attrsonly ); + + for ( msg = ldap_first_message( ld, res ); + msg != NULL; + msg = ldap_next_message( ld, msg ) ) + { + if( nresponses++ ) putchar('\n'); + + switch( ldap_msgtype( msg ) ) { + case LDAP_RES_SEARCH_ENTRY: + nentries++; + print_entry( ld, msg, attrsonly ); + break; + + case LDAP_RES_SEARCH_REFERENCE: + nreferences++; + print_reference( ld, msg ); + break; + + case LDAP_RES_EXTENDED: + nextended++; + print_extended( ld, msg ); + + if( ldap_msgid( msg ) == 0 ) { + /* unsolicited extended operation */ + goto done; + } + break; + + case LDAP_RES_EXTENDED_PARTIAL: + npartial++; + print_partial( ld, msg ); + break; + + case LDAP_RES_SEARCH_RESULT: + rc = print_result( ld, msg, 1 ); + goto done; + } } + + ldap_msgfree( res ); } - if ( verbose ) { - printf( "%d matches\n", matches ); + if ( rc == -1 ) { + ldap_perror( ld, "ldap_result" ); + return( rc ); + } + +done: + if ( ldif < 2 ) { + printf( "\n# numResponses: %d\n", nresponses ); + if( nentries ) printf( "# numEntries: %d\n", nentries ); + if( nextended ) printf( "# numExtended: %d\n", nextended ); + if( npartial ) printf( "# numPartial: %d\n", npartial ); + if( nreferences ) printf( "# numReferences: %d\n", nreferences ); } - ldap_msgfree( res ); return( rc ); } - -void print_entry( +static void +print_entry( LDAP *ld, LDAPMessage *entry, int attrsonly) @@ -565,33 +1209,39 @@ void print_entry( char *a, *dn, *ufn; char tmpfname[ 256 ]; char url[ 256 ]; - int i; + int i, rc; BerElement *ber = NULL; struct berval **bvals; + LDAPControl **ctrls = NULL; FILE *tmpfp; dn = ldap_get_dn( ld, entry ); ufn = NULL; - if ( ldif == 1 ) { + if ( ldif < 2 ) { ufn = ldap_dn2ufn( dn ); - write_ldif( LDIF_PUT_COMMENT, NULL, ufn, strlen( ufn )); + write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 ); } - if ( ldif ) { - write_ldif( LDIF_PUT_VALUE, "dn", dn, strlen( dn )); - } else { - printf( "%s\n", dn ); + write_ldif( LDIF_PUT_VALUE, "dn", dn, dn ? strlen( dn ) : 0); + + rc = ldap_get_entry_controls( ld, entry, &ctrls ); + + if( rc != LDAP_SUCCESS ) { + fprintf(stderr, "print_entry: %d\n", rc ); + ldap_perror( ld, "ldap_get_entry_controls" ); + exit( EXIT_FAILURE ); + } + + if( ctrls ) { + print_ctrls( ctrls ); + ldap_controls_free( ctrls ); } if ( includeufn ) { if( ufn == NULL ) { ufn = ldap_dn2ufn( dn ); } - if ( ldif ) { - write_ldif( LDIF_PUT_VALUE, "ufn", ufn, strlen( ufn )); - } else { - printf( "%s\n", ufn ); - } + write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 ); } if( ufn != NULL ) ldap_memfree( ufn ); @@ -600,33 +1250,29 @@ void print_entry( for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL; a = ldap_next_attribute( ld, entry, ber ) ) { - if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) { - continue; - } - if ( attrsonly ) { - if ( ldif ) { - write_ldif( LDIF_PUT_NOVALUE, a, NULL, 0 ); - } else { - printf( "%s\n", a ); - } + write_ldif( LDIF_PUT_NOVALUE, a, NULL, 0 ); } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) { for ( i = 0; bvals[i] != NULL; i++ ) { if ( vals2tmp > 1 || ( vals2tmp && ldif_is_not_printable( bvals[i]->bv_val, bvals[i]->bv_len ) )) { + 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 ) { + tmpfd = mkstemp( tmpfname ); + + if ( tmpfd < 0 ) { perror( tmpfname ); continue; } - if (( tmpfp = fopen( tmpfname, "w")) == NULL ) { + if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) { perror( tmpfname ); continue; } @@ -641,29 +1287,15 @@ void print_entry( fclose( tmpfp ); - sprintf( url, "%s%s", urlpre, + snprintf( url, sizeof url, "%s%s", urlpre, &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] ); - if ( ldif ) { - write_ldif( LDIF_PUT_URL, a, url, strlen( url )); - } else { - printf( "%s%s%s\n", a, sep, url ); - } - + urlize( url ); + write_ldif( LDIF_PUT_URL, a, url, strlen( url )); } else { - if ( ldif ) { - write_ldif( LDIF_PUT_VALUE, a, - bvals[ i ]->bv_val, bvals[ i ]->bv_len ); - - } else { - int notprint = !binary && !vals2tmp - && ldif_is_not_printable( bvals[i]->bv_val, - bvals[i]->bv_len ); - printf( "%s%s", a, sep ); - puts( notprint ? "NOT PRINTABLE" : bvals[ i ]->bv_val ); - puts( "\n" ); - } + write_ldif( LDIF_PUT_VALUE, a, + bvals[ i ]->bv_val, bvals[ i ]->bv_len ); } } ber_bvecfree( bvals ); @@ -675,8 +1307,244 @@ void print_entry( } } +static void print_reference( + LDAP *ld, + LDAPMessage *reference ) +{ + int rc; + char **refs = NULL; + LDAPControl **ctrls; -int + if( ldif < 2 ) { + printf("# search reference\n"); + } + + rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror(ld, "ldap_parse_reference"); + exit( EXIT_FAILURE ); + } + + if( refs ) { + int i; + for( i=0; refs[i] != NULL; i++ ) { + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "ref", refs[i], strlen(refs[i]) ); + } + ber_memvfree( (void **) refs ); + } + + if( ctrls ) { + print_ctrls( ctrls ); + ldap_controls_free( ctrls ); + } +} + +static void print_extended( + LDAP *ld, + LDAPMessage *extended ) +{ + int rc; + char *retoid = NULL; + struct berval *retdata = NULL; + + if( ldif < 2 ) { + printf("# extended result response\n"); + } + + rc = ldap_parse_extended_result( ld, extended, + &retoid, &retdata, 0 ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror(ld, "ldap_parse_extended_result"); + exit( EXIT_FAILURE ); + } + + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "extended", retoid, retoid ? strlen(retoid) : 0 ); + ber_memfree( retoid ); + + if(retdata) { + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, + "data", retdata->bv_val, retdata->bv_len ); + ber_bvfree( retdata ); + } + + print_result( ld, extended, 0 ); +} + +static void print_partial( + LDAP *ld, + LDAPMessage *partial ) +{ + int rc; + char *retoid = NULL; + struct berval *retdata = NULL; + LDAPControl **ctrls = NULL; + + if( ldif < 2 ) { + printf("# extended partial response\n"); + } + + rc = ldap_parse_extended_partial( ld, partial, + &retoid, &retdata, &ctrls, 0 ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror(ld, "ldap_parse_extended_partial"); + exit( EXIT_FAILURE ); + } + + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "partial", retoid, retoid ? strlen(retoid) : 0 ); + + ber_memfree( retoid ); + + if( retdata ) { + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, + "data", + retdata->bv_val, retdata->bv_len ); + + ber_bvfree( retdata ); + } + + if( ctrls ) { + print_ctrls( ctrls ); + ldap_controls_free( ctrls ); + } +} + +static int print_result( + LDAP *ld, + LDAPMessage *result, int search ) +{ + int rc; + int err; + char *matcheddn = NULL; + char *text = NULL; + char **refs = NULL; + LDAPControl **ctrls = NULL; + + if( search ) { + if ( ldif < 2 ) { + printf("# search result\n"); + } + if ( ldif < 1 ) { + printf("%s: %d\n", "search", ldap_msgid(result) ); + } + } + + rc = ldap_parse_result( ld, result, + &err, &matcheddn, &text, &refs, &ctrls, 0 ); + + if( rc != LDAP_SUCCESS ) { + ldap_perror(ld, "ldap_parse_result"); + exit( EXIT_FAILURE ); + } + + + if( !ldif ) { + printf( "result: %d %s\n", err, ldap_err2string(err) ); + + } else if ( err != LDAP_SUCCESS ) { + fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err ); + } + + if( matcheddn && *matcheddn ) { + if( !ldif ) { + write_ldif( LDIF_PUT_VALUE, + "matchedDN", matcheddn, strlen(matcheddn) ); + } else { + fprintf( stderr, "Matched DN: %s\n", matcheddn ); + } + + ber_memfree( matcheddn ); + } + + if( text && *text ) { + if( !ldif ) { + write_ldif( LDIF_PUT_TEXT, "text", + text, strlen(text) ); + } else { + fprintf( stderr, "Additional information: %s\n", text ); + } + + ber_memfree( text ); + } + + if( refs ) { + int i; + for( i=0; refs[i] != NULL; i++ ) { + if( !ldif ) { + write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) ); + } else { + fprintf( stderr, "Referral: %s\n", refs[i] ); + } + } + + ber_memvfree( (void **) refs ); + } + + if( ctrls ) { + print_ctrls( ctrls ); + ldap_controls_free( ctrls ); + } + + return err; +} + +static void print_ctrls( + LDAPControl **ctrls ) +{ + int i; + for(i=0; ctrls[i] != NULL; i++ ) { + /* control: OID criticality base64value */ + struct berval *b64 = NULL; + ber_len_t len; + char *str; + + len = strlen( ctrls[i]->ldctl_oid ); + + /* add enough for space after OID and the critical value itself */ + len += ctrls[i]->ldctl_iscritical + ? sizeof("true") : sizeof("false"); + + /* convert to base64 */ + if( ctrls[i]->ldctl_value.bv_len ) { + b64 = ber_memalloc( sizeof(struct berval) ); + + b64->bv_len = LUTIL_BASE64_ENCODE_LEN( + ctrls[i]->ldctl_value.bv_len ) + 1; + b64->bv_val = ber_memalloc( b64->bv_len + 1 ); + + b64->bv_len = lutil_b64_ntop( + ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len, + b64->bv_val, b64->bv_len ); + } + + if( b64 ) { + len += 1 + b64->bv_len; + } + + str = malloc( len + 1 ); + strcpy( str, ctrls[i]->ldctl_oid ); + strcat( str, ctrls[i]->ldctl_iscritical + ? " true" : " false" ); + + if( b64 ) { + strcat(str, " "); + strcat(str, b64->bv_val ); + } + + write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, + "control", str, len ); + + free( str ); + ber_bvfree( b64 ); + } +} + +static int write_ldif( int type, char *name, char *value, ber_len_t vallen ) { char *ldif;