1 /* common.c - common routines for the ldap client tools */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
6 * Portions Copyright 2003 Kurt D. Zeilenga.
7 * Portions Copyright 2003 IBM Corporation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
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>.
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)
29 #include <ac/stdlib.h>
30 #include <ac/signal.h>
31 #include <ac/string.h>
32 #include <ac/unistd.h>
37 #include "lutil_ldap.h"
38 #include "ldap_defaults.h"
51 char *ldaphost = NULL;
53 #ifdef HAVE_CYRUS_SASL
54 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
55 char *sasl_realm = NULL;
56 char *sasl_authc_id = NULL;
57 char *sasl_authz_id = NULL;
58 char *sasl_mech = NULL;
59 char *sasl_secprops = NULL;
64 char *assertion = NULL;
69 char *preread_attrs = NULL;
71 char *postread_attrs = NULL;
75 struct berval passwd = { 0, NULL };
88 ldap_pvt_setlocale(LC_MESSAGES, "");
89 ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE, LDAP_LOCALEDIR);
90 ldap_pvt_textdomain(OPENLDAP_PACKAGE);
94 tool_common_usage( void )
96 static const char *const descriptions[] = {
97 N_(" -c continuous operation mode (do not stop on errors)\n"),
98 N_(" -C chase referrals (anonymously)\n"),
99 N_(" -d level set LDAP debugging level to `level'\n"),
100 N_(" -D binddn bind DN\n"),
101 N_(" -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
102 N_(" [!]assert=<filter> (an RFC 2254 Filter)\n")
103 N_(" [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n")
104 N_(" [!]manageDSAit\n")
106 N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n")
107 N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n"),
108 N_(" -f file read operations from `file'\n"),
109 N_(" -h host LDAP server\n"),
110 N_(" -H URI LDAP Uniform Resource Indentifier(s)\n"),
111 N_(" -I use SASL Interactive mode\n"),
112 N_(" -k use Kerberos authentication\n"),
113 N_(" -K like -k, but do only step 1 of the Kerberos bind\n"),
114 N_(" -M enable Manage DSA IT control (-MM to make critical)\n"),
115 N_(" -n show what would be done but don't actually do it\n"),
116 N_(" -O props SASL security properties\n"),
117 N_(" -p port port on LDAP server\n"),
118 N_(" -P version procotol version (default: 3)\n"),
119 N_(" -Q use SASL Quiet mode\n"),
120 N_(" -R realm SASL realm\n"),
121 N_(" -U authcid SASL authentication identity\n"),
122 N_(" -v run in verbose mode (diagnostics to standard output)\n"),
123 N_(" -V print version info (-VV only)\n"),
124 N_(" -w passwd bind password (for simple authentication)\n"),
125 N_(" -W prompt for bind password\n"),
126 N_(" -x Simple authentication\n"),
127 N_(" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
128 N_(" -y file Read password from file\n"),
129 N_(" -Y mech SASL mechanism\n"),
130 N_(" -Z Start TLS request (-ZZ to require successful response)\n"),
133 const char *const *cpp;
135 fputs( _("Common options:\n"), stderr );
136 for( cpp = descriptions; *cpp != NULL; cpp++ ) {
137 if( strchr( options, (*cpp)[3] ) ) {
138 fputs( _(*cpp), stderr );
145 tool_args( int argc, char **argv )
149 while (( i = getopt( argc, argv, options )) != EOF ) {
151 char *control, *cvalue, *next;
153 case 'c': /* continuous operation mode */
160 ival = strtol( optarg, &next, 10 );
161 if (next == NULL || next[0] != '\0') {
162 fprintf( stderr, "%s: unable to parse debug value \"%s\"\n", prog, optarg);
167 case 'D': /* bind DN */
168 if( binddn != NULL ) {
169 fprintf( stderr, "%s: -D previously specified\n", prog );
170 exit( EXIT_FAILURE );
172 binddn = ber_strdup( optarg );
174 case 'e': /* general extensions (controls and such) */
175 /* should be extended to support comma separated list of
176 * [!]key[=value] parameters, e.g. -e !foo,bar=567
181 if( optarg[0] == '!' ) {
186 control = ber_strdup( optarg );
187 if ( (cvalue = strchr( control, '=' )) != NULL ) {
191 if ( strcasecmp( control, "assert" ) == 0 ) {
193 fprintf( stderr, "assert control previously specified\n");
194 exit( EXIT_FAILURE );
196 if( cvalue == NULL ) {
197 fprintf( stderr, "assert: control value expected\n" );
201 assertctl = 1 + crit;
203 assert( assertion == NULL );
206 } else if ( strcasecmp( control, "authzid" ) == 0 ) {
207 if( authzid != NULL ) {
208 fprintf( stderr, "authzid control previously specified\n");
209 exit( EXIT_FAILURE );
211 if( cvalue == NULL ) {
212 fprintf( stderr, "authzid: control value expected\n" );
216 fprintf( stderr, "authzid: must be marked critical\n" );
220 assert( authzid == NULL );
223 } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
226 "manageDSAit control previously specified\n");
227 exit( EXIT_FAILURE );
229 if( cvalue != NULL ) {
231 "manageDSAit: no control value expected\n" );
235 manageDSAit = 1 + crit;
237 } else if ( strcasecmp( control, "noop" ) == 0 ) {
239 fprintf( stderr, "noop control previously specified\n");
240 exit( EXIT_FAILURE );
242 if( cvalue != NULL ) {
243 fprintf( stderr, "noop: no control value expected\n" );
249 } else if ( strcasecmp( control, "preread" ) == 0 ) {
251 fprintf( stderr, "preread control previously specified\n");
252 exit( EXIT_FAILURE );
256 preread_attrs = cvalue;
258 } else if ( strcasecmp( control, "postread" ) == 0 ) {
260 fprintf( stderr, "postread control previously specified\n");
261 exit( EXIT_FAILURE );
265 postread_attrs = cvalue;
268 fprintf( stderr, "Invalid general control name: %s\n",
273 case 'f': /* read from file */
274 if( infile != NULL ) {
275 fprintf( stderr, "%s: -f previously specified\n", prog );
276 exit( EXIT_FAILURE );
278 infile = ber_strdup( optarg );
280 case 'h': /* ldap host */
281 if( ldaphost != NULL ) {
282 fprintf( stderr, "%s: -h previously specified\n", prog );
283 exit( EXIT_FAILURE );
285 ldaphost = ber_strdup( optarg );
287 case 'H': /* ldap URI */
288 if( ldapuri != NULL ) {
289 fprintf( stderr, "%s: -H previously specified\n", prog );
290 exit( EXIT_FAILURE );
292 ldapuri = ber_strdup( optarg );
295 #ifdef HAVE_CYRUS_SASL
296 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
297 fprintf( stderr, "%s: incompatible previous "
298 "authentication choice\n",
300 exit( EXIT_FAILURE );
302 authmethod = LDAP_AUTH_SASL;
303 sasl_flags = LDAP_SASL_INTERACTIVE;
306 fprintf( stderr, "%s: was not compiled with SASL support\n",
308 exit( EXIT_FAILURE );
310 case 'k': /* kerberos bind */
311 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
312 if( authmethod != -1 ) {
313 fprintf( stderr, "%s: -k incompatible with previous "
314 "authentication choice\n", prog );
315 exit( EXIT_FAILURE );
317 authmethod = LDAP_AUTH_KRBV4;
319 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
320 exit( EXIT_FAILURE );
323 case 'K': /* kerberos bind, part one only */
324 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
325 if( authmethod != -1 ) {
326 fprintf( stderr, "%s: incompatible with previous "
327 "authentication choice\n", prog );
328 exit( EXIT_FAILURE );
330 authmethod = LDAP_AUTH_KRBV41;
332 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
333 exit( EXIT_FAILURE );
337 /* enable Manage DSA IT */
340 case 'n': /* print operations, don't actually do them */
344 #ifdef HAVE_CYRUS_SASL
345 if( sasl_secprops != NULL ) {
346 fprintf( stderr, "%s: -O previously specified\n", prog );
347 exit( EXIT_FAILURE );
349 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
350 fprintf( stderr, "%s: incompatible previous "
351 "authentication choice\n", prog );
352 exit( EXIT_FAILURE );
354 authmethod = LDAP_AUTH_SASL;
355 sasl_secprops = ber_strdup( optarg );
357 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
358 exit( EXIT_FAILURE );
363 fprintf( stderr, "%s: -p previously specified\n", prog );
364 exit( EXIT_FAILURE );
366 ival = strtol( optarg, &next, 10 );
367 if ( next == NULL || next[0] != '\0' ) {
368 fprintf( stderr, "%s: unable to parse port number \"%s\"\n", prog, optarg );
369 exit( EXIT_FAILURE );
374 ival = strtol( optarg, &next, 10 );
375 if ( next == NULL || next[0] != '\0' ) {
376 fprintf( stderr, "%s: unabel to parse protocol version \"%s\"\n", prog, optarg );
377 exit( EXIT_FAILURE );
381 if( protocol == LDAP_VERSION3 ) {
382 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
384 exit( EXIT_FAILURE );
386 protocol = LDAP_VERSION2;
389 if( protocol == LDAP_VERSION2 ) {
390 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
392 exit( EXIT_FAILURE );
394 protocol = LDAP_VERSION3;
397 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
403 #ifdef HAVE_CYRUS_SASL
404 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
405 fprintf( stderr, "%s: incompatible previous "
406 "authentication choice\n",
408 exit( EXIT_FAILURE );
410 authmethod = LDAP_AUTH_SASL;
411 sasl_flags = LDAP_SASL_QUIET;
414 fprintf( stderr, "%s: not compiled with SASL support\n",
416 exit( EXIT_FAILURE );
419 #ifdef HAVE_CYRUS_SASL
420 if( sasl_realm != NULL ) {
421 fprintf( stderr, "%s: -R previously specified\n", prog );
422 exit( EXIT_FAILURE );
424 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
425 fprintf( stderr, "%s: incompatible previous "
426 "authentication choice\n",
428 exit( EXIT_FAILURE );
430 authmethod = LDAP_AUTH_SASL;
431 sasl_realm = ber_strdup( optarg );
433 fprintf( stderr, "%s: not compiled with SASL support\n",
435 exit( EXIT_FAILURE );
439 #ifdef HAVE_CYRUS_SASL
440 if( sasl_authc_id != NULL ) {
441 fprintf( stderr, "%s: -U previously specified\n", prog );
442 exit( EXIT_FAILURE );
444 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
445 fprintf( stderr, "%s: incompatible previous "
446 "authentication choice\n",
448 exit( EXIT_FAILURE );
450 authmethod = LDAP_AUTH_SASL;
451 sasl_authc_id = ber_strdup( optarg );
453 fprintf( stderr, "%s: not compiled with SASL support\n",
455 exit( EXIT_FAILURE );
458 case 'v': /* verbose mode */
461 case 'V': /* version */
464 case 'w': /* password */
465 passwd.bv_val = ber_strdup( optarg );
469 for( p = optarg; *p != '\0'; p++ ) {
473 passwd.bv_len = strlen( passwd.bv_val );
482 #ifdef HAVE_CYRUS_SASL
483 if( sasl_mech != NULL ) {
484 fprintf( stderr, "%s: -Y previously specified\n", prog );
485 exit( EXIT_FAILURE );
487 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
489 "%s: incompatible with authentication choice\n", prog );
490 exit( EXIT_FAILURE );
492 authmethod = LDAP_AUTH_SASL;
493 sasl_mech = ber_strdup( optarg );
495 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
496 exit( EXIT_FAILURE );
500 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
501 fprintf( stderr, "%s: incompatible with previous "
502 "authentication choice\n", prog );
503 exit( EXIT_FAILURE );
505 authmethod = LDAP_AUTH_SIMPLE;
508 #ifdef HAVE_CYRUS_SASL
509 if( sasl_authz_id != NULL ) {
510 fprintf( stderr, "%s: -X previously specified\n", prog );
511 exit( EXIT_FAILURE );
513 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
514 fprintf( stderr, "%s: -X incompatible with "
515 "authentication choice\n", prog );
516 exit( EXIT_FAILURE );
518 authmethod = LDAP_AUTH_SASL;
519 sasl_authz_id = ber_strdup( optarg );
521 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
522 exit( EXIT_FAILURE );
529 fprintf( stderr, "%s: not compiled with TLS support\n", prog );
530 exit( EXIT_FAILURE );
534 if( handle_private_option( i ) ) break;
535 fprintf( stderr, "%s: unrecognized option -%c\n",
542 /* prevent bad linking */
544 api.ldapai_info_version = LDAP_API_INFO_VERSION;
546 if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
547 != LDAP_OPT_SUCCESS )
549 fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
550 exit( EXIT_FAILURE );
553 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
554 fprintf( stderr, "LDAP APIInfo version mismatch: "
555 "got %d, expected %d\n",
556 api.ldapai_info_version, LDAP_API_INFO_VERSION );
557 exit( EXIT_FAILURE );
560 if( api.ldapai_api_version != LDAP_API_VERSION ) {
561 fprintf( stderr, "LDAP API version mismatch: "
562 "got %d, expected %d\n",
563 api.ldapai_api_version, LDAP_API_VERSION );
564 exit( EXIT_FAILURE );
567 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
568 fprintf( stderr, "LDAP vendor name mismatch: "
569 "got %s, expected %s\n",
570 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
571 exit( EXIT_FAILURE );
574 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
575 fprintf( stderr, "LDAP vendor version mismatch: "
576 "got %d, expected %d\n",
577 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
578 exit( EXIT_FAILURE );
582 fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
584 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
585 if (version > 1) exit( EXIT_SUCCESS );
590 protocol = LDAP_VERSION3;
592 if (authmethod == -1 && protocol > LDAP_VERSION2) {
593 #ifdef HAVE_CYRUS_SASL
594 authmethod = LDAP_AUTH_SASL;
596 authmethod = LDAP_AUTH_SIMPLE;
600 if( ldapuri == NULL ) {
601 if( ldapport && ( ldaphost == NULL )) {
602 fprintf( stderr, "%s: -p without -h is invalid.\n", prog );
603 exit( EXIT_FAILURE );
606 if( ldaphost != NULL ) {
607 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
608 exit( EXIT_FAILURE );
611 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
612 exit( EXIT_FAILURE );
615 if( protocol == LDAP_VERSION2 ) {
616 if( authzid || manageDSAit || noop ) {
617 fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
618 exit( EXIT_FAILURE );
622 fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
623 exit( EXIT_FAILURE );
626 #ifdef HAVE_CYRUS_SASL
627 if( authmethod == LDAP_AUTH_SASL ) {
628 fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
630 exit( EXIT_FAILURE );
634 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
635 if ( authmethod == LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
636 fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
638 exit( EXIT_FAILURE );
646 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
651 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
652 != LBER_OPT_SUCCESS )
654 fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
656 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
657 != LDAP_OPT_SUCCESS )
659 fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
664 (void) SIGNAL( SIGPIPE, SIG_IGN );
670 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
673 memset( &url, 0, sizeof(url));
675 url.lud_scheme = "ldap";
676 url.lud_host = ldaphost;
677 url.lud_port = ldapport;
678 url.lud_scope = LDAP_SCOPE_DEFAULT;
680 ldapuri = ldap_url_desc2str( &url );
684 fprintf( stderr, "ldap_initialize( %s )\n",
685 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
687 rc = ldap_initialize( &ld, ldapuri );
688 if( rc != LDAP_SUCCESS ) {
690 "Could not create LDAP session handle (%d): %s\n",
691 rc, ldap_err2string(rc) );
692 exit( EXIT_FAILURE );
695 if( private_setup ) private_setup( ld );
698 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
699 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
701 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
702 referrals ? "on" : "off" );
703 exit( EXIT_FAILURE );
706 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
707 != LDAP_OPT_SUCCESS )
709 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
711 exit( EXIT_FAILURE );
715 ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ))
717 ldap_perror( ld, "ldap_start_tls" );
719 exit( EXIT_FAILURE );
729 tool_bind( LDAP *ld )
731 if ( authmethod == LDAP_AUTH_SASL ) {
732 #ifdef HAVE_CYRUS_SASL
736 if( sasl_secprops != NULL ) {
737 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
738 (void *) sasl_secprops );
740 if( rc != LDAP_OPT_SUCCESS ) {
742 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
744 exit( EXIT_FAILURE );
748 defaults = lutil_sasl_defaults( ld,
755 rc = ldap_sasl_interactive_bind_s( ld, binddn,
756 sasl_mech, NULL, NULL,
757 sasl_flags, lutil_sasl_interact, defaults );
759 lutil_sasl_freedefs( defaults );
760 if( rc != LDAP_SUCCESS ) {
761 ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
762 exit( EXIT_FAILURE );
765 fprintf( stderr, "%s: not compiled with SASL support\n",
767 exit( EXIT_FAILURE );
770 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
773 ldap_perror( ld, "ldap_bind" );
774 exit( EXIT_FAILURE );
780 /* Set server controls. Add controls extra_c[0..count-1], if set. */
782 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
784 int i = 0, j, crit = 0, err;
785 LDAPControl c[6], **ctrls;
787 ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
788 if ( ctrls == NULL ) {
789 fprintf( stderr, "No memory\n" );
790 exit( EXIT_FAILURE );
794 BerElementBuffer berbuf;
795 BerElement *ber = (BerElement *)&berbuf;
797 if( assertion == NULL || *assertion == '\0' ) {
798 fprintf( stderr, "Assertion=<empty>\n" );
799 exit( EXIT_FAILURE );
802 ber_init2( ber, NULL, LBER_USE_DER );
804 err = ldap_pvt_put_filter( ber, assertion );
806 fprintf( stderr, "assertion encode failed (%d)\n", err );
807 exit( EXIT_FAILURE );
810 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
812 fprintf( stderr, "assertion flatten failed (%d)\n", err );
813 exit( EXIT_FAILURE );
816 c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
817 c[i].ldctl_iscritical = assertctl > 1;
823 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
824 c[i].ldctl_value.bv_val = authzid;
825 c[i].ldctl_value.bv_len = strlen( authzid );
826 c[i].ldctl_iscritical = 1;
832 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
833 c[i].ldctl_value.bv_val = NULL;
834 c[i].ldctl_value.bv_len = 0;
835 c[i].ldctl_iscritical = manageDSAit > 1;
841 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
842 c[i].ldctl_value.bv_val = NULL;
843 c[i].ldctl_value.bv_len = 0;
844 c[i].ldctl_iscritical = noop > 1;
850 char berbuf[LBER_ELEMENT_SIZEOF];
851 BerElement *ber = (BerElement *)berbuf;
854 if( preread_attrs ) {
855 attrs = ldap_str2charray( preread_attrs, "," );
858 ber_init2( ber, NULL, LBER_USE_DER );
860 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
861 fprintf( stderr, "preread attrs encode failed.\n" );
862 exit( EXIT_FAILURE );
865 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
867 fprintf( stderr, "preread flatten failed (%d)\n", err );
868 exit( EXIT_FAILURE );
871 c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
872 c[i].ldctl_iscritical = preread > 1;
876 if( attrs ) ldap_charray_free( attrs );
880 char berbuf[LBER_ELEMENT_SIZEOF];
881 BerElement *ber = (BerElement *)berbuf;
884 if( postread_attrs ) {
885 attrs = ldap_str2charray( postread_attrs, "," );
888 ber_init2( ber, NULL, LBER_USE_DER );
890 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
891 fprintf( stderr, "postread attrs encode failed.\n" );
892 exit( EXIT_FAILURE );
895 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
897 fprintf( stderr, "postread flatten failed (%d)\n", err );
898 exit( EXIT_FAILURE );
901 c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
902 c[i].ldctl_iscritical = postread > 1;
906 if( attrs ) ldap_charray_free( attrs );
910 ctrls[i++] = extra_c++;
914 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
916 if ( err != LDAP_OPT_SUCCESS ) {
917 for ( j = 0; j < i; j++ ) {
918 if ( ctrls[j]->ldctl_iscritical ) crit = 1;
920 fprintf( stderr, "Could not set %scontrols\n",
921 crit ? "critical " : "" );
926 exit( EXIT_FAILURE );