Back to index

openldap  2.4.31
common.c
Go to the documentation of this file.
00001 /* common.c - common routines for the ldap client tools */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2003 Kurt D. Zeilenga.
00007  * Portions Copyright 2003 IBM Corporation.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* ACKNOWLEDGEMENTS:
00019  * This file was initially created by Hallvard B. Furuseth based (in
00020  * part) upon argument parsing code for individual tools located in
00021  * this directory.   Additional contributors include:
00022  *   Kurt D. Zeilenga (additional common argument and control support)
00023  */
00024 
00025 #include "portable.h"
00026 
00027 #include <stdio.h>
00028 
00029 #include <ac/stdlib.h>
00030 #include <ac/signal.h>
00031 #include <ac/string.h>
00032 #include <ac/ctype.h>
00033 #include <ac/unistd.h>
00034 #include <ac/errno.h>
00035 #include <ac/time.h>
00036 #include <ac/socket.h>
00037 
00038 #ifdef HAVE_CYRUS_SASL
00039 #ifdef HAVE_SASL_SASL_H
00040 #include <sasl/sasl.h>
00041 #else
00042 #include <sasl.h>
00043 #endif
00044 #endif
00045 
00046 #include <ldap.h>
00047 
00048 #include "ldif.h"
00049 #include "lutil.h"
00050 #include "lutil_ldap.h"
00051 #include "ldap_defaults.h"
00052 #include "ldap_pvt.h"
00053 #include "lber_pvt.h"
00054 
00055 #include "common.h"
00056 
00057 /* input-related vars */
00058 
00059 /* misc. parameters */
00060 tool_type_t   tool_type;
00061 int           contoper = 0;
00062 int           debug = 0;
00063 char          *infile = NULL;
00064 int           dont = 0;
00065 int           nocanon = 0;
00066 int           referrals = 0;
00067 int           verbose = 0;
00068 int           ldif = 0;
00069 ber_len_t     ldif_wrap = LDIF_LINE_WIDTH;
00070 char          *prog = NULL;
00071 
00072 /* connection */
00073 char          *ldapuri = NULL;
00074 char          *ldaphost = NULL;
00075 int           ldapport = 0;
00076 int           use_tls = 0;
00077 int           protocol = -1;
00078 int           version = 0;
00079 
00080 /* authc/authz */
00081 int           authmethod = -1;
00082 char          *binddn = NULL;
00083 int           want_bindpw = 0;
00084 struct berval passwd = { 0, NULL };
00085 char          *pw_file = NULL;
00086 #ifdef HAVE_CYRUS_SASL
00087 unsigned      sasl_flags = LDAP_SASL_AUTOMATIC;
00088 char          *sasl_realm = NULL;
00089 char          *sasl_authc_id = NULL;
00090 char          *sasl_authz_id = NULL;
00091 char          *sasl_mech = NULL;
00092 char          *sasl_secprops = NULL;
00093 #endif
00094 
00095 /* controls */
00096 int           assertctl;
00097 char          *assertion = NULL;
00098 struct berval assertionvalue = BER_BVNULL;
00099 char          *authzid = NULL;
00100 /* support deprecated early version of proxyAuthz */
00101 #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12"
00102 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
00103 char          *proxydn = NULL;
00104 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
00105 int           manageDIT = 0;
00106 int           manageDSAit = 0;
00107 int           noop = 0;
00108 int           ppolicy = 0;
00109 int           preread = 0;
00110 static char   *preread_attrs = NULL;
00111 int           postread = 0;
00112 static char   *postread_attrs = NULL;
00113 ber_int_t     pr_morePagedResults = 1;
00114 struct berval pr_cookie = { 0, NULL };
00115 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
00116 int           chaining = 0;
00117 static int    chainingResolve = -1;
00118 static int    chainingContinuation = -1;
00119 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
00120 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
00121 static int    sessionTracking = 0;
00122 struct berval stValue;
00123 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
00124 ber_int_t vlvPos;
00125 ber_int_t vlvCount;
00126 struct berval *vlvContext;
00127 
00128 LDAPControl   *unknown_ctrls = NULL;
00129 int           unknown_ctrls_num = 0;
00130 
00131 /* options */
00132 struct timeval       nettimeout = { -1 , 0 };
00133 
00134 typedef int (*print_ctrl_fn)( LDAP *ld, LDAPControl *ctrl );
00135 
00136 static int print_preread( LDAP *ld, LDAPControl *ctrl );
00137 static int print_postread( LDAP *ld, LDAPControl *ctrl );
00138 static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
00139 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
00140 static int print_ppolicy( LDAP *ld, LDAPControl *ctrl );
00141 #endif
00142 static int print_sss( LDAP *ld, LDAPControl *ctrl );
00143 static int print_vlv( LDAP *ld, LDAPControl *ctrl );
00144 #ifdef LDAP_CONTROL_X_DEREF
00145 static int print_deref( LDAP *ld, LDAPControl *ctrl );
00146 #endif
00147 #ifdef LDAP_CONTROL_X_WHATFAILED
00148 static int print_whatfailed( LDAP *ld, LDAPControl *ctrl );
00149 #endif
00150 
00151 static struct tool_ctrls_t {
00152        const char    *oid;
00153        unsigned      mask;
00154        print_ctrl_fn func;
00155 } tool_ctrl_response[] = {
00156        { LDAP_CONTROL_PRE_READ,                  TOOL_ALL,     print_preread },
00157        { LDAP_CONTROL_POST_READ,                 TOOL_ALL,     print_postread },
00158        { LDAP_CONTROL_PAGEDRESULTS,                     TOOL_SEARCH,  print_paged_results },
00159 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
00160        { LDAP_CONTROL_PASSWORDPOLICYRESPONSE,           TOOL_ALL,     print_ppolicy },
00161 #endif
00162        { LDAP_CONTROL_SORTRESPONSE,       TOOL_SEARCH,  print_sss },
00163        { LDAP_CONTROL_VLVRESPONSE,        TOOL_SEARCH,  print_vlv },
00164 #ifdef LDAP_CONTROL_X_DEREF
00165        { LDAP_CONTROL_X_DEREF,                          TOOL_SEARCH,  print_deref },
00166 #endif
00167 #ifdef LDAP_CONTROL_X_WHATFAILED
00168        { LDAP_CONTROL_X_WHATFAILED,                     TOOL_ALL,     print_whatfailed },
00169 #endif
00170        { NULL,                                          0,            NULL }
00171 };
00172 
00173 /* "features" */
00174 enum { Intr_None = 0, Intr_Abandon, Intr_Cancel, Intr_Ignore }; 
00175 static volatile sig_atomic_t       gotintr, abcan;
00176 
00177 
00178 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
00179 static int
00180 st_value( LDAP *ld, struct berval *value )
00181 {
00182        char          *ip = NULL, *name = NULL;
00183        struct berval id = { 0 };
00184        char          namebuf[ MAXHOSTNAMELEN ];
00185 
00186        if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) {
00187               struct hostent       *h;
00188               struct in_addr       addr;
00189 
00190               name = namebuf;
00191 
00192               h = gethostbyname( name );
00193               if ( h != NULL ) {
00194                      AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) );
00195                      ip = inet_ntoa( addr );
00196               }
00197        }
00198 
00199 #ifdef HAVE_CYRUS_SASL
00200        if ( sasl_authz_id != NULL ) {
00201               ber_str2bv( sasl_authz_id, 0, 0, &id );
00202 
00203        } else if ( sasl_authc_id != NULL ) {
00204               ber_str2bv( sasl_authc_id, 0, 0, &id );
00205 
00206        } else 
00207 #endif /* HAVE_CYRUS_SASL */
00208        if ( binddn != NULL ) {
00209               ber_str2bv( binddn, 0, 0, &id );
00210        }
00211 
00212        if ( ldap_create_session_tracking_value( ld,
00213               ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME,
00214               &id, &stValue ) )
00215        {
00216               fprintf( stderr, _("Session tracking control encoding error!\n") );
00217               return -1;
00218        }
00219 
00220        return 0;
00221 }
00222 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
00223 
00224 RETSIGTYPE
00225 do_sig( int sig )
00226 {
00227        gotintr = abcan;
00228 }
00229 
00230 void
00231 tool_init( tool_type_t type )
00232 {
00233        tool_type = type;
00234        ldap_pvt_setlocale(LC_MESSAGES, "");
00235        ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE, LDAP_LOCALEDIR);
00236        ldap_pvt_textdomain(OPENLDAP_PACKAGE);
00237 }
00238 
00239 void
00240 tool_destroy( void )
00241 {
00242        static int destroyed;
00243        if ( destroyed++ )
00244               return;
00245 
00246 #ifdef HAVE_CYRUS_SASL
00247        sasl_done();
00248 #endif
00249 #ifdef HAVE_TLS
00250        ldap_pvt_tls_destroy();
00251 #endif
00252 
00253        if ( ldapuri != NULL ) {
00254               ber_memfree( ldapuri );
00255               ldapuri = NULL;
00256        }
00257 
00258        if ( pr_cookie.bv_val != NULL ) {
00259               ber_memfree( pr_cookie.bv_val );
00260               BER_BVZERO( &pr_cookie );
00261        }
00262 
00263        if ( binddn != NULL ) {
00264               ber_memfree( binddn );
00265               binddn = NULL;
00266        }
00267 
00268        if ( passwd.bv_val != NULL ) {
00269               ber_memfree( passwd.bv_val );
00270               BER_BVZERO( &passwd );
00271        }
00272 
00273        if ( infile != NULL ) {
00274               ber_memfree( infile );
00275               infile = NULL;
00276        }
00277 
00278        if ( assertion ) {
00279               ber_memfree( assertion );
00280               assertion = NULL;
00281        }
00282 
00283        if ( authzid ) {
00284               ber_memfree( authzid );
00285               authzid = NULL;
00286        }
00287 
00288        if ( proxydn ) {
00289               ber_memfree( proxydn );
00290               proxydn = NULL;
00291        }
00292 
00293        if ( preread_attrs ) {
00294               ber_memfree( preread_attrs );
00295               preread_attrs = NULL;
00296        }
00297 
00298        if ( postread_attrs ) {
00299               ber_memfree( postread_attrs );
00300               postread_attrs = NULL;
00301        }
00302 }
00303 
00304 void
00305 tool_common_usage( void )
00306 {
00307        static const char *const descriptions[] = {
00308 N_("  -d level   set LDAP debugging level to `level'\n"),
00309 N_("  -D binddn  bind DN\n"),
00310 N_("  -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
00311 N_("             [!]assert=<filter>     (RFC 4528; a RFC 4515 Filter string)\n")
00312 N_("             [!]authzid=<authzid>   (RFC 4370; \"dn:<dn>\" or \"u:<user>\")\n")
00313 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
00314 #if 0
00315                  /* non-advertized support for proxyDN */
00316 N_("             [!]proxydn=<dn>        (a RFC 4514 DN string)\n")
00317 #endif
00318 #endif
00319 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
00320 N_("             [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
00321 N_("                     one of \"chainingPreferred\", \"chainingRequired\",\n")
00322 N_("                     \"referralsPreferred\", \"referralsRequired\"\n")
00323 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
00324 N_("             [!]manageDSAit         (RFC 3296)\n")
00325 N_("             [!]noop\n")
00326 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
00327 N_("             ppolicy\n")
00328 #endif
00329 N_("             [!]postread[=<attrs>]  (RFC 4527; comma-separated attr list)\n")
00330 N_("             [!]preread[=<attrs>]   (RFC 4527; comma-separated attr list)\n")
00331 N_("             [!]relax\n")
00332 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
00333 N_("             [!]sessiontracking\n")
00334 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
00335 N_("             abandon, cancel, ignore (SIGINT sends abandon/cancel,\n"
00336    "             or ignores response; if critical, doesn't wait for SIGINT.\n"
00337    "             not really controls)\n")
00338 N_("  -h host    LDAP server\n"),
00339 N_("  -H URI     LDAP Uniform Resource Identifier(s)\n"),
00340 N_("  -I         use SASL Interactive mode\n"),
00341 N_("  -n         show what would be done but don't actually do it\n"),
00342 N_("  -N         do not use reverse DNS to canonicalize SASL host name\n"),
00343 N_("  -O props   SASL security properties\n"),
00344 N_("  -o <opt>[=<optparam>] general options\n"),
00345 N_("             nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"),
00346 N_("             ldif-wrap=<width> (in columns, or \"no\" for no wrapping)\n"),
00347 N_("  -p port    port on LDAP server\n"),
00348 N_("  -Q         use SASL Quiet mode\n"),
00349 N_("  -R realm   SASL realm\n"),
00350 N_("  -U authcid SASL authentication identity\n"),
00351 N_("  -v         run in verbose mode (diagnostics to standard output)\n"),
00352 N_("  -V         print version info (-VV only)\n"),
00353 N_("  -w passwd  bind password (for simple authentication)\n"),
00354 N_("  -W         prompt for bind password\n"),
00355 N_("  -x         Simple authentication\n"),
00356 N_("  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
00357 N_("  -y file    Read password from file\n"),
00358 N_("  -Y mech    SASL mechanism\n"),
00359 N_("  -Z         Start TLS request (-ZZ to require successful response)\n"),
00360 NULL
00361        };
00362        const char *const *cpp;
00363 
00364        fputs( _("Common options:\n"), stderr );
00365        for( cpp = descriptions; *cpp != NULL; cpp++ ) {
00366               if( strchr( options, (*cpp)[3] ) || (*cpp)[3] == ' ' ) {
00367                      fputs( _(*cpp), stderr );
00368               }
00369        }
00370 
00371        tool_destroy();
00372 }
00373 
00374 void tool_perror(
00375        const char *func,
00376        int err,
00377        const char *extra,
00378        const char *matched,
00379        const char *info,
00380        char **refs )
00381 {
00382        fprintf( stderr, "%s: %s (%d)%s\n",
00383               func, ldap_err2string( err ), err, extra ? extra : "" );
00384 
00385        if ( matched && *matched ) {
00386               fprintf( stderr, _("\tmatched DN: %s\n"), matched );
00387        }
00388 
00389        if ( info && *info ) {
00390               fprintf( stderr, _("\tadditional info: %s\n"), info );
00391        }
00392 
00393        if ( refs && *refs ) {
00394               int i;
00395               fprintf( stderr, _("\treferrals:\n") );
00396               for( i=0; refs[i]; i++ ) {
00397                      fprintf( stderr, "\t\t%s\n", refs[i] );
00398               }
00399        }
00400 }
00401 
00402 
00403 void
00404 tool_args( int argc, char **argv )
00405 {
00406        int i;
00407 
00408        while (( i = getopt( argc, argv, options )) != EOF ) {
00409               int crit, ival;
00410               char *control, *cvalue, *next;
00411               switch( i ) {
00412               case 'c':     /* continuous operation mode */
00413                      contoper++;
00414                      break;
00415               case 'C':     /* referrals: obsolete */
00416                      referrals++;
00417                      break;
00418               case 'd':
00419                      ival = strtol( optarg, &next, 10 );
00420                      if (next == NULL || next[0] != '\0') {
00421                             fprintf( stderr, "%s: unable to parse debug value \"%s\"\n", prog, optarg);
00422                             exit(EXIT_FAILURE);
00423                      }
00424                      debug |= ival;
00425                      break;
00426               case 'D':     /* bind DN */
00427                      if( binddn != NULL ) {
00428                             fprintf( stderr, "%s: -D previously specified\n", prog );
00429                             exit( EXIT_FAILURE );
00430                      }
00431                      binddn = ber_strdup( optarg );
00432                      break;
00433               case 'e':     /* general extensions (controls and such) */
00434                      /* should be extended to support comma separated list of
00435                       *     [!]key[=value] parameters, e.g.  -e !foo,bar=567
00436                       */
00437 
00438                      crit = 0;
00439                      cvalue = NULL;
00440                      if( optarg[0] == '!' ) {
00441                             crit = 1;
00442                             optarg++;
00443                      }
00444 
00445                      control = ber_strdup( optarg );
00446                      if ( (cvalue = strchr( control, '=' )) != NULL ) {
00447                             *cvalue++ = '\0';
00448                      }
00449 
00450                      if ( strcasecmp( control, "assert" ) == 0 ) {
00451                             if( assertctl ) {
00452                                    fprintf( stderr, "assert control previously specified\n");
00453                                    exit( EXIT_FAILURE );
00454                             }
00455                             if( cvalue == NULL ) {
00456                                    fprintf( stderr, "assert: control value expected\n" );
00457                                    usage();
00458                             }
00459 
00460                             assertctl = 1 + crit;
00461 
00462                             assert( assertion == NULL );
00463                             assertion = ber_strdup( cvalue );
00464 
00465                      } else if ( strcasecmp( control, "authzid" ) == 0 ) {
00466                             if( authzid != NULL ) {
00467                                    fprintf( stderr, "authzid control previously specified\n");
00468                                    exit( EXIT_FAILURE );
00469                             }
00470 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
00471                             if( proxydn != NULL ) {
00472                                    fprintf( stderr, "authzid control incompatible with proxydn\n");
00473                                    exit( EXIT_FAILURE );
00474                             }
00475 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
00476                             if( cvalue == NULL ) {
00477                                    fprintf( stderr, "authzid: control value expected\n" );
00478                                    usage();
00479                             }
00480                             if( !crit ) {
00481                                    fprintf( stderr, "authzid: must be marked critical\n" );
00482                                    usage();
00483                             }
00484 
00485                             assert( authzid == NULL );
00486                             authzid = ber_strdup( cvalue );
00487 
00488 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
00489                      } else if ( strcasecmp( control, "proxydn" ) == 0 ) {
00490                             if( proxydn != NULL ) {
00491                                    fprintf( stderr, "proxydn control previously specified\n");
00492                                    exit( EXIT_FAILURE );
00493                             }
00494                             if( authzid != NULL ) {
00495                                    fprintf( stderr, "proxydn control incompatible with authzid\n");
00496                                    exit( EXIT_FAILURE );
00497                             }
00498                             if( cvalue == NULL ) {
00499                                    fprintf( stderr, "proxydn: control value expected\n" );
00500                                    usage();
00501                             }
00502                             if( !crit ) {
00503                                    fprintf( stderr, "proxydn: must be marked critical\n" );
00504                                    usage();
00505                             }
00506 
00507                             assert( proxydn == NULL );
00508                             proxydn = ber_strdup( cvalue );
00509 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
00510 
00511                      } else if ( ( strcasecmp( control, "relax" ) == 0 ) ||
00512                             ( strcasecmp( control, "manageDIT" ) == 0 ) )
00513                      {
00514                             if( manageDIT ) {
00515                                    fprintf( stderr,
00516                                           "relax control previously specified\n");
00517                                    exit( EXIT_FAILURE );
00518                             }
00519                             if( cvalue != NULL ) {
00520                                    fprintf( stderr,
00521                                           "relax: no control value expected\n" );
00522                                    usage();
00523                             }
00524 
00525                             manageDIT = 1 + crit;
00526 
00527                      } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
00528                             if( manageDSAit ) {
00529                                    fprintf( stderr,
00530                                           "manageDSAit control previously specified\n");
00531                                    exit( EXIT_FAILURE );
00532                             }
00533                             if( cvalue != NULL ) {
00534                                    fprintf( stderr,
00535                                           "manageDSAit: no control value expected\n" );
00536                                    usage();
00537                             }
00538 
00539                             manageDSAit = 1 + crit;
00540 
00541                      } else if ( strcasecmp( control, "noop" ) == 0 ) {
00542                             if( noop ) {
00543                                    fprintf( stderr, "noop control previously specified\n");
00544                                    exit( EXIT_FAILURE );
00545                             }
00546                             if( cvalue != NULL ) {
00547                                    fprintf( stderr, "noop: no control value expected\n" );
00548                                    usage();
00549                             }
00550 
00551                             noop = 1 + crit;
00552 
00553 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
00554                      } else if ( strcasecmp( control, "ppolicy" ) == 0 ) {
00555                             if( ppolicy ) {
00556                                    fprintf( stderr, "ppolicy control previously specified\n");
00557                                    exit( EXIT_FAILURE );
00558                             }
00559                             if( cvalue != NULL ) {
00560                                    fprintf( stderr, "ppolicy: no control value expected\n" );
00561                                    usage();
00562                             }
00563                             if( crit ) {
00564                                    fprintf( stderr, "ppolicy: critical flag not allowed\n" );
00565                                    usage();
00566                             }
00567 
00568                             ppolicy = 1;
00569 #endif
00570 
00571                      } else if ( strcasecmp( control, "preread" ) == 0 ) {
00572                             if( preread ) {
00573                                    fprintf( stderr, "preread control previously specified\n");
00574                                    exit( EXIT_FAILURE );
00575                             }
00576 
00577                             preread = 1 + crit;
00578                             preread_attrs = ber_strdup( cvalue );
00579 
00580                      } else if ( strcasecmp( control, "postread" ) == 0 ) {
00581                             if( postread ) {
00582                                    fprintf( stderr, "postread control previously specified\n");
00583                                    exit( EXIT_FAILURE );
00584                             }
00585 
00586                             postread = 1 + crit;
00587                             postread_attrs = ber_strdup( cvalue );
00588 
00589 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
00590                      } else if ( strcasecmp( control, "chaining" ) == 0 ) {
00591                             chaining = 1 + crit;
00592 
00593                             if ( cvalue != NULL ) {
00594                                    char   *continuation;
00595 
00596                                    continuation = strchr( cvalue, '/' );
00597                                    if ( continuation ) {
00598                                           /* FIXME: this makes sense only in searches */
00599                                           *continuation++ = '\0';
00600                                           if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
00601                                                  chainingContinuation = LDAP_CHAINING_PREFERRED;
00602                                           } else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
00603                                                  chainingContinuation = LDAP_CHAINING_REQUIRED;
00604                                           } else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
00605                                                  chainingContinuation = LDAP_REFERRALS_PREFERRED;
00606                                           } else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
00607                                                  chainingContinuation = LDAP_REFERRALS_REQUIRED;
00608                                           } else {
00609                                                  fprintf( stderr,
00610                                                         "chaining behavior control "
00611                                                         "continuation value \"%s\" invalid\n",
00612                                                         continuation );
00613                                                  exit( EXIT_FAILURE );
00614                                           }
00615                                    }
00616        
00617                                    if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
00618                                           chainingResolve = LDAP_CHAINING_PREFERRED;
00619                                    } else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
00620                                           chainingResolve = LDAP_CHAINING_REQUIRED;
00621                                    } else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
00622                                           chainingResolve = LDAP_REFERRALS_PREFERRED;
00623                                    } else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
00624                                           chainingResolve = LDAP_REFERRALS_REQUIRED;
00625                                    } else {
00626                                           fprintf( stderr,
00627                                                  "chaining behavior control "
00628                                                  "resolve value \"%s\" invalid\n",
00629                                                  cvalue);
00630                                           exit( EXIT_FAILURE );
00631                                    }
00632                             }
00633 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
00634 
00635 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
00636                      } else if ( strcasecmp( control, "sessiontracking" ) == 0 ) {
00637                             if ( sessionTracking ) {
00638                                    fprintf( stderr, "%s: session tracking can be only specified once\n", prog );
00639                                    exit( EXIT_FAILURE );
00640                             }
00641                             sessionTracking = 1;
00642                             if( crit ) {
00643                                    fprintf( stderr, "sessiontracking: critical flag not allowed\n" );
00644                                    usage();
00645                             }
00646 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
00647 
00648                      /* this shouldn't go here, really; but it's a feature... */
00649                      } else if ( strcasecmp( control, "abandon" ) == 0 ) {
00650                             abcan = Intr_Abandon;
00651                             if ( crit ) {
00652                                    gotintr = abcan;
00653                             }
00654 
00655                      } else if ( strcasecmp( control, "cancel" ) == 0 ) {
00656                             abcan = Intr_Cancel;
00657                             if ( crit ) {
00658                                    gotintr = abcan;
00659                             }
00660 
00661                      } else if ( strcasecmp( control, "ignore" ) == 0 ) {
00662                             abcan = Intr_Ignore;
00663                             if ( crit ) {
00664                                    gotintr = abcan;
00665                             }
00666 
00667                      } else if ( tool_is_oid( control ) ) {
00668                             LDAPControl   *tmpctrls, ctrl;
00669 
00670                             tmpctrls = (LDAPControl *)ber_memrealloc( unknown_ctrls,
00671                                    (unknown_ctrls_num + 1)*sizeof( LDAPControl ) );
00672                             if ( tmpctrls == NULL ) {
00673                                    fprintf( stderr, "%s: no memory?\n", prog );
00674                                    exit( EXIT_FAILURE );
00675                             }
00676                             unknown_ctrls = tmpctrls;
00677                             ctrl.ldctl_oid = control;
00678                             /* don't free it */
00679                             control = NULL;
00680                             ctrl.ldctl_value.bv_val = NULL;
00681                             ctrl.ldctl_value.bv_len = 0;
00682                             ctrl.ldctl_iscritical = crit;
00683 
00684                             if ( cvalue != NULL ) {
00685                                    struct berval bv;
00686                                    size_t        len = strlen( cvalue );
00687                                    int           retcode;
00688 
00689                                    bv.bv_len = LUTIL_BASE64_DECODE_LEN( len );
00690                                    bv.bv_val = ber_memalloc( bv.bv_len + 1 );
00691 
00692                                    retcode = lutil_b64_pton( cvalue,
00693                                           (unsigned char *)bv.bv_val,
00694                                           bv.bv_len );
00695 
00696                                    if ( retcode == -1 || (unsigned) retcode > bv.bv_len ) {
00697                                           fprintf( stderr, "Unable to parse value of general control %s\n",
00698                                                  control );
00699                                           usage();
00700                                    }
00701 
00702                                    bv.bv_len = retcode;
00703                                    ctrl.ldctl_value = bv;
00704                             }
00705 
00706                             unknown_ctrls[ unknown_ctrls_num ] = ctrl;
00707                             unknown_ctrls_num++;
00708 
00709                      } else {
00710                             fprintf( stderr, "Invalid general control name: %s\n",
00711                                    control );
00712                             usage();
00713                      }
00714                      if ( control ) {
00715                             ber_memfree( control );      
00716                             control = NULL;
00717                      }
00718                      break;
00719               case 'f':     /* read from file */
00720                      if( infile != NULL ) {
00721                             fprintf( stderr, "%s: -f previously specified\n", prog );
00722                             exit( EXIT_FAILURE );
00723                      }
00724                      infile = ber_strdup( optarg );
00725                      break;
00726               case 'h':     /* ldap host */
00727                      if( ldaphost != NULL ) {
00728                             fprintf( stderr, "%s: -h previously specified\n", prog );
00729                             exit( EXIT_FAILURE );
00730                      }
00731                      ldaphost = ber_strdup( optarg );
00732                      break;
00733               case 'H':     /* ldap URI */
00734                      if( ldapuri != NULL ) {
00735                             fprintf( stderr, "%s: -H previously specified\n", prog );
00736                             exit( EXIT_FAILURE );
00737                      }
00738                      ldapuri = ber_strdup( optarg );
00739                      break;
00740               case 'I':
00741 #ifdef HAVE_CYRUS_SASL
00742                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00743                             fprintf( stderr, "%s: incompatible previous "
00744                                    "authentication choice\n",
00745                                    prog );
00746                             exit( EXIT_FAILURE );
00747                      }
00748                      authmethod = LDAP_AUTH_SASL;
00749                      sasl_flags = LDAP_SASL_INTERACTIVE;
00750                      break;
00751 #else
00752                      fprintf( stderr, "%s: was not compiled with SASL support\n",
00753                             prog );
00754                      exit( EXIT_FAILURE );
00755 #endif
00756               case 'M':
00757                      /* enable Manage DSA IT */
00758                      manageDSAit++;
00759                      break;
00760               case 'n':     /* print operations, don't actually do them */
00761                      dont++;
00762                      break;
00763               case 'N':
00764                      nocanon++;
00765                      break;
00766               case 'o':
00767                      control = ber_strdup( optarg );
00768                      if ( (cvalue = strchr( control, '=' )) != NULL ) {
00769                             *cvalue++ = '\0';
00770                      }
00771 
00772                      if ( strcasecmp( control, "nettimeout" ) == 0 ) {
00773                             if( nettimeout.tv_sec != -1 ) {
00774                                    fprintf( stderr, "nettimeout option previously specified\n");
00775                                    exit( EXIT_FAILURE );
00776                             }
00777                             if( cvalue == NULL || cvalue[0] == '\0' ) {
00778                                    fprintf( stderr, "nettimeout: option value expected\n" );
00779                                    usage();
00780                             }
00781                             if ( strcasecmp( cvalue, "none" ) == 0 ) {
00782                                    nettimeout.tv_sec = 0;
00783                             } else if ( strcasecmp( cvalue, "max" ) == 0 ) {
00784                                    nettimeout.tv_sec = LDAP_MAXINT;
00785                             } else {
00786                                    ival = strtol( cvalue, &next, 10 );
00787                                    if ( next == NULL || next[0] != '\0' ) {
00788                                           fprintf( stderr,
00789                                                  _("Unable to parse network timeout \"%s\"\n"), cvalue );
00790                                           exit( EXIT_FAILURE );
00791                                    }
00792                                    nettimeout.tv_sec = ival;
00793                             }
00794                             if( nettimeout.tv_sec < 0 || nettimeout.tv_sec > LDAP_MAXINT ) {
00795                                    fprintf( stderr, _("%s: invalid network timeout (%ld) specified\n"),
00796                                           prog, (long)nettimeout.tv_sec );
00797                                    exit( EXIT_FAILURE );
00798                             }
00799 
00800                      } else if ( strcasecmp( control, "ldif-wrap" ) == 0 ) {
00801                             if ( cvalue == 0 ) {
00802                                    ldif_wrap = LDIF_LINE_WIDTH;
00803 
00804                             } else if ( strcasecmp( cvalue, "no" ) == 0 ) {
00805                                    ldif_wrap = LDIF_LINE_WIDTH_MAX;
00806 
00807                             } else {
00808                                    unsigned int u;
00809                                    if ( lutil_atou( &u, cvalue ) ) {
00810                                           fprintf( stderr,
00811                                                  _("Unable to parse ldif-wrap=\"%s\"\n"), cvalue );
00812                                           exit( EXIT_FAILURE );
00813                                    }
00814                                    ldif_wrap = (ber_len_t)u;
00815                             }
00816 
00817                      } else {
00818                             fprintf( stderr, "Invalid general option name: %s\n",
00819                                    control );
00820                             usage();
00821                      }
00822                      ber_memfree(control);
00823                      break;
00824               case 'O':
00825 #ifdef HAVE_CYRUS_SASL
00826                      if( sasl_secprops != NULL ) {
00827                             fprintf( stderr, "%s: -O previously specified\n", prog );
00828                             exit( EXIT_FAILURE );
00829                      }
00830                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00831                             fprintf( stderr, "%s: incompatible previous "
00832                                    "authentication choice\n", prog );
00833                             exit( EXIT_FAILURE );
00834                      }
00835                      authmethod = LDAP_AUTH_SASL;
00836                      sasl_secprops = ber_strdup( optarg );
00837 #else
00838                      fprintf( stderr, "%s: not compiled with SASL support\n", prog );
00839                      exit( EXIT_FAILURE );
00840 #endif
00841                      break;
00842               case 'p':
00843                      if( ldapport ) {
00844                             fprintf( stderr, "%s: -p previously specified\n", prog );
00845                             exit( EXIT_FAILURE );
00846                      }
00847                      ival = strtol( optarg, &next, 10 );
00848                      if ( next == NULL || next[0] != '\0' ) {
00849                             fprintf( stderr, "%s: unable to parse port number \"%s\"\n", prog, optarg );
00850                             exit( EXIT_FAILURE );
00851                      }
00852                      ldapport = ival;
00853                      break;
00854               case 'P':
00855                      ival = strtol( optarg, &next, 10 );
00856                      if ( next == NULL || next[0] != '\0' ) {
00857                             fprintf( stderr, "%s: unable to parse protocol version \"%s\"\n", prog, optarg );
00858                             exit( EXIT_FAILURE );
00859                      }
00860                      switch( ival ) {
00861                      case 2:
00862                             if( protocol == LDAP_VERSION3 ) {
00863                                    fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
00864                                           prog, protocol );
00865                                    exit( EXIT_FAILURE );
00866                             }
00867                             protocol = LDAP_VERSION2;
00868                             break;
00869                      case 3:
00870                             if( protocol == LDAP_VERSION2 ) {
00871                                    fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
00872                                           prog, protocol );
00873                                    exit( EXIT_FAILURE );
00874                             }
00875                             protocol = LDAP_VERSION3;
00876                             break;
00877                      default:
00878                             fprintf( stderr, "%s: protocol version should be 2 or 3\n",
00879                                    prog );
00880                             usage();
00881                      }
00882                      break;
00883               case 'Q':
00884 #ifdef HAVE_CYRUS_SASL
00885                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00886                             fprintf( stderr, "%s: incompatible previous "
00887                                    "authentication choice\n",
00888                                    prog );
00889                             exit( EXIT_FAILURE );
00890                      }
00891                      authmethod = LDAP_AUTH_SASL;
00892                      sasl_flags = LDAP_SASL_QUIET;
00893                      break;
00894 #else
00895                      fprintf( stderr, "%s: not compiled with SASL support\n",
00896                             prog );
00897                      exit( EXIT_FAILURE );
00898 #endif
00899               case 'R':
00900 #ifdef HAVE_CYRUS_SASL
00901                      if( sasl_realm != NULL ) {
00902                             fprintf( stderr, "%s: -R previously specified\n", prog );
00903                             exit( EXIT_FAILURE );
00904                      }
00905                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00906                             fprintf( stderr, "%s: incompatible previous "
00907                                    "authentication choice\n",
00908                                    prog );
00909                             exit( EXIT_FAILURE );
00910                      }
00911                      authmethod = LDAP_AUTH_SASL;
00912                      sasl_realm = ber_strdup( optarg );
00913 #else
00914                      fprintf( stderr, "%s: not compiled with SASL support\n",
00915                             prog );
00916                      exit( EXIT_FAILURE );
00917 #endif
00918                      break;
00919               case 'U':
00920 #ifdef HAVE_CYRUS_SASL
00921                      if( sasl_authc_id != NULL ) {
00922                             fprintf( stderr, "%s: -U previously specified\n", prog );
00923                             exit( EXIT_FAILURE );
00924                      }
00925                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00926                             fprintf( stderr, "%s: incompatible previous "
00927                                    "authentication choice\n",
00928                                    prog );
00929                             exit( EXIT_FAILURE );
00930                      }
00931                      authmethod = LDAP_AUTH_SASL;
00932                      sasl_authc_id = ber_strdup( optarg );
00933 #else
00934                      fprintf( stderr, "%s: not compiled with SASL support\n",
00935                             prog );
00936                      exit( EXIT_FAILURE );
00937 #endif
00938                      break;
00939               case 'v':     /* verbose mode */
00940                      verbose++;
00941                      break;
00942               case 'V':     /* version */
00943                      version++;
00944                      break;
00945               case 'w':     /* password */
00946                      passwd.bv_val = ber_strdup( optarg );
00947                      {
00948                             char* p;
00949 
00950                             for( p = optarg; *p != '\0'; p++ ) {
00951                                    *p = '\0';
00952                             }
00953                      }
00954                      passwd.bv_len = strlen( passwd.bv_val );
00955                      break;
00956               case 'W':
00957                      want_bindpw++;
00958                      break;
00959               case 'y':
00960                      pw_file = optarg;
00961                      break;
00962               case 'Y':
00963 #ifdef HAVE_CYRUS_SASL
00964                      if( sasl_mech != NULL ) {
00965                             fprintf( stderr, "%s: -Y previously specified\n", prog );
00966                             exit( EXIT_FAILURE );
00967                      }
00968                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00969                             fprintf( stderr,
00970                                    "%s: incompatible with authentication choice\n", prog );
00971                             exit( EXIT_FAILURE );
00972                      }
00973                      authmethod = LDAP_AUTH_SASL;
00974                      sasl_mech = ber_strdup( optarg );
00975 #else
00976                      fprintf( stderr, "%s: not compiled with SASL support\n", prog );
00977                      exit( EXIT_FAILURE );
00978 #endif
00979                      break;
00980               case 'x':
00981                      if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
00982                             fprintf( stderr, "%s: incompatible with previous "
00983                                    "authentication choice\n", prog );
00984                             exit( EXIT_FAILURE );
00985                      }
00986                      authmethod = LDAP_AUTH_SIMPLE;
00987                      break;
00988               case 'X':
00989 #ifdef HAVE_CYRUS_SASL
00990                      if( sasl_authz_id != NULL ) {
00991                             fprintf( stderr, "%s: -X previously specified\n", prog );
00992                             exit( EXIT_FAILURE );
00993                      }
00994                      if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
00995                             fprintf( stderr, "%s: -X incompatible with "
00996                                    "authentication choice\n", prog );
00997                             exit( EXIT_FAILURE );
00998                      }
00999                      authmethod = LDAP_AUTH_SASL;
01000                      sasl_authz_id = ber_strdup( optarg );
01001 #else
01002                      fprintf( stderr, "%s: not compiled with SASL support\n", prog );
01003                      exit( EXIT_FAILURE );
01004 #endif
01005                      break;
01006               case 'Z':
01007 #ifdef HAVE_TLS
01008                      use_tls++;
01009 #else
01010                      fprintf( stderr, "%s: not compiled with TLS support\n", prog );
01011                      exit( EXIT_FAILURE );
01012 #endif
01013                      break;
01014               default:
01015                      if( handle_private_option( i ) ) break;
01016                      fprintf( stderr, "%s: unrecognized option -%c\n",
01017                             prog, optopt );
01018                      usage();
01019               }
01020        }
01021 
01022        {
01023               /* prevent bad linking */
01024               LDAPAPIInfo api;
01025               api.ldapai_info_version = LDAP_API_INFO_VERSION;
01026 
01027               if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
01028                      != LDAP_OPT_SUCCESS )
01029               {
01030                      fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
01031                      exit( EXIT_FAILURE );
01032               }
01033 
01034               if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
01035                      fprintf( stderr, "LDAP APIInfo version mismatch: "
01036                             "library %d, header %d\n",
01037                             api.ldapai_info_version, LDAP_API_INFO_VERSION );
01038                      exit( EXIT_FAILURE );
01039               }
01040 
01041               if( api.ldapai_api_version != LDAP_API_VERSION ) {
01042                      fprintf( stderr, "LDAP API version mismatch: "
01043                             "library %d, header %d\n",
01044                             api.ldapai_api_version, LDAP_API_VERSION );
01045                      exit( EXIT_FAILURE );
01046               }
01047 
01048               if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
01049                      fprintf( stderr, "LDAP vendor name mismatch: "
01050                             "library %s, header %s\n",
01051                             api.ldapai_vendor_name, LDAP_VENDOR_NAME );
01052                      exit( EXIT_FAILURE );
01053               }
01054 
01055               if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
01056                      fprintf( stderr, "LDAP vendor version mismatch: "
01057                             "library %d, header %d\n",
01058                             api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
01059                      exit( EXIT_FAILURE );
01060               }
01061 
01062               if (version) {
01063                      fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
01064                             prog, __Version,
01065                             LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
01066                      if (version > 1) exit( EXIT_SUCCESS );
01067               }
01068 
01069               ldap_memfree( api.ldapai_vendor_name );
01070               ber_memvfree( (void **)api.ldapai_extensions );
01071        }
01072 
01073        if (protocol == -1)
01074               protocol = LDAP_VERSION3;
01075 
01076        if (authmethod == -1 && protocol > LDAP_VERSION2) {
01077 #ifdef HAVE_CYRUS_SASL
01078               if ( binddn != NULL ) {
01079                      authmethod = LDAP_AUTH_SIMPLE;
01080               } else {
01081                      authmethod = LDAP_AUTH_SASL;
01082               }
01083 #else
01084               authmethod = LDAP_AUTH_SIMPLE;
01085 #endif
01086        }
01087 
01088        if( ldapuri == NULL ) {
01089               if( ldapport && ( ldaphost == NULL )) {
01090                      fprintf( stderr, "%s: -p without -h is invalid.\n", prog );
01091                      exit( EXIT_FAILURE );
01092               }
01093        } else {
01094               if( ldaphost != NULL ) {
01095                      fprintf( stderr, "%s: -H incompatible with -h\n", prog );
01096                      exit( EXIT_FAILURE );
01097               }
01098               if( ldapport ) {
01099                      fprintf( stderr, "%s: -H incompatible with -p\n", prog );
01100                      exit( EXIT_FAILURE );
01101               }
01102        }
01103 
01104        if( protocol == LDAP_VERSION2 ) {
01105               if( assertctl || authzid || manageDIT || manageDSAit ||
01106 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
01107                      proxydn ||
01108 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
01109 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
01110                      chaining ||
01111 #endif
01112 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
01113                      sessionTracking ||
01114 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
01115                      noop || ppolicy || preread || postread )
01116               {
01117                      fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
01118                      exit( EXIT_FAILURE );
01119               }
01120 #ifdef HAVE_TLS
01121               if( use_tls ) {
01122                      fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
01123                      exit( EXIT_FAILURE );
01124               }
01125 #endif
01126 #ifdef HAVE_CYRUS_SASL
01127               if( authmethod == LDAP_AUTH_SASL ) {
01128                      fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
01129                             prog );
01130                      exit( EXIT_FAILURE );
01131               }
01132 #endif
01133        }
01134 
01135        if ( ( pw_file || want_bindpw ) && !BER_BVISNULL( &passwd ) ) {
01136               fprintf( stderr, "%s: -%c incompatible with -w\n",
01137                      prog, ( pw_file ? 'y' : 'W' ) );
01138               exit( EXIT_FAILURE );
01139        }
01140 }
01141 
01142 
01143 LDAP *
01144 tool_conn_setup( int dont, void (*private_setup)( LDAP * ) )
01145 {
01146        LDAP *ld = NULL;
01147 
01148        if ( debug ) {
01149               if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
01150                      != LBER_OPT_SUCCESS )
01151               {
01152                      fprintf( stderr,
01153                             "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
01154               }
01155               if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
01156                      != LDAP_OPT_SUCCESS )
01157               {
01158                      fprintf( stderr,
01159                             "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
01160               }
01161        }
01162 
01163 #ifdef SIGPIPE
01164        (void) SIGNAL( SIGPIPE, SIG_IGN );
01165 #endif
01166 
01167        if ( abcan ) {
01168               SIGNAL( SIGINT, do_sig );
01169        }
01170 
01171        if ( !dont ) {
01172               int rc;
01173 
01174               if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
01175                      /* construct URL */
01176                      LDAPURLDesc url;
01177                      memset( &url, 0, sizeof(url));
01178 
01179                      url.lud_scheme = "ldap";
01180                      url.lud_host = ldaphost;
01181                      url.lud_port = ldapport;
01182                      url.lud_scope = LDAP_SCOPE_DEFAULT;
01183 
01184                      ldapuri = ldap_url_desc2str( &url );
01185 
01186               } else if ( ldapuri != NULL ) {
01187                      LDAPURLDesc   *ludlist, **ludp;
01188                      char          **urls = NULL;
01189                      int           nurls = 0;
01190 
01191                      rc = ldap_url_parselist( &ludlist, ldapuri );
01192                      if ( rc != LDAP_URL_SUCCESS ) {
01193                             fprintf( stderr,
01194                                    "Could not parse LDAP URI(s)=%s (%d)\n",
01195                                    ldapuri, rc );
01196                             exit( EXIT_FAILURE );
01197                      }
01198 
01199                      for ( ludp = &ludlist; *ludp != NULL; ) {
01200                             LDAPURLDesc   *lud = *ludp;
01201                             char          **tmp;
01202 
01203                             if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' &&
01204                                    ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) )
01205                             {
01206                                    /* if no host but a DN is provided,
01207                                     * use DNS SRV to gather the host list
01208                                     * and turn it into a list of URIs
01209                                     * using the scheme provided */
01210                                    char   *domain = NULL,
01211                                           *hostlist = NULL,
01212                                           **hosts = NULL;
01213                                    int    i,
01214                                           len_proto = strlen( lud->lud_scheme );
01215 
01216                                    if ( ldap_dn2domain( lud->lud_dn, &domain )
01217                                           || domain == NULL )
01218                                    {
01219                                           fprintf( stderr,
01220                                                  "DNS SRV: Could not turn "
01221                                                  "DN=\"%s\" into a domain\n",
01222                                                  lud->lud_dn );
01223                                           goto dnssrv_free;
01224                                    }
01225                                    
01226                                    rc = ldap_domain2hostlist( domain, &hostlist );
01227                                    if ( rc ) {
01228                                           fprintf( stderr,
01229                                                  "DNS SRV: Could not turn "
01230                                                  "domain=%s into a hostlist\n",
01231                                                  domain );
01232                                           goto dnssrv_free;
01233                                    }
01234 
01235                                    hosts = ldap_str2charray( hostlist, " " );
01236                                    if ( hosts == NULL ) {
01237                                           fprintf( stderr,
01238                                                  "DNS SRV: Could not parse "
01239                                                  "hostlist=\"%s\"\n",
01240                                                  hostlist );
01241                                           goto dnssrv_free;
01242                                    }
01243 
01244                                    for ( i = 0; hosts[ i ] != NULL; i++ )
01245                                           /* count'em */ ;
01246 
01247                                    tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + i + 1 ) );
01248                                    if ( tmp == NULL ) {
01249                                           fprintf( stderr,
01250                                                  "DNS SRV: out of memory?\n" );
01251                                           goto dnssrv_free;
01252                                    }
01253                                    urls = tmp;
01254                                    urls[ nurls ] = NULL;
01255 
01256                                    for ( i = 0; hosts[ i ] != NULL; i++ ) {
01257                                           size_t len = len_proto
01258                                                  + STRLENOF( "://" )
01259                                                  + strlen( hosts[ i ] )
01260                                                  + 1;
01261 
01262                                           urls[ nurls + i + 1 ] = NULL;
01263                                           urls[ nurls + i ] = (char *)malloc( sizeof( char ) * len );
01264                                           if ( urls[ nurls + i ] == NULL ) {
01265                                                  fprintf( stderr,
01266                                                         "DNS SRV: out of memory?\n" );
01267                                                  goto dnssrv_free;
01268                                           }
01269 
01270                                           snprintf( urls[ nurls + i ], len, "%s://%s",
01271                                                  lud->lud_scheme, hosts[ i ] );
01272                                    }
01273                                    nurls += i;
01274 
01275 dnssrv_free:;
01276                                    ber_memvfree( (void **)hosts );
01277                                    ber_memfree( hostlist );
01278                                    ber_memfree( domain );
01279 
01280                             } else {
01281                                    tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + 2 ) );
01282                                    if ( tmp == NULL ) {
01283                                           fprintf( stderr,
01284                                                  "DNS SRV: out of memory?\n" );
01285                                           break;
01286                                    }
01287                                    urls = tmp;
01288                                    urls[ nurls + 1 ] = NULL;
01289 
01290                                    urls[ nurls ] = ldap_url_desc2str( lud );
01291                                    if ( urls[ nurls ] == NULL ) {
01292                                           fprintf( stderr,
01293                                                  "DNS SRV: out of memory?\n" );
01294                                           break;
01295                                    }
01296                                    nurls++;
01297                             }
01298 
01299                             *ludp = lud->lud_next;
01300 
01301                             lud->lud_next = NULL;
01302                             ldap_free_urldesc( lud );
01303                      }
01304 
01305                      if ( ludlist != NULL ) {
01306                             ldap_free_urllist( ludlist );
01307                             exit( EXIT_FAILURE );
01308 
01309                      } else if ( urls == NULL ) {
01310                             exit( EXIT_FAILURE );
01311                      }
01312 
01313                      ldap_memfree( ldapuri );
01314                      ldapuri = ldap_charray2str( urls, " " );
01315                      ber_memvfree( (void **)urls );
01316               }
01317 
01318               if ( verbose ) {
01319                      fprintf( stderr, "ldap_initialize( %s )\n",
01320                             ldapuri != NULL ? ldapuri : "<DEFAULT>" );
01321               }
01322               rc = ldap_initialize( &ld, ldapuri );
01323               if( rc != LDAP_SUCCESS ) {
01324                      fprintf( stderr,
01325                             "Could not create LDAP session handle for URI=%s (%d): %s\n",
01326                             ldapuri, rc, ldap_err2string(rc) );
01327                      exit( EXIT_FAILURE );
01328               }
01329 
01330               if( private_setup ) private_setup( ld );
01331 
01332               /* referrals: obsolete */
01333               if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
01334                      referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
01335               {
01336                      fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
01337                             referrals ? "on" : "off" );
01338                      tool_exit( ld, EXIT_FAILURE );
01339               }
01340 
01341 #ifdef HAVE_CYRUS_SASL
01342               /* canon */
01343               if( ldap_set_option( ld, LDAP_OPT_X_SASL_NOCANON,
01344                      nocanon ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
01345               {
01346                      fprintf( stderr, "Could not set LDAP_OPT_X_SASL_NOCANON %s\n",
01347                             nocanon ? "on" : "off" );
01348                      tool_exit( ld, EXIT_FAILURE );
01349               }
01350 #endif
01351               if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
01352                      != LDAP_OPT_SUCCESS )
01353               {
01354                      fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
01355                             protocol );
01356                      tool_exit( ld, EXIT_FAILURE );
01357               }
01358 
01359               if ( use_tls ) {
01360                      rc = ldap_start_tls_s( ld, NULL, NULL );
01361                      if ( rc != LDAP_SUCCESS ) {
01362                             char *msg=NULL;
01363                             ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
01364                             tool_perror( "ldap_start_tls", rc, NULL, NULL, msg, NULL );
01365                             ldap_memfree(msg);
01366                             if ( use_tls > 1 ) {
01367                                    tool_exit( ld, EXIT_FAILURE );
01368                             }
01369                      }
01370               }
01371 
01372               if ( nettimeout.tv_sec > 0 ) {
01373                      if ( ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, (void *) &nettimeout )
01374                             != LDAP_OPT_SUCCESS )
01375                      {
01376                             fprintf( stderr, "Could not set LDAP_OPT_NETWORK_TIMEOUT %ld\n",
01377                                    (long)nettimeout.tv_sec );
01378                             tool_exit( ld, EXIT_FAILURE );
01379                      }
01380               }
01381        }
01382 
01383        return ld;
01384 }
01385 
01386 
01387 void
01388 tool_bind( LDAP *ld )
01389 {
01390        LDAPControl   **sctrlsp = NULL;
01391        LDAPControl   *sctrls[3];
01392        LDAPControl   sctrl[3];
01393        int           nsctrls = 0;
01394 
01395 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
01396        if ( ppolicy ) {
01397               LDAPControl c;
01398               c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
01399               c.ldctl_value.bv_val = NULL;
01400               c.ldctl_value.bv_len = 0;
01401               c.ldctl_iscritical = 0;
01402               sctrl[nsctrls] = c;
01403               sctrls[nsctrls] = &sctrl[nsctrls];
01404               sctrls[++nsctrls] = NULL;
01405        }
01406 #endif
01407 
01408 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
01409        if ( sessionTracking ) {
01410               LDAPControl c;
01411 
01412               if ( BER_BVISNULL( &stValue) && st_value( ld, &stValue ) ) {
01413                      tool_exit( ld, EXIT_FAILURE );
01414               }
01415 
01416               c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
01417               c.ldctl_iscritical = 0;
01418               ber_dupbv( &c.ldctl_value, &stValue );
01419 
01420               sctrl[nsctrls] = c;
01421               sctrls[nsctrls] = &sctrl[nsctrls];
01422               sctrls[++nsctrls] = NULL;
01423        }
01424 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
01425 
01426        if ( nsctrls ) {
01427               sctrlsp = sctrls;
01428        }
01429 
01430        assert( nsctrls < (int) (sizeof(sctrls)/sizeof(sctrls[0])) );
01431 
01432        if ( pw_file || want_bindpw ) {
01433               assert( passwd.bv_val == NULL && passwd.bv_len == 0 );
01434 
01435               if ( pw_file ) {
01436                      if ( lutil_get_filed_password( pw_file, &passwd ) ) {
01437                             tool_exit( ld, EXIT_FAILURE );
01438                      }
01439 
01440               } else {
01441                      char *pw = getpassphrase( _("Enter LDAP Password: ") );
01442                      if ( pw ) {
01443                             passwd.bv_val = ber_strdup( pw );
01444                             passwd.bv_len = strlen( passwd.bv_val );
01445                      }
01446               }
01447        }
01448 
01449        if ( authmethod == LDAP_AUTH_SASL ) {
01450 #ifdef HAVE_CYRUS_SASL
01451               void *defaults;
01452               int rc;
01453 
01454               if( sasl_secprops != NULL ) {
01455                      rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
01456                             (void *) sasl_secprops );
01457 
01458                      if( rc != LDAP_OPT_SUCCESS ) {
01459                             fprintf( stderr,
01460                                    "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
01461                                    sasl_secprops );
01462                             tool_exit( ld, LDAP_LOCAL_ERROR );
01463                      }
01464               }
01465 
01466               defaults = lutil_sasl_defaults( ld,
01467                      sasl_mech,
01468                      sasl_realm,
01469                      sasl_authc_id,
01470                      passwd.bv_val,
01471                      sasl_authz_id );
01472 
01473               rc = ldap_sasl_interactive_bind_s( ld, binddn, sasl_mech,
01474                      sctrlsp,
01475                      NULL, sasl_flags, lutil_sasl_interact, defaults );
01476 
01477               lutil_sasl_freedefs( defaults );
01478               if( rc != LDAP_SUCCESS ) {
01479                      char *msg=NULL;
01480                      ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
01481                      tool_perror( "ldap_sasl_interactive_bind_s",
01482                             rc, NULL, NULL, msg, NULL );
01483                      ldap_memfree(msg);
01484                      tool_exit( ld, rc );
01485               }
01486 #else
01487               fprintf( stderr, "%s: not compiled with SASL support\n", prog );
01488               tool_exit( ld, LDAP_NOT_SUPPORTED );
01489 #endif
01490        } else {
01491               int msgid, err, rc;
01492               LDAPMessage *result;
01493               LDAPControl **ctrls;
01494               char msgbuf[256];
01495               char *matched = NULL;
01496               char *info = NULL;
01497               char **refs = NULL;
01498 
01499               msgbuf[0] = 0;
01500 
01501               {
01502                      /* simple bind */
01503                      rc = ldap_sasl_bind( ld, binddn, LDAP_SASL_SIMPLE, &passwd,
01504                             sctrlsp, NULL, &msgid );
01505                      if ( msgid == -1 ) {
01506                             tool_perror( "ldap_sasl_bind(SIMPLE)", rc,
01507                                    NULL, NULL, NULL, NULL );
01508                             tool_exit( ld, rc );
01509                      }
01510               }
01511 
01512               rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result );
01513               if ( rc == -1 ) {
01514                      tool_perror( "ldap_result", -1, NULL, NULL, NULL, NULL );
01515                      tool_exit( ld, LDAP_LOCAL_ERROR );
01516               }
01517 
01518               if ( rc == 0 ) {
01519                      tool_perror( "ldap_result", LDAP_TIMEOUT, NULL, NULL, NULL, NULL );
01520                      tool_exit( ld, LDAP_LOCAL_ERROR );
01521               }
01522 
01523               rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs,
01524                      &ctrls, 1 );
01525               if ( rc != LDAP_SUCCESS ) {
01526                      tool_perror( "ldap_bind parse result", rc, NULL, matched, info, refs );
01527                      tool_exit( ld, LDAP_LOCAL_ERROR );
01528               }
01529 
01530 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
01531               if ( ctrls && ppolicy ) {
01532                      LDAPControl *ctrl;
01533                      int expire, grace, len = 0;
01534                      LDAPPasswordPolicyError pErr = -1;
01535                      
01536                      ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
01537                             ctrls, NULL );
01538 
01539                      if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl,
01540                             &expire, &grace, &pErr ) == LDAP_SUCCESS )
01541                      {
01542                             if ( pErr != PP_noError ){
01543                                    msgbuf[0] = ';';
01544                                    msgbuf[1] = ' ';
01545                                    strcpy( msgbuf+2, ldap_passwordpolicy_err2txt( pErr ));
01546                                    len = strlen( msgbuf );
01547                             }
01548                             if ( expire >= 0 ) {
01549                                    sprintf( msgbuf+len,
01550                                           " (Password expires in %d seconds)",
01551                                           expire );
01552                             } else if ( grace >= 0 ) {
01553                                    sprintf( msgbuf+len,
01554                                           " (Password expired, %d grace logins remain)",
01555                                           grace );
01556                             }
01557                      }
01558               }
01559 #endif
01560 
01561               if ( ctrls ) {
01562                      ldap_controls_free( ctrls );
01563               }
01564 
01565               if ( err != LDAP_SUCCESS
01566                      || msgbuf[0]
01567                      || ( matched && matched[ 0 ] )
01568                      || ( info && info[ 0 ] )
01569                      || refs )
01570               {
01571                      tool_perror( "ldap_bind", err, msgbuf, matched, info, refs );
01572 
01573                      if( matched ) ber_memfree( matched );
01574                      if( info ) ber_memfree( info );
01575                      if( refs ) ber_memvfree( (void **)refs );
01576 
01577                      if ( err != LDAP_SUCCESS ) tool_exit( ld, err );
01578               }
01579        }
01580 }
01581 
01582 void
01583 tool_unbind( LDAP *ld )
01584 {
01585        int err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
01586 
01587        if ( err != LDAP_OPT_SUCCESS ) {
01588               fprintf( stderr, "Could not unset controls\n");
01589        }
01590 
01591        (void) ldap_unbind_ext( ld, NULL, NULL );
01592 }
01593 
01594 void
01595 tool_exit( LDAP *ld, int status )
01596 {
01597        if ( ld != NULL ) {
01598               tool_unbind( ld );
01599        }
01600        tool_destroy();
01601        exit( status );
01602 }
01603 
01604 
01605 /* Set server controls.  Add controls extra_c[0..count-1], if set. */
01606 void
01607 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
01608 {
01609        int i = 0, j, crit = 0, err;
01610        LDAPControl c[16], **ctrls;
01611 
01612        if ( ! ( assertctl
01613               || authzid
01614 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
01615               || proxydn
01616 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
01617               || manageDIT
01618               || manageDSAit
01619               || noop
01620 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
01621               || ppolicy
01622 #endif
01623               || preread
01624               || postread
01625 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
01626               || chaining
01627 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
01628 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
01629               || sessionTracking
01630 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
01631               || count
01632               || unknown_ctrls_num ) )
01633        {
01634               return;
01635        }
01636 
01637        ctrls = (LDAPControl**) malloc(sizeof(c) + (count + unknown_ctrls_num + 1)*sizeof(LDAPControl*));
01638        if ( ctrls == NULL ) {
01639               fprintf( stderr, "No memory\n" );
01640               tool_exit( ld, EXIT_FAILURE );
01641        }
01642 
01643        if ( assertctl ) {
01644               if ( BER_BVISNULL( &assertionvalue ) ) {
01645                      err = ldap_create_assertion_control_value( ld,
01646                             assertion, &assertionvalue );
01647                      if ( err ) {
01648                             fprintf( stderr,
01649                                    "Unable to create assertion value "
01650                                    "\"%s\" (%d)\n", assertion, err );
01651                      }
01652               }
01653 
01654               c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
01655               c[i].ldctl_value = assertionvalue;
01656               c[i].ldctl_iscritical = assertctl > 1;
01657               ctrls[i] = &c[i];
01658               i++;
01659        }
01660 
01661        if ( authzid ) {
01662               c[i].ldctl_value.bv_val = authzid;
01663               c[i].ldctl_value.bv_len = strlen( authzid );
01664               c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
01665               c[i].ldctl_iscritical = 1;
01666               ctrls[i] = &c[i];
01667               i++;
01668        }
01669 
01670 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
01671        /* NOTE: doesn't need an extra count because it's incompatible
01672         * with authzid */
01673        if ( proxydn ) {
01674               BerElementBuffer berbuf;
01675               BerElement *ber = (BerElement *)&berbuf;
01676               
01677               ber_init2( ber, NULL, LBER_USE_DER );
01678 
01679               if ( ber_printf( ber, "s", proxydn ) == -1 ) {
01680                      tool_exit( ld, EXIT_FAILURE );
01681               }
01682 
01683               if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
01684                      tool_exit( ld, EXIT_FAILURE );
01685               }
01686 
01687               c[i].ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
01688               c[i].ldctl_iscritical = 1;
01689               ctrls[i] = &c[i];
01690               i++;
01691        }
01692 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
01693 
01694        if ( manageDIT ) {
01695               c[i].ldctl_oid = LDAP_CONTROL_MANAGEDIT;
01696               BER_BVZERO( &c[i].ldctl_value );
01697               c[i].ldctl_iscritical = manageDIT > 1;
01698               ctrls[i] = &c[i];
01699               i++;
01700        }
01701 
01702        if ( manageDSAit ) {
01703               c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
01704               BER_BVZERO( &c[i].ldctl_value );
01705               c[i].ldctl_iscritical = manageDSAit > 1;
01706               ctrls[i] = &c[i];
01707               i++;
01708        }
01709 
01710        if ( noop ) {
01711               c[i].ldctl_oid = LDAP_CONTROL_NOOP;
01712               BER_BVZERO( &c[i].ldctl_value );
01713               c[i].ldctl_iscritical = noop > 1;
01714               ctrls[i] = &c[i];
01715               i++;
01716        }
01717 
01718 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
01719        if ( ppolicy ) {
01720               c[i].ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
01721               BER_BVZERO( &c[i].ldctl_value );
01722               c[i].ldctl_iscritical = 0;
01723               ctrls[i] = &c[i];
01724               i++;
01725        }
01726 #endif
01727 
01728        if ( preread ) {
01729               BerElementBuffer berbuf;
01730               BerElement *ber = (BerElement *)&berbuf;
01731               char **attrs = NULL;
01732 
01733               if( preread_attrs ) {
01734                      attrs = ldap_str2charray( preread_attrs, "," );
01735               }
01736 
01737               ber_init2( ber, NULL, LBER_USE_DER );
01738 
01739               if( ber_printf( ber, "{v}", attrs ) == -1 ) {
01740                      fprintf( stderr, "preread attrs encode failed.\n" );
01741                      tool_exit( ld, EXIT_FAILURE );
01742               }
01743 
01744               err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
01745               if( err < 0 ) {
01746                      fprintf( stderr, "preread flatten failed (%d)\n", err );
01747                      tool_exit( ld, EXIT_FAILURE );
01748               }
01749 
01750               c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
01751               c[i].ldctl_iscritical = preread > 1;
01752               ctrls[i] = &c[i];
01753               i++;
01754 
01755               if( attrs ) ldap_charray_free( attrs );
01756        }
01757 
01758        if ( postread ) {
01759               BerElementBuffer berbuf;
01760               BerElement *ber = (BerElement *)&berbuf;
01761               char **attrs = NULL;
01762 
01763               if( postread_attrs ) {
01764                      attrs = ldap_str2charray( postread_attrs, "," );
01765               }
01766 
01767               ber_init2( ber, NULL, LBER_USE_DER );
01768 
01769               if( ber_printf( ber, "{v}", attrs ) == -1 ) {
01770                      fprintf( stderr, "postread attrs encode failed.\n" );
01771                      tool_exit( ld, EXIT_FAILURE );
01772               }
01773 
01774               err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
01775               if( err < 0 ) {
01776                      fprintf( stderr, "postread flatten failed (%d)\n", err );
01777                      tool_exit( ld, EXIT_FAILURE );
01778               }
01779 
01780               c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
01781               c[i].ldctl_iscritical = postread > 1;
01782               ctrls[i] = &c[i];
01783               i++;
01784 
01785               if( attrs ) ldap_charray_free( attrs );
01786        }
01787 
01788 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
01789        if ( chaining ) {
01790               if ( chainingResolve > -1 ) {
01791                      BerElementBuffer berbuf;
01792                      BerElement *ber = (BerElement *)&berbuf;
01793 
01794                      ber_init2( ber, NULL, LBER_USE_DER );
01795 
01796                      err = ber_printf( ber, "{e" /* } */, chainingResolve );
01797                      if ( err == -1 ) {
01798                             ber_free( ber, 1 );
01799                             fprintf( stderr, _("Chaining behavior control encoding error!\n") );
01800                             tool_exit( ld, EXIT_FAILURE );
01801                      }
01802 
01803                      if ( chainingContinuation > -1 ) {
01804                             err = ber_printf( ber, "e", chainingContinuation );
01805                             if ( err == -1 ) {
01806                                    ber_free( ber, 1 );
01807                                    fprintf( stderr, _("Chaining behavior control encoding error!\n") );
01808                                    tool_exit( ld, EXIT_FAILURE );
01809                             }
01810                      }
01811 
01812                      err = ber_printf( ber, /* { */ "N}" );
01813                      if ( err == -1 ) {
01814                             ber_free( ber, 1 );
01815                             fprintf( stderr, _("Chaining behavior control encoding error!\n") );
01816                             tool_exit( ld, EXIT_FAILURE );
01817                      }
01818 
01819                      if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
01820                             tool_exit( ld, EXIT_FAILURE );
01821                      }
01822 
01823               } else {
01824                      BER_BVZERO( &c[i].ldctl_value );
01825               }
01826 
01827               c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
01828               c[i].ldctl_iscritical = chaining > 1;
01829               ctrls[i] = &c[i];
01830               i++;
01831        }
01832 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
01833 
01834 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
01835        if ( sessionTracking ) {
01836               if ( BER_BVISNULL( &stValue ) && st_value( ld, &stValue ) ) {
01837                      tool_exit( ld, EXIT_FAILURE );
01838               }
01839 
01840               c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
01841               c[i].ldctl_iscritical = 0;
01842               ber_dupbv( &c[i].ldctl_value, &stValue );
01843 
01844               ctrls[i] = &c[i];
01845               i++;
01846        }
01847 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
01848 
01849        while ( count-- ) {
01850               ctrls[i++] = extra_c++;
01851        }
01852        for ( count = 0; count < unknown_ctrls_num; count++ ) {
01853               ctrls[i++] = &unknown_ctrls[count];
01854        }
01855        ctrls[i] = NULL;
01856 
01857        err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
01858 
01859        if ( err != LDAP_OPT_SUCCESS ) {
01860               for ( j = 0; j < i; j++ ) {
01861                      if ( ctrls[j]->ldctl_iscritical ) crit = 1;
01862               }
01863               fprintf( stderr, "Could not set %scontrols\n",
01864                      crit ? "critical " : "" );
01865        }
01866 
01867        free( ctrls );
01868        if ( crit ) {
01869               tool_exit( ld, EXIT_FAILURE );
01870        }
01871 }
01872 
01873 int
01874 tool_check_abandon( LDAP *ld, int msgid )
01875 {
01876        int    rc;
01877 
01878        switch ( gotintr ) {
01879        case Intr_Cancel:
01880               rc = ldap_cancel_s( ld, msgid, NULL, NULL );
01881               fprintf( stderr, "got interrupt, cancel got %d: %s\n",
01882                             rc, ldap_err2string( rc ) );
01883               return -1;
01884 
01885        case Intr_Abandon:
01886               rc = ldap_abandon_ext( ld, msgid, NULL, NULL );
01887               fprintf( stderr, "got interrupt, abandon got %d: %s\n",
01888                             rc, ldap_err2string( rc ) );
01889               return -1;
01890 
01891        case Intr_Ignore:
01892               /* just unbind, ignoring the request */
01893               return -1;
01894        }
01895 
01896        return 0;
01897 }
01898 
01899 static int
01900 print_prepostread( LDAP *ld, LDAPControl *ctrl, struct berval *what)
01901 {
01902        BerElement    *ber;
01903        struct berval bv;
01904 
01905        tool_write_ldif( LDIF_PUT_COMMENT, "==> ",
01906               what->bv_val, what->bv_len );
01907        ber = ber_init( &ctrl->ldctl_value );
01908        if ( ber == NULL ) {
01909               /* error? */
01910               return 1;
01911 
01912        } else if ( ber_scanf( ber, "{m{" /*}}*/, &bv ) == LBER_ERROR ) {
01913               /* error? */
01914               return 1;
01915 
01916        } else {
01917               tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
01918 
01919               while ( ber_scanf( ber, "{m" /*}*/, &bv ) != LBER_ERROR ) {
01920                      int           i;
01921                      BerVarray     vals = NULL;
01922                      char          *str = NULL;
01923 
01924                      if ( ber_scanf( ber, "[W]", &vals ) == LBER_ERROR ||
01925                             vals == NULL )
01926                      {
01927                             /* error? */
01928                             return 1;
01929                      }
01930 
01931                      if ( ldif ) {
01932                             char *ptr;
01933 
01934                             str = malloc( bv.bv_len + STRLENOF(": ") + 1 );
01935 
01936                             ptr = str;
01937                             ptr = lutil_strncopy( ptr, bv.bv_val, bv.bv_len );
01938                             ptr = lutil_strcopy( ptr, ": " );
01939                      }
01940               
01941                      for ( i = 0; vals[ i ].bv_val != NULL; i++ ) {
01942                             tool_write_ldif(
01943                                    ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
01944                                    ldif ? str : bv.bv_val, vals[ i ].bv_val, vals[ i ].bv_len );
01945                      }
01946 
01947                      ber_bvarray_free( vals );
01948                      if ( str ) free( str );
01949               }
01950        }
01951 
01952        if ( ber != NULL ) {
01953               ber_free( ber, 1 );
01954        }
01955 
01956        tool_write_ldif( LDIF_PUT_COMMENT, "<== ",
01957               what->bv_val, what->bv_len );
01958 
01959        return 0;
01960 }
01961 
01962 static int
01963 print_preread( LDAP *ld, LDAPControl *ctrl )
01964 {
01965        static struct berval what = BER_BVC( "preread" );
01966 
01967        return print_prepostread( ld, ctrl, &what );
01968 }
01969 
01970 static int
01971 print_postread( LDAP *ld, LDAPControl *ctrl )
01972 {
01973        static struct berval what = BER_BVC( "postread" );
01974 
01975        return print_prepostread( ld, ctrl, &what );
01976 }
01977 
01978 static int
01979 print_paged_results( LDAP *ld, LDAPControl *ctrl )
01980 {
01981        ber_int_t estimate;
01982 
01983        /* note: pr_cookie is being malloced; it's freed
01984         * the next time the control is sent, but the last
01985         * time it's not; we don't care too much, because
01986         * the last time an empty value is returned... */
01987        if ( ldap_parse_pageresponse_control( ld, ctrl, &estimate, &pr_cookie )
01988               != LDAP_SUCCESS )
01989        {
01990               /* error? */
01991               return 1;
01992 
01993        } else {
01994               /* FIXME: check buffer overflow */
01995               char   buf[ BUFSIZ ], *ptr = buf;
01996 
01997               if ( estimate > 0 ) {
01998                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
01999                             "estimate=%d", estimate );
02000               }
02001 
02002               if ( pr_cookie.bv_len > 0 ) {
02003                      struct berval bv;
02004 
02005                      bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
02006                             pr_cookie.bv_len ) + 1;
02007                      bv.bv_val = ber_memalloc( bv.bv_len + 1 );
02008 
02009                      bv.bv_len = lutil_b64_ntop(
02010                             (unsigned char *) pr_cookie.bv_val,
02011                             pr_cookie.bv_len,
02012                             bv.bv_val, bv.bv_len );
02013 
02014                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
02015                             "%scookie=%s", ptr == buf ? "" : " ",
02016                             bv.bv_val );
02017 
02018                      ber_memfree( bv.bv_val );
02019 
02020                      pr_morePagedResults = 1;
02021 
02022               } else {
02023                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
02024                             "%scookie=", ptr == buf ? "" : " " );
02025               }
02026 
02027               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
02028                      ldif ? "pagedresults: " : "pagedresults",
02029                      buf, ptr - buf );
02030        }
02031 
02032        return 0;
02033 }
02034 
02035 static int
02036 print_sss( LDAP *ld, LDAPControl *ctrl )
02037 {
02038        int rc;
02039        ber_int_t err;
02040        char *attr;
02041 
02042        rc = ldap_parse_sortresponse_control( ld, ctrl, &err, &attr );
02043        if ( rc == LDAP_SUCCESS ) {
02044               char buf[ BUFSIZ ];
02045               rc = snprintf( buf, sizeof(buf), "(%d) %s%s%s",
02046                      err, ldap_err2string(err), attr ? " " : "", attr ? attr : "" );
02047 
02048               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
02049                      ldif ? "sortResult: " : "sortResult", buf, rc );
02050        }
02051 
02052        return rc;
02053 }
02054 
02055 static int
02056 print_vlv( LDAP *ld, LDAPControl *ctrl )
02057 {
02058        int rc;
02059        ber_int_t err;
02060        struct berval bv;
02061 
02062        rc = ldap_parse_vlvresponse_control( ld, ctrl, &vlvPos, &vlvCount,
02063               &vlvContext, &err );
02064        if ( rc == LDAP_SUCCESS ) {
02065               char buf[ BUFSIZ ];
02066 
02067               if ( vlvContext && vlvContext->bv_len > 0 ) {
02068                      bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
02069                             vlvContext->bv_len ) + 1;
02070                      bv.bv_val = ber_memalloc( bv.bv_len + 1 );
02071 
02072                      bv.bv_len = lutil_b64_ntop(
02073                             (unsigned char *) vlvContext->bv_val,
02074                             vlvContext->bv_len,
02075                             bv.bv_val, bv.bv_len );
02076               } else {
02077                      bv.bv_val = "";
02078                      bv.bv_len = 0;
02079               }
02080 
02081               rc = snprintf( buf, sizeof(buf), "pos=%d count=%d context=%s (%d) %s",
02082                      vlvPos, vlvCount, bv.bv_val,
02083                      err, ldap_err2string(err));
02084 
02085               if ( bv.bv_len )
02086                      ber_memfree( bv.bv_val );
02087 
02088               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
02089                      ldif ? "vlvResult" : "vlvResult", buf, rc );
02090        }
02091 
02092        return rc;
02093 }
02094 
02095 #ifdef LDAP_CONTROL_X_DEREF
02096 static int
02097 print_deref( LDAP *ld, LDAPControl *ctrl )
02098 {
02099        LDAPDerefRes    *drhead = NULL, *dr;
02100        int           rc;
02101 
02102        rc = ldap_parse_derefresponse_control( ld, ctrl, &drhead );
02103        if ( rc != LDAP_SUCCESS ) {
02104               return rc;
02105        }
02106 
02107        for ( dr = drhead; dr != NULL; dr = dr->next ) {
02108               LDAPDerefVal  *dv;
02109               ber_len_t     len;
02110               char          *buf, *ptr;
02111 
02112               len = strlen( dr->derefAttr ) + STRLENOF(": ");
02113 
02114               for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
02115                      if ( dv->vals != NULL ) {
02116                             int j;
02117                             ber_len_t tlen = strlen(dv->type);
02118 
02119                             for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
02120                                    len += STRLENOF("<:=>;") + tlen + 4*((dv->vals[ j ].bv_len - 1)/3 + 1);
02121                             }
02122                      }
02123               }
02124               len += dr->derefVal.bv_len + STRLENOF("\n");
02125               buf = ldap_memalloc( len + 1 );
02126               if ( buf == NULL ) {
02127                      rc = LDAP_NO_MEMORY;
02128                      goto done;
02129               }
02130 
02131               ptr = buf;
02132               ptr = lutil_strcopy( ptr, dr->derefAttr );
02133               *ptr++ = ':';
02134               *ptr++ = ' ';
02135               for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
02136                      if ( dv->vals != NULL ) {
02137                             int j;
02138                             for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
02139                                    int k = ldif_is_not_printable( dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
02140 
02141                                    *ptr++ = '<';
02142                                    ptr = lutil_strcopy( ptr, dv->type );
02143                                    if ( k ) {
02144                                           *ptr++ = ':';
02145                                    }
02146                                    *ptr++ = '=';
02147                                    if ( k ) {
02148                                           k = lutil_b64_ntop(
02149                                                  (unsigned char *) dv->vals[ j ].bv_val,
02150                                                  dv->vals[ j ].bv_len,
02151                                                  ptr, buf + len - ptr );
02152                                           assert( k >= 0 );
02153                                           ptr += k;
02154                                           
02155                                    } else {
02156                                           ptr = lutil_memcopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
02157                                    }
02158                                    *ptr++ = '>';
02159                                    *ptr++ = ';';
02160                             }
02161                      }
02162               }
02163               ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len );
02164               *ptr++ = '\n';
02165               *ptr = '\0';
02166               assert( ptr <= buf + len );
02167 
02168               tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, ptr - buf);
02169 
02170               ldap_memfree( buf );
02171        }
02172 
02173        rc = LDAP_SUCCESS;
02174 
02175 done:;
02176        ldap_derefresponse_free( drhead );
02177 
02178        return rc;
02179 }
02180 #endif
02181 
02182 #ifdef LDAP_CONTROL_X_WHATFAILED
02183 static int
02184 print_whatfailed( LDAP *ld, LDAPControl *ctrl )
02185 {
02186        BerElement *ber;
02187        ber_tag_t tag;
02188        ber_len_t siz;
02189        BerVarray bva = NULL;
02190 
02191        /* Create a BerElement from the berval returned in the control. */
02192        ber = ber_init( &ctrl->ldctl_value );
02193 
02194        if ( ber == NULL ) {
02195               return LDAP_NO_MEMORY;
02196        }
02197 
02198        siz = sizeof(struct berval);
02199        tag = ber_scanf( ber, "[M]", &bva, &siz, 0 );
02200        if ( tag != LBER_ERROR ) {
02201               int i;
02202 
02203               tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 );
02204 
02205               for ( i = 0; bva[i].bv_val != NULL; i++ ) {
02206                      tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len );
02207               }
02208 
02209               ldap_memfree( bva );
02210        }
02211 
02212         ber_free( ber, 1 );
02213 
02214 
02215        return 0;
02216 }
02217 #endif
02218 
02219 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
02220 static int
02221 print_ppolicy( LDAP *ld, LDAPControl *ctrl )
02222 {
02223        int expire = 0, grace = 0, rc;
02224        LDAPPasswordPolicyError     pperr;
02225 
02226        rc = ldap_parse_passwordpolicy_control( ld, ctrl,
02227               &expire, &grace, &pperr );
02228        if ( rc == LDAP_SUCCESS ) {
02229               char   buf[ BUFSIZ ], *ptr = buf;
02230 
02231               if ( expire != -1 ) {
02232                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
02233                             "expire=%d", expire );
02234               }
02235 
02236               if ( grace != -1 ) {
02237                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
02238                             "%sgrace=%d", ptr == buf ? "" : " ", grace );
02239               }
02240 
02241               if ( pperr != PP_noError ) {
02242                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
02243                             "%serror=%d (%s)", ptr == buf ? "" : " ",
02244                             pperr,
02245                             ldap_passwordpolicy_err2txt( pperr ) );
02246               }
02247 
02248               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
02249                      ldif ? "ppolicy: " : "ppolicy", buf, ptr - buf );
02250        }
02251 
02252        return rc;
02253 }
02254 #endif
02255 
02256 void tool_print_ctrls(
02257        LDAP          *ld,
02258        LDAPControl   **ctrls )
02259 {
02260        int    i;
02261        char   *ptr;
02262 
02263        for ( i = 0; ctrls[i] != NULL; i++ ) {
02264               /* control: OID criticality base64value */
02265               struct berval b64 = BER_BVNULL;
02266               ber_len_t len;
02267               char *str;
02268               int j;
02269 
02270               /* FIXME: there might be cases where a control has NULL OID;
02271                * this makes little sense, especially when returned by the
02272                * server, but libldap happily allows it */
02273               if ( ctrls[i]->ldctl_oid == NULL ) {
02274                      continue;
02275               }
02276 
02277               len = ldif ? 2 : 0;
02278               len += strlen( ctrls[i]->ldctl_oid );
02279 
02280               /* add enough for space after OID and the critical value itself */
02281               len += ctrls[i]->ldctl_iscritical
02282                      ? sizeof("true") : sizeof("false");
02283 
02284               /* convert to base64 */
02285               if ( !BER_BVISNULL( &ctrls[i]->ldctl_value ) ) {
02286                      b64.bv_len = LUTIL_BASE64_ENCODE_LEN(
02287                             ctrls[i]->ldctl_value.bv_len ) + 1;
02288                      b64.bv_val = ber_memalloc( b64.bv_len + 1 );
02289 
02290                      b64.bv_len = lutil_b64_ntop(
02291                             (unsigned char *) ctrls[i]->ldctl_value.bv_val,
02292                             ctrls[i]->ldctl_value.bv_len,
02293                             b64.bv_val, b64.bv_len );
02294               }
02295 
02296               if ( b64.bv_len ) {
02297                      len += 1 + b64.bv_len;
02298               }
02299 
02300               ptr = str = malloc( len + 1 );
02301               if ( ldif ) {
02302                      ptr = lutil_strcopy( ptr, ": " );
02303               }
02304               ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_oid );
02305               ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_iscritical
02306                      ? " true" : " false" );
02307 
02308               if ( b64.bv_len ) {
02309                      ptr = lutil_strcopy( ptr, " " );
02310                      ptr = lutil_strcopy( ptr, b64.bv_val );
02311               }
02312 
02313               if ( ldif < 2 ) {
02314                      tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
02315                             "control", str, len );
02316               }
02317 
02318               free( str );
02319               if ( b64.bv_len ) {
02320                      ber_memfree( b64.bv_val );
02321               }
02322 
02323               /* known controls */
02324               for ( j = 0; tool_ctrl_response[j].oid != NULL; j++ ) {
02325                      if ( strcmp( tool_ctrl_response[j].oid, ctrls[i]->ldctl_oid ) == 0 ) {
02326                             if ( !tool_ctrl_response[j].mask & tool_type ) {
02327                                    /* this control should not appear
02328                                     * with this tool; warning? */
02329                             }
02330                             break;
02331                      }
02332               }
02333 
02334               if ( tool_ctrl_response[j].oid != NULL && tool_ctrl_response[j].func ) {
02335                      (void)tool_ctrl_response[j].func( ld, ctrls[i] );
02336               }
02337        }
02338 }
02339 
02340 int
02341 tool_write_ldif( int type, char *name, char *value, ber_len_t vallen )
02342 {
02343        char   *ldif;
02344 
02345        if (( ldif = ldif_put_wrap( type, name, value, vallen, ldif_wrap )) == NULL ) {
02346               return( -1 );
02347        }
02348 
02349        fputs( ldif, stdout );
02350        ber_memfree( ldif );
02351 
02352        return( 0 );
02353 }
02354 
02355 int
02356 tool_is_oid( const char *s )
02357 {
02358        int           first = 1;
02359 
02360        if ( !isdigit( (unsigned char) s[ 0 ] ) ) {
02361               return 0;
02362        }
02363 
02364        for ( ; s[ 0 ]; s++ ) {
02365               if ( s[ 0 ] == '.' ) {
02366                      if ( s[ 1 ] == '\0' ) {
02367                             return 0;
02368                      }
02369                      first = 1;
02370                      continue;
02371               }
02372 
02373               if ( !isdigit( (unsigned char) s[ 0 ] ) ) {
02374                      return 0;
02375               }
02376 
02377               if ( first == 1 && s[ 0 ] == '0' && s[ 1 ] != '.' ) {
02378                      return 0;
02379               }
02380               first = 0;
02381        }
02382 
02383        return 1;
02384 }