1 /* common.c - common routines for the ldap client tools */
2 /* $OpenLDAP: pkg/ldap/clients/tools/common.c,v 1.78.2.8 2008/07/09 00:29:57 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 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>
33 #include <ac/unistd.h>
36 #include <ac/socket.h>
38 #ifdef HAVE_CYRUS_SASL
39 #ifdef HAVE_SASL_SASL_H
40 #include <sasl/sasl.h>
50 #include "lutil_ldap.h"
51 #include "ldap_defaults.h"
57 /* input-related vars */
59 /* misc. parameters */
60 tool_type_t tool_type
;
72 char *ldaphost
= NULL
;
82 struct berval passwd
= { 0, NULL
};
84 #ifdef HAVE_CYRUS_SASL
85 unsigned sasl_flags
= LDAP_SASL_AUTOMATIC
;
86 char *sasl_realm
= NULL
;
87 char *sasl_authc_id
= NULL
;
88 char *sasl_authz_id
= NULL
;
89 char *sasl_mech
= NULL
;
90 char *sasl_secprops
= NULL
;
95 char *assertion
= NULL
;
96 struct berval assertionvalue
= BER_BVNULL
;
98 /* support deprecated early version of proxyAuthz */
99 #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12"
100 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
101 char *proxydn
= NULL
;
102 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
108 static char *preread_attrs
= NULL
;
110 static char *postread_attrs
= NULL
;
111 ber_int_t pr_morePagedResults
= 1;
112 struct berval pr_cookie
= { 0, NULL
};
113 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
115 static int chainingResolve
= -1;
116 static int chainingContinuation
= -1;
117 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
118 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
119 static int sessionTracking
= 0;
120 struct berval stValue
;
121 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
123 LDAPControl
*unknown_ctrls
= NULL
;
124 int unknown_ctrls_num
= 0;
127 struct timeval nettimeout
= { -1 , 0 };
129 typedef int (*print_ctrl_fn
)( LDAP
*ld
, LDAPControl
*ctrl
);
131 static int print_preread( LDAP
*ld
, LDAPControl
*ctrl
);
132 static int print_postread( LDAP
*ld
, LDAPControl
*ctrl
);
133 static int print_paged_results( LDAP
*ld
, LDAPControl
*ctrl
);
134 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
135 static int print_ppolicy( LDAP
*ld
, LDAPControl
*ctrl
);
138 static struct tool_ctrls_t
{
142 } tool_ctrl_response
[] = {
143 { LDAP_CONTROL_PRE_READ
, TOOL_ALL
, print_preread
},
144 { LDAP_CONTROL_POST_READ
, TOOL_ALL
, print_postread
},
145 { LDAP_CONTROL_PAGEDRESULTS
, TOOL_SEARCH
, print_paged_results
},
146 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
147 { LDAP_CONTROL_PASSWORDPOLICYRESPONSE
, TOOL_ALL
, print_ppolicy
},
153 enum { Intr_None
= 0, Intr_Abandon
, Intr_Cancel
, Intr_Ignore
};
154 static volatile sig_atomic_t gotintr
, abcan
;
157 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
159 st_value( LDAP
*ld
, struct berval
*value
)
161 char *ip
= NULL
, *name
= NULL
;
162 struct berval id
= { 0 };
163 char namebuf
[ MAXHOSTNAMELEN
];
165 if ( gethostname( namebuf
, sizeof( namebuf
) ) == 0 ) {
171 h
= gethostbyname( name
);
173 AC_MEMCPY( &addr
, h
->h_addr
, sizeof( addr
) );
174 ip
= inet_ntoa( addr
);
178 #ifdef HAVE_CYRUS_SASL
179 if ( sasl_authz_id
!= NULL
) {
180 ber_str2bv( sasl_authz_id
, 0, 0, &id
);
182 } else if ( sasl_authc_id
!= NULL
) {
183 ber_str2bv( sasl_authc_id
, 0, 0, &id
);
186 #endif /* HAVE_CYRUS_SASL */
187 if ( binddn
!= NULL
) {
188 ber_str2bv( binddn
, 0, 0, &id
);
191 if ( ldap_create_session_tracking_value( ld
,
192 ip
, name
, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME
,
195 fprintf( stderr
, _("Session tracking control encoding error!\n") );
201 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
210 tool_init( tool_type_t type
)
213 ldap_pvt_setlocale(LC_MESSAGES
, "");
214 ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE
, LDAP_LOCALEDIR
);
215 ldap_pvt_textdomain(OPENLDAP_PACKAGE
);
221 #ifdef HAVE_CYRUS_SASL
225 ldap_pvt_tls_destroy();
228 if ( ldapuri
!= NULL
) {
229 ber_memfree( ldapuri
);
233 if ( pr_cookie
.bv_val
!= NULL
) {
234 ber_memfree( pr_cookie
.bv_val
);
235 pr_cookie
.bv_val
= NULL
;
236 pr_cookie
.bv_len
= 0;
241 tool_common_usage( void )
243 static const char *const descriptions
[] = {
244 N_(" -c continuous operation mode (do not stop on errors)\n"),
245 N_(" -d level set LDAP debugging level to `level'\n"),
246 N_(" -D binddn bind DN\n"),
247 N_(" -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
248 N_(" [!]assert=<filter> (a RFC 4515 Filter string)\n")
249 N_(" [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n")
250 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
252 /* non-advertized support for proxyDN */
253 N_(" [!]proxydn=<dn> (a RFC 4514 DN string)\n")
256 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
257 N_(" [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
258 N_(" one of \"chainingPreferred\", \"chainingRequired\",\n")
259 N_(" \"referralsPreferred\", \"referralsRequired\"\n")
260 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
261 N_(" [!]manageDSAit\n")
263 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
266 N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n")
267 N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n")
269 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
270 N_(" [!]sessiontracking\n")
271 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
272 N_(" abandon, cancel, ignore (SIGINT sends abandon/cancel,\n"
273 " or ignores response; if critical, doesn't wait for SIGINT.\n"
274 " not really controls)\n")
275 N_(" -f file read operations from `file'\n"),
276 N_(" -h host LDAP server\n"),
277 N_(" -H URI LDAP Uniform Resource Identifier(s)\n"),
278 N_(" -I use SASL Interactive mode\n"),
279 N_(" -M enable Manage DSA IT control (-MM to make critical)\n"),
280 N_(" -n show what would be done but don't actually do it\n"),
281 N_(" -O props SASL security properties\n"),
282 N_(" -o <opt>[=<optparam] general options\n"),
283 N_(" nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"),
284 N_(" -p port port on LDAP server\n"),
285 N_(" -P version protocol version (default: 3)\n"),
286 N_(" -Q use SASL Quiet mode\n"),
287 N_(" -R realm SASL realm\n"),
288 N_(" -U authcid SASL authentication identity\n"),
289 N_(" -v run in verbose mode (diagnostics to standard output)\n"),
290 N_(" -V print version info (-VV only)\n"),
291 N_(" -w passwd bind password (for simple authentication)\n"),
292 N_(" -W prompt for bind password\n"),
293 N_(" -x Simple authentication\n"),
294 N_(" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
295 N_(" -y file Read password from file\n"),
296 N_(" -Y mech SASL mechanism\n"),
297 N_(" -Z Start TLS request (-ZZ to require successful response)\n"),
300 const char *const *cpp
;
302 fputs( _("Common options:\n"), stderr
);
303 for( cpp
= descriptions
; *cpp
!= NULL
; cpp
++ ) {
304 if( strchr( options
, (*cpp
)[3] ) || (*cpp
)[3] == ' ' ) {
305 fputs( _(*cpp
), stderr
);
318 fprintf( stderr
, "%s: %s (%d)%s\n",
319 func
, ldap_err2string( err
), err
, extra
? extra
: "" );
321 if ( matched
&& *matched
) {
322 fprintf( stderr
, _("\tmatched DN: %s\n"), matched
);
325 if ( info
&& *info
) {
326 fprintf( stderr
, _("\tadditional info: %s\n"), info
);
329 if ( refs
&& *refs
) {
331 fprintf( stderr
, _("\treferrals:\n") );
332 for( i
=0; refs
[i
]; i
++ ) {
333 fprintf( stderr
, "\t\t%s\n", refs
[i
] );
340 tool_args( int argc
, char **argv
)
344 while (( i
= getopt( argc
, argv
, options
)) != EOF
) {
346 char *control
, *cvalue
, *next
;
348 case 'c': /* continuous operation mode */
355 ival
= strtol( optarg
, &next
, 10 );
356 if (next
== NULL
|| next
[0] != '\0') {
357 fprintf( stderr
, "%s: unable to parse debug value \"%s\"\n", prog
, optarg
);
362 case 'D': /* bind DN */
363 if( binddn
!= NULL
) {
364 fprintf( stderr
, "%s: -D previously specified\n", prog
);
365 exit( EXIT_FAILURE
);
367 binddn
= ber_strdup( optarg
);
369 case 'e': /* general extensions (controls and such) */
370 /* should be extended to support comma separated list of
371 * [!]key[=value] parameters, e.g. -e !foo,bar=567
376 if( optarg
[0] == '!' ) {
381 control
= ber_strdup( optarg
);
382 if ( (cvalue
= strchr( control
, '=' )) != NULL
) {
386 if ( strcasecmp( control
, "assert" ) == 0 ) {
388 fprintf( stderr
, "assert control previously specified\n");
389 exit( EXIT_FAILURE
);
391 if( cvalue
== NULL
) {
392 fprintf( stderr
, "assert: control value expected\n" );
396 assertctl
= 1 + crit
;
398 assert( assertion
== NULL
);
401 } else if ( strcasecmp( control
, "authzid" ) == 0 ) {
402 if( authzid
!= NULL
) {
403 fprintf( stderr
, "authzid control previously specified\n");
404 exit( EXIT_FAILURE
);
406 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
407 if( proxydn
!= NULL
) {
408 fprintf( stderr
, "authzid control incompatible with proxydn\n");
409 exit( EXIT_FAILURE
);
411 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
412 if( cvalue
== NULL
) {
413 fprintf( stderr
, "authzid: control value expected\n" );
417 fprintf( stderr
, "authzid: must be marked critical\n" );
421 assert( authzid
== NULL
);
424 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
425 } else if ( strcasecmp( control
, "proxydn" ) == 0 ) {
426 if( proxydn
!= NULL
) {
427 fprintf( stderr
, "proxydn control previously specified\n");
428 exit( EXIT_FAILURE
);
430 if( authzid
!= NULL
) {
431 fprintf( stderr
, "proxydn control incompatible with authzid\n");
432 exit( EXIT_FAILURE
);
434 if( cvalue
== NULL
) {
435 fprintf( stderr
, "proxydn: control value expected\n" );
439 fprintf( stderr
, "proxydn: must be marked critical\n" );
443 assert( proxydn
== NULL
);
445 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
447 } else if ( ( strcasecmp( control
, "relax" ) == 0 ) ||
448 ( strcasecmp( control
, "manageDIT" ) == 0 ) )
452 "relax control previously specified\n");
453 exit( EXIT_FAILURE
);
455 if( cvalue
!= NULL
) {
457 "relax: no control value expected\n" );
461 manageDIT
= 1 + crit
;
463 } else if ( strcasecmp( control
, "manageDSAit" ) == 0 ) {
466 "manageDSAit control previously specified\n");
467 exit( EXIT_FAILURE
);
469 if( cvalue
!= NULL
) {
471 "manageDSAit: no control value expected\n" );
475 manageDSAit
= 1 + crit
;
477 } else if ( strcasecmp( control
, "noop" ) == 0 ) {
479 fprintf( stderr
, "noop control previously specified\n");
480 exit( EXIT_FAILURE
);
482 if( cvalue
!= NULL
) {
483 fprintf( stderr
, "noop: no control value expected\n" );
489 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
490 } else if ( strcasecmp( control
, "ppolicy" ) == 0 ) {
492 fprintf( stderr
, "ppolicy control previously specified\n");
493 exit( EXIT_FAILURE
);
495 if( cvalue
!= NULL
) {
496 fprintf( stderr
, "ppolicy: no control value expected\n" );
500 fprintf( stderr
, "ppolicy: critical flag not allowed\n" );
507 } else if ( strcasecmp( control
, "preread" ) == 0 ) {
509 fprintf( stderr
, "preread control previously specified\n");
510 exit( EXIT_FAILURE
);
514 preread_attrs
= cvalue
;
516 } else if ( strcasecmp( control
, "postread" ) == 0 ) {
518 fprintf( stderr
, "postread control previously specified\n");
519 exit( EXIT_FAILURE
);
523 postread_attrs
= cvalue
;
525 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
526 } else if ( strcasecmp( control
, "chaining" ) == 0 ) {
529 if ( cvalue
!= NULL
) {
532 continuation
= strchr( cvalue
, '/' );
533 if ( continuation
) {
534 /* FIXME: this makes sense only in searches */
535 *continuation
++ = '\0';
536 if ( strcasecmp( continuation
, "chainingPreferred" ) == 0 ) {
537 chainingContinuation
= LDAP_CHAINING_PREFERRED
;
538 } else if ( strcasecmp( continuation
, "chainingRequired" ) == 0 ) {
539 chainingContinuation
= LDAP_CHAINING_REQUIRED
;
540 } else if ( strcasecmp( continuation
, "referralsPreferred" ) == 0 ) {
541 chainingContinuation
= LDAP_REFERRALS_PREFERRED
;
542 } else if ( strcasecmp( continuation
, "referralsRequired" ) == 0 ) {
543 chainingContinuation
= LDAP_REFERRALS_REQUIRED
;
546 "chaining behavior control "
547 "continuation value \"%s\" invalid\n",
549 exit( EXIT_FAILURE
);
553 if ( strcasecmp( cvalue
, "chainingPreferred" ) == 0 ) {
554 chainingResolve
= LDAP_CHAINING_PREFERRED
;
555 } else if ( strcasecmp( cvalue
, "chainingRequired" ) == 0 ) {
556 chainingResolve
= LDAP_CHAINING_REQUIRED
;
557 } else if ( strcasecmp( cvalue
, "referralsPreferred" ) == 0 ) {
558 chainingResolve
= LDAP_REFERRALS_PREFERRED
;
559 } else if ( strcasecmp( cvalue
, "referralsRequired" ) == 0 ) {
560 chainingResolve
= LDAP_REFERRALS_REQUIRED
;
563 "chaining behavior control "
564 "resolve value \"%s\" invalid\n",
566 exit( EXIT_FAILURE
);
569 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
571 /* this shouldn't go here, really; but it's a feature... */
572 } else if ( strcasecmp( control
, "abandon" ) == 0 ) {
573 abcan
= Intr_Abandon
;
578 } else if ( strcasecmp( control
, "cancel" ) == 0 ) {
584 } else if ( strcasecmp( control
, "ignore" ) == 0 ) {
590 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
591 } else if ( strcasecmp( control
, "sessiontracking" ) == 0 ) {
592 if ( sessionTracking
) {
593 fprintf( stderr
, "%s: session tracking can be only specified once\n", prog
);
594 exit( EXIT_FAILURE
);
597 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
599 } else if ( tool_is_oid( control
) ) {
600 LDAPControl
*tmpctrls
, ctrl
;
602 tmpctrls
= (LDAPControl
*)realloc( unknown_ctrls
,
603 (unknown_ctrls_num
+ 1)*sizeof( LDAPControl
) );
604 if ( tmpctrls
== NULL
) {
605 fprintf( stderr
, "%s: no memory?\n", prog
);
606 exit( EXIT_FAILURE
);
608 unknown_ctrls
= tmpctrls
;
609 ctrl
.ldctl_oid
= control
;
610 ctrl
.ldctl_value
.bv_val
= NULL
;
611 ctrl
.ldctl_value
.bv_len
= 0;
612 ctrl
.ldctl_iscritical
= crit
;
614 if ( cvalue
!= NULL
) {
616 size_t len
= strlen( cvalue
);
619 bv
.bv_len
= LUTIL_BASE64_DECODE_LEN( len
);
620 bv
.bv_val
= ber_memalloc( bv
.bv_len
+ 1 );
622 retcode
= lutil_b64_pton( cvalue
,
623 (unsigned char *)bv
.bv_val
,
626 if ( retcode
== -1 || retcode
> bv
.bv_len
) {
627 fprintf( stderr
, "Unable to parse value of general control %s\n",
633 ctrl
.ldctl_value
= bv
;
636 unknown_ctrls
[ unknown_ctrls_num
] = ctrl
;
640 fprintf( stderr
, "Invalid general control name: %s\n",
645 case 'f': /* read from file */
646 if( infile
!= NULL
) {
647 fprintf( stderr
, "%s: -f previously specified\n", prog
);
648 exit( EXIT_FAILURE
);
650 infile
= ber_strdup( optarg
);
652 case 'h': /* ldap host */
653 if( ldaphost
!= NULL
) {
654 fprintf( stderr
, "%s: -h previously specified\n", prog
);
655 exit( EXIT_FAILURE
);
657 ldaphost
= ber_strdup( optarg
);
659 case 'H': /* ldap URI */
660 if( ldapuri
!= NULL
) {
661 fprintf( stderr
, "%s: -H previously specified\n", prog
);
662 exit( EXIT_FAILURE
);
664 ldapuri
= ber_strdup( optarg
);
667 #ifdef HAVE_CYRUS_SASL
668 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
669 fprintf( stderr
, "%s: incompatible previous "
670 "authentication choice\n",
672 exit( EXIT_FAILURE
);
674 authmethod
= LDAP_AUTH_SASL
;
675 sasl_flags
= LDAP_SASL_INTERACTIVE
;
678 fprintf( stderr
, "%s: was not compiled with SASL support\n",
680 exit( EXIT_FAILURE
);
683 /* enable Manage DSA IT */
686 case 'n': /* print operations, don't actually do them */
690 control
= ber_strdup( optarg
);
691 if ( (cvalue
= strchr( control
, '=' )) != NULL
) {
695 if ( strcasecmp( control
, "nettimeout" ) == 0 ) {
696 if( nettimeout
.tv_sec
!= -1 ) {
697 fprintf( stderr
, "nettimeout option previously specified\n");
698 exit( EXIT_FAILURE
);
700 if( cvalue
== NULL
|| cvalue
[0] == '\0' ) {
701 fprintf( stderr
, "nettimeout: option value expected\n" );
704 if ( strcasecmp( cvalue
, "none" ) == 0 ) {
705 nettimeout
.tv_sec
= 0;
706 } else if ( strcasecmp( cvalue
, "max" ) == 0 ) {
707 nettimeout
.tv_sec
= LDAP_MAXINT
;
709 ival
= strtol( cvalue
, &next
, 10 );
710 if ( next
== NULL
|| next
[0] != '\0' ) {
712 _("Unable to parse network timeout \"%s\"\n"), cvalue
);
713 exit( EXIT_FAILURE
);
715 nettimeout
.tv_sec
= ival
;
717 if( nettimeout
.tv_sec
< 0 || nettimeout
.tv_sec
> LDAP_MAXINT
) {
718 fprintf( stderr
, _("%s: invalid network timeout (%ld) specified\n"),
719 prog
, (long)nettimeout
.tv_sec
);
720 exit( EXIT_FAILURE
);
723 fprintf( stderr
, "Invalid general option name: %s\n",
729 #ifdef HAVE_CYRUS_SASL
730 if( sasl_secprops
!= NULL
) {
731 fprintf( stderr
, "%s: -O previously specified\n", prog
);
732 exit( EXIT_FAILURE
);
734 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
735 fprintf( stderr
, "%s: incompatible previous "
736 "authentication choice\n", prog
);
737 exit( EXIT_FAILURE
);
739 authmethod
= LDAP_AUTH_SASL
;
740 sasl_secprops
= ber_strdup( optarg
);
742 fprintf( stderr
, "%s: not compiled with SASL support\n", prog
);
743 exit( EXIT_FAILURE
);
748 fprintf( stderr
, "%s: -p previously specified\n", prog
);
749 exit( EXIT_FAILURE
);
751 ival
= strtol( optarg
, &next
, 10 );
752 if ( next
== NULL
|| next
[0] != '\0' ) {
753 fprintf( stderr
, "%s: unable to parse port number \"%s\"\n", prog
, optarg
);
754 exit( EXIT_FAILURE
);
759 ival
= strtol( optarg
, &next
, 10 );
760 if ( next
== NULL
|| next
[0] != '\0' ) {
761 fprintf( stderr
, "%s: unable to parse protocol version \"%s\"\n", prog
, optarg
);
762 exit( EXIT_FAILURE
);
766 if( protocol
== LDAP_VERSION3
) {
767 fprintf( stderr
, "%s: -P 2 incompatible with version %d\n",
769 exit( EXIT_FAILURE
);
771 protocol
= LDAP_VERSION2
;
774 if( protocol
== LDAP_VERSION2
) {
775 fprintf( stderr
, "%s: -P 2 incompatible with version %d\n",
777 exit( EXIT_FAILURE
);
779 protocol
= LDAP_VERSION3
;
782 fprintf( stderr
, "%s: protocol version should be 2 or 3\n",
788 #ifdef HAVE_CYRUS_SASL
789 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
790 fprintf( stderr
, "%s: incompatible previous "
791 "authentication choice\n",
793 exit( EXIT_FAILURE
);
795 authmethod
= LDAP_AUTH_SASL
;
796 sasl_flags
= LDAP_SASL_QUIET
;
799 fprintf( stderr
, "%s: not compiled with SASL support\n",
801 exit( EXIT_FAILURE
);
804 #ifdef HAVE_CYRUS_SASL
805 if( sasl_realm
!= NULL
) {
806 fprintf( stderr
, "%s: -R previously specified\n", prog
);
807 exit( EXIT_FAILURE
);
809 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
810 fprintf( stderr
, "%s: incompatible previous "
811 "authentication choice\n",
813 exit( EXIT_FAILURE
);
815 authmethod
= LDAP_AUTH_SASL
;
816 sasl_realm
= ber_strdup( optarg
);
818 fprintf( stderr
, "%s: not compiled with SASL support\n",
820 exit( EXIT_FAILURE
);
824 #ifdef HAVE_CYRUS_SASL
825 if( sasl_authc_id
!= NULL
) {
826 fprintf( stderr
, "%s: -U previously specified\n", prog
);
827 exit( EXIT_FAILURE
);
829 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
830 fprintf( stderr
, "%s: incompatible previous "
831 "authentication choice\n",
833 exit( EXIT_FAILURE
);
835 authmethod
= LDAP_AUTH_SASL
;
836 sasl_authc_id
= ber_strdup( optarg
);
838 fprintf( stderr
, "%s: not compiled with SASL support\n",
840 exit( EXIT_FAILURE
);
843 case 'v': /* verbose mode */
846 case 'V': /* version */
849 case 'w': /* password */
850 passwd
.bv_val
= ber_strdup( optarg
);
854 for( p
= optarg
; *p
!= '\0'; p
++ ) {
858 passwd
.bv_len
= strlen( passwd
.bv_val
);
867 #ifdef HAVE_CYRUS_SASL
868 if( sasl_mech
!= NULL
) {
869 fprintf( stderr
, "%s: -Y previously specified\n", prog
);
870 exit( EXIT_FAILURE
);
872 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
874 "%s: incompatible with authentication choice\n", prog
);
875 exit( EXIT_FAILURE
);
877 authmethod
= LDAP_AUTH_SASL
;
878 sasl_mech
= ber_strdup( optarg
);
880 fprintf( stderr
, "%s: not compiled with SASL support\n", prog
);
881 exit( EXIT_FAILURE
);
885 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SIMPLE
) {
886 fprintf( stderr
, "%s: incompatible with previous "
887 "authentication choice\n", prog
);
888 exit( EXIT_FAILURE
);
890 authmethod
= LDAP_AUTH_SIMPLE
;
893 #ifdef HAVE_CYRUS_SASL
894 if( sasl_authz_id
!= NULL
) {
895 fprintf( stderr
, "%s: -X previously specified\n", prog
);
896 exit( EXIT_FAILURE
);
898 if( authmethod
!= -1 && authmethod
!= LDAP_AUTH_SASL
) {
899 fprintf( stderr
, "%s: -X incompatible with "
900 "authentication choice\n", prog
);
901 exit( EXIT_FAILURE
);
903 authmethod
= LDAP_AUTH_SASL
;
904 sasl_authz_id
= ber_strdup( optarg
);
906 fprintf( stderr
, "%s: not compiled with SASL support\n", prog
);
907 exit( EXIT_FAILURE
);
914 fprintf( stderr
, "%s: not compiled with TLS support\n", prog
);
915 exit( EXIT_FAILURE
);
919 if( handle_private_option( i
) ) break;
920 fprintf( stderr
, "%s: unrecognized option -%c\n",
927 /* prevent bad linking */
929 api
.ldapai_info_version
= LDAP_API_INFO_VERSION
;
931 if ( ldap_get_option(NULL
, LDAP_OPT_API_INFO
, &api
)
932 != LDAP_OPT_SUCCESS
)
934 fprintf( stderr
, "%s: ldap_get_option(API_INFO) failed\n", prog
);
935 exit( EXIT_FAILURE
);
938 if (api
.ldapai_info_version
!= LDAP_API_INFO_VERSION
) {
939 fprintf( stderr
, "LDAP APIInfo version mismatch: "
940 "library %d, header %d\n",
941 api
.ldapai_info_version
, LDAP_API_INFO_VERSION
);
942 exit( EXIT_FAILURE
);
945 if( api
.ldapai_api_version
!= LDAP_API_VERSION
) {
946 fprintf( stderr
, "LDAP API version mismatch: "
947 "library %d, header %d\n",
948 api
.ldapai_api_version
, LDAP_API_VERSION
);
949 exit( EXIT_FAILURE
);
952 if( strcmp(api
.ldapai_vendor_name
, LDAP_VENDOR_NAME
) != 0 ) {
953 fprintf( stderr
, "LDAP vendor name mismatch: "
954 "library %s, header %s\n",
955 api
.ldapai_vendor_name
, LDAP_VENDOR_NAME
);
956 exit( EXIT_FAILURE
);
959 if( api
.ldapai_vendor_version
!= LDAP_VENDOR_VERSION
) {
960 fprintf( stderr
, "LDAP vendor version mismatch: "
961 "library %d, header %d\n",
962 api
.ldapai_vendor_version
, LDAP_VENDOR_VERSION
);
963 exit( EXIT_FAILURE
);
967 fprintf( stderr
, "%s: %s\t(LDAP library: %s %d)\n",
969 LDAP_VENDOR_NAME
, LDAP_VENDOR_VERSION
);
970 if (version
> 1) exit( EXIT_SUCCESS
);
973 ldap_memfree( api
.ldapai_vendor_name
);
974 ber_memvfree( (void **)api
.ldapai_extensions
);
978 protocol
= LDAP_VERSION3
;
980 if (authmethod
== -1 && protocol
> LDAP_VERSION2
) {
981 #ifdef HAVE_CYRUS_SASL
982 authmethod
= LDAP_AUTH_SASL
;
984 authmethod
= LDAP_AUTH_SIMPLE
;
988 if( ldapuri
== NULL
) {
989 if( ldapport
&& ( ldaphost
== NULL
)) {
990 fprintf( stderr
, "%s: -p without -h is invalid.\n", prog
);
991 exit( EXIT_FAILURE
);
994 if( ldaphost
!= NULL
) {
995 fprintf( stderr
, "%s: -H incompatible with -h\n", prog
);
996 exit( EXIT_FAILURE
);
999 fprintf( stderr
, "%s: -H incompatible with -p\n", prog
);
1000 exit( EXIT_FAILURE
);
1004 if( protocol
== LDAP_VERSION2
) {
1005 if( assertctl
|| authzid
|| manageDIT
|| manageDSAit
||
1006 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1008 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1009 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1012 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1014 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1015 noop
|| ppolicy
|| preread
|| postread
)
1017 fprintf( stderr
, "%s: -e/-M incompatible with LDAPv2\n", prog
);
1018 exit( EXIT_FAILURE
);
1022 fprintf( stderr
, "%s: -Z incompatible with LDAPv2\n", prog
);
1023 exit( EXIT_FAILURE
);
1026 #ifdef HAVE_CYRUS_SASL
1027 if( authmethod
== LDAP_AUTH_SASL
) {
1028 fprintf( stderr
, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
1030 exit( EXIT_FAILURE
);
1038 tool_conn_setup( int dont
, void (*private_setup
)( LDAP
* ) )
1043 if( ber_set_option( NULL
, LBER_OPT_DEBUG_LEVEL
, &debug
)
1044 != LBER_OPT_SUCCESS
)
1047 "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug
);
1049 if( ldap_set_option( NULL
, LDAP_OPT_DEBUG_LEVEL
, &debug
)
1050 != LDAP_OPT_SUCCESS
)
1053 "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug
);
1058 (void) SIGNAL( SIGPIPE
, SIG_IGN
);
1062 SIGNAL( SIGINT
, do_sig
);
1068 if( ( ldaphost
!= NULL
|| ldapport
) && ( ldapuri
== NULL
) ) {
1071 memset( &url
, 0, sizeof(url
));
1073 url
.lud_scheme
= "ldap";
1074 url
.lud_host
= ldaphost
;
1075 url
.lud_port
= ldapport
;
1076 url
.lud_scope
= LDAP_SCOPE_DEFAULT
;
1078 ldapuri
= ldap_url_desc2str( &url
);
1080 } else if ( ldapuri
!= NULL
) {
1081 LDAPURLDesc
*ludlist
, **ludp
;
1085 rc
= ldap_url_parselist( &ludlist
, ldapuri
);
1086 if ( rc
!= LDAP_URL_SUCCESS
) {
1088 "Could not parse LDAP URI(s)=%s (%d)\n",
1090 exit( EXIT_FAILURE
);
1093 for ( ludp
= &ludlist
; *ludp
!= NULL
; ) {
1094 LDAPURLDesc
*lud
= *ludp
;
1097 if ( lud
->lud_dn
!= NULL
&& lud
->lud_dn
[ 0 ] != '\0' &&
1098 ( lud
->lud_host
== NULL
|| lud
->lud_host
[0] == '\0' ) )
1100 /* if no host but a DN is provided,
1101 * use DNS SRV to gather the host list
1102 * and turn it into a list of URIs
1103 * using the scheme provided */
1104 char *domain
= NULL
,
1108 len_proto
= strlen( lud
->lud_scheme
);
1110 if ( ldap_dn2domain( lud
->lud_dn
, &domain
)
1114 "DNS SRV: Could not turn "
1115 "DN=\"%s\" into a domain\n",
1120 rc
= ldap_domain2hostlist( domain
, &hostlist
);
1123 "DNS SRV: Could not turn "
1124 "domain=%s into a hostlist\n",
1129 hosts
= ldap_str2charray( hostlist
, " " );
1130 if ( hosts
== NULL
) {
1132 "DNS SRV: Could not parse "
1133 "hostlist=\"%s\"\n",
1138 for ( i
= 0; hosts
[ i
] != NULL
; i
++ )
1141 tmp
= (char **)realloc( urls
, sizeof( char * ) * ( nurls
+ i
+ 1 ) );
1142 if ( tmp
== NULL
) {
1144 "DNS SRV: out of memory?\n" );
1148 urls
[ nurls
] = NULL
;
1150 for ( i
= 0; hosts
[ i
] != NULL
; i
++ ) {
1151 size_t len
= len_proto
1153 + strlen( hosts
[ i
] )
1156 urls
[ nurls
+ i
+ 1 ] = NULL
;
1157 urls
[ nurls
+ i
] = (char *)malloc( sizeof( char ) * len
);
1158 if ( urls
[ nurls
+ i
] == NULL
) {
1160 "DNS SRV: out of memory?\n" );
1164 snprintf( urls
[ nurls
+ i
], len
, "%s://%s",
1165 lud
->lud_scheme
, hosts
[ i
] );
1170 ber_memvfree( (void **)hosts
);
1171 ber_memfree( hostlist
);
1172 ber_memfree( domain
);
1175 tmp
= (char **)realloc( urls
, sizeof( char * ) * ( nurls
+ 2 ) );
1176 if ( tmp
== NULL
) {
1178 "DNS SRV: out of memory?\n" );
1182 urls
[ nurls
+ 1 ] = NULL
;
1184 urls
[ nurls
] = ldap_url_desc2str( lud
);
1185 if ( urls
[ nurls
] == NULL
) {
1187 "DNS SRV: out of memory?\n" );
1193 *ludp
= lud
->lud_next
;
1195 lud
->lud_next
= NULL
;
1196 ldap_free_urldesc( lud
);
1199 if ( ludlist
!= NULL
) {
1200 ldap_free_urllist( ludlist
);
1201 exit( EXIT_FAILURE
);
1203 } else if ( urls
== NULL
) {
1204 exit( EXIT_FAILURE
);
1207 ldap_memfree( ldapuri
);
1208 ldapuri
= ldap_charray2str( urls
, " " );
1209 ber_memvfree( (void **)urls
);
1213 fprintf( stderr
, "ldap_initialize( %s )\n",
1214 ldapuri
!= NULL
? ldapuri
: "<DEFAULT>" );
1216 rc
= ldap_initialize( &ld
, ldapuri
);
1217 if( rc
!= LDAP_SUCCESS
) {
1219 "Could not create LDAP session handle for URI=%s (%d): %s\n",
1220 ldapuri
, rc
, ldap_err2string(rc
) );
1221 exit( EXIT_FAILURE
);
1224 if( private_setup
) private_setup( ld
);
1227 if( ldap_set_option( ld
, LDAP_OPT_REFERRALS
,
1228 referrals
? LDAP_OPT_ON
: LDAP_OPT_OFF
) != LDAP_OPT_SUCCESS
)
1230 fprintf( stderr
, "Could not set LDAP_OPT_REFERRALS %s\n",
1231 referrals
? "on" : "off" );
1232 exit( EXIT_FAILURE
);
1235 if( ldap_set_option( ld
, LDAP_OPT_PROTOCOL_VERSION
, &protocol
)
1236 != LDAP_OPT_SUCCESS
)
1238 fprintf( stderr
, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
1240 exit( EXIT_FAILURE
);
1244 rc
= ldap_start_tls_s( ld
, NULL
, NULL
);
1245 if ( rc
!= LDAP_SUCCESS
) {
1246 tool_perror( "ldap_start_tls", rc
, NULL
, NULL
, NULL
, NULL
);
1247 if ( use_tls
> 1 ) {
1248 exit( EXIT_FAILURE
);
1253 if ( nettimeout
.tv_sec
> 0 ) {
1254 if ( ldap_set_option( ld
, LDAP_OPT_NETWORK_TIMEOUT
, (void *) &nettimeout
)
1255 != LDAP_OPT_SUCCESS
)
1257 fprintf( stderr
, "Could not set LDAP_OPT_NETWORK_TIMEOUT %ld\n",
1258 (long)nettimeout
.tv_sec
);
1259 exit( EXIT_FAILURE
);
1269 tool_bind( LDAP
*ld
)
1271 LDAPControl
**sctrlsp
= NULL
;
1272 LDAPControl
*sctrls
[3];
1273 LDAPControl sctrl
[3];
1276 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1279 c
.ldctl_oid
= LDAP_CONTROL_PASSWORDPOLICYREQUEST
;
1280 c
.ldctl_value
.bv_val
= NULL
;
1281 c
.ldctl_value
.bv_len
= 0;
1282 c
.ldctl_iscritical
= 0;
1284 sctrls
[nsctrls
] = &sctrl
[nsctrls
];
1285 sctrls
[++nsctrls
] = NULL
;
1289 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1290 if ( sessionTracking
) {
1293 if (stValue
.bv_val
== NULL
&& st_value( ld
, &stValue
) ) {
1294 exit( EXIT_FAILURE
);
1297 c
.ldctl_oid
= LDAP_CONTROL_X_SESSION_TRACKING
;
1298 c
.ldctl_iscritical
= 0;
1299 ber_dupbv( &c
.ldctl_value
, &stValue
);
1302 sctrls
[nsctrls
] = &sctrl
[nsctrls
];
1303 sctrls
[++nsctrls
] = NULL
;
1305 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1311 assert( nsctrls
< sizeof(sctrls
)/sizeof(sctrls
[0]) );
1313 if ( authmethod
== LDAP_AUTH_SASL
) {
1314 #ifdef HAVE_CYRUS_SASL
1318 if( sasl_secprops
!= NULL
) {
1319 rc
= ldap_set_option( ld
, LDAP_OPT_X_SASL_SECPROPS
,
1320 (void *) sasl_secprops
);
1322 if( rc
!= LDAP_OPT_SUCCESS
) {
1324 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
1326 exit( LDAP_LOCAL_ERROR
);
1330 defaults
= lutil_sasl_defaults( ld
,
1337 rc
= ldap_sasl_interactive_bind_s( ld
, binddn
, sasl_mech
,
1339 NULL
, sasl_flags
, lutil_sasl_interact
, defaults
);
1341 lutil_sasl_freedefs( defaults
);
1342 if( rc
!= LDAP_SUCCESS
) {
1343 tool_perror( "ldap_sasl_interactive_bind_s",
1344 rc
, NULL
, NULL
, NULL
, NULL
);
1348 fprintf( stderr
, "%s: not compiled with SASL support\n", prog
);
1349 exit( LDAP_NOT_SUPPORTED
);
1353 LDAPMessage
*result
;
1354 LDAPControl
**ctrls
;
1356 char *matched
= NULL
;
1364 rc
= ldap_sasl_bind( ld
, binddn
, LDAP_SASL_SIMPLE
, &passwd
,
1365 sctrlsp
, NULL
, &msgid
);
1366 if ( msgid
== -1 ) {
1367 tool_perror( "ldap_sasl_bind(SIMPLE)", rc
,
1368 NULL
, NULL
, NULL
, NULL
);
1373 if ( ldap_result( ld
, msgid
, LDAP_MSG_ALL
, NULL
, &result
) == -1 ) {
1374 tool_perror( "ldap_result", -1, NULL
, NULL
, NULL
, NULL
);
1375 exit( LDAP_LOCAL_ERROR
);
1378 rc
= ldap_parse_result( ld
, result
, &err
, &matched
, &info
, &refs
,
1380 if ( rc
!= LDAP_SUCCESS
) {
1381 tool_perror( "ldap_bind parse result", rc
, NULL
, matched
, info
, refs
);
1382 exit( LDAP_LOCAL_ERROR
);
1385 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1386 if ( ctrls
&& ppolicy
) {
1388 int expire
, grace
, len
= 0;
1389 LDAPPasswordPolicyError pErr
= -1;
1391 ctrl
= ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE
,
1394 if ( ctrl
&& ldap_parse_passwordpolicy_control( ld
, ctrl
,
1395 &expire
, &grace
, &pErr
) == LDAP_SUCCESS
)
1397 if ( pErr
!= PP_noError
){
1400 strcpy( msgbuf
+2, ldap_passwordpolicy_err2txt( pErr
));
1401 len
= strlen( msgbuf
);
1403 if ( expire
>= 0 ) {
1404 sprintf( msgbuf
+len
,
1405 " (Password expires in %d seconds)",
1407 } else if ( grace
>= 0 ) {
1408 sprintf( msgbuf
+len
,
1409 " (Password expired, %d grace logins remain)",
1417 ldap_controls_free( ctrls
);
1420 if ( err
!= LDAP_SUCCESS
1422 || ( matched
&& matched
[ 0 ] )
1423 || ( info
&& info
[ 0 ] )
1426 tool_perror( "ldap_bind", err
, msgbuf
, matched
, info
, refs
);
1428 if( matched
) ber_memfree( matched
);
1429 if( info
) ber_memfree( info
);
1430 if( refs
) ber_memvfree( (void **)refs
);
1432 if ( err
!= LDAP_SUCCESS
) exit( err
);
1438 tool_unbind( LDAP
*ld
)
1440 int err
= ldap_set_option( ld
, LDAP_OPT_SERVER_CONTROLS
, NULL
);
1442 if ( err
!= LDAP_OPT_SUCCESS
) {
1443 fprintf( stderr
, "Could not unset controls\n");
1446 (void) ldap_unbind_ext( ld
, NULL
, NULL
);
1450 /* Set server controls. Add controls extra_c[0..count-1], if set. */
1452 tool_server_controls( LDAP
*ld
, LDAPControl
*extra_c
, int count
)
1454 int i
= 0, j
, crit
= 0, err
;
1455 LDAPControl c
[16], **ctrls
;
1459 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1461 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1465 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1470 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1472 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
1473 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1475 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1477 || unknown_ctrls_num
) )
1482 ctrls
= (LDAPControl
**) malloc(sizeof(c
) + (count
+ unknown_ctrls_num
+ 1)*sizeof(LDAPControl
*));
1483 if ( ctrls
== NULL
) {
1484 fprintf( stderr
, "No memory\n" );
1485 exit( EXIT_FAILURE
);
1489 if ( BER_BVISNULL( &assertionvalue
) ) {
1490 err
= ldap_create_assertion_control_value( ld
,
1491 assertion
, &assertionvalue
);
1494 "Unable to create assertion value "
1495 "\"%s\" (%d)\n", assertion
, err
);
1499 c
[i
].ldctl_oid
= LDAP_CONTROL_ASSERT
;
1500 c
[i
].ldctl_value
= assertionvalue
;
1501 c
[i
].ldctl_iscritical
= assertctl
> 1;
1507 c
[i
].ldctl_value
.bv_val
= authzid
;
1508 c
[i
].ldctl_value
.bv_len
= strlen( authzid
);
1509 c
[i
].ldctl_oid
= LDAP_CONTROL_PROXY_AUTHZ
;
1510 c
[i
].ldctl_iscritical
= 1;
1515 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1516 /* NOTE: doesn't need an extra count because it's incompatible
1519 BerElementBuffer berbuf
;
1520 BerElement
*ber
= (BerElement
*)&berbuf
;
1522 ber_init2( ber
, NULL
, LBER_USE_DER
);
1524 if ( ber_printf( ber
, "s", proxydn
) == LBER_ERROR
) {
1525 exit( EXIT_FAILURE
);
1528 if ( ber_flatten2( ber
, &c
[i
].ldctl_value
, 0 ) == -1 ) {
1529 exit( EXIT_FAILURE
);
1532 c
[i
].ldctl_oid
= LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
;
1533 c
[i
].ldctl_iscritical
= 1;
1537 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1540 c
[i
].ldctl_oid
= LDAP_CONTROL_MANAGEDIT
;
1541 BER_BVZERO( &c
[i
].ldctl_value
);
1542 c
[i
].ldctl_iscritical
= manageDIT
> 1;
1547 if ( manageDSAit
) {
1548 c
[i
].ldctl_oid
= LDAP_CONTROL_MANAGEDSAIT
;
1549 BER_BVZERO( &c
[i
].ldctl_value
);
1550 c
[i
].ldctl_iscritical
= manageDSAit
> 1;
1556 c
[i
].ldctl_oid
= LDAP_CONTROL_NOOP
;
1557 BER_BVZERO( &c
[i
].ldctl_value
);
1558 c
[i
].ldctl_iscritical
= noop
> 1;
1563 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1565 c
[i
].ldctl_oid
= LDAP_CONTROL_PASSWORDPOLICYREQUEST
;
1566 BER_BVZERO( &c
[i
].ldctl_value
);
1567 c
[i
].ldctl_iscritical
= 0;
1574 char berbuf
[LBER_ELEMENT_SIZEOF
];
1575 BerElement
*ber
= (BerElement
*)berbuf
;
1576 char **attrs
= NULL
;
1578 if( preread_attrs
) {
1579 attrs
= ldap_str2charray( preread_attrs
, "," );
1582 ber_init2( ber
, NULL
, LBER_USE_DER
);
1584 if( ber_printf( ber
, "{v}", attrs
) == -1 ) {
1585 fprintf( stderr
, "preread attrs encode failed.\n" );
1586 exit( EXIT_FAILURE
);
1589 err
= ber_flatten2( ber
, &c
[i
].ldctl_value
, 0 );
1591 fprintf( stderr
, "preread flatten failed (%d)\n", err
);
1592 exit( EXIT_FAILURE
);
1595 c
[i
].ldctl_oid
= LDAP_CONTROL_PRE_READ
;
1596 c
[i
].ldctl_iscritical
= preread
> 1;
1600 if( attrs
) ldap_charray_free( attrs
);
1604 char berbuf
[LBER_ELEMENT_SIZEOF
];
1605 BerElement
*ber
= (BerElement
*)berbuf
;
1606 char **attrs
= NULL
;
1608 if( postread_attrs
) {
1609 attrs
= ldap_str2charray( postread_attrs
, "," );
1612 ber_init2( ber
, NULL
, LBER_USE_DER
);
1614 if( ber_printf( ber
, "{v}", attrs
) == -1 ) {
1615 fprintf( stderr
, "postread attrs encode failed.\n" );
1616 exit( EXIT_FAILURE
);
1619 err
= ber_flatten2( ber
, &c
[i
].ldctl_value
, 0 );
1621 fprintf( stderr
, "postread flatten failed (%d)\n", err
);
1622 exit( EXIT_FAILURE
);
1625 c
[i
].ldctl_oid
= LDAP_CONTROL_POST_READ
;
1626 c
[i
].ldctl_iscritical
= postread
> 1;
1630 if( attrs
) ldap_charray_free( attrs
);
1633 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1635 if ( chainingResolve
> -1 ) {
1636 BerElementBuffer berbuf
;
1637 BerElement
*ber
= (BerElement
*)&berbuf
;
1639 ber_init2( ber
, NULL
, LBER_USE_DER
);
1641 err
= ber_printf( ber
, "{e" /* } */, chainingResolve
);
1644 fprintf( stderr
, _("Chaining behavior control encoding error!\n") );
1645 exit( EXIT_FAILURE
);
1648 if ( chainingContinuation
> -1 ) {
1649 err
= ber_printf( ber
, "e", chainingContinuation
);
1652 fprintf( stderr
, _("Chaining behavior control encoding error!\n") );
1653 exit( EXIT_FAILURE
);
1657 err
= ber_printf( ber
, /* { */ "N}" );
1660 fprintf( stderr
, _("Chaining behavior control encoding error!\n") );
1661 exit( EXIT_FAILURE
);
1664 if ( ber_flatten2( ber
, &c
[i
].ldctl_value
, 0 ) == -1 ) {
1665 exit( EXIT_FAILURE
);
1669 BER_BVZERO( &c
[i
].ldctl_value
);
1672 c
[i
].ldctl_oid
= LDAP_CONTROL_X_CHAINING_BEHAVIOR
;
1673 c
[i
].ldctl_iscritical
= chaining
> 1;
1677 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
1679 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1680 if ( sessionTracking
) {
1681 if ( stValue
.bv_val
== NULL
&& st_value( ld
, &stValue
) ) {
1682 exit( EXIT_FAILURE
);
1685 c
[i
].ldctl_oid
= LDAP_CONTROL_X_SESSION_TRACKING
;
1686 c
[i
].ldctl_iscritical
= 0;
1687 ber_dupbv( &c
[i
].ldctl_value
, &stValue
);
1692 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1695 ctrls
[i
++] = extra_c
++;
1697 for ( count
= 0; count
< unknown_ctrls_num
; count
++ ) {
1698 ctrls
[i
++] = &unknown_ctrls
[count
];
1702 err
= ldap_set_option( ld
, LDAP_OPT_SERVER_CONTROLS
, ctrls
);
1704 if ( err
!= LDAP_OPT_SUCCESS
) {
1705 for ( j
= 0; j
< i
; j
++ ) {
1706 if ( ctrls
[j
]->ldctl_iscritical
) crit
= 1;
1708 fprintf( stderr
, "Could not set %scontrols\n",
1709 crit
? "critical " : "" );
1714 exit( EXIT_FAILURE
);
1719 tool_check_abandon( LDAP
*ld
, int msgid
)
1723 switch ( gotintr
) {
1725 rc
= ldap_cancel_s( ld
, msgid
, NULL
, NULL
);
1726 fprintf( stderr
, "got interrupt, cancel got %d: %s\n",
1727 rc
, ldap_err2string( rc
) );
1731 rc
= ldap_abandon_ext( ld
, msgid
, NULL
, NULL
);
1732 fprintf( stderr
, "got interrupt, abandon got %d: %s\n",
1733 rc
, ldap_err2string( rc
) );
1737 /* just unbind, ignoring the request */
1745 print_prepostread( LDAP
*ld
, LDAPControl
*ctrl
, struct berval
*what
)
1750 tool_write_ldif( LDIF_PUT_COMMENT
, "==> ",
1751 what
->bv_val
, what
->bv_len
);
1752 ber
= ber_init( &ctrl
->ldctl_value
);
1753 if ( ber
== NULL
) {
1757 } else if ( ber_scanf( ber
, "{m{" /*}}*/, &bv
) == LBER_ERROR
) {
1762 tool_write_ldif( LDIF_PUT_VALUE
, "dn", bv
.bv_val
, bv
.bv_len
);
1764 while ( ber_scanf( ber
, "{m" /*}*/, &bv
) != LBER_ERROR
) {
1766 BerVarray vals
= NULL
;
1768 if ( ber_scanf( ber
, "[W]", &vals
) == LBER_ERROR
||
1775 for ( i
= 0; vals
[ i
].bv_val
!= NULL
; i
++ ) {
1777 ldif
? LDIF_PUT_COMMENT
: LDIF_PUT_VALUE
,
1778 bv
.bv_val
, vals
[ i
].bv_val
, vals
[ i
].bv_len
);
1781 ber_bvarray_free( vals
);
1785 if ( ber
!= NULL
) {
1789 tool_write_ldif( LDIF_PUT_COMMENT
, "<== ",
1790 what
->bv_val
, what
->bv_len
);
1796 print_preread( LDAP
*ld
, LDAPControl
*ctrl
)
1798 static struct berval what
= BER_BVC( "preread" );
1800 return print_prepostread( ld
, ctrl
, &what
);
1804 print_postread( LDAP
*ld
, LDAPControl
*ctrl
)
1806 static struct berval what
= BER_BVC( "postread" );
1808 return print_prepostread( ld
, ctrl
, &what
);
1812 print_paged_results( LDAP
*ld
, LDAPControl
*ctrl
)
1816 /* note: pr_cookie is being malloced; it's freed
1817 * the next time the control is sent, but the last
1818 * time it's not; we don't care too much, because
1819 * the last time an empty value is returned... */
1820 if ( ldap_parse_pageresponse_control( ld
, ctrl
, &estimate
, &pr_cookie
)
1827 /* FIXME: check buffer overflow */
1828 char buf
[ BUFSIZ
], *ptr
= buf
;
1830 if ( estimate
> 0 ) {
1831 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1832 "estimate=%d", estimate
);
1835 if ( pr_cookie
.bv_len
> 0 ) {
1838 bv
.bv_len
= LUTIL_BASE64_ENCODE_LEN(
1839 pr_cookie
.bv_len
) + 1;
1840 bv
.bv_val
= ber_memalloc( bv
.bv_len
+ 1 );
1842 bv
.bv_len
= lutil_b64_ntop(
1843 (unsigned char *) pr_cookie
.bv_val
,
1845 bv
.bv_val
, bv
.bv_len
);
1847 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1848 "%scookie=%s", ptr
== buf
? "" : " ",
1851 ber_memfree( bv
.bv_val
);
1853 pr_morePagedResults
= 1;
1856 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1857 "%scookie=", ptr
== buf
? "" : " " );
1860 tool_write_ldif( ldif
? LDIF_PUT_COMMENT
: LDIF_PUT_VALUE
,
1861 "pagedresults", buf
, ptr
- buf
);
1867 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1869 print_ppolicy( LDAP
*ld
, LDAPControl
*ctrl
)
1871 int expire
= 0, grace
= 0, rc
;
1872 LDAPPasswordPolicyError pperr
;
1874 rc
= ldap_parse_passwordpolicy_control( ld
, ctrl
,
1875 &expire
, &grace
, &pperr
);
1876 if ( rc
== LDAP_SUCCESS
) {
1877 char buf
[ BUFSIZ
], *ptr
= buf
;
1879 if ( expire
!= -1 ) {
1880 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1881 "expire=%d", expire
);
1884 if ( grace
!= -1 ) {
1885 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1886 "%sgrace=%d", ptr
== buf
? "" : " ", grace
);
1889 if ( pperr
!= PP_noError
) {
1890 ptr
+= snprintf( ptr
, sizeof( buf
) - ( ptr
- buf
),
1891 "%serror=%d (%s)", ptr
== buf
? "" : " ",
1893 ldap_passwordpolicy_err2txt( pperr
) );
1896 tool_write_ldif( ldif
? LDIF_PUT_COMMENT
: LDIF_PUT_VALUE
,
1897 "ppolicy", buf
, ptr
- buf
);
1904 void tool_print_ctrls(
1906 LDAPControl
**ctrls
)
1911 for ( i
= 0; ctrls
[i
] != NULL
; i
++ ) {
1912 /* control: OID criticality base64value */
1913 struct berval b64
= BER_BVNULL
;
1918 /* FIXME: there might be cases where a control has NULL OID;
1919 * this makes little sense, especially when returned by the
1920 * server, but libldap happily allows it */
1921 if ( ctrls
[i
]->ldctl_oid
== NULL
) {
1926 len
+= strlen( ctrls
[i
]->ldctl_oid
);
1928 /* add enough for space after OID and the critical value itself */
1929 len
+= ctrls
[i
]->ldctl_iscritical
1930 ? sizeof("true") : sizeof("false");
1932 /* convert to base64 */
1933 if ( !BER_BVISNULL( &ctrls
[i
]->ldctl_value
) ) {
1934 b64
.bv_len
= LUTIL_BASE64_ENCODE_LEN(
1935 ctrls
[i
]->ldctl_value
.bv_len
) + 1;
1936 b64
.bv_val
= ber_memalloc( b64
.bv_len
+ 1 );
1938 b64
.bv_len
= lutil_b64_ntop(
1939 (unsigned char *) ctrls
[i
]->ldctl_value
.bv_val
,
1940 ctrls
[i
]->ldctl_value
.bv_len
,
1941 b64
.bv_val
, b64
.bv_len
);
1945 len
+= 1 + b64
.bv_len
;
1948 ptr
= str
= malloc( len
+ 1 );
1950 ptr
= lutil_strcopy( ptr
, ": " );
1952 ptr
= lutil_strcopy( ptr
, ctrls
[i
]->ldctl_oid
);
1953 ptr
= lutil_strcopy( ptr
, ctrls
[i
]->ldctl_iscritical
1954 ? " true" : " false" );
1957 ptr
= lutil_strcopy( ptr
, " " );
1958 ptr
= lutil_strcopy( ptr
, b64
.bv_val
);
1962 tool_write_ldif( ldif
? LDIF_PUT_COMMENT
: LDIF_PUT_VALUE
,
1963 "control", str
, len
);
1968 ber_memfree( b64
.bv_val
);
1971 /* known controls */
1972 for ( j
= 0; tool_ctrl_response
[j
].oid
!= NULL
; j
++ ) {
1973 if ( strcmp( tool_ctrl_response
[j
].oid
, ctrls
[i
]->ldctl_oid
) == 0 ) {
1974 if ( !tool_ctrl_response
[j
].mask
& tool_type
) {
1975 /* this control should not appear
1976 * with this tool; warning? */
1982 if ( tool_ctrl_response
[j
].oid
!= NULL
&& tool_ctrl_response
[j
].func
) {
1983 (void)tool_ctrl_response
[j
].func( ld
, ctrls
[i
] );
1989 tool_write_ldif( int type
, char *name
, char *value
, ber_len_t vallen
)
1993 if (( ldif
= ldif_put( type
, name
, value
, vallen
)) == NULL
) {
1997 fputs( ldif
, stdout
);
1998 ber_memfree( ldif
);
2004 tool_is_oid( const char *s
)
2008 if ( !isdigit( (unsigned char) s
[ 0 ] ) ) {
2012 for ( ; s
[ 0 ]; s
++ ) {
2013 if ( s
[ 0 ] == '.' ) {
2014 if ( s
[ 1 ] == '\0' ) {
2021 if ( !isdigit( (unsigned char) s
[ 0 ] ) ) {
2025 if ( first
== 1 && s
[ 0 ] == '0' && s
[ 1 ] != '.' ) {