Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*
      7  * The contents of this file are subject to the Netscape Public
      8  * License Version 1.1 (the "License"); you may not use this file
      9  * except in compliance with the License. You may obtain a copy of
     10  * the License at http://www.mozilla.org/NPL/
     11  *
     12  * Software distributed under the License is distributed on an "AS
     13  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     14  * implied. See the License for the specific language governing
     15  * rights and limitations under the License.
     16  *
     17  * The Original Code is Mozilla Communicator client code, released
     18  * March 31, 1998.
     19  *
     20  * The Initial Developer of the Original Code is Netscape
     21  * Communications Corporation. Portions created by Netscape are
     22  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
     23  * Rights Reserved.
     24  *
     25  * Contributor(s):
     26  */
     27 
     28 /*
     29  * code that is shared by two or more of the LDAP command line tools
     30  */
     31 
     32 #include "ldaptool.h"
     33 #include "fileurl.h"
     34 #ifdef SOLARIS_LDAP_CMD
     35 #include "solaris-int.h"
     36 #include <ldap.h>
     37 #include <locale.h>
     38 #include <libgen.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #include <limits.h>
     42 #endif	/* SOLARIS_LDAP_CMD */
     43 
     44 #ifdef LDAP_TOOL_ARGPIN
     45 #include "argpin.h"
     46 #include "ntuserpin.h"
     47 #endif /* LDAP_TOOL_ARGPIN */
     48 
     49 #ifndef SOLARIS_LDAP_CMD
     50 #include <nspr.h> /* for PR_Cleanup() */
     51 #endif	/* SOLARIS_LDAP_CMD */
     52 #include <stdlib.h>
     53 #include <time.h>	/* for time() and ctime() */
     54 #ifdef HAVE_SASL_OPTIONS
     55 #ifdef SOLARIS_LDAP_CMD
     56 #include <sasl/sasl.h>
     57 #else
     58 #include <sasl.h>
     59 #endif	/* SOLARIS_LDAP_CMD */
     60 #include "ldaptool-sasl.h"
     61 #endif	/* HAVE_SASL_OPTIONS */
     62 
     63 #ifndef SOLARIS_LDAP_CMD
     64 #define gettext(s) s
     65 #endif
     66 
     67 #ifdef SOLARIS_LDAP_CMD
     68 #define	PATH_BUF_SIZE	(PATH_MAX + 1)
     69 #endif
     70 
     71 static LDAP_REBINDPROC_CALLBACK get_rebind_credentials;
     72 static void print_library_info( const LDAPAPIInfo *aip, FILE *fp );
     73 static int wait4result( LDAP *ld, int msgid, struct berval **servercredp,
     74 	char *msg );
     75 static int parse_result( LDAP *ld, LDAPMessage *res,
     76 	struct berval **servercredp, char *msg, int freeit );
     77 
     78 #ifdef LDAPTOOL_DEBUG_MEMORY
     79 static void *ldaptool_debug_malloc( size_t size );
     80 static void *ldaptool_debug_calloc( size_t nelem, size_t elsize );
     81 static void *ldaptool_debug_realloc( void *ptr, size_t size );
     82 static void ldaptool_debug_free( void *ptr );
     83 #endif /* LDAPTOOL_DEBUG_MEMORY */
     84 
     85 #if defined(NET_SSL)
     86 static char *certpath2keypath( char *certdbpath );
     87 static int ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns);
     88 static char * buildTokenCertName( const char *tokenName, const char *certName);
     89 #ifdef FORTEZZA
     90 static int ldaptool_fortezza_init( int exit_on_error );
     91 static int ldaptool_fortezza_alert( void *arg, PRBool onOpen,
     92 	char *string, int value1, void *value2 );
     93 static void * ldaptool_fortezza_getpin( char **passwordp );
     94 static char * ldaptool_fortezza_err2string( int err );
     95 #endif /* FORTEZZA */
     96 #endif
     97 #ifdef HAVE_SASL_OPTIONS
     98 static int saslSetParam(char *saslarg);
     99 #endif	/* HAVE_SASL_OPTIONS */
    100 
    101 /*
    102  * display usage for common options with one exception: -f is not included
    103  * since the description tends to be tool-specific.
    104  *
    105  * As of 1-Jul-1998, of the characters in the set [A-Za-z] the following are
    106  * not currently used by any of the tools: EJgjqr
    107  */
    108 void
    109 ldaptool_common_usage( int two_hosts )
    110 {
    111     fprintf( stderr, gettext("    -n\t\tshow what would be done but don't actually do it\n") );
    112     fprintf( stderr, gettext("    -v\t\trun in verbose mode (diagnostics to standard output)\n") );
    113     if ( two_hosts ) {
    114 	fprintf( stderr, gettext("    -h host\tLDAP server1 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
    115 	fprintf( stderr, gettext("    -p port\tLDAP server1 TCP port number (default: %d)\n"), LDAP_PORT );
    116 	fprintf( stderr, gettext("    -h host\tLDAP server2 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
    117 	fprintf( stderr, gettext("    -p port\tLDAP server2 TCP port number (default: %d)\n"), LDAP_PORT );
    118     } else {
    119 	fprintf( stderr, gettext("    -h host\tLDAP server name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
    120 	fprintf( stderr, gettext("    -p port\tLDAP server TCP port number (default: %d)\n"), LDAP_PORT );
    121     }
    122     fprintf( stderr,
    123 	    gettext("    -V n\tLDAP protocol version number (%d or %d; default: %d)\n"),
    124 	    LDAP_VERSION2, LDAP_VERSION3, LDAP_VERSION3 );
    125 #if defined(NET_SSL)
    126     fprintf( stderr, gettext("    -Z\t\tmake an SSL-encrypted connection\n") );
    127     fprintf( stderr, gettext("    -P pathname\tpath to SSL certificate database (default: current directory)\n") );
    128     fprintf( stderr, gettext("    -N\t\tname of certificate to use for SSL client authentication\n") );
    129 #ifndef SOLARIS_LDAP_CMD
    130     fprintf( stderr, gettext("    -K pathname\tpath to key database to use for SSL client authentication\n") );
    131     fprintf( stderr, gettext("    \t\t(default: path to certificate database provided with -P option)\n") );
    132 #endif	/* SOLARIS_LDAP_CMD */
    133 #ifdef LDAP_TOOL_PKCS11
    134     fprintf( stderr, gettext("    -m pathname\tpath to security module database\n"));
    135 #endif /* LDAP_TOOL_PKCS11 */
    136     fprintf( stderr, gettext("    -W\t\tSSL key password\n") );
    137 #ifndef SOLARIS_LDAP_CMD
    138     fprintf( stderr, gettext("    -3\t\tcheck hostnames in SSL certificates\n") );
    139 #endif	/* SOLARIS_LDAP_CMD */
    140 
    141 #ifdef LDAP_TOOL_PKCS11
    142     fprintf( stderr, gettext("    -Q [token][:certificate name]\tPKCS 11\n") );
    143     /*    fprintf( stderr, "    -X pathname\tFORTEZZA compromised key list (CKL)\n" ); */
    144     fprintf( stderr, gettext("    -I pin\tcard password file\n") );
    145 #endif /* LDAP_TOOL_PKCS11 */
    146 
    147 #endif /* NET_SSL */
    148     fprintf( stderr, gettext("    -D binddn\tbind dn\n") );
    149     fprintf( stderr, gettext("    -w passwd\tbind passwd (for simple authentication)\n") );
    150     fprintf( stderr, gettext("    -w - \tprompt for bind passwd (for simple authentication)\n") );
    151     fprintf( stderr, gettext("    -j file\tread bind passwd (for simple authentication)\n") );
    152     fprintf( stderr, gettext("      \t\tor SSL key password from 'file'\n") );
    153     fprintf( stderr, gettext("    -E\t\task server to expose (report) bind identity\n") );
    154 #ifdef LDAP_DEBUG
    155     fprintf( stderr, gettext("    -d level\tset LDAP debugging level to `level'\n") );
    156 #endif
    157     fprintf( stderr, gettext("    -R\t\tdo not automatically follow referrals\n") );
    158     fprintf( stderr, gettext("    -O limit\tmaximum number of referral hops to traverse (default: %d)\n"), LDAPTOOL_DEFREFHOPLIMIT );
    159     fprintf( stderr, gettext("    -M\t\tmanage references (treat them as regular entries)\n") );
    160 #ifndef SOLARIS_LDAP_CMD
    161     fprintf( stderr, gettext("    -0\t\tignore LDAP library version mismatches\n") );
    162 #endif	/* SOLARIS_LDAP_CMD */
    163 
    164 #ifndef NO_LIBLCACHE
    165     fprintf( stderr, gettext("    -C cfgfile\tuse local database described by cfgfile\n") );
    166 #endif
    167     fprintf( stderr, gettext("    -i charset\tcharacter set for command line input (default taken from locale)\n") );
    168     fprintf( stderr, gettext("    -k dir\tconversion routine directory (default: current directory)\n") );
    169 #if 0
    170 /*
    171  * Suppress usage for -y (old proxied authorization control) even though
    172  * we still support it.  We want to encourage people to use -Y instead (the
    173  * new proxied authorization control).
    174  */
    175     fprintf( stderr, gettext("    -y proxydn\tDN used for proxy authorization\n") );
    176 #endif
    177     fprintf( stderr, gettext("    -Y proxyid\tproxied authorization id,\n") );
    178     fprintf( stderr, gettext("              \te.g, dn:uid=bjensen,dc=example,dc=com\n") );
    179     fprintf( stderr, gettext("    -H\t\tdisplay usage information\n") );
    180 #ifdef SOLARIS_LDAP_CMD
    181     fprintf( stderr, gettext("    -?\t\tdisplay usage information\n") );
    182 #endif	/* SOLARIS_LDAP_CMD */
    183     fprintf( stderr, gettext("    -J controloid[:criticality[:value|::b64value|:<fileurl]]\n") );
    184     fprintf( stderr, gettext("\t\tcriticality is a boolean value (default is false)\n") );
    185 #ifdef HAVE_SASL_OPTIONS
    186     fprintf( stderr, gettext("    -o attrName=attrVal\tSASL options which are described in the man page\n"));
    187 #endif	/* HAVE_SASL_OPTIONS */
    188 }
    189 
    190 /* globals */
    191 char			*ldaptool_charset = "";
    192 char			*ldaptool_host = LDAPTOOL_DEFHOST;
    193 char			*ldaptool_host2 = LDAPTOOL_DEFHOST;
    194 int			ldaptool_port = LDAP_PORT;
    195 int			ldaptool_port2 = LDAP_PORT;
    196 int			ldaptool_verbose = 0;
    197 int			ldaptool_not = 0;
    198 #ifdef SOLARIS_LDAP_CMD
    199 int			ldaptool_require_binddn = 1;
    200 #endif	/* SOLARIS_LDAP_CMD */
    201 FILE			*ldaptool_fp = NULL;
    202 FILE			*password_fp = NULL;
    203 char			*ldaptool_progname = "";
    204 char			*ldaptool_nls_lang = NULL;
    205 char                    *proxyauth_id = NULL;
    206 int			proxyauth_version = 2;	/* use newer proxy control */
    207 LDAPControl		*ldaptool_request_ctrls[CONTROL_REQUESTS] = {0};
    208 #ifdef LDAP_DEBUG
    209 int			ldaptool_dbg_lvl = 0;
    210 #endif /* LDAP_DEBUG */
    211 
    212 /* statics */
    213 static char		*binddn = NULL;
    214 static char		*passwd = NULL;
    215 static int		send_auth_response_ctrl = 0;
    216 static int		user_specified_port = 0;
    217 static int		user_specified_port2 = 0;
    218 static int		chase_referrals = 1;
    219 static int		lib_version_mismatch_is_fatal = 1;
    220 static int		ldversion = -1;	/* use default */
    221 static int		refhoplim = LDAPTOOL_DEFREFHOPLIMIT;
    222 static int		send_manage_dsait_ctrl = 0;
    223 static int		prompt_password = 0;
    224 #ifdef HAVE_SASL_OPTIONS
    225 static unsigned		sasl_flags = LDAP_SASL_INTERACTIVE;
    226 static char		*sasl_mech = NULL;
    227 static char		*sasl_authid = NULL;
    228 static char		*sasl_mode = NULL;
    229 static char		*sasl_realm = NULL;
    230 static char		*sasl_username = NULL;
    231 static char		*sasl_secprops = NULL;
    232 static int		ldapauth = -1;
    233 #endif	/* HAVE_SASL_OPTIONS */
    234 
    235 #ifndef NO_LIBLCACHE
    236 static char		*cache_config_file = NULL;
    237 #endif /* !NO_LIBLCACHE */
    238 #if defined(NET_SSL)
    239 static int		secure = 0;
    240 static int		isZ = 0;
    241 static int		isN = 0;
    242 static int		isW = 0;
    243 static int		isw = 0;
    244 static int		isD = 0;
    245 static int		isj = 0;
    246 static int		ssl_strength = LDAPTOOL_DEFSSLSTRENGTH;
    247 #ifdef SOLARIS_LDAP_CMD
    248 static char		pathname[PATH_BUF_SIZE];
    249 #endif
    250 static char		*ssl_certdbpath = NULL;
    251 static char		*ssl_keydbpath = NULL;
    252 static char		*ssl_keyname = NULL;
    253 static char		*ssl_certname = NULL;
    254 static char		*ssl_passwd = NULL;
    255 
    256 #ifdef LDAP_TOOL_PKCS11
    257 static char     	*ssl_secmodpath = NULL;
    258 
    259 static char             *pkcs_token = NULL;
    260 
    261 static char             *ssl_donglefile = NULL;
    262 
    263 #if 0
    264 static char             *pkcs_pin = NULL;
    265 #endif
    266 static struct ldapssl_pkcs_fns local_pkcs_fns =
    267     {0,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL };
    268 
    269 #ifdef FORTEZZA
    270 static uint32		fortezza_cardmask = 0;
    271 static char		*fortezza_personality = NULL;
    272 static char		*fortezza_krlfile = NULL;
    273 static char		*fortezza_pin = NULL;
    274 #endif /* FORTEZZA */
    275 #endif /* LDAP_TOOL_PKCS11 */
    276 #endif /* NET_SSL */
    277 
    278 /*
    279  * Handle general initialization and options that are common to all of
    280  * the LDAP tools.
    281  * Handle options that are common to all of the LDAP tools.
    282  * Note the the H option is included here but handled via the
    283  * extra_opt_callback function (along with any "extra_opts" ).
    284  *
    285  * Return: final value for optind or -1 if usage should be displayed (for
    286  * some fatal errors, we call exit here).
    287  */
    288 int
    289 ldaptool_process_args( int argc, char **argv, char *extra_opts,
    290 	int two_hosts, void (*extra_opt_callback)( int option, char *optarg ))
    291 {
    292     int		rc, i, hostnum;
    293     char	*optstring, *common_opts;
    294     extern char	*optarg;
    295     extern int	optind;
    296     LDAPAPIInfo	ldai;
    297     char *ctrl_arg, *ctrl_oid=NULL, *ctrl_value=NULL;
    298     int ctrl_criticality=0, vlen;
    299     LDAPControl *ldctrl;
    300 #ifdef SOLARIS_LDAP_CMD
    301 	struct stat st;
    302 #endif
    303 
    304 
    305     /*
    306      * Set program name global based on argv[0].
    307      */
    308     if (( ldaptool_progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
    309         ldaptool_progname = argv[ 0 ];
    310     } else {
    311         ++ldaptool_progname;
    312     }
    313 
    314 #ifdef LDAPTOOL_DEBUG_MEMORY
    315     {
    316 	struct ldap_memalloc_fns mafns = {
    317 		ldaptool_debug_malloc,
    318 		ldaptool_debug_calloc,
    319 		ldaptool_debug_realloc,
    320 		ldaptool_debug_free
    321 	};
    322 
    323 	ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &mafns );
    324     }
    325 #endif	/* LDAPTOOL_DEBUG_MEMORY */
    326 
    327 #ifdef LDAP_DEBUG
    328     i = LDAP_DEBUG_ANY;
    329     ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, (void *) &i);
    330 #endif
    331 
    332     /*
    333      * Perform a sanity check on the revision of the LDAP API library to
    334      * make sure it is at least as new as the one we were compiled against.
    335      * If the API implementation is from the same vendor as we were compiled
    336      * against, we also check to make sure the vendor version is at least
    337      * as new as the library we were compiled against.
    338      *
    339      * Version differences are fatal unless the -0 option is passed on the
    340      * tool command line (that's a zero, not an oh).  We check for the
    341      * presence of -0 in a crude way to it must appear by itself in argv.
    342      */
    343     for ( i = 1; i < argc; ++i ) {
    344 	if ( strcmp( argv[i], "-0" ) == 0 ) {
    345 	    lib_version_mismatch_is_fatal = 0;
    346 	    break;
    347 	}
    348     }
    349 
    350     memset( &ldai, 0, sizeof(ldai));
    351     ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
    352     if (( rc = ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldai )) != 0 ) {
    353 	fprintf( stderr, gettext("%s: unable to retrieve LDAP library version"
    354 		" information;\n\tthis program requires an LDAP library that"
    355 		" implements revision\n\t%d or greater of the LDAP API.\n"),
    356 		ldaptool_progname, LDAP_API_VERSION );
    357 	if ( lib_version_mismatch_is_fatal ) {
    358 	    exit( LDAP_LOCAL_ERROR );
    359 	}
    360     } else if ( ldai.ldapai_api_version < LDAP_API_VERSION ) {
    361 	fprintf( stderr, gettext("%s: this program requires an LDAP library that"
    362 		" implements revision\n\t%d or greater of the LDAP API;"
    363 		" running with revision %d.\n"),
    364 		ldaptool_progname, LDAP_API_VERSION, ldai.ldapai_api_version );
    365 	if ( lib_version_mismatch_is_fatal ) {
    366 	    exit( LDAP_LOCAL_ERROR );
    367 	}
    368     } else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0) {
    369 	fprintf( stderr, gettext("%s: this program requires %s's LDAP\n"
    370 		"\tlibrary version %2.2f or greater; running with\n"
    371 		"\t%s's version %2.2f.\n"),
    372 		ldaptool_progname, LDAP_VENDOR_NAME,
    373 		(float)LDAP_VENDOR_VERSION / 100,
    374 		ldai.ldapai_vendor_name,
    375 		(float)ldai.ldapai_vendor_version / 100 );
    376 	if ( lib_version_mismatch_is_fatal ) {
    377 	    exit( LDAP_LOCAL_ERROR );
    378 	}
    379     } else if (ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
    380 	fprintf( stderr, gettext("%s: this program requires %s's LDAP\n"
    381 		"\tlibrary version %2.2f or greater; running with"
    382 		" version %2.2f.\n"),
    383 		ldaptool_progname, LDAP_VENDOR_NAME,
    384 		(float)LDAP_VENDOR_VERSION / 100,
    385 		(float)ldai.ldapai_vendor_version / 100 );
    386 	if ( lib_version_mismatch_is_fatal ) {
    387 	    exit( LDAP_LOCAL_ERROR );
    388 	}
    389     }
    390 
    391     /*
    392      * Process command line options.
    393      */
    394     if ( extra_opts == NULL ) {
    395 	extra_opts = "";
    396     }
    397 
    398 #ifdef HAVE_SASL_OPTIONS
    399 #ifdef SOLARIS_LDAP_CMD
    400     common_opts = "nvEMRH?Zd:D:f:h:j:N:O:o:P:p:W:w:V:i:k:y:Y:J:";
    401 #else
    402     common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:o:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
    403 #endif	/* SOLARIS_LDAP_CMD */
    404 #else
    405     common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
    406 #endif	/* HAVE_SASL_OPTIONS */
    407 
    408     /* note: optstring must include room for liblcache "C:" option */
    409     if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts )
    410 	    + 3 )) == NULL ) {
    411 	perror( "malloc" );
    412 	exit( LDAP_NO_MEMORY );
    413     }
    414 
    415 #ifdef NO_LIBLCACHE
    416     sprintf( optstring, "%s%s", common_opts, extra_opts );
    417 #else
    418     sprintf( optstring, "%s%sC:", common_opts, extra_opts );
    419 #endif
    420 
    421     hostnum = 0;
    422     while ( (i = getopt( argc, argv, optstring )) != EOF ) {
    423 	switch( i ) {
    424 	case 'n':	/* do Not do any LDAP operations */
    425 	    ++ldaptool_not;
    426 	    break;
    427 	case 'v':	/* verbose mode */
    428 	    ++ldaptool_verbose;
    429 	    break;
    430 	case 'd':
    431 #ifdef LDAP_DEBUG
    432 	    ldaptool_dbg_lvl = atoi( optarg );	/* */
    433 #ifdef SOLARIS_LDAP_CMD
    434 	    ldap_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
    435 		    (void *)&ldaptool_dbg_lvl);
    436 #else
    437 	    ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
    438 		    (void *)&ldaptool_dbg_lvl);
    439 #endif	/* SOLARIS_LDAP_CMD */
    440 	    ldaptool_dbg_lvl |= LDAP_DEBUG_ANY;
    441 	    ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL,
    442 		    (void *)&ldaptool_dbg_lvl);
    443 #else /* LDAP_DEBUG */
    444 	    fprintf( stderr, gettext("compile with -DLDAP_DEBUG for debugging\n") );
    445 #endif /* LDAP_DEBUG */
    446 	    break;
    447 	case 'R':	/* don't automatically chase referrals */
    448 	    chase_referrals = 0;
    449 	    break;
    450 #ifndef NO_LIBLCACHE
    451 	case 'C':	/* search local database */
    452 	    cache_config_file = strdup( optarg );
    453 	    break;
    454 #endif
    455 	case 'f':	/* input file */
    456 	    if ( optarg[0] == '-' && optarg[1] == '\0' ) {
    457 		ldaptool_fp = stdin;
    458 	    } else if (( ldaptool_fp = ldaptool_open_file( optarg, "r" )) == NULL ) {
    459 		perror( optarg );
    460 		exit( LDAP_PARAM_ERROR );
    461 	    }
    462 	    break;
    463 	case 'h':	/* ldap host */
    464 	    if ( hostnum == 0 ) {
    465 		ldaptool_host = strdup( optarg );
    466 	    } else {
    467 		ldaptool_host2 = strdup( optarg );
    468 	    }
    469 	    ++hostnum;
    470 	    break;
    471 	case 'D':	/* bind DN */
    472 	    isD = 1;
    473 	    binddn = strdup( optarg );
    474 	    break;
    475 	case 'E':	/* expose bind identity via auth. response control */
    476 	    ++send_auth_response_ctrl;
    477 	    break;
    478 
    479 	case 'p':	/* ldap port */
    480 	    if ( !user_specified_port ) {
    481 		++user_specified_port;
    482 		ldaptool_port = atoi( optarg );
    483 	    } else {
    484 		++user_specified_port2;
    485 		ldaptool_port2 = atoi( optarg );
    486 	    }
    487 	    break;
    488 #if defined(NET_SSL)
    489 	case 'P':	/* path to security database */
    490 	    secure = 1; /* do SSL encryption */
    491 #ifndef SOLARIS_LDAP_CMD
    492 	    ssl_certdbpath = strdup(optarg);
    493 	    if (NULL == ssl_certdbpath) {
    494 		perror("malloc");
    495 		exit( LDAP_NO_MEMORY );
    496 	    }
    497 #else
    498 		/*
    499 		 * Verify whether it's a base directory or a cert db file.
    500 		 * If it is not a directory, truncate the file name as
    501 		 * the revised NSS_Init() doesn't take file name any longer.
    502 		 */
    503 		if (strlcpy(pathname, optarg, PATH_BUF_SIZE) >= PATH_BUF_SIZE) {
    504 			fprintf(stderr, gettext("\"-P\": Path name is too "
    505 				"long\n"));
    506 			exit(LDAP_PARAM_ERROR);
    507 		}
    508 
    509 		if (stat(pathname, &st) != 0) {
    510 			perror("stat");
    511 			fprintf(stderr, gettext("\"-P\": Path name is "
    512 				"invalid\n"));
    513 			exit(LDAP_PARAM_ERROR);
    514 		} else {
    515 			if (S_ISREG(st.st_mode)) {
    516 				/* redir to a regular file's dir name */
    517 				ssl_certdbpath = dirname(pathname);
    518 			} else
    519 				ssl_certdbpath = pathname;
    520 		}
    521 #endif /* SOLARIS_LDAP_CMD */
    522 	    break;
    523 	case 'Z':	/* do SSL encryption */
    524 	    secure = 1;
    525 	    isZ = 1;
    526 	    break;
    527 	case 'N':	/* nickname of cert. to use for client auth. */
    528 	    ssl_certname = strdup( optarg );
    529 	    if (NULL == ssl_certname)
    530 	    {
    531 		perror("malloc");
    532 		exit( LDAP_NO_MEMORY );
    533 	    }
    534 	    isN = 1;
    535 	    break;
    536 #ifndef SOLARIS_LDAP_CMD
    537 	case 'K':	/* location of key database */
    538 	    ssl_keydbpath = strdup( optarg );
    539 	    if (NULL == ssl_keydbpath)
    540 	    {
    541 		perror("malloc");
    542 		exit( LDAP_NO_MEMORY );
    543 	    }
    544 	    break;
    545 #endif	/* SOLARIS_LDAP_CMD */
    546 
    547 	case 'W':	/* SSL key password */
    548 	    ssl_passwd = strdup( optarg );
    549 	    if (NULL == ssl_passwd)
    550 	    {
    551 		perror("malloc");
    552 		exit( LDAP_NO_MEMORY );
    553 	    }
    554 	    isW = 1;
    555 	    break;
    556 
    557 #ifndef SOLARIS_LDAP_CMD
    558 	case '3': /* check hostnames in SSL certificates ("no third") */
    559 	    ssl_strength = LDAPSSL_AUTH_CNCHECK;
    560 	    break;
    561 #endif	/* SOLARIS_LDAP_CMD */
    562 
    563 #ifdef LDAP_TOOL_PKCS11
    564 	case 'm':	/* SSL secmod path */
    565 	    ssl_secmodpath = strdup( optarg);
    566 	    if (NULL == ssl_secmodpath)
    567 	    {
    568 		perror("malloc");
    569 		exit( LDAP_NO_MEMORY );
    570 	    }
    571 	    break;
    572 
    573 	case 'Q': 	/* FORTEZZA [card][:personality] */
    574 	    pkcs_token = strdup(optarg);
    575 	    if (NULL == pkcs_token)
    576 	    {
    577 		perror("malloc");
    578 		exit( LDAP_NO_MEMORY );
    579 	    }
    580 
    581 	    break;
    582 	    /* This option removed to prevent interference
    583 	       with the getEffectiveRights option, also -X
    584 	       case 'X':	* path to FORTEZZA CKL file *
    585 
    586 	       fortezza_krlfile = strdup( optarg );
    587 
    588 
    589 	       break;
    590 	    */
    591 	case 'I':	/* FORTEZZA PIN (password file) */
    592 	    ssl_donglefile = strdup( optarg );
    593 
    594 	    break;
    595 #endif /* LDAP_TOOL_PKCS11 */
    596 
    597 #endif /* NET_SSL */
    598 	case 'w':	/* bind password */
    599 	    isw = 1;
    600 	    if ( optarg[0] == '-' && optarg[1] == '\0' )
    601 		prompt_password = 1;
    602 	    else
    603 		passwd = strdup( optarg );
    604 	    break;
    605 	    case 'j':       /* bind password or SSL key password from file */
    606 	    isj = 1;
    607 	    if ((password_fp = fopen( optarg, "r" )) == NULL ) {
    608 		fprintf(stderr, gettext("%s: Unable to open '%s' file\n"),
    609 			ldaptool_progname, optarg);
    610 		exit( LDAP_PARAM_ERROR );
    611 	    }
    612             break;
    613 	case 'O':	/* referral hop limit */
    614 	    refhoplim = atoi( optarg );
    615 	    break;
    616 	case 'V':	/* protocol version */
    617 	    ldversion = atoi (optarg);
    618 	    if ( ldversion != LDAP_VERSION2 && ldversion != LDAP_VERSION3 ) {
    619 		fprintf( stderr, gettext("%s: LDAP protocol version %d is not "
    620 			"supported (use -V%d or -V%d)\n"),
    621 			ldaptool_progname, ldversion, LDAP_VERSION2,
    622 			LDAP_VERSION3 );
    623 		exit( LDAP_PARAM_ERROR );
    624 	    }
    625 	    break;
    626 	case 'M':	/* send a manageDsaIT control */
    627 	    send_manage_dsait_ctrl = 1;
    628 	    break;
    629 
    630 	case 'i':   /* character set specified */
    631 	    ldaptool_charset = strdup( optarg );
    632 	    if (NULL == ldaptool_charset)
    633 	    {
    634 		perror( "malloc" );
    635 		exit( LDAP_NO_MEMORY );
    636 	    }
    637 
    638 	    break;
    639 	case 'k':   /* conversion directory */
    640 	    ldaptool_convdir = strdup( optarg );
    641 	    if (NULL == ldaptool_convdir)
    642 	    {
    643 		perror( "malloc" );
    644 		exit( LDAP_NO_MEMORY );
    645 	    }
    646 	    break;
    647 	case 'y':   /* old (version 1) proxied authorization control */
    648 		proxyauth_version = 1;
    649 	case 'Y':   /* new (version 2 ) proxied authorization control */
    650 		/*FALLTHRU*/
    651 	    proxyauth_id = strdup(optarg);
    652 	    if (NULL == proxyauth_id)
    653 	    {
    654 		perror( "malloc" );
    655 		exit( LDAP_NO_MEMORY );
    656 	    }
    657 
    658 	    break;
    659 
    660 #ifndef SOLARIS_LDAP_CMD
    661  	case '0':	/* zero -- override LDAP library version check */
    662 	    break;	/* already handled above */
    663 #endif	/* SOLARIS_LDAP_CMD */
    664 	case 'J':	 /* send an arbitrary control */
    665 	    if ( (ctrl_arg = strdup( optarg)) == NULL ) {
    666 		perror ("strdup");
    667 		exit (LDAP_NO_MEMORY);
    668 	    }
    669 	    if (ldaptool_parse_ctrl_arg(ctrl_arg, ':', &ctrl_oid,
    670 		    &ctrl_criticality, &ctrl_value, &vlen)) {
    671 		return (-1);
    672 	    }
    673 	    ldctrl = calloc(1,sizeof(LDAPControl));
    674 	    if (ctrl_value) {
    675 		rc = ldaptool_berval_from_ldif_value( ctrl_value,
    676 			vlen, &(ldctrl->ldctl_value),
    677 			1 /* recognize file URLs */,
    678 			0 /* always try file */,
    679 			1 /* report errors */ );
    680 		if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
    681 		    fprintf( stderr, gettext("Unable to parse %s\n"), ctrl_value);
    682 		    return (-1);
    683 		}
    684 	    }
    685 	    ldctrl->ldctl_oid = ctrl_oid;
    686 	    ldctrl->ldctl_iscritical = ctrl_criticality;
    687 	    ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
    688 	    break;
    689 #ifdef HAVE_SASL_OPTIONS
    690 	case 'o':	/* attribute assignment */
    691 	      if ((rc = saslSetParam(optarg)) == -1) {
    692 	      	  return (-1);
    693 	      }
    694 	      ldapauth = LDAP_AUTH_SASL;
    695 	      ldversion = LDAP_VERSION3;
    696 	      break;
    697 #endif	/* HAVE_SASL_OPTIONS */
    698 	default:
    699 	    (*extra_opt_callback)( i, optarg );
    700 	}
    701     }
    702 
    703 
    704     /* If '-Z' is specified, check if '-P' is specified too. */
    705     if ( isN || isW ) {
    706 	if ( !isZ ) {
    707 		fprintf( stderr, gettext("%s: with -N, -W options, please specify -Z\n\n"), ldaptool_progname );
    708 		return (-1);
    709 	}
    710     }
    711 
    712     /* if '-N' is specified, -W is needed too */
    713     if ( isN && NULL == ssl_passwd ) {
    714         fprintf( stderr, gettext("%s: with the -N option, please specify -W also\n\n"),
    715 		ldaptool_progname );
    716         return (-1);
    717     }
    718 
    719 #ifdef SOLARIS_LDAP_CMD
    720     if ( isj && ( isw || isW )) {
    721 	fprintf(stderr, gettext("%s: -j and -w or -W options cannot be specified simultaneously\n\n"), ldaptool_progname );
    722 #else
    723     if ( isj && isw ) {
    724 	fprintf(stderr, gettext("%s: -j and -w options cannot be specified simultaneously\n\n"), ldaptool_progname );
    725 #endif	/* SOLARIS_LDAP_CMD */
    726 	return (-1);
    727     }
    728 
    729     /* complain if -j or -w does not also have -D, unless using SASL */
    730 #ifdef HAVE_SASL_OPTIONS
    731     if ( (isj || isw) && !isD && (  ldapauth != LDAP_AUTH_SASL ) ) {
    732 #else
    733     if ( (isj || isw) && !isD ) {
    734 #endif
    735 	fprintf(stderr, gettext("%s: with -j, -w options, please specify -D\n\n"), ldaptool_progname );
    736 	return (-1);
    737     }
    738 
    739     /* use default key and cert DB paths if not set on the command line */
    740     if ( NULL == ssl_keydbpath ) {
    741         if ( NULL == ssl_certdbpath ) {
    742             ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH;
    743         } else {
    744             ssl_keydbpath = certpath2keypath( ssl_certdbpath );
    745         }
    746     }
    747     if ( NULL == ssl_certdbpath ) {
    748         ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH;
    749     }
    750 
    751     if (prompt_password != 0) {
    752 	char *password_string = "Enter bind password: ";
    753 
    754 #if defined(_WIN32)
    755 	char pbuf[257];
    756 	fputs(password_string,stdout);
    757 	fflush(stdout);
    758 	if (fgets(pbuf,256,stdin) == NULL) {
    759 	    passwd = NULL;
    760 	} else {
    761 	    char *tmp;
    762 
    763 	    tmp = strchr(pbuf,'\n');
    764 	    if (tmp) *tmp = '\0';
    765 	    tmp = strchr(pbuf,'\r');
    766 	    if (tmp) *tmp = '\0';
    767 	    passwd = strdup(pbuf);
    768 	}
    769 #else
    770 #if defined(SOLARIS)
    771 	/* 256 characters on Solaris */
    772 	passwd = getpassphrase(password_string);
    773 #else
    774 	/* limited to 16 chars on Tru64, 32 on AIX */
    775 	passwd = getpass(password_string);
    776 #endif
    777 #endif
    778 
    779     } else if (password_fp != NULL) {
    780 	char *linep = NULL;
    781 	int   increment = 0;
    782 	int   c, index;
    783 
    784 	/* allocate initial block of memory */
    785 	if ((linep = (char *)malloc(BUFSIZ)) == NULL) {
    786 	    fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname );
    787 	    exit( LDAP_NO_MEMORY );
    788 	}
    789 	increment++;
    790 	index = 0;
    791 	while ((c = fgetc( password_fp )) != '\n' && c != EOF) {
    792 
    793 	    /* check if we will overflow the buffer */
    794 	    if ((c != EOF) && (index == ((increment * BUFSIZ) -1))) {
    795 
    796 		/* if we did, add another BUFSIZ worth of bytes */
    797 		if ((linep = (char *)
    798 		    realloc(linep, (increment + 1) * BUFSIZ)) == NULL) {
    799 			fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname );
    800 			exit( LDAP_NO_MEMORY );
    801 		}
    802 	 	increment++;
    803 	    }
    804 	    linep[index++] = c;
    805 	}
    806 	linep[index] = '\0';
    807 	passwd = linep;
    808     }
    809 
    810 #ifdef SOLARIS_LDAP_CMD
    811     if (binddn != NULL && passwd == NULL) {
    812 	char *password_string = gettext("Enter bind password: ");
    813 	passwd = getpassphrase(password_string);
    814     }
    815 
    816 #ifdef HAVE_SASL_OPTIONS
    817     if (ldapauth == LDAP_AUTH_SASL) {
    818 	/* BindDN not required for SASL */
    819 	ldaptool_require_binddn = 0;
    820     }
    821 #endif	/* HAVE_SASL_OPTIONS */
    822 
    823 #ifdef NET_SSL
    824     if (secure == 1) {
    825 	/* BindDN not required for SSL */
    826 	ldaptool_require_binddn = 0;
    827     }
    828 #endif	/* NET_SSL */
    829 
    830     if (ldaptool_require_binddn && binddn == NULL && passwd == NULL) {
    831 		fprintf(stderr,
    832 			gettext("%s: DN and Bind Password are required.\n"),
    833 			ldaptool_progname );
    834 		exit(1);
    835     }
    836 #endif	/* SOLARIS_LDAP_CMD */
    837 
    838     /*
    839      * If verbose (-v) flag was passed in, display program name and start time.
    840      * If the verbose flag was passed at least twice (-vv), also display
    841      * information about the API library we are running with.
    842      */
    843     if ( ldaptool_verbose ) {
    844 	time_t	curtime;
    845 
    846 	curtime = time( NULL );
    847 	printf( gettext("%s: started %s\n"), ldaptool_progname, ctime( &curtime ));
    848 	if ( ldaptool_verbose > 1 ) {
    849 	    print_library_info( &ldai, stdout );
    850 	}
    851     }
    852 
    853 #ifdef LDAP_TOOL_PKCS11
    854     if ((NULL != pkcs_token) && (NULL != ssl_certname)) {
    855 	char *result;
    856 
    857 	if ( (result = buildTokenCertName( pkcs_token, ssl_certname)) != NULL){
    858 	    free( ssl_certname );
    859 	    ssl_certname = result;
    860 	}
    861     }
    862 #endif /* LDAP_TOOL_PKCS11 */
    863 
    864     free( optstring );
    865 
    866     /*
    867      * Clean up and return index of first non-option argument.
    868      */
    869     if ( ldai.ldapai_extensions != NULL ) {
    870 	ldap_value_free( ldai.ldapai_extensions );
    871     }
    872     if ( ldai.ldapai_vendor_name != NULL ) {
    873 	ldap_memfree( ldai.ldapai_vendor_name );
    874     }
    875 
    876 #ifdef HAVE_SASL_OPTIONS
    877     if (ldversion == LDAP_VERSION2 && ldapauth == LDAP_AUTH_SASL) {
    878        fprintf( stderr, gettext("Incompatible with version %d\n"), ldversion);
    879        return (-1);
    880     }
    881 #endif	/* HAVE_SASL_OPTIONS */
    882     return( optind );
    883 }
    884 
    885 
    886 /*
    887  * Write detailed information about the API library we are running with to fp.
    888  */
    889 static void
    890 print_library_info( const LDAPAPIInfo *aip, FILE *fp )
    891 {
    892     int                 i;
    893     LDAPAPIFeatureInfo  fi;
    894 
    895     fprintf( fp, gettext("LDAP Library Information -\n"
    896 	    "    Highest supported protocol version: %d\n"
    897 	    "    LDAP API revision:                  %d\n"
    898 	    "    API vendor name:                    %s\n"
    899 	    "    Vendor-specific version:            %.2f\n"),
    900 	    aip->ldapai_protocol_version, aip->ldapai_api_version,
    901 	    aip->ldapai_vendor_name,
    902 	    (float)aip->ldapai_vendor_version / 100.0 );
    903 
    904     if ( aip->ldapai_extensions != NULL ) {
    905 	fputs( gettext("    LDAP API Extensions:\n"), fp );
    906 
    907 	for ( i = 0; aip->ldapai_extensions[i] != NULL; i++ )  {
    908 	    fprintf( fp, gettext("        %s"), aip->ldapai_extensions[i] );
    909 	    fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
    910 	    fi.ldapaif_name = aip->ldapai_extensions[i];
    911 	    fi.ldapaif_version = 0;
    912 
    913 	    if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi )
    914 		    != 0 ) {
    915 		fprintf( fp, gettext(" %s: ldap_get_option( NULL,"
    916 			" LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed"
    917 			" (Feature Info version: %d)\n"), ldaptool_progname,
    918 			fi.ldapaif_name, fi.ldapaif_info_version );
    919 	    } else {
    920 		fprintf( fp, gettext(" (revision %d)\n"), fi.ldapaif_version);
    921 	    }
    922 	}
    923     }
    924    fputc( '\n', fp );
    925 }
    926 
    927 
    928 
    929 #ifdef LDAP_TOOL_ARGPIN
    930 static int PinArgRegistration( void )
    931 {
    932 
    933     /* pkcs_init was successful  register the pin args */
    934 
    935     SVRCOREArgPinObj *ArgPinObj;
    936     char *tokenName;
    937 #ifndef _WIN32
    938     SVRCOREStdPinObj *StdPinObj;
    939 #else
    940     SVRCOREFilePinObj *FilePinObj;
    941     SVRCOREAltPinObj *AltPinObj;
    942     SVRCORENTUserPinObj *NTUserPinObj;
    943     int err;
    944 #endif
    945     char *pin;
    946     char *filename;
    947     /* Create and register the pin object for PKCS 11 */
    948     local_pkcs_fns.pkcs_getdonglefilename(NULL, &filename);
    949     local_pkcs_fns.pkcs_getpin(NULL, "", &pin);
    950 #ifndef _WIN32
    951     if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) !=
    952 	 SVRCORE_Success) {
    953 	fprintf(stderr, gettext("Security Initialization: Unable to create PinObj "
    954 	       "(%d)"), PR_GetError());
    955 	return -1;
    956     }
    957     if (pin != NULL)
    958     {
    959 	local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
    960 	SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, (SVRCOREPinObj *)StdPinObj);
    961 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
    962     }
    963     else
    964     {
    965 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj);
    966     }
    967 #else
    968     if (NULL != pin)
    969     {
    970 	local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
    971 	if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
    972 	    fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj "
    973 		   "(%d)"), PR_GetError());
    974 	    exit( LDAP_LOCAL_ERROR );
    975 	}
    976 	if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin,
    977 					   (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success)
    978 	{
    979 	    fprintf(stderr, gettext("Security Initialization: Unable to create ArgPinObj "
    980 		   "(%d)"), PR_GetError());
    981 	    return -1;
    982 
    983 	}
    984 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
    985 
    986     }
    987     else
    988     {
    989 	if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
    990 	    fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj "
    991 		   "(%d)"), PR_GetError());
    992 		return -1;
    993 	}
    994 	if (filename && *filename)
    995 	{
    996 	    if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) !=
    997 		SVRCORE_Success) {
    998 		fprintf(stderr, gettext("Security Initialization: Unable to create FilePinObj "
    999 		       "(%d)"), PR_GetError());
   1000 		return -1;
   1001 
   1002 	    }
   1003 	    if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
   1004 					       (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) {
   1005 		fprintf(stderr, gettext("Security Initialization: Unable to create AltPinObj "
   1006 		       "(%d)"), PR_GetError());
   1007 		return -1;
   1008 	    }
   1009 	    SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj);
   1010 	}
   1011 	else
   1012 	{
   1013 	    SVRCORE_RegisterPinObj((SVRCOREPinObj *)NTUserPinObj);
   1014 	}
   1015     }
   1016 #endif
   1017     return LDAP_SUCCESS;
   1018 
   1019 }
   1020 #endif /* LDAP_TOOL_ARGPIN */
   1021 
   1022 
   1023 /*
   1024  * initialize and return an LDAP session handle.
   1025  * if errors occur, we exit here.
   1026  */
   1027 LDAP *
   1028 ldaptool_ldap_init( int second_host )
   1029 {
   1030     LDAP	*ld = NULL;
   1031     char	*host;
   1032     int		port, rc, user_port;
   1033 
   1034     if ( ldaptool_not ) {
   1035 	return( NULL );
   1036     }
   1037 
   1038     if ( second_host ) {
   1039 	host = ldaptool_host2;
   1040 	port = ldaptool_port2;
   1041 	user_port = user_specified_port2;
   1042     } else {
   1043 	host = ldaptool_host;
   1044 	port = ldaptool_port;
   1045 	user_port = user_specified_port;
   1046     }
   1047 
   1048 
   1049     if ( ldaptool_verbose ) {
   1050 	printf( gettext("ldap_init( %s, %d )\n"), host, port );
   1051     }
   1052 
   1053 #if defined(NET_SSL)
   1054     /*
   1055      * Initialize security libraries and databases and LDAP session.  If
   1056      * ssl_certname is not NULL, then we will attempt to use client auth.
   1057      * if the server supports it.
   1058      */
   1059 #ifdef LDAP_TOOL_PKCS11
   1060     ldaptool_setcallbacks( &local_pkcs_fns );
   1061 
   1062     if ( !second_host 	&& secure
   1063 	 &&(rc = ldapssl_pkcs_init( &local_pkcs_fns))  < 0) {
   1064 	    /* secure connection requested -- fail if no SSL */
   1065 #ifndef SOLARIS_LDAP_CMD
   1066 	    rc = PORT_GetError();
   1067 #endif	/* SOLARIS_LDAP_CMD */
   1068 	    fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"),
   1069 		    rc, ldapssl_err2string( rc ));
   1070 	    exit( LDAP_LOCAL_ERROR );
   1071     }
   1072 
   1073 #ifdef LDAP_TOOL_ARGPIN
   1074     if (secure) {
   1075 	if (PinArgRegistration( )) {
   1076 	    exit( LDAP_LOCAL_ERROR);
   1077 	}
   1078     }
   1079 #endif /* LDAP_TOOL_ARGPIN */
   1080 
   1081 #else /* LDAP_TOOL_PKCS11 */
   1082     if ( !second_host 	&& secure
   1083 	 &&(rc = ldapssl_client_init( ssl_certdbpath, NULL )) < 0) {
   1084 	    /* secure connection requested -- fail if no SSL */
   1085 #ifndef SOLARIS_LDAP_CMD
   1086 	    rc = PORT_GetError();
   1087 #endif	/* SOLARIS_LDAP_CMD */
   1088 	    fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"),
   1089 		    rc, ldapssl_err2string( rc ));
   1090 	    exit( LDAP_LOCAL_ERROR );
   1091     }
   1092 #endif /* LDAP_TOOL_PKCS11 */
   1093 
   1094     /* set the default SSL strength (used for all future ld's we create) */
   1095     if ( ldapssl_set_strength( NULL, ssl_strength ) < 0 ) {
   1096         perror( "ldapssl_set_strength" );
   1097         exit( LDAP_LOCAL_ERROR );
   1098     }
   1099 
   1100 
   1101     if (secure) {
   1102 	if ( !user_port ) {
   1103 	    port = LDAPS_PORT;
   1104 	}
   1105 
   1106 	if (( ld = ldapssl_init( host, port,
   1107 		secure )) != NULL && ssl_certname != NULL )
   1108 	    if (ldapssl_enable_clientauth( ld, ssl_keydbpath, ssl_passwd,
   1109 		ssl_certname ) != 0 ) {
   1110 		exit ( ldaptool_print_lderror( ld, "ldapssl_enable_clientauth",
   1111 		    LDAPTOOL_CHECK4SSL_ALWAYS ));
   1112 	    }
   1113     } else {
   1114 	/* In order to support IPv6, we use NSPR I/O */
   1115 #ifdef SOLARIS_LDAP_CMD
   1116 	ld = ldap_init( host, port );
   1117 #else
   1118 	ld = prldap_init( host, port, 0 /* not shared across threads */ );
   1119 #endif /* SOLARIS_LDAP_CMD */
   1120     }
   1121 
   1122 #else /* NET_SSL */
   1123     /* In order to support IPv6, we use NSPR I/O */
   1124 #ifdef SOLARIS_LDAP_CMD
   1125     ld = ldap_init( host, port );
   1126 #else
   1127     ld = prldap_init( host, port, 0 /* not shared across threads */ );
   1128 #endif /* SOLARIS_LDAP_CMD */
   1129 #endif /* NET_SSL */
   1130 
   1131     if ( ld == NULL ) {
   1132 	perror( "ldap_init" );
   1133 	exit( LDAP_LOCAL_ERROR );
   1134     }
   1135 
   1136 #ifndef NO_LIBLCACHE
   1137     if ( cache_config_file != NULL ) {
   1138 	int	opt;
   1139 
   1140 	if ( lcache_init( ld, cache_config_file ) != 0 ) {
   1141 		exit( ldaptool_print_lderror( ld, cache_config_file,
   1142 			LDAPTOOL_CHECK4SSL_NEVER ));
   1143 	}
   1144 	opt = 1;
   1145 	(void) ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &opt );
   1146 	opt = LDAP_CACHE_LOCALDB;
   1147 	(void) ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &opt );
   1148 	if ( ldversion == -1 ) {	/* not set with -V */
   1149 	    ldversion = LDAP_VERSION2;	/* local db only supports v2 */
   1150 	}
   1151     }
   1152 #endif
   1153 
   1154 
   1155     ldap_set_option( ld, LDAP_OPT_REFERRALS, chase_referrals ? LDAP_OPT_ON:
   1156 	LDAP_OPT_OFF );
   1157     if ( chase_referrals ) {
   1158 	ldap_set_rebind_proc( ld, get_rebind_credentials, NULL );
   1159 	ldap_set_option( ld, LDAP_OPT_REFERRAL_HOP_LIMIT, &refhoplim );
   1160     }
   1161 
   1162     if ( ldversion == -1 ) {	/* not set with -V and not using local db */
   1163 	ldversion = LDAP_VERSION3;
   1164     }
   1165     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
   1166 
   1167     return( ld );
   1168 }
   1169 
   1170 
   1171 /*
   1172  * perform a bind to the LDAP server if needed.
   1173  * if an error occurs, we exit here.
   1174  */
   1175 void
   1176 ldaptool_bind( LDAP *ld )
   1177 {
   1178     int		rc;
   1179     char	*conv;
   1180     LDAPControl	auth_resp_ctrl, *ctrl_array[ 2 ], **bindctrls;
   1181 #ifdef HAVE_SASL_OPTIONS
   1182     void *defaults;
   1183 #endif
   1184 
   1185     if ( ldaptool_not ) {
   1186 	return;
   1187     }
   1188 
   1189     if ( send_auth_response_ctrl ) {
   1190 	auth_resp_ctrl.ldctl_oid = LDAP_CONTROL_AUTH_REQUEST;
   1191 	auth_resp_ctrl.ldctl_value.bv_val = NULL;
   1192 	auth_resp_ctrl.ldctl_value.bv_len = 0;
   1193 	auth_resp_ctrl.ldctl_iscritical = 0;
   1194 
   1195 	ctrl_array[0] = &auth_resp_ctrl;
   1196 	ctrl_array[1] = NULL;
   1197 	bindctrls = ctrl_array;
   1198     } else {
   1199 	bindctrls = NULL;
   1200     }
   1201 
   1202     /*
   1203      * if using LDAPv3 and not using client auth., omit NULL bind for
   1204      * efficiency.
   1205      */
   1206     if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
   1207 	    && ssl_certname == NULL ) {
   1208 #ifdef HAVE_SASL_OPTIONS
   1209 	if ( ldapauth != LDAP_AUTH_SASL ) {
   1210 	   return;
   1211 	}
   1212 #else
   1213 	return;
   1214 #endif
   1215     }
   1216 
   1217     /*
   1218      * do the bind, backing off one LDAP version if necessary
   1219      */
   1220     conv = ldaptool_local2UTF8( binddn );
   1221 
   1222 #ifdef HAVE_SASL_OPTIONS
   1223     if ( ldapauth == LDAP_AUTH_SASL) {
   1224 	if ( sasl_mech == NULL) {
   1225 	   fprintf( stderr, gettext("Please specify the SASL mechanism name when "
   1226 				"using SASL options\n"));
   1227 	   return;
   1228 	}
   1229 
   1230         if ( sasl_secprops != NULL) {
   1231            rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
   1232                                 (void *) sasl_secprops );
   1233 
   1234            if ( rc != LDAP_SUCCESS ) {
   1235               fprintf( stderr, gettext("Unable to set LDAP_OPT_X_SASL_SECPROPS: %s\n"),
   1236 				sasl_secprops );
   1237               return;
   1238            }
   1239         }
   1240 
   1241         defaults = ldaptool_set_sasl_defaults( ld, sasl_mech, sasl_authid, sasl_username, passwd, sasl_realm );
   1242         if (defaults == NULL) {
   1243 	   perror ("malloc");
   1244 	   exit (LDAP_NO_MEMORY);
   1245 	}
   1246 
   1247         rc = ldap_sasl_interactive_bind_s( ld, binddn, sasl_mech, NULL, NULL,
   1248                         sasl_flags, ldaptool_sasl_interact, defaults );
   1249 
   1250         if (rc != LDAP_SUCCESS ) {
   1251            ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
   1252         }
   1253     } else
   1254 #endif	/* HAVE_SASL_OPTIONS */
   1255         /*
   1256          * if using LDAPv3 and client auth., try a SASL EXTERNAL bind
   1257          */
   1258          if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
   1259 	    	&& ssl_certname != NULL ) {
   1260 	     rc = ldaptool_sasl_bind_s( ld, NULL, LDAP_SASL_EXTERNAL, NULL,
   1261 			bindctrls, NULL, NULL, "ldap_sasl_bind" );
   1262     	 }
   1263          else {
   1264 	     rc = ldaptool_simple_bind_s( ld, conv, passwd, bindctrls, NULL,
   1265 		    "ldap_simple_bind" );
   1266 	  }
   1267 
   1268     if ( rc == LDAP_SUCCESS ) {
   1269         if ( conv != NULL ) {
   1270            free( conv );
   1271 	}
   1272 	return;			/* success */
   1273     }
   1274 
   1275 #ifdef HAVE_SASL_OPTIONS
   1276   if (ldapauth != LDAP_AUTH_SASL) {
   1277 #endif	/* HAVE_SASL_OPTIONS */
   1278     if ( rc == LDAP_PROTOCOL_ERROR && ldversion > LDAP_VERSION2 ) {
   1279 	/*
   1280 	 * try again, backing off one LDAP version
   1281 	 * this is okay even for client auth. because the way to achieve
   1282 	 * client auth. with LDAPv2 is to perform a NULL simple bind.
   1283 	 */
   1284 	--ldversion;
   1285 	fprintf( stderr, gettext("%s: the server doesn't understand LDAPv%d;"
   1286 		" trying LDAPv%d instead...\n"), ldaptool_progname,
   1287 		ldversion + 1, ldversion );
   1288 	ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
   1289 	if (( rc = ldaptool_simple_bind_s( ld, conv, passwd,
   1290 		bindctrls, NULL, "ldap_simple_bind" )) == LDAP_SUCCESS ) {
   1291             if( conv != NULL )
   1292                 free( conv );
   1293 	    return;		/* a qualified success */
   1294 	}
   1295     }
   1296 #ifdef HAVE_SASL_OPTIONS
   1297   }
   1298 #endif	/* HAVE_SASL_OPTIONS */
   1299 
   1300     if ( conv != NULL ) {
   1301         free( conv );
   1302     }
   1303 
   1304     /*
   1305      * bind(s) failed -- fatal error
   1306      */
   1307     ldap_unbind( ld );
   1308     exit( rc );
   1309 }
   1310 
   1311 
   1312 /*
   1313  * close open files, unbind, etc.
   1314  */
   1315 void
   1316 ldaptool_cleanup( LDAP *ld )
   1317 {
   1318     if ( ld != NULL ) {
   1319 	ldap_unbind( ld );
   1320     }
   1321 
   1322     if ( ldaptool_fp != NULL && ldaptool_fp != stdin ) {
   1323 	fclose( ldaptool_fp );
   1324 	ldaptool_fp = NULL;
   1325     }
   1326 }
   1327 
   1328 
   1329 /*
   1330  * Retrieve and print an LDAP error message.  Returns the LDAP error code.
   1331  */
   1332 int
   1333 ldaptool_print_lderror( LDAP *ld, char *msg, int check4ssl )
   1334 {
   1335     int		lderr = ldap_get_lderrno( ld, NULL, NULL );
   1336 
   1337     ldap_perror( ld, msg );
   1338 #ifndef SOLARIS_LDAP_CMD
   1339     if ( secure && check4ssl != LDAPTOOL_CHECK4SSL_NEVER ) {
   1340 	if ( check4ssl == LDAPTOOL_CHECK4SSL_ALWAYS
   1341 		|| ( lderr == LDAP_SERVER_DOWN )) {
   1342 	    int		sslerr = PORT_GetError();
   1343 
   1344 	    fprintf( stderr, gettext("\tSSL error %d (%s)\n"), sslerr,
   1345 		    ldapssl_err2string( sslerr ));
   1346 	}
   1347     }
   1348 #endif	/* SOLARIS_LDAP_CMD */
   1349 
   1350     return( lderr );
   1351 }
   1352 
   1353 
   1354 /*
   1355  * print referrals to stderr
   1356  */
   1357 void
   1358 ldaptool_print_referrals( char **refs )
   1359 {
   1360     int		i;
   1361 
   1362     if ( refs != NULL ) {
   1363 	for ( i = 0; refs[ i ] != NULL; ++i ) {
   1364 	    fprintf( stderr, gettext("Referral: %s\n"), refs[ i ] );
   1365 	}
   1366     }
   1367 }
   1368 
   1369 
   1370 /*
   1371  * print contents of an extended response to stderr
   1372  * this is mainly to support unsolicited notifications
   1373  * Returns an LDAP error code (from the extended result).
   1374  */
   1375 int
   1376 ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg )
   1377 {
   1378     char		*oid;
   1379     struct berval	*data;
   1380 
   1381     if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 )
   1382 	    != LDAP_SUCCESS ) {
   1383 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1384     } else {
   1385 	if ( oid != NULL ) {
   1386 	    if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) {
   1387 		fprintf( stderr, gettext("%s: Notice of Disconnection\n"), msg );
   1388 	    } else {
   1389 		fprintf( stderr, gettext("%s: OID %s\n"), msg, oid );
   1390 	    }
   1391 	    ldap_memfree( oid );
   1392 	} else {
   1393 	    fprintf( stderr, gettext("%s: missing OID\n"), msg );
   1394 	}
   1395 
   1396 	if ( data != NULL ) {
   1397 	    fprintf( stderr, gettext("%s: Data (length %ld):\n"), msg, data->bv_len );
   1398 #if 0
   1399 /* XXXmcs: maybe we should display the actual data? */
   1400 	    lber_bprint( data->bv_val, data->bv_len );
   1401 #endif
   1402 	    ber_bvfree( data );
   1403 	}
   1404     }
   1405 
   1406     return parse_result( ld, res, NULL, msg, 1 );
   1407 }
   1408 
   1409 
   1410 /*
   1411  * Like ldap_sasl_bind_s() but calls wait4result() to display
   1412  * any referrals returned and report errors in a consistent way.
   1413  */
   1414 int
   1415 ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism,
   1416 	const struct berval *cred, LDAPControl **serverctrls,
   1417 	LDAPControl **clientctrls, struct berval **servercredp, char *msg )
   1418 {
   1419     int		rc, msgid;
   1420 
   1421     if ( servercredp != NULL ) {
   1422 	    *servercredp = NULL;
   1423     }
   1424 
   1425     if (( rc = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls,
   1426 	    clientctrls, &msgid )) != LDAP_SUCCESS ) {
   1427 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1428     } else {
   1429 	rc = wait4result( ld, msgid, servercredp, msg );
   1430     }
   1431 
   1432     return( rc );
   1433 }
   1434 
   1435 
   1436 /*
   1437  * Like ldap_simple_bind_s() but calls wait4result() to display
   1438  * any referrals returned and report errors in a consistent way.
   1439  */
   1440 int
   1441 ldaptool_simple_bind_s( LDAP *ld, const char *dn, const char *passwd,
   1442 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
   1443 {
   1444     struct berval	bv;
   1445 
   1446     bv.bv_val = (char *)passwd;		/* XXXmcs: had to cast away const */
   1447     bv.bv_len = ( passwd == NULL ? 0 : strlen( passwd ));
   1448     return( ldaptool_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &bv, serverctrls,
   1449 	    clientctrls, NULL, msg ));
   1450 }
   1451 
   1452 
   1453 /*
   1454  * Like ldap_add_ext_s() but calls wait4result() to display
   1455  * any referrals returned and report errors in a consistent way.
   1456  */
   1457 int
   1458 ldaptool_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
   1459 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
   1460 {
   1461     int		rc, msgid;
   1462 
   1463     if (( rc = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, &msgid ))
   1464 	    != LDAP_SUCCESS ) {
   1465 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1466     } else {
   1467 	/*
   1468 	 * 25-April-2000 Note: the next line used to read:
   1469 	 *	rc = wait4result( ld, msgid, NULL, msg );
   1470 	 * 'msgid' it was changed to 'LDAP_RES_ANY' in order to receive
   1471 	 * unsolicited notifications.
   1472 	 */
   1473 	rc = wait4result( ld, LDAP_RES_ANY, NULL, msg );
   1474     }
   1475 
   1476     return( rc );
   1477 }
   1478 
   1479 
   1480 /*
   1481  * Like ldap_modify_ext_s() but calls wait4result() to display
   1482  * any referrals returned and report errors in a consistent way.
   1483  */
   1484 int
   1485 ldaptool_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
   1486 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
   1487 {
   1488     int		rc, msgid;
   1489 
   1490     if (( rc = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
   1491 	    &msgid )) != LDAP_SUCCESS ) {
   1492 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1493     } else {
   1494 	rc = wait4result( ld, msgid, NULL, msg );
   1495     }
   1496 
   1497     return( rc );
   1498 }
   1499 
   1500 
   1501 /*
   1502  * Like ldap_delete_ext_s() but calls wait4result() to display
   1503  * any referrals returned and report errors in a consistent way.
   1504  */
   1505 int
   1506 ldaptool_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls,
   1507 	LDAPControl **clientctrls, char *msg )
   1508 {
   1509     int		rc, msgid;
   1510 
   1511     if (( rc = ldap_delete_ext( ld, dn, serverctrls, clientctrls, &msgid ))
   1512 	    != LDAP_SUCCESS ) {
   1513 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1514     } else {
   1515 	rc = wait4result( ld, msgid, NULL, msg );
   1516     }
   1517 
   1518     return( rc );
   1519 }
   1520 
   1521 
   1522 /*
   1523  * Like ldap_compare_ext_s() but calls wait4result() to display
   1524  * any referrals returned and report errors in a consistent way.
   1525  */
   1526 int ldaptool_compare_ext_s( LDAP *ld, const char *dn, const char *attrtype,
   1527 	    const struct berval *bvalue, LDAPControl **serverctrls,
   1528 	    LDAPControl **clientctrls, char *msg )
   1529 {
   1530     int		rc, msgid;
   1531 
   1532     if (( rc = ldap_compare_ext( ld, dn, attrtype, bvalue, serverctrls,
   1533 	    clientctrls, &msgid )) != LDAP_SUCCESS ) {
   1534 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1535     } else {
   1536 	rc = wait4result( ld, msgid, NULL, msg );
   1537     }
   1538 
   1539     return( rc );
   1540 }
   1541 
   1542 
   1543 /*
   1544  * Like ldap_rename_s() but calls wait4result() to display
   1545  * any referrals returned and report errors in a consistent way.
   1546  */
   1547 int
   1548 ldaptool_rename_s(  LDAP *ld, const char *dn, const char *newrdn,
   1549 	const char *newparent, int deleteoldrdn, LDAPControl **serverctrls,
   1550 	LDAPControl **clientctrls, char *msg )
   1551 {
   1552     int		rc, msgid;
   1553 
   1554     if (( rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn,
   1555 	    serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
   1556 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1557     } else {
   1558 	rc = wait4result( ld, msgid, NULL, msg );
   1559     }
   1560 
   1561     return( rc );
   1562 }
   1563 
   1564 
   1565 /*
   1566  * Wait for a result, check for and display errors and referrals.
   1567  * Also recognize and display "Unsolicited notification" messages.
   1568  * Returns an LDAP error code.
   1569  */
   1570 static int
   1571 wait4result( LDAP *ld, int msgid, struct berval **servercredp, char *msg )
   1572 {
   1573     LDAPMessage	*res;
   1574     int		rc, received_only_unsolicited = 1;
   1575 
   1576     while ( received_only_unsolicited ) {
   1577 	res = NULL;
   1578 	if (( rc = ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ))
   1579 		    == -1 ) {
   1580 	    ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1581 	    return( ldap_get_lderrno( ld, NULL, NULL ));
   1582 	}
   1583 
   1584 	/*
   1585 	 * Special handling for unsolicited notifications:
   1586 	 *    1. Parse and display contents.
   1587 	 *    2. go back and wait for another (real) result.
   1588 	 */
   1589 	if ( rc == LDAP_RES_EXTENDED
   1590 		    && ldap_msgid( res ) == LDAP_RES_UNSOLICITED ) {
   1591 	    rc = ldaptool_print_extended_response( ld, res,
   1592 		    "Unsolicited response" );
   1593 	} else {
   1594 	    rc = parse_result( ld, res, servercredp, msg, 1 );
   1595 	    received_only_unsolicited = 0;	/* we're done */
   1596 	}
   1597     }
   1598 
   1599     return( rc );
   1600 }
   1601 
   1602 
   1603 static int
   1604 parse_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp,
   1605 	char *msg, int freeit )
   1606 {
   1607     int		rc, lderr, errno;
   1608     int		pw_days=0, pw_hrs=0, pw_mins=0, pw_secs=0; /* for pwpolicy */
   1609     char	**refs = NULL;
   1610     LDAPControl	**ctrls;
   1611 
   1612     if (( rc = ldap_parse_result( ld, res, &lderr, NULL, NULL, &refs,
   1613 	    &ctrls, 0 )) != LDAP_SUCCESS ) {
   1614 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1615 	ldap_msgfree( res );
   1616 	return( rc );
   1617     }
   1618 
   1619     /* check for authentication response control & PWPOLICY control*/
   1620     if ( NULL != ctrls ) {
   1621 	int		i;
   1622 	char		*s;
   1623 
   1624 	for ( i = 0; NULL != ctrls[i]; ++i ) {
   1625 	    if ( 0 == strcmp( ctrls[i]->ldctl_oid,
   1626 			LDAP_CONTROL_AUTH_RESPONSE )) {
   1627 		    s = ctrls[i]->ldctl_value.bv_val;
   1628 		    if ( NULL == s ) {
   1629 			s = "Null";
   1630 		    } else if ( *s == '\0' ) {
   1631 			s = "Anonymous";
   1632 		    }
   1633 		fprintf( stderr, gettext("%s: bound as %s\n"), ldaptool_progname, s );
   1634 	    }
   1635 
   1636 	    if ( 0 == strcmp( ctrls[i]->ldctl_oid,
   1637 			LDAP_CONTROL_PWEXPIRING )) {
   1638 
   1639 		    /* Warn the user his passwd is to expire */
   1640 		    errno = 0;
   1641 		    pw_secs = atoi(ctrls[i]->ldctl_value.bv_val);
   1642 		    if ( pw_secs > 0  && errno != ERANGE ) {
   1643 			if ( pw_secs > 86400 ) {
   1644 				pw_days = ( pw_secs / 86400 );
   1645 				pw_secs = ( pw_secs % 86400 );
   1646 			}
   1647 			if ( pw_secs > 3600 ) {
   1648 				pw_hrs = ( pw_secs / 3600 );
   1649 				pw_secs = ( pw_secs % 3600 );
   1650 			}
   1651 			if ( pw_secs > 60 ) {
   1652 				pw_mins = ( pw_secs / 60 );
   1653 				pw_secs = ( pw_secs % 60 );
   1654 			}
   1655 
   1656 			printf(gettext("%s: Warning ! Your password will expire after "), ldaptool_progname);
   1657 			if ( pw_days ) {
   1658 				printf (gettext("%d days, "), pw_days);
   1659 			}
   1660 			if ( pw_hrs ) {
   1661 				printf (gettext("%d hrs, "), pw_hrs);
   1662 			}
   1663 			if ( pw_mins ) {
   1664 				printf (gettext("%d mins, "), pw_mins);
   1665 			}
   1666 			printf(gettext("%d seconds.\n"), pw_secs);
   1667 
   1668 		   }
   1669 		}
   1670 	}
   1671 	ldap_controls_free( ctrls );
   1672     }
   1673 
   1674     if ( servercredp != NULL && ( rc = ldap_parse_sasl_bind_result( ld, res,
   1675 	    servercredp, 0 )) != LDAP_SUCCESS ) {
   1676 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1677 	ldap_msgfree( res );
   1678 	return( rc );
   1679     }
   1680 
   1681     if ( freeit ) {
   1682 	ldap_msgfree( res );
   1683     }
   1684 
   1685     if ( LDAPTOOL_RESULT_IS_AN_ERROR( lderr )) {
   1686 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
   1687     }
   1688 
   1689     if ( refs != NULL ) {
   1690 	ldaptool_print_referrals( refs );
   1691 	ldap_value_free( refs );
   1692     }
   1693 
   1694     return( lderr );
   1695 }
   1696 
   1697 
   1698 /*
   1699  * if -M was passed on the command line, create and return a "Manage DSA IT"
   1700  * LDAPv3 control.  If not, return NULL.
   1701  */
   1702 LDAPControl *
   1703 ldaptool_create_manage_dsait_control( void )
   1704 {
   1705     LDAPControl	*ctl;
   1706 
   1707     if ( !send_manage_dsait_ctrl ) {
   1708 	return( NULL );
   1709     }
   1710 
   1711     if (( ctl = (LDAPControl *)calloc( 1, sizeof( LDAPControl ))) == NULL ||
   1712 	    ( ctl->ldctl_oid = strdup( LDAP_CONTROL_MANAGEDSAIT )) == NULL ) {
   1713 	perror( "calloc" );
   1714 	exit( LDAP_NO_MEMORY );
   1715     }
   1716 
   1717     ctl->ldctl_iscritical = 1;
   1718 
   1719     return( ctl );
   1720 }
   1721 
   1722 /*
   1723  * if -y "dn" was supplied on the command line, create the control
   1724  */
   1725 LDAPControl *
   1726 ldaptool_create_proxyauth_control( LDAP *ld )
   1727 {
   1728     LDAPControl	*ctl = NULL;
   1729     int rc;
   1730 
   1731 
   1732     if ( !proxyauth_id)
   1733 	return( NULL );
   1734 
   1735     if ( 2 == proxyauth_version ) {
   1736 	rc = ldap_create_proxiedauth_control( ld, proxyauth_id, &ctl);
   1737     } else {
   1738 	rc = ldap_create_proxyauth_control( ld, proxyauth_id, 1, &ctl);
   1739     }
   1740     if ( rc != LDAP_SUCCESS)
   1741     {
   1742 	if (ctl)
   1743 	    ldap_control_free( ctl);
   1744 	return NULL;
   1745     }
   1746     return( ctl );
   1747 }
   1748 
   1749 #ifndef SOLARIS_LDAP_CMD
   1750 LDAPControl *
   1751 ldaptool_create_geteffectiveRights_control ( LDAP *ld, const char *authzid,
   1752 											const char **attrlist)
   1753 {
   1754     LDAPControl	*ctl = NULL;
   1755     int rc;
   1756 
   1757 	rc = ldap_create_geteffectiveRights_control( ld, authzid, attrlist, 1,
   1758 							&ctl);
   1759 
   1760     if ( rc != LDAP_SUCCESS)
   1761     {
   1762 		if (ctl)
   1763 	    	ldap_control_free( ctl);
   1764 		return NULL;
   1765     }
   1766     return( ctl );
   1767 }
   1768 #endif	/* SOLARIS_LDAP_CMD */
   1769 
   1770 
   1771 void
   1772 ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array)
   1773 {
   1774 
   1775     int i;
   1776     for (i=0; i< CONTROL_REQUESTS; i++)
   1777     {
   1778 	if (*(array + i) == NULL)
   1779 	{
   1780 	    *(array + i +1) = NULL;
   1781 	    *(array + i) = ctrl;
   1782 	    return ;
   1783 	}
   1784     }
   1785     fprintf(stderr, gettext("%s: failed to store request control!!!!!!\n"),
   1786 	    ldaptool_progname);
   1787 }
   1788 
   1789 /*
   1790  * Dispose of all controls in array and prepare array for reuse.
   1791  */
   1792 void
   1793 ldaptool_reset_control_array( LDAPControl **array )
   1794 {
   1795     int		i;
   1796 
   1797     for ( i = 0; i < CONTROL_REQUESTS; i++ ) {
   1798 	if ( array[i] != NULL ) {
   1799 	    ldap_control_free( array[i] );
   1800 	    array[i] = NULL;
   1801 	}
   1802     }
   1803 }
   1804 
   1805 /*
   1806  * This function calculates control value and its length. *value can
   1807  * be pointing to plain value, ":b64encoded value" or "<fileurl".
   1808  */
   1809 static int
   1810 calculate_ctrl_value( const char *value,
   1811 	char **ctrl_value, int *vlen)
   1812 {
   1813     int b64;
   1814     if (*value == ':') {
   1815 	value++;
   1816 	b64 = 1;
   1817     } else {
   1818 	b64 = 0;
   1819     }
   1820     *ctrl_value = (char *)value;
   1821 
   1822     if ( b64 ) {
   1823 	if (( *vlen = ldif_base64_decode( (char *)value,
   1824 		(unsigned char *)value )) < 0 ) {
   1825 	    fprintf( stderr,
   1826 		gettext("Unable to decode base64 control value \"%s\"\n"), value);
   1827 	    return( -1 );
   1828 	}
   1829     } else {
   1830 	*vlen = (int)strlen(*ctrl_value);
   1831     }
   1832     return( 0 );
   1833 }
   1834 
   1835 /*
   1836  * Parse the optarg from -J option of ldapsearch
   1837  * and within LDIFfile for ldapmodify. Take ctrl_arg
   1838  * (the whole string) and divide it into oid, criticality
   1839  * and value. This function breaks down original ctrl_arg
   1840  * with '\0' in places. Also, calculate length of valuestring.
   1841  */
   1842 int
   1843 ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep,
   1844 		char **ctrl_oid, int *ctrl_criticality,
   1845 		char **ctrl_value, int *vlen)
   1846 {
   1847     char *s, *p;
   1848     int strict;
   1849 
   1850     /* Initialize passed variables with default values */
   1851     *ctrl_oid = *ctrl_value = NULL;
   1852     *ctrl_criticality = 0;
   1853     *vlen = 0;
   1854 
   1855     strict = (sep == ' ' ? 1 : 0);
   1856     if(!(s=strchr(ctrl_arg, sep))) {
   1857 	/* Possible values of ctrl_arg are
   1858 	 * oid[:value|::b64value|:<fileurl] within LDIF, i.e. sep=' '
   1859 	 * oid from command line option, i.e. sep=':'
   1860 	 */
   1861 	if (sep == ' ') {
   1862 	    if (!(s=strchr(ctrl_arg, ':'))) {
   1863 		*ctrl_oid = ctrl_arg;
   1864 	    }
   1865 	    else {
   1866 		/* ctrl_arg is of oid:[value|:b64value|<fileurl]
   1867 		 * form in the LDIF record. So, grab the oid and then
   1868 		 * jump to continue the parsing of ctrl_arg.
   1869 		 * 's' is pointing just after oid ends.
   1870 		 */
   1871 		*s++ = '\0';
   1872 		*ctrl_oid = ctrl_arg;
   1873 		return (calculate_ctrl_value( s, ctrl_value, vlen ));
   1874 	    }
   1875 	} else {
   1876 		/* oid - from command line option, i.e. sep=':' */
   1877 		*ctrl_oid = ctrl_arg;
   1878 	}
   1879     }
   1880     else {
   1881 	/* Possible values of ctrl_arg are
   1882 	 * oid:criticality[:value|::b64value|:<fileurl] - command line
   1883 	 * oid criticality[:value|::b64value|:<fileurl] - LDIF
   1884 	 * And 's' is pointing just after oid ends.
   1885 	 */
   1886 
   1887 	if (*(s+1) == '\0') {
   1888 	    fprintf( stderr, gettext("missing value\n") );
   1889 	    return( -1 );
   1890 	}
   1891 	*s = '\0';
   1892 	*ctrl_oid = ctrl_arg;
   1893 	p = ++s;
   1894 	if(!(s=strchr(p, ':'))) {
   1895 	    if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
   1896 			== -1 ) {
   1897 		fprintf( stderr, gettext("Invalid criticality value\n") );
   1898 		return( -1 );
   1899 	    }
   1900 	}
   1901 	else {
   1902 	    if (*(s+1) == '\0') {
   1903 	        fprintf( stderr, gettext("missing value\n") );
   1904 	        return ( -1 );
   1905 	    }
   1906 	    *s++ = '\0';
   1907             if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
   1908 			== -1 ) {
   1909 		fprintf( stderr, gettext("Invalid criticality value\n") );
   1910 		return ( -1 );
   1911 	    }
   1912 	    return (calculate_ctrl_value( s, ctrl_value, vlen ));
   1913 	}
   1914     }
   1915 
   1916     return( 0 );
   1917 }
   1918 
   1919 
   1920 /*
   1921  * callback function for LDAP bind credentials
   1922  */
   1923 static int
   1924 LDAP_CALL
   1925 LDAP_CALLBACK
   1926 get_rebind_credentials( LDAP *ld, char **whop, char **credp,
   1927         int *methodp, int freeit, void* arg )
   1928 {
   1929     if ( !freeit ) {
   1930 	*whop = binddn;
   1931 	*credp = passwd;
   1932 	*methodp = LDAP_AUTH_SIMPLE;
   1933     }
   1934 
   1935     return( LDAP_SUCCESS );
   1936 }
   1937 
   1938 
   1939 /*
   1940  * return pointer to pathname to temporary directory.
   1941  * First we see if the environment variable "TEMP" is set and use it.
   1942  * Then we see if the environment variable "TMP" is set and use it.
   1943  * If this fails, we use "/tmp" on UNIX and fail on Windows.
   1944  */
   1945 char *
   1946 ldaptool_get_tmp_dir( void )
   1947 {
   1948     char	*p;
   1949     int		offset;
   1950 
   1951     if (( p = getenv( "TEMP" )) == NULL && ( p = getenv( "TMP" )) == NULL ) {
   1952 #ifdef _WINDOWS
   1953 	fprintf( stderr, gettext("%s: please set the TEMP environment variable.\n"),
   1954 		ldaptool_progname );
   1955 	exit( LDAP_LOCAL_ERROR );
   1956 #else
   1957 	return( "/tmp" );	/* last resort on UNIX */
   1958 #endif
   1959     }
   1960 
   1961     /*
   1962      * remove trailing slash if present
   1963      */
   1964     offset = strlen( p ) - 1;
   1965     if ( p[offset] == '/'
   1966 #ifdef _WINDOWS
   1967 	    || p[offset] == '\\'
   1968 #endif
   1969 	    ) {
   1970 	if (( p = strdup( p )) == NULL ) {
   1971 	    perror( "strdup" );
   1972 	    exit( LDAP_NO_MEMORY );
   1973 	}
   1974 
   1975 	p[offset] = '\0';
   1976     }
   1977 
   1978     return( p );
   1979 }
   1980 
   1981 
   1982 int
   1983 ldaptool_berval_is_ascii( const struct berval *bvp )
   1984 {
   1985     unsigned long	j;
   1986     int			is_ascii = 1;	 /* optimistic */
   1987 
   1988     for ( j = 0; j < bvp->bv_len; ++j ) {
   1989 	if ( !isascii( bvp->bv_val[ j ] )) {
   1990 	    is_ascii = 0;
   1991 	    break;
   1992 	}
   1993     }
   1994 
   1995     return( is_ascii );
   1996 }
   1997 
   1998 
   1999 #ifdef LDAP_DEBUG_MEMORY
   2000 #define LDAPTOOL_ALLOC_FREED	0xF001
   2001 #define LDAPTOOL_ALLOC_INUSE	0xF002
   2002 
   2003 static void *
   2004 ldaptool_debug_alloc( void *ptr, size_t size )
   2005 {
   2006     int		*statusp;
   2007     void	*systemptr;
   2008 
   2009     if ( ptr == NULL ) {
   2010 	systemptr = NULL;
   2011     } else {
   2012 	systemptr = (void *)((char *)ptr - sizeof(int));
   2013     }
   2014 
   2015     if (( statusp = (int *)realloc( systemptr, size + sizeof(int))) == NULL ) {
   2016 	fprintf( stderr, gettext("%s: realloc( 0x%x, %d) failed\n"),
   2017 		ldaptool_progname, systemptr, size );
   2018 	return( NULL );
   2019     }
   2020 
   2021     *statusp = LDAPTOOL_ALLOC_INUSE;
   2022 
   2023     return( (char *)statusp + sizeof(int));
   2024 }
   2025 
   2026 
   2027 static void *
   2028 ldaptool_debug_realloc( void *ptr, size_t size )
   2029 {
   2030     void	*p;
   2031 
   2032     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2033 	fprintf( stderr, gettext("%s: => realloc( 0x%x, %d )\n"),
   2034 		ldaptool_progname, ptr, size );
   2035     }
   2036 
   2037     p = ldaptool_debug_alloc( ptr, size );
   2038 
   2039     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2040 	fprintf( stderr, gettext("%s: 0x%x <= realloc()\n"), ldaptool_progname, p );
   2041     }
   2042 
   2043     return( p );
   2044 }
   2045 
   2046 
   2047 static void *
   2048 ldaptool_debug_malloc( size_t size )
   2049 {
   2050     void	*p;
   2051 
   2052     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2053 	fprintf( stderr, gettext("%s: => malloc( %d)\n"), ldaptool_progname, size );
   2054     }
   2055 
   2056     p = ldaptool_debug_alloc( NULL, size );
   2057 
   2058     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2059 	fprintf( stderr, gettext("%s: 0x%x <= malloc()\n"), ldaptool_progname, p );
   2060     }
   2061 
   2062     return( p );
   2063 }
   2064 
   2065 
   2066 static void *
   2067 ldaptool_debug_calloc( size_t nelem, size_t elsize )
   2068 {
   2069     void	*p;
   2070 
   2071     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2072 	fprintf( stderr, gettext("%s: => calloc( %d, %d )\n"),
   2073 		ldaptool_progname, nelem, elsize );
   2074     }
   2075 
   2076     if (( p = ldaptool_debug_alloc( NULL, nelem * elsize )) != NULL ) {
   2077 	memset( p, 0, nelem * elsize );
   2078     }
   2079 
   2080     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2081 	fprintf( stderr, gettext("%s: 0x%x <= calloc()\n"), ldaptool_progname, p );
   2082     }
   2083 
   2084     return( p );
   2085 }
   2086 
   2087 
   2088 static void
   2089 ldaptool_debug_free( void *ptr )
   2090 {
   2091     int		*statusp = (int *)((char *)ptr - sizeof(int));
   2092 
   2093     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
   2094 	fprintf( stderr, gettext("%s: => free( 0x%x )\n"), ldaptool_progname, ptr );
   2095     }
   2096 
   2097     if ( ptr == NULL ) {
   2098 	fprintf( stderr, gettext("%s: bad free( 0x0 ) attempted (NULL pointer)\n"),
   2099 		ldaptool_progname );
   2100     } else if ( *statusp != LDAPTOOL_ALLOC_INUSE ) {
   2101 	fprintf( stderr, gettext("%s: bad free( 0x%x ) attempted"
   2102 		" (block not in use; status is %d)\n"),
   2103 		ldaptool_progname, ptr, *statusp );
   2104     } else {
   2105 	*statusp = LDAPTOOL_ALLOC_FREED;
   2106 	free( statusp );
   2107     }
   2108 }
   2109 #endif /* LDAP_DEBUG_MEMORY */
   2110 
   2111 
   2112 #if defined(NET_SSL)
   2113 /*
   2114  * Derive key database path from certificate database path and return a
   2115  * malloc'd string.
   2116  *
   2117  * We just return an exact copy of "certdbpath" unless it ends in "cert.db",
   2118  * "cert5.db", or "cert7.db".  In those cases we strip off everything from
   2119  * "cert" on and append "key.db", "key5.db", or "key3.db" as appropriate.
   2120  * Strangely enough cert7.db and key3.db go together.
   2121  */
   2122 static char *
   2123 certpath2keypath( char *certdbpath )
   2124 {
   2125     char	*keydbpath, *appendstr;
   2126     int		len, striplen;
   2127 
   2128     if ( certdbpath == NULL ) {
   2129 	return( NULL );
   2130     }
   2131 
   2132     if (( keydbpath = strdup( certdbpath )) == NULL ) {
   2133 	perror( "strdup" );
   2134 	exit( LDAP_NO_MEMORY );
   2135     }
   2136 
   2137     len = strlen( keydbpath );
   2138     if ( len > 7 &&
   2139 	    strcasecmp( "cert.db", keydbpath + len - 7 ) == 0 ) {
   2140 	striplen = 7;
   2141 	appendstr = "key.db";
   2142 
   2143     } else if ( len > 8 &&
   2144 	    strcasecmp( "cert5.db", keydbpath + len - 8 ) == 0 ) {
   2145 	striplen = 8;
   2146 	appendstr = "key5.db";
   2147     } else if ( len > 8 &&
   2148 	    strcasecmp( "cert7.db", keydbpath + len - 8 ) == 0 ) {
   2149 	striplen = 8;
   2150 	appendstr = "key3.db";
   2151     } else {
   2152 	striplen = 0;
   2153     }
   2154 
   2155     if ( striplen > 0 ) {
   2156 	/*
   2157 	 * The following code assumes that strlen( appendstr ) < striplen!
   2158 	 */
   2159 	strcpy( keydbpath + len - striplen, appendstr );
   2160     }
   2161 
   2162     return( keydbpath );
   2163 }
   2164 
   2165 #ifdef LDAP_TOOL_PKCS11
   2166 static
   2167 char *
   2168 buildTokenCertName( const char *tokenName, const char *certName)
   2169 {
   2170 
   2171     int tokenlen = strlen(tokenName);
   2172     int len = tokenlen + strlen(certName) +2;
   2173     char *result;
   2174 
   2175     if (( result = malloc( len )) != NULL) {
   2176 	strcpy(result, tokenName);
   2177 	*(result+tokenlen) = ':';
   2178 	++tokenlen;
   2179 	strcpy(result+tokenlen, certName);
   2180     } else {
   2181 	perror("malloc");
   2182 	exit( LDAP_NO_MEMORY );
   2183     }
   2184     return result;
   2185 }
   2186 
   2187 
   2188 
   2189 static
   2190 int
   2191 ldaptool_getcertpath( void *context, char **certlocp )
   2192 {
   2193 
   2194     *certlocp = ssl_certdbpath;
   2195     if ( ldaptool_verbose ) {
   2196 	if (ssl_certdbpath)
   2197 	{
   2198 	    printf(gettext("ldaptool_getcertpath -- %s\n"), ssl_certdbpath );
   2199 	}
   2200 	else
   2201 	{
   2202 	    printf(gettext("ldaptool_getcertpath -- (null)\n"));
   2203 	}
   2204 
   2205     }
   2206     return LDAP_SUCCESS;
   2207 }
   2208 
   2209 int
   2210 ldaptool_getcertname( void *context, char **certnamep )
   2211 {
   2212 
   2213    *certnamep = ssl_certname;
   2214     if ( ldaptool_verbose ) {
   2215 	if (ssl_certname)
   2216 	{
   2217 	    printf(gettext("ldaptool_getcertname -- %s\n"), *certnamep);
   2218 	}
   2219 	else
   2220 	{
   2221 	    printf(gettext("ldaptool_getcertname -- (null)\n"));
   2222 	}
   2223     }
   2224     return LDAP_SUCCESS;
   2225 }
   2226 
   2227 int
   2228 ldaptool_getkeypath(void *context, char **keylocp )
   2229 {
   2230     *keylocp = ssl_keydbpath;
   2231     if ( ldaptool_verbose ) {
   2232 	if (ssl_keydbpath)
   2233 	{
   2234 	    printf(gettext("ldaptool_getkeypath -- %s\n"),*keylocp);
   2235 	}
   2236 	else
   2237 	{
   2238 	    printf(gettext("ldaptool_getkeypath -- (null)\n"));
   2239 	}
   2240     }
   2241 
   2242     return LDAP_SUCCESS;
   2243 }
   2244 
   2245 int
   2246 ldaptool_gettokenname( void *context, char **tokennamep )
   2247 {
   2248 
   2249     *tokennamep = pkcs_token;
   2250     if ( ldaptool_verbose ) {
   2251 	if (pkcs_token)
   2252 	{
   2253 	    printf(gettext("ldaptool_gettokenname -- %s\n"),*tokennamep);
   2254 	}
   2255 	else
   2256 	{
   2257 	    printf(gettext("ldaptool_gettokenname -- (null)\n"));
   2258 	}
   2259     }
   2260 
   2261     return LDAP_SUCCESS;
   2262 }
   2263 int
   2264 ldaptool_gettokenpin( void *context, const char *tokennamep, char **tokenpinp)
   2265 {
   2266 
   2267 #if 0
   2268   char *localtoken;
   2269 #endif
   2270 
   2271 /* XXXceb this stuff is removed for the time being.
   2272  * This function should return the pin from ssl_password
   2273  */
   2274 
   2275 
   2276   *tokenpinp = ssl_passwd;
   2277   return LDAP_SUCCESS;
   2278 
   2279 #if 0
   2280 
   2281   ldaptool_gettokenname( NULL, &localtoken);
   2282 
   2283   if (strcmp( localtoken, tokennamep))
   2284 
   2285       *tokenpinp = pkcs_pin;
   2286    else
   2287       *tokenpinp = NULL;
   2288 
   2289     if ( ldaptool_verbose ) {
   2290 	if (pkcs_pin)
   2291 	{
   2292 	    printf(gettext("ldaptool_getokenpin --%s\n"), tokenpinp);
   2293 	}
   2294 	else
   2295 	{
   2296 	    printf(gettext("ldaptool_getokenpin -- (null)\n"));
   2297 	}
   2298     }
   2299     return LDAP_SUCCESS;
   2300 #endif
   2301 }
   2302 
   2303 int
   2304 ldaptool_getmodpath( void *context, char **modulep )
   2305 {
   2306     *modulep = ssl_secmodpath;
   2307     if ( ldaptool_verbose ) {
   2308 	if (ssl_secmodpath)
   2309 	{
   2310 	    printf(gettext("ldaptool_getmodpath -- %s\n"), *modulep);
   2311 	}
   2312 	else
   2313 	{
   2314 	    printf(gettext("ldaptool_getmodpath -- (null)\n"));
   2315 	}
   2316     }
   2317 
   2318     return LDAP_SUCCESS;
   2319 }
   2320 
   2321 int
   2322 ldaptool_getdonglefilename( void *context, char **filename )
   2323 {
   2324     *filename = ssl_donglefile;
   2325     if ( ldaptool_verbose ) {
   2326 	if (ssl_donglefile)
   2327 	{
   2328 	    printf(gettext("ldaptool_getdonglefilename -- %s\n"), *filename);
   2329 	}
   2330 	else
   2331 	{
   2332 	    printf(gettext("ldaptool_getdonglefilename -- (null)\n"));
   2333 	}
   2334 
   2335     }
   2336 
   2337     return LDAP_SUCCESS;
   2338 }
   2339 
   2340 static int
   2341 ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns)
   2342 {
   2343   pfns->pkcs_getcertpath = (int (*)(void *, char **))ldaptool_getcertpath;
   2344   pfns->pkcs_getcertname =  (int (*)(void *, char **))ldaptool_getcertname;
   2345   pfns->pkcs_getkeypath =  (int (*)(void *, char **)) ldaptool_getkeypath;
   2346   pfns->pkcs_getmodpath =  (int (*)(void *, char **)) ldaptool_getmodpath;
   2347   pfns->pkcs_getpin =  (int (*)(void *, const char*, char **)) ldaptool_gettokenpin;
   2348   pfns->pkcs_gettokenname =  (int (*)(void *, char **)) ldaptool_gettokenname;
   2349   pfns->pkcs_getdonglefilename =  (int (*)(void *, char **)) ldaptool_getdonglefilename;
   2350   pfns->local_structure_id=PKCS_STRUCTURE_ID;
   2351   return LDAP_SUCCESS;
   2352 }
   2353 
   2354 
   2355 
   2356 #ifdef FORTEZZA
   2357 static int
   2358 ldaptool_fortezza_init( int exit_on_error )
   2359 {
   2360     int		rc, errcode;
   2361 
   2362     if ( fortezza_personality == NULL && fortezza_cardmask == 0 ) { /* no FORTEZZA desired */
   2363 	SSL_EnableGroup( SSL_GroupFortezza, DSFalse );	/* disable FORTEZZA */
   2364 	return( 0 );
   2365     }
   2366 
   2367     if (( rc = FortezzaConfigureServer( ldaptool_fortezza_getpin, fortezza_cardmask,
   2368 	    fortezza_personality, ldaptool_fortezza_alert, NULL, &errcode,
   2369 	    fortezza_krlfile )) < 0 ) {
   2370 	fprintf( stderr,
   2371 		"%s: FORTEZZA initialization failed (error %d - %s)\n",
   2372 		ldaptool_progname, errcode,
   2373 		ldaptool_fortezza_err2string( errcode ));
   2374 	if ( exit_on_error ) {
   2375 	    exit( LDAP_LOCAL_ERROR );
   2376 	}
   2377 
   2378 	SSL_EnableGroup( SSL_GroupFortezza, DSFalse );	/* disable FORTEZZA */
   2379 	return( -1 );
   2380     }
   2381 
   2382     SSL_EnableGroup( SSL_GroupFortezza, DSTrue );	/* enable FORTEZZA */
   2383     return( 0 );
   2384 }
   2385 
   2386 
   2387 static int
   2388 ldaptool_fortezza_alert( void *arg, PRBool onOpen, char *string,
   2389 	int value1, void *value2 )
   2390 {
   2391     fprintf( stderr, "%s: FORTEZZA alert: ", ldaptool_progname );
   2392     fprintf( stderr, string, value1, value2 );
   2393     fprintf( stderr, "\n" );
   2394     return( 1 );
   2395 }
   2396 
   2397 
   2398 static void *
   2399 ldaptool_fortezza_getpin( char **passwordp )
   2400 {
   2401     *passwordp = fortezza_pin;
   2402     return( *passwordp );
   2403 }
   2404 
   2405 
   2406 /*
   2407  * convert a Fortezza error code (as returned by FortezzaConfigureServer()
   2408  * into a human-readable string.
   2409  *
   2410  * Error strings are intentionally similar to those found in
   2411  * ns/netsite/lib/libadmin/httpcon.c
   2412  */
   2413 static char *
   2414 ldaptool_fortezza_err2string( int err )
   2415 {
   2416     char	*s;
   2417 
   2418     switch( err ) {
   2419     case FORTEZZA_BADPASSWD:
   2420 	s = "invalid pin number";
   2421 	break;
   2422     case FORTEZZA_BADCARD:
   2423 	s = "bad or missing card";
   2424 	break;
   2425     case FORTEZZA_MISSING_KRL:
   2426 	s = "bad or missing compromised key list";
   2427 	break;
   2428     case FORTEZZA_CERT_INIT_ERROR:
   2429 	s = "unable to initialize certificate cache.  either a cert on "
   2430 		"the card is bad, or an old FORTEZZA certificate is in a"
   2431 		 "readonly database";
   2432 	break;
   2433     case FORTEZZA_EXPIRED_CERT:
   2434 	s = "unable to verify certificate";
   2435 	break;
   2436     default:
   2437 	s = "unknown error";
   2438     }
   2439 
   2440     return( s );
   2441 }
   2442 
   2443 #endif /* FORTEZZA */
   2444 #endif /* LDAP_TOOL_PKCS11 */
   2445 #endif /* NET_SSL */
   2446 
   2447 int
   2448 ldaptool_boolean_str2value ( const char *ptr, int strict )
   2449 {
   2450     if (strict) {
   2451 	if ( !(strcasecmp(ptr, "true"))) {
   2452 	    return 1;
   2453 	}
   2454 	else if ( !(strcasecmp(ptr, "false"))) {
   2455 	    return 0;
   2456 	}
   2457 	else {
   2458 	    return (-1);
   2459 	}
   2460     }
   2461     else {
   2462 	if ( !(strcasecmp(ptr, "true")) ||
   2463 	     !(strcasecmp(ptr, "t")) ||
   2464 	     !(strcmp(ptr, "1")) ) {
   2465 		return (1);
   2466 	}
   2467 	else if ( !(strcasecmp(ptr, "false")) ||
   2468 	     !(strcasecmp(ptr, "f")) ||
   2469 	     !(strcmp(ptr, "0")) ) {
   2470 	    	return (0);
   2471 	}
   2472 	else {
   2473 	    return (-1);
   2474 	}
   2475     }
   2476 }
   2477 
   2478 FILE *
   2479 ldaptool_open_file(const char *filename, const char *mode)
   2480 {
   2481 #ifdef _LARGEFILE64_SOURCE
   2482 	return fopen64(filename, mode);
   2483 #else
   2484 	return fopen(filename, mode);
   2485 #endif
   2486 }
   2487 
   2488 #ifdef later
   2489 /* Functions for list in ldapdelete.c */
   2490 
   2491 void L_Init(Head *list)
   2492 {
   2493     if(list)
   2494     {
   2495         list->first = NULL;
   2496         list->last = NULL;
   2497         list->count = 0;
   2498     }
   2499 }
   2500 
   2501 void L_Insert(Element *Node, Head *HeadNode)
   2502 {
   2503     if (!Node || !HeadNode)
   2504         return;
   2505 
   2506     Node->right = NULL;
   2507 
   2508     if (HeadNode->first == NULL)
   2509     {
   2510         Node->left= NULL;
   2511         HeadNode->last = HeadNode->first = Node;
   2512     }
   2513     else
   2514     {
   2515         Node->left = HeadNode->last;
   2516         HeadNode->last = Node->left->right = Node;
   2517     }
   2518     HeadNode->count++;
   2519 }
   2520 
   2521 void L_Remove(Element *Node, Head *HeadNode)
   2522 {
   2523     Element *traverse = NULL;
   2524     Element *prevnode = NULL;
   2525 
   2526     if(!Node || !HeadNode)
   2527         return;
   2528 
   2529     for(traverse = HeadNode->first; traverse; traverse = traverse->right)
   2530     {
   2531         if(traverse == Node)
   2532         {
   2533             if(HeadNode->first == traverse)
   2534             {
   2535                 HeadNode->first = traverse->right;
   2536             }
   2537             if(HeadNode->last == traverse)
   2538             {
   2539                 HeadNode->last = prevnode;
   2540             }
   2541             traverse = traverse->right;
   2542             if(prevnode != NULL)
   2543             {
   2544                 prevnode->right = traverse;
   2545             }
   2546             if(traverse != NULL)
   2547             {
   2548                 traverse->left = prevnode;
   2549             }
   2550             HeadNode->count--;
   2551             return;
   2552         }
   2553         else /* traverse != node */
   2554         {
   2555             prevnode = traverse;
   2556         }
   2557     }
   2558 }
   2559 #endif
   2560 
   2561 #ifdef HAVE_SASL_OPTIONS
   2562 /*
   2563  * Function checks for valid args, returns an error if not found
   2564  * and sets SASL params from command line
   2565  */
   2566 
   2567 static int
   2568 saslSetParam(char *saslarg)
   2569 {
   2570 	char *attr = NULL;
   2571 
   2572 	attr = strchr(saslarg, '=');
   2573 	if (attr == NULL) {
   2574            fprintf( stderr, gettext("Didn't find \"=\" character in %s\n"), saslarg);
   2575            return (-1);
   2576 	}
   2577 	*attr = '\0';
   2578 	attr++;
   2579 
   2580 	if (!strcasecmp(saslarg, "secProp")) {
   2581 	     if ( sasl_secprops != NULL ) {
   2582                 fprintf( stderr, gettext("secProp previously specified\n"));
   2583                 return (-1);
   2584              }
   2585              if (( sasl_secprops = strdup(attr)) == NULL ) {
   2586 		perror ("malloc");
   2587                 exit (LDAP_NO_MEMORY);
   2588              }
   2589 	} else if (!strcasecmp(saslarg, "realm")) {
   2590 	     if ( sasl_realm != NULL ) {
   2591                 fprintf( stderr, gettext("Realm previously specified\n"));
   2592                 return (-1);
   2593              }
   2594              if (( sasl_realm = strdup(attr)) == NULL ) {
   2595 		perror ("malloc");
   2596                 exit (LDAP_NO_MEMORY);
   2597              }
   2598 	} else if (!strcasecmp(saslarg, "authzid")) {
   2599              if (sasl_username != NULL) {
   2600                 fprintf( stderr, gettext("Authorization name previously specified\n"));
   2601                 return (-1);
   2602              }
   2603              if (( sasl_username = strdup(attr)) == NULL ) {
   2604 		perror ("malloc");
   2605                 exit (LDAP_NO_MEMORY);
   2606              }
   2607 	} else if (!strcasecmp(saslarg, "authid")) {
   2608              if ( sasl_authid != NULL ) {
   2609                 fprintf( stderr, gettext("Authentication name previously specified\n"));
   2610                 return (-1);
   2611              }
   2612              if (( sasl_authid = strdup(attr)) == NULL) {
   2613 		perror ("malloc");
   2614                 exit (LDAP_NO_MEMORY);
   2615              }
   2616 	} else if (!strcasecmp(saslarg, "mech")) {
   2617 	     if ( sasl_mech != NULL ) {
   2618                 fprintf( stderr, gettext("Mech previously specified\n"));
   2619                 return (-1);
   2620              }
   2621 	     if (( sasl_mech = strdup(attr)) == NULL) {
   2622 		perror ("malloc");
   2623 		exit (LDAP_NO_MEMORY);
   2624 	     }
   2625 	} else {
   2626 	     fprintf (stderr, gettext("Invalid attribute name %s\n"), saslarg);
   2627 	     return (-1);
   2628 	}
   2629 	return 0;
   2630 }
   2631 #endif	/* HAVE_SASL_OPTIONS */
   2632 
   2633 /*
   2634  * check for and report input or output error on named stream
   2635  * return ldap_err or ferror() (ldap_err takes precedence)
   2636  * assume that fflush() already has been called if needed.
   2637  * don't want to fflush() an input stream.
   2638  */
   2639 int
   2640 ldaptool_check_ferror(FILE * stream, const int ldap_err, const char *msg)
   2641 {
   2642 	int err = 0;
   2643 	if ((err = ferror(stream)) != 0 ) {
   2644 		fprintf(stderr, gettext("%s: ERROR: "), ldaptool_progname);
   2645 		perror(msg);
   2646 		err = LDAP_LOCAL_ERROR;
   2647 	}
   2648 
   2649 	/*
   2650 	 * reporting LDAP error code is more important than
   2651 	 * reporting errors from ferror()
   2652 	 */
   2653 	if (ldap_err == LDAP_SUCCESS) {
   2654 		return(err);
   2655 	} else {
   2656 		return(ldap_err);
   2657 	}
   2658 }
   2659