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