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