]> git.sur5r.net Git - openldap/blob - clients/tools/common.c
a9d2bcc749f8538803bc7c61aeb59d251af109be
[openldap] / clients / tools / common.c
1 /* common.c - common routines for the ldap client tools */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * Portions Copyright 2003 Kurt D. Zeilenga.
7  * Portions Copyright 2003 IBM Corporation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This file was initially created by Hallvard B. Furuseth based (in
20  * part) upon argument parsing code for individual tools located in
21  * this directory.   Additional contributors include:
22  *   Kurt D. Zeilenga (additional common argument and control support)
23  */
24
25 #include "portable.h"
26
27 #include <stdio.h>
28
29 #include <ac/stdlib.h>
30 #include <ac/signal.h>
31 #include <ac/string.h>
32 #include <ac/unistd.h>
33 #include <ac/errno.h>
34
35 #ifdef HAVE_CYRUS_SASL
36 #ifdef HAVE_SASL_SASL_H
37 #include <sasl/sasl.h>
38 #else
39 #include <sasl.h>
40 #endif
41 #endif
42
43 #include <ldap.h>
44
45 #include "lutil_ldap.h"
46 #include "ldap_defaults.h"
47 #include "ldap_pvt.h"
48 #include "lber_pvt.h"
49
50 #include "common.h"
51
52 #if !LDAP_DEPRECATED
53 /*
54  * NOTE: we declare it here only because we want to keep supporting
55  * (how long?) ancient, deprecated LDAP_AUTH_KRB* auth methods
56  */
57 LDAP_F( int )
58 ldap_bind LDAP_P((      /* deprecated */
59         LDAP *ld,
60         LDAP_CONST char *who,
61         LDAP_CONST char *passwd,
62         int authmethod ));
63 #endif
64
65 int   authmethod = -1;
66 char *binddn = NULL;
67 int   contoper = 0;
68 int   debug = 0;
69 char *infile = NULL;
70 char *ldapuri = NULL;
71 char *ldaphost = NULL;
72 int   ldapport = 0;
73 #ifdef HAVE_CYRUS_SASL
74 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
75 char    *sasl_realm = NULL;
76 char    *sasl_authc_id = NULL;
77 char    *sasl_authz_id = NULL;
78 char    *sasl_mech = NULL;
79 char    *sasl_secprops = NULL;
80 #endif
81 int   use_tls = 0;
82
83 int       assertctl;
84 char *assertion = NULL;
85 char *authzid = NULL;
86 int   manageDIT = 0;
87 int   manageDSAit = 0;
88 int   noop = 0;
89 int   ppolicy = 0;
90 int   preread = 0;
91 char *preread_attrs = NULL;
92 int   postread = 0;
93 char *postread_attrs = NULL;
94
95 int   not = 0;
96 int   want_bindpw = 0;
97 struct berval passwd = { 0, NULL };
98 char *pw_file = NULL;
99 int   referrals = 0;
100 int   protocol = -1;
101 int   verbose = 0;
102 int   version = 0;
103
104 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
105 int chaining = 0;
106 static int chainingResolve = -1;
107 static int chainingContinuation = -1;
108 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
109
110 static int gotintr;
111 static int abcan;
112
113 RETSIGTYPE
114 do_sig( int sig )
115 {
116         gotintr = abcan;
117 }
118
119 /* Set in main() */
120 char *prog = NULL;
121
122 void
123 tool_init( void )
124 {
125         ldap_pvt_setlocale(LC_MESSAGES, "");
126         ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE, LDAP_LOCALEDIR);
127         ldap_pvt_textdomain(OPENLDAP_PACKAGE);
128 }
129
130 void
131 tool_destroy( void )
132 {
133 #ifdef HAVE_CYRUS_SASL
134         sasl_done();
135 #endif
136 #ifdef HAVE_TLS
137         ldap_pvt_tls_destroy();
138 #endif
139 }
140
141 void
142 tool_common_usage( void )
143 {
144         static const char *const descriptions[] = {
145 N_("  -c         continuous operation mode (do not stop on errors)\n"),
146 N_("  -C         chase referrals (anonymously)\n"),
147 N_("  -d level   set LDAP debugging level to `level'\n"),
148 N_("  -D binddn  bind DN\n"),
149 N_("  -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
150 N_("             [!]assert=<filter>     (an RFC 2254 Filter)\n")
151 N_("             [!]authzid=<authzid>   (\"dn:<dn>\" or \"u:<user>\")\n")
152 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
153 N_("             [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
154 N_("                     one of \"chainingPreferred\", \"chainingRequired\",\n")
155 N_("                     \"referralsPreferred\", \"referralsRequired\"\n")
156 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
157 #ifdef LDAP_DEVEL
158 N_("             [!]manageDIT\n")
159 #endif
160 N_("             [!]manageDSAit\n")
161 N_("             [!]noop\n")
162 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
163 N_("             ppolicy\n")
164 #endif
165 N_("             [!]postread[=<attrs>]  (a comma-separated attribute list)\n")
166 N_("             [!]preread[=<attrs>]   (a comma-separated attribute list)\n"),
167 N_("             abandon, cancel (SIGINT sends abandon/cancel; not really controls)\n")
168 N_("  -f file    read operations from `file'\n"),
169 N_("  -h host    LDAP server\n"),
170 N_("  -H URI     LDAP Uniform Resource Indentifier(s)\n"),
171 N_("  -I         use SASL Interactive mode\n"),
172 N_("  -k         use Kerberos authentication\n"),
173 N_("  -K         like -k, but do only step 1 of the Kerberos bind\n"),
174 N_("  -M         enable Manage DSA IT control (-MM to make critical)\n"),
175 N_("  -n         show what would be done but don't actually do it\n"),
176 N_("  -O props   SASL security properties\n"),
177 N_("  -p port    port on LDAP server\n"),
178 N_("  -P version procotol version (default: 3)\n"),
179 N_("  -Q         use SASL Quiet mode\n"),
180 N_("  -R realm   SASL realm\n"),
181 N_("  -U authcid SASL authentication identity\n"),
182 N_("  -v         run in verbose mode (diagnostics to standard output)\n"),
183 N_("  -V         print version info (-VV only)\n"),
184 N_("  -w passwd  bind password (for simple authentication)\n"),
185 N_("  -W         prompt for bind password\n"),
186 N_("  -x         Simple authentication\n"),
187 N_("  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
188 N_("  -y file    Read password from file\n"),
189 N_("  -Y mech    SASL mechanism\n"),
190 N_("  -Z         Start TLS request (-ZZ to require successful response)\n"),
191 NULL
192         };
193         const char *const *cpp;
194
195         fputs( _("Common options:\n"), stderr );
196         for( cpp = descriptions; *cpp != NULL; cpp++ ) {
197                 if( strchr( options, (*cpp)[3] ) || (*cpp)[3] == ' ' ) {
198                         fputs( _(*cpp), stderr );
199                 }
200         }
201 }
202
203 void tool_perror(
204         const char *func,
205         int err,
206         const char *extra,
207         const char *matched,
208         const char *info,
209         char **refs )
210 {
211         fprintf( stderr, "%s: %s (%d)%s\n",
212                 func, ldap_err2string( err ), err, extra ? extra : "" );
213
214         if ( matched && *matched ) {
215                 fprintf( stderr, _("\tmatched DN: %s\n"), matched );
216         }
217
218         if ( info && *info ) {
219                 fprintf( stderr, _("\tadditional info: %s\n"), info );
220         }
221
222         if ( refs && *refs ) {
223                 int i;
224                 fprintf( stderr, _("\treferrals:\n") );
225                 for( i=0; refs[i]; i++ ) {
226                         fprintf( stderr, "\t\t%s\n", refs[i] );
227                 }
228         }
229 }
230
231
232 void
233 tool_args( int argc, char **argv )
234 {
235         int i;
236
237         while (( i = getopt( argc, argv, options )) != EOF ) {
238                 int crit, ival;
239                 char *control, *cvalue, *next;
240                 switch( i ) {
241                 case 'c':       /* continuous operation mode */
242                         contoper++;
243                         break;
244                 case 'C':
245                         referrals++;
246                         break;
247                 case 'd':
248                         ival = strtol( optarg, &next, 10 );
249                         if (next == NULL || next[0] != '\0') {
250                                 fprintf( stderr, "%s: unable to parse debug value \"%s\"\n", prog, optarg);
251                                 exit(EXIT_FAILURE);
252                         }
253                         debug |= ival;
254                         break;
255                 case 'D':       /* bind DN */
256                         if( binddn != NULL ) {
257                                 fprintf( stderr, "%s: -D previously specified\n", prog );
258                                 exit( EXIT_FAILURE );
259                         }
260                         binddn = ber_strdup( optarg );
261                         break;
262                 case 'e': /* general extensions (controls and such) */
263                         /* should be extended to support comma separated list of
264                          *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
265                          */
266
267                         crit = 0;
268                         cvalue = NULL;
269                         if( optarg[0] == '!' ) {
270                                 crit = 1;
271                                 optarg++;
272                         }
273
274                         control = ber_strdup( optarg );
275                         if ( (cvalue = strchr( control, '=' )) != NULL ) {
276                                 *cvalue++ = '\0';
277                         }
278
279                         if ( strcasecmp( control, "assert" ) == 0 ) {
280                                 if( assertctl ) {
281                                         fprintf( stderr, "assert control previously specified\n");
282                                         exit( EXIT_FAILURE );
283                                 }
284                                 if( cvalue == NULL ) {
285                                         fprintf( stderr, "assert: control value expected\n" );
286                                         usage();
287                                 }
288
289                                 assertctl = 1 + crit;
290
291                                 assert( assertion == NULL );
292                                 assertion = cvalue;
293
294                         } else if ( strcasecmp( control, "authzid" ) == 0 ) {
295                                 if( authzid != NULL ) {
296                                         fprintf( stderr, "authzid control previously specified\n");
297                                         exit( EXIT_FAILURE );
298                                 }
299                                 if( cvalue == NULL ) {
300                                         fprintf( stderr, "authzid: control value expected\n" );
301                                         usage();
302                                 }
303                                 if( !crit ) {
304                                         fprintf( stderr, "authzid: must be marked critical\n" );
305                                         usage();
306                                 }
307
308                                 assert( authzid == NULL );
309                                 authzid = cvalue;
310
311                         } else if ( strcasecmp( control, "manageDIT" ) == 0 ) {
312                                 if( manageDIT ) {
313                                         fprintf( stderr,
314                                                 "manageDIT control previously specified\n");
315                                         exit( EXIT_FAILURE );
316                                 }
317                                 if( cvalue != NULL ) {
318                                         fprintf( stderr,
319                                                 "manageDIT: no control value expected\n" );
320                                         usage();
321                                 }
322
323                                 manageDIT = 1 + crit;
324
325                         } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
326                                 if( manageDSAit ) {
327                                         fprintf( stderr,
328                                                 "manageDSAit control previously specified\n");
329                                         exit( EXIT_FAILURE );
330                                 }
331                                 if( cvalue != NULL ) {
332                                         fprintf( stderr,
333                                                 "manageDSAit: no control value expected\n" );
334                                         usage();
335                                 }
336
337                                 manageDSAit = 1 + crit;
338
339                         } else if ( strcasecmp( control, "noop" ) == 0 ) {
340                                 if( noop ) {
341                                         fprintf( stderr, "noop control previously specified\n");
342                                         exit( EXIT_FAILURE );
343                                 }
344                                 if( cvalue != NULL ) {
345                                         fprintf( stderr, "noop: no control value expected\n" );
346                                         usage();
347                                 }
348
349                                 noop = 1 + crit;
350
351 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
352                         } else if ( strcasecmp( control, "ppolicy" ) == 0 ) {
353                                 if( ppolicy ) {
354                                         fprintf( stderr, "ppolicy control previously specified\n");
355                                         exit( EXIT_FAILURE );
356                                 }
357                                 if( cvalue != NULL ) {
358                                         fprintf( stderr, "ppolicy: no control value expected\n" );
359                                         usage();
360                                 }
361                                 if( crit ) {
362                                         fprintf( stderr, "ppolicy: critical flag not allowed\n" );
363                                         usage();
364                                 }
365
366                                 ppolicy = 1;
367 #endif
368
369                         } else if ( strcasecmp( control, "preread" ) == 0 ) {
370                                 if( preread ) {
371                                         fprintf( stderr, "preread control previously specified\n");
372                                         exit( EXIT_FAILURE );
373                                 }
374
375                                 preread = 1 + crit;
376                                 preread_attrs = cvalue;
377
378                         } else if ( strcasecmp( control, "postread" ) == 0 ) {
379                                 if( postread ) {
380                                         fprintf( stderr, "postread control previously specified\n");
381                                         exit( EXIT_FAILURE );
382                                 }
383
384                                 postread = 1 + crit;
385                                 postread_attrs = cvalue;
386
387 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
388                         } else if ( strcasecmp( control, "chaining" ) == 0 ) {
389                                 chaining = 1 + crit;
390
391                                 if ( cvalue != NULL ) {
392                                         char    *continuation;
393
394                                         continuation = strchr( cvalue, '/' );
395                                         if ( continuation ) {
396                                                 /* FIXME: this makes sense only in searches */
397                                                 *continuation++ = '\0';
398                                                 if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
399                                                         chainingContinuation = LDAP_CHAINING_PREFERRED;
400                                                 } else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
401                                                         chainingContinuation = LDAP_CHAINING_REQUIRED;
402                                                 } else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
403                                                         chainingContinuation = LDAP_REFERRALS_PREFERRED;
404                                                 } else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
405                                                         chainingContinuation = LDAP_REFERRALS_REQUIRED;
406                                                 } else {
407                                                         fprintf( stderr,
408                                                                 "chaining behavior control "
409                                                                 "continuation value \"%s\" invalid\n",
410                                                                 continuation );
411                                                         exit( EXIT_FAILURE );
412                                                 }
413                                         }
414         
415                                         if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
416                                                 chainingResolve = LDAP_CHAINING_PREFERRED;
417                                         } else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
418                                                 chainingResolve = LDAP_CHAINING_REQUIRED;
419                                         } else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
420                                                 chainingResolve = LDAP_REFERRALS_PREFERRED;
421                                         } else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
422                                                 chainingResolve = LDAP_REFERRALS_REQUIRED;
423                                         } else {
424                                                 fprintf( stderr,
425                                                         "chaining behavior control "
426                                                         "resolve value \"%s\" invalid\n",
427                                                         cvalue);
428                                                 exit( EXIT_FAILURE );
429                                         }
430                                 }
431 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
432
433                         /* this shouldn't go here, really; but it's a feature... */
434                         } else if ( strcasecmp( control, "abandon" ) == 0 ) {
435                                 abcan = LDAP_REQ_ABANDON;
436
437                         } else if ( strcasecmp( control, "cancel" ) == 0 ) {
438                                 abcan = LDAP_REQ_EXTENDED;
439
440                         } else {
441                                 fprintf( stderr, "Invalid general control name: %s\n",
442                                         control );
443                                 usage();
444                         }
445                         break;
446                 case 'f':       /* read from file */
447                         if( infile != NULL ) {
448                                 fprintf( stderr, "%s: -f previously specified\n", prog );
449                                 exit( EXIT_FAILURE );
450                         }
451                         infile = ber_strdup( optarg );
452                         break;
453                 case 'h':       /* ldap host */
454                         if( ldaphost != NULL ) {
455                                 fprintf( stderr, "%s: -h previously specified\n", prog );
456                                 exit( EXIT_FAILURE );
457                         }
458                         ldaphost = ber_strdup( optarg );
459                         break;
460                 case 'H':       /* ldap URI */
461                         if( ldapuri != NULL ) {
462                                 fprintf( stderr, "%s: -H previously specified\n", prog );
463                                 exit( EXIT_FAILURE );
464                         }
465                         ldapuri = ber_strdup( optarg );
466                         break;
467                 case 'I':
468 #ifdef HAVE_CYRUS_SASL
469                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
470                                 fprintf( stderr, "%s: incompatible previous "
471                                         "authentication choice\n",
472                                         prog );
473                                 exit( EXIT_FAILURE );
474                         }
475                         authmethod = LDAP_AUTH_SASL;
476                         sasl_flags = LDAP_SASL_INTERACTIVE;
477                         break;
478 #else
479                         fprintf( stderr, "%s: was not compiled with SASL support\n",
480                                 prog );
481                         exit( EXIT_FAILURE );
482 #endif
483                 case 'k':       /* kerberos bind */
484 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
485                         if( authmethod != -1 ) {
486                                 fprintf( stderr, "%s: -k incompatible with previous "
487                                         "authentication choice\n", prog );
488                                 exit( EXIT_FAILURE );
489                         }
490                         authmethod = LDAP_AUTH_KRBV4;
491 #else
492                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
493                         exit( EXIT_FAILURE );
494 #endif
495                         break;
496                 case 'K':       /* kerberos bind, part one only */
497 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
498                         if( authmethod != -1 ) {
499                                 fprintf( stderr, "%s: incompatible with previous "
500                                         "authentication choice\n", prog );
501                                 exit( EXIT_FAILURE );
502                         }
503                         authmethod = LDAP_AUTH_KRBV41;
504 #else
505                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
506                         exit( EXIT_FAILURE );
507 #endif
508                         break;
509                 case 'M':
510                         /* enable Manage DSA IT */
511                         manageDSAit++;
512                         break;
513                 case 'n':       /* print operations, don't actually do them */
514                         not++;
515                         break;
516                 case 'O':
517 #ifdef HAVE_CYRUS_SASL
518                         if( sasl_secprops != NULL ) {
519                                 fprintf( stderr, "%s: -O previously specified\n", prog );
520                                 exit( EXIT_FAILURE );
521                         }
522                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
523                                 fprintf( stderr, "%s: incompatible previous "
524                                         "authentication choice\n", prog );
525                                 exit( EXIT_FAILURE );
526                         }
527                         authmethod = LDAP_AUTH_SASL;
528                         sasl_secprops = ber_strdup( optarg );
529 #else
530                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
531                         exit( EXIT_FAILURE );
532 #endif
533                         break;
534                 case 'p':
535                         if( ldapport ) {
536                                 fprintf( stderr, "%s: -p previously specified\n", prog );
537                                 exit( EXIT_FAILURE );
538                         }
539                         ival = strtol( optarg, &next, 10 );
540                         if ( next == NULL || next[0] != '\0' ) {
541                                 fprintf( stderr, "%s: unable to parse port number \"%s\"\n", prog, optarg );
542                                 exit( EXIT_FAILURE );
543                         }
544                         ldapport = ival;
545                         break;
546                 case 'P':
547                         ival = strtol( optarg, &next, 10 );
548                         if ( next == NULL || next[0] != '\0' ) {
549                                 fprintf( stderr, "%s: unabel to parse protocol version \"%s\"\n", prog, optarg );
550                                 exit( EXIT_FAILURE );
551                         }
552                         switch( ival ) {
553                         case 2:
554                                 if( protocol == LDAP_VERSION3 ) {
555                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
556                                                 prog, protocol );
557                                         exit( EXIT_FAILURE );
558                                 }
559                                 protocol = LDAP_VERSION2;
560                                 break;
561                         case 3:
562                                 if( protocol == LDAP_VERSION2 ) {
563                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
564                                                 prog, protocol );
565                                         exit( EXIT_FAILURE );
566                                 }
567                                 protocol = LDAP_VERSION3;
568                                 break;
569                         default:
570                                 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
571                                         prog );
572                                 usage();
573                         }
574                         break;
575                 case 'Q':
576 #ifdef HAVE_CYRUS_SASL
577                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
578                                 fprintf( stderr, "%s: incompatible previous "
579                                         "authentication choice\n",
580                                         prog );
581                                 exit( EXIT_FAILURE );
582                         }
583                         authmethod = LDAP_AUTH_SASL;
584                         sasl_flags = LDAP_SASL_QUIET;
585                         break;
586 #else
587                         fprintf( stderr, "%s: not compiled with SASL support\n",
588                                 prog );
589                         exit( EXIT_FAILURE );
590 #endif
591                 case 'R':
592 #ifdef HAVE_CYRUS_SASL
593                         if( sasl_realm != NULL ) {
594                                 fprintf( stderr, "%s: -R previously specified\n", prog );
595                                 exit( EXIT_FAILURE );
596                         }
597                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
598                                 fprintf( stderr, "%s: incompatible previous "
599                                         "authentication choice\n",
600                                         prog );
601                                 exit( EXIT_FAILURE );
602                         }
603                         authmethod = LDAP_AUTH_SASL;
604                         sasl_realm = ber_strdup( optarg );
605 #else
606                         fprintf( stderr, "%s: not compiled with SASL support\n",
607                                 prog );
608                         exit( EXIT_FAILURE );
609 #endif
610                         break;
611                 case 'U':
612 #ifdef HAVE_CYRUS_SASL
613                         if( sasl_authc_id != NULL ) {
614                                 fprintf( stderr, "%s: -U previously specified\n", prog );
615                                 exit( EXIT_FAILURE );
616                         }
617                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
618                                 fprintf( stderr, "%s: incompatible previous "
619                                         "authentication choice\n",
620                                         prog );
621                                 exit( EXIT_FAILURE );
622                         }
623                         authmethod = LDAP_AUTH_SASL;
624                         sasl_authc_id = ber_strdup( optarg );
625 #else
626                         fprintf( stderr, "%s: not compiled with SASL support\n",
627                                 prog );
628                         exit( EXIT_FAILURE );
629 #endif
630                         break;
631                 case 'v':       /* verbose mode */
632                         verbose++;
633                         break;
634                 case 'V':       /* version */
635                         version++;
636                         break;
637                 case 'w':       /* password */
638                         passwd.bv_val = ber_strdup( optarg );
639                         {
640                                 char* p;
641
642                                 for( p = optarg; *p != '\0'; p++ ) {
643                                         *p = '\0';
644                                 }
645                         }
646                         passwd.bv_len = strlen( passwd.bv_val );
647                         break;
648                 case 'W':
649                         want_bindpw++;
650                         break;
651                 case 'y':
652                         pw_file = optarg;
653                         break;
654                 case 'Y':
655 #ifdef HAVE_CYRUS_SASL
656                         if( sasl_mech != NULL ) {
657                                 fprintf( stderr, "%s: -Y previously specified\n", prog );
658                                 exit( EXIT_FAILURE );
659                         }
660                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
661                                 fprintf( stderr,
662                                         "%s: incompatible with authentication choice\n", prog );
663                                 exit( EXIT_FAILURE );
664                         }
665                         authmethod = LDAP_AUTH_SASL;
666                         sasl_mech = ber_strdup( optarg );
667 #else
668                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
669                         exit( EXIT_FAILURE );
670 #endif
671                         break;
672                 case 'x':
673                         if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
674                                 fprintf( stderr, "%s: incompatible with previous "
675                                         "authentication choice\n", prog );
676                                 exit( EXIT_FAILURE );
677                         }
678                         authmethod = LDAP_AUTH_SIMPLE;
679                         break;
680                 case 'X':
681 #ifdef HAVE_CYRUS_SASL
682                         if( sasl_authz_id != NULL ) {
683                                 fprintf( stderr, "%s: -X previously specified\n", prog );
684                                 exit( EXIT_FAILURE );
685                         }
686                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
687                                 fprintf( stderr, "%s: -X incompatible with "
688                                         "authentication choice\n", prog );
689                                 exit( EXIT_FAILURE );
690                         }
691                         authmethod = LDAP_AUTH_SASL;
692                         sasl_authz_id = ber_strdup( optarg );
693 #else
694                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
695                         exit( EXIT_FAILURE );
696 #endif
697                         break;
698                 case 'Z':
699 #ifdef HAVE_TLS
700                         use_tls++;
701 #else
702                         fprintf( stderr, "%s: not compiled with TLS support\n", prog );
703                         exit( EXIT_FAILURE );
704 #endif
705                         break;
706                 default:
707                         if( handle_private_option( i ) ) break;
708                         fprintf( stderr, "%s: unrecognized option -%c\n",
709                                 prog, optopt );
710                         usage();
711                 }
712         }
713
714         {
715                 /* prevent bad linking */
716                 LDAPAPIInfo api;
717                 api.ldapai_info_version = LDAP_API_INFO_VERSION;
718
719                 if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
720                         != LDAP_OPT_SUCCESS )
721                 {
722                         fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
723                         exit( EXIT_FAILURE );
724                 }
725
726                 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
727                         fprintf( stderr, "LDAP APIInfo version mismatch: "
728                                 "library %d, header %d\n",
729                                 api.ldapai_info_version, LDAP_API_INFO_VERSION );
730                         exit( EXIT_FAILURE );
731                 }
732
733                 if( api.ldapai_api_version != LDAP_API_VERSION ) {
734                         fprintf( stderr, "LDAP API version mismatch: "
735                                 "library %d, header %d\n",
736                                 api.ldapai_api_version, LDAP_API_VERSION );
737                         exit( EXIT_FAILURE );
738                 }
739
740                 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
741                         fprintf( stderr, "LDAP vendor name mismatch: "
742                                 "library %s, header %s\n",
743                                 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
744                         exit( EXIT_FAILURE );
745                 }
746
747                 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
748                         fprintf( stderr, "LDAP vendor version mismatch: "
749                                 "library %d, header %d\n",
750                                 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
751                         exit( EXIT_FAILURE );
752                 }
753
754                 if (version) {
755                         fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
756                                 prog, __Version,
757                                 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
758                         if (version > 1) exit( EXIT_SUCCESS );
759                 }
760
761                 ldap_memfree( api.ldapai_vendor_name );
762                 ber_memvfree( (void **)api.ldapai_extensions );
763         }
764
765         if (protocol == -1)
766                 protocol = LDAP_VERSION3;
767
768         if (authmethod == -1 && protocol > LDAP_VERSION2) {
769 #ifdef HAVE_CYRUS_SASL
770                 authmethod = LDAP_AUTH_SASL;
771 #else
772                 authmethod = LDAP_AUTH_SIMPLE;
773 #endif
774         }
775
776         if( ldapuri == NULL ) {
777                 if( ldapport && ( ldaphost == NULL )) {
778                         fprintf( stderr, "%s: -p without -h is invalid.\n", prog );
779                         exit( EXIT_FAILURE );
780                 }
781         } else {
782                 if( ldaphost != NULL ) {
783                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
784                         exit( EXIT_FAILURE );
785                 }
786                 if( ldapport ) {
787                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
788                         exit( EXIT_FAILURE );
789                 }
790         }
791         if( protocol == LDAP_VERSION2 ) {
792                 if( assertctl || authzid || manageDIT || manageDSAit ||
793 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
794                         chaining ||
795 #endif
796                         noop || ppolicy || preread || postread )
797                 {
798                         fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
799                         exit( EXIT_FAILURE );
800                 }
801 #ifdef HAVE_TLS
802                 if( use_tls ) {
803                         fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
804                         exit( EXIT_FAILURE );
805                 }
806 #endif
807 #ifdef HAVE_CYRUS_SASL
808                 if( authmethod == LDAP_AUTH_SASL ) {
809                         fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
810                                 prog );
811                         exit( EXIT_FAILURE );
812                 }
813 #endif
814         } else {
815 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
816                 if ( authmethod == LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
817                         fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
818                                 prog, protocol );
819                         exit( EXIT_FAILURE );
820                 }
821 #endif
822         }
823 }
824
825
826 LDAP *
827 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
828 {
829         LDAP *ld = NULL;
830
831         if ( debug ) {
832                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
833                         != LBER_OPT_SUCCESS )
834                 {
835                         fprintf( stderr,
836                                 "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
837                 }
838                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
839                         != LDAP_OPT_SUCCESS )
840                 {
841                         fprintf( stderr,
842                                 "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
843                 }
844         }
845
846 #ifdef SIGPIPE
847         (void) SIGNAL( SIGPIPE, SIG_IGN );
848 #endif
849
850         if ( abcan ) {
851                 SIGNAL( SIGINT, do_sig );
852         }
853
854         if ( !not ) {
855                 int rc;
856
857                 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
858                         /* construct URL */
859                         LDAPURLDesc url;
860                         memset( &url, 0, sizeof(url));
861
862                         url.lud_scheme = "ldap";
863                         url.lud_host = ldaphost;
864                         url.lud_port = ldapport;
865                         url.lud_scope = LDAP_SCOPE_DEFAULT;
866
867                         ldapuri = ldap_url_desc2str( &url );
868                 }
869
870                 if ( verbose ) {
871                         fprintf( stderr, "ldap_initialize( %s )\n",
872                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
873                 }
874                 rc = ldap_initialize( &ld, ldapuri );
875                 if( rc != LDAP_SUCCESS ) {
876                         fprintf( stderr,
877                                 "Could not create LDAP session handle for URI=%s (%d): %s\n",
878                                 ldapuri, rc, ldap_err2string(rc) );
879                         exit( EXIT_FAILURE );
880                 }
881
882                 if( private_setup ) private_setup( ld );
883
884                 /* referrals */
885                 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
886                         referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
887                 {
888                         fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
889                                 referrals ? "on" : "off" );
890                         exit( EXIT_FAILURE );
891                 }
892
893                 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
894                         != LDAP_OPT_SUCCESS )
895                 {
896                         fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
897                                 protocol );
898                         exit( EXIT_FAILURE );
899                 }
900
901                 if ( use_tls ) {
902                         rc = ldap_start_tls_s( ld, NULL, NULL );
903                         if ( rc != LDAP_SUCCESS ) {
904                                 tool_perror( "ldap_start_tls", rc, NULL, NULL, NULL, NULL );
905                                 if ( use_tls > 1 ) {
906                                         exit( EXIT_FAILURE );
907                                 }
908                         }
909                 }
910         }
911
912         return ld;
913 }
914
915
916 void
917 tool_bind( LDAP *ld )
918 {
919 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
920         if ( ppolicy ) {
921                 LDAPControl *ctrls[2], c;
922                 c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
923                 c.ldctl_value.bv_val = NULL;
924                 c.ldctl_value.bv_len = 0;
925                 c.ldctl_iscritical = 0;
926                 ctrls[0] = &c;
927                 ctrls[1] = NULL;
928                 ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
929         }
930 #endif
931
932         if ( authmethod == LDAP_AUTH_SASL ) {
933 #ifdef HAVE_CYRUS_SASL
934                 void *defaults;
935                 int rc;
936
937                 if( sasl_secprops != NULL ) {
938                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
939                                 (void *) sasl_secprops );
940
941                         if( rc != LDAP_OPT_SUCCESS ) {
942                                 fprintf( stderr,
943                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
944                                         sasl_secprops );
945                                 exit( EXIT_FAILURE );
946                         }
947                 }
948
949                 defaults = lutil_sasl_defaults( ld,
950                         sasl_mech,
951                         sasl_realm,
952                         sasl_authc_id,
953                         passwd.bv_val,
954                         sasl_authz_id );
955
956                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
957                         sasl_mech, NULL, NULL,
958                         sasl_flags, lutil_sasl_interact, defaults );
959
960                 lutil_sasl_freedefs( defaults );
961                 if( rc != LDAP_SUCCESS ) {
962                         tool_perror( "ldap_sasl_interactive_bind_s",
963                                 rc, NULL, NULL, NULL, NULL );
964                         exit( EXIT_FAILURE );
965                 }
966 #else
967                 fprintf( stderr, "%s: not compiled with SASL support\n",
968                         prog );
969                 exit( EXIT_FAILURE );
970 #endif
971         } else {
972                 int msgid, err, rc;
973                 LDAPMessage *result;
974                 LDAPControl **ctrls;
975                 char msgbuf[256];
976                 char *matched = NULL;
977                 char *info = NULL;
978                 char **refs = NULL;
979
980                 msgbuf[0] = 0;
981
982                 msgid = ldap_bind( ld, binddn, passwd.bv_val, authmethod );
983                 if ( msgid == -1 ) {
984                         tool_perror( "ldap_bind", -1, NULL, NULL, NULL, NULL );
985                         exit( EXIT_FAILURE );
986                 }
987
988                 if ( ldap_result( ld, msgid, 1, NULL, &result ) == -1 ) {
989                         tool_perror( "ldap_result", -1, NULL, NULL, NULL, NULL );
990                         exit( EXIT_FAILURE );
991                 }
992
993                 rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs,
994                         &ctrls, 1 );
995                 if ( rc != LDAP_SUCCESS ) {
996                         tool_perror( "ldap_bind parse result", rc, NULL, NULL, NULL, NULL );
997                         exit( EXIT_FAILURE );
998                 }
999
1000 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1001                 if ( ctrls && ppolicy ) {
1002                         LDAPControl *ctrl;
1003                         int expire, grace, len = 0;
1004                         LDAPPasswordPolicyError pErr = -1;
1005                         
1006                         ctrl = ldap_find_control( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
1007                                 ctrls );
1008
1009                         if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl,
1010                                 &expire, &grace, &pErr ) == LDAP_SUCCESS )
1011                         {
1012                                 if ( pErr != PP_noError ){
1013                                         msgbuf[0] = ';';
1014                                         msgbuf[1] = ' ';
1015                                         strcpy( msgbuf+2, ldap_passwordpolicy_err2txt( pErr ));
1016                                         len = strlen( msgbuf );
1017                                 }
1018                                 if ( expire >= 0 ) {
1019                                         sprintf( msgbuf+len,
1020                                                 " (Password expires in %d seconds)",
1021                                                 expire );
1022                                 } else if ( grace >= 0 ) {
1023                                         sprintf( msgbuf+len,
1024                                                 " (Password expired, %d grace logins remain)",
1025                                                 grace );
1026                                 }
1027                         }
1028                 }
1029 #endif
1030
1031                 if ( ctrls ) {
1032                         ldap_controls_free( ctrls );
1033                 }
1034
1035                 if ( err != LDAP_SUCCESS
1036                         || msgbuf[0]
1037                         || ( matched && matched[ 0 ] )
1038                         || ( info && info[ 0 ] )
1039                         || refs )
1040                 {
1041                         tool_perror( "ldap_bind", err, msgbuf, matched, info, refs );
1042
1043                         if( matched ) ber_memfree( matched );
1044                         if( info ) ber_memfree( info );
1045                         if( refs ) ber_memvfree( (void **)refs );
1046
1047                         if ( err != LDAP_SUCCESS ) exit( EXIT_FAILURE );
1048                 }
1049         }
1050 }
1051
1052 void
1053 tool_unbind( LDAP *ld )
1054 {
1055         int err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
1056
1057         if ( err != LDAP_OPT_SUCCESS ) {
1058                 fprintf( stderr, "Could not unset controls\n");
1059         }
1060
1061         (void) ldap_unbind_ext( ld, NULL, NULL );
1062 }
1063
1064
1065 /* Set server controls.  Add controls extra_c[0..count-1], if set. */
1066 void
1067 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
1068 {
1069         int i = 0, j, crit = 0, err;
1070         LDAPControl c[10], **ctrls;
1071
1072         ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
1073         if ( ctrls == NULL ) {
1074                 fprintf( stderr, "No memory\n" );
1075                 exit( EXIT_FAILURE );
1076         }
1077
1078         if ( assertctl ) {
1079                 BerElementBuffer berbuf;
1080                 BerElement *ber = (BerElement *)&berbuf;
1081                 
1082                 if( assertion == NULL || *assertion == '\0' ) {
1083                         fprintf( stderr, "Assertion=<empty>\n" );
1084                         exit( EXIT_FAILURE );
1085                 }
1086
1087                 ber_init2( ber, NULL, LBER_USE_DER );
1088
1089                 err = ldap_pvt_put_filter( ber, assertion );
1090                 if( err < 0 ) {
1091                         fprintf( stderr, "assertion encode failed (%d)\n", err );
1092                         exit( EXIT_FAILURE );
1093                 }
1094
1095                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
1096                 if( err < 0 ) {
1097                         fprintf( stderr, "assertion flatten failed (%d)\n", err );
1098                         exit( EXIT_FAILURE );
1099                 }
1100
1101                 c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
1102                 c[i].ldctl_iscritical = assertctl > 1;
1103                 ctrls[i] = &c[i];
1104                 i++;
1105         }
1106
1107         if ( authzid ) {
1108                 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
1109                 c[i].ldctl_value.bv_val = authzid;
1110                 c[i].ldctl_value.bv_len = strlen( authzid );
1111                 c[i].ldctl_iscritical = 1;
1112                 ctrls[i] = &c[i];
1113                 i++;
1114         }
1115
1116         if ( manageDIT ) {
1117                 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDIT;
1118                 BER_BVZERO( &c[i].ldctl_value );
1119                 c[i].ldctl_iscritical = manageDIT > 1;
1120                 ctrls[i] = &c[i];
1121                 i++;
1122         }
1123
1124         if ( manageDSAit ) {
1125                 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
1126                 BER_BVZERO( &c[i].ldctl_value );
1127                 c[i].ldctl_iscritical = manageDSAit > 1;
1128                 ctrls[i] = &c[i];
1129                 i++;
1130         }
1131
1132         if ( noop ) {
1133                 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
1134                 BER_BVZERO( &c[i].ldctl_value );
1135                 c[i].ldctl_iscritical = noop > 1;
1136                 ctrls[i] = &c[i];
1137                 i++;
1138         }
1139
1140         if ( preread ) {
1141                 char berbuf[LBER_ELEMENT_SIZEOF];
1142                 BerElement *ber = (BerElement *)berbuf;
1143                 char **attrs = NULL;
1144
1145                 if( preread_attrs ) {
1146                         attrs = ldap_str2charray( preread_attrs, "," );
1147                 }
1148
1149                 ber_init2( ber, NULL, LBER_USE_DER );
1150
1151                 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
1152                         fprintf( stderr, "preread attrs encode failed.\n" );
1153                         exit( EXIT_FAILURE );
1154                 }
1155
1156                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
1157                 if( err < 0 ) {
1158                         fprintf( stderr, "preread flatten failed (%d)\n", err );
1159                         exit( EXIT_FAILURE );
1160                 }
1161
1162                 c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
1163                 c[i].ldctl_iscritical = preread > 1;
1164                 ctrls[i] = &c[i];
1165                 i++;
1166
1167                 if( attrs ) ldap_charray_free( attrs );
1168         }
1169
1170         if ( postread ) {
1171                 char berbuf[LBER_ELEMENT_SIZEOF];
1172                 BerElement *ber = (BerElement *)berbuf;
1173                 char **attrs = NULL;
1174
1175                 if( postread_attrs ) {
1176                         attrs = ldap_str2charray( postread_attrs, "," );
1177                 }
1178
1179                 ber_init2( ber, NULL, LBER_USE_DER );
1180
1181                 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
1182                         fprintf( stderr, "postread attrs encode failed.\n" );
1183                         exit( EXIT_FAILURE );
1184                 }
1185
1186                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
1187                 if( err < 0 ) {
1188                         fprintf( stderr, "postread flatten failed (%d)\n", err );
1189                         exit( EXIT_FAILURE );
1190                 }
1191
1192                 c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
1193                 c[i].ldctl_iscritical = postread > 1;
1194                 ctrls[i] = &c[i];
1195                 i++;
1196
1197                 if( attrs ) ldap_charray_free( attrs );
1198         }
1199
1200 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1201         if ( chaining ) {
1202                 if ( chainingResolve > -1 ) {
1203                         BerElementBuffer berbuf;
1204                         BerElement *ber = (BerElement *)&berbuf;
1205
1206                         ber_init2( ber, NULL, LBER_USE_DER );
1207
1208                         err = ber_printf( ber, "{e" /* } */, chainingResolve );
1209                         if ( err == -1 ) {
1210                                 ber_free( ber, 1 );
1211                                 fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1212                                 exit( EXIT_FAILURE );
1213                         }
1214
1215                         if ( chainingContinuation > -1 ) {
1216                                 err = ber_printf( ber, "e", chainingContinuation );
1217                                 if ( err == -1 ) {
1218                                         ber_free( ber, 1 );
1219                                         fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1220                                         exit( EXIT_FAILURE );
1221                                 }
1222                         }
1223
1224                         err = ber_printf( ber, /* { */ "N}" );
1225                         if ( err == -1 ) {
1226                                 ber_free( ber, 1 );
1227                                 fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1228                                 exit( EXIT_FAILURE );
1229                         }
1230
1231                         if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
1232                                 exit( EXIT_FAILURE );
1233                         }
1234
1235                 } else {
1236                         BER_BVZERO( &c[i].ldctl_value );
1237                 }
1238
1239                 c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
1240                 c[i].ldctl_iscritical = chaining > 1;
1241                 ctrls[i] = &c[i];
1242                 i++;
1243         }
1244 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
1245
1246         while ( count-- ) {
1247                 ctrls[i++] = extra_c++;
1248         }
1249         ctrls[i] = NULL;
1250
1251         err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
1252
1253         if ( err != LDAP_OPT_SUCCESS ) {
1254                 for ( j = 0; j < i; j++ ) {
1255                         if ( ctrls[j]->ldctl_iscritical ) crit = 1;
1256                 }
1257                 fprintf( stderr, "Could not set %scontrols\n",
1258                         crit ? "critical " : "" );
1259         }
1260
1261         free( ctrls );
1262         if ( crit ) {
1263                 exit( EXIT_FAILURE );
1264         }
1265 }
1266
1267 int
1268 tool_check_abandon( LDAP *ld, int msgid )
1269 {
1270         int     rc;
1271
1272         switch ( gotintr ) {
1273         case LDAP_REQ_EXTENDED:
1274                 rc = ldap_cancel_s( ld, msgid, NULL, NULL );
1275                 fprintf( stderr, "got interrupt, cancel got %d: %s\n",
1276                                 rc, ldap_err2string( rc ) );
1277                 return -1;
1278
1279         case LDAP_REQ_ABANDON:
1280                 rc = ldap_abandon_ext( ld, msgid, NULL, NULL );
1281                 fprintf( stderr, "got interrupt, abandon got %d: %s\n",
1282                                 rc, ldap_err2string( rc ) );
1283                 return -1;
1284         }
1285
1286         return 0;
1287 }
1288