xref: /onnv-gate/usr/src/cmd/ldap/common/common.c (revision 8097:4d57974af082)
10Sstevel@tonic-gate /*
2*8097SSreedhar.Chalamalasetti@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
6702Sth160488 /*
70Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
80Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
90Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
100Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
130Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
140Sstevel@tonic-gate  * implied. See the License for the specific language governing
150Sstevel@tonic-gate  * rights and limitations under the License.
160Sstevel@tonic-gate  *
170Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
180Sstevel@tonic-gate  * March 31, 1998.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
210Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
220Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
230Sstevel@tonic-gate  * Rights Reserved.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * Contributor(s):
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * code that is shared by two or more of the LDAP command line tools
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include "ldaptool.h"
330Sstevel@tonic-gate #include "fileurl.h"
340Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
350Sstevel@tonic-gate #include "solaris-int.h"
360Sstevel@tonic-gate #include <ldap.h>
370Sstevel@tonic-gate #include <locale.h>
380Sstevel@tonic-gate #include <libgen.h>
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/stat.h>
410Sstevel@tonic-gate #include <limits.h>
420Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #ifdef LDAP_TOOL_ARGPIN
450Sstevel@tonic-gate #include "argpin.h"
460Sstevel@tonic-gate #include "ntuserpin.h"
470Sstevel@tonic-gate #endif /* LDAP_TOOL_ARGPIN */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
500Sstevel@tonic-gate #include <nspr.h> /* for PR_Cleanup() */
510Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
520Sstevel@tonic-gate #include <stdlib.h>
530Sstevel@tonic-gate #include <time.h>	/* for time() and ctime() */
540Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
550Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
560Sstevel@tonic-gate #include <sasl/sasl.h>
570Sstevel@tonic-gate #else
580Sstevel@tonic-gate #include <sasl.h>
590Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
600Sstevel@tonic-gate #include "ldaptool-sasl.h"
610Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
640Sstevel@tonic-gate #define gettext(s) s
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate 
670Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
680Sstevel@tonic-gate #define	PATH_BUF_SIZE	(PATH_MAX + 1)
690Sstevel@tonic-gate #endif
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static LDAP_REBINDPROC_CALLBACK get_rebind_credentials;
720Sstevel@tonic-gate static void print_library_info( const LDAPAPIInfo *aip, FILE *fp );
730Sstevel@tonic-gate static int wait4result( LDAP *ld, int msgid, struct berval **servercredp,
740Sstevel@tonic-gate 	char *msg );
750Sstevel@tonic-gate static int parse_result( LDAP *ld, LDAPMessage *res,
760Sstevel@tonic-gate 	struct berval **servercredp, char *msg, int freeit );
770Sstevel@tonic-gate 
780Sstevel@tonic-gate #ifdef LDAPTOOL_DEBUG_MEMORY
790Sstevel@tonic-gate static void *ldaptool_debug_malloc( size_t size );
800Sstevel@tonic-gate static void *ldaptool_debug_calloc( size_t nelem, size_t elsize );
810Sstevel@tonic-gate static void *ldaptool_debug_realloc( void *ptr, size_t size );
820Sstevel@tonic-gate static void ldaptool_debug_free( void *ptr );
830Sstevel@tonic-gate #endif /* LDAPTOOL_DEBUG_MEMORY */
840Sstevel@tonic-gate 
850Sstevel@tonic-gate #if defined(NET_SSL)
860Sstevel@tonic-gate static char *certpath2keypath( char *certdbpath );
870Sstevel@tonic-gate static int ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns);
880Sstevel@tonic-gate static char * buildTokenCertName( const char *tokenName, const char *certName);
890Sstevel@tonic-gate #ifdef FORTEZZA
900Sstevel@tonic-gate static int ldaptool_fortezza_init( int exit_on_error );
910Sstevel@tonic-gate static int ldaptool_fortezza_alert( void *arg, PRBool onOpen,
920Sstevel@tonic-gate 	char *string, int value1, void *value2 );
930Sstevel@tonic-gate static void * ldaptool_fortezza_getpin( char **passwordp );
940Sstevel@tonic-gate static char * ldaptool_fortezza_err2string( int err );
950Sstevel@tonic-gate #endif /* FORTEZZA */
960Sstevel@tonic-gate #endif
970Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
980Sstevel@tonic-gate static int saslSetParam(char *saslarg);
990Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * display usage for common options with one exception: -f is not included
1030Sstevel@tonic-gate  * since the description tends to be tool-specific.
1040Sstevel@tonic-gate  *
1050Sstevel@tonic-gate  * As of 1-Jul-1998, of the characters in the set [A-Za-z] the following are
1060Sstevel@tonic-gate  * not currently used by any of the tools: EJgjqr
1070Sstevel@tonic-gate  */
1080Sstevel@tonic-gate void
ldaptool_common_usage(int two_hosts)1090Sstevel@tonic-gate ldaptool_common_usage( int two_hosts )
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate     fprintf( stderr, gettext("    -n\t\tshow what would be done but don't actually do it\n") );
1120Sstevel@tonic-gate     fprintf( stderr, gettext("    -v\t\trun in verbose mode (diagnostics to standard output)\n") );
1130Sstevel@tonic-gate     if ( two_hosts ) {
1140Sstevel@tonic-gate 	fprintf( stderr, gettext("    -h host\tLDAP server1 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
1150Sstevel@tonic-gate 	fprintf( stderr, gettext("    -p port\tLDAP server1 TCP port number (default: %d)\n"), LDAP_PORT );
1160Sstevel@tonic-gate 	fprintf( stderr, gettext("    -h host\tLDAP server2 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
1170Sstevel@tonic-gate 	fprintf( stderr, gettext("    -p port\tLDAP server2 TCP port number (default: %d)\n"), LDAP_PORT );
1180Sstevel@tonic-gate     } else {
1190Sstevel@tonic-gate 	fprintf( stderr, gettext("    -h host\tLDAP server name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST );
1200Sstevel@tonic-gate 	fprintf( stderr, gettext("    -p port\tLDAP server TCP port number (default: %d)\n"), LDAP_PORT );
1210Sstevel@tonic-gate     }
1220Sstevel@tonic-gate     fprintf( stderr,
1230Sstevel@tonic-gate 	    gettext("    -V n\tLDAP protocol version number (%d or %d; default: %d)\n"),
1240Sstevel@tonic-gate 	    LDAP_VERSION2, LDAP_VERSION3, LDAP_VERSION3 );
1250Sstevel@tonic-gate #if defined(NET_SSL)
1260Sstevel@tonic-gate     fprintf( stderr, gettext("    -Z\t\tmake an SSL-encrypted connection\n") );
1270Sstevel@tonic-gate     fprintf( stderr, gettext("    -P pathname\tpath to SSL certificate database (default: current directory)\n") );
1280Sstevel@tonic-gate     fprintf( stderr, gettext("    -N\t\tname of certificate to use for SSL client authentication\n") );
1290Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
1300Sstevel@tonic-gate     fprintf( stderr, gettext("    -K pathname\tpath to key database to use for SSL client authentication\n") );
1310Sstevel@tonic-gate     fprintf( stderr, gettext("    \t\t(default: path to certificate database provided with -P option)\n") );
1320Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1330Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
1340Sstevel@tonic-gate     fprintf( stderr, gettext("    -m pathname\tpath to security module database\n"));
1350Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
1360Sstevel@tonic-gate     fprintf( stderr, gettext("    -W\t\tSSL key password\n") );
1370Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
1380Sstevel@tonic-gate     fprintf( stderr, gettext("    -3\t\tcheck hostnames in SSL certificates\n") );
139702Sth160488 #endif	/* SOLARIS_LDAP_CMD */
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
1420Sstevel@tonic-gate     fprintf( stderr, gettext("    -Q [token][:certificate name]\tPKCS 11\n") );
1430Sstevel@tonic-gate     /*    fprintf( stderr, "    -X pathname\tFORTEZZA compromised key list (CKL)\n" ); */
1440Sstevel@tonic-gate     fprintf( stderr, gettext("    -I pin\tcard password file\n") );
1450Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate #endif /* NET_SSL */
1480Sstevel@tonic-gate     fprintf( stderr, gettext("    -D binddn\tbind dn\n") );
1490Sstevel@tonic-gate     fprintf( stderr, gettext("    -w passwd\tbind passwd (for simple authentication)\n") );
1500Sstevel@tonic-gate     fprintf( stderr, gettext("    -w - \tprompt for bind passwd (for simple authentication)\n") );
1510Sstevel@tonic-gate     fprintf( stderr, gettext("    -j file\tread bind passwd (for simple authentication)\n") );
1520Sstevel@tonic-gate     fprintf( stderr, gettext("      \t\tor SSL key password from 'file'\n") );
1530Sstevel@tonic-gate     fprintf( stderr, gettext("    -E\t\task server to expose (report) bind identity\n") );
1540Sstevel@tonic-gate #ifdef LDAP_DEBUG
1550Sstevel@tonic-gate     fprintf( stderr, gettext("    -d level\tset LDAP debugging level to `level'\n") );
1560Sstevel@tonic-gate #endif
1570Sstevel@tonic-gate     fprintf( stderr, gettext("    -R\t\tdo not automatically follow referrals\n") );
1580Sstevel@tonic-gate     fprintf( stderr, gettext("    -O limit\tmaximum number of referral hops to traverse (default: %d)\n"), LDAPTOOL_DEFREFHOPLIMIT );
1590Sstevel@tonic-gate     fprintf( stderr, gettext("    -M\t\tmanage references (treat them as regular entries)\n") );
1600Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
1610Sstevel@tonic-gate     fprintf( stderr, gettext("    -0\t\tignore LDAP library version mismatches\n") );
1620Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate #ifndef NO_LIBLCACHE
1650Sstevel@tonic-gate     fprintf( stderr, gettext("    -C cfgfile\tuse local database described by cfgfile\n") );
1660Sstevel@tonic-gate #endif
1670Sstevel@tonic-gate     fprintf( stderr, gettext("    -i charset\tcharacter set for command line input (default taken from locale)\n") );
1680Sstevel@tonic-gate     fprintf( stderr, gettext("    -k dir\tconversion routine directory (default: current directory)\n") );
1690Sstevel@tonic-gate #if 0
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate  * Suppress usage for -y (old proxied authorization control) even though
1720Sstevel@tonic-gate  * we still support it.  We want to encourage people to use -Y instead (the
1730Sstevel@tonic-gate  * new proxied authorization control).
1740Sstevel@tonic-gate  */
1750Sstevel@tonic-gate     fprintf( stderr, gettext("    -y proxydn\tDN used for proxy authorization\n") );
1760Sstevel@tonic-gate #endif
1770Sstevel@tonic-gate     fprintf( stderr, gettext("    -Y proxyid\tproxied authorization id,\n") );
1780Sstevel@tonic-gate     fprintf( stderr, gettext("              \te.g, dn:uid=bjensen,dc=example,dc=com\n") );
1790Sstevel@tonic-gate     fprintf( stderr, gettext("    -H\t\tdisplay usage information\n") );
1800Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1810Sstevel@tonic-gate     fprintf( stderr, gettext("    -?\t\tdisplay usage information\n") );
1820Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
1830Sstevel@tonic-gate     fprintf( stderr, gettext("    -J controloid[:criticality[:value|::b64value|:<fileurl]]\n") );
1840Sstevel@tonic-gate     fprintf( stderr, gettext("\t\tcriticality is a boolean value (default is false)\n") );
1850Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
1860Sstevel@tonic-gate     fprintf( stderr, gettext("    -o attrName=attrVal\tSASL options which are described in the man page\n"));
1870Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate /* globals */
1910Sstevel@tonic-gate char			*ldaptool_charset = "";
1920Sstevel@tonic-gate char			*ldaptool_host = LDAPTOOL_DEFHOST;
1930Sstevel@tonic-gate char			*ldaptool_host2 = LDAPTOOL_DEFHOST;
1940Sstevel@tonic-gate int			ldaptool_port = LDAP_PORT;
1950Sstevel@tonic-gate int			ldaptool_port2 = LDAP_PORT;
1960Sstevel@tonic-gate int			ldaptool_verbose = 0;
1970Sstevel@tonic-gate int			ldaptool_not = 0;
1980Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
1990Sstevel@tonic-gate int			ldaptool_require_binddn = 1;
2000Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
2010Sstevel@tonic-gate FILE			*ldaptool_fp = NULL;
2020Sstevel@tonic-gate FILE			*password_fp = NULL;
2030Sstevel@tonic-gate char			*ldaptool_progname = "";
2040Sstevel@tonic-gate char			*ldaptool_nls_lang = NULL;
2050Sstevel@tonic-gate char                    *proxyauth_id = NULL;
2060Sstevel@tonic-gate int			proxyauth_version = 2;	/* use newer proxy control */
2070Sstevel@tonic-gate LDAPControl		*ldaptool_request_ctrls[CONTROL_REQUESTS] = {0};
2080Sstevel@tonic-gate #ifdef LDAP_DEBUG
2090Sstevel@tonic-gate int			ldaptool_dbg_lvl = 0;
2100Sstevel@tonic-gate #endif /* LDAP_DEBUG */
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate /* statics */
2130Sstevel@tonic-gate static char		*binddn = NULL;
2140Sstevel@tonic-gate static char		*passwd = NULL;
2150Sstevel@tonic-gate static int		send_auth_response_ctrl = 0;
2160Sstevel@tonic-gate static int		user_specified_port = 0;
2170Sstevel@tonic-gate static int		user_specified_port2 = 0;
2180Sstevel@tonic-gate static int		chase_referrals = 1;
2190Sstevel@tonic-gate static int		lib_version_mismatch_is_fatal = 1;
2200Sstevel@tonic-gate static int		ldversion = -1;	/* use default */
2210Sstevel@tonic-gate static int		refhoplim = LDAPTOOL_DEFREFHOPLIMIT;
2220Sstevel@tonic-gate static int		send_manage_dsait_ctrl = 0;
2230Sstevel@tonic-gate static int		prompt_password = 0;
2240Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
2250Sstevel@tonic-gate static unsigned		sasl_flags = LDAP_SASL_INTERACTIVE;
2260Sstevel@tonic-gate static char		*sasl_mech = NULL;
2270Sstevel@tonic-gate static char		*sasl_authid = NULL;
2280Sstevel@tonic-gate static char		*sasl_mode = NULL;
2290Sstevel@tonic-gate static char		*sasl_realm = NULL;
2300Sstevel@tonic-gate static char		*sasl_username = NULL;
2310Sstevel@tonic-gate static char		*sasl_secprops = NULL;
2320Sstevel@tonic-gate static int		ldapauth = -1;
2330Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate #ifndef NO_LIBLCACHE
2360Sstevel@tonic-gate static char		*cache_config_file = NULL;
2370Sstevel@tonic-gate #endif /* !NO_LIBLCACHE */
2380Sstevel@tonic-gate #if defined(NET_SSL)
2390Sstevel@tonic-gate static int		secure = 0;
2400Sstevel@tonic-gate static int		isZ = 0;
2410Sstevel@tonic-gate static int		isN = 0;
2420Sstevel@tonic-gate static int		isW = 0;
2430Sstevel@tonic-gate static int		isw = 0;
2440Sstevel@tonic-gate static int		isD = 0;
2450Sstevel@tonic-gate static int		isj = 0;
2460Sstevel@tonic-gate static int		ssl_strength = LDAPTOOL_DEFSSLSTRENGTH;
2470Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
2480Sstevel@tonic-gate static char		pathname[PATH_BUF_SIZE];
2490Sstevel@tonic-gate #endif
2500Sstevel@tonic-gate static char		*ssl_certdbpath = NULL;
2510Sstevel@tonic-gate static char		*ssl_keydbpath = NULL;
2520Sstevel@tonic-gate static char		*ssl_keyname = NULL;
2530Sstevel@tonic-gate static char		*ssl_certname = NULL;
2540Sstevel@tonic-gate static char		*ssl_passwd = NULL;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
2570Sstevel@tonic-gate static char     	*ssl_secmodpath = NULL;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate static char             *pkcs_token = NULL;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate static char             *ssl_donglefile = NULL;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate #if 0
2640Sstevel@tonic-gate static char             *pkcs_pin = NULL;
2650Sstevel@tonic-gate #endif
2660Sstevel@tonic-gate static struct ldapssl_pkcs_fns local_pkcs_fns =
2670Sstevel@tonic-gate     {0,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL };
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate #ifdef FORTEZZA
2700Sstevel@tonic-gate static uint32		fortezza_cardmask = 0;
2710Sstevel@tonic-gate static char		*fortezza_personality = NULL;
2720Sstevel@tonic-gate static char		*fortezza_krlfile = NULL;
2730Sstevel@tonic-gate static char		*fortezza_pin = NULL;
2740Sstevel@tonic-gate #endif /* FORTEZZA */
2750Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
2760Sstevel@tonic-gate #endif /* NET_SSL */
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate  * Handle general initialization and options that are common to all of
2800Sstevel@tonic-gate  * the LDAP tools.
2810Sstevel@tonic-gate  * Handle options that are common to all of the LDAP tools.
2820Sstevel@tonic-gate  * Note the the H option is included here but handled via the
2830Sstevel@tonic-gate  * extra_opt_callback function (along with any "extra_opts" ).
2840Sstevel@tonic-gate  *
2850Sstevel@tonic-gate  * Return: final value for optind or -1 if usage should be displayed (for
2860Sstevel@tonic-gate  * some fatal errors, we call exit here).
2870Sstevel@tonic-gate  */
2880Sstevel@tonic-gate int
ldaptool_process_args(int argc,char ** argv,char * extra_opts,int two_hosts,void (* extra_opt_callback)(int option,char * optarg))2890Sstevel@tonic-gate ldaptool_process_args( int argc, char **argv, char *extra_opts,
2900Sstevel@tonic-gate 	int two_hosts, void (*extra_opt_callback)( int option, char *optarg ))
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate     int		rc, i, hostnum;
2930Sstevel@tonic-gate     char	*optstring, *common_opts;
2940Sstevel@tonic-gate     extern char	*optarg;
2950Sstevel@tonic-gate     extern int	optind;
2960Sstevel@tonic-gate     LDAPAPIInfo	ldai;
2970Sstevel@tonic-gate     char *ctrl_arg, *ctrl_oid=NULL, *ctrl_value=NULL;
2980Sstevel@tonic-gate     int ctrl_criticality=0, vlen;
2990Sstevel@tonic-gate     LDAPControl *ldctrl;
3000Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
3010Sstevel@tonic-gate 	struct stat st;
3020Sstevel@tonic-gate #endif
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate     /*
3060Sstevel@tonic-gate      * Set program name global based on argv[0].
3070Sstevel@tonic-gate      */
3080Sstevel@tonic-gate     if (( ldaptool_progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
3090Sstevel@tonic-gate         ldaptool_progname = argv[ 0 ];
3100Sstevel@tonic-gate     } else {
3110Sstevel@tonic-gate         ++ldaptool_progname;
3120Sstevel@tonic-gate     }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate #ifdef LDAPTOOL_DEBUG_MEMORY
3150Sstevel@tonic-gate     {
3160Sstevel@tonic-gate 	struct ldap_memalloc_fns mafns = {
3170Sstevel@tonic-gate 		ldaptool_debug_malloc,
3180Sstevel@tonic-gate 		ldaptool_debug_calloc,
3190Sstevel@tonic-gate 		ldaptool_debug_realloc,
3200Sstevel@tonic-gate 		ldaptool_debug_free
3210Sstevel@tonic-gate 	};
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &mafns );
3240Sstevel@tonic-gate     }
3250Sstevel@tonic-gate #endif	/* LDAPTOOL_DEBUG_MEMORY */
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate #ifdef LDAP_DEBUG
3280Sstevel@tonic-gate     i = LDAP_DEBUG_ANY;
3290Sstevel@tonic-gate     ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, (void *) &i);
3300Sstevel@tonic-gate #endif
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate     /*
3330Sstevel@tonic-gate      * Perform a sanity check on the revision of the LDAP API library to
3340Sstevel@tonic-gate      * make sure it is at least as new as the one we were compiled against.
3350Sstevel@tonic-gate      * If the API implementation is from the same vendor as we were compiled
3360Sstevel@tonic-gate      * against, we also check to make sure the vendor version is at least
3370Sstevel@tonic-gate      * as new as the library we were compiled against.
3380Sstevel@tonic-gate      *
3390Sstevel@tonic-gate      * Version differences are fatal unless the -0 option is passed on the
3400Sstevel@tonic-gate      * tool command line (that's a zero, not an oh).  We check for the
3410Sstevel@tonic-gate      * presence of -0 in a crude way to it must appear by itself in argv.
3420Sstevel@tonic-gate      */
3430Sstevel@tonic-gate     for ( i = 1; i < argc; ++i ) {
3440Sstevel@tonic-gate 	if ( strcmp( argv[i], "-0" ) == 0 ) {
3450Sstevel@tonic-gate 	    lib_version_mismatch_is_fatal = 0;
3460Sstevel@tonic-gate 	    break;
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate     }
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate     memset( &ldai, 0, sizeof(ldai));
3510Sstevel@tonic-gate     ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
3520Sstevel@tonic-gate     if (( rc = ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldai )) != 0 ) {
3530Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: unable to retrieve LDAP library version"
3540Sstevel@tonic-gate 		" information;\n\tthis program requires an LDAP library that"
3550Sstevel@tonic-gate 		" implements revision\n\t%d or greater of the LDAP API.\n"),
3560Sstevel@tonic-gate 		ldaptool_progname, LDAP_API_VERSION );
3570Sstevel@tonic-gate 	if ( lib_version_mismatch_is_fatal ) {
3580Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate     } else if ( ldai.ldapai_api_version < LDAP_API_VERSION ) {
3610Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: this program requires an LDAP library that"
3620Sstevel@tonic-gate 		" implements revision\n\t%d or greater of the LDAP API;"
3630Sstevel@tonic-gate 		" running with revision %d.\n"),
3640Sstevel@tonic-gate 		ldaptool_progname, LDAP_API_VERSION, ldai.ldapai_api_version );
3650Sstevel@tonic-gate 	if ( lib_version_mismatch_is_fatal ) {
3660Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate     } else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0) {
3690Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: this program requires %s's LDAP\n"
3700Sstevel@tonic-gate 		"\tlibrary version %2.2f or greater; running with\n"
3710Sstevel@tonic-gate 		"\t%s's version %2.2f.\n"),
3720Sstevel@tonic-gate 		ldaptool_progname, LDAP_VENDOR_NAME,
3730Sstevel@tonic-gate 		(float)LDAP_VENDOR_VERSION / 100,
3740Sstevel@tonic-gate 		ldai.ldapai_vendor_name,
3750Sstevel@tonic-gate 		(float)ldai.ldapai_vendor_version / 100 );
3760Sstevel@tonic-gate 	if ( lib_version_mismatch_is_fatal ) {
3770Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate     } else if (ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
3800Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: this program requires %s's LDAP\n"
3810Sstevel@tonic-gate 		"\tlibrary version %2.2f or greater; running with"
3820Sstevel@tonic-gate 		" version %2.2f.\n"),
3830Sstevel@tonic-gate 		ldaptool_progname, LDAP_VENDOR_NAME,
3840Sstevel@tonic-gate 		(float)LDAP_VENDOR_VERSION / 100,
3850Sstevel@tonic-gate 		(float)ldai.ldapai_vendor_version / 100 );
3860Sstevel@tonic-gate 	if ( lib_version_mismatch_is_fatal ) {
3870Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate     }
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate     /*
3920Sstevel@tonic-gate      * Process command line options.
3930Sstevel@tonic-gate      */
3940Sstevel@tonic-gate     if ( extra_opts == NULL ) {
3950Sstevel@tonic-gate 	extra_opts = "";
3960Sstevel@tonic-gate     }
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
3990Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4000Sstevel@tonic-gate     common_opts = "nvEMRH?Zd:D:f:h:j:N:O:o:P:p:W:w:V:i:k:y:Y:J:";
4010Sstevel@tonic-gate #else
4020Sstevel@tonic-gate     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:";
4030Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
4040Sstevel@tonic-gate #else
4050Sstevel@tonic-gate     common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
4060Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate     /* note: optstring must include room for liblcache "C:" option */
4090Sstevel@tonic-gate     if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts )
4100Sstevel@tonic-gate 	    + 3 )) == NULL ) {
4110Sstevel@tonic-gate 	perror( "malloc" );
4120Sstevel@tonic-gate 	exit( LDAP_NO_MEMORY );
4130Sstevel@tonic-gate     }
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate #ifdef NO_LIBLCACHE
4160Sstevel@tonic-gate     sprintf( optstring, "%s%s", common_opts, extra_opts );
4170Sstevel@tonic-gate #else
4180Sstevel@tonic-gate     sprintf( optstring, "%s%sC:", common_opts, extra_opts );
4190Sstevel@tonic-gate #endif
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate     hostnum = 0;
4220Sstevel@tonic-gate     while ( (i = getopt( argc, argv, optstring )) != EOF ) {
4230Sstevel@tonic-gate 	switch( i ) {
4240Sstevel@tonic-gate 	case 'n':	/* do Not do any LDAP operations */
4250Sstevel@tonic-gate 	    ++ldaptool_not;
4260Sstevel@tonic-gate 	    break;
4270Sstevel@tonic-gate 	case 'v':	/* verbose mode */
4280Sstevel@tonic-gate 	    ++ldaptool_verbose;
4290Sstevel@tonic-gate 	    break;
4300Sstevel@tonic-gate 	case 'd':
4310Sstevel@tonic-gate #ifdef LDAP_DEBUG
4320Sstevel@tonic-gate 	    ldaptool_dbg_lvl = atoi( optarg );	/* */
4330Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
4340Sstevel@tonic-gate 	    ldap_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
4350Sstevel@tonic-gate 		    (void *)&ldaptool_dbg_lvl);
4360Sstevel@tonic-gate #else
4370Sstevel@tonic-gate 	    ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
4380Sstevel@tonic-gate 		    (void *)&ldaptool_dbg_lvl);
4390Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
4400Sstevel@tonic-gate 	    ldaptool_dbg_lvl |= LDAP_DEBUG_ANY;
4410Sstevel@tonic-gate 	    ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL,
4420Sstevel@tonic-gate 		    (void *)&ldaptool_dbg_lvl);
4430Sstevel@tonic-gate #else /* LDAP_DEBUG */
4440Sstevel@tonic-gate 	    fprintf( stderr, gettext("compile with -DLDAP_DEBUG for debugging\n") );
4450Sstevel@tonic-gate #endif /* LDAP_DEBUG */
4460Sstevel@tonic-gate 	    break;
4470Sstevel@tonic-gate 	case 'R':	/* don't automatically chase referrals */
4480Sstevel@tonic-gate 	    chase_referrals = 0;
4490Sstevel@tonic-gate 	    break;
4500Sstevel@tonic-gate #ifndef NO_LIBLCACHE
4510Sstevel@tonic-gate 	case 'C':	/* search local database */
4520Sstevel@tonic-gate 	    cache_config_file = strdup( optarg );
4530Sstevel@tonic-gate 	    break;
4540Sstevel@tonic-gate #endif
4550Sstevel@tonic-gate 	case 'f':	/* input file */
4560Sstevel@tonic-gate 	    if ( optarg[0] == '-' && optarg[1] == '\0' ) {
4570Sstevel@tonic-gate 		ldaptool_fp = stdin;
4580Sstevel@tonic-gate 	    } else if (( ldaptool_fp = ldaptool_open_file( optarg, "r" )) == NULL ) {
4590Sstevel@tonic-gate 		perror( optarg );
4600Sstevel@tonic-gate 		exit( LDAP_PARAM_ERROR );
4610Sstevel@tonic-gate 	    }
4620Sstevel@tonic-gate 	    break;
4630Sstevel@tonic-gate 	case 'h':	/* ldap host */
4640Sstevel@tonic-gate 	    if ( hostnum == 0 ) {
4650Sstevel@tonic-gate 		ldaptool_host = strdup( optarg );
4660Sstevel@tonic-gate 	    } else {
4670Sstevel@tonic-gate 		ldaptool_host2 = strdup( optarg );
4680Sstevel@tonic-gate 	    }
4690Sstevel@tonic-gate 	    ++hostnum;
4700Sstevel@tonic-gate 	    break;
4710Sstevel@tonic-gate 	case 'D':	/* bind DN */
4720Sstevel@tonic-gate 	    isD = 1;
4730Sstevel@tonic-gate 	    binddn = strdup( optarg );
4740Sstevel@tonic-gate 	    break;
4750Sstevel@tonic-gate 	case 'E':	/* expose bind identity via auth. response control */
4760Sstevel@tonic-gate 	    ++send_auth_response_ctrl;
4770Sstevel@tonic-gate 	    break;
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	case 'p':	/* ldap port */
4800Sstevel@tonic-gate 	    if ( !user_specified_port ) {
4810Sstevel@tonic-gate 		++user_specified_port;
4820Sstevel@tonic-gate 		ldaptool_port = atoi( optarg );
4830Sstevel@tonic-gate 	    } else {
4840Sstevel@tonic-gate 		++user_specified_port2;
4850Sstevel@tonic-gate 		ldaptool_port2 = atoi( optarg );
4860Sstevel@tonic-gate 	    }
4870Sstevel@tonic-gate 	    break;
4880Sstevel@tonic-gate #if defined(NET_SSL)
4890Sstevel@tonic-gate 	case 'P':	/* path to security database */
4900Sstevel@tonic-gate 	    secure = 1; /* do SSL encryption */
4910Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
4920Sstevel@tonic-gate 	    ssl_certdbpath = strdup(optarg);
4930Sstevel@tonic-gate 	    if (NULL == ssl_certdbpath) {
4940Sstevel@tonic-gate 		perror("malloc");
4950Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
4960Sstevel@tonic-gate 	    }
4970Sstevel@tonic-gate #else
4980Sstevel@tonic-gate 		/*
4990Sstevel@tonic-gate 		 * Verify whether it's a base directory or a cert db file.
5000Sstevel@tonic-gate 		 * If it is not a directory, truncate the file name as
5010Sstevel@tonic-gate 		 * the revised NSS_Init() doesn't take file name any longer.
5020Sstevel@tonic-gate 		 */
5030Sstevel@tonic-gate 		if (strlcpy(pathname, optarg, PATH_BUF_SIZE) >= PATH_BUF_SIZE) {
5040Sstevel@tonic-gate 			fprintf(stderr, gettext("\"-P\": Path name is too "
5050Sstevel@tonic-gate 				"long\n"));
5060Sstevel@tonic-gate 			exit(LDAP_PARAM_ERROR);
5070Sstevel@tonic-gate 		}
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		if (stat(pathname, &st) != 0) {
5100Sstevel@tonic-gate 			perror("stat");
5110Sstevel@tonic-gate 			fprintf(stderr, gettext("\"-P\": Path name is "
5120Sstevel@tonic-gate 				"invalid\n"));
5130Sstevel@tonic-gate 			exit(LDAP_PARAM_ERROR);
5140Sstevel@tonic-gate 		} else {
5150Sstevel@tonic-gate 			if (S_ISREG(st.st_mode)) {
5160Sstevel@tonic-gate 				/* redir to a regular file's dir name */
5170Sstevel@tonic-gate 				ssl_certdbpath = dirname(pathname);
5180Sstevel@tonic-gate 			} else
5190Sstevel@tonic-gate 				ssl_certdbpath = pathname;
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
5220Sstevel@tonic-gate 	    break;
5230Sstevel@tonic-gate 	case 'Z':	/* do SSL encryption */
5240Sstevel@tonic-gate 	    secure = 1;
5250Sstevel@tonic-gate 	    isZ = 1;
5260Sstevel@tonic-gate 	    break;
5270Sstevel@tonic-gate 	case 'N':	/* nickname of cert. to use for client auth. */
5280Sstevel@tonic-gate 	    ssl_certname = strdup( optarg );
5290Sstevel@tonic-gate 	    if (NULL == ssl_certname)
5300Sstevel@tonic-gate 	    {
5310Sstevel@tonic-gate 		perror("malloc");
5320Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
5330Sstevel@tonic-gate 	    }
5340Sstevel@tonic-gate 	    isN = 1;
5350Sstevel@tonic-gate 	    break;
5360Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
5370Sstevel@tonic-gate 	case 'K':	/* location of key database */
5380Sstevel@tonic-gate 	    ssl_keydbpath = strdup( optarg );
5390Sstevel@tonic-gate 	    if (NULL == ssl_keydbpath)
5400Sstevel@tonic-gate 	    {
5410Sstevel@tonic-gate 		perror("malloc");
5420Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
5430Sstevel@tonic-gate 	    }
5440Sstevel@tonic-gate 	    break;
5450Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	case 'W':	/* SSL key password */
5480Sstevel@tonic-gate 	    ssl_passwd = strdup( optarg );
5490Sstevel@tonic-gate 	    if (NULL == ssl_passwd)
5500Sstevel@tonic-gate 	    {
5510Sstevel@tonic-gate 		perror("malloc");
5520Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
5530Sstevel@tonic-gate 	    }
5540Sstevel@tonic-gate 	    isW = 1;
5550Sstevel@tonic-gate 	    break;
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
5580Sstevel@tonic-gate 	case '3': /* check hostnames in SSL certificates ("no third") */
5590Sstevel@tonic-gate 	    ssl_strength = LDAPSSL_AUTH_CNCHECK;
5600Sstevel@tonic-gate 	    break;
5610Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
5640Sstevel@tonic-gate 	case 'm':	/* SSL secmod path */
5650Sstevel@tonic-gate 	    ssl_secmodpath = strdup( optarg);
5660Sstevel@tonic-gate 	    if (NULL == ssl_secmodpath)
5670Sstevel@tonic-gate 	    {
5680Sstevel@tonic-gate 		perror("malloc");
5690Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
5700Sstevel@tonic-gate 	    }
5710Sstevel@tonic-gate 	    break;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	case 'Q': 	/* FORTEZZA [card][:personality] */
5740Sstevel@tonic-gate 	    pkcs_token = strdup(optarg);
5750Sstevel@tonic-gate 	    if (NULL == pkcs_token)
5760Sstevel@tonic-gate 	    {
5770Sstevel@tonic-gate 		perror("malloc");
5780Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
5790Sstevel@tonic-gate 	    }
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	    break;
5820Sstevel@tonic-gate 	    /* This option removed to prevent interference
5830Sstevel@tonic-gate 	       with the getEffectiveRights option, also -X
5840Sstevel@tonic-gate 	       case 'X':	* path to FORTEZZA CKL file *
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	       fortezza_krlfile = strdup( optarg );
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	       break;
5900Sstevel@tonic-gate 	    */
5910Sstevel@tonic-gate 	case 'I':	/* FORTEZZA PIN (password file) */
5920Sstevel@tonic-gate 	    ssl_donglefile = strdup( optarg );
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	    break;
5950Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate #endif /* NET_SSL */
5980Sstevel@tonic-gate 	case 'w':	/* bind password */
5990Sstevel@tonic-gate 	    isw = 1;
6000Sstevel@tonic-gate 	    if ( optarg[0] == '-' && optarg[1] == '\0' )
6010Sstevel@tonic-gate 		prompt_password = 1;
6020Sstevel@tonic-gate 	    else
6030Sstevel@tonic-gate 		passwd = strdup( optarg );
6040Sstevel@tonic-gate 	    break;
6050Sstevel@tonic-gate 	    case 'j':       /* bind password or SSL key password from file */
6060Sstevel@tonic-gate 	    isj = 1;
6070Sstevel@tonic-gate 	    if ((password_fp = fopen( optarg, "r" )) == NULL ) {
6080Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: Unable to open '%s' file\n"),
6090Sstevel@tonic-gate 			ldaptool_progname, optarg);
6100Sstevel@tonic-gate 		exit( LDAP_PARAM_ERROR );
6110Sstevel@tonic-gate 	    }
6120Sstevel@tonic-gate             break;
6130Sstevel@tonic-gate 	case 'O':	/* referral hop limit */
6140Sstevel@tonic-gate 	    refhoplim = atoi( optarg );
6150Sstevel@tonic-gate 	    break;
6160Sstevel@tonic-gate 	case 'V':	/* protocol version */
6170Sstevel@tonic-gate 	    ldversion = atoi (optarg);
6180Sstevel@tonic-gate 	    if ( ldversion != LDAP_VERSION2 && ldversion != LDAP_VERSION3 ) {
6190Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: LDAP protocol version %d is not "
6200Sstevel@tonic-gate 			"supported (use -V%d or -V%d)\n"),
6210Sstevel@tonic-gate 			ldaptool_progname, ldversion, LDAP_VERSION2,
6220Sstevel@tonic-gate 			LDAP_VERSION3 );
6230Sstevel@tonic-gate 		exit( LDAP_PARAM_ERROR );
6240Sstevel@tonic-gate 	    }
6250Sstevel@tonic-gate 	    break;
6260Sstevel@tonic-gate 	case 'M':	/* send a manageDsaIT control */
6270Sstevel@tonic-gate 	    send_manage_dsait_ctrl = 1;
6280Sstevel@tonic-gate 	    break;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	case 'i':   /* character set specified */
6310Sstevel@tonic-gate 	    ldaptool_charset = strdup( optarg );
6320Sstevel@tonic-gate 	    if (NULL == ldaptool_charset)
6330Sstevel@tonic-gate 	    {
6340Sstevel@tonic-gate 		perror( "malloc" );
6350Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
6360Sstevel@tonic-gate 	    }
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	    break;
6390Sstevel@tonic-gate 	case 'k':   /* conversion directory */
6400Sstevel@tonic-gate 	    ldaptool_convdir = strdup( optarg );
6410Sstevel@tonic-gate 	    if (NULL == ldaptool_convdir)
6420Sstevel@tonic-gate 	    {
6430Sstevel@tonic-gate 		perror( "malloc" );
6440Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
6450Sstevel@tonic-gate 	    }
6460Sstevel@tonic-gate 	    break;
6470Sstevel@tonic-gate 	case 'y':   /* old (version 1) proxied authorization control */
6480Sstevel@tonic-gate 		proxyauth_version = 1;
6490Sstevel@tonic-gate 	case 'Y':   /* new (version 2 ) proxied authorization control */
6500Sstevel@tonic-gate 		/*FALLTHRU*/
6510Sstevel@tonic-gate 	    proxyauth_id = strdup(optarg);
6520Sstevel@tonic-gate 	    if (NULL == proxyauth_id)
6530Sstevel@tonic-gate 	    {
6540Sstevel@tonic-gate 		perror( "malloc" );
6550Sstevel@tonic-gate 		exit( LDAP_NO_MEMORY );
6560Sstevel@tonic-gate 	    }
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	    break;
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
6610Sstevel@tonic-gate  	case '0':	/* zero -- override LDAP library version check */
6620Sstevel@tonic-gate 	    break;	/* already handled above */
6630Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
6640Sstevel@tonic-gate 	case 'J':	 /* send an arbitrary control */
6650Sstevel@tonic-gate 	    if ( (ctrl_arg = strdup( optarg)) == NULL ) {
6660Sstevel@tonic-gate 		perror ("strdup");
6670Sstevel@tonic-gate 		exit (LDAP_NO_MEMORY);
6680Sstevel@tonic-gate 	    }
6690Sstevel@tonic-gate 	    if (ldaptool_parse_ctrl_arg(ctrl_arg, ':', &ctrl_oid,
6700Sstevel@tonic-gate 		    &ctrl_criticality, &ctrl_value, &vlen)) {
6710Sstevel@tonic-gate 		return (-1);
6720Sstevel@tonic-gate 	    }
6730Sstevel@tonic-gate 	    ldctrl = calloc(1,sizeof(LDAPControl));
6740Sstevel@tonic-gate 	    if (ctrl_value) {
6750Sstevel@tonic-gate 		rc = ldaptool_berval_from_ldif_value( ctrl_value,
6760Sstevel@tonic-gate 			vlen, &(ldctrl->ldctl_value),
6770Sstevel@tonic-gate 			1 /* recognize file URLs */,
6780Sstevel@tonic-gate 			0 /* always try file */,
6790Sstevel@tonic-gate 			1 /* report errors */ );
6800Sstevel@tonic-gate 		if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
6810Sstevel@tonic-gate 		    fprintf( stderr, gettext("Unable to parse %s\n"), ctrl_value);
6820Sstevel@tonic-gate 		    return (-1);
6830Sstevel@tonic-gate 		}
6840Sstevel@tonic-gate 	    }
6850Sstevel@tonic-gate 	    ldctrl->ldctl_oid = ctrl_oid;
6860Sstevel@tonic-gate 	    ldctrl->ldctl_iscritical = ctrl_criticality;
6870Sstevel@tonic-gate 	    ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
6880Sstevel@tonic-gate 	    break;
6890Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
6900Sstevel@tonic-gate 	case 'o':	/* attribute assignment */
6910Sstevel@tonic-gate 	      if ((rc = saslSetParam(optarg)) == -1) {
6920Sstevel@tonic-gate 	      	  return (-1);
6930Sstevel@tonic-gate 	      }
6940Sstevel@tonic-gate 	      ldapauth = LDAP_AUTH_SASL;
6950Sstevel@tonic-gate 	      ldversion = LDAP_VERSION3;
6960Sstevel@tonic-gate 	      break;
6970Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
6980Sstevel@tonic-gate 	default:
6990Sstevel@tonic-gate 	    (*extra_opt_callback)( i, optarg );
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate     }
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate     /* If '-Z' is specified, check if '-P' is specified too. */
7050Sstevel@tonic-gate     if ( isN || isW ) {
7060Sstevel@tonic-gate 	if ( !isZ ) {
7070Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: with -N, -W options, please specify -Z\n\n"), ldaptool_progname );
7080Sstevel@tonic-gate 		return (-1);
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate     }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate     /* if '-N' is specified, -W is needed too */
7130Sstevel@tonic-gate     if ( isN && NULL == ssl_passwd ) {
7140Sstevel@tonic-gate         fprintf( stderr, gettext("%s: with the -N option, please specify -W also\n\n"),
7150Sstevel@tonic-gate 		ldaptool_progname );
7160Sstevel@tonic-gate         return (-1);
7170Sstevel@tonic-gate     }
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
7200Sstevel@tonic-gate     if ( isj && ( isw || isW )) {
7210Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: -j and -w or -W options cannot be specified simultaneously\n\n"), ldaptool_progname );
7220Sstevel@tonic-gate #else
7230Sstevel@tonic-gate     if ( isj && isw ) {
7240Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: -j and -w options cannot be specified simultaneously\n\n"), ldaptool_progname );
7250Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
7260Sstevel@tonic-gate 	return (-1);
7270Sstevel@tonic-gate     }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate     /* complain if -j or -w does not also have -D, unless using SASL */
7300Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
7310Sstevel@tonic-gate     if ( (isj || isw) && !isD && (  ldapauth != LDAP_AUTH_SASL ) ) {
7320Sstevel@tonic-gate #else
7330Sstevel@tonic-gate     if ( (isj || isw) && !isD ) {
7340Sstevel@tonic-gate #endif
7350Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: with -j, -w options, please specify -D\n\n"), ldaptool_progname );
7360Sstevel@tonic-gate 	return (-1);
7370Sstevel@tonic-gate     }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate     /* use default key and cert DB paths if not set on the command line */
7400Sstevel@tonic-gate     if ( NULL == ssl_keydbpath ) {
7410Sstevel@tonic-gate         if ( NULL == ssl_certdbpath ) {
7420Sstevel@tonic-gate             ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH;
7430Sstevel@tonic-gate         } else {
7440Sstevel@tonic-gate             ssl_keydbpath = certpath2keypath( ssl_certdbpath );
7450Sstevel@tonic-gate         }
7460Sstevel@tonic-gate     }
7470Sstevel@tonic-gate     if ( NULL == ssl_certdbpath ) {
7480Sstevel@tonic-gate         ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH;
7490Sstevel@tonic-gate     }
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate     if (prompt_password != 0) {
7520Sstevel@tonic-gate 	char *password_string = "Enter bind password: ";
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate #if defined(_WIN32)
7550Sstevel@tonic-gate 	char pbuf[257];
7560Sstevel@tonic-gate 	fputs(password_string,stdout);
7570Sstevel@tonic-gate 	fflush(stdout);
7580Sstevel@tonic-gate 	if (fgets(pbuf,256,stdin) == NULL) {
7590Sstevel@tonic-gate 	    passwd = NULL;
7600Sstevel@tonic-gate 	} else {
7610Sstevel@tonic-gate 	    char *tmp;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	    tmp = strchr(pbuf,'\n');
7640Sstevel@tonic-gate 	    if (tmp) *tmp = '\0';
7650Sstevel@tonic-gate 	    tmp = strchr(pbuf,'\r');
7660Sstevel@tonic-gate 	    if (tmp) *tmp = '\0';
7670Sstevel@tonic-gate 	    passwd = strdup(pbuf);
7680Sstevel@tonic-gate 	}
7690Sstevel@tonic-gate #else
7700Sstevel@tonic-gate #if defined(SOLARIS)
7710Sstevel@tonic-gate 	/* 256 characters on Solaris */
7720Sstevel@tonic-gate 	passwd = getpassphrase(password_string);
7730Sstevel@tonic-gate #else
7740Sstevel@tonic-gate 	/* limited to 16 chars on Tru64, 32 on AIX */
7750Sstevel@tonic-gate 	passwd = getpass(password_string);
7760Sstevel@tonic-gate #endif
7770Sstevel@tonic-gate #endif
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate     } else if (password_fp != NULL) {
7800Sstevel@tonic-gate 	char *linep = NULL;
7810Sstevel@tonic-gate 	int   increment = 0;
7820Sstevel@tonic-gate 	int   c, index;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	/* allocate initial block of memory */
7850Sstevel@tonic-gate 	if ((linep = (char *)malloc(BUFSIZ)) == NULL) {
7860Sstevel@tonic-gate 	    fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname );
7870Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 	increment++;
7900Sstevel@tonic-gate 	index = 0;
7910Sstevel@tonic-gate 	while ((c = fgetc( password_fp )) != '\n' && c != EOF) {
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	    /* check if we will overflow the buffer */
7940Sstevel@tonic-gate 	    if ((c != EOF) && (index == ((increment * BUFSIZ) -1))) {
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 		/* if we did, add another BUFSIZ worth of bytes */
7970Sstevel@tonic-gate 		if ((linep = (char *)
7980Sstevel@tonic-gate 		    realloc(linep, (increment + 1) * BUFSIZ)) == NULL) {
7990Sstevel@tonic-gate 			fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname );
8000Sstevel@tonic-gate 			exit( LDAP_NO_MEMORY );
8010Sstevel@tonic-gate 		}
8020Sstevel@tonic-gate 	 	increment++;
8030Sstevel@tonic-gate 	    }
8040Sstevel@tonic-gate 	    linep[index++] = c;
8050Sstevel@tonic-gate 	}
8060Sstevel@tonic-gate 	linep[index] = '\0';
8070Sstevel@tonic-gate 	passwd = linep;
8080Sstevel@tonic-gate     }
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
8110Sstevel@tonic-gate     if (binddn != NULL && passwd == NULL) {
8120Sstevel@tonic-gate 	char *password_string = gettext("Enter bind password: ");
8130Sstevel@tonic-gate 	passwd = getpassphrase(password_string);
8140Sstevel@tonic-gate     }
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
8170Sstevel@tonic-gate     if (ldapauth == LDAP_AUTH_SASL) {
8180Sstevel@tonic-gate 	/* BindDN not required for SASL */
8190Sstevel@tonic-gate 	ldaptool_require_binddn = 0;
8200Sstevel@tonic-gate     }
8210Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate #ifdef NET_SSL
8240Sstevel@tonic-gate     if (secure == 1) {
8250Sstevel@tonic-gate 	/* BindDN not required for SSL */
8260Sstevel@tonic-gate 	ldaptool_require_binddn = 0;
8270Sstevel@tonic-gate     }
8280Sstevel@tonic-gate #endif	/* NET_SSL */
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate     if (ldaptool_require_binddn && binddn == NULL && passwd == NULL) {
8310Sstevel@tonic-gate 		fprintf(stderr,
8320Sstevel@tonic-gate 			gettext("%s: DN and Bind Password are required.\n"),
8330Sstevel@tonic-gate 			ldaptool_progname );
8340Sstevel@tonic-gate 		exit(1);
8350Sstevel@tonic-gate     }
8360Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate     /*
8390Sstevel@tonic-gate      * If verbose (-v) flag was passed in, display program name and start time.
8400Sstevel@tonic-gate      * If the verbose flag was passed at least twice (-vv), also display
8410Sstevel@tonic-gate      * information about the API library we are running with.
8420Sstevel@tonic-gate      */
8430Sstevel@tonic-gate     if ( ldaptool_verbose ) {
8440Sstevel@tonic-gate 	time_t	curtime;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	curtime = time( NULL );
8470Sstevel@tonic-gate 	printf( gettext("%s: started %s\n"), ldaptool_progname, ctime( &curtime ));
8480Sstevel@tonic-gate 	if ( ldaptool_verbose > 1 ) {
8490Sstevel@tonic-gate 	    print_library_info( &ldai, stdout );
8500Sstevel@tonic-gate 	}
8510Sstevel@tonic-gate     }
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
8540Sstevel@tonic-gate     if ((NULL != pkcs_token) && (NULL != ssl_certname)) {
8550Sstevel@tonic-gate 	char *result;
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	if ( (result = buildTokenCertName( pkcs_token, ssl_certname)) != NULL){
8580Sstevel@tonic-gate 	    free( ssl_certname );
8590Sstevel@tonic-gate 	    ssl_certname = result;
8600Sstevel@tonic-gate 	}
8610Sstevel@tonic-gate     }
8620Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate     free( optstring );
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate     /*
8670Sstevel@tonic-gate      * Clean up and return index of first non-option argument.
8680Sstevel@tonic-gate      */
8690Sstevel@tonic-gate     if ( ldai.ldapai_extensions != NULL ) {
8700Sstevel@tonic-gate 	ldap_value_free( ldai.ldapai_extensions );
8710Sstevel@tonic-gate     }
8720Sstevel@tonic-gate     if ( ldai.ldapai_vendor_name != NULL ) {
8730Sstevel@tonic-gate 	ldap_memfree( ldai.ldapai_vendor_name );
8740Sstevel@tonic-gate     }
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
8770Sstevel@tonic-gate     if (ldversion == LDAP_VERSION2 && ldapauth == LDAP_AUTH_SASL) {
8780Sstevel@tonic-gate        fprintf( stderr, gettext("Incompatible with version %d\n"), ldversion);
8790Sstevel@tonic-gate        return (-1);
8800Sstevel@tonic-gate     }
8810Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
8820Sstevel@tonic-gate     return( optind );
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate /*
8870Sstevel@tonic-gate  * Write detailed information about the API library we are running with to fp.
8880Sstevel@tonic-gate  */
8890Sstevel@tonic-gate static void
8900Sstevel@tonic-gate print_library_info( const LDAPAPIInfo *aip, FILE *fp )
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate     int                 i;
8930Sstevel@tonic-gate     LDAPAPIFeatureInfo  fi;
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate     fprintf( fp, gettext("LDAP Library Information -\n"
8960Sstevel@tonic-gate 	    "    Highest supported protocol version: %d\n"
8970Sstevel@tonic-gate 	    "    LDAP API revision:                  %d\n"
8980Sstevel@tonic-gate 	    "    API vendor name:                    %s\n"
8990Sstevel@tonic-gate 	    "    Vendor-specific version:            %.2f\n"),
9000Sstevel@tonic-gate 	    aip->ldapai_protocol_version, aip->ldapai_api_version,
9010Sstevel@tonic-gate 	    aip->ldapai_vendor_name,
9020Sstevel@tonic-gate 	    (float)aip->ldapai_vendor_version / 100.0 );
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate     if ( aip->ldapai_extensions != NULL ) {
9050Sstevel@tonic-gate 	fputs( gettext("    LDAP API Extensions:\n"), fp );
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	for ( i = 0; aip->ldapai_extensions[i] != NULL; i++ )  {
9080Sstevel@tonic-gate 	    fprintf( fp, gettext("        %s"), aip->ldapai_extensions[i] );
9090Sstevel@tonic-gate 	    fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
9100Sstevel@tonic-gate 	    fi.ldapaif_name = aip->ldapai_extensions[i];
9110Sstevel@tonic-gate 	    fi.ldapaif_version = 0;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	    if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi )
9140Sstevel@tonic-gate 		    != 0 ) {
9150Sstevel@tonic-gate 		fprintf( fp, gettext(" %s: ldap_get_option( NULL,"
9160Sstevel@tonic-gate 			" LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed"
9170Sstevel@tonic-gate 			" (Feature Info version: %d)\n"), ldaptool_progname,
9180Sstevel@tonic-gate 			fi.ldapaif_name, fi.ldapaif_info_version );
9190Sstevel@tonic-gate 	    } else {
9200Sstevel@tonic-gate 		fprintf( fp, gettext(" (revision %d)\n"), fi.ldapaif_version);
9210Sstevel@tonic-gate 	    }
9220Sstevel@tonic-gate 	}
9230Sstevel@tonic-gate     }
9240Sstevel@tonic-gate    fputc( '\n', fp );
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate #ifdef LDAP_TOOL_ARGPIN
9300Sstevel@tonic-gate static int PinArgRegistration( void )
9310Sstevel@tonic-gate {
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate     /* pkcs_init was successful  register the pin args */
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate     SVRCOREArgPinObj *ArgPinObj;
9360Sstevel@tonic-gate     char *tokenName;
9370Sstevel@tonic-gate #ifndef _WIN32
9380Sstevel@tonic-gate     SVRCOREStdPinObj *StdPinObj;
9390Sstevel@tonic-gate #else
9400Sstevel@tonic-gate     SVRCOREFilePinObj *FilePinObj;
9410Sstevel@tonic-gate     SVRCOREAltPinObj *AltPinObj;
9420Sstevel@tonic-gate     SVRCORENTUserPinObj *NTUserPinObj;
9430Sstevel@tonic-gate     int err;
9440Sstevel@tonic-gate #endif
9450Sstevel@tonic-gate     char *pin;
9460Sstevel@tonic-gate     char *filename;
9470Sstevel@tonic-gate     /* Create and register the pin object for PKCS 11 */
9480Sstevel@tonic-gate     local_pkcs_fns.pkcs_getdonglefilename(NULL, &filename);
9490Sstevel@tonic-gate     local_pkcs_fns.pkcs_getpin(NULL, "", &pin);
9500Sstevel@tonic-gate #ifndef _WIN32
9510Sstevel@tonic-gate     if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) !=
9520Sstevel@tonic-gate 	 SVRCORE_Success) {
9530Sstevel@tonic-gate 	fprintf(stderr, gettext("Security Initialization: Unable to create PinObj "
9540Sstevel@tonic-gate 	       "(%d)"), PR_GetError());
9550Sstevel@tonic-gate 	return -1;
9560Sstevel@tonic-gate     }
9570Sstevel@tonic-gate     if (pin != NULL)
9580Sstevel@tonic-gate     {
9590Sstevel@tonic-gate 	local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
9600Sstevel@tonic-gate 	SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, (SVRCOREPinObj *)StdPinObj);
9610Sstevel@tonic-gate 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
9620Sstevel@tonic-gate     }
9630Sstevel@tonic-gate     else
9640Sstevel@tonic-gate     {
9650Sstevel@tonic-gate 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj);
9660Sstevel@tonic-gate     }
9670Sstevel@tonic-gate #else
9680Sstevel@tonic-gate     if (NULL != pin)
9690Sstevel@tonic-gate     {
9700Sstevel@tonic-gate 	local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
9710Sstevel@tonic-gate 	if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
9720Sstevel@tonic-gate 	    fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj "
9730Sstevel@tonic-gate 		   "(%d)"), PR_GetError());
9740Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
9750Sstevel@tonic-gate 	}
9760Sstevel@tonic-gate 	if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin,
9770Sstevel@tonic-gate 					   (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success)
9780Sstevel@tonic-gate 	{
9790Sstevel@tonic-gate 	    fprintf(stderr, gettext("Security Initialization: Unable to create ArgPinObj "
9800Sstevel@tonic-gate 		   "(%d)"), PR_GetError());
9810Sstevel@tonic-gate 	    return -1;
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	}
9840Sstevel@tonic-gate 	SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate     }
9870Sstevel@tonic-gate     else
9880Sstevel@tonic-gate     {
9890Sstevel@tonic-gate 	if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
9900Sstevel@tonic-gate 	    fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj "
9910Sstevel@tonic-gate 		   "(%d)"), PR_GetError());
9920Sstevel@tonic-gate 		return -1;
9930Sstevel@tonic-gate 	}
9940Sstevel@tonic-gate 	if (filename && *filename)
9950Sstevel@tonic-gate 	{
9960Sstevel@tonic-gate 	    if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) !=
9970Sstevel@tonic-gate 		SVRCORE_Success) {
9980Sstevel@tonic-gate 		fprintf(stderr, gettext("Security Initialization: Unable to create FilePinObj "
9990Sstevel@tonic-gate 		       "(%d)"), PR_GetError());
10000Sstevel@tonic-gate 		return -1;
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	    }
10030Sstevel@tonic-gate 	    if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
10040Sstevel@tonic-gate 					       (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) {
10050Sstevel@tonic-gate 		fprintf(stderr, gettext("Security Initialization: Unable to create AltPinObj "
10060Sstevel@tonic-gate 		       "(%d)"), PR_GetError());
10070Sstevel@tonic-gate 		return -1;
10080Sstevel@tonic-gate 	    }
10090Sstevel@tonic-gate 	    SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj);
10100Sstevel@tonic-gate 	}
10110Sstevel@tonic-gate 	else
10120Sstevel@tonic-gate 	{
10130Sstevel@tonic-gate 	    SVRCORE_RegisterPinObj((SVRCOREPinObj *)NTUserPinObj);
10140Sstevel@tonic-gate 	}
10150Sstevel@tonic-gate     }
10160Sstevel@tonic-gate #endif
10170Sstevel@tonic-gate     return LDAP_SUCCESS;
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate #endif /* LDAP_TOOL_ARGPIN */
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate  * initialize and return an LDAP session handle.
10250Sstevel@tonic-gate  * if errors occur, we exit here.
10260Sstevel@tonic-gate  */
10270Sstevel@tonic-gate LDAP *
10280Sstevel@tonic-gate ldaptool_ldap_init( int second_host )
10290Sstevel@tonic-gate {
10300Sstevel@tonic-gate     LDAP	*ld = NULL;
10310Sstevel@tonic-gate     char	*host;
10320Sstevel@tonic-gate     int		port, rc, user_port;
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate     if ( ldaptool_not ) {
10350Sstevel@tonic-gate 	return( NULL );
10360Sstevel@tonic-gate     }
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate     if ( second_host ) {
10390Sstevel@tonic-gate 	host = ldaptool_host2;
10400Sstevel@tonic-gate 	port = ldaptool_port2;
10410Sstevel@tonic-gate 	user_port = user_specified_port2;
10420Sstevel@tonic-gate     } else {
10430Sstevel@tonic-gate 	host = ldaptool_host;
10440Sstevel@tonic-gate 	port = ldaptool_port;
10450Sstevel@tonic-gate 	user_port = user_specified_port;
10460Sstevel@tonic-gate     }
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate     if ( ldaptool_verbose ) {
10500Sstevel@tonic-gate 	printf( gettext("ldap_init( %s, %d )\n"), host, port );
10510Sstevel@tonic-gate     }
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate #if defined(NET_SSL)
10540Sstevel@tonic-gate     /*
10550Sstevel@tonic-gate      * Initialize security libraries and databases and LDAP session.  If
10560Sstevel@tonic-gate      * ssl_certname is not NULL, then we will attempt to use client auth.
10570Sstevel@tonic-gate      * if the server supports it.
10580Sstevel@tonic-gate      */
10590Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
10600Sstevel@tonic-gate     ldaptool_setcallbacks( &local_pkcs_fns );
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate     if ( !second_host 	&& secure
10630Sstevel@tonic-gate 	 &&(rc = ldapssl_pkcs_init( &local_pkcs_fns))  < 0) {
10640Sstevel@tonic-gate 	    /* secure connection requested -- fail if no SSL */
10650Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
10660Sstevel@tonic-gate 	    rc = PORT_GetError();
10670Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
10680Sstevel@tonic-gate 	    fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"),
10690Sstevel@tonic-gate 		    rc, ldapssl_err2string( rc ));
10700Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
10710Sstevel@tonic-gate     }
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate #ifdef LDAP_TOOL_ARGPIN
10740Sstevel@tonic-gate     if (secure) {
10750Sstevel@tonic-gate 	if (PinArgRegistration( )) {
10760Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR);
10770Sstevel@tonic-gate 	}
10780Sstevel@tonic-gate     }
10790Sstevel@tonic-gate #endif /* LDAP_TOOL_ARGPIN */
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate #else /* LDAP_TOOL_PKCS11 */
10820Sstevel@tonic-gate     if ( !second_host 	&& secure
10830Sstevel@tonic-gate 	 &&(rc = ldapssl_client_init( ssl_certdbpath, NULL )) < 0) {
10840Sstevel@tonic-gate 	    /* secure connection requested -- fail if no SSL */
10850Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
10860Sstevel@tonic-gate 	    rc = PORT_GetError();
10870Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
10880Sstevel@tonic-gate 	    fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"),
10890Sstevel@tonic-gate 		    rc, ldapssl_err2string( rc ));
10900Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
10910Sstevel@tonic-gate     }
10920Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate     /* set the default SSL strength (used for all future ld's we create) */
10950Sstevel@tonic-gate     if ( ldapssl_set_strength( NULL, ssl_strength ) < 0 ) {
10960Sstevel@tonic-gate         perror( "ldapssl_set_strength" );
10970Sstevel@tonic-gate         exit( LDAP_LOCAL_ERROR );
10980Sstevel@tonic-gate     }
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate     if (secure) {
11020Sstevel@tonic-gate 	if ( !user_port ) {
11030Sstevel@tonic-gate 	    port = LDAPS_PORT;
11040Sstevel@tonic-gate 	}
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	if (( ld = ldapssl_init( host, port,
11070Sstevel@tonic-gate 		secure )) != NULL && ssl_certname != NULL )
11080Sstevel@tonic-gate 	    if (ldapssl_enable_clientauth( ld, ssl_keydbpath, ssl_passwd,
11090Sstevel@tonic-gate 		ssl_certname ) != 0 ) {
11100Sstevel@tonic-gate 		exit ( ldaptool_print_lderror( ld, "ldapssl_enable_clientauth",
11110Sstevel@tonic-gate 		    LDAPTOOL_CHECK4SSL_ALWAYS ));
11120Sstevel@tonic-gate 	    }
11130Sstevel@tonic-gate     } else {
11140Sstevel@tonic-gate 	/* In order to support IPv6, we use NSPR I/O */
11150Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11160Sstevel@tonic-gate 	ld = ldap_init( host, port );
11170Sstevel@tonic-gate #else
11180Sstevel@tonic-gate 	ld = prldap_init( host, port, 0 /* not shared across threads */ );
11190Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
11200Sstevel@tonic-gate     }
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate #else /* NET_SSL */
11230Sstevel@tonic-gate     /* In order to support IPv6, we use NSPR I/O */
11240Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD
11250Sstevel@tonic-gate     ld = ldap_init( host, port );
11260Sstevel@tonic-gate #else
11270Sstevel@tonic-gate     ld = prldap_init( host, port, 0 /* not shared across threads */ );
11280Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */
11290Sstevel@tonic-gate #endif /* NET_SSL */
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate     if ( ld == NULL ) {
11320Sstevel@tonic-gate 	perror( "ldap_init" );
11330Sstevel@tonic-gate 	exit( LDAP_LOCAL_ERROR );
11340Sstevel@tonic-gate     }
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate #ifndef NO_LIBLCACHE
11370Sstevel@tonic-gate     if ( cache_config_file != NULL ) {
11380Sstevel@tonic-gate 	int	opt;
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	if ( lcache_init( ld, cache_config_file ) != 0 ) {
11410Sstevel@tonic-gate 		exit( ldaptool_print_lderror( ld, cache_config_file,
11420Sstevel@tonic-gate 			LDAPTOOL_CHECK4SSL_NEVER ));
11430Sstevel@tonic-gate 	}
11440Sstevel@tonic-gate 	opt = 1;
11450Sstevel@tonic-gate 	(void) ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &opt );
11460Sstevel@tonic-gate 	opt = LDAP_CACHE_LOCALDB;
11470Sstevel@tonic-gate 	(void) ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &opt );
11480Sstevel@tonic-gate 	if ( ldversion == -1 ) {	/* not set with -V */
11490Sstevel@tonic-gate 	    ldversion = LDAP_VERSION2;	/* local db only supports v2 */
11500Sstevel@tonic-gate 	}
11510Sstevel@tonic-gate     }
11520Sstevel@tonic-gate #endif
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate     ldap_set_option( ld, LDAP_OPT_REFERRALS, chase_referrals ? LDAP_OPT_ON:
11560Sstevel@tonic-gate 	LDAP_OPT_OFF );
11570Sstevel@tonic-gate     if ( chase_referrals ) {
11580Sstevel@tonic-gate 	ldap_set_rebind_proc( ld, get_rebind_credentials, NULL );
11590Sstevel@tonic-gate 	ldap_set_option( ld, LDAP_OPT_REFERRAL_HOP_LIMIT, &refhoplim );
11600Sstevel@tonic-gate     }
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate     if ( ldversion == -1 ) {	/* not set with -V and not using local db */
11630Sstevel@tonic-gate 	ldversion = LDAP_VERSION3;
11640Sstevel@tonic-gate     }
11650Sstevel@tonic-gate     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate     return( ld );
11680Sstevel@tonic-gate }
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate /*
11720Sstevel@tonic-gate  * perform a bind to the LDAP server if needed.
11730Sstevel@tonic-gate  * if an error occurs, we exit here.
11740Sstevel@tonic-gate  */
11750Sstevel@tonic-gate void
11760Sstevel@tonic-gate ldaptool_bind( LDAP *ld )
11770Sstevel@tonic-gate {
11780Sstevel@tonic-gate     int		rc;
11790Sstevel@tonic-gate     char	*conv;
11800Sstevel@tonic-gate     LDAPControl	auth_resp_ctrl, *ctrl_array[ 2 ], **bindctrls;
11810Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
11820Sstevel@tonic-gate     void *defaults;
11830Sstevel@tonic-gate #endif
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate     if ( ldaptool_not ) {
11860Sstevel@tonic-gate 	return;
11870Sstevel@tonic-gate     }
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate     if ( send_auth_response_ctrl ) {
11900Sstevel@tonic-gate 	auth_resp_ctrl.ldctl_oid = LDAP_CONTROL_AUTH_REQUEST;
11910Sstevel@tonic-gate 	auth_resp_ctrl.ldctl_value.bv_val = NULL;
11920Sstevel@tonic-gate 	auth_resp_ctrl.ldctl_value.bv_len = 0;
11930Sstevel@tonic-gate 	auth_resp_ctrl.ldctl_iscritical = 0;
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 	ctrl_array[0] = &auth_resp_ctrl;
11960Sstevel@tonic-gate 	ctrl_array[1] = NULL;
11970Sstevel@tonic-gate 	bindctrls = ctrl_array;
11980Sstevel@tonic-gate     } else {
11990Sstevel@tonic-gate 	bindctrls = NULL;
12000Sstevel@tonic-gate     }
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate     /*
12030Sstevel@tonic-gate      * if using LDAPv3 and not using client auth., omit NULL bind for
12040Sstevel@tonic-gate      * efficiency.
12050Sstevel@tonic-gate      */
12060Sstevel@tonic-gate     if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
12070Sstevel@tonic-gate 	    && ssl_certname == NULL ) {
12080Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
12090Sstevel@tonic-gate 	if ( ldapauth != LDAP_AUTH_SASL ) {
12100Sstevel@tonic-gate 	   return;
12110Sstevel@tonic-gate 	}
12120Sstevel@tonic-gate #else
12130Sstevel@tonic-gate 	return;
12140Sstevel@tonic-gate #endif
12150Sstevel@tonic-gate     }
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate     /*
12180Sstevel@tonic-gate      * do the bind, backing off one LDAP version if necessary
12190Sstevel@tonic-gate      */
12200Sstevel@tonic-gate     conv = ldaptool_local2UTF8( binddn );
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
12230Sstevel@tonic-gate     if ( ldapauth == LDAP_AUTH_SASL) {
12240Sstevel@tonic-gate 	if ( sasl_mech == NULL) {
12250Sstevel@tonic-gate 	   fprintf( stderr, gettext("Please specify the SASL mechanism name when "
12260Sstevel@tonic-gate 				"using SASL options\n"));
12270Sstevel@tonic-gate 	   return;
12280Sstevel@tonic-gate 	}
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate         if ( sasl_secprops != NULL) {
12310Sstevel@tonic-gate            rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
12320Sstevel@tonic-gate                                 (void *) sasl_secprops );
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate            if ( rc != LDAP_SUCCESS ) {
12350Sstevel@tonic-gate               fprintf( stderr, gettext("Unable to set LDAP_OPT_X_SASL_SECPROPS: %s\n"),
12360Sstevel@tonic-gate 				sasl_secprops );
12370Sstevel@tonic-gate               return;
12380Sstevel@tonic-gate            }
12390Sstevel@tonic-gate         }
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate         defaults = ldaptool_set_sasl_defaults( ld, sasl_mech, sasl_authid, sasl_username, passwd, sasl_realm );
12420Sstevel@tonic-gate         if (defaults == NULL) {
12430Sstevel@tonic-gate 	   perror ("malloc");
12440Sstevel@tonic-gate 	   exit (LDAP_NO_MEMORY);
12450Sstevel@tonic-gate 	}
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate         rc = ldap_sasl_interactive_bind_s( ld, binddn, sasl_mech, NULL, NULL,
12480Sstevel@tonic-gate                         sasl_flags, ldaptool_sasl_interact, defaults );
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate         if (rc != LDAP_SUCCESS ) {
12510Sstevel@tonic-gate            ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
12520Sstevel@tonic-gate         }
12530Sstevel@tonic-gate     } else
12540Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
12550Sstevel@tonic-gate         /*
12560Sstevel@tonic-gate          * if using LDAPv3 and client auth., try a SASL EXTERNAL bind
12570Sstevel@tonic-gate          */
12580Sstevel@tonic-gate          if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
12590Sstevel@tonic-gate 	    	&& ssl_certname != NULL ) {
12600Sstevel@tonic-gate 	     rc = ldaptool_sasl_bind_s( ld, NULL, LDAP_SASL_EXTERNAL, NULL,
12610Sstevel@tonic-gate 			bindctrls, NULL, NULL, "ldap_sasl_bind" );
12620Sstevel@tonic-gate     	 }
12630Sstevel@tonic-gate          else {
12640Sstevel@tonic-gate 	     rc = ldaptool_simple_bind_s( ld, conv, passwd, bindctrls, NULL,
12650Sstevel@tonic-gate 		    "ldap_simple_bind" );
12660Sstevel@tonic-gate 	  }
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate     if ( rc == LDAP_SUCCESS ) {
12690Sstevel@tonic-gate         if ( conv != NULL ) {
12700Sstevel@tonic-gate            free( conv );
12710Sstevel@tonic-gate 	}
12720Sstevel@tonic-gate 	return;			/* success */
12730Sstevel@tonic-gate     }
12740Sstevel@tonic-gate 
12750Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
12760Sstevel@tonic-gate   if (ldapauth != LDAP_AUTH_SASL) {
12770Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
12780Sstevel@tonic-gate     if ( rc == LDAP_PROTOCOL_ERROR && ldversion > LDAP_VERSION2 ) {
12790Sstevel@tonic-gate 	/*
12800Sstevel@tonic-gate 	 * try again, backing off one LDAP version
12810Sstevel@tonic-gate 	 * this is okay even for client auth. because the way to achieve
12820Sstevel@tonic-gate 	 * client auth. with LDAPv2 is to perform a NULL simple bind.
12830Sstevel@tonic-gate 	 */
12840Sstevel@tonic-gate 	--ldversion;
12850Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: the server doesn't understand LDAPv%d;"
12860Sstevel@tonic-gate 		" trying LDAPv%d instead...\n"), ldaptool_progname,
12870Sstevel@tonic-gate 		ldversion + 1, ldversion );
12880Sstevel@tonic-gate 	ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
12890Sstevel@tonic-gate 	if (( rc = ldaptool_simple_bind_s( ld, conv, passwd,
12900Sstevel@tonic-gate 		bindctrls, NULL, "ldap_simple_bind" )) == LDAP_SUCCESS ) {
12910Sstevel@tonic-gate             if( conv != NULL )
12920Sstevel@tonic-gate                 free( conv );
12930Sstevel@tonic-gate 	    return;		/* a qualified success */
12940Sstevel@tonic-gate 	}
12950Sstevel@tonic-gate     }
12960Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
12970Sstevel@tonic-gate   }
12980Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate     if ( conv != NULL ) {
13010Sstevel@tonic-gate         free( conv );
13020Sstevel@tonic-gate     }
13030Sstevel@tonic-gate 
13040Sstevel@tonic-gate     /*
13050Sstevel@tonic-gate      * bind(s) failed -- fatal error
13060Sstevel@tonic-gate      */
13070Sstevel@tonic-gate     ldap_unbind( ld );
13080Sstevel@tonic-gate     exit( rc );
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate /*
13130Sstevel@tonic-gate  * close open files, unbind, etc.
13140Sstevel@tonic-gate  */
13150Sstevel@tonic-gate void
13160Sstevel@tonic-gate ldaptool_cleanup( LDAP *ld )
13170Sstevel@tonic-gate {
13180Sstevel@tonic-gate     if ( ld != NULL ) {
13190Sstevel@tonic-gate 	ldap_unbind( ld );
13200Sstevel@tonic-gate     }
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate     if ( ldaptool_fp != NULL && ldaptool_fp != stdin ) {
13230Sstevel@tonic-gate 	fclose( ldaptool_fp );
13240Sstevel@tonic-gate 	ldaptool_fp = NULL;
13250Sstevel@tonic-gate     }
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate /*
13300Sstevel@tonic-gate  * Retrieve and print an LDAP error message.  Returns the LDAP error code.
13310Sstevel@tonic-gate  */
13320Sstevel@tonic-gate int
13330Sstevel@tonic-gate ldaptool_print_lderror( LDAP *ld, char *msg, int check4ssl )
13340Sstevel@tonic-gate {
13350Sstevel@tonic-gate     int		lderr = ldap_get_lderrno( ld, NULL, NULL );
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate     ldap_perror( ld, msg );
13380Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
13390Sstevel@tonic-gate     if ( secure && check4ssl != LDAPTOOL_CHECK4SSL_NEVER ) {
13400Sstevel@tonic-gate 	if ( check4ssl == LDAPTOOL_CHECK4SSL_ALWAYS
13410Sstevel@tonic-gate 		|| ( lderr == LDAP_SERVER_DOWN )) {
13420Sstevel@tonic-gate 	    int		sslerr = PORT_GetError();
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	    fprintf( stderr, gettext("\tSSL error %d (%s)\n"), sslerr,
13450Sstevel@tonic-gate 		    ldapssl_err2string( sslerr ));
13460Sstevel@tonic-gate 	}
13470Sstevel@tonic-gate     }
13480Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate     return( lderr );
13510Sstevel@tonic-gate }
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate /*
13550Sstevel@tonic-gate  * print referrals to stderr
13560Sstevel@tonic-gate  */
13570Sstevel@tonic-gate void
13580Sstevel@tonic-gate ldaptool_print_referrals( char **refs )
13590Sstevel@tonic-gate {
13600Sstevel@tonic-gate     int		i;
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate     if ( refs != NULL ) {
13630Sstevel@tonic-gate 	for ( i = 0; refs[ i ] != NULL; ++i ) {
13640Sstevel@tonic-gate 	    fprintf( stderr, gettext("Referral: %s\n"), refs[ i ] );
13650Sstevel@tonic-gate 	}
13660Sstevel@tonic-gate     }
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate /*
13710Sstevel@tonic-gate  * print contents of an extended response to stderr
13720Sstevel@tonic-gate  * this is mainly to support unsolicited notifications
13730Sstevel@tonic-gate  * Returns an LDAP error code (from the extended result).
13740Sstevel@tonic-gate  */
13750Sstevel@tonic-gate int
13760Sstevel@tonic-gate ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg )
13770Sstevel@tonic-gate {
13780Sstevel@tonic-gate     char		*oid;
13790Sstevel@tonic-gate     struct berval	*data;
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate     if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 )
13820Sstevel@tonic-gate 	    != LDAP_SUCCESS ) {
13830Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
13840Sstevel@tonic-gate     } else {
13850Sstevel@tonic-gate 	if ( oid != NULL ) {
13860Sstevel@tonic-gate 	    if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) {
13870Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: Notice of Disconnection\n"), msg );
13880Sstevel@tonic-gate 	    } else {
13890Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: OID %s\n"), msg, oid );
13900Sstevel@tonic-gate 	    }
13910Sstevel@tonic-gate 	    ldap_memfree( oid );
13920Sstevel@tonic-gate 	} else {
13930Sstevel@tonic-gate 	    fprintf( stderr, gettext("%s: missing OID\n"), msg );
13940Sstevel@tonic-gate 	}
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	if ( data != NULL ) {
13970Sstevel@tonic-gate 	    fprintf( stderr, gettext("%s: Data (length %ld):\n"), msg, data->bv_len );
13980Sstevel@tonic-gate #if 0
13990Sstevel@tonic-gate /* XXXmcs: maybe we should display the actual data? */
14000Sstevel@tonic-gate 	    lber_bprint( data->bv_val, data->bv_len );
14010Sstevel@tonic-gate #endif
14020Sstevel@tonic-gate 	    ber_bvfree( data );
14030Sstevel@tonic-gate 	}
14040Sstevel@tonic-gate     }
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate     return parse_result( ld, res, NULL, msg, 1 );
14070Sstevel@tonic-gate }
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 
14100Sstevel@tonic-gate /*
14110Sstevel@tonic-gate  * Like ldap_sasl_bind_s() but calls wait4result() to display
14120Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
14130Sstevel@tonic-gate  */
14140Sstevel@tonic-gate int
14150Sstevel@tonic-gate ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism,
14160Sstevel@tonic-gate 	const struct berval *cred, LDAPControl **serverctrls,
14170Sstevel@tonic-gate 	LDAPControl **clientctrls, struct berval **servercredp, char *msg )
14180Sstevel@tonic-gate {
14190Sstevel@tonic-gate     int		rc, msgid;
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate     if ( servercredp != NULL ) {
14220Sstevel@tonic-gate 	    *servercredp = NULL;
14230Sstevel@tonic-gate     }
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate     if (( rc = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls,
14260Sstevel@tonic-gate 	    clientctrls, &msgid )) != LDAP_SUCCESS ) {
14270Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
14280Sstevel@tonic-gate     } else {
14290Sstevel@tonic-gate 	rc = wait4result( ld, msgid, servercredp, msg );
14300Sstevel@tonic-gate     }
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate     return( rc );
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate /*
14370Sstevel@tonic-gate  * Like ldap_simple_bind_s() but calls wait4result() to display
14380Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
14390Sstevel@tonic-gate  */
14400Sstevel@tonic-gate int
14410Sstevel@tonic-gate ldaptool_simple_bind_s( LDAP *ld, const char *dn, const char *passwd,
14420Sstevel@tonic-gate 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
14430Sstevel@tonic-gate {
14440Sstevel@tonic-gate     struct berval	bv;
14450Sstevel@tonic-gate 
14460Sstevel@tonic-gate     bv.bv_val = (char *)passwd;		/* XXXmcs: had to cast away const */
14470Sstevel@tonic-gate     bv.bv_len = ( passwd == NULL ? 0 : strlen( passwd ));
14480Sstevel@tonic-gate     return( ldaptool_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &bv, serverctrls,
14490Sstevel@tonic-gate 	    clientctrls, NULL, msg ));
14500Sstevel@tonic-gate }
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate /*
14540Sstevel@tonic-gate  * Like ldap_add_ext_s() but calls wait4result() to display
14550Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
14560Sstevel@tonic-gate  */
14570Sstevel@tonic-gate int
14580Sstevel@tonic-gate ldaptool_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
14590Sstevel@tonic-gate 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
14600Sstevel@tonic-gate {
14610Sstevel@tonic-gate     int		rc, msgid;
14620Sstevel@tonic-gate 
14630Sstevel@tonic-gate     if (( rc = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, &msgid ))
14640Sstevel@tonic-gate 	    != LDAP_SUCCESS ) {
14650Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
14660Sstevel@tonic-gate     } else {
14670Sstevel@tonic-gate 	/*
14680Sstevel@tonic-gate 	 * 25-April-2000 Note: the next line used to read:
14690Sstevel@tonic-gate 	 *	rc = wait4result( ld, msgid, NULL, msg );
14700Sstevel@tonic-gate 	 * 'msgid' it was changed to 'LDAP_RES_ANY' in order to receive
14710Sstevel@tonic-gate 	 * unsolicited notifications.
14720Sstevel@tonic-gate 	 */
14730Sstevel@tonic-gate 	rc = wait4result( ld, LDAP_RES_ANY, NULL, msg );
14740Sstevel@tonic-gate     }
14750Sstevel@tonic-gate 
14760Sstevel@tonic-gate     return( rc );
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 
14800Sstevel@tonic-gate /*
14810Sstevel@tonic-gate  * Like ldap_modify_ext_s() but calls wait4result() to display
14820Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
14830Sstevel@tonic-gate  */
14840Sstevel@tonic-gate int
14850Sstevel@tonic-gate ldaptool_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
14860Sstevel@tonic-gate 	LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
14870Sstevel@tonic-gate {
14880Sstevel@tonic-gate     int		rc, msgid;
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate     if (( rc = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
14910Sstevel@tonic-gate 	    &msgid )) != LDAP_SUCCESS ) {
14920Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
14930Sstevel@tonic-gate     } else {
14940Sstevel@tonic-gate 	rc = wait4result( ld, msgid, NULL, msg );
14950Sstevel@tonic-gate     }
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate     return( rc );
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate /*
15020Sstevel@tonic-gate  * Like ldap_delete_ext_s() but calls wait4result() to display
15030Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
15040Sstevel@tonic-gate  */
15050Sstevel@tonic-gate int
15060Sstevel@tonic-gate ldaptool_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls,
15070Sstevel@tonic-gate 	LDAPControl **clientctrls, char *msg )
15080Sstevel@tonic-gate {
15090Sstevel@tonic-gate     int		rc, msgid;
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate     if (( rc = ldap_delete_ext( ld, dn, serverctrls, clientctrls, &msgid ))
15120Sstevel@tonic-gate 	    != LDAP_SUCCESS ) {
15130Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
15140Sstevel@tonic-gate     } else {
15150Sstevel@tonic-gate 	rc = wait4result( ld, msgid, NULL, msg );
15160Sstevel@tonic-gate     }
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate     return( rc );
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate /*
15230Sstevel@tonic-gate  * Like ldap_compare_ext_s() but calls wait4result() to display
15240Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
15250Sstevel@tonic-gate  */
15260Sstevel@tonic-gate int ldaptool_compare_ext_s( LDAP *ld, const char *dn, const char *attrtype,
15270Sstevel@tonic-gate 	    const struct berval *bvalue, LDAPControl **serverctrls,
15280Sstevel@tonic-gate 	    LDAPControl **clientctrls, char *msg )
15290Sstevel@tonic-gate {
15300Sstevel@tonic-gate     int		rc, msgid;
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate     if (( rc = ldap_compare_ext( ld, dn, attrtype, bvalue, serverctrls,
15330Sstevel@tonic-gate 	    clientctrls, &msgid )) != LDAP_SUCCESS ) {
15340Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
15350Sstevel@tonic-gate     } else {
15360Sstevel@tonic-gate 	rc = wait4result( ld, msgid, NULL, msg );
15370Sstevel@tonic-gate     }
15380Sstevel@tonic-gate 
15390Sstevel@tonic-gate     return( rc );
15400Sstevel@tonic-gate }
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate /*
15440Sstevel@tonic-gate  * Like ldap_rename_s() but calls wait4result() to display
15450Sstevel@tonic-gate  * any referrals returned and report errors in a consistent way.
15460Sstevel@tonic-gate  */
15470Sstevel@tonic-gate int
15480Sstevel@tonic-gate ldaptool_rename_s(  LDAP *ld, const char *dn, const char *newrdn,
15490Sstevel@tonic-gate 	const char *newparent, int deleteoldrdn, LDAPControl **serverctrls,
15500Sstevel@tonic-gate 	LDAPControl **clientctrls, char *msg )
15510Sstevel@tonic-gate {
15520Sstevel@tonic-gate     int		rc, msgid;
15530Sstevel@tonic-gate 
15540Sstevel@tonic-gate     if (( rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn,
15550Sstevel@tonic-gate 	    serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
15560Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
15570Sstevel@tonic-gate     } else {
15580Sstevel@tonic-gate 	rc = wait4result( ld, msgid, NULL, msg );
15590Sstevel@tonic-gate     }
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate     return( rc );
15620Sstevel@tonic-gate }
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate /*
15660Sstevel@tonic-gate  * Wait for a result, check for and display errors and referrals.
15670Sstevel@tonic-gate  * Also recognize and display "Unsolicited notification" messages.
15680Sstevel@tonic-gate  * Returns an LDAP error code.
15690Sstevel@tonic-gate  */
15700Sstevel@tonic-gate static int
15710Sstevel@tonic-gate wait4result( LDAP *ld, int msgid, struct berval **servercredp, char *msg )
15720Sstevel@tonic-gate {
15730Sstevel@tonic-gate     LDAPMessage	*res;
15740Sstevel@tonic-gate     int		rc, received_only_unsolicited = 1;
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate     while ( received_only_unsolicited ) {
15770Sstevel@tonic-gate 	res = NULL;
15780Sstevel@tonic-gate 	if (( rc = ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ))
15790Sstevel@tonic-gate 		    == -1 ) {
15800Sstevel@tonic-gate 	    ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
15810Sstevel@tonic-gate 	    return( ldap_get_lderrno( ld, NULL, NULL ));
15820Sstevel@tonic-gate 	}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	/*
15850Sstevel@tonic-gate 	 * Special handling for unsolicited notifications:
15860Sstevel@tonic-gate 	 *    1. Parse and display contents.
15870Sstevel@tonic-gate 	 *    2. go back and wait for another (real) result.
15880Sstevel@tonic-gate 	 */
15890Sstevel@tonic-gate 	if ( rc == LDAP_RES_EXTENDED
15900Sstevel@tonic-gate 		    && ldap_msgid( res ) == LDAP_RES_UNSOLICITED ) {
15910Sstevel@tonic-gate 	    rc = ldaptool_print_extended_response( ld, res,
15920Sstevel@tonic-gate 		    "Unsolicited response" );
15930Sstevel@tonic-gate 	} else {
15940Sstevel@tonic-gate 	    rc = parse_result( ld, res, servercredp, msg, 1 );
15950Sstevel@tonic-gate 	    received_only_unsolicited = 0;	/* we're done */
15960Sstevel@tonic-gate 	}
15970Sstevel@tonic-gate     }
15980Sstevel@tonic-gate 
15990Sstevel@tonic-gate     return( rc );
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate static int
16040Sstevel@tonic-gate parse_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp,
16050Sstevel@tonic-gate 	char *msg, int freeit )
16060Sstevel@tonic-gate {
16070Sstevel@tonic-gate     int		rc, lderr, errno;
16080Sstevel@tonic-gate     int		pw_days=0, pw_hrs=0, pw_mins=0, pw_secs=0; /* for pwpolicy */
16090Sstevel@tonic-gate     char	**refs = NULL;
16100Sstevel@tonic-gate     LDAPControl	**ctrls;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate     if (( rc = ldap_parse_result( ld, res, &lderr, NULL, NULL, &refs,
16130Sstevel@tonic-gate 	    &ctrls, 0 )) != LDAP_SUCCESS ) {
16140Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
16150Sstevel@tonic-gate 	ldap_msgfree( res );
16160Sstevel@tonic-gate 	return( rc );
16170Sstevel@tonic-gate     }
16180Sstevel@tonic-gate 
16190Sstevel@tonic-gate     /* check for authentication response control & PWPOLICY control*/
16200Sstevel@tonic-gate     if ( NULL != ctrls ) {
16210Sstevel@tonic-gate 	int		i;
16220Sstevel@tonic-gate 	char		*s;
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 	for ( i = 0; NULL != ctrls[i]; ++i ) {
16250Sstevel@tonic-gate 	    if ( 0 == strcmp( ctrls[i]->ldctl_oid,
16260Sstevel@tonic-gate 			LDAP_CONTROL_AUTH_RESPONSE )) {
16270Sstevel@tonic-gate 		    s = ctrls[i]->ldctl_value.bv_val;
16280Sstevel@tonic-gate 		    if ( NULL == s ) {
16290Sstevel@tonic-gate 			s = "Null";
16300Sstevel@tonic-gate 		    } else if ( *s == '\0' ) {
16310Sstevel@tonic-gate 			s = "Anonymous";
16320Sstevel@tonic-gate 		    }
16330Sstevel@tonic-gate 		fprintf( stderr, gettext("%s: bound as %s\n"), ldaptool_progname, s );
16340Sstevel@tonic-gate 	    }
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 	    if ( 0 == strcmp( ctrls[i]->ldctl_oid,
16370Sstevel@tonic-gate 			LDAP_CONTROL_PWEXPIRING )) {
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 		    /* Warn the user his passwd is to expire */
16400Sstevel@tonic-gate 		    errno = 0;
16410Sstevel@tonic-gate 		    pw_secs = atoi(ctrls[i]->ldctl_value.bv_val);
16420Sstevel@tonic-gate 		    if ( pw_secs > 0  && errno != ERANGE ) {
16430Sstevel@tonic-gate 			if ( pw_secs > 86400 ) {
16440Sstevel@tonic-gate 				pw_days = ( pw_secs / 86400 );
16450Sstevel@tonic-gate 				pw_secs = ( pw_secs % 86400 );
16460Sstevel@tonic-gate 			}
16470Sstevel@tonic-gate 			if ( pw_secs > 3600 ) {
16480Sstevel@tonic-gate 				pw_hrs = ( pw_secs / 3600 );
16490Sstevel@tonic-gate 				pw_secs = ( pw_secs % 3600 );
16500Sstevel@tonic-gate 			}
16510Sstevel@tonic-gate 			if ( pw_secs > 60 ) {
16520Sstevel@tonic-gate 				pw_mins = ( pw_secs / 60 );
16530Sstevel@tonic-gate 				pw_secs = ( pw_secs % 60 );
16540Sstevel@tonic-gate 			}
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 			printf(gettext("%s: Warning ! Your password will expire after "), ldaptool_progname);
16570Sstevel@tonic-gate 			if ( pw_days ) {
16580Sstevel@tonic-gate 				printf (gettext("%d days, "), pw_days);
16590Sstevel@tonic-gate 			}
16600Sstevel@tonic-gate 			if ( pw_hrs ) {
16610Sstevel@tonic-gate 				printf (gettext("%d hrs, "), pw_hrs);
16620Sstevel@tonic-gate 			}
16630Sstevel@tonic-gate 			if ( pw_mins ) {
16640Sstevel@tonic-gate 				printf (gettext("%d mins, "), pw_mins);
16650Sstevel@tonic-gate 			}
16660Sstevel@tonic-gate 			printf(gettext("%d seconds.\n"), pw_secs);
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 		   }
16690Sstevel@tonic-gate 		}
16700Sstevel@tonic-gate 	}
16710Sstevel@tonic-gate 	ldap_controls_free( ctrls );
16720Sstevel@tonic-gate     }
16730Sstevel@tonic-gate 
16740Sstevel@tonic-gate     if ( servercredp != NULL && ( rc = ldap_parse_sasl_bind_result( ld, res,
16750Sstevel@tonic-gate 	    servercredp, 0 )) != LDAP_SUCCESS ) {
16760Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
16770Sstevel@tonic-gate 	ldap_msgfree( res );
16780Sstevel@tonic-gate 	return( rc );
16790Sstevel@tonic-gate     }
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate     if ( freeit ) {
16820Sstevel@tonic-gate 	ldap_msgfree( res );
16830Sstevel@tonic-gate     }
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate     if ( LDAPTOOL_RESULT_IS_AN_ERROR( lderr )) {
16860Sstevel@tonic-gate 	ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
16870Sstevel@tonic-gate     }
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate     if ( refs != NULL ) {
16900Sstevel@tonic-gate 	ldaptool_print_referrals( refs );
16910Sstevel@tonic-gate 	ldap_value_free( refs );
16920Sstevel@tonic-gate     }
16930Sstevel@tonic-gate 
16940Sstevel@tonic-gate     return( lderr );
16950Sstevel@tonic-gate }
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate /*
16990Sstevel@tonic-gate  * if -M was passed on the command line, create and return a "Manage DSA IT"
17000Sstevel@tonic-gate  * LDAPv3 control.  If not, return NULL.
17010Sstevel@tonic-gate  */
17020Sstevel@tonic-gate LDAPControl *
17030Sstevel@tonic-gate ldaptool_create_manage_dsait_control( void )
17040Sstevel@tonic-gate {
17050Sstevel@tonic-gate     LDAPControl	*ctl;
17060Sstevel@tonic-gate 
17070Sstevel@tonic-gate     if ( !send_manage_dsait_ctrl ) {
17080Sstevel@tonic-gate 	return( NULL );
17090Sstevel@tonic-gate     }
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate     if (( ctl = (LDAPControl *)calloc( 1, sizeof( LDAPControl ))) == NULL ||
17120Sstevel@tonic-gate 	    ( ctl->ldctl_oid = strdup( LDAP_CONTROL_MANAGEDSAIT )) == NULL ) {
17130Sstevel@tonic-gate 	perror( "calloc" );
17140Sstevel@tonic-gate 	exit( LDAP_NO_MEMORY );
17150Sstevel@tonic-gate     }
17160Sstevel@tonic-gate 
17170Sstevel@tonic-gate     ctl->ldctl_iscritical = 1;
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate     return( ctl );
17200Sstevel@tonic-gate }
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate /*
17230Sstevel@tonic-gate  * if -y "dn" was supplied on the command line, create the control
17240Sstevel@tonic-gate  */
17250Sstevel@tonic-gate LDAPControl *
17260Sstevel@tonic-gate ldaptool_create_proxyauth_control( LDAP *ld )
17270Sstevel@tonic-gate {
17280Sstevel@tonic-gate     LDAPControl	*ctl = NULL;
17290Sstevel@tonic-gate     int rc;
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 
17320Sstevel@tonic-gate     if ( !proxyauth_id)
17330Sstevel@tonic-gate 	return( NULL );
17340Sstevel@tonic-gate 
17350Sstevel@tonic-gate     if ( 2 == proxyauth_version ) {
17360Sstevel@tonic-gate 	rc = ldap_create_proxiedauth_control( ld, proxyauth_id, &ctl);
17370Sstevel@tonic-gate     } else {
17380Sstevel@tonic-gate 	rc = ldap_create_proxyauth_control( ld, proxyauth_id, 1, &ctl);
17390Sstevel@tonic-gate     }
17400Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS)
17410Sstevel@tonic-gate     {
17420Sstevel@tonic-gate 	if (ctl)
17430Sstevel@tonic-gate 	    ldap_control_free( ctl);
17440Sstevel@tonic-gate 	return NULL;
17450Sstevel@tonic-gate     }
17460Sstevel@tonic-gate     return( ctl );
17470Sstevel@tonic-gate }
17480Sstevel@tonic-gate 
17490Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD
17500Sstevel@tonic-gate LDAPControl *
17510Sstevel@tonic-gate ldaptool_create_geteffectiveRights_control ( LDAP *ld, const char *authzid,
17520Sstevel@tonic-gate 											const char **attrlist)
17530Sstevel@tonic-gate {
17540Sstevel@tonic-gate     LDAPControl	*ctl = NULL;
17550Sstevel@tonic-gate     int rc;
17560Sstevel@tonic-gate 
17570Sstevel@tonic-gate 	rc = ldap_create_geteffectiveRights_control( ld, authzid, attrlist, 1,
17580Sstevel@tonic-gate 							&ctl);
17590Sstevel@tonic-gate 
17600Sstevel@tonic-gate     if ( rc != LDAP_SUCCESS)
17610Sstevel@tonic-gate     {
17620Sstevel@tonic-gate 		if (ctl)
17630Sstevel@tonic-gate 	    	ldap_control_free( ctl);
17640Sstevel@tonic-gate 		return NULL;
17650Sstevel@tonic-gate     }
17660Sstevel@tonic-gate     return( ctl );
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate #endif	/* SOLARIS_LDAP_CMD */
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate void
17720Sstevel@tonic-gate ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array)
17730Sstevel@tonic-gate {
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate     int i;
17760Sstevel@tonic-gate     for (i=0; i< CONTROL_REQUESTS; i++)
17770Sstevel@tonic-gate     {
17780Sstevel@tonic-gate 	if (*(array + i) == NULL)
17790Sstevel@tonic-gate 	{
17800Sstevel@tonic-gate 	    *(array + i +1) = NULL;
17810Sstevel@tonic-gate 	    *(array + i) = ctrl;
17820Sstevel@tonic-gate 	    return ;
17830Sstevel@tonic-gate 	}
17840Sstevel@tonic-gate     }
17850Sstevel@tonic-gate     fprintf(stderr, gettext("%s: failed to store request control!!!!!!\n"),
17860Sstevel@tonic-gate 	    ldaptool_progname);
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate /*
17900Sstevel@tonic-gate  * Dispose of all controls in array and prepare array for reuse.
17910Sstevel@tonic-gate  */
17920Sstevel@tonic-gate void
17930Sstevel@tonic-gate ldaptool_reset_control_array( LDAPControl **array )
17940Sstevel@tonic-gate {
17950Sstevel@tonic-gate     int		i;
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate     for ( i = 0; i < CONTROL_REQUESTS; i++ ) {
17980Sstevel@tonic-gate 	if ( array[i] != NULL ) {
17990Sstevel@tonic-gate 	    ldap_control_free( array[i] );
18000Sstevel@tonic-gate 	    array[i] = NULL;
18010Sstevel@tonic-gate 	}
18020Sstevel@tonic-gate     }
18030Sstevel@tonic-gate }
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate /*
18060Sstevel@tonic-gate  * This function calculates control value and its length. *value can
18070Sstevel@tonic-gate  * be pointing to plain value, ":b64encoded value" or "<fileurl".
18080Sstevel@tonic-gate  */
18090Sstevel@tonic-gate static int
18100Sstevel@tonic-gate calculate_ctrl_value( const char *value,
18110Sstevel@tonic-gate 	char **ctrl_value, int *vlen)
18120Sstevel@tonic-gate {
18130Sstevel@tonic-gate     int b64;
18140Sstevel@tonic-gate     if (*value == ':') {
18150Sstevel@tonic-gate 	value++;
18160Sstevel@tonic-gate 	b64 = 1;
18170Sstevel@tonic-gate     } else {
18180Sstevel@tonic-gate 	b64 = 0;
18190Sstevel@tonic-gate     }
18200Sstevel@tonic-gate     *ctrl_value = (char *)value;
18210Sstevel@tonic-gate 
18220Sstevel@tonic-gate     if ( b64 ) {
18230Sstevel@tonic-gate 	if (( *vlen = ldif_base64_decode( (char *)value,
18240Sstevel@tonic-gate 		(unsigned char *)value )) < 0 ) {
18250Sstevel@tonic-gate 	    fprintf( stderr,
18260Sstevel@tonic-gate 		gettext("Unable to decode base64 control value \"%s\"\n"), value);
18270Sstevel@tonic-gate 	    return( -1 );
18280Sstevel@tonic-gate 	}
18290Sstevel@tonic-gate     } else {
18300Sstevel@tonic-gate 	*vlen = (int)strlen(*ctrl_value);
18310Sstevel@tonic-gate     }
18320Sstevel@tonic-gate     return( 0 );
18330Sstevel@tonic-gate }
18340Sstevel@tonic-gate 
18350Sstevel@tonic-gate /*
18360Sstevel@tonic-gate  * Parse the optarg from -J option of ldapsearch
18370Sstevel@tonic-gate  * and within LDIFfile for ldapmodify. Take ctrl_arg
18380Sstevel@tonic-gate  * (the whole string) and divide it into oid, criticality
18390Sstevel@tonic-gate  * and value. This function breaks down original ctrl_arg
18400Sstevel@tonic-gate  * with '\0' in places. Also, calculate length of valuestring.
18410Sstevel@tonic-gate  */
18420Sstevel@tonic-gate int
18430Sstevel@tonic-gate ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep,
18440Sstevel@tonic-gate 		char **ctrl_oid, int *ctrl_criticality,
18450Sstevel@tonic-gate 		char **ctrl_value, int *vlen)
18460Sstevel@tonic-gate {
18470Sstevel@tonic-gate     char *s, *p;
18480Sstevel@tonic-gate     int strict;
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate     /* Initialize passed variables with default values */
18510Sstevel@tonic-gate     *ctrl_oid = *ctrl_value = NULL;
18520Sstevel@tonic-gate     *ctrl_criticality = 0;
18530Sstevel@tonic-gate     *vlen = 0;
18540Sstevel@tonic-gate 
18550Sstevel@tonic-gate     strict = (sep == ' ' ? 1 : 0);
18560Sstevel@tonic-gate     if(!(s=strchr(ctrl_arg, sep))) {
18570Sstevel@tonic-gate 	/* Possible values of ctrl_arg are
18580Sstevel@tonic-gate 	 * oid[:value|::b64value|:<fileurl] within LDIF, i.e. sep=' '
18590Sstevel@tonic-gate 	 * oid from command line option, i.e. sep=':'
18600Sstevel@tonic-gate 	 */
18610Sstevel@tonic-gate 	if (sep == ' ') {
18620Sstevel@tonic-gate 	    if (!(s=strchr(ctrl_arg, ':'))) {
18630Sstevel@tonic-gate 		*ctrl_oid = ctrl_arg;
18640Sstevel@tonic-gate 	    }
18650Sstevel@tonic-gate 	    else {
18660Sstevel@tonic-gate 		/* ctrl_arg is of oid:[value|:b64value|<fileurl]
18670Sstevel@tonic-gate 		 * form in the LDIF record. So, grab the oid and then
18680Sstevel@tonic-gate 		 * jump to continue the parsing of ctrl_arg.
18690Sstevel@tonic-gate 		 * 's' is pointing just after oid ends.
18700Sstevel@tonic-gate 		 */
18710Sstevel@tonic-gate 		*s++ = '\0';
18720Sstevel@tonic-gate 		*ctrl_oid = ctrl_arg;
18730Sstevel@tonic-gate 		return (calculate_ctrl_value( s, ctrl_value, vlen ));
18740Sstevel@tonic-gate 	    }
18750Sstevel@tonic-gate 	} else {
18760Sstevel@tonic-gate 		/* oid - from command line option, i.e. sep=':' */
18770Sstevel@tonic-gate 		*ctrl_oid = ctrl_arg;
18780Sstevel@tonic-gate 	}
18790Sstevel@tonic-gate     }
18800Sstevel@tonic-gate     else {
18810Sstevel@tonic-gate 	/* Possible values of ctrl_arg are
18820Sstevel@tonic-gate 	 * oid:criticality[:value|::b64value|:<fileurl] - command line
18830Sstevel@tonic-gate 	 * oid criticality[:value|::b64value|:<fileurl] - LDIF
18840Sstevel@tonic-gate 	 * And 's' is pointing just after oid ends.
18850Sstevel@tonic-gate 	 */
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 	if (*(s+1) == '\0') {
18880Sstevel@tonic-gate 	    fprintf( stderr, gettext("missing value\n") );
18890Sstevel@tonic-gate 	    return( -1 );
18900Sstevel@tonic-gate 	}
18910Sstevel@tonic-gate 	*s = '\0';
18920Sstevel@tonic-gate 	*ctrl_oid = ctrl_arg;
18930Sstevel@tonic-gate 	p = ++s;
18940Sstevel@tonic-gate 	if(!(s=strchr(p, ':'))) {
18950Sstevel@tonic-gate 	    if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
18960Sstevel@tonic-gate 			== -1 ) {
18970Sstevel@tonic-gate 		fprintf( stderr, gettext("Invalid criticality value\n") );
18980Sstevel@tonic-gate 		return( -1 );
18990Sstevel@tonic-gate 	    }
19000Sstevel@tonic-gate 	}
19010Sstevel@tonic-gate 	else {
19020Sstevel@tonic-gate 	    if (*(s+1) == '\0') {
19030Sstevel@tonic-gate 	        fprintf( stderr, gettext("missing value\n") );
19040Sstevel@tonic-gate 	        return ( -1 );
19050Sstevel@tonic-gate 	    }
19060Sstevel@tonic-gate 	    *s++ = '\0';
19070Sstevel@tonic-gate             if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
19080Sstevel@tonic-gate 			== -1 ) {
19090Sstevel@tonic-gate 		fprintf( stderr, gettext("Invalid criticality value\n") );
19100Sstevel@tonic-gate 		return ( -1 );
19110Sstevel@tonic-gate 	    }
19120Sstevel@tonic-gate 	    return (calculate_ctrl_value( s, ctrl_value, vlen ));
19130Sstevel@tonic-gate 	}
19140Sstevel@tonic-gate     }
19150Sstevel@tonic-gate 
19160Sstevel@tonic-gate     return( 0 );
19170Sstevel@tonic-gate }
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate /*
19210Sstevel@tonic-gate  * callback function for LDAP bind credentials
19220Sstevel@tonic-gate  */
19230Sstevel@tonic-gate static int
19240Sstevel@tonic-gate LDAP_CALL
19250Sstevel@tonic-gate LDAP_CALLBACK
19260Sstevel@tonic-gate get_rebind_credentials( LDAP *ld, char **whop, char **credp,
19270Sstevel@tonic-gate         int *methodp, int freeit, void* arg )
19280Sstevel@tonic-gate {
19290Sstevel@tonic-gate     if ( !freeit ) {
19300Sstevel@tonic-gate 	*whop = binddn;
19310Sstevel@tonic-gate 	*credp = passwd;
19320Sstevel@tonic-gate 	*methodp = LDAP_AUTH_SIMPLE;
19330Sstevel@tonic-gate     }
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate     return( LDAP_SUCCESS );
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate 
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate /*
19400Sstevel@tonic-gate  * return pointer to pathname to temporary directory.
19410Sstevel@tonic-gate  * First we see if the environment variable "TEMP" is set and use it.
19420Sstevel@tonic-gate  * Then we see if the environment variable "TMP" is set and use it.
19430Sstevel@tonic-gate  * If this fails, we use "/tmp" on UNIX and fail on Windows.
19440Sstevel@tonic-gate  */
19450Sstevel@tonic-gate char *
19460Sstevel@tonic-gate ldaptool_get_tmp_dir( void )
19470Sstevel@tonic-gate {
19480Sstevel@tonic-gate     char	*p;
19490Sstevel@tonic-gate     int		offset;
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate     if (( p = getenv( "TEMP" )) == NULL && ( p = getenv( "TMP" )) == NULL ) {
19520Sstevel@tonic-gate #ifdef _WINDOWS
19530Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: please set the TEMP environment variable.\n"),
19540Sstevel@tonic-gate 		ldaptool_progname );
19550Sstevel@tonic-gate 	exit( LDAP_LOCAL_ERROR );
19560Sstevel@tonic-gate #else
19570Sstevel@tonic-gate 	return( "/tmp" );	/* last resort on UNIX */
19580Sstevel@tonic-gate #endif
19590Sstevel@tonic-gate     }
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate     /*
19620Sstevel@tonic-gate      * remove trailing slash if present
19630Sstevel@tonic-gate      */
19640Sstevel@tonic-gate     offset = strlen( p ) - 1;
19650Sstevel@tonic-gate     if ( p[offset] == '/'
19660Sstevel@tonic-gate #ifdef _WINDOWS
19670Sstevel@tonic-gate 	    || p[offset] == '\\'
19680Sstevel@tonic-gate #endif
19690Sstevel@tonic-gate 	    ) {
19700Sstevel@tonic-gate 	if (( p = strdup( p )) == NULL ) {
19710Sstevel@tonic-gate 	    perror( "strdup" );
19720Sstevel@tonic-gate 	    exit( LDAP_NO_MEMORY );
19730Sstevel@tonic-gate 	}
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 	p[offset] = '\0';
19760Sstevel@tonic-gate     }
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate     return( p );
19790Sstevel@tonic-gate }
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate 
19820Sstevel@tonic-gate int
19830Sstevel@tonic-gate ldaptool_berval_is_ascii( const struct berval *bvp )
19840Sstevel@tonic-gate {
19850Sstevel@tonic-gate     unsigned long	j;
19860Sstevel@tonic-gate     int			is_ascii = 1;	 /* optimistic */
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate     for ( j = 0; j < bvp->bv_len; ++j ) {
19890Sstevel@tonic-gate 	if ( !isascii( bvp->bv_val[ j ] )) {
19900Sstevel@tonic-gate 	    is_ascii = 0;
19910Sstevel@tonic-gate 	    break;
19920Sstevel@tonic-gate 	}
19930Sstevel@tonic-gate     }
19940Sstevel@tonic-gate 
19950Sstevel@tonic-gate     return( is_ascii );
19960Sstevel@tonic-gate }
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate #ifdef LDAP_DEBUG_MEMORY
20000Sstevel@tonic-gate #define LDAPTOOL_ALLOC_FREED	0xF001
20010Sstevel@tonic-gate #define LDAPTOOL_ALLOC_INUSE	0xF002
20020Sstevel@tonic-gate 
20030Sstevel@tonic-gate static void *
20040Sstevel@tonic-gate ldaptool_debug_alloc( void *ptr, size_t size )
20050Sstevel@tonic-gate {
20060Sstevel@tonic-gate     int		*statusp;
20070Sstevel@tonic-gate     void	*systemptr;
20080Sstevel@tonic-gate 
20090Sstevel@tonic-gate     if ( ptr == NULL ) {
20100Sstevel@tonic-gate 	systemptr = NULL;
20110Sstevel@tonic-gate     } else {
20120Sstevel@tonic-gate 	systemptr = (void *)((char *)ptr - sizeof(int));
20130Sstevel@tonic-gate     }
20140Sstevel@tonic-gate 
20150Sstevel@tonic-gate     if (( statusp = (int *)realloc( systemptr, size + sizeof(int))) == NULL ) {
20160Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: realloc( 0x%x, %d) failed\n"),
20170Sstevel@tonic-gate 		ldaptool_progname, systemptr, size );
20180Sstevel@tonic-gate 	return( NULL );
20190Sstevel@tonic-gate     }
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate     *statusp = LDAPTOOL_ALLOC_INUSE;
20220Sstevel@tonic-gate 
20230Sstevel@tonic-gate     return( (char *)statusp + sizeof(int));
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 
20270Sstevel@tonic-gate static void *
20280Sstevel@tonic-gate ldaptool_debug_realloc( void *ptr, size_t size )
20290Sstevel@tonic-gate {
20300Sstevel@tonic-gate     void	*p;
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20330Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: => realloc( 0x%x, %d )\n"),
20340Sstevel@tonic-gate 		ldaptool_progname, ptr, size );
20350Sstevel@tonic-gate     }
20360Sstevel@tonic-gate 
20370Sstevel@tonic-gate     p = ldaptool_debug_alloc( ptr, size );
20380Sstevel@tonic-gate 
20390Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20400Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: 0x%x <= realloc()\n"), ldaptool_progname, p );
20410Sstevel@tonic-gate     }
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate     return( p );
20440Sstevel@tonic-gate }
20450Sstevel@tonic-gate 
20460Sstevel@tonic-gate 
20470Sstevel@tonic-gate static void *
20480Sstevel@tonic-gate ldaptool_debug_malloc( size_t size )
20490Sstevel@tonic-gate {
20500Sstevel@tonic-gate     void	*p;
20510Sstevel@tonic-gate 
20520Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20530Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: => malloc( %d)\n"), ldaptool_progname, size );
20540Sstevel@tonic-gate     }
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate     p = ldaptool_debug_alloc( NULL, size );
20570Sstevel@tonic-gate 
20580Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20590Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: 0x%x <= malloc()\n"), ldaptool_progname, p );
20600Sstevel@tonic-gate     }
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate     return( p );
20630Sstevel@tonic-gate }
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 
20660Sstevel@tonic-gate static void *
20670Sstevel@tonic-gate ldaptool_debug_calloc( size_t nelem, size_t elsize )
20680Sstevel@tonic-gate {
20690Sstevel@tonic-gate     void	*p;
20700Sstevel@tonic-gate 
20710Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20720Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: => calloc( %d, %d )\n"),
20730Sstevel@tonic-gate 		ldaptool_progname, nelem, elsize );
20740Sstevel@tonic-gate     }
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate     if (( p = ldaptool_debug_alloc( NULL, nelem * elsize )) != NULL ) {
20770Sstevel@tonic-gate 	memset( p, 0, nelem * elsize );
20780Sstevel@tonic-gate     }
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20810Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: 0x%x <= calloc()\n"), ldaptool_progname, p );
20820Sstevel@tonic-gate     }
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate     return( p );
20850Sstevel@tonic-gate }
20860Sstevel@tonic-gate 
20870Sstevel@tonic-gate 
20880Sstevel@tonic-gate static void
20890Sstevel@tonic-gate ldaptool_debug_free( void *ptr )
20900Sstevel@tonic-gate {
20910Sstevel@tonic-gate     int		*statusp = (int *)((char *)ptr - sizeof(int));
20920Sstevel@tonic-gate 
20930Sstevel@tonic-gate     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
20940Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: => free( 0x%x )\n"), ldaptool_progname, ptr );
20950Sstevel@tonic-gate     }
20960Sstevel@tonic-gate 
20970Sstevel@tonic-gate     if ( ptr == NULL ) {
20980Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: bad free( 0x0 ) attempted (NULL pointer)\n"),
20990Sstevel@tonic-gate 		ldaptool_progname );
21000Sstevel@tonic-gate     } else if ( *statusp != LDAPTOOL_ALLOC_INUSE ) {
21010Sstevel@tonic-gate 	fprintf( stderr, gettext("%s: bad free( 0x%x ) attempted"
21020Sstevel@tonic-gate 		" (block not in use; status is %d)\n"),
21030Sstevel@tonic-gate 		ldaptool_progname, ptr, *statusp );
21040Sstevel@tonic-gate     } else {
21050Sstevel@tonic-gate 	*statusp = LDAPTOOL_ALLOC_FREED;
21060Sstevel@tonic-gate 	free( statusp );
21070Sstevel@tonic-gate     }
21080Sstevel@tonic-gate }
21090Sstevel@tonic-gate #endif /* LDAP_DEBUG_MEMORY */
21100Sstevel@tonic-gate 
21110Sstevel@tonic-gate 
21120Sstevel@tonic-gate #if defined(NET_SSL)
21130Sstevel@tonic-gate /*
21140Sstevel@tonic-gate  * Derive key database path from certificate database path and return a
21150Sstevel@tonic-gate  * malloc'd string.
21160Sstevel@tonic-gate  *
21170Sstevel@tonic-gate  * We just return an exact copy of "certdbpath" unless it ends in "cert.db",
21180Sstevel@tonic-gate  * "cert5.db", or "cert7.db".  In those cases we strip off everything from
21190Sstevel@tonic-gate  * "cert" on and append "key.db", "key5.db", or "key3.db" as appropriate.
21200Sstevel@tonic-gate  * Strangely enough cert7.db and key3.db go together.
21210Sstevel@tonic-gate  */
21220Sstevel@tonic-gate static char *
21230Sstevel@tonic-gate certpath2keypath( char *certdbpath )
21240Sstevel@tonic-gate {
21250Sstevel@tonic-gate     char	*keydbpath, *appendstr;
21260Sstevel@tonic-gate     int		len, striplen;
21270Sstevel@tonic-gate 
21280Sstevel@tonic-gate     if ( certdbpath == NULL ) {
21290Sstevel@tonic-gate 	return( NULL );
21300Sstevel@tonic-gate     }
21310Sstevel@tonic-gate 
21320Sstevel@tonic-gate     if (( keydbpath = strdup( certdbpath )) == NULL ) {
21330Sstevel@tonic-gate 	perror( "strdup" );
21340Sstevel@tonic-gate 	exit( LDAP_NO_MEMORY );
21350Sstevel@tonic-gate     }
21360Sstevel@tonic-gate 
21370Sstevel@tonic-gate     len = strlen( keydbpath );
21380Sstevel@tonic-gate     if ( len > 7 &&
21390Sstevel@tonic-gate 	    strcasecmp( "cert.db", keydbpath + len - 7 ) == 0 ) {
21400Sstevel@tonic-gate 	striplen = 7;
21410Sstevel@tonic-gate 	appendstr = "key.db";
21420Sstevel@tonic-gate 
21430Sstevel@tonic-gate     } else if ( len > 8 &&
21440Sstevel@tonic-gate 	    strcasecmp( "cert5.db", keydbpath + len - 8 ) == 0 ) {
21450Sstevel@tonic-gate 	striplen = 8;
21460Sstevel@tonic-gate 	appendstr = "key5.db";
21470Sstevel@tonic-gate     } else if ( len > 8 &&
21480Sstevel@tonic-gate 	    strcasecmp( "cert7.db", keydbpath + len - 8 ) == 0 ) {
21490Sstevel@tonic-gate 	striplen = 8;
21500Sstevel@tonic-gate 	appendstr = "key3.db";
21510Sstevel@tonic-gate     } else {
21520Sstevel@tonic-gate 	striplen = 0;
21530Sstevel@tonic-gate     }
21540Sstevel@tonic-gate 
21550Sstevel@tonic-gate     if ( striplen > 0 ) {
21560Sstevel@tonic-gate 	/*
21570Sstevel@tonic-gate 	 * The following code assumes that strlen( appendstr ) < striplen!
21580Sstevel@tonic-gate 	 */
21590Sstevel@tonic-gate 	strcpy( keydbpath + len - striplen, appendstr );
21600Sstevel@tonic-gate     }
21610Sstevel@tonic-gate 
21620Sstevel@tonic-gate     return( keydbpath );
21630Sstevel@tonic-gate }
21640Sstevel@tonic-gate 
21650Sstevel@tonic-gate #ifdef LDAP_TOOL_PKCS11
21660Sstevel@tonic-gate static
21670Sstevel@tonic-gate char *
21680Sstevel@tonic-gate buildTokenCertName( const char *tokenName, const char *certName)
21690Sstevel@tonic-gate {
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate     int tokenlen = strlen(tokenName);
21720Sstevel@tonic-gate     int len = tokenlen + strlen(certName) +2;
21730Sstevel@tonic-gate     char *result;
21740Sstevel@tonic-gate 
21750Sstevel@tonic-gate     if (( result = malloc( len )) != NULL) {
21760Sstevel@tonic-gate 	strcpy(result, tokenName);
21770Sstevel@tonic-gate 	*(result+tokenlen) = ':';
21780Sstevel@tonic-gate 	++tokenlen;
21790Sstevel@tonic-gate 	strcpy(result+tokenlen, certName);
21800Sstevel@tonic-gate     } else {
21810Sstevel@tonic-gate 	perror("malloc");
21820Sstevel@tonic-gate 	exit( LDAP_NO_MEMORY );
21830Sstevel@tonic-gate     }
21840Sstevel@tonic-gate     return result;
21850Sstevel@tonic-gate }
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 
21880Sstevel@tonic-gate 
21890Sstevel@tonic-gate static
21900Sstevel@tonic-gate int
21910Sstevel@tonic-gate ldaptool_getcertpath( void *context, char **certlocp )
21920Sstevel@tonic-gate {
21930Sstevel@tonic-gate 
21940Sstevel@tonic-gate     *certlocp = ssl_certdbpath;
21950Sstevel@tonic-gate     if ( ldaptool_verbose ) {
21960Sstevel@tonic-gate 	if (ssl_certdbpath)
21970Sstevel@tonic-gate 	{
21980Sstevel@tonic-gate 	    printf(gettext("ldaptool_getcertpath -- %s\n"), ssl_certdbpath );
21990Sstevel@tonic-gate 	}
22000Sstevel@tonic-gate 	else
22010Sstevel@tonic-gate 	{
22020Sstevel@tonic-gate 	    printf(gettext("ldaptool_getcertpath -- (null)\n"));
22030Sstevel@tonic-gate 	}
22040Sstevel@tonic-gate 
22050Sstevel@tonic-gate     }
22060Sstevel@tonic-gate     return LDAP_SUCCESS;
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate 
22090Sstevel@tonic-gate int
22100Sstevel@tonic-gate ldaptool_getcertname( void *context, char **certnamep )
22110Sstevel@tonic-gate {
22120Sstevel@tonic-gate 
22130Sstevel@tonic-gate    *certnamep = ssl_certname;
22140Sstevel@tonic-gate     if ( ldaptool_verbose ) {
22150Sstevel@tonic-gate 	if (ssl_certname)
22160Sstevel@tonic-gate 	{
22170Sstevel@tonic-gate 	    printf(gettext("ldaptool_getcertname -- %s\n"), *certnamep);
22180Sstevel@tonic-gate 	}
22190Sstevel@tonic-gate 	else
22200Sstevel@tonic-gate 	{
22210Sstevel@tonic-gate 	    printf(gettext("ldaptool_getcertname -- (null)\n"));
22220Sstevel@tonic-gate 	}
22230Sstevel@tonic-gate     }
22240Sstevel@tonic-gate     return LDAP_SUCCESS;
22250Sstevel@tonic-gate }
22260Sstevel@tonic-gate 
22270Sstevel@tonic-gate int
22280Sstevel@tonic-gate ldaptool_getkeypath(void *context, char **keylocp )
22290Sstevel@tonic-gate {
22300Sstevel@tonic-gate     *keylocp = ssl_keydbpath;
22310Sstevel@tonic-gate     if ( ldaptool_verbose ) {
22320Sstevel@tonic-gate 	if (ssl_keydbpath)
22330Sstevel@tonic-gate 	{
22340Sstevel@tonic-gate 	    printf(gettext("ldaptool_getkeypath -- %s\n"),*keylocp);
22350Sstevel@tonic-gate 	}
22360Sstevel@tonic-gate 	else
22370Sstevel@tonic-gate 	{
22380Sstevel@tonic-gate 	    printf(gettext("ldaptool_getkeypath -- (null)\n"));
22390Sstevel@tonic-gate 	}
22400Sstevel@tonic-gate     }
22410Sstevel@tonic-gate 
22420Sstevel@tonic-gate     return LDAP_SUCCESS;
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate 
22450Sstevel@tonic-gate int
22460Sstevel@tonic-gate ldaptool_gettokenname( void *context, char **tokennamep )
22470Sstevel@tonic-gate {
22480Sstevel@tonic-gate 
22490Sstevel@tonic-gate     *tokennamep = pkcs_token;
22500Sstevel@tonic-gate     if ( ldaptool_verbose ) {
22510Sstevel@tonic-gate 	if (pkcs_token)
22520Sstevel@tonic-gate 	{
22530Sstevel@tonic-gate 	    printf(gettext("ldaptool_gettokenname -- %s\n"),*tokennamep);
22540Sstevel@tonic-gate 	}
22550Sstevel@tonic-gate 	else
22560Sstevel@tonic-gate 	{
22570Sstevel@tonic-gate 	    printf(gettext("ldaptool_gettokenname -- (null)\n"));
22580Sstevel@tonic-gate 	}
22590Sstevel@tonic-gate     }
22600Sstevel@tonic-gate 
22610Sstevel@tonic-gate     return LDAP_SUCCESS;
22620Sstevel@tonic-gate }
22630Sstevel@tonic-gate int
22640Sstevel@tonic-gate ldaptool_gettokenpin( void *context, const char *tokennamep, char **tokenpinp)
22650Sstevel@tonic-gate {
22660Sstevel@tonic-gate 
22670Sstevel@tonic-gate #if 0
22680Sstevel@tonic-gate   char *localtoken;
22690Sstevel@tonic-gate #endif
22700Sstevel@tonic-gate 
22710Sstevel@tonic-gate /* XXXceb this stuff is removed for the time being.
22720Sstevel@tonic-gate  * This function should return the pin from ssl_password
22730Sstevel@tonic-gate  */
22740Sstevel@tonic-gate 
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate   *tokenpinp = ssl_passwd;
22770Sstevel@tonic-gate   return LDAP_SUCCESS;
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate #if 0
22800Sstevel@tonic-gate 
22810Sstevel@tonic-gate   ldaptool_gettokenname( NULL, &localtoken);
22820Sstevel@tonic-gate 
22830Sstevel@tonic-gate   if (strcmp( localtoken, tokennamep))
22840Sstevel@tonic-gate 
22850Sstevel@tonic-gate       *tokenpinp = pkcs_pin;
22860Sstevel@tonic-gate    else
22870Sstevel@tonic-gate       *tokenpinp = NULL;
22880Sstevel@tonic-gate 
22890Sstevel@tonic-gate     if ( ldaptool_verbose ) {
22900Sstevel@tonic-gate 	if (pkcs_pin)
22910Sstevel@tonic-gate 	{
22920Sstevel@tonic-gate 	    printf(gettext("ldaptool_getokenpin --%s\n"), tokenpinp);
22930Sstevel@tonic-gate 	}
22940Sstevel@tonic-gate 	else
22950Sstevel@tonic-gate 	{
22960Sstevel@tonic-gate 	    printf(gettext("ldaptool_getokenpin -- (null)\n"));
22970Sstevel@tonic-gate 	}
22980Sstevel@tonic-gate     }
22990Sstevel@tonic-gate     return LDAP_SUCCESS;
23000Sstevel@tonic-gate #endif
23010Sstevel@tonic-gate }
23020Sstevel@tonic-gate 
23030Sstevel@tonic-gate int
23040Sstevel@tonic-gate ldaptool_getmodpath( void *context, char **modulep )
23050Sstevel@tonic-gate {
23060Sstevel@tonic-gate     *modulep = ssl_secmodpath;
23070Sstevel@tonic-gate     if ( ldaptool_verbose ) {
23080Sstevel@tonic-gate 	if (ssl_secmodpath)
23090Sstevel@tonic-gate 	{
23100Sstevel@tonic-gate 	    printf(gettext("ldaptool_getmodpath -- %s\n"), *modulep);
23110Sstevel@tonic-gate 	}
23120Sstevel@tonic-gate 	else
23130Sstevel@tonic-gate 	{
23140Sstevel@tonic-gate 	    printf(gettext("ldaptool_getmodpath -- (null)\n"));
23150Sstevel@tonic-gate 	}
23160Sstevel@tonic-gate     }
23170Sstevel@tonic-gate 
23180Sstevel@tonic-gate     return LDAP_SUCCESS;
23190Sstevel@tonic-gate }
23200Sstevel@tonic-gate 
23210Sstevel@tonic-gate int
23220Sstevel@tonic-gate ldaptool_getdonglefilename( void *context, char **filename )
23230Sstevel@tonic-gate {
23240Sstevel@tonic-gate     *filename = ssl_donglefile;
23250Sstevel@tonic-gate     if ( ldaptool_verbose ) {
23260Sstevel@tonic-gate 	if (ssl_donglefile)
23270Sstevel@tonic-gate 	{
23280Sstevel@tonic-gate 	    printf(gettext("ldaptool_getdonglefilename -- %s\n"), *filename);
23290Sstevel@tonic-gate 	}
23300Sstevel@tonic-gate 	else
23310Sstevel@tonic-gate 	{
23320Sstevel@tonic-gate 	    printf(gettext("ldaptool_getdonglefilename -- (null)\n"));
23330Sstevel@tonic-gate 	}
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate     }
23360Sstevel@tonic-gate 
23370Sstevel@tonic-gate     return LDAP_SUCCESS;
23380Sstevel@tonic-gate }
23390Sstevel@tonic-gate 
23400Sstevel@tonic-gate static int
23410Sstevel@tonic-gate ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns)
23420Sstevel@tonic-gate {
23430Sstevel@tonic-gate   pfns->pkcs_getcertpath = (int (*)(void *, char **))ldaptool_getcertpath;
23440Sstevel@tonic-gate   pfns->pkcs_getcertname =  (int (*)(void *, char **))ldaptool_getcertname;
23450Sstevel@tonic-gate   pfns->pkcs_getkeypath =  (int (*)(void *, char **)) ldaptool_getkeypath;
23460Sstevel@tonic-gate   pfns->pkcs_getmodpath =  (int (*)(void *, char **)) ldaptool_getmodpath;
23470Sstevel@tonic-gate   pfns->pkcs_getpin =  (int (*)(void *, const char*, char **)) ldaptool_gettokenpin;
23480Sstevel@tonic-gate   pfns->pkcs_gettokenname =  (int (*)(void *, char **)) ldaptool_gettokenname;
23490Sstevel@tonic-gate   pfns->pkcs_getdonglefilename =  (int (*)(void *, char **)) ldaptool_getdonglefilename;
23500Sstevel@tonic-gate   pfns->local_structure_id=PKCS_STRUCTURE_ID;
23510Sstevel@tonic-gate   return LDAP_SUCCESS;
23520Sstevel@tonic-gate }
23530Sstevel@tonic-gate 
23540Sstevel@tonic-gate 
23550Sstevel@tonic-gate 
23560Sstevel@tonic-gate #ifdef FORTEZZA
23570Sstevel@tonic-gate static int
23580Sstevel@tonic-gate ldaptool_fortezza_init( int exit_on_error )
23590Sstevel@tonic-gate {
23600Sstevel@tonic-gate     int		rc, errcode;
23610Sstevel@tonic-gate 
23620Sstevel@tonic-gate     if ( fortezza_personality == NULL && fortezza_cardmask == 0 ) { /* no FORTEZZA desired */
23630Sstevel@tonic-gate 	SSL_EnableGroup( SSL_GroupFortezza, DSFalse );	/* disable FORTEZZA */
23640Sstevel@tonic-gate 	return( 0 );
23650Sstevel@tonic-gate     }
23660Sstevel@tonic-gate 
23670Sstevel@tonic-gate     if (( rc = FortezzaConfigureServer( ldaptool_fortezza_getpin, fortezza_cardmask,
23680Sstevel@tonic-gate 	    fortezza_personality, ldaptool_fortezza_alert, NULL, &errcode,
23690Sstevel@tonic-gate 	    fortezza_krlfile )) < 0 ) {
23700Sstevel@tonic-gate 	fprintf( stderr,
23710Sstevel@tonic-gate 		"%s: FORTEZZA initialization failed (error %d - %s)\n",
23720Sstevel@tonic-gate 		ldaptool_progname, errcode,
23730Sstevel@tonic-gate 		ldaptool_fortezza_err2string( errcode ));
23740Sstevel@tonic-gate 	if ( exit_on_error ) {
23750Sstevel@tonic-gate 	    exit( LDAP_LOCAL_ERROR );
23760Sstevel@tonic-gate 	}
23770Sstevel@tonic-gate 
23780Sstevel@tonic-gate 	SSL_EnableGroup( SSL_GroupFortezza, DSFalse );	/* disable FORTEZZA */
23790Sstevel@tonic-gate 	return( -1 );
23800Sstevel@tonic-gate     }
23810Sstevel@tonic-gate 
23820Sstevel@tonic-gate     SSL_EnableGroup( SSL_GroupFortezza, DSTrue );	/* enable FORTEZZA */
23830Sstevel@tonic-gate     return( 0 );
23840Sstevel@tonic-gate }
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate 
23870Sstevel@tonic-gate static int
23880Sstevel@tonic-gate ldaptool_fortezza_alert( void *arg, PRBool onOpen, char *string,
23890Sstevel@tonic-gate 	int value1, void *value2 )
23900Sstevel@tonic-gate {
23910Sstevel@tonic-gate     fprintf( stderr, "%s: FORTEZZA alert: ", ldaptool_progname );
23920Sstevel@tonic-gate     fprintf( stderr, string, value1, value2 );
23930Sstevel@tonic-gate     fprintf( stderr, "\n" );
23940Sstevel@tonic-gate     return( 1 );
23950Sstevel@tonic-gate }
23960Sstevel@tonic-gate 
23970Sstevel@tonic-gate 
23980Sstevel@tonic-gate static void *
23990Sstevel@tonic-gate ldaptool_fortezza_getpin( char **passwordp )
24000Sstevel@tonic-gate {
24010Sstevel@tonic-gate     *passwordp = fortezza_pin;
24020Sstevel@tonic-gate     return( *passwordp );
24030Sstevel@tonic-gate }
24040Sstevel@tonic-gate 
24050Sstevel@tonic-gate 
24060Sstevel@tonic-gate /*
24070Sstevel@tonic-gate  * convert a Fortezza error code (as returned by FortezzaConfigureServer()
24080Sstevel@tonic-gate  * into a human-readable string.
24090Sstevel@tonic-gate  *
24100Sstevel@tonic-gate  * Error strings are intentionally similar to those found in
24110Sstevel@tonic-gate  * ns/netsite/lib/libadmin/httpcon.c
24120Sstevel@tonic-gate  */
24130Sstevel@tonic-gate static char *
24140Sstevel@tonic-gate ldaptool_fortezza_err2string( int err )
24150Sstevel@tonic-gate {
24160Sstevel@tonic-gate     char	*s;
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate     switch( err ) {
24190Sstevel@tonic-gate     case FORTEZZA_BADPASSWD:
24200Sstevel@tonic-gate 	s = "invalid pin number";
24210Sstevel@tonic-gate 	break;
24220Sstevel@tonic-gate     case FORTEZZA_BADCARD:
24230Sstevel@tonic-gate 	s = "bad or missing card";
24240Sstevel@tonic-gate 	break;
24250Sstevel@tonic-gate     case FORTEZZA_MISSING_KRL:
24260Sstevel@tonic-gate 	s = "bad or missing compromised key list";
24270Sstevel@tonic-gate 	break;
24280Sstevel@tonic-gate     case FORTEZZA_CERT_INIT_ERROR:
24290Sstevel@tonic-gate 	s = "unable to initialize certificate cache.  either a cert on "
24300Sstevel@tonic-gate 		"the card is bad, or an old FORTEZZA certificate is in a"
24310Sstevel@tonic-gate 		 "readonly database";
24320Sstevel@tonic-gate 	break;
24330Sstevel@tonic-gate     case FORTEZZA_EXPIRED_CERT:
24340Sstevel@tonic-gate 	s = "unable to verify certificate";
24350Sstevel@tonic-gate 	break;
24360Sstevel@tonic-gate     default:
24370Sstevel@tonic-gate 	s = "unknown error";
24380Sstevel@tonic-gate     }
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate     return( s );
24410Sstevel@tonic-gate }
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate #endif /* FORTEZZA */
24440Sstevel@tonic-gate #endif /* LDAP_TOOL_PKCS11 */
24450Sstevel@tonic-gate #endif /* NET_SSL */
24460Sstevel@tonic-gate 
24470Sstevel@tonic-gate int
24480Sstevel@tonic-gate ldaptool_boolean_str2value ( const char *ptr, int strict )
24490Sstevel@tonic-gate {
24500Sstevel@tonic-gate     if (strict) {
24510Sstevel@tonic-gate 	if ( !(strcasecmp(ptr, "true"))) {
24520Sstevel@tonic-gate 	    return 1;
24530Sstevel@tonic-gate 	}
24540Sstevel@tonic-gate 	else if ( !(strcasecmp(ptr, "false"))) {
24550Sstevel@tonic-gate 	    return 0;
24560Sstevel@tonic-gate 	}
24570Sstevel@tonic-gate 	else {
24580Sstevel@tonic-gate 	    return (-1);
24590Sstevel@tonic-gate 	}
24600Sstevel@tonic-gate     }
24610Sstevel@tonic-gate     else {
24620Sstevel@tonic-gate 	if ( !(strcasecmp(ptr, "true")) ||
24630Sstevel@tonic-gate 	     !(strcasecmp(ptr, "t")) ||
24640Sstevel@tonic-gate 	     !(strcmp(ptr, "1")) ) {
24650Sstevel@tonic-gate 		return (1);
24660Sstevel@tonic-gate 	}
24670Sstevel@tonic-gate 	else if ( !(strcasecmp(ptr, "false")) ||
24680Sstevel@tonic-gate 	     !(strcasecmp(ptr, "f")) ||
24690Sstevel@tonic-gate 	     !(strcmp(ptr, "0")) ) {
24700Sstevel@tonic-gate 	    	return (0);
24710Sstevel@tonic-gate 	}
24720Sstevel@tonic-gate 	else {
24730Sstevel@tonic-gate 	    return (-1);
24740Sstevel@tonic-gate 	}
24750Sstevel@tonic-gate     }
24760Sstevel@tonic-gate }
24770Sstevel@tonic-gate 
24780Sstevel@tonic-gate FILE *
24790Sstevel@tonic-gate ldaptool_open_file(const char *filename, const char *mode)
24800Sstevel@tonic-gate {
24810Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
24820Sstevel@tonic-gate 	return fopen64(filename, mode);
24830Sstevel@tonic-gate #else
24840Sstevel@tonic-gate 	return fopen(filename, mode);
24850Sstevel@tonic-gate #endif
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate #ifdef later
24890Sstevel@tonic-gate /* Functions for list in ldapdelete.c */
24900Sstevel@tonic-gate 
24910Sstevel@tonic-gate void L_Init(Head *list)
24920Sstevel@tonic-gate {
24930Sstevel@tonic-gate     if(list)
24940Sstevel@tonic-gate     {
24950Sstevel@tonic-gate         list->first = NULL;
24960Sstevel@tonic-gate         list->last = NULL;
24970Sstevel@tonic-gate         list->count = 0;
24980Sstevel@tonic-gate     }
24990Sstevel@tonic-gate }
25000Sstevel@tonic-gate 
25010Sstevel@tonic-gate void L_Insert(Element *Node, Head *HeadNode)
25020Sstevel@tonic-gate {
25030Sstevel@tonic-gate     if (!Node || !HeadNode)
25040Sstevel@tonic-gate         return;
25050Sstevel@tonic-gate 
25060Sstevel@tonic-gate     Node->right = NULL;
25070Sstevel@tonic-gate 
25080Sstevel@tonic-gate     if (HeadNode->first == NULL)
25090Sstevel@tonic-gate     {
25100Sstevel@tonic-gate         Node->left= NULL;
25110Sstevel@tonic-gate         HeadNode->last = HeadNode->first = Node;
25120Sstevel@tonic-gate     }
25130Sstevel@tonic-gate     else
25140Sstevel@tonic-gate     {
25150Sstevel@tonic-gate         Node->left = HeadNode->last;
25160Sstevel@tonic-gate         HeadNode->last = Node->left->right = Node;
25170Sstevel@tonic-gate     }
25180Sstevel@tonic-gate     HeadNode->count++;
25190Sstevel@tonic-gate }
25200Sstevel@tonic-gate 
25210Sstevel@tonic-gate void L_Remove(Element *Node, Head *HeadNode)
25220Sstevel@tonic-gate {
25230Sstevel@tonic-gate     Element *traverse = NULL;
25240Sstevel@tonic-gate     Element *prevnode = NULL;
25250Sstevel@tonic-gate 
25260Sstevel@tonic-gate     if(!Node || !HeadNode)
25270Sstevel@tonic-gate         return;
25280Sstevel@tonic-gate 
25290Sstevel@tonic-gate     for(traverse = HeadNode->first; traverse; traverse = traverse->right)
25300Sstevel@tonic-gate     {
25310Sstevel@tonic-gate         if(traverse == Node)
25320Sstevel@tonic-gate         {
25330Sstevel@tonic-gate             if(HeadNode->first == traverse)
25340Sstevel@tonic-gate             {
25350Sstevel@tonic-gate                 HeadNode->first = traverse->right;
25360Sstevel@tonic-gate             }
25370Sstevel@tonic-gate             if(HeadNode->last == traverse)
25380Sstevel@tonic-gate             {
25390Sstevel@tonic-gate                 HeadNode->last = prevnode;
25400Sstevel@tonic-gate             }
25410Sstevel@tonic-gate             traverse = traverse->right;
25420Sstevel@tonic-gate             if(prevnode != NULL)
25430Sstevel@tonic-gate             {
25440Sstevel@tonic-gate                 prevnode->right = traverse;
25450Sstevel@tonic-gate             }
25460Sstevel@tonic-gate             if(traverse != NULL)
25470Sstevel@tonic-gate             {
25480Sstevel@tonic-gate                 traverse->left = prevnode;
25490Sstevel@tonic-gate             }
25500Sstevel@tonic-gate             HeadNode->count--;
25510Sstevel@tonic-gate             return;
25520Sstevel@tonic-gate         }
25530Sstevel@tonic-gate         else /* traverse != node */
25540Sstevel@tonic-gate         {
25550Sstevel@tonic-gate             prevnode = traverse;
25560Sstevel@tonic-gate         }
25570Sstevel@tonic-gate     }
25580Sstevel@tonic-gate }
25590Sstevel@tonic-gate #endif
25600Sstevel@tonic-gate 
25610Sstevel@tonic-gate #ifdef HAVE_SASL_OPTIONS
25620Sstevel@tonic-gate /*
25630Sstevel@tonic-gate  * Function checks for valid args, returns an error if not found
25640Sstevel@tonic-gate  * and sets SASL params from command line
25650Sstevel@tonic-gate  */
25660Sstevel@tonic-gate 
25670Sstevel@tonic-gate static int
25680Sstevel@tonic-gate saslSetParam(char *saslarg)
25690Sstevel@tonic-gate {
25700Sstevel@tonic-gate 	char *attr = NULL;
25710Sstevel@tonic-gate 
25720Sstevel@tonic-gate 	attr = strchr(saslarg, '=');
25730Sstevel@tonic-gate 	if (attr == NULL) {
25740Sstevel@tonic-gate            fprintf( stderr, gettext("Didn't find \"=\" character in %s\n"), saslarg);
25750Sstevel@tonic-gate            return (-1);
25760Sstevel@tonic-gate 	}
25770Sstevel@tonic-gate 	*attr = '\0';
25780Sstevel@tonic-gate 	attr++;
25790Sstevel@tonic-gate 
25800Sstevel@tonic-gate 	if (!strcasecmp(saslarg, "secProp")) {
25810Sstevel@tonic-gate 	     if ( sasl_secprops != NULL ) {
25820Sstevel@tonic-gate                 fprintf( stderr, gettext("secProp previously specified\n"));
25830Sstevel@tonic-gate                 return (-1);
25840Sstevel@tonic-gate              }
25850Sstevel@tonic-gate              if (( sasl_secprops = strdup(attr)) == NULL ) {
25860Sstevel@tonic-gate 		perror ("malloc");
25870Sstevel@tonic-gate                 exit (LDAP_NO_MEMORY);
25880Sstevel@tonic-gate              }
25890Sstevel@tonic-gate 	} else if (!strcasecmp(saslarg, "realm")) {
25900Sstevel@tonic-gate 	     if ( sasl_realm != NULL ) {
25910Sstevel@tonic-gate                 fprintf( stderr, gettext("Realm previously specified\n"));
25920Sstevel@tonic-gate                 return (-1);
25930Sstevel@tonic-gate              }
25940Sstevel@tonic-gate              if (( sasl_realm = strdup(attr)) == NULL ) {
25950Sstevel@tonic-gate 		perror ("malloc");
25960Sstevel@tonic-gate                 exit (LDAP_NO_MEMORY);
25970Sstevel@tonic-gate              }
25980Sstevel@tonic-gate 	} else if (!strcasecmp(saslarg, "authzid")) {
25990Sstevel@tonic-gate              if (sasl_username != NULL) {
26000Sstevel@tonic-gate                 fprintf( stderr, gettext("Authorization name previously specified\n"));
26010Sstevel@tonic-gate                 return (-1);
26020Sstevel@tonic-gate              }
26030Sstevel@tonic-gate              if (( sasl_username = strdup(attr)) == NULL ) {
26040Sstevel@tonic-gate 		perror ("malloc");
26050Sstevel@tonic-gate                 exit (LDAP_NO_MEMORY);
26060Sstevel@tonic-gate              }
26070Sstevel@tonic-gate 	} else if (!strcasecmp(saslarg, "authid")) {
26080Sstevel@tonic-gate              if ( sasl_authid != NULL ) {
26090Sstevel@tonic-gate                 fprintf( stderr, gettext("Authentication name previously specified\n"));
26100Sstevel@tonic-gate                 return (-1);
26110Sstevel@tonic-gate              }
26120Sstevel@tonic-gate              if (( sasl_authid = strdup(attr)) == NULL) {
26130Sstevel@tonic-gate 		perror ("malloc");
26140Sstevel@tonic-gate                 exit (LDAP_NO_MEMORY);
26150Sstevel@tonic-gate              }
26160Sstevel@tonic-gate 	} else if (!strcasecmp(saslarg, "mech")) {
26170Sstevel@tonic-gate 	     if ( sasl_mech != NULL ) {
26180Sstevel@tonic-gate                 fprintf( stderr, gettext("Mech previously specified\n"));
26190Sstevel@tonic-gate                 return (-1);
26200Sstevel@tonic-gate              }
26210Sstevel@tonic-gate 	     if (( sasl_mech = strdup(attr)) == NULL) {
26220Sstevel@tonic-gate 		perror ("malloc");
26230Sstevel@tonic-gate 		exit (LDAP_NO_MEMORY);
26240Sstevel@tonic-gate 	     }
26250Sstevel@tonic-gate 	} else {
26260Sstevel@tonic-gate 	     fprintf (stderr, gettext("Invalid attribute name %s\n"), saslarg);
26270Sstevel@tonic-gate 	     return (-1);
26280Sstevel@tonic-gate 	}
26290Sstevel@tonic-gate 	return 0;
26300Sstevel@tonic-gate }
26310Sstevel@tonic-gate #endif	/* HAVE_SASL_OPTIONS */
2632*8097SSreedhar.Chalamalasetti@Sun.COM 
2633*8097SSreedhar.Chalamalasetti@Sun.COM /*
2634*8097SSreedhar.Chalamalasetti@Sun.COM  * check for and report input or output error on named stream
2635*8097SSreedhar.Chalamalasetti@Sun.COM  * return ldap_err or ferror() (ldap_err takes precedence)
2636*8097SSreedhar.Chalamalasetti@Sun.COM  * assume that fflush() already has been called if needed.
2637*8097SSreedhar.Chalamalasetti@Sun.COM  * don't want to fflush() an input stream.
2638*8097SSreedhar.Chalamalasetti@Sun.COM  */
2639*8097SSreedhar.Chalamalasetti@Sun.COM int
2640*8097SSreedhar.Chalamalasetti@Sun.COM ldaptool_check_ferror(FILE * stream, const int ldap_err, const char *msg)
2641*8097SSreedhar.Chalamalasetti@Sun.COM {
2642*8097SSreedhar.Chalamalasetti@Sun.COM 	int err = 0;
2643*8097SSreedhar.Chalamalasetti@Sun.COM 	if ((err = ferror(stream)) != 0 ) {
2644*8097SSreedhar.Chalamalasetti@Sun.COM 		fprintf(stderr, gettext("%s: ERROR: "), ldaptool_progname);
2645*8097SSreedhar.Chalamalasetti@Sun.COM 		perror(msg);
2646*8097SSreedhar.Chalamalasetti@Sun.COM 		err = LDAP_LOCAL_ERROR;
2647*8097SSreedhar.Chalamalasetti@Sun.COM 	}
2648*8097SSreedhar.Chalamalasetti@Sun.COM 
2649*8097SSreedhar.Chalamalasetti@Sun.COM 	/*
2650*8097SSreedhar.Chalamalasetti@Sun.COM 	 * reporting LDAP error code is more important than
2651*8097SSreedhar.Chalamalasetti@Sun.COM 	 * reporting errors from ferror()
2652*8097SSreedhar.Chalamalasetti@Sun.COM 	 */
2653*8097SSreedhar.Chalamalasetti@Sun.COM 	if (ldap_err == LDAP_SUCCESS) {
2654*8097SSreedhar.Chalamalasetti@Sun.COM 		return(err);
2655*8097SSreedhar.Chalamalasetti@Sun.COM 	} else {
2656*8097SSreedhar.Chalamalasetti@Sun.COM 		return(ldap_err);
2657*8097SSreedhar.Chalamalasetti@Sun.COM 	}
2658*8097SSreedhar.Chalamalasetti@Sun.COM }
2659