mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 11:40:13 +01:00
2203 lines
57 KiB
C
2203 lines
57 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
* March 31, 1998.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998-1999
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/*
|
|
* code that is shared by two or more of the LDAP command line tools
|
|
*/
|
|
|
|
#include "ldaptool.h"
|
|
#include "fileurl.h"
|
|
|
|
#ifdef LDAP_TOOL_ARGPIN
|
|
#include "argpin.h"
|
|
#include "ntuserpin.h"
|
|
#endif /* LDAP_TOOL_ARGPIN */
|
|
|
|
#include <nspr.h> /* for PR_Cleanup() */
|
|
#include <stdlib.h>
|
|
#include <time.h> /* for time() and ctime() */
|
|
|
|
static LDAP_REBINDPROC_CALLBACK get_rebind_credentials;
|
|
static void print_library_info( const LDAPAPIInfo *aip, FILE *fp );
|
|
static int wait4result( LDAP *ld, int msgid, struct berval **servercredp,
|
|
char *msg );
|
|
static int parse_result( LDAP *ld, LDAPMessage *res,
|
|
struct berval **servercredp, char *msg, int freeit );
|
|
|
|
#ifdef LDAPTOOL_DEBUG_MEMORY
|
|
static void *ldaptool_debug_malloc( size_t size );
|
|
static void *ldaptool_debug_calloc( size_t nelem, size_t elsize );
|
|
static void *ldaptool_debug_realloc( void *ptr, size_t size );
|
|
static void ldaptool_debug_free( void *ptr );
|
|
#endif /* LDAPTOOL_DEBUG_MEMORY */
|
|
|
|
#if defined(NET_SSL)
|
|
static char *certpath2keypath( char *certdbpath );
|
|
static int ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns);
|
|
static char * buildTokenCertName( const char *tokenName, const char *certName);
|
|
#ifdef FORTEZZA
|
|
static int ldaptool_fortezza_init( int exit_on_error );
|
|
static int ldaptool_fortezza_alert( void *arg, PRBool onOpen,
|
|
char *string, int value1, void *value2 );
|
|
static void * ldaptool_fortezza_getpin( char **passwordp );
|
|
static char * ldaptool_fortezza_err2string( int err );
|
|
#endif /* FORTEZZA */
|
|
#endif
|
|
|
|
/*
|
|
* display usage for common options with one exception: -f is not included
|
|
* since the description tends to be tool-specific.
|
|
*
|
|
* As of 1-Jul-1998, of the characters in the set [A-Za-z] the following are
|
|
* not currently used by any of the tools: EJgjqr
|
|
*/
|
|
void
|
|
ldaptool_common_usage( int two_hosts )
|
|
{
|
|
fprintf( stderr, " -n\t\tshow what would be done but don't actually do it\n" );
|
|
fprintf( stderr, " -v\t\trun in verbose mode (diagnostics to standard output)\n" );
|
|
if ( two_hosts ) {
|
|
fprintf( stderr, " -h host\tLDAP server1 name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
|
|
fprintf( stderr, " -p port\tLDAP server1 TCP port number (default: %d)\n", LDAP_PORT );
|
|
fprintf( stderr, " -h host\tLDAP server2 name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
|
|
fprintf( stderr, " -p port\tLDAP server2 TCP port number (default: %d)\n", LDAP_PORT );
|
|
} else {
|
|
fprintf( stderr, " -h host\tLDAP server name or IP address (default: %s)\n", LDAPTOOL_DEFHOST );
|
|
fprintf( stderr, " -p port\tLDAP server TCP port number (default: %d)\n", LDAP_PORT );
|
|
}
|
|
fprintf( stderr,
|
|
" -V n\tLDAP protocol version number (%d or %d; default: %d)\n",
|
|
LDAP_VERSION2, LDAP_VERSION3, LDAP_VERSION3 );
|
|
#if defined(NET_SSL)
|
|
fprintf( stderr, " -Z\t\tmake an SSL-encrypted connection\n" );
|
|
fprintf( stderr, " -P pathname\tpath to SSL certificate database (default: current directory)\n" );
|
|
fprintf( stderr, " -N\t\tname of certificate to use for SSL client authentication\n" );
|
|
fprintf( stderr, " -K pathname\tpath to key database to use for SSL client authentication\n" );
|
|
fprintf( stderr, " \t\t(default: path to certificate database provided with -P option)\n" );
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
fprintf( stderr, " -m pathname\tpath to security module database\n");
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
fprintf( stderr, " -W\t\tSSL key password\n" );
|
|
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
fprintf( stderr, " -Q [token][:certificate name]\tPKCS 11\n" );
|
|
fprintf( stderr, " -X pathname\tFORTEZZA compromised key list (CKL)\n" );
|
|
fprintf( stderr, " -I pin\tcard password file\n" );
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
|
|
#endif /* NET_SSL */
|
|
fprintf( stderr, " -D binddn\tbind dn\n" );
|
|
fprintf( stderr, " -w passwd\tbind passwd (for simple authentication)\n" );
|
|
fprintf( stderr, " -w - \tprompt for bind passwd (for simple authentication)\n" );
|
|
fprintf( stderr, " -j file\tread bind passwd from 'file' (for simple authentication)\n" );
|
|
fprintf( stderr, " -E\t\task server to expose (report) bind identity\n" );
|
|
#ifdef LDAP_DEBUG
|
|
fprintf( stderr, " -d level\tset LDAP debugging level to `level'\n" );
|
|
#endif
|
|
fprintf( stderr, " -R\t\tdo not automatically follow referrals\n" );
|
|
fprintf( stderr, " -O limit\tmaximum number of referral hops to traverse (default: %d)\n", LDAPTOOL_DEFREFHOPLIMIT );
|
|
fprintf( stderr, " -M\t\tmanage references (treat them as regular entries)\n" );
|
|
fprintf( stderr, " -0\t\tignore LDAP library version mismatches\n" );
|
|
|
|
#ifndef NO_LIBLCACHE
|
|
fprintf( stderr, " -C cfgfile\tuse local database described by cfgfile\n" );
|
|
#endif
|
|
fprintf( stderr, " -i charset\tcharacter set for command line input (default taken from locale)\n" );
|
|
fprintf( stderr, " -k dir\tconversion routine directory (default: current directory)\n" );
|
|
#if 0
|
|
/*
|
|
* Suppress usage for -y (old proxied authorization control) even though
|
|
* we still support it. We want to encourage people to use -Y instead (the
|
|
* new proxied authorization control).
|
|
*/
|
|
fprintf( stderr, " -y proxydn\tDN used for proxy authorization\n" );
|
|
#endif
|
|
fprintf( stderr, " -Y proxyid\tproxied authorization id,\n" );
|
|
fprintf( stderr, " \te.g, dn:uid=bjensen,dc=example,dc=com\n" );
|
|
fprintf( stderr, " -H\t\tdisplay usage information\n" );
|
|
fprintf( stderr, " -J controloid[:criticality[:value|::b64value|:<fileurl]]\n" );
|
|
fprintf( stderr, "\t\tcriticality is a boolean value (default is false)\n" );
|
|
}
|
|
|
|
/* globals */
|
|
char *ldaptool_charset = "";
|
|
char *ldaptool_host = LDAPTOOL_DEFHOST;
|
|
char *ldaptool_host2 = LDAPTOOL_DEFHOST;
|
|
int ldaptool_port = LDAP_PORT;
|
|
int ldaptool_port2 = LDAP_PORT;
|
|
int ldaptool_verbose = 0;
|
|
int ldaptool_not = 0;
|
|
FILE *ldaptool_fp = NULL;
|
|
FILE *password_fp = NULL;
|
|
char *ldaptool_progname = "";
|
|
char *ldaptool_nls_lang = NULL;
|
|
char *proxyauth_id = NULL;
|
|
int proxyauth_version = 2; /* use newer proxy control */
|
|
LDAPControl *ldaptool_request_ctrls[CONTROL_REQUESTS] = {0};
|
|
#ifdef LDAP_DEBUG
|
|
int ldaptool_dbg_lvl = 0;
|
|
#endif /* LDAP_DEBUG */
|
|
|
|
/* statics */
|
|
static char *binddn = NULL;
|
|
static char *passwd = NULL;
|
|
static int send_auth_response_ctrl = 0;
|
|
static int user_specified_port = 0;
|
|
static int user_specified_port2 = 0;
|
|
static int chase_referrals = 1;
|
|
static int lib_version_mismatch_is_fatal = 1;
|
|
static int ldversion = -1; /* use default */
|
|
static int refhoplim = LDAPTOOL_DEFREFHOPLIMIT;
|
|
static int send_manage_dsait_ctrl = 0;
|
|
static int prompt_password = 0;
|
|
|
|
#ifndef NO_LIBLCACHE
|
|
static char *cache_config_file = NULL;
|
|
#endif /* !NO_LIBLCACHE */
|
|
#if defined(NET_SSL)
|
|
static int secure = 0;
|
|
static int isZ = 0;
|
|
static int isN = 0;
|
|
static int isW = 0;
|
|
static int isw = 0;
|
|
static int isD = 0;
|
|
static int isj = 0;
|
|
static char *ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH;
|
|
static char *ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH;
|
|
/*
|
|
static char *ssl_keyname = NULL;
|
|
*/
|
|
static char *ssl_certname = NULL;
|
|
static char *ssl_passwd = NULL;
|
|
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
static char *ssl_secmodpath = NULL;
|
|
|
|
static char *pkcs_token = NULL;
|
|
|
|
static char *ssl_donglefile = NULL;
|
|
|
|
#if 0
|
|
static char *pkcs_pin = NULL;
|
|
#endif
|
|
static struct ldapssl_pkcs_fns local_pkcs_fns =
|
|
{0,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL };
|
|
|
|
#ifdef FORTEZZA
|
|
static uint32 fortezza_cardmask = 0;
|
|
static char *fortezza_personality = NULL;
|
|
static char *fortezza_krlfile = NULL;
|
|
static char *fortezza_pin = NULL;
|
|
#endif /* FORTEZZA */
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
#endif /* NET_SSL */
|
|
|
|
|
|
|
|
/*
|
|
* Handle general initialization and options that are common to all of
|
|
* the LDAP tools.
|
|
* Handle options that are common to all of the LDAP tools.
|
|
* Note the the H option is included here but handled via the
|
|
* extra_opt_callback function (along with any "extra_opts" ).
|
|
*
|
|
* Return: final value for optind or -1 if usage should be displayed (for
|
|
* some fatal errors, we call exit here).
|
|
*/
|
|
int
|
|
ldaptool_process_args( int argc, char **argv, char *extra_opts,
|
|
int two_hosts, void (*extra_opt_callback)( int option, char *optarg ))
|
|
{
|
|
int rc, i, hostnum;
|
|
char *optstring, *common_opts;
|
|
extern char *optarg;
|
|
extern int optind;
|
|
LDAPAPIInfo ldai;
|
|
char *ctrl_arg, *ctrl_oid=NULL, *ctrl_value=NULL;
|
|
int ctrl_criticality=0, vlen;
|
|
LDAPControl *ldctrl;
|
|
|
|
/*
|
|
* Set program name global based on argv[0].
|
|
*/
|
|
if (( ldaptool_progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
|
|
ldaptool_progname = argv[ 0 ];
|
|
} else {
|
|
++ldaptool_progname;
|
|
}
|
|
|
|
#ifdef LDAPTOOL_DEBUG_MEMORY
|
|
{
|
|
struct ldap_memalloc_fns mafns = {
|
|
ldaptool_debug_malloc,
|
|
ldaptool_debug_calloc,
|
|
ldaptool_debug_realloc,
|
|
ldaptool_debug_free
|
|
};
|
|
|
|
ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &mafns );
|
|
}
|
|
#endif /* LDAPTOOL_DEBUG_MEMORY */
|
|
|
|
#ifdef LDAP_DEBUG
|
|
i = LDAP_DEBUG_ANY;
|
|
ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, (void *) &i);
|
|
#endif
|
|
|
|
/*
|
|
* Perform a sanity check on the revision of the LDAP API library to
|
|
* make sure it is at least as new as the one we were compiled against.
|
|
* If the API implementation is from the same vendor as we were compiled
|
|
* against, we also check to make sure the vendor version is at least
|
|
* as new as the library we were compiled against.
|
|
*
|
|
* Version differences are fatal unless the -0 option is passed on the
|
|
* tool command line (that's a zero, not an oh). We check for the
|
|
* presence of -0 in a crude way to it must appear by itself in argv.
|
|
*/
|
|
for ( i = 1; i < argc; ++i ) {
|
|
if ( strcmp( argv[i], "-0" ) == 0 ) {
|
|
lib_version_mismatch_is_fatal = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
memset( &ldai, 0, sizeof(ldai));
|
|
ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
|
|
if (( rc = ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldai )) != 0 ) {
|
|
fprintf( stderr, "%s: unable to retrieve LDAP library version"
|
|
" information;\n\tthis program requires an LDAP library that"
|
|
" implements revision\n\t%d or greater of the LDAP API.\n",
|
|
ldaptool_progname, LDAP_API_VERSION );
|
|
if ( lib_version_mismatch_is_fatal ) {
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
} else if ( ldai.ldapai_api_version < LDAP_API_VERSION ) {
|
|
fprintf( stderr, "%s: this program requires an LDAP library that"
|
|
" implements revision\n\t%d or greater of the LDAP API;"
|
|
" running with revision %d.\n",
|
|
ldaptool_progname, LDAP_API_VERSION, ldai.ldapai_api_version );
|
|
if ( lib_version_mismatch_is_fatal ) {
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
} else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) == 0
|
|
&& ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
|
|
fprintf( stderr, "%s: this program requires %s's LDAP\n"
|
|
"\tlibrary version %2.2f or greater; running with"
|
|
" version %2.2f.\n",
|
|
ldaptool_progname, LDAP_VENDOR_NAME,
|
|
(float)LDAP_VENDOR_VERSION / 100,
|
|
(float)ldai.ldapai_vendor_version / 100 );
|
|
if ( lib_version_mismatch_is_fatal ) {
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Process command line options.
|
|
*/
|
|
if ( extra_opts == NULL ) {
|
|
extra_opts = "";
|
|
}
|
|
|
|
common_opts = "nvEMRHZ0d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
|
|
|
|
/* note: optstring must include room for liblcache "C:" option */
|
|
if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts )
|
|
+ 3 )) == NULL ) {
|
|
perror( "malloc" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
#ifdef NO_LIBLCACHE
|
|
sprintf( optstring, "%s%s", common_opts, extra_opts );
|
|
#else
|
|
sprintf( optstring, "%s%sC:", common_opts, extra_opts );
|
|
#endif
|
|
|
|
hostnum = 0;
|
|
while ( (i = getopt( argc, argv, optstring )) != EOF ) {
|
|
switch( i ) {
|
|
case 'n': /* do Not do any LDAP operations */
|
|
++ldaptool_not;
|
|
break;
|
|
case 'v': /* verbose mode */
|
|
++ldaptool_verbose;
|
|
break;
|
|
case 'd':
|
|
#ifdef LDAP_DEBUG
|
|
ldaptool_dbg_lvl = atoi( optarg ); /* */
|
|
ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
|
|
(void *)&ldaptool_dbg_lvl);
|
|
ldaptool_dbg_lvl |= LDAP_DEBUG_ANY;
|
|
ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL,
|
|
(void *)&ldaptool_dbg_lvl);
|
|
#else /* LDAP_DEBUG */
|
|
fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
|
|
#endif /* LDAP_DEBUG */
|
|
break;
|
|
case 'R': /* don't automatically chase referrals */
|
|
chase_referrals = 0;
|
|
break;
|
|
#ifndef NO_LIBLCACHE
|
|
case 'C': /* search local database */
|
|
cache_config_file = strdup( optarg );
|
|
break;
|
|
#endif
|
|
case 'f': /* input file */
|
|
if ( optarg[0] == '-' && optarg[1] == '\0' ) {
|
|
ldaptool_fp = stdin;
|
|
} else if (( ldaptool_fp = fopen( optarg, "r" )) == NULL ) {
|
|
perror( optarg );
|
|
exit( LDAP_PARAM_ERROR );
|
|
}
|
|
break;
|
|
case 'h': /* ldap host */
|
|
if ( hostnum == 0 ) {
|
|
ldaptool_host = strdup( optarg );
|
|
} else {
|
|
ldaptool_host2 = strdup( optarg );
|
|
}
|
|
++hostnum;
|
|
break;
|
|
case 'D': /* bind DN */
|
|
isD = 1;
|
|
binddn = strdup( optarg );
|
|
break;
|
|
case 'E': /* expose bind identity via auth. response control */
|
|
++send_auth_response_ctrl;
|
|
break;
|
|
|
|
case 'p': /* ldap port */
|
|
if ( !user_specified_port ) {
|
|
++user_specified_port;
|
|
ldaptool_port = atoi( optarg );
|
|
} else {
|
|
++user_specified_port2;
|
|
ldaptool_port2 = atoi( optarg );
|
|
}
|
|
break;
|
|
#if defined(NET_SSL)
|
|
case 'P': /* path to security database */
|
|
secure = 1; /* do SSL encryption */
|
|
ssl_certdbpath = strdup( optarg );
|
|
if (NULL== ssl_keydbpath)
|
|
{
|
|
ssl_keydbpath = certpath2keypath( ssl_certdbpath );
|
|
}
|
|
break;
|
|
case 'Z': /* do SSL encryption */
|
|
secure = 1;
|
|
isZ = 1;
|
|
break;
|
|
case 'N': /* nickname of cert. to use for client auth. */
|
|
ssl_certname = strdup( optarg );
|
|
if (NULL == ssl_certname)
|
|
{
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
isN = 1;
|
|
break;
|
|
case 'K': /* location of key database */
|
|
/* if keydb path is not null, then it was probably strdup by the
|
|
* cert db option. free it first
|
|
*/
|
|
if (ssl_keydbpath)
|
|
free( ssl_keydbpath);
|
|
|
|
ssl_keydbpath = strdup( optarg );
|
|
if (NULL == ssl_keydbpath)
|
|
{
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
break;
|
|
case 'W': /* SSL key password */
|
|
ssl_passwd = strdup( optarg );
|
|
if (NULL == ssl_passwd)
|
|
{
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
isW = 1;
|
|
break;
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
case 'm': /* SSL secmod path */
|
|
ssl_secmodpath = strdup( optarg);
|
|
if (NULL == ssl_secmodpath)
|
|
{
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
break;
|
|
|
|
case 'Q': /* FORTEZZA [card][:personality] */
|
|
pkcs_token = strdup(optarg);
|
|
if (NULL == pkcs_token)
|
|
{
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
break;
|
|
case 'X': /* path to FORTEZZA CKL file */
|
|
/*
|
|
fortezza_krlfile = strdup( optarg );
|
|
*/
|
|
|
|
break;
|
|
case 'I': /* FORTEZZA PIN (password file) */
|
|
ssl_donglefile = strdup( optarg );
|
|
|
|
break;
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
|
|
#endif /* NET_SSL */
|
|
case 'w': /* bind password */
|
|
isw = 1;
|
|
if ( optarg[0] == '-' && optarg[1] == '\0' )
|
|
prompt_password = 1;
|
|
else
|
|
passwd = strdup( optarg );
|
|
break;
|
|
case 'j': /* bind password from file */
|
|
isj = 1;
|
|
if ((password_fp = fopen( optarg, "r" )) == NULL ) {
|
|
fprintf(stderr, "%s: Unable to open '%s' file\n",
|
|
ldaptool_progname, optarg);
|
|
exit( LDAP_PARAM_ERROR );
|
|
}
|
|
break;
|
|
case 'O': /* referral hop limit */
|
|
refhoplim = atoi( optarg );
|
|
break;
|
|
case 'V': /* protocol version */
|
|
ldversion = atoi (optarg);
|
|
if ( ldversion != LDAP_VERSION2 && ldversion != LDAP_VERSION3 ) {
|
|
fprintf( stderr, "%s: LDAP protocol version %d is not "
|
|
"supported (use -V%d or -V%d)\n",
|
|
ldaptool_progname, ldversion, LDAP_VERSION2,
|
|
LDAP_VERSION3 );
|
|
exit( LDAP_PARAM_ERROR );
|
|
}
|
|
break;
|
|
case 'M': /* send a manageDsaIT control */
|
|
send_manage_dsait_ctrl = 1;
|
|
break;
|
|
|
|
case 'i': /* character set specified */
|
|
ldaptool_charset = strdup( optarg );
|
|
if (NULL == ldaptool_charset)
|
|
{
|
|
perror( "malloc" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
break;
|
|
case 'k': /* conversion directory */
|
|
ldaptool_convdir = strdup( optarg );
|
|
if (NULL == ldaptool_convdir)
|
|
{
|
|
perror( "malloc" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
break;
|
|
case 'y': /* old (version 1) proxied authorization control */
|
|
proxyauth_version = 1;
|
|
case 'Y': /* new (version 2 ) proxied authorization control */
|
|
/*FALLTHRU*/
|
|
proxyauth_id = strdup(optarg);
|
|
if (NULL == proxyauth_id)
|
|
{
|
|
perror( "malloc" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
break;
|
|
|
|
case '0': /* zero -- override LDAP library version check */
|
|
break; /* already handled above */
|
|
case 'J':
|
|
if ( (ctrl_arg = strdup( optarg)) == NULL ) {
|
|
perror ("strdup");
|
|
exit (LDAP_NO_MEMORY);
|
|
}
|
|
if (ldaptool_parse_ctrl_arg(ctrl_arg, ':', &ctrl_oid,
|
|
&ctrl_criticality, &ctrl_value, &vlen)) {
|
|
return (-1);
|
|
}
|
|
ldctrl = calloc(1,sizeof(LDAPControl));
|
|
if (ctrl_value) {
|
|
rc = ldaptool_berval_from_ldif_value( ctrl_value,
|
|
vlen, &(ldctrl->ldctl_value),
|
|
1 /* recognize file URLs */,
|
|
0 /* always try file */,
|
|
1 /* report errors */ );
|
|
if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) {
|
|
fprintf( stderr, "Unable to parse %s\n", ctrl_value);
|
|
return (-1);
|
|
}
|
|
}
|
|
ldctrl->ldctl_oid = ctrl_oid;
|
|
ldctrl->ldctl_iscritical = ctrl_criticality;
|
|
ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls);
|
|
break;
|
|
default:
|
|
(*extra_opt_callback)( i, optarg );
|
|
}
|
|
}
|
|
|
|
/* If '-Z' is specified, check if '-P' is specified too. */
|
|
if ( isN || isW ) {
|
|
if ( !isZ ) {
|
|
printf( "%s: with -N, -W options, please specify -Z\n\n", ldaptool_progname );
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
if ( isj && isw ) {
|
|
fprintf(stderr, "%s: -j and -w options cannot be specified simultaneously\n\n", ldaptool_progname );
|
|
return (-1);
|
|
}
|
|
|
|
if ( (isj || isw) && !isD ) {
|
|
fprintf(stderr, "%s: with -j, -w options, please specify -D\n\n", ldaptool_progname );
|
|
return (-1);
|
|
}
|
|
|
|
if (prompt_password != 0) {
|
|
char *password_string = "Enter bind password: ";
|
|
char pbuf[257];
|
|
|
|
#if defined(_WIN32)
|
|
fputs(password_string,stdout);
|
|
fflush(stdout);
|
|
if (fgets(pbuf,256,stdin) == NULL) {
|
|
passwd = NULL;
|
|
} else {
|
|
char *tmp;
|
|
|
|
tmp = strchr(pbuf,'\n');
|
|
if (tmp) *tmp = '\0';
|
|
tmp = strchr(pbuf,'\r');
|
|
if (tmp) *tmp = '\0';
|
|
passwd = strdup(pbuf);
|
|
}
|
|
#else
|
|
#if defined(SOLARIS)
|
|
/* 256 characters on Solaris */
|
|
passwd = getpassphrase(password_string);
|
|
#else
|
|
/* limited to 16 chars on Tru64, 32 on AIX */
|
|
passwd = getpass(password_string);
|
|
#endif
|
|
#endif
|
|
|
|
} else if (password_fp != NULL) {
|
|
char *linep = NULL;
|
|
int increment = 0;
|
|
int c, index;
|
|
|
|
/* allocate initial block of memory */
|
|
if ((linep = (char *)malloc(BUFSIZ)) == NULL) {
|
|
fprintf( stderr, "%s: not enough memory to read password from file\n", ldaptool_progname );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
increment++;
|
|
index = 0;
|
|
while ((c = fgetc( password_fp )) != '\n' && c != EOF) {
|
|
|
|
/* check if we will overflow the buffer */
|
|
if ((c != EOF) && (index == ((increment * BUFSIZ) -1))) {
|
|
|
|
/* if we did, add another BUFSIZ worth of bytes */
|
|
if ((linep = (char *)
|
|
realloc(linep, (increment + 1) * BUFSIZ)) == NULL) {
|
|
fprintf( stderr, "%s: not enough memory to read password from file\n", ldaptool_progname );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
increment++;
|
|
}
|
|
linep[index++] = c;
|
|
}
|
|
linep[index] = '\0';
|
|
passwd = linep;
|
|
}
|
|
|
|
/*
|
|
* If verbose (-v) flag was passed in, display program name and start time.
|
|
* If the verbose flag was passed at least twice (-vv), also display
|
|
* information about the API library we are running with.
|
|
*/
|
|
if ( ldaptool_verbose ) {
|
|
time_t curtime;
|
|
|
|
curtime = time( NULL );
|
|
printf( "%s: started %s\n", ldaptool_progname, ctime( &curtime ));
|
|
if ( ldaptool_verbose > 1 ) {
|
|
print_library_info( &ldai, stdout );
|
|
}
|
|
}
|
|
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
if ((NULL != pkcs_token) && (NULL != ssl_certname)) {
|
|
char *result;
|
|
|
|
if ( (result = buildTokenCertName( pkcs_token, ssl_certname)) != NULL){
|
|
free( ssl_certname );
|
|
ssl_certname = result;
|
|
}
|
|
}
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
|
|
free( optstring );
|
|
|
|
/*
|
|
* Clean up and return index of first non-option argument.
|
|
*/
|
|
if ( ldai.ldapai_extensions != NULL ) {
|
|
ldap_value_free( ldai.ldapai_extensions );
|
|
}
|
|
if ( ldai.ldapai_vendor_name != NULL ) {
|
|
ldap_memfree( ldai.ldapai_vendor_name );
|
|
}
|
|
|
|
return( optind );
|
|
}
|
|
|
|
|
|
/*
|
|
* Write detailed information about the API library we are running with to fp.
|
|
*/
|
|
static void
|
|
print_library_info( const LDAPAPIInfo *aip, FILE *fp )
|
|
{
|
|
int i;
|
|
LDAPAPIFeatureInfo fi;
|
|
|
|
fprintf( fp, "LDAP Library Information -\n"
|
|
" Highest supported protocol version: %d\n"
|
|
" LDAP API revision: %d\n"
|
|
" API vendor name: %s\n"
|
|
" Vendor-specific version: %.2f\n",
|
|
aip->ldapai_protocol_version, aip->ldapai_api_version,
|
|
aip->ldapai_vendor_name,
|
|
(float)aip->ldapai_vendor_version / 100.0 );
|
|
|
|
if ( aip->ldapai_extensions != NULL ) {
|
|
fputs( " LDAP API Extensions:\n", fp );
|
|
|
|
for ( i = 0; aip->ldapai_extensions[i] != NULL; i++ ) {
|
|
fprintf( fp, " %s", aip->ldapai_extensions[i] );
|
|
fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
|
|
fi.ldapaif_name = aip->ldapai_extensions[i];
|
|
fi.ldapaif_version = 0;
|
|
|
|
if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi )
|
|
!= 0 ) {
|
|
fprintf( fp, " %s: ldap_get_option( NULL,"
|
|
" LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed"
|
|
" (Feature Info version: %d)\n", ldaptool_progname,
|
|
fi.ldapaif_name, fi.ldapaif_info_version );
|
|
} else {
|
|
fprintf( fp, " (revision %d)\n", fi.ldapaif_version);
|
|
}
|
|
}
|
|
}
|
|
fputc( '\n', fp );
|
|
}
|
|
|
|
|
|
|
|
#ifdef LDAP_TOOL_ARGPIN
|
|
static int PinArgRegistration( void )
|
|
{
|
|
|
|
/* pkcs_init was successful register the pin args */
|
|
|
|
SVRCOREArgPinObj *ArgPinObj;
|
|
char *tokenName;
|
|
#ifndef _WIN32
|
|
SVRCOREStdPinObj *StdPinObj;
|
|
#else
|
|
SVRCOREFilePinObj *FilePinObj;
|
|
SVRCOREAltPinObj *AltPinObj;
|
|
SVRCORENTUserPinObj *NTUserPinObj;
|
|
int err;
|
|
#endif
|
|
char *pin;
|
|
char *filename;
|
|
/* Create and register the pin object for PKCS 11 */
|
|
local_pkcs_fns.pkcs_getdonglefilename(NULL, &filename);
|
|
local_pkcs_fns.pkcs_getpin(NULL, "", &pin);
|
|
#ifndef _WIN32
|
|
if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) !=
|
|
SVRCORE_Success) {
|
|
printf("Security Initialization: Unable to create PinObj "
|
|
"(%d)", PR_GetError());
|
|
return -1;
|
|
}
|
|
if (pin != NULL)
|
|
{
|
|
local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
|
|
SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, (SVRCOREPinObj *)StdPinObj);
|
|
SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
|
|
}
|
|
else
|
|
{
|
|
SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj);
|
|
}
|
|
#else
|
|
if (NULL != pin)
|
|
{
|
|
local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
|
|
if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
|
|
printf("Security Initialization: Unable to create NTUserPinObj "
|
|
"(%d)", PR_GetError());
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin,
|
|
(SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success)
|
|
{
|
|
printf("Security Initialization: Unable to create ArgPinObj "
|
|
"(%d)", PR_GetError());
|
|
return -1;
|
|
|
|
}
|
|
SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj);
|
|
|
|
}
|
|
else
|
|
{
|
|
if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
|
|
printf("Security Initialization: Unable to create NTUserPinObj "
|
|
"(%d)", PR_GetError());
|
|
return -1;
|
|
}
|
|
if (filename && *filename)
|
|
{
|
|
if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) !=
|
|
SVRCORE_Success) {
|
|
printf("Security Initialization: Unable to create FilePinObj "
|
|
"(%d)", PR_GetError());
|
|
return -1;
|
|
|
|
}
|
|
if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
|
|
(SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) {
|
|
printf("Security Initialization: Unable to create AltPinObj "
|
|
"(%d)", PR_GetError());
|
|
return -1;
|
|
}
|
|
SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj);
|
|
}
|
|
else
|
|
{
|
|
SVRCORE_RegisterPinObj((SVRCOREPinObj *)NTUserPinObj);
|
|
}
|
|
}
|
|
#endif
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
#endif /* LDAP_TOOL_ARGPIN */
|
|
|
|
|
|
/*
|
|
* initialize and return an LDAP session handle.
|
|
* if errors occur, we exit here.
|
|
*/
|
|
LDAP *
|
|
ldaptool_ldap_init( int second_host )
|
|
{
|
|
LDAP *ld = NULL;
|
|
char *host;
|
|
int port, rc, user_port;
|
|
|
|
if ( ldaptool_not ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if ( second_host ) {
|
|
host = ldaptool_host2;
|
|
port = ldaptool_port2;
|
|
user_port = user_specified_port2;
|
|
} else {
|
|
host = ldaptool_host;
|
|
port = ldaptool_port;
|
|
user_port = user_specified_port;
|
|
}
|
|
|
|
|
|
if ( ldaptool_verbose ) {
|
|
printf( "ldap_init( %s, %d )\n", host, port );
|
|
}
|
|
|
|
#if defined(NET_SSL)
|
|
/*
|
|
* Initialize security libraries and databases and LDAP session. If
|
|
* ssl_certname is not NULL, then we will attempt to use client auth.
|
|
* if the server supports it.
|
|
*/
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
ldaptool_setcallbacks( &local_pkcs_fns );
|
|
|
|
if ( !second_host && secure
|
|
&&(rc = ldapssl_pkcs_init( &local_pkcs_fns)) < 0) {
|
|
/* secure connection requested -- fail if no SSL */
|
|
rc = PORT_GetError();
|
|
fprintf( stderr, "SSL initialization failed: error %d (%s)\n",
|
|
rc, ldapssl_err2string( rc ));
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
|
|
#ifdef LDAP_TOOL_ARGPIN
|
|
if (secure) {
|
|
if (PinArgRegistration( )) {
|
|
exit( LDAP_LOCAL_ERROR);
|
|
}
|
|
}
|
|
#endif /* LDAP_TOOL_ARGPIN */
|
|
|
|
#else /* LDAP_TOOL_PKCS11 */
|
|
if ( !second_host && secure
|
|
&&(rc = ldapssl_client_init( ssl_certdbpath, NULL )) < 0) {
|
|
/* secure connection requested -- fail if no SSL */
|
|
rc = PORT_GetError();
|
|
fprintf( stderr, "SSL initialization failed: error %d (%s)\n",
|
|
rc, ldapssl_err2string( rc ));
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
|
|
if (secure) {
|
|
if ( !user_port ) {
|
|
port = LDAPS_PORT;
|
|
}
|
|
|
|
if (( ld = ldapssl_init( host, port,
|
|
secure )) != NULL && ssl_certname != NULL )
|
|
if (ldapssl_enable_clientauth( ld, ssl_keydbpath, ssl_passwd,
|
|
ssl_certname ) != 0 ) {
|
|
exit ( ldaptool_print_lderror( ld, "ldapssl_enable_clientauth",
|
|
LDAPTOOL_CHECK4SSL_ALWAYS ));
|
|
}
|
|
} else {
|
|
/* In order to support IPv6, we use NSPR I/O */
|
|
ld = prldap_init( host, port, 0 /* not shared across threads */ );
|
|
}
|
|
|
|
#else
|
|
/* In order to support IPv6, we use NSPR I/O */
|
|
ld = prldap_init( host, port, 0 /* not shared across threads */ );
|
|
#endif
|
|
|
|
if ( ld == NULL ) {
|
|
perror( "ldap_init" );
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
|
|
#ifndef NO_LIBLCACHE
|
|
if ( cache_config_file != NULL ) {
|
|
int opt;
|
|
|
|
if ( lcache_init( ld, cache_config_file ) != 0 ) {
|
|
exit( ldaptool_print_lderror( ld, cache_config_file,
|
|
LDAPTOOL_CHECK4SSL_NEVER ));
|
|
}
|
|
opt = 1;
|
|
(void) ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &opt );
|
|
opt = LDAP_CACHE_LOCALDB;
|
|
(void) ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &opt );
|
|
if ( ldversion == -1 ) { /* not set with -V */
|
|
ldversion = LDAP_VERSION2; /* local db only supports v2 */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
ldap_set_option( ld, LDAP_OPT_REFERRALS, chase_referrals ? LDAP_OPT_ON:
|
|
LDAP_OPT_OFF );
|
|
if ( chase_referrals ) {
|
|
ldap_set_rebind_proc( ld, get_rebind_credentials, NULL );
|
|
ldap_set_option( ld, LDAP_OPT_REFERRAL_HOP_LIMIT, &refhoplim );
|
|
}
|
|
|
|
if ( ldversion == -1 ) { /* not set with -V and not using local db */
|
|
ldversion = LDAP_VERSION3;
|
|
}
|
|
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
|
|
|
|
return( ld );
|
|
}
|
|
|
|
|
|
/*
|
|
* perform a bind to the LDAP server if needed.
|
|
* if an error occurs, we exit here.
|
|
*/
|
|
void
|
|
ldaptool_bind( LDAP *ld )
|
|
{
|
|
int rc;
|
|
char *conv;
|
|
LDAPControl auth_resp_ctrl, *ctrl_array[ 2 ], **bindctrls;
|
|
|
|
if ( ldaptool_not ) {
|
|
return;
|
|
}
|
|
|
|
if ( send_auth_response_ctrl ) {
|
|
auth_resp_ctrl.ldctl_oid = LDAP_CONTROL_AUTH_REQUEST;
|
|
auth_resp_ctrl.ldctl_value.bv_val = NULL;
|
|
auth_resp_ctrl.ldctl_value.bv_len = 0;
|
|
auth_resp_ctrl.ldctl_iscritical = 0;
|
|
|
|
ctrl_array[0] = &auth_resp_ctrl;
|
|
ctrl_array[1] = NULL;
|
|
bindctrls = ctrl_array;
|
|
} else {
|
|
bindctrls = NULL;
|
|
}
|
|
|
|
/*
|
|
* if using LDAPv3 and not using client auth., omit NULL bind for
|
|
* efficiency.
|
|
*/
|
|
if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
|
|
&& ssl_certname == NULL ) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* do the bind, backing off one LDAP version if necessary
|
|
*/
|
|
conv = ldaptool_local2UTF8( binddn );
|
|
|
|
/*
|
|
* if using LDAPv3 and client auth., try a SASL EXTERNAL bind
|
|
*/
|
|
if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL
|
|
&& ssl_certname != NULL ) {
|
|
rc = ldaptool_sasl_bind_s( ld, NULL, LDAP_SASL_EXTERNAL, NULL,
|
|
bindctrls, NULL, NULL, "ldap_sasl_bind" );
|
|
} else {
|
|
rc = ldaptool_simple_bind_s( ld, conv, passwd, bindctrls, NULL,
|
|
"ldap_simple_bind" );
|
|
}
|
|
|
|
if ( rc == LDAP_SUCCESS ) {
|
|
if ( conv != NULL ) {
|
|
free( conv );
|
|
}
|
|
return; /* success */
|
|
}
|
|
|
|
if ( rc == LDAP_PROTOCOL_ERROR && ldversion > LDAP_VERSION2 ) {
|
|
/*
|
|
* try again, backing off one LDAP version
|
|
* this is okay even for client auth. because the way to achieve
|
|
* client auth. with LDAPv2 is to perform a NULL simple bind.
|
|
*/
|
|
--ldversion;
|
|
fprintf( stderr, "%s: the server doesn't understand LDAPv%d;"
|
|
" trying LDAPv%d instead...\n", ldaptool_progname,
|
|
ldversion + 1, ldversion );
|
|
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion );
|
|
if (( rc = ldaptool_simple_bind_s( ld, conv, passwd,
|
|
bindctrls, NULL, "ldap_simple_bind" )) == LDAP_SUCCESS ) {
|
|
if( conv != NULL )
|
|
free( conv );
|
|
return; /* a qualified success */
|
|
}
|
|
}
|
|
|
|
if ( conv != NULL ) {
|
|
free( conv );
|
|
}
|
|
|
|
/*
|
|
* bind(s) failed -- fatal error
|
|
*/
|
|
ldap_unbind( ld );
|
|
exit( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* close open files, unbind, etc.
|
|
*/
|
|
void
|
|
ldaptool_cleanup( LDAP *ld )
|
|
{
|
|
if ( ld != NULL ) {
|
|
ldap_unbind( ld );
|
|
}
|
|
|
|
if ( ldaptool_fp != NULL && ldaptool_fp != stdin ) {
|
|
fclose( ldaptool_fp );
|
|
ldaptool_fp = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Retrieve and print an LDAP error message. Returns the LDAP error code.
|
|
*/
|
|
int
|
|
ldaptool_print_lderror( LDAP *ld, char *msg, int check4ssl )
|
|
{
|
|
int lderr = ldap_get_lderrno( ld, NULL, NULL );
|
|
|
|
ldap_perror( ld, msg );
|
|
if ( secure && check4ssl != LDAPTOOL_CHECK4SSL_NEVER ) {
|
|
if ( check4ssl == LDAPTOOL_CHECK4SSL_ALWAYS
|
|
|| ( lderr == LDAP_SERVER_DOWN )) {
|
|
int sslerr = PORT_GetError();
|
|
|
|
fprintf( stderr, "\tSSL error %d (%s)\n", sslerr,
|
|
ldapssl_err2string( sslerr ));
|
|
}
|
|
}
|
|
|
|
return( lderr );
|
|
}
|
|
|
|
|
|
/*
|
|
* print referrals to stderr
|
|
*/
|
|
void
|
|
ldaptool_print_referrals( char **refs )
|
|
{
|
|
int i;
|
|
|
|
if ( refs != NULL ) {
|
|
for ( i = 0; refs[ i ] != NULL; ++i ) {
|
|
fprintf( stderr, "Referral: %s\n", refs[ i ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* print contents of an extended response to stderr
|
|
* this is mainly to support unsolicited notifications
|
|
* Returns an LDAP error code (from the extended result).
|
|
*/
|
|
int
|
|
ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg )
|
|
{
|
|
char *oid;
|
|
struct berval *data;
|
|
|
|
if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 )
|
|
!= LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
if ( oid != NULL ) {
|
|
if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) {
|
|
fprintf( stderr, "%s: Notice of Disconnection\n", msg );
|
|
} else {
|
|
fprintf( stderr, "%s: OID %s\n", msg, oid );
|
|
}
|
|
ldap_memfree( oid );
|
|
} else {
|
|
fprintf( stderr, "%s: missing OID\n", msg );
|
|
}
|
|
|
|
if ( data != NULL ) {
|
|
fprintf( stderr, "%s: Data (length %ld):\n", msg, data->bv_len );
|
|
#if 0
|
|
/* XXXmcs: maybe we should display the actual data? */
|
|
lber_bprint( data->bv_val, data->bv_len );
|
|
#endif
|
|
ber_bvfree( data );
|
|
}
|
|
}
|
|
|
|
return parse_result( ld, res, NULL, msg, 1 );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_sasl_bind_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism,
|
|
const struct berval *cred, LDAPControl **serverctrls,
|
|
LDAPControl **clientctrls, struct berval **servercredp, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if ( servercredp != NULL ) {
|
|
*servercredp = NULL;
|
|
}
|
|
|
|
if (( rc = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls,
|
|
clientctrls, &msgid )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
rc = wait4result( ld, msgid, servercredp, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_simple_bind_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_simple_bind_s( LDAP *ld, const char *dn, const char *passwd,
|
|
LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
|
|
{
|
|
struct berval bv;
|
|
|
|
bv.bv_val = (char *)passwd; /* XXXmcs: had to cast away const */
|
|
bv.bv_len = ( passwd == NULL ? 0 : strlen( passwd ));
|
|
return( ldaptool_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &bv, serverctrls,
|
|
clientctrls, NULL, msg ));
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_add_ext_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
|
|
LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if (( rc = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, &msgid ))
|
|
!= LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
/*
|
|
* 25-April-2000 Note: the next line used to read:
|
|
* rc = wait4result( ld, msgid, NULL, msg );
|
|
* 'msgid' it was changed to 'LDAP_RES_ANY' in order to receive
|
|
* unsolicited notifications.
|
|
*/
|
|
rc = wait4result( ld, LDAP_RES_ANY, NULL, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_modify_ext_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
|
|
LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if (( rc = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
|
|
&msgid )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
rc = wait4result( ld, msgid, NULL, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_delete_ext_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls,
|
|
LDAPControl **clientctrls, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if (( rc = ldap_delete_ext( ld, dn, serverctrls, clientctrls, &msgid ))
|
|
!= LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
rc = wait4result( ld, msgid, NULL, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_compare_ext_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int ldaptool_compare_ext_s( LDAP *ld, const char *dn, const char *attrtype,
|
|
const struct berval *bvalue, LDAPControl **serverctrls,
|
|
LDAPControl **clientctrls, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if (( rc = ldap_compare_ext( ld, dn, attrtype, bvalue, serverctrls,
|
|
clientctrls, &msgid )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
rc = wait4result( ld, msgid, NULL, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Like ldap_rename_s() but calls wait4result() to display
|
|
* any referrals returned and report errors in a consistent way.
|
|
*/
|
|
int
|
|
ldaptool_rename_s( LDAP *ld, const char *dn, const char *newrdn,
|
|
const char *newparent, int deleteoldrdn, LDAPControl **serverctrls,
|
|
LDAPControl **clientctrls, char *msg )
|
|
{
|
|
int rc, msgid;
|
|
|
|
if (( rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn,
|
|
serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
} else {
|
|
rc = wait4result( ld, msgid, NULL, msg );
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* Wait for a result, check for and display errors and referrals.
|
|
* Also recognize and display "Unsolicited notification" messages.
|
|
* Returns an LDAP error code.
|
|
*/
|
|
static int
|
|
wait4result( LDAP *ld, int msgid, struct berval **servercredp, char *msg )
|
|
{
|
|
LDAPMessage *res;
|
|
int rc, received_only_unsolicited = 1;
|
|
|
|
while ( received_only_unsolicited ) {
|
|
res = NULL;
|
|
if (( rc = ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ))
|
|
== -1 ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
return( ldap_get_lderrno( ld, NULL, NULL ));
|
|
}
|
|
|
|
/*
|
|
* Special handling for unsolicited notifications:
|
|
* 1. Parse and display contents.
|
|
* 2. go back and wait for another (real) result.
|
|
*/
|
|
if ( rc == LDAP_RES_EXTENDED
|
|
&& ldap_msgid( res ) == LDAP_RES_UNSOLICITED ) {
|
|
rc = ldaptool_print_extended_response( ld, res,
|
|
"Unsolicited response" );
|
|
} else {
|
|
rc = parse_result( ld, res, servercredp, msg, 1 );
|
|
received_only_unsolicited = 0; /* we're done */
|
|
}
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
static int
|
|
parse_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp,
|
|
char *msg, int freeit )
|
|
{
|
|
int rc, lderr, errno;
|
|
int pw_days=0, pw_hrs=0, pw_mins=0, pw_secs=0; /* for pwpolicy */
|
|
char **refs = NULL;
|
|
LDAPControl **ctrls;
|
|
|
|
if (( rc = ldap_parse_result( ld, res, &lderr, NULL, NULL, &refs,
|
|
&ctrls, 0 )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
ldap_msgfree( res );
|
|
return( rc );
|
|
}
|
|
|
|
/* check for authentication response control & PWPOLICY control*/
|
|
if ( NULL != ctrls ) {
|
|
int i;
|
|
char *s;
|
|
|
|
for ( i = 0; NULL != ctrls[i]; ++i ) {
|
|
if ( 0 == strcmp( ctrls[i]->ldctl_oid,
|
|
LDAP_CONTROL_AUTH_RESPONSE )) {
|
|
s = ctrls[i]->ldctl_value.bv_val;
|
|
if ( NULL == s ) {
|
|
s = "Null";
|
|
} else if ( *s == '\0' ) {
|
|
s = "Anonymous";
|
|
}
|
|
fprintf( stderr, "%s: bound as %s\n", ldaptool_progname, s );
|
|
}
|
|
|
|
if ( 0 == strcmp( ctrls[i]->ldctl_oid,
|
|
LDAP_CONTROL_PWEXPIRING )) {
|
|
|
|
/* Warn the user his passwd is to expire */
|
|
errno = 0;
|
|
pw_secs = atoi(ctrls[i]->ldctl_value.bv_val);
|
|
if ( pw_secs > 0 && errno != ERANGE ) {
|
|
if ( pw_secs > 86400 ) {
|
|
pw_days = ( pw_secs / 86400 );
|
|
pw_secs = ( pw_secs % 86400 );
|
|
}
|
|
if ( pw_secs > 3600 ) {
|
|
pw_hrs = ( pw_secs / 3600 );
|
|
pw_secs = ( pw_secs % 3600 );
|
|
}
|
|
if ( pw_secs > 60 ) {
|
|
pw_mins = ( pw_secs / 60 );
|
|
pw_secs = ( pw_secs % 60 );
|
|
}
|
|
|
|
printf("%s: Warning ! Your password will expire after ", ldaptool_progname);
|
|
if ( pw_days ) {
|
|
printf ("%d days, ", pw_days);
|
|
}
|
|
if ( pw_hrs ) {
|
|
printf ("%d hrs, ", pw_hrs);
|
|
}
|
|
if ( pw_mins ) {
|
|
printf ("%d mins, ", pw_mins);
|
|
}
|
|
printf("%d seconds.\n", pw_secs);
|
|
|
|
}
|
|
}
|
|
}
|
|
ldap_controls_free( ctrls );
|
|
}
|
|
|
|
if ( servercredp != NULL && ( rc = ldap_parse_sasl_bind_result( ld, res,
|
|
servercredp, 0 )) != LDAP_SUCCESS ) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
ldap_msgfree( res );
|
|
return( rc );
|
|
}
|
|
|
|
if ( freeit ) {
|
|
ldap_msgfree( res );
|
|
}
|
|
|
|
if ( LDAPTOOL_RESULT_IS_AN_ERROR( lderr )) {
|
|
ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP );
|
|
}
|
|
|
|
if ( refs != NULL ) {
|
|
ldaptool_print_referrals( refs );
|
|
ldap_value_free( refs );
|
|
}
|
|
|
|
return( lderr );
|
|
}
|
|
|
|
|
|
/*
|
|
* if -M was passed on the command line, create and return a "Manage DSA IT"
|
|
* LDAPv3 control. If not, return NULL.
|
|
*/
|
|
LDAPControl *
|
|
ldaptool_create_manage_dsait_control( void )
|
|
{
|
|
LDAPControl *ctl;
|
|
|
|
if ( !send_manage_dsait_ctrl ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if (( ctl = (LDAPControl *)calloc( 1, sizeof( LDAPControl ))) == NULL ||
|
|
( ctl->ldctl_oid = strdup( LDAP_CONTROL_MANAGEDSAIT )) == NULL ) {
|
|
perror( "calloc" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
ctl->ldctl_iscritical = 1;
|
|
|
|
return( ctl );
|
|
}
|
|
|
|
/*
|
|
* if -y "dn" was supplied on the command line, create the control
|
|
*/
|
|
LDAPControl *
|
|
ldaptool_create_proxyauth_control( LDAP *ld )
|
|
{
|
|
LDAPControl *ctl = NULL;
|
|
int rc;
|
|
|
|
|
|
if ( !proxyauth_id)
|
|
return( NULL );
|
|
|
|
if ( 2 == proxyauth_version ) {
|
|
rc = ldap_create_proxiedauth_control( ld, proxyauth_id, &ctl);
|
|
} else {
|
|
rc = ldap_create_proxyauth_control( ld, proxyauth_id, 1, &ctl);
|
|
}
|
|
if ( rc != LDAP_SUCCESS)
|
|
{
|
|
if (ctl)
|
|
ldap_control_free( ctl);
|
|
return NULL;
|
|
}
|
|
return( ctl );
|
|
}
|
|
|
|
void
|
|
ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array)
|
|
{
|
|
|
|
int i;
|
|
for (i=0; i< CONTROL_REQUESTS; i++)
|
|
{
|
|
if (*(array + i) == NULL)
|
|
{
|
|
*(array + i +1) = NULL;
|
|
*(array + i) = ctrl;
|
|
return ;
|
|
}
|
|
}
|
|
fprintf(stderr, "%s: failed to store request control!!!!!!\n",
|
|
ldaptool_progname);
|
|
}
|
|
|
|
/*
|
|
* Dispose of all controls in array and prepare array for reuse.
|
|
*/
|
|
void
|
|
ldaptool_reset_control_array( LDAPControl **array )
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < CONTROL_REQUESTS; i++ ) {
|
|
if ( array[i] != NULL ) {
|
|
ldap_control_free( array[i] );
|
|
array[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This function calculates control value and its length. *value can
|
|
* be pointing to plain value, ":b64encoded value" or "<fileurl".
|
|
*/
|
|
static int
|
|
calculate_ctrl_value( const char *value,
|
|
char **ctrl_value, int *vlen)
|
|
{
|
|
int b64;
|
|
if (*value == ':') {
|
|
value++;
|
|
b64 = 1;
|
|
} else {
|
|
b64 = 0;
|
|
}
|
|
*ctrl_value = (char *)value;
|
|
|
|
if ( b64 ) {
|
|
if (( *vlen = ldif_base64_decode( (char *)value,
|
|
(unsigned char *)value )) < 0 ) {
|
|
fprintf( stderr,
|
|
"Unable to decode base64 control value \"%s\"\n", value);
|
|
return( -1 );
|
|
}
|
|
} else {
|
|
*vlen = (int)strlen(*ctrl_value);
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
/*
|
|
* Parse the optarg from -J option of ldapsearch
|
|
* and within LDIFfile for ldapmodify. Take ctrl_arg
|
|
* (the whole string) and divide it into oid, criticality
|
|
* and value. This function breaks down original ctrl_arg
|
|
* with '\0' in places. Also, calculate length of valuestring.
|
|
*/
|
|
int
|
|
ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep,
|
|
char **ctrl_oid, int *ctrl_criticality,
|
|
char **ctrl_value, int *vlen)
|
|
{
|
|
char *s, *p, *d;
|
|
int strict;
|
|
|
|
/* Initialize passed variables with default values */
|
|
*ctrl_oid = *ctrl_value = NULL;
|
|
*ctrl_criticality = 0;
|
|
*vlen = 0;
|
|
|
|
strict = (sep == ' ' ? 1 : 0);
|
|
if(!(s=strchr(ctrl_arg, sep))) {
|
|
/* Possible values of ctrl_arg are
|
|
* oid[:value|::b64value|:<fileurl] within LDIF, i.e. sep=' '
|
|
* oid from command line option, i.e. sep=':'
|
|
*/
|
|
if (sep == ' ') {
|
|
if (!(s=strchr(ctrl_arg, ':'))) {
|
|
*ctrl_oid = ctrl_arg;
|
|
}
|
|
else {
|
|
/* ctrl_arg is of oid:[value|:b64value|<fileurl]
|
|
* form in the LDIF record. So, grab the oid and then
|
|
* jump to continue the parsing of ctrl_arg.
|
|
* 's' is pointing just after oid ends.
|
|
*/
|
|
*s++ = '\0';
|
|
*ctrl_oid = ctrl_arg;
|
|
return (calculate_ctrl_value( s, ctrl_value, vlen ));
|
|
}
|
|
} else {
|
|
/* oid - from command line option, i.e. sep=':' */
|
|
*ctrl_oid = ctrl_arg;
|
|
}
|
|
}
|
|
else {
|
|
/* Possible values of ctrl_arg are
|
|
* oid:criticality[:value|::b64value|:<fileurl] - command line
|
|
* oid criticality[:value|::b64value|:<fileurl] - LDIF
|
|
* And 's' is pointing just after oid ends.
|
|
*/
|
|
|
|
if (*(s+1) == '\0') {
|
|
fprintf( stderr, "missing value\n" );
|
|
return( -1 );
|
|
}
|
|
*s = '\0';
|
|
*ctrl_oid = ctrl_arg;
|
|
p = ++s;
|
|
if(!(s=strchr(p, ':'))) {
|
|
if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
|
|
== -1 ) {
|
|
fprintf( stderr, "Invalid criticality value\n" );
|
|
return( -1 );
|
|
}
|
|
}
|
|
else {
|
|
if (*(s+1) == '\0') {
|
|
fprintf( stderr, "missing value\n" );
|
|
return ( -1 );
|
|
}
|
|
*s++ = '\0';
|
|
if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict))
|
|
== -1 ) {
|
|
fprintf( stderr, "Invalid criticality value\n" );
|
|
return ( -1 );
|
|
}
|
|
return (calculate_ctrl_value( s, ctrl_value, vlen ));
|
|
}
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
* callback function for LDAP bind credentials
|
|
*/
|
|
static int
|
|
LDAP_CALL
|
|
LDAP_CALLBACK
|
|
get_rebind_credentials( LDAP *ld, char **whop, char **credp,
|
|
int *methodp, int freeit, void* arg )
|
|
{
|
|
if ( !freeit ) {
|
|
*whop = binddn;
|
|
*credp = passwd;
|
|
*methodp = LDAP_AUTH_SIMPLE;
|
|
}
|
|
|
|
return( LDAP_SUCCESS );
|
|
}
|
|
|
|
|
|
/*
|
|
* return pointer to pathname to temporary directory.
|
|
* First we see if the environment variable "TEMP" is set and use it.
|
|
* Then we see if the environment variable "TMP" is set and use it.
|
|
* If this fails, we use "/tmp" on UNIX and fail on Windows.
|
|
*/
|
|
char *
|
|
ldaptool_get_tmp_dir( void )
|
|
{
|
|
char *p;
|
|
int offset;
|
|
|
|
if (( p = getenv( "TEMP" )) == NULL && ( p = getenv( "TMP" )) == NULL ) {
|
|
#ifdef _WINDOWS
|
|
fprintf( stderr, "%s: please set the TEMP environment variable.\n",
|
|
ldaptool_progname );
|
|
exit( LDAP_LOCAL_ERROR );
|
|
#else
|
|
return( "/tmp" ); /* last resort on UNIX */
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* remove trailing slash if present
|
|
*/
|
|
offset = strlen( p ) - 1;
|
|
if ( p[offset] == '/'
|
|
#ifdef _WINDOWS
|
|
|| p[offset] == '\\'
|
|
#endif
|
|
) {
|
|
if (( p = strdup( p )) == NULL ) {
|
|
perror( "strdup" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
p[offset] = '\0';
|
|
}
|
|
|
|
return( p );
|
|
}
|
|
|
|
|
|
int
|
|
ldaptool_berval_is_ascii( const struct berval *bvp )
|
|
{
|
|
unsigned long j;
|
|
int is_ascii = 1; /* optimistic */
|
|
|
|
for ( j = 0; j < bvp->bv_len; ++j ) {
|
|
if ( !isascii( bvp->bv_val[ j ] )) {
|
|
is_ascii = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( is_ascii );
|
|
}
|
|
|
|
|
|
#ifdef LDAP_DEBUG_MEMORY
|
|
#define LDAPTOOL_ALLOC_FREED 0xF001
|
|
#define LDAPTOOL_ALLOC_INUSE 0xF002
|
|
|
|
static void *
|
|
ldaptool_debug_alloc( void *ptr, size_t size )
|
|
{
|
|
int *statusp;
|
|
void *systemptr;
|
|
|
|
if ( ptr == NULL ) {
|
|
systemptr = NULL;
|
|
} else {
|
|
systemptr = (void *)((char *)ptr - sizeof(int));
|
|
}
|
|
|
|
if (( statusp = (int *)realloc( systemptr, size + sizeof(int))) == NULL ) {
|
|
fprintf( stderr, "%s: realloc( 0x%x, %d) failed\n",
|
|
ldaptool_progname, systemptr, size );
|
|
return( NULL );
|
|
}
|
|
|
|
*statusp = LDAPTOOL_ALLOC_INUSE;
|
|
|
|
return( (char *)statusp + sizeof(int));
|
|
}
|
|
|
|
|
|
static void *
|
|
ldaptool_debug_realloc( void *ptr, size_t size )
|
|
{
|
|
void *p;
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: => realloc( 0x%x, %d )\n",
|
|
ldaptool_progname, ptr, size );
|
|
}
|
|
|
|
p = ldaptool_debug_alloc( ptr, size );
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: 0x%x <= realloc()\n", ldaptool_progname, p );
|
|
}
|
|
|
|
return( p );
|
|
}
|
|
|
|
|
|
static void *
|
|
ldaptool_debug_malloc( size_t size )
|
|
{
|
|
void *p;
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: => malloc( %d)\n", ldaptool_progname, size );
|
|
}
|
|
|
|
p = ldaptool_debug_alloc( NULL, size );
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: 0x%x <= malloc()\n", ldaptool_progname, p );
|
|
}
|
|
|
|
return( p );
|
|
}
|
|
|
|
|
|
static void *
|
|
ldaptool_debug_calloc( size_t nelem, size_t elsize )
|
|
{
|
|
void *p;
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: => calloc( %d, %d )\n",
|
|
ldaptool_progname, nelem, elsize );
|
|
}
|
|
|
|
if (( p = ldaptool_debug_alloc( NULL, nelem * elsize )) != NULL ) {
|
|
memset( p, 0, nelem * elsize );
|
|
}
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: 0x%x <= calloc()\n", ldaptool_progname, p );
|
|
}
|
|
|
|
return( p );
|
|
}
|
|
|
|
|
|
static void
|
|
ldaptool_debug_free( void *ptr )
|
|
{
|
|
int *statusp = (int *)((char *)ptr - sizeof(int));
|
|
|
|
if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) {
|
|
fprintf( stderr, "%s: => free( 0x%x )\n", ldaptool_progname, ptr );
|
|
}
|
|
|
|
if ( ptr == NULL ) {
|
|
fprintf( stderr, "%s: bad free( 0x0 ) attempted (NULL pointer)\n",
|
|
ldaptool_progname );
|
|
} else if ( *statusp != LDAPTOOL_ALLOC_INUSE ) {
|
|
fprintf( stderr, "%s: bad free( 0x%x ) attempted"
|
|
" (block not in use; status is %d)\n",
|
|
ldaptool_progname, ptr, *statusp );
|
|
} else {
|
|
*statusp = LDAPTOOL_ALLOC_FREED;
|
|
free( statusp );
|
|
}
|
|
}
|
|
#endif /* LDAP_DEBUG_MEMORY */
|
|
|
|
|
|
#if defined(NET_SSL)
|
|
/*
|
|
* Derive key database path from certificate database path and return a
|
|
* malloc'd string.
|
|
*
|
|
* We just return an exact copy of "certdbpath" unless it ends in "cert.db",
|
|
* "cert5.db", or "cert7.db". In those cases we strip off everything from
|
|
* "cert" on and append "key.db", "key5.db", or "key3.db" as appropriate.
|
|
* Strangely enough cert7.db and key3.db go together.
|
|
*/
|
|
static char *
|
|
certpath2keypath( char *certdbpath )
|
|
{
|
|
char *keydbpath, *appendstr;
|
|
int len, striplen;
|
|
|
|
if ( certdbpath == NULL ) {
|
|
return( NULL );
|
|
}
|
|
|
|
if (( keydbpath = strdup( certdbpath )) == NULL ) {
|
|
perror( "strdup" );
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
|
|
len = strlen( keydbpath );
|
|
if ( len > 7 &&
|
|
strcasecmp( "cert.db", keydbpath + len - 7 ) == 0 ) {
|
|
striplen = 7;
|
|
appendstr = "key.db";
|
|
|
|
} else if ( len > 8 &&
|
|
strcasecmp( "cert5.db", keydbpath + len - 8 ) == 0 ) {
|
|
striplen = 8;
|
|
appendstr = "key5.db";
|
|
} else if ( len > 8 &&
|
|
strcasecmp( "cert7.db", keydbpath + len - 8 ) == 0 ) {
|
|
striplen = 8;
|
|
appendstr = "key3.db";
|
|
} else {
|
|
striplen = 0;
|
|
}
|
|
|
|
if ( striplen > 0 ) {
|
|
/*
|
|
* The following code assumes that strlen( appendstr ) < striplen!
|
|
*/
|
|
strcpy( keydbpath + len - striplen, appendstr );
|
|
}
|
|
|
|
return( keydbpath );
|
|
}
|
|
|
|
#ifdef LDAP_TOOL_PKCS11
|
|
static
|
|
char *
|
|
buildTokenCertName( const char *tokenName, const char *certName)
|
|
{
|
|
|
|
int tokenlen = strlen(tokenName);
|
|
int len = tokenlen + strlen(certName) +2;
|
|
char *result;
|
|
|
|
if (( result = malloc( len )) != NULL) {
|
|
strcpy(result, tokenName);
|
|
*(result+tokenlen) = ':';
|
|
++tokenlen;
|
|
strcpy(result+tokenlen, certName);
|
|
} else {
|
|
perror("malloc");
|
|
exit( LDAP_NO_MEMORY );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static
|
|
int
|
|
ldaptool_getcertpath( void *context, char **certlocp )
|
|
{
|
|
|
|
*certlocp = ssl_certdbpath;
|
|
if ( ldaptool_verbose ) {
|
|
if (ssl_certdbpath)
|
|
{
|
|
printf("ldaptool_getcertpath -- %s\n", ssl_certdbpath );
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getcertpath -- (null)\n");
|
|
}
|
|
|
|
}
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
ldaptool_getcertname( void *context, char **certnamep )
|
|
{
|
|
|
|
*certnamep = ssl_certname;
|
|
if ( ldaptool_verbose ) {
|
|
if (ssl_certname)
|
|
{
|
|
printf("ldaptool_getcertname -- %s\n", *certnamep);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getcertname -- (null)\n");
|
|
}
|
|
}
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
ldaptool_getkeypath(void *context, char **keylocp )
|
|
{
|
|
*keylocp = ssl_keydbpath;
|
|
if ( ldaptool_verbose ) {
|
|
if (ssl_keydbpath)
|
|
{
|
|
printf("ldaptool_getkeypath -- %s\n",*keylocp);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getkeypath -- (null)\n");
|
|
}
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
ldaptool_gettokenname( void *context, char **tokennamep )
|
|
{
|
|
|
|
*tokennamep = pkcs_token;
|
|
if ( ldaptool_verbose ) {
|
|
if (pkcs_token)
|
|
{
|
|
printf("ldaptool_gettokenname -- %s\n",*tokennamep);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_gettokenname -- (null)\n");
|
|
}
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
int
|
|
ldaptool_gettokenpin( void *context, const char *tokennamep, char **tokenpinp)
|
|
{
|
|
|
|
#if 0
|
|
char *localtoken;
|
|
#endif
|
|
|
|
/* XXXceb this stuff is removed for the time being.
|
|
* This function should return the pin from ssl_password
|
|
*/
|
|
|
|
|
|
*tokenpinp = ssl_passwd;
|
|
return LDAP_SUCCESS;
|
|
|
|
#if 0
|
|
|
|
ldaptool_gettokenname( NULL, &localtoken);
|
|
|
|
if (strcmp( localtoken, tokennamep))
|
|
|
|
*tokenpinp = pkcs_pin;
|
|
else
|
|
*tokenpinp = NULL;
|
|
|
|
if ( ldaptool_verbose ) {
|
|
if (pkcs_pin)
|
|
{
|
|
printf("ldaptool_getokenpin --%s\n", tokenpinp);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getokenpin -- (null)\n");
|
|
}
|
|
}
|
|
return LDAP_SUCCESS;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
ldaptool_getmodpath( void *context, char **modulep )
|
|
{
|
|
*modulep = ssl_secmodpath;
|
|
if ( ldaptool_verbose ) {
|
|
if (ssl_secmodpath)
|
|
{
|
|
printf("ldaptool_getmodpath -- %s\n", *modulep);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getmodpath -- (null)\n");
|
|
}
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
ldaptool_getdonglefilename( void *context, char **filename )
|
|
{
|
|
*filename = ssl_donglefile;
|
|
if ( ldaptool_verbose ) {
|
|
if (ssl_donglefile)
|
|
{
|
|
printf("ldaptool_getdonglefilename -- %s\n", *filename);
|
|
}
|
|
else
|
|
{
|
|
printf("ldaptool_getdonglefilename -- (null)\n");
|
|
}
|
|
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
static int
|
|
ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns)
|
|
{
|
|
pfns->pkcs_getcertpath = (int (*)(void *, char **))ldaptool_getcertpath;
|
|
pfns->pkcs_getcertname = (int (*)(void *, char **))ldaptool_getcertname;
|
|
pfns->pkcs_getkeypath = (int (*)(void *, char **)) ldaptool_getkeypath;
|
|
pfns->pkcs_getmodpath = (int (*)(void *, char **)) ldaptool_getmodpath;
|
|
pfns->pkcs_getpin = (int (*)(void *, const char*, char **)) ldaptool_gettokenpin;
|
|
pfns->pkcs_gettokenname = (int (*)(void *, char **)) ldaptool_gettokenname;
|
|
pfns->pkcs_getdonglefilename = (int (*)(void *, char **)) ldaptool_getdonglefilename;
|
|
pfns->local_structure_id=PKCS_STRUCTURE_ID;
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
#ifdef FORTEZZA
|
|
static int
|
|
ldaptool_fortezza_init( int exit_on_error )
|
|
{
|
|
int rc, errcode;
|
|
|
|
if ( fortezza_personality == NULL && fortezza_cardmask == 0 ) { /* no FORTEZZA desired */
|
|
SSL_EnableGroup( SSL_GroupFortezza, DSFalse ); /* disable FORTEZZA */
|
|
return( 0 );
|
|
}
|
|
|
|
if (( rc = FortezzaConfigureServer( ldaptool_fortezza_getpin, fortezza_cardmask,
|
|
fortezza_personality, ldaptool_fortezza_alert, NULL, &errcode,
|
|
fortezza_krlfile )) < 0 ) {
|
|
fprintf( stderr,
|
|
"%s: FORTEZZA initialization failed (error %d - %s)\n",
|
|
ldaptool_progname, errcode,
|
|
ldaptool_fortezza_err2string( errcode ));
|
|
if ( exit_on_error ) {
|
|
exit( LDAP_LOCAL_ERROR );
|
|
}
|
|
|
|
SSL_EnableGroup( SSL_GroupFortezza, DSFalse ); /* disable FORTEZZA */
|
|
return( -1 );
|
|
}
|
|
|
|
SSL_EnableGroup( SSL_GroupFortezza, DSTrue ); /* enable FORTEZZA */
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
static int
|
|
ldaptool_fortezza_alert( void *arg, PRBool onOpen, char *string,
|
|
int value1, void *value2 )
|
|
{
|
|
fprintf( stderr, "%s: FORTEZZA alert: ", ldaptool_progname );
|
|
fprintf( stderr, string, value1, value2 );
|
|
fprintf( stderr, "\n" );
|
|
return( 1 );
|
|
}
|
|
|
|
|
|
static void *
|
|
ldaptool_fortezza_getpin( char **passwordp )
|
|
{
|
|
*passwordp = fortezza_pin;
|
|
return( *passwordp );
|
|
}
|
|
|
|
|
|
/*
|
|
* convert a Fortezza error code (as returned by FortezzaConfigureServer()
|
|
* into a human-readable string.
|
|
*
|
|
* Error strings are intentionally similar to those found in
|
|
* ns/netsite/lib/libadmin/httpcon.c
|
|
*/
|
|
static char *
|
|
ldaptool_fortezza_err2string( int err )
|
|
{
|
|
char *s;
|
|
|
|
switch( err ) {
|
|
case FORTEZZA_BADPASSWD:
|
|
s = "invalid pin number";
|
|
break;
|
|
case FORTEZZA_BADCARD:
|
|
s = "bad or missing card";
|
|
break;
|
|
case FORTEZZA_MISSING_KRL:
|
|
s = "bad or missing compromised key list";
|
|
break;
|
|
case FORTEZZA_CERT_INIT_ERROR:
|
|
s = "unable to initialize certificate cache. either a cert on "
|
|
"the card is bad, or an old FORTEZZA certificate is in a"
|
|
"readonly database";
|
|
break;
|
|
case FORTEZZA_EXPIRED_CERT:
|
|
s = "unable to verify certificate";
|
|
break;
|
|
default:
|
|
s = "unknown error";
|
|
}
|
|
|
|
return( s );
|
|
}
|
|
|
|
#endif /* FORTEZZA */
|
|
#endif /* LDAP_TOOL_PKCS11 */
|
|
#endif /* NET_SSL */
|
|
|
|
int
|
|
ldaptool_boolean_str2value ( const char *ptr, int strict )
|
|
{
|
|
if (strict) {
|
|
if ( !(strcasecmp(ptr, "true"))) {
|
|
return 1;
|
|
}
|
|
else if ( !(strcasecmp(ptr, "false"))) {
|
|
return 0;
|
|
}
|
|
else {
|
|
return (-1);
|
|
}
|
|
}
|
|
else {
|
|
if ( !(strcasecmp(ptr, "true")) ||
|
|
!(strcasecmp(ptr, "t")) ||
|
|
!(strcmp(ptr, "1")) ) {
|
|
return (1);
|
|
}
|
|
else if ( !(strcasecmp(ptr, "false")) ||
|
|
!(strcasecmp(ptr, "f")) ||
|
|
!(strcmp(ptr, "0")) ) {
|
|
return (0);
|
|
}
|
|
else {
|
|
return (-1);
|
|
}
|
|
}
|
|
}
|