]> git.sur5r.net Git - openldap/blob - clients/tools/common.c
Dunno in advance how many controls will be set by a client
[openldap] / clients / tools / common.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* common.c - common routines for the ldap client tools */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/stdlib.h>
13 #include <ac/signal.h>
14 #include <ac/string.h>
15 #include <ac/unistd.h>
16 #include <ac/errno.h>
17
18 #include <ldap.h>
19
20 #include "lutil_ldap.h"
21
22 #include "common.h"
23
24
25 int   authmethod = -1;
26 char *binddn = NULL;
27 int   contoper = 0;
28 int   debug = 0;
29 char *infile = NULL;
30 char *ldapuri = NULL;
31 char *ldaphost = NULL;
32 int   ldapport = 0;
33 #ifdef HAVE_CYRUS_SASL
34 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
35 char    *sasl_realm = NULL;
36 char    *sasl_authc_id = NULL;
37 char    *sasl_authz_id = NULL;
38 char    *sasl_mech = NULL;
39 char    *sasl_secprops = NULL;
40 #endif
41 int   use_tls = 0;
42
43 char *authzid = NULL;
44 int   manageDSAit = 0;
45 int   noop = 0;
46
47 int   not = 0;
48 int   want_bindpw = 0;
49 struct berval passwd = { 0, NULL };
50 char *pw_file = NULL;
51 int   referrals = 0;
52 int   verbose = 0;
53 int   version = -1;
54
55
56 /* Set in main() */
57 char *prog;
58
59
60 void
61 tool_common_usage( void )
62 {
63         static const char *const descriptions[] = {
64 "  -c         continuous operation mode (do not stop on errors)\n",
65 "  -C         chase referrals\n",
66 "  -d level   set LDAP debugging level to `level'\n",
67 "  -D binddn  bind DN\n",
68 "  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
69 "             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
70 "             [!]manageDSAit       (alternate form, see -M)\n"
71 "             [!]noop\n",
72 "  -f file    read operations from `file'\n",
73 "  -h host    LDAP server\n",
74 "  -H URI     LDAP Uniform Resource Indentifier(s)\n",
75 "  -I         use SASL Interactive mode\n",
76 "  -k         use Kerberos authentication\n",
77 "  -K         like -k, but do only step 1 of the Kerberos bind\n",
78 "  -M         enable Manage DSA IT control (-MM to make critical)\n",
79 "  -n         show what would be done but don't actually do it\n",
80 "  -O props   SASL security properties\n",
81 "  -p port    port on LDAP server\n",
82 "  -P version procotol version (default: 3)\n",
83 "  -Q         use SASL Quiet mode\n",
84 "  -R realm   SASL realm\n",
85 "  -U authcid SASL authentication identity\n",
86 "  -v         run in verbose mode (diagnostics to standard output)\n",
87 "  -w passwd  bind passwd (for simple authentication)\n",
88 "  -W         prompt for bind passwd\n",
89 "  -x         Simple authentication\n",
90 "  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n",
91 "  -y file    Read passwd from file\n",
92 "  -Y mech    SASL mechanism\n",
93 "  -Z         Start TLS request (-ZZ to require successful response)\n",
94 NULL
95         };
96         const char *const *cpp, *cp;
97
98         fputs( "Common options:\n", stderr );
99         for( cpp = descriptions; (cp = *cpp) != NULL; cpp++ )
100                 if( strchr( options, cp[3] ) )
101                         fputs( cp, stderr );
102 }
103
104
105 void
106 tool_args( int argc, char **argv )
107 {
108         int i;
109     while (( i = getopt( argc, argv, options )) != EOF )
110         {
111                 int crit;
112                 char *control, *cvalue;
113                 switch( i ) {
114                 case 'c':       /* continuous operation mode */
115                         contoper = 1;
116                         break;
117                 case 'C':
118                         referrals = 1;
119                         break;
120                 case 'd':
121                         debug |= atoi( optarg );
122                         break;
123                 case 'D':       /* bind DN */
124                         if( binddn != NULL ) {
125                                 fprintf( stderr, "%s: -D previously specified\n", prog );
126                                 exit( EXIT_FAILURE );
127                         }
128                         binddn = ber_strdup( optarg );
129                         break;
130                 case 'e': /* general controls */
131                         /* should be extended to support comma separated list of
132                          *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
133                          */
134
135                         crit = 0;
136                         cvalue = NULL;
137                         if( optarg[0] == '!' ) {
138                                 crit = 1;
139                                 optarg++;
140                         }
141
142                         control = ber_strdup( optarg );
143                         if ( (cvalue = strchr( control, '=' )) != NULL ) {
144                                 *cvalue++ = '\0';
145                         }
146
147                         if ( strcasecmp( control, "authzid" ) == 0 ) {
148                                 if( authzid != NULL ) {
149                                         fprintf( stderr, "authzid control previously specified\n");
150                                         exit( EXIT_FAILURE );
151                                 }
152                                 if( cvalue == NULL ) {
153                                         fprintf( stderr, "authzid: control value expected\n" );
154                                         usage();
155                                 }
156                                 if( !crit ) {
157                                         fprintf( stderr, "authzid: must be marked critical\n" );
158                                         usage();
159                                 }
160
161                                 assert( authzid == NULL );
162                                 authzid = cvalue;
163
164                         } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
165                                 if( manageDSAit ) {
166                                         fprintf( stderr,
167                                                  "manageDSAit control previously specified\n");
168                                         exit( EXIT_FAILURE );
169                                 }
170                                 if( cvalue != NULL ) {
171                                         fprintf( stderr,
172                                                  "manageDSAit: no control value expected\n" );
173                                         usage();
174                                 }
175
176                                 manageDSAit = 1 + crit;
177
178                         } else if ( strcasecmp( control, "noop" ) == 0 ) {
179                                 if( noop ) {
180                                         fprintf( stderr, "noop control previously specified\n");
181                                         exit( EXIT_FAILURE );
182                                 }
183                                 if( cvalue != NULL ) {
184                                         fprintf( stderr, "noop: no control value expected\n" );
185                                         usage();
186                                 }
187
188                                 noop = 1 + crit;
189
190                         } else {
191                                 fprintf( stderr, "Invalid general control name: %s\n",
192                                          control );
193                                 usage();
194                         }
195                         break;
196                 case 'f':       /* read from file */
197                         if( infile != NULL ) {
198                                 fprintf( stderr, "%s: -f previously specified\n", prog );
199                                 exit( EXIT_FAILURE );
200                         }
201                         infile = ber_strdup( optarg );
202                         break;
203                 case 'h':       /* ldap host */
204                         if( ldaphost != NULL ) {
205                                 fprintf( stderr, "%s: -h previously specified\n", prog );
206                                 exit( EXIT_FAILURE );
207                         }
208                         ldaphost = ber_strdup( optarg );
209                         break;
210                 case 'H':       /* ldap URI */
211                         if( ldapuri != NULL ) {
212                                 fprintf( stderr, "%s: -H previously specified\n", prog );
213                                 exit( EXIT_FAILURE );
214                         }
215                         ldapuri = ber_strdup( optarg );
216                         break;
217                 case 'I':
218 #ifdef HAVE_CYRUS_SASL
219                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
220                                 fprintf( stderr, "%s: incompatible previous "
221                                                  "authentication choice\n",
222                                                  prog );
223                                 exit( EXIT_FAILURE );
224                         }
225                         authmethod = LDAP_AUTH_SASL;
226                         sasl_flags = LDAP_SASL_INTERACTIVE;
227                         break;
228 #else
229                         fprintf( stderr, "%s: was not compiled with SASL support\n",
230                                          prog );
231                         exit( EXIT_FAILURE );
232 #endif
233                 case 'k':       /* kerberos bind */
234 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
235                         if( authmethod != -1 ) {
236                                 fprintf( stderr, "%s: -k incompatible with previous "
237                                                  "authentication choice\n", prog );
238                                 exit( EXIT_FAILURE );
239                         }
240                         authmethod = LDAP_AUTH_KRBV4;
241 #else
242                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
243                         exit( EXIT_FAILURE );
244 #endif
245                         break;
246                 case 'K':       /* kerberos bind, part one only */
247 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
248                         if( authmethod != -1 ) {
249                                 fprintf( stderr, "%s: incompatible with previous "
250                                                  "authentication choice\n", prog );
251                                 exit( EXIT_FAILURE );
252                         }
253                         authmethod = LDAP_AUTH_KRBV41;
254 #else
255                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
256                         exit( EXIT_FAILURE );
257 #endif
258                         break;
259                 case 'M':
260                         /* enable Manage DSA IT */
261                         manageDSAit = 1;
262                         break;
263                 case 'n':       /* print operations, don't actually do them */
264                         not = 1;
265                         break;
266                 case 'O':
267 #ifdef HAVE_CYRUS_SASL
268                         if( sasl_secprops != NULL ) {
269                                 fprintf( stderr, "%s: -O previously specified\n", prog );
270                                 exit( EXIT_FAILURE );
271                         }
272                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
273                                 fprintf( stderr, "%s: incompatible previous "
274                                                  "authentication choice\n", prog );
275                                 exit( EXIT_FAILURE );
276                         }
277                         authmethod = LDAP_AUTH_SASL;
278                         sasl_secprops = ber_strdup( optarg );
279 #else
280                         fprintf( stderr, "%s: not compiled with SASL support\n",
281                                          prog );
282                         exit( EXIT_FAILURE );
283 #endif
284                         break;
285                 case 'p':
286                         if( ldapport ) {
287                                 fprintf( stderr, "%s: -p previously specified\n", prog );
288                                 exit( EXIT_FAILURE );
289                         }
290                         ldapport = atoi( optarg );
291                         break;
292                 case 'P':
293                         switch( atoi(optarg) ) {
294                         case 2:
295                                 if( version == LDAP_VERSION3 ) {
296                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
297                                                          prog, version );
298                                         exit( EXIT_FAILURE );
299                                 }
300                                 version = LDAP_VERSION2;
301                                 break;
302                         case 3:
303                                 if( version == LDAP_VERSION2 ) {
304                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
305                                                          prog, version );
306                                         exit( EXIT_FAILURE );
307                                 }
308                                 version = LDAP_VERSION3;
309                                 break;
310                         default:
311                                 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
312                                                  prog );
313                                 usage();
314                         }
315                         break;
316                 case 'Q':
317 #ifdef HAVE_CYRUS_SASL
318                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
319                                 fprintf( stderr, "%s: incompatible previous "
320                                                  "authentication choice\n",
321                                                  prog );
322                                 exit( EXIT_FAILURE );
323                         }
324                         authmethod = LDAP_AUTH_SASL;
325                         sasl_flags = LDAP_SASL_QUIET;
326                         break;
327 #else
328                         fprintf( stderr, "%s: not compiled with SASL support\n",
329                                          prog );
330                         exit( EXIT_FAILURE );
331 #endif
332                 case 'R':
333 #ifdef HAVE_CYRUS_SASL
334                         if( sasl_realm != NULL ) {
335                                 fprintf( stderr, "%s: -R previously specified\n", prog );
336                                 exit( EXIT_FAILURE );
337                         }
338                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
339                                 fprintf( stderr, "%s: incompatible previous "
340                                                  "authentication choice\n",
341                                                  prog );
342                                 exit( EXIT_FAILURE );
343                         }
344                         authmethod = LDAP_AUTH_SASL;
345                         sasl_realm = ber_strdup( optarg );
346 #else
347                         fprintf( stderr, "%s: not compiled with SASL support\n",
348                                          prog );
349                         exit( EXIT_FAILURE );
350 #endif
351                         break;
352                 case 'U':
353 #ifdef HAVE_CYRUS_SASL
354                         if( sasl_authc_id != NULL ) {
355                                 fprintf( stderr, "%s: -U previously specified\n", prog );
356                                 exit( EXIT_FAILURE );
357                         }
358                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
359                                 fprintf( stderr, "%s: incompatible previous "
360                                                  "authentication choice\n",
361                                                  prog );
362                                 exit( EXIT_FAILURE );
363                         }
364                         authmethod = LDAP_AUTH_SASL;
365                         sasl_authc_id = ber_strdup( optarg );
366 #else
367                         fprintf( stderr, "%s: not compiled with SASL support\n",
368                                          prog );
369                         exit( EXIT_FAILURE );
370 #endif
371                         break;
372                 case 'v':       /* verbose mode */
373                         verbose = 1;
374                         break;
375                 case 'w':       /* password */
376                         passwd.bv_val = ber_strdup( optarg );
377                         {
378                                 char* p;
379
380                                 for( p = optarg; *p != '\0'; p++ ) {
381                                         *p = '\0';
382                                 }
383                         }
384                         passwd.bv_len = strlen( passwd.bv_val );
385                         break;
386                 case 'W':
387                         want_bindpw = 1;
388                         break;
389                 case 'y':
390                         pw_file = optarg;
391                         break;
392                 case 'Y':
393 #ifdef HAVE_CYRUS_SASL
394                         if( sasl_mech != NULL ) {
395                                 fprintf( stderr, "%s: -Y previously specified\n", prog );
396                                 exit( EXIT_FAILURE );
397                         }
398                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
399                                 fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
400                                 exit( EXIT_FAILURE );
401                         }
402                         authmethod = LDAP_AUTH_SASL;
403                         sasl_mech = ber_strdup( optarg );
404 #else
405                         fprintf( stderr, "%s: not compiled with SASL support\n",
406                                          prog );
407                         exit( EXIT_FAILURE );
408 #endif
409                         break;
410                 case 'x':
411                         if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
412                                 fprintf( stderr, "%s: incompatible with previous "
413                                                  "authentication choice\n", prog );
414                                 exit( EXIT_FAILURE );
415                         }
416                         authmethod = LDAP_AUTH_SIMPLE;
417                         break;
418                 case 'X':
419 #ifdef HAVE_CYRUS_SASL
420                         if( sasl_authz_id != NULL ) {
421                                 fprintf( stderr, "%s: -X previously specified\n", prog );
422                                 exit( EXIT_FAILURE );
423                         }
424                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
425                                 fprintf( stderr, "%s: -X incompatible with "
426                                                  "authentication choice\n", prog );
427                                 exit( EXIT_FAILURE );
428                         }
429                         authmethod = LDAP_AUTH_SASL;
430                         sasl_authz_id = ber_strdup( optarg );
431 #else
432                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
433                         exit( EXIT_FAILURE );
434 #endif
435                         break;
436                 case 'Z':
437 #ifdef HAVE_TLS
438                         use_tls = 1;
439 #else
440                         fprintf( stderr, "%s: not compiled with TLS support\n", prog );
441                         exit( EXIT_FAILURE );
442 #endif
443                         break;
444                 default:
445                         if( handle_private_option( i ) )
446                                 break;
447                         fprintf( stderr, "%s: unrecognized option -%c\n",
448                                          prog, optopt );
449                         usage();
450                 }
451     }
452
453         if (version == -1)
454                 version = LDAP_VERSION3;
455
456         if (authmethod == -1 && version > LDAP_VERSION2) {
457 #ifdef HAVE_CYRUS_SASL
458                 authmethod = LDAP_AUTH_SASL;
459 #else
460                 authmethod = LDAP_AUTH_SIMPLE;
461 #endif
462         }
463
464         if( ldapuri != NULL ) {
465                 if( ldaphost != NULL ) {
466                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
467                         exit( EXIT_FAILURE );
468                 }
469                 if( ldapport ) {
470                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
471                         exit( EXIT_FAILURE );
472                 }
473         }
474         if( version == LDAP_VERSION2 ) {
475                 if( authzid || manageDSAit || noop ) {
476                         fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
477                         exit( EXIT_FAILURE );
478                 }
479 #ifdef HAVE_TLS
480                 if( use_tls ) {
481                         fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
482                         exit( EXIT_FAILURE );
483                 }
484 #endif
485 #ifdef HAVE_CYRUS_SASL
486                 if( authmethod == LDAP_AUTH_SASL ) {
487                         fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
488                                  prog );
489                         exit( EXIT_FAILURE );
490                 }
491 #endif
492         } else {
493 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
494                 if ( authmethod = LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
495                         fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
496                                  prog, version );
497                         exit( EXIT_FAILURE );
498                 }
499 #endif
500         }
501 }
502
503
504 LDAP *
505 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
506 {
507         LDAP *ld = NULL;
508
509         if ( debug ) {
510                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
511                     != LBER_OPT_SUCCESS ) {
512                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
513                 }
514                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
515                     != LDAP_OPT_SUCCESS ) {
516                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
517                 }
518         }
519
520 #ifdef SIGPIPE
521         (void) SIGNAL( SIGPIPE, SIG_IGN );
522 #endif
523
524         if ( !not ) {
525                 /* connect to server */
526                 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
527                         if ( verbose ) {
528                                 fprintf( stderr, "ldap_init( %s, %d )\n",
529                                          ldaphost != NULL ? ldaphost : "<DEFAULT>",
530                                          ldapport );
531                         }
532
533                         ld = ldap_init( ldaphost, ldapport );
534                         if( ld == NULL ) {
535                                 char buf[20 + sizeof(": ldap_init")];
536                                 sprintf( buf, "%.20s: ldap_init", prog );
537                                 perror( buf );
538                                 exit( EXIT_FAILURE );
539                         }
540
541                 } else {
542                         int rc;
543                         if ( verbose ) {
544                                 fprintf( stderr, "ldap_initialize( %s )\n",
545                                          ldapuri != NULL ? ldapuri : "<DEFAULT>" );
546                         }
547                         rc = ldap_initialize( &ld, ldapuri );
548                         if( rc != LDAP_SUCCESS ) {
549                                 fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
550                                          rc, ldap_err2string(rc) );
551                                 exit( EXIT_FAILURE );
552                         }
553                 }
554
555                 if( private_setup )
556                         private_setup( ld );
557
558                 /* referrals */
559                 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
560                                          referrals ? LDAP_OPT_ON : LDAP_OPT_OFF )
561                         != LDAP_OPT_SUCCESS )
562                 {
563                         fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
564                                  referrals ? "on" : "off" );
565                         exit( EXIT_FAILURE );
566                 }
567
568                 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
569                     != LDAP_OPT_SUCCESS )
570                 {
571                         fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
572                                  version );
573                         exit( EXIT_FAILURE );
574                 }
575
576                 if ( use_tls &&
577                      ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
578                         ldap_perror( ld, "ldap_start_tls" );
579                         if ( use_tls > 1 ) {
580                                 exit( EXIT_FAILURE );
581                         }
582                 }
583         }
584
585         return ld;
586 }
587
588
589 void
590 tool_bind( LDAP *ld )
591 {
592         if ( authmethod == LDAP_AUTH_SASL ) {
593 #ifdef HAVE_CYRUS_SASL
594                 void *defaults;
595                 int rc;
596
597                 if( sasl_secprops != NULL ) {
598                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
599                                 (void *) sasl_secprops );
600
601                         if( rc != LDAP_OPT_SUCCESS ) {
602                                 fprintf( stderr,
603                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
604                                         sasl_secprops );
605                                 exit( EXIT_FAILURE );
606                         }
607                 }
608
609                 defaults = lutil_sasl_defaults( ld,
610                         sasl_mech,
611                         sasl_realm,
612                         sasl_authc_id,
613                         passwd.bv_val,
614                         sasl_authz_id );
615
616                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
617                         sasl_mech, NULL, NULL,
618                         sasl_flags, lutil_sasl_interact, defaults );
619
620                 if( rc != LDAP_SUCCESS ) {
621                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
622                         exit( EXIT_FAILURE );
623                 }
624 #else
625                 fprintf( stderr, "%s: not compiled with SASL support\n",
626                         prog );
627                 exit( EXIT_FAILURE );
628 #endif
629         } else {
630                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
631                      != LDAP_SUCCESS ) {
632                         ldap_perror( ld, "ldap_bind" );
633                         exit( EXIT_FAILURE );
634                 }
635         }
636 }
637
638
639 /* Set server controls.  Add controls extra_c[0..count-1], if set. */
640 void
641 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
642 {
643         int i = 0, j, crit = 0, err;
644         LDAPControl c[3], **ctrls;
645
646         ctrls = (LDAPControl **)malloc( sizeof(c) + (count + 1)*sizeof(LDAPControl *) );
647         if ( ctrls == NULL ) {
648                 fprintf( stderr, "No memory\n" );
649                 exit( EXIT_FAILURE );
650         }
651
652         if ( authzid ) {
653                 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
654                 c[i].ldctl_value.bv_val = authzid;
655                 c[i].ldctl_value.bv_len = strlen( authzid );
656                 c[i].ldctl_iscritical = 1;
657                 ctrls[i] = &c[i];
658                 i++;
659         }
660
661         if ( manageDSAit ) {
662                 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
663                 c[i].ldctl_value.bv_val = NULL;
664                 c[i].ldctl_value.bv_len = 0;
665                 c[i].ldctl_iscritical = manageDSAit > 1;
666                 ctrls[i] = &c[i];
667                 i++;
668         }
669
670         if ( noop ) {
671                 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
672                 c[i].ldctl_value.bv_val = NULL;
673                 c[i].ldctl_value.bv_len = 0;
674                 c[i].ldctl_iscritical = noop > 1;
675                 ctrls[i] = &c[i];
676                 i++;
677         }
678         
679         while ( count-- )
680                 ctrls[i++] = extra_c++;
681         ctrls[i] = NULL;
682
683         err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
684
685         if ( err != LDAP_OPT_SUCCESS ) {
686                 for ( j = 0; j < i; j++ )
687                         if ( ctrls[j]->ldctl_iscritical )
688                                 crit = 1;
689                 fprintf( stderr, "Could not set %scontrols\n",
690                                  crit ? "critical " : "" );
691         }
692
693         free( ctrls );
694         if ( crit ) {
695                 exit( EXIT_FAILURE );
696         }
697 }