Back to index

lightning-sunbird  0.9+nobinonly
common.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * code that is shared by two or more of the LDAP command line tools
00040  */
00041 
00042 #include "ldaptool.h"
00043 #include "fileurl.h"
00044 
00045 #ifdef LDAP_TOOL_ARGPIN
00046 #include "argpin.h"
00047 #include "ntuserpin.h"
00048 #endif /* LDAP_TOOL_ARGPIN */
00049 
00050 #include <nspr.h>    /* for PR_Cleanup() */
00051 #include <stdlib.h>
00052 #include <time.h>    /* for time() and ctime() */
00053 
00054 static LDAP_REBINDPROC_CALLBACK get_rebind_credentials;
00055 static void print_library_info( const LDAPAPIInfo *aip, FILE *fp );
00056 static int wait4result( LDAP *ld, int msgid, struct berval **servercredp,
00057        char *msg );
00058 static int parse_result( LDAP *ld, LDAPMessage *res,
00059        struct berval **servercredp, char *msg, int freeit );
00060 
00061 #ifdef LDAPTOOL_DEBUG_MEMORY   
00062 static void *ldaptool_debug_malloc( size_t size );
00063 static void *ldaptool_debug_calloc( size_t nelem, size_t elsize );
00064 static void *ldaptool_debug_realloc( void *ptr, size_t size );
00065 static void ldaptool_debug_free( void *ptr );
00066 #endif /* LDAPTOOL_DEBUG_MEMORY */
00067 
00068 #if defined(NET_SSL)
00069 static char *certpath2keypath( char *certdbpath );
00070 static int ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns);
00071 static char * buildTokenCertName( const char *tokenName, const char *certName);
00072 #ifdef FORTEZZA
00073 static int ldaptool_fortezza_init( int exit_on_error );
00074 static int ldaptool_fortezza_alert( void *arg, PRBool onOpen,
00075        char *string, int value1, void *value2 );
00076 static void * ldaptool_fortezza_getpin( char **passwordp );
00077 static char * ldaptool_fortezza_err2string( int err );
00078 #endif /* FORTEZZA */
00079 #endif
00080 
00081 /*
00082  * display usage for common options with one exception: -f is not included
00083  * since the description tends to be tool-specific.
00084  *
00085  * As of 1-Jul-1998, of the characters in the set [A-Za-z] the following are
00086  * not currently used by any of the tools: EJgjqr
00087  */
00088 void
00089 ldaptool_common_usage( int two_hosts )
00090 {
00091     fprintf( stderr, "    -n\t\tshow what would be done but don't actually do it\n" );
00092     fprintf( stderr, "    -v\t\trun in verbose mode (diagnostics to standard output)\n" );
00093     if ( two_hosts ) {
00094        fprintf( stderr, "    -h host\tLDAP server1 name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
00095        fprintf( stderr, "    -p port\tLDAP server1 TCP port number (default: %d)\n", LDAP_PORT );
00096        fprintf( stderr, "    -h host\tLDAP server2 name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
00097        fprintf( stderr, "    -p port\tLDAP server2 TCP port number (default: %d)\n", LDAP_PORT );
00098     } else {
00099        fprintf( stderr, "    -h host\tLDAP server name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
00100        fprintf( stderr, "    -p port\tLDAP server TCP port number (default: %d)\n", LDAP_PORT );
00101     }
00102     fprintf( stderr,
00103            "    -V n\tLDAP protocol version number (%d or %d; default: %d)\n",
00104            LDAP_VERSION2, LDAP_VERSION3, LDAP_VERSION3 );
00105 #if defined(NET_SSL)
00106     fprintf( stderr, "    -Z\t\tmake an SSL-encrypted connection\n" );
00107     fprintf( stderr, "    -P pathname\tpath to SSL certificate database (default: current directory)\n" );
00108     fprintf( stderr, "    -N\t\tname of certificate to use for SSL client authentication\n" );
00109     fprintf( stderr, "    -K pathname\tpath to key database to use for SSL client authentication\n" );
00110     fprintf( stderr, "    \t\t(default: path to certificate database provided with -P option)\n" );
00111 #ifdef LDAP_TOOL_PKCS11
00112     fprintf( stderr, "    -m pathname\tpath to security module database\n");
00113 #endif /* LDAP_TOOL_PKCS11 */
00114     fprintf( stderr, "    -W\t\tSSL key password\n" );
00115 
00116 #ifdef LDAP_TOOL_PKCS11
00117     fprintf( stderr, "    -Q [token][:certificate name]\tPKCS 11\n" );
00118     fprintf( stderr, "    -X pathname\tFORTEZZA compromised key list (CKL)\n" );
00119     fprintf( stderr, "    -I pin\tcard password file\n" );
00120 #endif /* LDAP_TOOL_PKCS11 */
00121 
00122 #endif /* NET_SSL */
00123     fprintf( stderr, "    -D binddn\tbind dn\n" );
00124     fprintf( stderr, "    -w passwd\tbind passwd (for simple authentication)\n" );
00125     fprintf( stderr, "    -w - \tprompt for bind passwd (for simple authentication)\n" );
00126     fprintf( stderr, "    -j file\tread bind passwd from 'file' (for simple authentication)\n" );
00127     fprintf( stderr, "    -E\t\task server to expose (report) bind identity\n" );
00128 #ifdef LDAP_DEBUG
00129     fprintf( stderr, "    -d level\tset LDAP debugging level to `level'\n" );
00130 #endif
00131     fprintf( stderr, "    -R\t\tdo not automatically follow referrals\n" );
00132     fprintf( stderr, "    -O limit\tmaximum number of referral hops to traverse (default: %d)\n", LDAPTOOL_DEFREFHOPLIMIT );
00133     fprintf( stderr, "    -M\t\tmanage references (treat them as regular entries)\n" );
00134     fprintf( stderr, "    -0\t\tignore LDAP library version mismatches\n" );
00135 
00136 #ifndef NO_LIBLCACHE
00137     fprintf( stderr, "    -C cfgfile\tuse local database described by cfgfile\n" );
00138 #endif
00139     fprintf( stderr, "    -i charset\tcharacter set for command line input (default taken from locale)\n" );
00140     fprintf( stderr, "    -k dir\tconversion routine directory (default: current directory)\n" );
00141 #if 0
00142 /*
00143  * Suppress usage for -y (old proxied authorization control) even though
00144  * we still support it.  We want to encourage people to use -Y instead (the
00145  * new proxied authorization control).
00146  */
00147     fprintf( stderr, "    -y proxydn\tDN used for proxy authorization\n" );
00148 #endif
00149     fprintf( stderr, "    -Y proxyid\tproxied authorization id,\n" );
00150     fprintf( stderr, "              \te.g, dn:uid=bjensen,dc=example,dc=com\n" );
00151     fprintf( stderr, "    -H\t\tdisplay usage information\n" );
00152     fprintf( stderr, "    -J controloid[:criticality[:value|::b64value|:<fileurl]]\n" );
00153     fprintf( stderr, "\t\tcriticality is a boolean value (default is false)\n" );
00154 }
00155 
00156 /* globals */
00157 char                 *ldaptool_charset = "";
00158 char                 *ldaptool_host = LDAPTOOL_DEFHOST;
00159 char                 *ldaptool_host2 = LDAPTOOL_DEFHOST;
00160 int                  ldaptool_port = LDAP_PORT;
00161 int                  ldaptool_port2 = LDAP_PORT;
00162 int                  ldaptool_verbose = 0;
00163 int                  ldaptool_not = 0;
00164 FILE                 *ldaptool_fp = NULL;
00165 FILE                 *password_fp = NULL;
00166 char                 *ldaptool_progname = "";
00167 char                 *ldaptool_nls_lang = NULL;
00168 char                    *proxyauth_id = NULL;
00169 int                  proxyauth_version = 2;      /* use newer proxy control */
00170 LDAPControl          *ldaptool_request_ctrls[CONTROL_REQUESTS] = {0};
00171 #ifdef LDAP_DEBUG
00172 int                  ldaptool_dbg_lvl = 0;
00173 #endif /* LDAP_DEBUG */
00174 
00175 /* statics */
00176 static char          *binddn = NULL;
00177 static char          *passwd = NULL;
00178 static int           send_auth_response_ctrl = 0;
00179 static int           user_specified_port = 0;
00180 static int           user_specified_port2 = 0;
00181 static int           chase_referrals = 1;
00182 static int           lib_version_mismatch_is_fatal = 1;
00183 static int           ldversion = -1;      /* use default */
00184 static int           refhoplim = LDAPTOOL_DEFREFHOPLIMIT;
00185 static int           send_manage_dsait_ctrl = 0;
00186 static int           prompt_password = 0;
00187 
00188 #ifndef NO_LIBLCACHE
00189 static char          *cache_config_file = NULL;
00190 #endif /* !NO_LIBLCACHE */
00191 #if defined(NET_SSL)
00192 static int           secure = 0;
00193 static int           isZ = 0;
00194 static int           isN = 0;
00195 static int           isW = 0;
00196 static int           isw = 0;
00197 static int           isD = 0;
00198 static int           isj = 0;
00199 static char          *ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH;
00200 static char          *ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH;
00201 /*
00202 static char          *ssl_keyname = NULL;
00203 */
00204 static char          *ssl_certname = NULL;
00205 static char          *ssl_passwd = NULL;
00206 
00207 #ifdef LDAP_TOOL_PKCS11
00208 static char          *ssl_secmodpath = NULL;
00209 
00210 static char             *pkcs_token = NULL;
00211 
00212 static char             *ssl_donglefile = NULL;
00213 
00214 #if 0
00215 static char             *pkcs_pin = NULL;
00216 #endif
00217 static struct ldapssl_pkcs_fns local_pkcs_fns = 
00218     {0,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL };
00219 
00220 #ifdef FORTEZZA
00221 static uint32        fortezza_cardmask = 0;
00222 static char          *fortezza_personality = NULL;
00223 static char          *fortezza_krlfile = NULL;
00224 static char          *fortezza_pin = NULL;
00225 #endif /* FORTEZZA */
00226 #endif /* LDAP_TOOL_PKCS11 */
00227 #endif /* NET_SSL */
00228 
00229 
00230 
00231 /*
00232  * Handle general initialization and options that are common to all of
00233  * the LDAP tools.
00234  * Handle options that are common to all of the LDAP tools.
00235  * Note the the H option is included here but handled via the
00236  * extra_opt_callback function (along with any "extra_opts" ).
00237  *
00238  * Return: final value for optind or -1 if usage should be displayed (for
00239  * some fatal errors, we call exit here).
00240  */
00241 int
00242 ldaptool_process_args( int argc, char **argv, char *extra_opts,
00243        int two_hosts, void (*extra_opt_callback)( int option, char *optarg ))
00244 {
00245     int              rc, i, hostnum;
00246     char      *optstring, *common_opts;
00247     extern char      *optarg;
00248     extern int       optind;
00249     LDAPAPIInfo      ldai;
00250     char *ctrl_arg, *ctrl_oid=NULL, *ctrl_value=NULL;
00251     int ctrl_criticality=0, vlen;
00252     LDAPControl *ldctrl;
00253 
00254     /*
00255      * Set program name global based on argv[0].
00256      */
00257     if (( ldaptool_progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
00258         ldaptool_progname = argv[ 0 ];
00259     } else {
00260         ++ldaptool_progname;
00261     }
00262 
00263 #ifdef LDAPTOOL_DEBUG_MEMORY
00264     {
00265        struct ldap_memalloc_fns mafns = {
00266               ldaptool_debug_malloc,
00267               ldaptool_debug_calloc,
00268               ldaptool_debug_realloc,
00269               ldaptool_debug_free
00270        };
00271 
00272        ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &mafns );
00273     }
00274 #endif /* LDAPTOOL_DEBUG_MEMORY */
00275 
00276 #ifdef LDAP_DEBUG
00277     i = LDAP_DEBUG_ANY;
00278     ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, (void *) &i);
00279 #endif
00280 
00281     /*
00282      * Perform a sanity check on the revision of the LDAP API library to
00283      * make sure it is at least as new as the one we were compiled against.
00284      * If the API implementation is from the same vendor as we were compiled
00285      * against, we also check to make sure the vendor version is at least
00286      * as new as the library we were compiled against.
00287      *
00288      * Version differences are fatal unless the -0 option is passed on the
00289      * tool command line (that's a zero, not an oh).  We check for the
00290      * presence of -0 in a crude way to it must appear by itself in argv.
00291      */
00292     for ( i = 1; i < argc; ++i ) {
00293        if ( strcmp( argv[i], "-0" ) == 0 ) {
00294            lib_version_mismatch_is_fatal = 0;
00295            break;
00296        }
00297     }
00298 
00299     memset( &ldai, 0, sizeof(ldai));
00300     ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
00301     if (( rc = ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldai )) != 0 ) {
00302        fprintf( stderr, "%s: unable to retrieve LDAP library version"
00303               " information;\n\tthis program requires an LDAP library that"
00304               " implements revision\n\t%d or greater of the LDAP API.\n",
00305               ldaptool_progname, LDAP_API_VERSION );
00306        if ( lib_version_mismatch_is_fatal ) {
00307            exit( LDAP_LOCAL_ERROR );
00308        }
00309     } else if ( ldai.ldapai_api_version < LDAP_API_VERSION ) {
00310        fprintf( stderr, "%s: this program requires an LDAP library that"
00311               " implements revision\n\t%d or greater of the LDAP API;"
00312               " running with revision %d.\n",
00313               ldaptool_progname, LDAP_API_VERSION, ldai.ldapai_api_version );
00314        if ( lib_version_mismatch_is_fatal ) {
00315            exit( LDAP_LOCAL_ERROR );
00316        }
00317     } else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) == 0
00318            && ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
00319        fprintf( stderr, "%s: this program requires %s's LDAP\n"
00320               "\tlibrary version %2.2f or greater; running with"
00321               " version %2.2f.\n",
00322               ldaptool_progname, LDAP_VENDOR_NAME,
00323               (float)LDAP_VENDOR_VERSION / 100,
00324               (float)ldai.ldapai_vendor_version / 100 );
00325        if ( lib_version_mismatch_is_fatal ) {
00326            exit( LDAP_LOCAL_ERROR );
00327        }
00328     }
00329 
00330     /*
00331      * Process command line options.
00332      */
00333     if ( extra_opts == NULL ) {
00334        extra_opts = "";
00335     }
00336 
00337     common_opts = "nvEMRHZ0d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
00338 
00339     /* note: optstring must include room for liblcache "C:" option */
00340     if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts )
00341            + 3 )) == NULL ) {
00342        perror( "malloc" );
00343        exit( LDAP_NO_MEMORY );
00344     }
00345 
00346 #ifdef NO_LIBLCACHE
00347     sprintf( optstring, "%s%s", common_opts, extra_opts );
00348 #else
00349     sprintf( optstring, "%s%sC:", common_opts, extra_opts );
00350 #endif
00351 
00352     hostnum = 0;
00353     while ( (i = getopt( argc, argv, optstring )) != EOF ) {
00354        switch( i ) {
00355        case 'n':     /* do Not do any LDAP operations */
00356            ++ldaptool_not;
00357            break;
00358        case 'v':     /* verbose mode */
00359            ++ldaptool_verbose;
00360            break;
00361        case 'd':
00362 #ifdef LDAP_DEBUG
00363            ldaptool_dbg_lvl = atoi( optarg );    /* */
00364            ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
00365                   (void *)&ldaptool_dbg_lvl);
00366            ldaptool_dbg_lvl |= LDAP_DEBUG_ANY;
00367            ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL,
00368                   (void *)&ldaptool_dbg_lvl);
00369 #else /* LDAP_DEBUG */
00370            fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
00371 #endif /* LDAP_DEBUG */
00372            break;
00373        case 'R':     /* don't automatically chase referrals */
00374            chase_referrals = 0;
00375            break;
00376 #ifndef NO_LIBLCACHE
00377        case 'C':     /* search local database */
00378            cache_config_file = strdup( optarg );
00379            break;
00380 #endif
00381        case 'f':     /* input file */
00382            if ( optarg[0] == '-' && optarg[1] == '\0' ) {
00383               ldaptool_fp = stdin;
00384            } else if (( ldaptool_fp = fopen( optarg, "r" )) == NULL ) {
00385               perror( optarg );
00386               exit( LDAP_PARAM_ERROR );
00387            }
00388            break;
00389        case 'h':     /* ldap host */
00390            if ( hostnum == 0 ) {
00391               ldaptool_host = strdup( optarg );
00392            } else {
00393               ldaptool_host2 = strdup( optarg );
00394            }
00395            ++hostnum;
00396            break;
00397        case 'D':     /* bind DN */
00398            isD = 1;
00399            binddn = strdup( optarg );
00400            break;
00401        case 'E':     /* expose bind identity via auth. response control */
00402            ++send_auth_response_ctrl;
00403            break;
00404 
00405        case 'p':     /* ldap port */
00406            if ( !user_specified_port ) {
00407               ++user_specified_port;
00408               ldaptool_port = atoi( optarg );
00409            } else {
00410               ++user_specified_port2;
00411               ldaptool_port2 = atoi( optarg );
00412            }
00413            break;
00414 #if defined(NET_SSL)
00415        case 'P':     /* path to security database */
00416            secure = 1; /* do SSL encryption */
00417            ssl_certdbpath = strdup( optarg );
00418            if (NULL== ssl_keydbpath)
00419            {
00420               ssl_keydbpath = certpath2keypath( ssl_certdbpath );
00421            }
00422            break;
00423        case 'Z':     /* do SSL encryption */
00424            secure = 1;
00425            isZ = 1;
00426            break;
00427        case 'N':     /* nickname of cert. to use for client auth. */
00428            ssl_certname = strdup( optarg );
00429            if (NULL == ssl_certname)
00430            {
00431               perror("malloc");
00432               exit( LDAP_NO_MEMORY );
00433            }
00434            isN = 1;
00435            break;
00436        case 'K':     /* location of key database */
00437            /* if keydb path is not null, then it was probably strdup by the 
00438             * cert db option.  free it first 
00439             */
00440            if (ssl_keydbpath)
00441               free( ssl_keydbpath);
00442 
00443            ssl_keydbpath = strdup( optarg );
00444            if (NULL == ssl_keydbpath)
00445            {
00446               perror("malloc");
00447               exit( LDAP_NO_MEMORY );
00448            }
00449            break;
00450        case 'W':     /* SSL key password */
00451            ssl_passwd = strdup( optarg );
00452            if (NULL == ssl_passwd)
00453            {
00454               perror("malloc");
00455               exit( LDAP_NO_MEMORY );
00456            }
00457            isW = 1;
00458            break;
00459 #ifdef LDAP_TOOL_PKCS11
00460        case 'm':     /* SSL secmod path */
00461            ssl_secmodpath = strdup( optarg);
00462            if (NULL == ssl_secmodpath)
00463            {
00464               perror("malloc");
00465               exit( LDAP_NO_MEMORY );
00466            }
00467            break;
00468 
00469        case 'Q':     /* FORTEZZA [card][:personality] */
00470            pkcs_token = strdup(optarg);
00471            if (NULL == pkcs_token)
00472            {
00473               perror("malloc");
00474               exit( LDAP_NO_MEMORY );
00475            }
00476 
00477            break;
00478        case 'X':     /* path to FORTEZZA CKL file */
00479          /*
00480            fortezza_krlfile = strdup( optarg );
00481            */
00482 
00483            break;
00484        case 'I':     /* FORTEZZA PIN (password file) */
00485            ssl_donglefile = strdup( optarg );
00486            
00487            break;
00488 #endif /* LDAP_TOOL_PKCS11 */
00489 
00490 #endif /* NET_SSL */
00491        case 'w':     /* bind password */
00492            isw = 1;
00493            if ( optarg[0] == '-' && optarg[1] == '\0' )
00494               prompt_password = 1;
00495            else
00496               passwd = strdup( optarg );
00497            break;
00498            case 'j':       /* bind password from file */
00499            isj = 1;
00500            if ((password_fp = fopen( optarg, "r" )) == NULL ) {
00501               fprintf(stderr, "%s: Unable to open '%s' file\n",
00502                      ldaptool_progname, optarg);
00503               exit( LDAP_PARAM_ERROR );
00504            }
00505             break;
00506        case 'O':     /* referral hop limit */
00507            refhoplim = atoi( optarg );
00508            break;
00509        case 'V':     /* protocol version */
00510            ldversion = atoi (optarg);
00511            if ( ldversion != LDAP_VERSION2 && ldversion != LDAP_VERSION3 ) {
00512               fprintf( stderr, "%s: LDAP protocol version %d is not "
00513                      "supported (use -V%d or -V%d)\n",
00514                      ldaptool_progname, ldversion, LDAP_VERSION2,
00515                      LDAP_VERSION3 );
00516               exit( LDAP_PARAM_ERROR );
00517            }
00518            break;
00519        case 'M':     /* send a manageDsaIT control */
00520            send_manage_dsait_ctrl = 1;
00521            break;
00522 
00523        case 'i':   /* character set specified */
00524            ldaptool_charset = strdup( optarg );
00525            if (NULL == ldaptool_charset)
00526            {
00527               perror( "malloc" );
00528               exit( LDAP_NO_MEMORY );
00529            }
00530               
00531            break;
00532        case 'k':   /* conversion directory */
00533            ldaptool_convdir = strdup( optarg );
00534            if (NULL == ldaptool_convdir)
00535            {
00536               perror( "malloc" );
00537               exit( LDAP_NO_MEMORY );
00538            }
00539            break;
00540        case 'y':   /* old (version 1) proxied authorization control */
00541               proxyauth_version = 1;
00542        case 'Y':   /* new (version 2 ) proxied authorization control */
00543               /*FALLTHRU*/
00544            proxyauth_id = strdup(optarg);
00545            if (NULL == proxyauth_id)
00546            {
00547               perror( "malloc" );
00548               exit( LDAP_NO_MEMORY );
00549            }
00550 
00551            break;
00552 
00553        case '0':     /* zero -- override LDAP library version check */
00554            break;    /* already handled above */
00555        case 'J':
00556            if ( (ctrl_arg = strdup( optarg)) == NULL ) {
00557               perror ("strdup");
00558               exit (LDAP_NO_MEMORY);
00559            }
00560            if (ldaptool_parse_ctrl_arg(ctrl_arg, ':', &ctrl_oid,
00561                   &ctrl_criticality, &ctrl_value, &vlen)) {
00562               return (-1);
00563            }
00564            ldctrl = calloc(1,sizeof(LDAPControl));
00565            if (ctrl_value) {
00566               rc = ldaptool_berval_from_ldif_value( ctrl_value, 
00567                      vlen, &(ldctrl->ldctl_value),
00568                      1 /* recognize file URLs */, 
00569                      0 /* always try file */,
00570                      1 /* report errors */ );
00571               if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
00572                   fprintf( stderr, "Unable to parse %s\n", ctrl_value);
00573                   return (-1);
00574               }
00575            }
00576            ldctrl->ldctl_oid = ctrl_oid;
00577            ldctrl->ldctl_iscritical = ctrl_criticality;
00578            ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
00579            break;
00580        default:
00581            (*extra_opt_callback)( i, optarg );
00582        }
00583     }
00584 
00585     /* If '-Z' is specified, check if '-P' is specified too. */
00586     if ( isN || isW ) {
00587        if ( !isZ ) {
00588               printf( "%s: with -N, -W options, please specify -Z\n\n", ldaptool_progname ); 
00589               return (-1);
00590        }
00591     }
00592 
00593     if ( isj && isw ) {
00594        fprintf(stderr, "%s: -j and -w options cannot be specified simultaneously\n\n", ldaptool_progname );
00595        return (-1);
00596     }
00597 
00598     if ( (isj || isw) && !isD ) {
00599        fprintf(stderr, "%s: with -j, -w options, please specify -D\n\n", ldaptool_progname );
00600        return (-1);
00601     }
00602 
00603     if (prompt_password != 0) {
00604        char *password_string = "Enter bind password: ";
00605        char pbuf[257];
00606 
00607 #if defined(_WIN32)
00608        fputs(password_string,stdout);
00609        fflush(stdout);
00610        if (fgets(pbuf,256,stdin) == NULL) {
00611            passwd = NULL;
00612        } else {
00613            char *tmp;
00614 
00615            tmp = strchr(pbuf,'\n');
00616            if (tmp) *tmp = '\0';
00617            tmp = strchr(pbuf,'\r');
00618            if (tmp) *tmp = '\0';
00619            passwd = strdup(pbuf);
00620        }
00621 #else
00622 #if defined(SOLARIS)
00623        /* 256 characters on Solaris */
00624        passwd = getpassphrase(password_string);
00625 #else
00626        /* limited to 16 chars on Tru64, 32 on AIX */
00627        passwd = getpass(password_string);
00628 #endif
00629 #endif
00630 
00631     } else if (password_fp != NULL) {
00632        char *linep = NULL;
00633        int   increment = 0;
00634        int   c, index;
00635 
00636        /* allocate initial block of memory */
00637        if ((linep = (char *)malloc(BUFSIZ)) == NULL) {
00638            fprintf( stderr, "%s: not enough memory to read password from file\n", ldaptool_progname );
00639            exit( LDAP_NO_MEMORY );
00640        }
00641        increment++;
00642        index = 0;
00643        while ((c = fgetc( password_fp )) != '\n' && c != EOF) {
00644 
00645            /* check if we will overflow the buffer */
00646            if ((c != EOF) && (index == ((increment * BUFSIZ) -1))) {
00647 
00648               /* if we did, add another BUFSIZ worth of bytes */
00649               if ((linep = (char *)
00650                   realloc(linep, (increment + 1) * BUFSIZ)) == NULL) {
00651                      fprintf( stderr, "%s: not enough memory to read password from file\n", ldaptool_progname );
00652                      exit( LDAP_NO_MEMORY );
00653               }
00654               increment++;
00655            }
00656            linep[index++] = c;
00657        }
00658        linep[index] = '\0';
00659        passwd = linep;
00660     }
00661 
00662     /*
00663      * If verbose (-v) flag was passed in, display program name and start time.
00664      * If the verbose flag was passed at least twice (-vv), also display
00665      * information about the API library we are running with.
00666      */
00667     if ( ldaptool_verbose ) {
00668        time_t curtime;
00669 
00670        curtime = time( NULL );
00671        printf( "%s: started %s\n", ldaptool_progname, ctime( &curtime ));
00672        if ( ldaptool_verbose > 1 ) {
00673            print_library_info( &ldai, stdout );
00674        }
00675     }
00676 
00677 #ifdef LDAP_TOOL_PKCS11
00678     if ((NULL != pkcs_token) && (NULL != ssl_certname)) {
00679        char *result;
00680        
00681        if ( (result = buildTokenCertName( pkcs_token, ssl_certname)) != NULL){
00682            free( ssl_certname );
00683            ssl_certname = result;
00684        }
00685     }
00686 #endif /* LDAP_TOOL_PKCS11 */
00687 
00688     free( optstring );
00689 
00690     /*
00691      * Clean up and return index of first non-option argument.
00692      */
00693     if ( ldai.ldapai_extensions != NULL ) {
00694        ldap_value_free( ldai.ldapai_extensions );
00695     }
00696     if ( ldai.ldapai_vendor_name != NULL ) {
00697        ldap_memfree( ldai.ldapai_vendor_name );
00698     }
00699 
00700     return( optind );
00701 }
00702 
00703 
00704 /*
00705  * Write detailed information about the API library we are running with to fp.
00706  */
00707 static void
00708 print_library_info( const LDAPAPIInfo *aip, FILE *fp )
00709 {
00710     int                 i;                                                      
00711     LDAPAPIFeatureInfo  fi;         
00712 
00713     fprintf( fp, "LDAP Library Information -\n"
00714            "    Highest supported protocol version: %d\n"
00715            "    LDAP API revision:                  %d\n"
00716            "    API vendor name:                    %s\n"
00717            "    Vendor-specific version:            %.2f\n",
00718            aip->ldapai_protocol_version, aip->ldapai_api_version, 
00719            aip->ldapai_vendor_name,
00720            (float)aip->ldapai_vendor_version / 100.0 );
00721 
00722     if ( aip->ldapai_extensions != NULL ) {
00723        fputs( "    LDAP API Extensions:\n", fp );
00724 
00725        for ( i = 0; aip->ldapai_extensions[i] != NULL; i++ )  {
00726            fprintf( fp, "        %s", aip->ldapai_extensions[i] );
00727            fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
00728            fi.ldapaif_name = aip->ldapai_extensions[i];
00729            fi.ldapaif_version = 0;
00730 
00731            if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi )
00732                   != 0 ) {
00733               fprintf( fp, " %s: ldap_get_option( NULL,"
00734                      " LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed"
00735                      " (Feature Info version: %d)\n", ldaptool_progname,
00736                      fi.ldapaif_name, fi.ldapaif_info_version );
00737            } else {
00738               fprintf( fp, " (revision %d)\n", fi.ldapaif_version);
00739            }
00740        }
00741     }
00742    fputc( '\n', fp );
00743 }
00744 
00745 
00746 
00747 #ifdef LDAP_TOOL_ARGPIN
00748 static int PinArgRegistration( void )
00749 {
00750     
00751     /* pkcs_init was successful  register the pin args */
00752     
00753     SVRCOREArgPinObj *ArgPinObj;
00754     char *tokenName;
00755 #ifndef _WIN32
00756     SVRCOREStdPinObj *StdPinObj;
00757 #else
00758     SVRCOREFilePinObj *FilePinObj;
00759     SVRCOREAltPinObj *AltPinObj;
00760     SVRCORENTUserPinObj *NTUserPinObj;
00761     int err;
00762 #endif
00763     char *pin;
00764     char *filename;
00765     /* Create and register the pin object for PKCS 11 */
00766     local_pkcs_fns.pkcs_getdonglefilename(NULL, &filename);
00767     local_pkcs_fns.pkcs_getpin(NULL, "", &pin);
00768 #ifndef _WIN32
00769     if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) !=
00770         SVRCORE_Success) {
00771        printf("Security Initialization: Unable to create PinObj "
00772               "(%d)", PR_GetError());
00773        return -1;
00774     }
00775     if (pin != NULL)
00776     {
00777        local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
00778        SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, (SVRCOREPinObj *)StdPinObj);
00779        SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
00780     }
00781     else
00782     {
00783        SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj);
00784     }
00785 #else
00786     if (NULL != pin)
00787     {
00788        local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
00789        if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
00790            printf("Security Initialization: Unable to create NTUserPinObj "
00791                  "(%d)", PR_GetError());
00792            exit( LDAP_LOCAL_ERROR );
00793        }
00794        if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin,
00795                                       (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success)
00796        {
00797            printf("Security Initialization: Unable to create ArgPinObj "
00798                  "(%d)", PR_GetError());
00799            return -1;
00800 
00801        }
00802        SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
00803        
00804     }
00805     else
00806     {
00807        if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
00808            printf("Security Initialization: Unable to create NTUserPinObj "
00809                  "(%d)", PR_GetError());
00810               return -1;
00811        }
00812        if (filename && *filename)
00813        {
00814            if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) !=
00815               SVRCORE_Success) {
00816               printf("Security Initialization: Unable to create FilePinObj "
00817                      "(%d)", PR_GetError());
00818               return -1;
00819 
00820            }
00821            if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
00822                                           (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) {
00823               printf("Security Initialization: Unable to create AltPinObj "
00824                      "(%d)", PR_GetError());
00825               return -1;
00826            }
00827            SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj);
00828        }
00829        else
00830        {
00831            SVRCORE_RegisterPinObj((SVRCOREPinObj *)NTUserPinObj);
00832        }
00833     }
00834 #endif
00835     return LDAP_SUCCESS;
00836     
00837 }
00838 #endif /* LDAP_TOOL_ARGPIN */
00839 
00840 
00841 /*
00842  * initialize and return an LDAP session handle.
00843  * if errors occur, we exit here.
00844  */
00845 LDAP *
00846 ldaptool_ldap_init( int second_host )
00847 {
00848     LDAP      *ld = NULL;
00849     char      *host;
00850     int              port, rc, user_port;
00851 
00852     if ( ldaptool_not ) {
00853        return( NULL );
00854     }
00855     
00856     if ( second_host ) {
00857        host = ldaptool_host2;
00858        port = ldaptool_port2;
00859        user_port = user_specified_port2;
00860     } else {
00861        host = ldaptool_host;
00862        port = ldaptool_port;
00863        user_port = user_specified_port;
00864     }
00865 
00866 
00867     if ( ldaptool_verbose ) {
00868        printf( "ldap_init( %s, %d )\n", host, port );
00869     }
00870 
00871 #if defined(NET_SSL)
00872     /*
00873      * Initialize security libraries and databases and LDAP session.  If
00874      * ssl_certname is not NULL, then we will attempt to use client auth.
00875      * if the server supports it.
00876      */
00877 #ifdef LDAP_TOOL_PKCS11
00878     ldaptool_setcallbacks( &local_pkcs_fns );
00879 
00880     if ( !second_host       && secure  
00881         &&(rc = ldapssl_pkcs_init( &local_pkcs_fns))  < 0) {
00882            /* secure connection requested -- fail if no SSL */
00883            rc = PORT_GetError();
00884            fprintf( stderr, "SSL initialization failed: error %d (%s)\n",
00885                   rc, ldapssl_err2string( rc ));
00886            exit( LDAP_LOCAL_ERROR );
00887     }
00888 
00889 #ifdef LDAP_TOOL_ARGPIN
00890     if (secure) {
00891        if (PinArgRegistration( )) {
00892            exit( LDAP_LOCAL_ERROR);
00893        }
00894     }
00895 #endif /* LDAP_TOOL_ARGPIN */
00896 
00897 #else /* LDAP_TOOL_PKCS11 */
00898     if ( !second_host       && secure  
00899         &&(rc = ldapssl_client_init( ssl_certdbpath, NULL )) < 0) {
00900            /* secure connection requested -- fail if no SSL */
00901            rc = PORT_GetError();
00902            fprintf( stderr, "SSL initialization failed: error %d (%s)\n",
00903                   rc, ldapssl_err2string( rc ));
00904            exit( LDAP_LOCAL_ERROR );
00905     }
00906 #endif /* LDAP_TOOL_PKCS11 */
00907 
00908     if (secure) {
00909        if ( !user_port ) {
00910            port = LDAPS_PORT;
00911        }
00912        
00913        if (( ld = ldapssl_init( host, port,
00914               secure )) != NULL && ssl_certname != NULL )
00915            if (ldapssl_enable_clientauth( ld, ssl_keydbpath, ssl_passwd,
00916               ssl_certname ) != 0 ) {
00917               exit ( ldaptool_print_lderror( ld, "ldapssl_enable_clientauth",
00918                   LDAPTOOL_CHECK4SSL_ALWAYS ));
00919            }
00920     } else {
00921        /* In order to support IPv6, we use NSPR I/O */
00922        ld = prldap_init( host, port, 0 /* not shared across threads */ );
00923     }
00924 
00925 #else
00926     /* In order to support IPv6, we use NSPR I/O */
00927     ld = prldap_init( host, port, 0 /* not shared across threads */ );
00928 #endif
00929 
00930     if ( ld == NULL ) {
00931        perror( "ldap_init" );
00932        exit( LDAP_LOCAL_ERROR );
00933     }
00934 
00935 #ifndef NO_LIBLCACHE
00936     if ( cache_config_file != NULL ) {
00937        int    opt;
00938 
00939        if ( lcache_init( ld, cache_config_file ) != 0 ) {
00940               exit( ldaptool_print_lderror( ld, cache_config_file,
00941                      LDAPTOOL_CHECK4SSL_NEVER ));
00942        }
00943        opt = 1;
00944        (void) ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &opt );
00945        opt = LDAP_CACHE_LOCALDB;
00946        (void) ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &opt );
00947        if ( ldversion == -1 ) {    /* not set with -V */
00948            ldversion = LDAP_VERSION2;     /* local db only supports v2 */
00949        }
00950     }
00951 #endif
00952 
00953 
00954     ldap_set_option( ld, LDAP_OPT_REFERRALS, chase_referrals ? LDAP_OPT_ON:
00955        LDAP_OPT_OFF );
00956     if ( chase_referrals ) {
00957        ldap_set_rebind_proc( ld, get_rebind_credentials, NULL );
00958        ldap_set_option( ld, LDAP_OPT_REFERRAL_HOP_LIMIT, &refhoplim );
00959     }
00960 
00961     if ( ldversion == -1 ) {       /* not set with -V and not using local db */
00962        ldversion = LDAP_VERSION3;
00963     }
00964     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
00965 
00966     return( ld );
00967 }
00968 
00969 
00970 /*
00971  * perform a bind to the LDAP server if needed.
00972  * if an error occurs, we exit here.
00973  */
00974 void
00975 ldaptool_bind( LDAP *ld )
00976 {
00977     int              rc;
00978     char      *conv;
00979     LDAPControl      auth_resp_ctrl, *ctrl_array[ 2 ], **bindctrls;
00980 
00981     if ( ldaptool_not ) {
00982        return;
00983     }
00984 
00985     if ( send_auth_response_ctrl ) {
00986        auth_resp_ctrl.ldctl_oid = LDAP_CONTROL_AUTH_REQUEST;
00987        auth_resp_ctrl.ldctl_value.bv_val = NULL;
00988        auth_resp_ctrl.ldctl_value.bv_len = 0;
00989        auth_resp_ctrl.ldctl_iscritical = 0;
00990 
00991        ctrl_array[0] = &auth_resp_ctrl;
00992        ctrl_array[1] = NULL;
00993        bindctrls = ctrl_array;
00994     } else {
00995        bindctrls = NULL;
00996     }
00997 
00998     /*
00999      * if using LDAPv3 and not using client auth., omit NULL bind for
01000      * efficiency.
01001      */
01002     if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
01003            && ssl_certname == NULL ) {
01004        return;
01005     }
01006 
01007     /*
01008      * do the bind, backing off one LDAP version if necessary
01009      */
01010     conv = ldaptool_local2UTF8( binddn );
01011 
01012     /*
01013      * if using LDAPv3 and client auth., try a SASL EXTERNAL bind
01014      */
01015     if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
01016            && ssl_certname != NULL ) {
01017        rc = ldaptool_sasl_bind_s( ld, NULL, LDAP_SASL_EXTERNAL, NULL,
01018               bindctrls, NULL, NULL, "ldap_sasl_bind" );
01019     } else {
01020        rc = ldaptool_simple_bind_s( ld, conv, passwd, bindctrls, NULL,
01021                   "ldap_simple_bind" );
01022     }
01023 
01024     if ( rc == LDAP_SUCCESS ) {
01025         if ( conv != NULL ) {
01026            free( conv );
01027        }
01028        return;                     /* success */
01029     }
01030 
01031     if ( rc == LDAP_PROTOCOL_ERROR && ldversion > LDAP_VERSION2 ) {
01032        /*
01033         * try again, backing off one LDAP version
01034         * this is okay even for client auth. because the way to achieve
01035         * client auth. with LDAPv2 is to perform a NULL simple bind.
01036         */
01037        --ldversion;
01038        fprintf( stderr, "%s: the server doesn't understand LDAPv%d;"
01039               " trying LDAPv%d instead...\n", ldaptool_progname,
01040               ldversion + 1, ldversion );
01041        ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
01042        if (( rc = ldaptool_simple_bind_s( ld, conv, passwd,
01043               bindctrls, NULL, "ldap_simple_bind" )) == LDAP_SUCCESS ) {
01044             if( conv != NULL )
01045                 free( conv );
01046            return;          /* a qualified success */
01047        }
01048     }
01049 
01050     if ( conv != NULL ) {
01051         free( conv );
01052     }
01053 
01054     /*
01055      * bind(s) failed -- fatal error
01056      */
01057     ldap_unbind( ld );
01058     exit( rc );
01059 }
01060 
01061 
01062 /*
01063  * close open files, unbind, etc.
01064  */
01065 void
01066 ldaptool_cleanup( LDAP *ld )
01067 {
01068     if ( ld != NULL ) {
01069        ldap_unbind( ld );
01070     }
01071 
01072     if ( ldaptool_fp != NULL && ldaptool_fp != stdin ) {
01073        fclose( ldaptool_fp );
01074        ldaptool_fp = NULL;
01075     }
01076 }
01077 
01078 
01079 /*
01080  * Retrieve and print an LDAP error message.  Returns the LDAP error code.
01081  */
01082 int
01083 ldaptool_print_lderror( LDAP *ld, char *msg, int check4ssl )
01084 {
01085     int              lderr = ldap_get_lderrno( ld, NULL, NULL );
01086 
01087     ldap_perror( ld, msg );
01088     if ( secure && check4ssl != LDAPTOOL_CHECK4SSL_NEVER ) {
01089        if ( check4ssl == LDAPTOOL_CHECK4SSL_ALWAYS
01090               || ( lderr == LDAP_SERVER_DOWN )) {
01091            int              sslerr = PORT_GetError();
01092 
01093            fprintf( stderr, "\tSSL error %d (%s)\n", sslerr,
01094                   ldapssl_err2string( sslerr ));
01095        }
01096     }
01097 
01098     return( lderr );
01099 }
01100 
01101 
01102 /*
01103  * print referrals to stderr
01104  */
01105 void
01106 ldaptool_print_referrals( char **refs )
01107 {
01108     int              i;
01109 
01110     if ( refs != NULL ) {
01111        for ( i = 0; refs[ i ] != NULL; ++i ) {
01112            fprintf( stderr, "Referral: %s\n", refs[ i ] );
01113        }
01114     }
01115 }
01116 
01117 
01118 /*
01119  * print contents of an extended response to stderr
01120  * this is mainly to support unsolicited notifications
01121  * Returns an LDAP error code (from the extended result).
01122  */
01123 int
01124 ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg )
01125 {
01126     char             *oid;
01127     struct berval    *data;
01128 
01129     if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 )
01130            != LDAP_SUCCESS ) {
01131        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01132     } else {
01133        if ( oid != NULL ) {
01134            if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) {
01135               fprintf( stderr, "%s: Notice of Disconnection\n", msg );
01136            } else {
01137               fprintf( stderr, "%s: OID %s\n", msg, oid );
01138            }
01139            ldap_memfree( oid );
01140        } else {
01141            fprintf( stderr, "%s: missing OID\n", msg );
01142        }
01143 
01144        if ( data != NULL ) {
01145            fprintf( stderr, "%s: Data (length %ld):\n", msg, data->bv_len );
01146 #if 0
01147 /* XXXmcs: maybe we should display the actual data? */
01148            lber_bprint( data->bv_val, data->bv_len );
01149 #endif
01150            ber_bvfree( data );
01151        }
01152     }
01153 
01154     return parse_result( ld, res, NULL, msg, 1 );
01155 }
01156 
01157 
01158 /*
01159  * Like ldap_sasl_bind_s() but calls wait4result() to display
01160  * any referrals returned and report errors in a consistent way.
01161  */
01162 int
01163 ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism,
01164        const struct berval *cred, LDAPControl **serverctrls,
01165        LDAPControl **clientctrls, struct berval **servercredp, char *msg )
01166 {
01167     int              rc, msgid;
01168 
01169     if ( servercredp != NULL ) {
01170            *servercredp = NULL;
01171     }
01172 
01173     if (( rc = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls,
01174            clientctrls, &msgid )) != LDAP_SUCCESS ) {
01175        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01176     } else {
01177        rc = wait4result( ld, msgid, servercredp, msg );
01178     }
01179 
01180     return( rc );
01181 }
01182 
01183 
01184 /*
01185  * Like ldap_simple_bind_s() but calls wait4result() to display
01186  * any referrals returned and report errors in a consistent way.
01187  */
01188 int
01189 ldaptool_simple_bind_s( LDAP *ld, const char *dn, const char *passwd,
01190        LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
01191 {
01192     struct berval    bv;
01193 
01194     bv.bv_val = (char *)passwd;           /* XXXmcs: had to cast away const */
01195     bv.bv_len = ( passwd == NULL ? 0 : strlen( passwd ));
01196     return( ldaptool_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &bv, serverctrls,
01197            clientctrls, NULL, msg ));
01198 }
01199 
01200 
01201 /*
01202  * Like ldap_add_ext_s() but calls wait4result() to display
01203  * any referrals returned and report errors in a consistent way.
01204  */
01205 int
01206 ldaptool_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
01207        LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
01208 {
01209     int              rc, msgid;
01210 
01211     if (( rc = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, &msgid ))
01212            != LDAP_SUCCESS ) {
01213        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01214     } else {
01215        /*
01216         * 25-April-2000 Note: the next line used to read:
01217         *     rc = wait4result( ld, msgid, NULL, msg );
01218         * 'msgid' it was changed to 'LDAP_RES_ANY' in order to receive
01219         * unsolicited notifications.
01220         */
01221        rc = wait4result( ld, LDAP_RES_ANY, NULL, msg );
01222     }
01223 
01224     return( rc );
01225 }
01226 
01227 
01228 /*
01229  * Like ldap_modify_ext_s() but calls wait4result() to display
01230  * any referrals returned and report errors in a consistent way.
01231  */
01232 int
01233 ldaptool_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
01234        LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
01235 {
01236     int              rc, msgid;
01237 
01238     if (( rc = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
01239            &msgid )) != LDAP_SUCCESS ) {
01240        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01241     } else {
01242        rc = wait4result( ld, msgid, NULL, msg );
01243     }
01244 
01245     return( rc );
01246 }
01247 
01248 
01249 /*
01250  * Like ldap_delete_ext_s() but calls wait4result() to display
01251  * any referrals returned and report errors in a consistent way.
01252  */
01253 int
01254 ldaptool_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls,
01255        LDAPControl **clientctrls, char *msg )
01256 {
01257     int              rc, msgid;
01258 
01259     if (( rc = ldap_delete_ext( ld, dn, serverctrls, clientctrls, &msgid ))
01260            != LDAP_SUCCESS ) {
01261        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01262     } else {
01263        rc = wait4result( ld, msgid, NULL, msg );
01264     }
01265 
01266     return( rc );
01267 }
01268 
01269 
01270 /*
01271  * Like ldap_compare_ext_s() but calls wait4result() to display
01272  * any referrals returned and report errors in a consistent way.
01273  */
01274 int ldaptool_compare_ext_s( LDAP *ld, const char *dn, const char *attrtype,
01275            const struct berval *bvalue, LDAPControl **serverctrls,
01276            LDAPControl **clientctrls, char *msg )
01277 {
01278     int              rc, msgid;
01279 
01280     if (( rc = ldap_compare_ext( ld, dn, attrtype, bvalue, serverctrls,
01281            clientctrls, &msgid )) != LDAP_SUCCESS ) {
01282        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01283     } else {
01284        rc = wait4result( ld, msgid, NULL, msg );
01285     }
01286 
01287     return( rc );
01288 }
01289 
01290 
01291 /*
01292  * Like ldap_rename_s() but calls wait4result() to display
01293  * any referrals returned and report errors in a consistent way.
01294  */
01295 int
01296 ldaptool_rename_s(  LDAP *ld, const char *dn, const char *newrdn,
01297        const char *newparent, int deleteoldrdn, LDAPControl **serverctrls,
01298        LDAPControl **clientctrls, char *msg )
01299 {
01300     int              rc, msgid;
01301 
01302     if (( rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn,
01303            serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
01304        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01305     } else {
01306        rc = wait4result( ld, msgid, NULL, msg );
01307     }
01308 
01309     return( rc );
01310 }
01311 
01312 
01313 /*
01314  * Wait for a result, check for and display errors and referrals.
01315  * Also recognize and display "Unsolicited notification" messages.
01316  * Returns an LDAP error code.
01317  */
01318 static int
01319 wait4result( LDAP *ld, int msgid, struct berval **servercredp, char *msg )
01320 {
01321     LDAPMessage      *res;
01322     int              rc, received_only_unsolicited = 1;
01323 
01324     while ( received_only_unsolicited ) {
01325        res = NULL;
01326        if (( rc = ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ))
01327                   == -1 ) {
01328            ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01329            return( ldap_get_lderrno( ld, NULL, NULL ));
01330        }
01331 
01332        /*
01333         * Special handling for unsolicited notifications:
01334         *    1. Parse and display contents.
01335         *    2. go back and wait for another (real) result.
01336         */
01337        if ( rc == LDAP_RES_EXTENDED
01338                   && ldap_msgid( res ) == LDAP_RES_UNSOLICITED ) {
01339            rc = ldaptool_print_extended_response( ld, res,
01340                   "Unsolicited response" );
01341        } else {
01342            rc = parse_result( ld, res, servercredp, msg, 1 );
01343            received_only_unsolicited = 0; /* we're done */
01344        }
01345     }
01346 
01347     return( rc );
01348 }
01349 
01350 
01351 static int
01352 parse_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp,
01353        char *msg, int freeit )
01354 {
01355     int              rc, lderr, errno;
01356     int              pw_days=0, pw_hrs=0, pw_mins=0, pw_secs=0; /* for pwpolicy */
01357     char      **refs = NULL;
01358     LDAPControl      **ctrls;
01359 
01360     if (( rc = ldap_parse_result( ld, res, &lderr, NULL, NULL, &refs,
01361            &ctrls, 0 )) != LDAP_SUCCESS ) {
01362        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01363        ldap_msgfree( res );
01364        return( rc );
01365     }
01366 
01367     /* check for authentication response control & PWPOLICY control*/
01368     if ( NULL != ctrls ) {
01369        int           i;
01370        char          *s;
01371 
01372        for ( i = 0; NULL != ctrls[i]; ++i ) {
01373            if ( 0 == strcmp( ctrls[i]->ldctl_oid,
01374                      LDAP_CONTROL_AUTH_RESPONSE )) {
01375                   s = ctrls[i]->ldctl_value.bv_val;
01376                   if ( NULL == s ) {
01377                      s = "Null";
01378                   } else if ( *s == '\0' ) {
01379                      s = "Anonymous";
01380                   }
01381               fprintf( stderr, "%s: bound as %s\n", ldaptool_progname, s );
01382            }
01383 
01384            if ( 0 == strcmp( ctrls[i]->ldctl_oid,
01385                      LDAP_CONTROL_PWEXPIRING )) {
01386 
01387                   /* Warn the user his passwd is to expire */
01388                   errno = 0;       
01389                   pw_secs = atoi(ctrls[i]->ldctl_value.bv_val);
01390                   if ( pw_secs > 0  && errno != ERANGE ) {
01391                      if ( pw_secs > 86400 ) {
01392                             pw_days = ( pw_secs / 86400 );
01393                             pw_secs = ( pw_secs % 86400 );
01394                      } 
01395                      if ( pw_secs > 3600 ) {
01396                             pw_hrs = ( pw_secs / 3600 );
01397                             pw_secs = ( pw_secs % 3600 );
01398                      }
01399                      if ( pw_secs > 60 ) {
01400                             pw_mins = ( pw_secs / 60 );
01401                             pw_secs = ( pw_secs % 60 );
01402                      }
01403 
01404                      printf("%s: Warning ! Your password will expire after ", ldaptool_progname);
01405                      if ( pw_days ) {
01406                             printf ("%d days, ", pw_days);
01407                      }
01408                      if ( pw_hrs ) {
01409                             printf ("%d hrs, ", pw_hrs);
01410                      }
01411                      if ( pw_mins ) {
01412                             printf ("%d mins, ", pw_mins);
01413                      }
01414                      printf("%d seconds.\n", pw_secs);
01415                      
01416                  }
01417               }
01418        }
01419        ldap_controls_free( ctrls );
01420     }
01421 
01422     if ( servercredp != NULL && ( rc = ldap_parse_sasl_bind_result( ld, res,
01423            servercredp, 0 )) != LDAP_SUCCESS ) {
01424        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01425        ldap_msgfree( res );
01426        return( rc );
01427     }
01428 
01429     if ( freeit ) {
01430        ldap_msgfree( res );
01431     }
01432 
01433     if ( LDAPTOOL_RESULT_IS_AN_ERROR( lderr )) {
01434        ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
01435     }
01436 
01437     if ( refs != NULL ) {
01438        ldaptool_print_referrals( refs );
01439        ldap_value_free( refs );
01440     }
01441 
01442     return( lderr );
01443 }
01444 
01445 
01446 /*
01447  * if -M was passed on the command line, create and return a "Manage DSA IT"
01448  * LDAPv3 control.  If not, return NULL.
01449  */
01450 LDAPControl *
01451 ldaptool_create_manage_dsait_control( void )
01452 {
01453     LDAPControl      *ctl;
01454 
01455     if ( !send_manage_dsait_ctrl ) {
01456        return( NULL );
01457     }
01458 
01459     if (( ctl = (LDAPControl *)calloc( 1, sizeof( LDAPControl ))) == NULL ||
01460            ( ctl->ldctl_oid = strdup( LDAP_CONTROL_MANAGEDSAIT )) == NULL ) {
01461        perror( "calloc" );
01462        exit( LDAP_NO_MEMORY );
01463     }
01464 
01465     ctl->ldctl_iscritical = 1;
01466 
01467     return( ctl );
01468 }
01469 
01470 /*
01471  * if -y "dn" was supplied on the command line, create the control
01472  */
01473 LDAPControl *
01474 ldaptool_create_proxyauth_control( LDAP *ld )
01475 {
01476     LDAPControl      *ctl = NULL;
01477     int rc;
01478     
01479 
01480     if ( !proxyauth_id)
01481        return( NULL );
01482 
01483     if ( 2 == proxyauth_version ) {
01484        rc = ldap_create_proxiedauth_control( ld, proxyauth_id, &ctl);
01485     } else {
01486        rc = ldap_create_proxyauth_control( ld, proxyauth_id, 1, &ctl);
01487     }
01488     if ( rc != LDAP_SUCCESS) 
01489     {
01490        if (ctl)
01491            ldap_control_free( ctl);
01492        return NULL;
01493     }
01494     return( ctl );
01495 }
01496 
01497 void
01498 ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array)
01499 {
01500     
01501     int i;
01502     for (i=0; i< CONTROL_REQUESTS; i++)
01503     {
01504        if (*(array + i) == NULL)
01505        {
01506            *(array + i +1) = NULL;
01507            *(array + i) = ctrl;
01508            return ;
01509        }
01510     }
01511     fprintf(stderr, "%s: failed to store request control!!!!!!\n",
01512            ldaptool_progname);
01513 }
01514 
01515 /*
01516  * Dispose of all controls in array and prepare array for reuse.
01517  */
01518 void
01519 ldaptool_reset_control_array( LDAPControl **array )
01520 {
01521     int              i;
01522 
01523     for ( i = 0; i < CONTROL_REQUESTS; i++ ) {
01524        if ( array[i] != NULL ) {
01525            ldap_control_free( array[i] );
01526            array[i] = NULL;
01527        }
01528     }
01529 }
01530 
01531 /*
01532  * This function calculates control value and its length. *value can
01533  * be pointing to plain value, ":b64encoded value" or "<fileurl".
01534  */
01535 static int
01536 calculate_ctrl_value( const char *value,
01537        char **ctrl_value, int *vlen)
01538 {
01539     int b64;
01540     if (*value == ':') {
01541        value++;
01542        b64 = 1;
01543     } else {
01544        b64 = 0;
01545     }
01546     *ctrl_value = (char *)value;
01547 
01548     if ( b64 ) {
01549        if (( *vlen = ldif_base64_decode( (char *)value,
01550               (unsigned char *)value )) < 0 ) {
01551            fprintf( stderr, 
01552               "Unable to decode base64 control value \"%s\"\n", value);
01553            return( -1 );
01554        }
01555     } else {
01556        *vlen = (int)strlen(*ctrl_value);
01557     }
01558     return( 0 );
01559 }
01560 
01561 /*
01562  * Parse the optarg from -J option of ldapsearch
01563  * and within LDIFfile for ldapmodify. Take ctrl_arg 
01564  * (the whole string) and divide it into oid, criticality
01565  * and value. This function breaks down original ctrl_arg
01566  * with '\0' in places. Also, calculate length of valuestring.
01567  */
01568 int
01569 ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep,
01570               char **ctrl_oid, int *ctrl_criticality,
01571               char **ctrl_value, int *vlen)
01572 {
01573     char *s, *p, *d;
01574     int strict;
01575 
01576     /* Initialize passed variables with default values */
01577     *ctrl_oid = *ctrl_value = NULL;
01578     *ctrl_criticality = 0;
01579     *vlen = 0;
01580 
01581     strict = (sep == ' ' ? 1 : 0);
01582     if(!(s=strchr(ctrl_arg, sep))) {
01583        /* Possible values of ctrl_arg are 
01584         * oid[:value|::b64value|:<fileurl] within LDIF, i.e. sep=' '
01585         * oid from command line option, i.e. sep=':'
01586         */
01587        if (sep == ' ') {
01588            if (!(s=strchr(ctrl_arg, ':'))) {
01589               *ctrl_oid = ctrl_arg;
01590            }
01591            else {
01592               /* ctrl_arg is of oid:[value|:b64value|<fileurl]
01593                * form in the LDIF record. So, grab the oid and then
01594                * jump to continue the parsing of ctrl_arg.
01595                * 's' is pointing just after oid ends.
01596                */
01597               *s++ = '\0';
01598               *ctrl_oid = ctrl_arg;
01599               return (calculate_ctrl_value( s, ctrl_value, vlen ));
01600            }
01601        } else {
01602               /* oid - from command line option, i.e. sep=':' */
01603               *ctrl_oid = ctrl_arg;
01604        }
01605     }
01606     else {
01607        /* Possible values of ctrl_arg are
01608         * oid:criticality[:value|::b64value|:<fileurl] - command line
01609         * oid criticality[:value|::b64value|:<fileurl] - LDIF
01610         * And 's' is pointing just after oid ends.
01611         */
01612 
01613        if (*(s+1) == '\0') {
01614            fprintf( stderr, "missing value\n" );
01615            return( -1 );
01616        }
01617        *s = '\0';
01618        *ctrl_oid = ctrl_arg;
01619        p = ++s;
01620        if(!(s=strchr(p, ':'))) {
01621            if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
01622                      == -1 ) {
01623               fprintf( stderr, "Invalid criticality value\n" );
01624               return( -1 );
01625            }
01626        }
01627        else {
01628            if (*(s+1) == '\0') { 
01629                fprintf( stderr, "missing value\n" );
01630                return ( -1 );
01631            }
01632            *s++ = '\0';
01633             if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
01634                      == -1 ) {
01635               fprintf( stderr, "Invalid criticality value\n" );
01636               return ( -1 );
01637            }
01638            return (calculate_ctrl_value( s, ctrl_value, vlen ));
01639        }
01640     }
01641 
01642     return( 0 );
01643 }
01644 
01645 
01646 /*
01647  * callback function for LDAP bind credentials
01648  */
01649 static int
01650 LDAP_CALL
01651 LDAP_CALLBACK
01652 get_rebind_credentials( LDAP *ld, char **whop, char **credp,
01653         int *methodp, int freeit, void* arg )
01654 {
01655     if ( !freeit ) {
01656        *whop = binddn;
01657        *credp = passwd;
01658        *methodp = LDAP_AUTH_SIMPLE;
01659     }
01660 
01661     return( LDAP_SUCCESS );
01662 }
01663 
01664 
01665 /*
01666  * return pointer to pathname to temporary directory.
01667  * First we see if the environment variable "TEMP" is set and use it.
01668  * Then we see if the environment variable "TMP" is set and use it.
01669  * If this fails, we use "/tmp" on UNIX and fail on Windows.
01670  */
01671 char *
01672 ldaptool_get_tmp_dir( void )
01673 {
01674     char      *p;
01675     int              offset;
01676 
01677     if (( p = getenv( "TEMP" )) == NULL && ( p = getenv( "TMP" )) == NULL ) {
01678 #ifdef _WINDOWS
01679        fprintf( stderr, "%s: please set the TEMP environment variable.\n",
01680               ldaptool_progname );
01681        exit( LDAP_LOCAL_ERROR );
01682 #else
01683        return( "/tmp" );    /* last resort on UNIX */
01684 #endif
01685     }
01686 
01687     /*
01688      * remove trailing slash if present
01689      */
01690     offset = strlen( p ) - 1;
01691     if ( p[offset] == '/'
01692 #ifdef _WINDOWS
01693            || p[offset] == '\\'
01694 #endif
01695            ) {
01696        if (( p = strdup( p )) == NULL ) {
01697            perror( "strdup" );
01698            exit( LDAP_NO_MEMORY );
01699        }
01700 
01701        p[offset] = '\0';
01702     }
01703 
01704     return( p );
01705 }
01706 
01707 
01708 int
01709 ldaptool_berval_is_ascii( const struct berval *bvp )
01710 {
01711     unsigned long    j;
01712     int                     is_ascii = 1;  /* optimistic */
01713 
01714     for ( j = 0; j < bvp->bv_len; ++j ) {
01715        if ( !isascii( bvp->bv_val[ j ] )) {
01716            is_ascii = 0;
01717            break;
01718        }
01719     }
01720 
01721     return( is_ascii );
01722 }
01723 
01724 
01725 #ifdef LDAP_DEBUG_MEMORY   
01726 #define LDAPTOOL_ALLOC_FREED       0xF001
01727 #define LDAPTOOL_ALLOC_INUSE       0xF002
01728 
01729 static void *
01730 ldaptool_debug_alloc( void *ptr, size_t size )
01731 {
01732     int              *statusp;
01733     void      *systemptr;
01734 
01735     if ( ptr == NULL ) {
01736        systemptr = NULL;
01737     } else {
01738        systemptr = (void *)((char *)ptr - sizeof(int));
01739     }
01740 
01741     if (( statusp = (int *)realloc( systemptr, size + sizeof(int))) == NULL ) {
01742        fprintf( stderr, "%s: realloc( 0x%x, %d) failed\n",
01743               ldaptool_progname, systemptr, size );
01744        return( NULL );
01745     }
01746 
01747     *statusp = LDAPTOOL_ALLOC_INUSE;
01748 
01749     return( (char *)statusp + sizeof(int));
01750 }
01751 
01752 
01753 static void *
01754 ldaptool_debug_realloc( void *ptr, size_t size )
01755 {
01756     void      *p;
01757 
01758     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01759        fprintf( stderr, "%s: => realloc( 0x%x, %d )\n",
01760               ldaptool_progname, ptr, size );
01761     }
01762 
01763     p = ldaptool_debug_alloc( ptr, size );
01764 
01765     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01766        fprintf( stderr, "%s: 0x%x <= realloc()\n", ldaptool_progname, p );
01767     }
01768 
01769     return( p );
01770 }
01771 
01772 
01773 static void *
01774 ldaptool_debug_malloc( size_t size )
01775 {
01776     void      *p;
01777 
01778     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01779        fprintf( stderr, "%s: => malloc( %d)\n", ldaptool_progname, size );
01780     }
01781 
01782     p = ldaptool_debug_alloc( NULL, size );
01783 
01784     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01785        fprintf( stderr, "%s: 0x%x <= malloc()\n", ldaptool_progname, p );
01786     }
01787 
01788     return( p );
01789 }
01790 
01791 
01792 static void *
01793 ldaptool_debug_calloc( size_t nelem, size_t elsize )
01794 {
01795     void      *p;
01796 
01797     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01798        fprintf( stderr, "%s: => calloc( %d, %d )\n",
01799               ldaptool_progname, nelem, elsize );
01800     }
01801 
01802     if (( p = ldaptool_debug_alloc( NULL, nelem * elsize )) != NULL ) {
01803        memset( p, 0, nelem * elsize );
01804     }
01805 
01806     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01807        fprintf( stderr, "%s: 0x%x <= calloc()\n", ldaptool_progname, p );
01808     }
01809 
01810     return( p );
01811 }
01812 
01813 
01814 static void
01815 ldaptool_debug_free( void *ptr )
01816 {
01817     int              *statusp = (int *)((char *)ptr - sizeof(int));
01818 
01819     if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
01820        fprintf( stderr, "%s: => free( 0x%x )\n", ldaptool_progname, ptr );
01821     }
01822 
01823     if ( ptr == NULL ) {
01824        fprintf( stderr, "%s: bad free( 0x0 ) attempted (NULL pointer)\n",
01825               ldaptool_progname );
01826     } else if ( *statusp != LDAPTOOL_ALLOC_INUSE ) {
01827        fprintf( stderr, "%s: bad free( 0x%x ) attempted"
01828               " (block not in use; status is %d)\n",
01829               ldaptool_progname, ptr, *statusp );
01830     } else {
01831        *statusp = LDAPTOOL_ALLOC_FREED;
01832        free( statusp );
01833     }
01834 }
01835 #endif /* LDAP_DEBUG_MEMORY */
01836 
01837 
01838 #if defined(NET_SSL)
01839 /*
01840  * Derive key database path from certificate database path and return a
01841  * malloc'd string.
01842  *
01843  * We just return an exact copy of "certdbpath" unless it ends in "cert.db",
01844  * "cert5.db", or "cert7.db".  In those cases we strip off everything from
01845  * "cert" on and append "key.db", "key5.db", or "key3.db" as appropriate.
01846  * Strangely enough cert7.db and key3.db go together.
01847  */
01848 static char *
01849 certpath2keypath( char *certdbpath )
01850 {
01851     char      *keydbpath, *appendstr;
01852     int              len, striplen;
01853 
01854     if ( certdbpath == NULL ) {
01855        return( NULL );
01856     }
01857 
01858     if (( keydbpath = strdup( certdbpath )) == NULL ) {
01859        perror( "strdup" );
01860        exit( LDAP_NO_MEMORY );
01861     }
01862 
01863     len = strlen( keydbpath );
01864     if ( len > 7 &&
01865            strcasecmp( "cert.db", keydbpath + len - 7 ) == 0 ) {
01866        striplen = 7;
01867        appendstr = "key.db";
01868        
01869     } else if ( len > 8 &&
01870            strcasecmp( "cert5.db", keydbpath + len - 8 ) == 0 ) {
01871        striplen = 8;
01872        appendstr = "key5.db";
01873     } else if ( len > 8 &&
01874            strcasecmp( "cert7.db", keydbpath + len - 8 ) == 0 ) {
01875        striplen = 8;
01876        appendstr = "key3.db";
01877     } else {
01878        striplen = 0;
01879     }
01880 
01881     if ( striplen > 0 ) {
01882        /*
01883         * The following code assumes that strlen( appendstr ) < striplen!
01884         */
01885        strcpy( keydbpath + len - striplen, appendstr );
01886     }
01887 
01888     return( keydbpath );
01889 }
01890 
01891 #ifdef LDAP_TOOL_PKCS11
01892 static 
01893 char * 
01894 buildTokenCertName( const char *tokenName, const char *certName)
01895 {
01896     
01897     int tokenlen = strlen(tokenName);
01898     int len = tokenlen + strlen(certName) +2;
01899     char *result;
01900     
01901     if (( result = malloc( len )) != NULL) {
01902        strcpy(result, tokenName);
01903        *(result+tokenlen) = ':';
01904        ++tokenlen;
01905        strcpy(result+tokenlen, certName);
01906     } else {
01907        perror("malloc");
01908        exit( LDAP_NO_MEMORY );
01909     }
01910     return result;
01911 }
01912 
01913 
01914 
01915 static
01916 int
01917 ldaptool_getcertpath( void *context, char **certlocp )
01918 {
01919     
01920     *certlocp = ssl_certdbpath;
01921     if ( ldaptool_verbose ) {
01922        if (ssl_certdbpath)
01923        {
01924            printf("ldaptool_getcertpath -- %s\n", ssl_certdbpath );
01925        }
01926        else
01927        {
01928            printf("ldaptool_getcertpath -- (null)\n");
01929        }
01930        
01931     }
01932     return LDAP_SUCCESS;
01933 }
01934 
01935 int
01936 ldaptool_getcertname( void *context, char **certnamep )
01937 { 
01938     
01939    *certnamep = ssl_certname;
01940     if ( ldaptool_verbose ) {
01941        if (ssl_certname)
01942        {
01943            printf("ldaptool_getcertname -- %s\n", *certnamep);
01944        }
01945        else
01946        {
01947            printf("ldaptool_getcertname -- (null)\n");
01948        }
01949     }
01950     return LDAP_SUCCESS;
01951 }
01952 
01953 int
01954 ldaptool_getkeypath(void *context, char **keylocp )
01955 {
01956     *keylocp = ssl_keydbpath;
01957     if ( ldaptool_verbose ) {
01958        if (ssl_keydbpath)
01959        {
01960            printf("ldaptool_getkeypath -- %s\n",*keylocp);
01961        }
01962        else
01963        {
01964            printf("ldaptool_getkeypath -- (null)\n");
01965        }
01966     }
01967     
01968     return LDAP_SUCCESS;
01969 }
01970 
01971 int
01972 ldaptool_gettokenname( void *context, char **tokennamep )
01973 {
01974     
01975     *tokennamep = pkcs_token;
01976     if ( ldaptool_verbose ) {
01977        if (pkcs_token)
01978        {
01979            printf("ldaptool_gettokenname -- %s\n",*tokennamep);
01980        }
01981        else
01982        {
01983            printf("ldaptool_gettokenname -- (null)\n");
01984        }
01985     }
01986 
01987     return LDAP_SUCCESS;
01988 }
01989 int
01990 ldaptool_gettokenpin( void *context, const char *tokennamep, char **tokenpinp)
01991 {
01992   
01993 #if 0
01994   char *localtoken;
01995 #endif
01996 
01997 /* XXXceb this stuff is removed for the time being.  
01998  * This function should return the pin from ssl_password
01999  */
02000 
02001 
02002   *tokenpinp = ssl_passwd;
02003   return LDAP_SUCCESS;
02004   
02005 #if 0
02006 
02007   ldaptool_gettokenname( NULL, &localtoken);
02008 
02009   if (strcmp( localtoken, tokennamep))
02010 
02011       *tokenpinp = pkcs_pin;
02012    else 
02013       *tokenpinp = NULL;
02014 
02015     if ( ldaptool_verbose ) {
02016        if (pkcs_pin)
02017        {
02018            printf("ldaptool_getokenpin --%s\n", tokenpinp);
02019        }
02020        else
02021        {
02022            printf("ldaptool_getokenpin -- (null)\n");
02023        }
02024     }
02025     return LDAP_SUCCESS;
02026 #endif
02027 }
02028 
02029 int
02030 ldaptool_getmodpath( void *context, char **modulep )
02031 {
02032     *modulep = ssl_secmodpath;
02033     if ( ldaptool_verbose ) {
02034        if (ssl_secmodpath)
02035        {
02036            printf("ldaptool_getmodpath -- %s\n", *modulep);
02037        }
02038        else
02039        {
02040            printf("ldaptool_getmodpath -- (null)\n");
02041        }
02042     }
02043     
02044     return LDAP_SUCCESS;
02045 }
02046 
02047 int
02048 ldaptool_getdonglefilename( void *context, char **filename )
02049 {
02050     *filename = ssl_donglefile;
02051     if ( ldaptool_verbose ) {
02052        if (ssl_donglefile)
02053        {
02054            printf("ldaptool_getdonglefilename -- %s\n", *filename);
02055        }
02056        else
02057        {
02058            printf("ldaptool_getdonglefilename -- (null)\n");
02059        }
02060        
02061     }
02062     
02063     return LDAP_SUCCESS;
02064 }
02065 
02066 static int
02067 ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns)
02068 {
02069   pfns->pkcs_getcertpath = (int (*)(void *, char **))ldaptool_getcertpath;
02070   pfns->pkcs_getcertname =  (int (*)(void *, char **))ldaptool_getcertname;
02071   pfns->pkcs_getkeypath =  (int (*)(void *, char **)) ldaptool_getkeypath;
02072   pfns->pkcs_getmodpath =  (int (*)(void *, char **)) ldaptool_getmodpath;
02073   pfns->pkcs_getpin =  (int (*)(void *, const char*, char **)) ldaptool_gettokenpin;
02074   pfns->pkcs_gettokenname =  (int (*)(void *, char **)) ldaptool_gettokenname;
02075   pfns->pkcs_getdonglefilename =  (int (*)(void *, char **)) ldaptool_getdonglefilename;
02076   pfns->local_structure_id=PKCS_STRUCTURE_ID;
02077   return LDAP_SUCCESS;
02078 }
02079 
02080 
02081 
02082 #ifdef FORTEZZA
02083 static int
02084 ldaptool_fortezza_init( int exit_on_error )
02085 {
02086     int              rc, errcode;
02087 
02088     if ( fortezza_personality == NULL && fortezza_cardmask == 0 ) { /* no FORTEZZA desired */
02089        SSL_EnableGroup( SSL_GroupFortezza, DSFalse );   /* disable FORTEZZA */
02090        return( 0 );
02091     }
02092 
02093     if (( rc = FortezzaConfigureServer( ldaptool_fortezza_getpin, fortezza_cardmask,
02094            fortezza_personality, ldaptool_fortezza_alert, NULL, &errcode,
02095            fortezza_krlfile )) < 0 ) {
02096        fprintf( stderr,
02097               "%s: FORTEZZA initialization failed (error %d - %s)\n",
02098               ldaptool_progname, errcode,
02099               ldaptool_fortezza_err2string( errcode ));
02100        if ( exit_on_error ) {
02101            exit( LDAP_LOCAL_ERROR );
02102        }
02103 
02104        SSL_EnableGroup( SSL_GroupFortezza, DSFalse );   /* disable FORTEZZA */
02105        return( -1 );
02106     }
02107 
02108     SSL_EnableGroup( SSL_GroupFortezza, DSTrue );       /* enable FORTEZZA */
02109     return( 0 );
02110 }
02111 
02112 
02113 static int
02114 ldaptool_fortezza_alert( void *arg, PRBool onOpen, char *string,
02115        int value1, void *value2 )
02116 {
02117     fprintf( stderr, "%s: FORTEZZA alert: ", ldaptool_progname );
02118     fprintf( stderr, string, value1, value2 );
02119     fprintf( stderr, "\n" );
02120     return( 1 );
02121 }
02122 
02123 
02124 static void *
02125 ldaptool_fortezza_getpin( char **passwordp )
02126 {
02127     *passwordp = fortezza_pin;
02128     return( *passwordp );
02129 }
02130 
02131 
02132 /*
02133  * convert a Fortezza error code (as returned by FortezzaConfigureServer()
02134  * into a human-readable string.
02135  *
02136  * Error strings are intentionally similar to those found in
02137  * ns/netsite/lib/libadmin/httpcon.c
02138  */
02139 static char *
02140 ldaptool_fortezza_err2string( int err )
02141 {
02142     char      *s;
02143 
02144     switch( err ) {
02145     case FORTEZZA_BADPASSWD:
02146        s = "invalid pin number";
02147        break;
02148     case FORTEZZA_BADCARD:
02149        s = "bad or missing card";
02150        break;
02151     case FORTEZZA_MISSING_KRL:
02152        s = "bad or missing compromised key list";
02153        break;
02154     case FORTEZZA_CERT_INIT_ERROR:
02155        s = "unable to initialize certificate cache.  either a cert on "
02156               "the card is bad, or an old FORTEZZA certificate is in a"
02157                "readonly database";
02158        break;
02159     case FORTEZZA_EXPIRED_CERT:
02160        s = "unable to verify certificate";
02161        break;
02162     default:
02163        s = "unknown error";
02164     }
02165 
02166     return( s );
02167 }
02168 
02169 #endif /* FORTEZZA */
02170 #endif /* LDAP_TOOL_PKCS11 */
02171 #endif /* NET_SSL */
02172 
02173 int
02174 ldaptool_boolean_str2value ( const char *ptr, int strict )
02175 {
02176     if (strict) {
02177        if ( !(strcasecmp(ptr, "true"))) {
02178            return 1;
02179        }
02180        else if ( !(strcasecmp(ptr, "false"))) {
02181            return 0;
02182        }
02183        else {
02184            return (-1);
02185        }
02186     }
02187     else {
02188        if ( !(strcasecmp(ptr, "true")) ||
02189             !(strcasecmp(ptr, "t")) ||
02190             !(strcmp(ptr, "1")) ) {
02191               return (1);
02192        }
02193        else if ( !(strcasecmp(ptr, "false")) ||
02194             !(strcasecmp(ptr, "f")) ||
02195             !(strcmp(ptr, "0")) ) {
02196               return (0);
02197        }
02198        else { 
02199            return (-1);
02200        }      
02201     }
02202 }