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