1 /*        $NetBSD: common.c,v 1.10 2021/08/14 16:14:49 christos Exp $ */
2 
3 /* common.c - common routines for the ldap client tools */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2003 Kurt D. Zeilenga.
9  * Portions Copyright 2003 IBM Corporation.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted only as authorized by the OpenLDAP
14  * Public License.
15  *
16  * A copy of this license is available in the file LICENSE in the
17  * top-level directory of the distribution or, alternatively, at
18  * <http://www.OpenLDAP.org/license.html>.
19  */
20 /* ACKNOWLEDGEMENTS:
21  * This file was initially created by Hallvard B. Furuseth based (in
22  * part) upon argument parsing code for individual tools located in
23  * this directory.   Additional contributors include:
24  *   Kurt D. Zeilenga (additional common argument and control support)
25  */
26 
27 #include <sys/cdefs.h>
28 __RCSID("$NetBSD: common.c,v 1.10 2021/08/14 16:14:49 christos Exp $");
29 
30 #include "portable.h"
31 
32 #include <stdio.h>
33 
34 #include <ac/stdlib.h>
35 #include <ac/signal.h>
36 #include <ac/string.h>
37 #include <ac/ctype.h>
38 #include <ac/unistd.h>
39 #include <ac/errno.h>
40 #include <ac/time.h>
41 #include <ac/socket.h>
42 
43 #ifdef HAVE_CYRUS_SASL
44 #ifdef HAVE_SASL_SASL_H
45 #include <sasl/sasl.h>
46 #else
47 #include <sasl.h>
48 #endif
49 #endif
50 
51 #include <ldap.h>
52 
53 #include "ldif.h"
54 #include "lutil.h"
55 #include "lutil_ldap.h"
56 #include "ldap_defaults.h"
57 #include "ldap_pvt.h"
58 #include "lber_pvt.h"
59 
60 #include "common.h"
61 
62 /* input-related vars */
63 
64 /* misc. parameters */
65 tool_type_t         tool_type;
66 int                 contoper = 0;
67 int                 debug = 0;
68 char                *infile = NULL;
69 int                 dont = 0;
70 int                 nocanon = 0;
71 int                 referrals = 0;
72 int                 verbose = 0;
73 int                 ldif = 0;
74 ber_len_t ldif_wrap = 0;
75 char                *prog = NULL;
76 
77 /* connection */
78 char                *ldapuri = NULL;
79 int                 use_tls = 0;
80 int                 protocol = -1;
81 int                 version = 0;
82 
83 /* authc/authz */
84 int                 authmethod = -1;
85 char                *binddn = NULL;
86 int                 want_bindpw = 0;
87 struct berval       passwd = { 0, NULL };
88 char                *pw_file = NULL;
89 #ifdef HAVE_CYRUS_SASL
90 unsigned  sasl_flags = LDAP_SASL_AUTOMATIC;
91 char                *sasl_realm = NULL;
92 char                *sasl_authc_id = NULL;
93 char                *sasl_authz_id = NULL;
94 char                *sasl_mech = NULL;
95 char                *sasl_secprops = NULL;
96 #endif
97 
98 /* controls */
99 int                 assertctl;
100 char                *assertion = NULL;
101 struct berval       assertionvalue = BER_BVNULL;
102 char                *authzid = NULL;
103 int                 authzcrit = 1;
104 /* support deprecated early version of proxyAuthz */
105 #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ         "2.16.840.1.113730.3.4.12"
106 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
107 char                *proxydn = NULL;
108 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
109 int                 manageDIT = 0;
110 int                 manageDSAit = 0;
111 int                 noop = 0;
112 int                 ppolicy = 0;
113 int                 preread = 0;
114 static char         *preread_attrs = NULL;
115 int                 postread = 0;
116 static char         *postread_attrs = NULL;
117 ber_int_t pr_morePagedResults = 1;
118 struct berval       pr_cookie = { 0, NULL };
119 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
120 int                 chaining = 0;
121 static int          chainingResolve = -1;
122 static int          chainingContinuation = -1;
123 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
124 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
125 static int          sessionTracking = 0;
126 static char         *sessionTrackingName;
127 struct berval       stValue;
128 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
129 ber_int_t vlvPos;
130 ber_int_t vlvCount;
131 struct berval *vlvContext;
132 static int          bauthzid;
133 
134 LDAPControl         *unknown_ctrls = NULL;
135 int                 unknown_ctrls_num = 0;
136 
137 /* options */
138 struct timeval      nettimeout = { -1 , 0 };
139 
140 typedef int (*print_ctrl_fn)( LDAP *ld, LDAPControl *ctrl );
141 
142 static int print_preread( LDAP *ld, LDAPControl *ctrl );
143 static int print_postread( LDAP *ld, LDAPControl *ctrl );
144 static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
145 static int print_psearch( LDAP *ld, LDAPControl *ctrl );
146 #ifdef LDAP_CONTROL_AUTHZID_RESPONSE
147 static int print_authzid( LDAP *ld, LDAPControl *ctrl );
148 #endif
149 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
150 static int print_ppolicy( LDAP *ld, LDAPControl *ctrl );
151 #endif
152 static int print_sss( LDAP *ld, LDAPControl *ctrl );
153 static int print_vlv( LDAP *ld, LDAPControl *ctrl );
154 #ifdef LDAP_CONTROL_X_DEREF
155 static int print_deref( LDAP *ld, LDAPControl *ctrl );
156 #endif
157 #ifdef LDAP_CONTROL_X_WHATFAILED
158 static int print_whatfailed( LDAP *ld, LDAPControl *ctrl );
159 #endif
160 static int print_syncstate( LDAP *ld, LDAPControl *ctrl );
161 static int print_syncdone( LDAP *ld, LDAPControl *ctrl );
162 #ifdef LDAP_CONTROL_X_DIRSYNC
163 static int print_dirsync( LDAP *ld, LDAPControl *ctrl );
164 #endif
165 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
166 static int print_account_usability( LDAP *ld, LDAPControl *ctrl );
167 #endif
168 #ifdef LDAP_CONTROL_X_PASSWORD_EXPIRED
169 static int print_netscape_pwexpired( LDAP *ld, LDAPControl *ctrl );
170 static int print_netscape_pwexpiring( LDAP *ld, LDAPControl *ctrl );
171 #endif
172 
173 static struct tool_ctrls_t {
174           const char          *oid;
175           unsigned  mask;
176           print_ctrl_fn       func;
177 } tool_ctrl_response[] = {
178           { LDAP_CONTROL_PRE_READ,                          TOOL_ALL, print_preread },
179           { LDAP_CONTROL_POST_READ,                         TOOL_ALL, print_postread },
180           { LDAP_CONTROL_PAGEDRESULTS,                      TOOL_SEARCH,        print_paged_results },
181           { LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE,                           TOOL_SEARCH,        print_psearch },
182 #ifdef LDAP_CONTROL_AUTHZID_RESPONSE
183           /* this is generally deprecated in favor of LDAP WhoAmI? operation, hence only supported as a VC inner control */
184           { LDAP_CONTROL_AUTHZID_RESPONSE,                  TOOL_VC,  print_authzid },
185 #endif
186 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
187           { LDAP_CONTROL_PASSWORDPOLICYRESPONSE,            TOOL_ALL, print_ppolicy },
188 #endif
189           { LDAP_CONTROL_SORTRESPONSE,  TOOL_SEARCH,        print_sss },
190           { LDAP_CONTROL_VLVRESPONSE,             TOOL_SEARCH,        print_vlv },
191 #ifdef LDAP_CONTROL_X_DEREF
192           { LDAP_CONTROL_X_DEREF,                                     TOOL_SEARCH,        print_deref },
193 #endif
194 #ifdef LDAP_CONTROL_X_WHATFAILED
195           { LDAP_CONTROL_X_WHATFAILED,                      TOOL_ALL, print_whatfailed },
196 #endif
197           { LDAP_CONTROL_SYNC_STATE,                        TOOL_SEARCH,        print_syncstate },
198           { LDAP_CONTROL_SYNC_DONE,                         TOOL_SEARCH,        print_syncdone },
199 #ifdef LDAP_CONTROL_X_DIRSYNC
200           { LDAP_CONTROL_X_DIRSYNC,                         TOOL_SEARCH,        print_dirsync },
201 #endif
202 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
203           { LDAP_CONTROL_X_ACCOUNT_USABILITY,               TOOL_SEARCH,        print_account_usability },
204 #endif
205 #ifdef LDAP_CONTROL_X_PASSWORD_EXPIRED
206           { LDAP_CONTROL_X_PASSWORD_EXPIRED,                TOOL_ALL, print_netscape_pwexpired },
207           { LDAP_CONTROL_X_PASSWORD_EXPIRING,               TOOL_ALL, print_netscape_pwexpiring },
208 #endif
209           { NULL,                                                     0,                  NULL }
210 };
211 
212 /* "features" */
213 enum { Intr_None = 0, Intr_Abandon, Intr_Cancel, Intr_Ignore };
214 static volatile sig_atomic_t  gotintr, abcan;
215 
216 int backlog;
217 
218 
219 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
220 static int
st_value(LDAP * ld,struct berval * value)221 st_value( LDAP *ld, struct berval *value )
222 {
223           char                *ip = NULL, *name = NULL;
224           struct berval       id = { 0 };
225           char                namebuf[ MAXHOSTNAMELEN ];
226 
227           if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) {
228                     struct hostent      *h;
229                     struct in_addr      addr;
230 
231                     name = namebuf;
232 
233                     h = gethostbyname( name );
234                     if ( h != NULL ) {
235                               AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) );
236                               ip = inet_ntoa( addr );
237                     }
238           }
239 
240           if ( sessionTrackingName != NULL ) {
241                     ber_str2bv( sessionTrackingName , 0, 0, &id );
242           } else
243 #ifdef HAVE_CYRUS_SASL
244           if ( sasl_authz_id != NULL ) {
245                     ber_str2bv( sasl_authz_id, 0, 0, &id );
246 
247           } else if ( sasl_authc_id != NULL ) {
248                     ber_str2bv( sasl_authc_id, 0, 0, &id );
249 
250           } else
251 #endif /* HAVE_CYRUS_SASL */
252           if ( binddn != NULL ) {
253                     ber_str2bv( binddn, 0, 0, &id );
254           }
255 
256           if ( ldap_create_session_tracking_value( ld,
257                     ip, name, LDAP_CONTROL_X_SESSION_TRACKING_USERNAME,
258                     &id, &stValue ) )
259           {
260                     fprintf( stderr, _("Session tracking control encoding error!\n") );
261                     return -1;
262           }
263 
264           return 0;
265 }
266 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
267 
268 RETSIGTYPE
do_sig(int sig)269 do_sig( int sig )
270 {
271           gotintr = abcan;
272 }
273 
274 void
tool_init(tool_type_t type)275 tool_init( tool_type_t type )
276 {
277           tool_type = type;
278           ldap_pvt_setlocale(LC_MESSAGES, "");
279           ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE, LDAP_LOCALEDIR);
280           ldap_pvt_textdomain(OPENLDAP_PACKAGE);
281 }
282 
283 void
tool_destroy(void)284 tool_destroy( void )
285 {
286           static int destroyed;
287           if ( destroyed++ )
288                     return;
289 
290 #ifdef HAVE_CYRUS_SASL
291           sasl_done();
292 #endif
293 #ifdef HAVE_TLS
294           ldap_pvt_tls_destroy();
295 #endif
296 
297           if ( ldapuri != NULL ) {
298                     ber_memfree( ldapuri );
299                     ldapuri = NULL;
300           }
301 
302           if ( pr_cookie.bv_val != NULL ) {
303                     ber_memfree( pr_cookie.bv_val );
304                     BER_BVZERO( &pr_cookie );
305           }
306 
307           if ( passwd.bv_val != NULL ) {
308                     ber_memfree( passwd.bv_val );
309                     BER_BVZERO( &passwd );
310           }
311 
312 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
313           if ( !BER_BVISNULL( &stValue ) ) {
314                     ber_memfree( stValue.bv_val );
315                     BER_BVZERO( &stValue );
316           }
317 
318 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
319 }
320 
321 void
tool_common_usage(void)322 tool_common_usage( void )
323 {
324           static const char *const descriptions[] = {
325 N_("  -d level   set LDAP debugging level to `level'\n"),
326 N_("  -D binddn  bind DN\n"),
327 N_("  -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n")
328 N_("             [!]assert=<filter>     (RFC 4528; a RFC 4515 Filter string)\n")
329 N_("             [!]authzid=<authzid>   (RFC 4370; \"dn:<dn>\" or \"u:<user>\")\n")
330 N_("             [!]bauthzid            (RFC 3829)\n")
331 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
332 #if 0
333                  /* non-advertized support for proxyDN */
334 N_("             [!]proxydn=<dn>        (a RFC 4514 DN string)\n")
335 #endif
336 #endif
337 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
338 N_("             [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
339 N_("                     one of \"chainingPreferred\", \"chainingRequired\",\n")
340 N_("                     \"referralsPreferred\", \"referralsRequired\"\n")
341 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
342 N_("             [!]manageDSAit         (RFC 3296)\n")
343 N_("             [!]noop\n")
344 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
345 N_("             ppolicy\n")
346 #endif
347 N_("             [!]postread[=<attrs>]  (RFC 4527; comma-separated attr list)\n")
348 N_("             [!]preread[=<attrs>]   (RFC 4527; comma-separated attr list)\n")
349 N_("             [!]relax\n")
350 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
351 N_("             [!]sessiontracking[=<username>]\n")
352 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
353 N_("             abandon, cancel, ignore (SIGINT sends abandon/cancel,\n"
354    "             or ignores response; if critical, doesn't wait for SIGINT.\n"
355    "             not really controls)\n")
356 N_("  -H URI     LDAP Uniform Resource Identifier(s)\n"),
357 N_("  -I         use SASL Interactive mode\n"),
358 N_("  -n         show what would be done but don't actually do it\n"),
359 N_("  -N         do not use reverse DNS to canonicalize SASL host name\n"),
360 N_("  -O props   SASL security properties\n"),
361 N_("  -o <opt>[=<optparam>] any libldap ldap.conf options, plus\n"),
362 N_("             ldif_wrap=<width> (in columns, or \"no\" for no wrapping)\n"),
363 N_("             nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"),
364 N_("  -Q         use SASL Quiet mode\n"),
365 N_("  -R realm   SASL realm\n"),
366 N_("  -U authcid SASL authentication identity\n"),
367 N_("  -v         run in verbose mode (diagnostics to standard output)\n"),
368 N_("  -V         print version info (-VV only)\n"),
369 N_("  -w passwd  bind password (for simple authentication)\n"),
370 N_("  -W         prompt for bind password\n"),
371 N_("  -x         Simple authentication\n"),
372 N_("  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
373 N_("  -y file    Read password from file\n"),
374 N_("  -Y mech    SASL mechanism\n"),
375 N_("  -Z         Start TLS request (-ZZ to require successful response)\n"),
376 NULL
377           };
378           const char *const *cpp;
379 
380           fputs( _("Common options:\n"), stderr );
381           for( cpp = descriptions; *cpp != NULL; cpp++ ) {
382                     if( strchr( options, (*cpp)[3] ) || (*cpp)[3] == ' ' ) {
383                               fputs( _(*cpp), stderr );
384                     }
385           }
386 
387           tool_destroy();
388 }
389 
tool_perror(const char * func,int err,const char * extra,const char * matched,const char * info,char ** refs)390 void tool_perror(
391           const char *func,
392           int err,
393           const char *extra,
394           const char *matched,
395           const char *info,
396           char **refs )
397 {
398           fprintf( stderr, "%s: %s (%d)%s\n",
399                     func, ldap_err2string( err ), err, extra ? extra : "" );
400 
401           if ( matched && *matched ) {
402                     fprintf( stderr, _("\tmatched DN: %s\n"), matched );
403           }
404 
405           if ( info && *info ) {
406                     fprintf( stderr, _("\tadditional info: %s\n"), info );
407           }
408 
409           if ( refs && *refs ) {
410                     int i;
411                     fprintf( stderr, _("\treferrals:\n") );
412                     for( i=0; refs[i]; i++ ) {
413                               fprintf( stderr, "\t\t%s\n", refs[i] );
414                     }
415           }
416 }
417 
418 
419 void
tool_args(int argc,char ** argv)420 tool_args( int argc, char **argv )
421 {
422           int i;
423 
424           while (( i = getopt( argc, argv, options )) != EOF ) {
425                     int crit, ival;
426                     char *control, *cvalue, *next;
427                     switch( i ) {
428                     case 'c': /* continuous operation mode */
429                               contoper++;
430                               break;
431                     case 'C': /* referrals: obsolete */
432                               referrals++;
433                               break;
434                     case 'd':
435                               ival = strtol( optarg, &next, 10 );
436                               if (next == NULL || next[0] != '\0') {
437                                         fprintf( stderr, "%s: unable to parse debug value \"%s\"\n", prog, optarg);
438                                         exit(EXIT_FAILURE);
439                               }
440                               debug |= ival;
441                               break;
442                     case 'D': /* bind DN */
443                               if( binddn != NULL ) {
444                                         fprintf( stderr, "%s: -D previously specified\n", prog );
445                                         exit( EXIT_FAILURE );
446                               }
447                               binddn = optarg;
448                               break;
449                     case 'e': /* general extensions (controls and such) */
450                               /* should be extended to support comma separated list of
451                                *        [!]key[=value] parameters, e.g.  -e !foo,bar=567
452                                */
453 
454                               crit = 0;
455                               cvalue = NULL;
456                               while ( optarg[0] == '!' ) {
457                                         crit++;
458                                         optarg++;
459                               }
460 
461                               control = optarg;
462                               if ( (cvalue = strchr( control, '=' )) != NULL ) {
463                                         *cvalue++ = '\0';
464                               }
465 
466                               if ( strcasecmp( control, "assert" ) == 0 ) {
467                                         if( assertctl ) {
468                                                   fprintf( stderr, "assert control previously specified\n");
469                                                   exit( EXIT_FAILURE );
470                                         }
471                                         if( cvalue == NULL ) {
472                                                   fprintf( stderr, "assert: control value expected\n" );
473                                                   usage();
474                                         }
475 
476                                         assertctl = 1 + crit;
477 
478                                         assert( assertion == NULL );
479                                         assertion = cvalue;
480 
481                               } else if ( strcasecmp( control, "authzid" ) == 0 ) {
482                                         if( authzid != NULL ) {
483                                                   fprintf( stderr, "authzid control previously specified\n");
484                                                   exit( EXIT_FAILURE );
485                                         }
486 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
487                                         if( proxydn != NULL ) {
488                                                   fprintf( stderr, "authzid control incompatible with proxydn\n");
489                                                   exit( EXIT_FAILURE );
490                                         }
491 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
492                                         if( cvalue == NULL ) {
493                                                   fprintf( stderr, "authzid: control value expected\n" );
494                                                   usage();
495                                         }
496                                         if( !crit ) {
497                                                   fprintf( stderr, "authzid: must be marked critical\n" );
498                                                   usage();
499                                         } else if ( crit > 1 ) {
500                                                   /* purposely flag proxied authorization
501                                                    * as non-critical, to test DSA */
502                                                   authzcrit = 0;
503                                         }
504 
505                                         assert( authzid == NULL );
506                                         authzid = cvalue;
507 
508 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
509                               } else if ( strcasecmp( control, "proxydn" ) == 0 ) {
510                                         if( proxydn != NULL ) {
511                                                   fprintf( stderr, "proxydn control previously specified\n");
512                                                   exit( EXIT_FAILURE );
513                                         }
514                                         if( authzid != NULL ) {
515                                                   fprintf( stderr, "proxydn control incompatible with authzid\n");
516                                                   exit( EXIT_FAILURE );
517                                         }
518                                         if( cvalue == NULL ) {
519                                                   fprintf( stderr, "proxydn: control value expected\n" );
520                                                   usage();
521                                         }
522                                         if( !crit ) {
523                                                   fprintf( stderr, "proxydn: must be marked critical\n" );
524                                                   usage();
525                                         } else if ( crit > 1 ) {
526                                                   /* purposely flag proxied authorization
527                                                    * as non-critical, to test DSA */
528                                                   authzcrit = 0;
529                                         }
530 
531                                         assert( proxydn == NULL );
532                                         proxydn = cvalue;
533 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
534 
535                               } else if ( strcasecmp( control, "bauthzid" ) == 0 ) {
536                                         if( bauthzid ) {
537                                                   fprintf( stderr, "bauthzid control previously specified\n");
538                                                   exit( EXIT_FAILURE );
539                                         }
540                                         if( cvalue != NULL ) {
541                                                   fprintf( stderr, "bauthzid: no control value expected\n" );
542                                                   usage();
543                                         }
544                                         bauthzid = 1 + crit;
545 
546                               } else if ( ( strcasecmp( control, "relax" ) == 0 ) ||
547                                         ( strcasecmp( control, "manageDIT" ) == 0 ) )
548                               {
549                                         if( manageDIT ) {
550                                                   fprintf( stderr,
551                                                             "relax control previously specified\n");
552                                                   exit( EXIT_FAILURE );
553                                         }
554                                         if( cvalue != NULL ) {
555                                                   fprintf( stderr,
556                                                             "relax: no control value expected\n" );
557                                                   usage();
558                                         }
559 
560                                         manageDIT = 1 + crit;
561 
562                               } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
563                                         if( manageDSAit ) {
564                                                   fprintf( stderr,
565                                                             "manageDSAit control previously specified\n");
566                                                   exit( EXIT_FAILURE );
567                                         }
568                                         if( cvalue != NULL ) {
569                                                   fprintf( stderr,
570                                                             "manageDSAit: no control value expected\n" );
571                                                   usage();
572                                         }
573 
574                                         manageDSAit = 1 + crit;
575 
576                               } else if ( strcasecmp( control, "noop" ) == 0 ) {
577                                         if( noop ) {
578                                                   fprintf( stderr, "noop control previously specified\n");
579                                                   exit( EXIT_FAILURE );
580                                         }
581                                         if( cvalue != NULL ) {
582                                                   fprintf( stderr, "noop: no control value expected\n" );
583                                                   usage();
584                                         }
585 
586                                         noop = 1 + crit;
587 
588 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
589                               } else if ( strcasecmp( control, "ppolicy" ) == 0 ) {
590                                         if( ppolicy ) {
591                                                   fprintf( stderr, "ppolicy control previously specified\n");
592                                                   exit( EXIT_FAILURE );
593                                         }
594                                         if( cvalue != NULL ) {
595                                                   fprintf( stderr, "ppolicy: no control value expected\n" );
596                                                   usage();
597                                         }
598                                         if( crit ) {
599                                                   fprintf( stderr, "ppolicy: critical flag not allowed\n" );
600                                                   usage();
601                                         }
602 
603                                         ppolicy = 1;
604 #endif
605 
606                               } else if ( strcasecmp( control, "preread" ) == 0 ) {
607                                         if( preread ) {
608                                                   fprintf( stderr, "preread control previously specified\n");
609                                                   exit( EXIT_FAILURE );
610                                         }
611 
612                                         preread = 1 + crit;
613                                         preread_attrs = cvalue;
614 
615                               } else if ( strcasecmp( control, "postread" ) == 0 ) {
616                                         if( postread ) {
617                                                   fprintf( stderr, "postread control previously specified\n");
618                                                   exit( EXIT_FAILURE );
619                                         }
620 
621                                         postread = 1 + crit;
622                                         postread_attrs = cvalue;
623 
624 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
625                               } else if ( strcasecmp( control, "chaining" ) == 0 ) {
626                                         if ( chaining ) {
627                                                   fprintf( stderr, "chaining control previously specified\n");
628                                                   exit( EXIT_FAILURE );
629                                         }
630 
631                                         chaining = 1 + crit;
632 
633                                         if ( cvalue != NULL ) {
634                                                   char      *continuation;
635 
636                                                   continuation = strchr( cvalue, '/' );
637                                                   if ( continuation ) {
638                                                             /* FIXME: this makes sense only in searches */
639                                                             *continuation++ = '\0';
640                                                             if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
641                                                                       chainingContinuation = LDAP_CHAINING_PREFERRED;
642                                                             } else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
643                                                                       chainingContinuation = LDAP_CHAINING_REQUIRED;
644                                                             } else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
645                                                                       chainingContinuation = LDAP_REFERRALS_PREFERRED;
646                                                             } else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
647                                                                       chainingContinuation = LDAP_REFERRALS_REQUIRED;
648                                                             } else {
649                                                                       fprintf( stderr,
650                                                                                 "chaining behavior control "
651                                                                                 "continuation value \"%s\" invalid\n",
652                                                                                 continuation );
653                                                                       exit( EXIT_FAILURE );
654                                                             }
655                                                   }
656 
657                                                   if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
658                                                             chainingResolve = LDAP_CHAINING_PREFERRED;
659                                                   } else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
660                                                             chainingResolve = LDAP_CHAINING_REQUIRED;
661                                                   } else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
662                                                             chainingResolve = LDAP_REFERRALS_PREFERRED;
663                                                   } else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
664                                                             chainingResolve = LDAP_REFERRALS_REQUIRED;
665                                                   } else {
666                                                             fprintf( stderr,
667                                                                       "chaining behavior control "
668                                                                       "resolve value \"%s\" invalid\n",
669                                                                       cvalue);
670                                                             exit( EXIT_FAILURE );
671                                                   }
672                                         }
673 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
674 
675 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
676                               } else if ( strcasecmp( control, "sessiontracking" ) == 0 ) {
677                                         if ( sessionTracking ) {
678                                                   fprintf( stderr, "%s: session tracking can be only specified once\n", prog );
679                                                   exit( EXIT_FAILURE );
680                                         }
681                                         sessionTracking = 1;
682                                         if ( crit ) {
683                                                   fprintf( stderr, "sessiontracking: critical flag not allowed\n" );
684                                                   usage();
685                                         }
686                                         if ( cvalue ) {
687                                                   sessionTrackingName = cvalue;
688                                         }
689 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
690 
691                               /* this shouldn't go here, really; but it's a feature... */
692                               } else if ( strcasecmp( control, "abandon" ) == 0 ) {
693                                         abcan = Intr_Abandon;
694                                         if ( crit ) {
695                                                   gotintr = abcan;
696                                         }
697 
698                               } else if ( strcasecmp( control, "cancel" ) == 0 ) {
699                                         abcan = Intr_Cancel;
700                                         if ( crit ) {
701                                                   gotintr = abcan;
702                                         }
703 
704                               } else if ( strcasecmp( control, "ignore" ) == 0 ) {
705                                         abcan = Intr_Ignore;
706                                         if ( crit ) {
707                                                   gotintr = abcan;
708                                         }
709 
710                               } else if ( strcasecmp( control, "backlog" ) == 0 ) {
711                                         /* special search: accumulate lots of responses
712                                          * but don't read any, force slapd writer to wait.
713                                          * Then abandon the search and issue a new one.
714                                          */
715                                         backlog = 1;
716 
717                               } else if ( tool_is_oid( control ) ) {
718                                         LDAPControl         *tmpctrls, ctrl;
719 
720                                         if ( unknown_ctrls != NULL ) {
721                                                   int i;
722                                                   for ( i = 0; unknown_ctrls[ i ].ldctl_oid != NULL; i++ ) {
723                                                             if ( strcmp( control, unknown_ctrls[ i ].ldctl_oid ) == 0 ) {
724                                                                       fprintf( stderr, "%s control previously specified\n", control );
725                                                                       exit( EXIT_FAILURE );
726                                                             }
727                                                   }
728                                         }
729 
730                                         tmpctrls = (LDAPControl *)ber_memrealloc( unknown_ctrls,
731                                                   (unknown_ctrls_num + 1)*sizeof( LDAPControl ) );
732                                         if ( tmpctrls == NULL ) {
733                                                   fprintf( stderr, "%s: no memory?\n", prog );
734                                                   exit( EXIT_FAILURE );
735                                         }
736                                         unknown_ctrls = tmpctrls;
737                                         ctrl.ldctl_oid = control;
738                                         ctrl.ldctl_value.bv_val = NULL;
739                                         ctrl.ldctl_value.bv_len = 0;
740                                         ctrl.ldctl_iscritical = crit;
741 
742                                         if ( cvalue != NULL ) {
743                                                   struct berval       bv;
744                                                   size_t              len = strlen( cvalue );
745                                                   int                 retcode;
746 
747                                                   bv.bv_len = LUTIL_BASE64_DECODE_LEN( len );
748                                                   bv.bv_val = ber_memalloc( bv.bv_len + 1 );
749 
750                                                   retcode = lutil_b64_pton( cvalue,
751                                                             (unsigned char *)bv.bv_val,
752                                                             bv.bv_len );
753 
754                                                   if ( retcode == -1 || (unsigned) retcode > bv.bv_len ) {
755                                                             fprintf( stderr, "Unable to parse value of general control %s\n",
756                                                                       control );
757                                                             usage();
758                                                   }
759 
760                                                   bv.bv_len = retcode;
761                                                   ctrl.ldctl_value = bv;
762                                         }
763 
764                                         /* don't free it */
765                                         control = NULL;
766                                         unknown_ctrls[ unknown_ctrls_num ] = ctrl;
767                                         unknown_ctrls_num++;
768 
769                               } else {
770                                         fprintf( stderr, "Invalid general control name: %s\n",
771                                                   control );
772                                         usage();
773                               }
774                               break;
775                     case 'f': /* read from file */
776                               if( infile != NULL ) {
777                                         fprintf( stderr, "%s: -f previously specified\n", prog );
778                                         exit( EXIT_FAILURE );
779                               }
780                               infile = optarg;
781                               break;
782                     case 'H': /* ldap URI */
783                               if( ldapuri != NULL ) {
784                                         fprintf( stderr, "%s: -H previously specified\n", prog );
785                                         exit( EXIT_FAILURE );
786                               }
787                               ldapuri = ber_strdup( optarg );
788                               break;
789                     case 'I':
790 #ifdef HAVE_CYRUS_SASL
791                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
792                                         fprintf( stderr, "%s: incompatible previous "
793                                                   "authentication choice\n",
794                                                   prog );
795                                         exit( EXIT_FAILURE );
796                               }
797                               authmethod = LDAP_AUTH_SASL;
798                               sasl_flags = LDAP_SASL_INTERACTIVE;
799                               break;
800 #else
801                               fprintf( stderr, "%s: was not compiled with SASL support\n",
802                                         prog );
803                               exit( EXIT_FAILURE );
804 #endif
805                     case 'M':
806                               /* enable Manage DSA IT */
807                               manageDSAit++;
808                               break;
809                     case 'n': /* print operations, don't actually do them */
810                               dont++;
811                               break;
812                     case 'N':
813                               nocanon++;
814                               break;
815                     case 'o':
816                               control = optarg;
817                               if ( (cvalue = strchr( control, '=' )) != NULL ) {
818                                         *cvalue++ = '\0';
819                               }
820                               for ( next=control; *next; next++ ) {
821                                         if ( *next == '-' ) {
822                                                   *next = '_';
823                                         }
824                               }
825 
826                               if ( strcasecmp( control, "nettimeout" ) == 0 ) {
827                                         if( nettimeout.tv_sec != -1 ) {
828                                                   fprintf( stderr, "nettimeout option previously specified\n");
829                                                   exit( EXIT_FAILURE );
830                                         }
831                                         if( cvalue == NULL || cvalue[0] == '\0' ) {
832                                                   fprintf( stderr, "nettimeout: option value expected\n" );
833                                                   usage();
834                                         }
835                                         if ( strcasecmp( cvalue, "none" ) == 0 ) {
836                                                   nettimeout.tv_sec = 0;
837                                         } else if ( strcasecmp( cvalue, "max" ) == 0 ) {
838                                                   nettimeout.tv_sec = LDAP_MAXINT;
839                                         } else {
840                                                   ival = strtol( cvalue, &next, 10 );
841                                                   if ( next == NULL || next[0] != '\0' ) {
842                                                             fprintf( stderr,
843                                                                       _("Unable to parse network timeout \"%s\"\n"), cvalue );
844                                                             exit( EXIT_FAILURE );
845                                                   }
846                                                   nettimeout.tv_sec = ival;
847                                         }
848                                         if( nettimeout.tv_sec < 0 || nettimeout.tv_sec > LDAP_MAXINT ) {
849                                                   fprintf( stderr, _("%s: invalid network timeout (%ld) specified\n"),
850                                                             prog, (long)nettimeout.tv_sec );
851                                                   exit( EXIT_FAILURE );
852                                         }
853 
854                               } else if ( strcasecmp( control, "ldif_wrap" ) == 0 ) {
855                                         if ( cvalue == 0 ) {
856                                                   ldif_wrap = LDIF_LINE_WIDTH;
857 
858                                         } else if ( strcasecmp( cvalue, "no" ) == 0 ) {
859                                                   ldif_wrap = LDIF_LINE_WIDTH_MAX;
860 
861                                         } else {
862                                                   unsigned int u;
863                                                   if ( lutil_atou( &u, cvalue ) ) {
864                                                             fprintf( stderr,
865                                                                       _("Unable to parse ldif_wrap=\"%s\"\n"), cvalue );
866                                                             exit( EXIT_FAILURE );
867                                                   }
868                                                   ldif_wrap = (ber_len_t)u;
869                                         }
870 
871                               } else if ( ldap_pvt_conf_option( control, cvalue, 1 ) ) {
872                                         fprintf( stderr, "Invalid general option name: %s\n",
873                                                   control );
874                                         usage();
875                               }
876                               break;
877                     case 'O':
878 #ifdef HAVE_CYRUS_SASL
879                               if( sasl_secprops != NULL ) {
880                                         fprintf( stderr, "%s: -O previously specified\n", prog );
881                                         exit( EXIT_FAILURE );
882                               }
883                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
884                                         fprintf( stderr, "%s: incompatible previous "
885                                                   "authentication choice\n", prog );
886                                         exit( EXIT_FAILURE );
887                               }
888                               authmethod = LDAP_AUTH_SASL;
889                               sasl_secprops = optarg;
890 #else
891                               fprintf( stderr, "%s: not compiled with SASL support\n", prog );
892                               exit( EXIT_FAILURE );
893 #endif
894                               break;
895                     case 'P':
896                               ival = strtol( optarg, &next, 10 );
897                               if ( next == NULL || next[0] != '\0' ) {
898                                         fprintf( stderr, "%s: unable to parse protocol version \"%s\"\n", prog, optarg );
899                                         exit( EXIT_FAILURE );
900                               }
901                               switch( ival ) {
902                               case 2:
903                                         if( protocol == LDAP_VERSION3 ) {
904                                                   fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
905                                                             prog, protocol );
906                                                   exit( EXIT_FAILURE );
907                                         }
908                                         protocol = LDAP_VERSION2;
909                                         break;
910                               case 3:
911                                         if( protocol == LDAP_VERSION2 ) {
912                                                   fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
913                                                             prog, protocol );
914                                                   exit( EXIT_FAILURE );
915                                         }
916                                         protocol = LDAP_VERSION3;
917                                         break;
918                               default:
919                                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
920                                                   prog );
921                                         usage();
922                               }
923                               break;
924                     case 'Q':
925 #ifdef HAVE_CYRUS_SASL
926                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
927                                         fprintf( stderr, "%s: incompatible previous "
928                                                   "authentication choice\n",
929                                                   prog );
930                                         exit( EXIT_FAILURE );
931                               }
932                               authmethod = LDAP_AUTH_SASL;
933                               sasl_flags = LDAP_SASL_QUIET;
934                               break;
935 #else
936                               fprintf( stderr, "%s: not compiled with SASL support\n",
937                                         prog );
938                               exit( EXIT_FAILURE );
939 #endif
940                     case 'R':
941 #ifdef HAVE_CYRUS_SASL
942                               if( sasl_realm != NULL ) {
943                                         fprintf( stderr, "%s: -R previously specified\n", prog );
944                                         exit( EXIT_FAILURE );
945                               }
946                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
947                                         fprintf( stderr, "%s: incompatible previous "
948                                                   "authentication choice\n",
949                                                   prog );
950                                         exit( EXIT_FAILURE );
951                               }
952                               authmethod = LDAP_AUTH_SASL;
953                               sasl_realm = optarg;
954 #else
955                               fprintf( stderr, "%s: not compiled with SASL support\n",
956                                         prog );
957                               exit( EXIT_FAILURE );
958 #endif
959                               break;
960                     case 'U':
961 #ifdef HAVE_CYRUS_SASL
962                               if( sasl_authc_id != NULL ) {
963                                         fprintf( stderr, "%s: -U previously specified\n", prog );
964                                         exit( EXIT_FAILURE );
965                               }
966                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
967                                         fprintf( stderr, "%s: incompatible previous "
968                                                   "authentication choice\n",
969                                                   prog );
970                                         exit( EXIT_FAILURE );
971                               }
972                               authmethod = LDAP_AUTH_SASL;
973                               sasl_authc_id = optarg;
974 #else
975                               fprintf( stderr, "%s: not compiled with SASL support\n",
976                                         prog );
977                               exit( EXIT_FAILURE );
978 #endif
979                               break;
980                     case 'v': /* verbose mode */
981                               verbose++;
982                               break;
983                     case 'V': /* version */
984                               version++;
985                               break;
986                     case 'w': /* password */
987                               passwd.bv_val = ber_strdup( optarg );
988                               {
989                                         char* p;
990 
991                                         for( p = optarg; *p != '\0'; p++ ) {
992                                                   *p = '\0';
993                                         }
994                               }
995                               passwd.bv_len = strlen( passwd.bv_val );
996                               break;
997                     case 'W':
998                               want_bindpw++;
999                               break;
1000                     case 'y':
1001                               pw_file = optarg;
1002                               break;
1003                     case 'Y':
1004 #ifdef HAVE_CYRUS_SASL
1005                               if( sasl_mech != NULL ) {
1006                                         fprintf( stderr, "%s: -Y previously specified\n", prog );
1007                                         exit( EXIT_FAILURE );
1008                               }
1009                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
1010                                         fprintf( stderr,
1011                                                   "%s: incompatible with authentication choice\n", prog );
1012                                         exit( EXIT_FAILURE );
1013                               }
1014                               authmethod = LDAP_AUTH_SASL;
1015                               sasl_mech = optarg;
1016 #else
1017                               fprintf( stderr, "%s: not compiled with SASL support\n", prog );
1018                               exit( EXIT_FAILURE );
1019 #endif
1020                               break;
1021                     case 'x':
1022                               if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
1023                                         fprintf( stderr, "%s: incompatible with previous "
1024                                                   "authentication choice\n", prog );
1025                                         exit( EXIT_FAILURE );
1026                               }
1027                               authmethod = LDAP_AUTH_SIMPLE;
1028                               break;
1029                     case 'X':
1030 #ifdef HAVE_CYRUS_SASL
1031                               if( sasl_authz_id != NULL ) {
1032                                         fprintf( stderr, "%s: -X previously specified\n", prog );
1033                                         exit( EXIT_FAILURE );
1034                               }
1035                               if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
1036                                         fprintf( stderr, "%s: -X incompatible with "
1037                                                   "authentication choice\n", prog );
1038                                         exit( EXIT_FAILURE );
1039                               }
1040                               authmethod = LDAP_AUTH_SASL;
1041                               sasl_authz_id = optarg;
1042 #else
1043                               fprintf( stderr, "%s: not compiled with SASL support\n", prog );
1044                               exit( EXIT_FAILURE );
1045 #endif
1046                               break;
1047                     case 'Z':
1048 #ifdef HAVE_TLS
1049                               use_tls++;
1050 #else
1051                               fprintf( stderr, "%s: not compiled with TLS support\n", prog );
1052                               exit( EXIT_FAILURE );
1053 #endif
1054                               break;
1055                     default:
1056                               if( handle_private_option( i ) ) break;
1057                               fprintf( stderr, "%s: unrecognized option -%c\n",
1058                                         prog, optopt );
1059                               usage();
1060                     }
1061           }
1062 
1063           {
1064                     /* prevent bad linking */
1065                     LDAPAPIInfo api;
1066                     api.ldapai_info_version = LDAP_API_INFO_VERSION;
1067 
1068                     if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
1069                               != LDAP_OPT_SUCCESS )
1070                     {
1071                               fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
1072                               exit( EXIT_FAILURE );
1073                     }
1074 
1075                     if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
1076                               fprintf( stderr, "LDAP APIInfo version mismatch: "
1077                                         "library %d, header %d\n",
1078                                         api.ldapai_info_version, LDAP_API_INFO_VERSION );
1079                               exit( EXIT_FAILURE );
1080                     }
1081 
1082                     if( api.ldapai_api_version != LDAP_API_VERSION ) {
1083                               fprintf( stderr, "LDAP API version mismatch: "
1084                                         "library %d, header %d\n",
1085                                         api.ldapai_api_version, LDAP_API_VERSION );
1086                               exit( EXIT_FAILURE );
1087                     }
1088 
1089                     if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
1090                               fprintf( stderr, "LDAP vendor name mismatch: "
1091                                         "library %s, header %s\n",
1092                                         api.ldapai_vendor_name, LDAP_VENDOR_NAME );
1093                               exit( EXIT_FAILURE );
1094                     }
1095 
1096                     if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
1097                               fprintf( stderr, "LDAP vendor version mismatch: "
1098                                         "library %d, header %d\n",
1099                                         api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
1100                               exit( EXIT_FAILURE );
1101                     }
1102 
1103                     if (version) {
1104                               fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
1105                                         prog, __Version,
1106                                         LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
1107                               if (version > 1) exit( EXIT_SUCCESS );
1108                     }
1109 
1110                     ldap_memfree( api.ldapai_vendor_name );
1111                     ber_memvfree( (void **)api.ldapai_extensions );
1112           }
1113 
1114           if (protocol == -1)
1115                     protocol = LDAP_VERSION3;
1116 
1117           if (authmethod == -1 && protocol > LDAP_VERSION2) {
1118 #ifdef HAVE_CYRUS_SASL
1119                     if ( binddn != NULL ) {
1120                               authmethod = LDAP_AUTH_SIMPLE;
1121                     } else {
1122                               authmethod = LDAP_AUTH_SASL;
1123                     }
1124 #else
1125                     authmethod = LDAP_AUTH_SIMPLE;
1126 #endif
1127           }
1128 
1129           if( protocol == LDAP_VERSION2 ) {
1130                     if( assertctl || authzid || manageDIT || manageDSAit ||
1131 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1132                               proxydn ||
1133 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1134 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1135                               chaining ||
1136 #endif
1137 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1138                               sessionTracking ||
1139 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1140                               noop || ppolicy || preread || postread )
1141                     {
1142                               fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
1143                               exit( EXIT_FAILURE );
1144                     }
1145 #ifdef HAVE_TLS
1146                     if( use_tls ) {
1147                               fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
1148                               exit( EXIT_FAILURE );
1149                     }
1150 #endif
1151 #ifdef HAVE_CYRUS_SASL
1152                     if( authmethod == LDAP_AUTH_SASL ) {
1153                               fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
1154                                         prog );
1155                               exit( EXIT_FAILURE );
1156                     }
1157 #endif
1158           }
1159 
1160           if ( ( pw_file || want_bindpw ) && !BER_BVISNULL( &passwd ) ) {
1161                     fprintf( stderr, "%s: -%c incompatible with -w\n",
1162                               prog, ( pw_file ? 'y' : 'W' ) );
1163                     exit( EXIT_FAILURE );
1164           }
1165 }
1166 
1167 
1168 LDAP *
tool_conn_setup(int dont,void (* private_setup)(LDAP *))1169 tool_conn_setup( int dont, void (*private_setup)( LDAP * ) )
1170 {
1171           LDAP *ld = NULL;
1172 
1173           if ( debug ) {
1174                     if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
1175                               != LBER_OPT_SUCCESS )
1176                     {
1177                               fprintf( stderr,
1178                                         "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
1179                     }
1180                     if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
1181                               != LDAP_OPT_SUCCESS )
1182                     {
1183                               fprintf( stderr,
1184                                         "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
1185                     }
1186           }
1187 
1188 #ifdef SIGPIPE
1189           (void) SIGNAL( SIGPIPE, SIG_IGN );
1190 #endif
1191 
1192           if ( abcan ) {
1193                     SIGNAL( SIGINT, do_sig );
1194           }
1195 
1196           if ( !dont ) {
1197                     int rc;
1198 
1199                     if ( ldapuri != NULL ) {
1200                               LDAPURLDesc         *ludlist, **ludp;
1201                               char                **urls = NULL;
1202                               int                 nurls = 0;
1203 
1204                               rc = ldap_url_parselist( &ludlist, ldapuri );
1205                               if ( rc != LDAP_URL_SUCCESS ) {
1206                                         fprintf( stderr,
1207                                                   "Could not parse LDAP URI(s)=%s (%d)\n",
1208                                                   ldapuri, rc );
1209                                         exit( EXIT_FAILURE );
1210                               }
1211 
1212                               for ( ludp = &ludlist; *ludp != NULL; ) {
1213                                         LDAPURLDesc         *lud = *ludp;
1214                                         char                **tmp;
1215 
1216                                         if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' &&
1217                                                   ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) )
1218                                         {
1219                                                   /* if no host but a DN is provided,
1220                                                    * use DNS SRV to gather the host list
1221                                                    * and turn it into a list of URIs
1222                                                    * using the scheme provided */
1223                                                   char      *domain = NULL,
1224                                                             *hostlist = NULL,
1225                                                             **hosts = NULL;
1226                                                   int       i,
1227                                                             len_proto = strlen( lud->lud_scheme );
1228 
1229                                                   if ( ldap_dn2domain( lud->lud_dn, &domain )
1230                                                             || domain == NULL )
1231                                                   {
1232                                                             fprintf( stderr,
1233                                                                       "DNS SRV: Could not turn "
1234                                                                       "DN=\"%s\" into a domain\n",
1235                                                                       lud->lud_dn );
1236                                                             goto dnssrv_free;
1237                                                   }
1238 
1239                                                   rc = ldap_domain2hostlist( domain, &hostlist );
1240                                                   if ( rc ) {
1241                                                             fprintf( stderr,
1242                                                                       "DNS SRV: Could not turn "
1243                                                                       "domain=%s into a hostlist\n",
1244                                                                       domain );
1245                                                             goto dnssrv_free;
1246                                                   }
1247 
1248                                                   hosts = ldap_str2charray( hostlist, " " );
1249                                                   if ( hosts == NULL ) {
1250                                                             fprintf( stderr,
1251                                                                       "DNS SRV: Could not parse "
1252                                                                       "hostlist=\"%s\"\n",
1253                                                                       hostlist );
1254                                                             goto dnssrv_free;
1255                                                   }
1256 
1257                                                   for ( i = 0; hosts[ i ] != NULL; i++ )
1258                                                             /* count'em */ ;
1259 
1260                                                   tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + i + 1 ) );
1261                                                   if ( tmp == NULL ) {
1262                                                             fprintf( stderr,
1263                                                                       "DNS SRV: out of memory?\n" );
1264                                                             goto dnssrv_free;
1265                                                   }
1266                                                   urls = tmp;
1267                                                   urls[ nurls ] = NULL;
1268 
1269                                                   for ( i = 0; hosts[ i ] != NULL; i++ ) {
1270                                                             size_t    len = len_proto
1271                                                                       + STRLENOF( "://" )
1272                                                                       + strlen( hosts[ i ] )
1273                                                                       + 1;
1274 
1275                                                             urls[ nurls + i + 1 ] = NULL;
1276                                                             urls[ nurls + i ] = (char *)malloc( sizeof( char ) * len );
1277                                                             if ( urls[ nurls + i ] == NULL ) {
1278                                                                       fprintf( stderr,
1279                                                                                 "DNS SRV: out of memory?\n" );
1280                                                                       goto dnssrv_free;
1281                                                             }
1282 
1283                                                             snprintf( urls[ nurls + i ], len, "%s://%s",
1284                                                                       lud->lud_scheme, hosts[ i ] );
1285                                                   }
1286                                                   nurls += i;
1287 
1288 dnssrv_free:;
1289                                                   ber_memvfree( (void **)hosts );
1290                                                   ber_memfree( hostlist );
1291                                                   ber_memfree( domain );
1292 
1293                                         } else {
1294                                                   tmp = (char **)ber_memrealloc( urls, sizeof( char * ) * ( nurls + 2 ) );
1295                                                   if ( tmp == NULL ) {
1296                                                             fprintf( stderr,
1297                                                                       "DNS SRV: out of memory?\n" );
1298                                                             break;
1299                                                   }
1300                                                   urls = tmp;
1301                                                   urls[ nurls + 1 ] = NULL;
1302 
1303                                                   urls[ nurls ] = ldap_url_desc2str( lud );
1304                                                   if ( urls[ nurls ] == NULL ) {
1305                                                             fprintf( stderr,
1306                                                                       "DNS SRV: out of memory?\n" );
1307                                                             break;
1308                                                   }
1309                                                   nurls++;
1310                                         }
1311 
1312                                         *ludp = lud->lud_next;
1313 
1314                                         lud->lud_next = NULL;
1315                                         ldap_free_urldesc( lud );
1316                               }
1317 
1318                               if ( ludlist != NULL ) {
1319                                         ldap_free_urllist( ludlist );
1320                                         exit( EXIT_FAILURE );
1321 
1322                               } else if ( urls == NULL ) {
1323                                         exit( EXIT_FAILURE );
1324                               }
1325 
1326                               ldap_memfree( ldapuri );
1327                               ldapuri = ldap_charray2str( urls, " " );
1328                               ber_memvfree( (void **)urls );
1329                     }
1330 
1331                     if ( verbose ) {
1332                               fprintf( stderr, "ldap_initialize( %s )\n",
1333                                         ldapuri != NULL ? ldapuri : "<DEFAULT>" );
1334                     }
1335                     rc = ldap_initialize( &ld, ldapuri );
1336                     if( rc != LDAP_SUCCESS ) {
1337                               fprintf( stderr,
1338                                         "Could not create LDAP session handle for URI=%s (%d): %s\n",
1339                                         ldapuri, rc, ldap_err2string(rc) );
1340                               exit( EXIT_FAILURE );
1341                     }
1342 
1343                     if( private_setup ) private_setup( ld );
1344 
1345                     /* referrals: obsolete */
1346                     if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
1347                               referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
1348                     {
1349                               fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
1350                                         referrals ? "on" : "off" );
1351                               tool_exit( ld, EXIT_FAILURE );
1352                     }
1353 
1354 #ifdef HAVE_CYRUS_SASL
1355                     /* canon */
1356                     if( nocanon ) {
1357                               if( ldap_set_option( ld, LDAP_OPT_X_SASL_NOCANON,
1358                                         LDAP_OPT_ON ) != LDAP_OPT_SUCCESS )
1359                               {
1360                                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_NOCANON on\n" );
1361                                         tool_exit( ld, EXIT_FAILURE );
1362                               }
1363                     }
1364 #endif
1365                     if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
1366                               != LDAP_OPT_SUCCESS )
1367                     {
1368                               fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
1369                                         protocol );
1370                               tool_exit( ld, EXIT_FAILURE );
1371                     }
1372 
1373 #ifdef HAVE_TLS
1374                     if ( use_tls ) {
1375                               rc = ldap_start_tls_s( ld, NULL, NULL );
1376                               if ( rc != LDAP_SUCCESS ) {
1377                                         char *msg=NULL;
1378                                         ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
1379                                         tool_perror( "ldap_start_tls", rc, NULL, NULL, msg, NULL );
1380                                         ldap_memfree(msg);
1381                                         if ( use_tls > 1 || rc < 0 ) {
1382                                                   tool_exit( ld, EXIT_FAILURE );
1383                                         }
1384                               }
1385                     }
1386 #endif
1387 
1388                     if ( nettimeout.tv_sec > 0 ) {
1389                               if ( ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, (void *) &nettimeout )
1390                                         != LDAP_OPT_SUCCESS )
1391                               {
1392                                         fprintf( stderr, "Could not set LDAP_OPT_NETWORK_TIMEOUT %ld\n",
1393                                                   (long)nettimeout.tv_sec );
1394                                         tool_exit( ld, EXIT_FAILURE );
1395                               }
1396                     }
1397           }
1398 
1399           return ld;
1400 }
1401 
1402 
1403 void
tool_bind(LDAP * ld)1404 tool_bind( LDAP *ld )
1405 {
1406           LDAPControl         **sctrlsp = NULL;
1407           LDAPControl         *sctrls[4];
1408           LDAPControl         sctrl[3];
1409           int                 nsctrls = 0;
1410 
1411           int rc, msgid;
1412           LDAPMessage *result = NULL;
1413 
1414           int err;
1415           char *matched = NULL;
1416           char *info = NULL;
1417           char **refs = NULL;
1418           LDAPControl **ctrls = NULL;
1419           char msgbuf[256];
1420 
1421           msgbuf[0] = 0;
1422 
1423 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1424           if ( ppolicy ) {
1425                     LDAPControl c;
1426                     c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
1427                     c.ldctl_value.bv_val = NULL;
1428                     c.ldctl_value.bv_len = 0;
1429                     c.ldctl_iscritical = 0;
1430                     sctrl[nsctrls] = c;
1431                     sctrls[nsctrls] = &sctrl[nsctrls];
1432                     sctrls[++nsctrls] = NULL;
1433           }
1434 #endif
1435 
1436           if ( bauthzid ) {
1437                     LDAPControl c;
1438 
1439                     c.ldctl_oid = LDAP_CONTROL_AUTHZID_REQUEST;
1440                     c.ldctl_iscritical = bauthzid > 1;
1441                     BER_BVZERO( &c.ldctl_value );
1442 
1443                     sctrl[nsctrls] = c;
1444                     sctrls[nsctrls] = &sctrl[nsctrls];
1445                     sctrls[++nsctrls] = NULL;
1446           }
1447 
1448 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1449           if ( sessionTracking ) {
1450                     LDAPControl c;
1451 
1452                     if ( BER_BVISNULL( &stValue) && st_value( ld, &stValue ) ) {
1453                               tool_exit( ld, EXIT_FAILURE );
1454                     }
1455 
1456                     c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
1457                     c.ldctl_iscritical = 0;
1458                     c.ldctl_value = stValue;
1459 
1460                     sctrl[nsctrls] = c;
1461                     sctrls[nsctrls] = &sctrl[nsctrls];
1462                     sctrls[++nsctrls] = NULL;
1463           }
1464 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1465 
1466           if ( nsctrls ) {
1467                     sctrlsp = sctrls;
1468           }
1469 
1470           assert( nsctrls < (int) (sizeof(sctrls)/sizeof(sctrls[0])) );
1471 
1472           if ( pw_file || want_bindpw ) {
1473                     assert( passwd.bv_val == NULL && passwd.bv_len == 0 );
1474 
1475                     if ( pw_file ) {
1476                               if ( lutil_get_filed_password( pw_file, &passwd ) ) {
1477                                         tool_exit( ld, EXIT_FAILURE );
1478                               }
1479 
1480                     } else {
1481                               char *pw = getpassphrase( _("Enter LDAP Password: ") );
1482                               if ( pw ) {
1483                                         passwd.bv_val = ber_strdup( pw );
1484                                         passwd.bv_len = strlen( passwd.bv_val );
1485                               }
1486                     }
1487           }
1488 
1489           if ( authmethod == LDAP_AUTH_SASL ) {
1490 #ifdef HAVE_CYRUS_SASL
1491                     void *defaults;
1492                     const char *rmech = NULL;
1493 
1494                     if( sasl_secprops != NULL ) {
1495                               rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
1496                                         (void *) sasl_secprops );
1497 
1498                               if( rc != LDAP_OPT_SUCCESS ) {
1499                                         fprintf( stderr,
1500                                                   "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
1501                                                   sasl_secprops );
1502                                         tool_exit( ld, LDAP_LOCAL_ERROR );
1503                               }
1504                     }
1505 
1506                     defaults = lutil_sasl_defaults( ld,
1507                               sasl_mech,
1508                               sasl_realm,
1509                               sasl_authc_id,
1510                               passwd.bv_val,
1511                               sasl_authz_id );
1512 
1513                     do {
1514                               rc = ldap_sasl_interactive_bind( ld, binddn, sasl_mech,
1515                                         sctrlsp, NULL, sasl_flags, lutil_sasl_interact, defaults,
1516                                         result, &rmech, &msgid );
1517 
1518                               if ( rc != LDAP_SASL_BIND_IN_PROGRESS )
1519                                         break;
1520 
1521                               ldap_msgfree( result );
1522 
1523                               if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) {
1524                                         ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void*)&err );
1525                                         ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&info );
1526                                         tool_perror( "ldap_sasl_interactive_bind",
1527                                                   err, NULL, NULL, info, NULL );
1528                                         ldap_memfree( info );
1529                                         tool_exit( ld, err );
1530                               }
1531                     } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
1532 
1533                     lutil_sasl_freedefs( defaults );
1534 
1535                     if ( rc != LDAP_SUCCESS ) {
1536                               ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&info );
1537                               tool_perror( "ldap_sasl_interactive_bind",
1538                                         rc, NULL, NULL, info, NULL );
1539                               ldap_memfree( info );
1540                               tool_exit( ld, rc );
1541                     }
1542 #else
1543                     fprintf( stderr, "%s: not compiled with SASL support\n", prog );
1544                     tool_exit( ld, LDAP_NOT_SUPPORTED );
1545 #endif
1546           } else {
1547                     /* simple bind */
1548                     rc = ldap_sasl_bind( ld, binddn, LDAP_SASL_SIMPLE, &passwd,
1549                               sctrlsp, NULL, &msgid );
1550                     if ( msgid == -1 ) {
1551                               tool_perror( "ldap_sasl_bind(SIMPLE)", rc,
1552                                         NULL, NULL, NULL, NULL );
1553                               tool_exit( ld, rc );
1554                     }
1555 
1556                     rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result );
1557                     if ( rc == -1 ) {
1558                               tool_perror( "ldap_result", -1, NULL, NULL, NULL, NULL );
1559                               tool_exit( ld, LDAP_LOCAL_ERROR );
1560                     }
1561 
1562                     if ( rc == 0 ) {
1563                               tool_perror( "ldap_result", LDAP_TIMEOUT, NULL, NULL, NULL, NULL );
1564                               tool_exit( ld, LDAP_LOCAL_ERROR );
1565                     }
1566           }
1567 
1568           if ( result ) {
1569                     rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs,
1570                                             &ctrls, 1 );
1571                     if ( rc != LDAP_SUCCESS ) {
1572                               tool_perror( "ldap_bind parse result", rc, NULL, matched, info, refs );
1573                               tool_exit( ld, LDAP_LOCAL_ERROR );
1574                     }
1575           }
1576 
1577 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1578           if ( ctrls && ppolicy ) {
1579                     LDAPControl *ctrl;
1580                     int expire, grace, len = 0;
1581                     LDAPPasswordPolicyError pErr = -1;
1582 
1583                     ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
1584                               ctrls, NULL );
1585 
1586                     if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl,
1587                               &expire, &grace, &pErr ) == LDAP_SUCCESS )
1588                     {
1589                               if ( pErr != PP_noError ){
1590                                         msgbuf[0] = ';';
1591                                         msgbuf[1] = ' ';
1592                                         strcpy( msgbuf+2, ldap_passwordpolicy_err2txt( pErr ));
1593                                         len = strlen( msgbuf );
1594                               }
1595                               if ( expire >= 0 ) {
1596                                         sprintf( msgbuf+len,
1597                                                   " (Password expires in %d seconds)",
1598                                                   expire );
1599                               } else if ( grace >= 0 ) {
1600                                         sprintf( msgbuf+len,
1601                                                   " (Password expired, %d grace logins remain)",
1602                                                   grace );
1603                               }
1604                     }
1605           }
1606 #endif
1607 
1608           if ( ctrls && bauthzid ) {
1609                     LDAPControl *ctrl;
1610 
1611                     ctrl = ldap_control_find( LDAP_CONTROL_AUTHZID_RESPONSE,
1612                               ctrls, NULL );
1613                     if ( ctrl ) {
1614                               LDAPControl *ctmp[2];
1615                               ctmp[0] = ctrl;
1616                               ctmp[1] = NULL;
1617                               tool_print_ctrls( ld, ctmp );
1618                     }
1619           }
1620 
1621 #ifdef LDAP_CONTROL_X_PASSWORD_EXPIRED
1622           if ( ctrls ) {
1623                     LDAPControl *ctrl;
1624                     ctrl = ldap_control_find( LDAP_CONTROL_X_PASSWORD_EXPIRED,
1625                               ctrls, NULL );
1626                     if ( !ctrl )
1627                               ctrl = ldap_control_find( LDAP_CONTROL_X_PASSWORD_EXPIRING,
1628                                         ctrls, NULL );
1629                     if ( ctrl ) {
1630                               LDAPControl *ctmp[2];
1631                               ctmp[0] = ctrl;
1632                               ctmp[1] = NULL;
1633                               tool_print_ctrls( ld, ctmp );
1634                     }
1635           }
1636 #endif
1637 
1638           if ( ctrls ) {
1639                     ldap_controls_free( ctrls );
1640           }
1641 
1642           if ( err != LDAP_SUCCESS
1643                     || msgbuf[0]
1644                     || ( matched && matched[ 0 ] )
1645                     || ( info && info[ 0 ] )
1646                     || refs )
1647           {
1648                     tool_perror( "ldap_bind", err, msgbuf, matched, info, refs );
1649 
1650                     if( matched ) ber_memfree( matched );
1651                     if( info ) ber_memfree( info );
1652                     if( refs ) ber_memvfree( (void **)refs );
1653 
1654                     if ( err != LDAP_SUCCESS ) tool_exit( ld, err );
1655           }
1656 }
1657 
1658 void
tool_unbind(LDAP * ld)1659 tool_unbind( LDAP *ld )
1660 {
1661           int err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
1662 
1663           if ( err != LDAP_OPT_SUCCESS ) {
1664                     fprintf( stderr, "Could not unset controls\n");
1665           }
1666 
1667           (void) ldap_unbind_ext( ld, NULL, NULL );
1668 }
1669 
1670 void
tool_exit(LDAP * ld,int status)1671 tool_exit( LDAP *ld, int status )
1672 {
1673           if ( ld != NULL ) {
1674                     tool_unbind( ld );
1675           }
1676           tool_destroy();
1677           exit( status );
1678 }
1679 
1680 
1681 /* Set server controls.  Add controls extra_c[0..count-1], if set. */
1682 void
tool_server_controls(LDAP * ld,LDAPControl * extra_c,int count)1683 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
1684 {
1685           int i = 0, j, crit = 0, err;
1686           LDAPControl c[16], **ctrls;
1687 
1688           if ( ! ( assertctl
1689                     || authzid
1690 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1691                     || proxydn
1692 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1693                     || manageDIT
1694                     || manageDSAit
1695                     || noop
1696 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1697                     || ppolicy
1698 #endif
1699                     || preread
1700                     || postread
1701 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1702                     || chaining
1703 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
1704 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1705                     || sessionTracking
1706 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1707                     || count
1708                     || unknown_ctrls_num ) )
1709           {
1710                     return;
1711           }
1712 
1713           ctrls = (LDAPControl**) malloc(sizeof(c) + (count + unknown_ctrls_num + 1)*sizeof(LDAPControl*));
1714           if ( ctrls == NULL ) {
1715                     fprintf( stderr, "No memory\n" );
1716                     tool_exit( ld, EXIT_FAILURE );
1717           }
1718 
1719           if ( assertctl ) {
1720                     if ( BER_BVISNULL( &assertionvalue ) ) {
1721                               err = ldap_create_assertion_control_value( ld,
1722                                         assertion, &assertionvalue );
1723                               if ( err ) {
1724                                         fprintf( stderr,
1725                                                   "Unable to create assertion value "
1726                                                   "\"%s\" (%d)\n", assertion, err );
1727                               }
1728                     }
1729 
1730                     c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
1731                     c[i].ldctl_value = assertionvalue;
1732                     c[i].ldctl_iscritical = assertctl > 1;
1733                     ctrls[i] = &c[i];
1734                     i++;
1735           }
1736 
1737           if ( authzid ) {
1738                     c[i].ldctl_value.bv_val = authzid;
1739                     c[i].ldctl_value.bv_len = strlen( authzid );
1740                     c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
1741                     c[i].ldctl_iscritical = authzcrit;
1742                     ctrls[i] = &c[i];
1743                     i++;
1744           }
1745 
1746 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ
1747           /* NOTE: doesn't need an extra count because it's incompatible
1748            * with authzid */
1749           if ( proxydn ) {
1750                     BerElementBuffer berbuf;
1751                     BerElement *ber = (BerElement *)&berbuf;
1752 
1753                     ber_init2( ber, NULL, LBER_USE_DER );
1754 
1755                     if ( ber_printf( ber, "s", proxydn ) == -1 ) {
1756                               tool_exit( ld, EXIT_FAILURE );
1757                     }
1758 
1759                     if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
1760                               tool_exit( ld, EXIT_FAILURE );
1761                     }
1762 
1763                     c[i].ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;
1764                     c[i].ldctl_iscritical = authzcrit;
1765                     ctrls[i] = &c[i];
1766                     i++;
1767           }
1768 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */
1769 
1770           if ( manageDIT ) {
1771                     c[i].ldctl_oid = LDAP_CONTROL_MANAGEDIT;
1772                     BER_BVZERO( &c[i].ldctl_value );
1773                     c[i].ldctl_iscritical = manageDIT > 1;
1774                     ctrls[i] = &c[i];
1775                     i++;
1776           }
1777 
1778           if ( manageDSAit ) {
1779                     c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
1780                     BER_BVZERO( &c[i].ldctl_value );
1781                     c[i].ldctl_iscritical = manageDSAit > 1;
1782                     ctrls[i] = &c[i];
1783                     i++;
1784           }
1785 
1786           if ( noop ) {
1787                     c[i].ldctl_oid = LDAP_CONTROL_NOOP;
1788                     BER_BVZERO( &c[i].ldctl_value );
1789                     c[i].ldctl_iscritical = noop > 1;
1790                     ctrls[i] = &c[i];
1791                     i++;
1792           }
1793 
1794 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
1795           if ( ppolicy ) {
1796                     c[i].ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
1797                     BER_BVZERO( &c[i].ldctl_value );
1798                     c[i].ldctl_iscritical = 0;
1799                     ctrls[i] = &c[i];
1800                     i++;
1801           }
1802 #endif
1803 
1804           if ( preread ) {
1805                     BerElementBuffer berbuf;
1806                     BerElement *ber = (BerElement *)&berbuf;
1807                     char **attrs = NULL;
1808 
1809                     if( preread_attrs ) {
1810                               attrs = ldap_str2charray( preread_attrs, "," );
1811                     }
1812 
1813                     ber_init2( ber, NULL, LBER_USE_DER );
1814 
1815                     if( ber_printf( ber, "{v}", attrs ) == -1 ) {
1816                               fprintf( stderr, "preread attrs encode failed.\n" );
1817                               tool_exit( ld, EXIT_FAILURE );
1818                     }
1819 
1820                     err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
1821                     if( err < 0 ) {
1822                               fprintf( stderr, "preread flatten failed (%d)\n", err );
1823                               tool_exit( ld, EXIT_FAILURE );
1824                     }
1825 
1826                     c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
1827                     c[i].ldctl_iscritical = preread > 1;
1828                     ctrls[i] = &c[i];
1829                     i++;
1830 
1831                     if( attrs ) ldap_charray_free( attrs );
1832           }
1833 
1834           if ( postread ) {
1835                     BerElementBuffer berbuf;
1836                     BerElement *ber = (BerElement *)&berbuf;
1837                     char **attrs = NULL;
1838 
1839                     if( postread_attrs ) {
1840                               attrs = ldap_str2charray( postread_attrs, "," );
1841                     }
1842 
1843                     ber_init2( ber, NULL, LBER_USE_DER );
1844 
1845                     if( ber_printf( ber, "{v}", attrs ) == -1 ) {
1846                               fprintf( stderr, "postread attrs encode failed.\n" );
1847                               tool_exit( ld, EXIT_FAILURE );
1848                     }
1849 
1850                     err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
1851                     if( err < 0 ) {
1852                               fprintf( stderr, "postread flatten failed (%d)\n", err );
1853                               tool_exit( ld, EXIT_FAILURE );
1854                     }
1855 
1856                     c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
1857                     c[i].ldctl_iscritical = postread > 1;
1858                     ctrls[i] = &c[i];
1859                     i++;
1860 
1861                     if( attrs ) ldap_charray_free( attrs );
1862           }
1863 
1864 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
1865           if ( chaining ) {
1866                     if ( chainingResolve > -1 ) {
1867                               BerElementBuffer berbuf;
1868                               BerElement *ber = (BerElement *)&berbuf;
1869 
1870                               ber_init2( ber, NULL, LBER_USE_DER );
1871 
1872                               err = ber_printf( ber, "{e" /* } */, chainingResolve );
1873                               if ( err == -1 ) {
1874                                         ber_free( ber, 1 );
1875                                         fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1876                                         tool_exit( ld, EXIT_FAILURE );
1877                               }
1878 
1879                               if ( chainingContinuation > -1 ) {
1880                                         err = ber_printf( ber, "e", chainingContinuation );
1881                                         if ( err == -1 ) {
1882                                                   ber_free( ber, 1 );
1883                                                   fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1884                                                   tool_exit( ld, EXIT_FAILURE );
1885                                         }
1886                               }
1887 
1888                               err = ber_printf( ber, /* { */ "N}" );
1889                               if ( err == -1 ) {
1890                                         ber_free( ber, 1 );
1891                                         fprintf( stderr, _("Chaining behavior control encoding error!\n") );
1892                                         tool_exit( ld, EXIT_FAILURE );
1893                               }
1894 
1895                               if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
1896                                         tool_exit( ld, EXIT_FAILURE );
1897                               }
1898 
1899                     } else {
1900                               BER_BVZERO( &c[i].ldctl_value );
1901                     }
1902 
1903                     c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
1904                     c[i].ldctl_iscritical = chaining > 1;
1905                     ctrls[i] = &c[i];
1906                     i++;
1907           }
1908 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
1909 
1910 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
1911           if ( sessionTracking ) {
1912                     if ( BER_BVISNULL( &stValue ) && st_value( ld, &stValue ) ) {
1913                               tool_exit( ld, EXIT_FAILURE );
1914                     }
1915 
1916                     c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
1917                     c[i].ldctl_iscritical = 0;
1918                     c[i].ldctl_value = stValue;
1919 
1920                     ctrls[i] = &c[i];
1921                     i++;
1922           }
1923 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
1924 
1925           while ( count-- ) {
1926                     ctrls[i++] = extra_c++;
1927           }
1928           for ( count = 0; count < unknown_ctrls_num; count++ ) {
1929                     ctrls[i++] = &unknown_ctrls[count];
1930           }
1931           ctrls[i] = NULL;
1932 
1933           err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
1934 
1935           if ( err != LDAP_OPT_SUCCESS ) {
1936                     for ( j = 0; j < i; j++ ) {
1937                               if ( ctrls[j]->ldctl_iscritical ) crit = 1;
1938                     }
1939                     fprintf( stderr, "Could not set %scontrols\n",
1940                               crit ? "critical " : "" );
1941           }
1942 
1943           free( ctrls );
1944           if ( crit ) {
1945                     tool_exit( ld, EXIT_FAILURE );
1946           }
1947 }
1948 
1949 int
tool_check_abandon(LDAP * ld,int msgid)1950 tool_check_abandon( LDAP *ld, int msgid )
1951 {
1952           int       rc;
1953           LDAPControl *sctrls[1] = { NULL };
1954 
1955           switch ( gotintr ) {
1956           case Intr_Cancel:
1957                     rc = ldap_cancel_s( ld, msgid, sctrls, NULL );
1958                     fprintf( stderr, "got interrupt, cancel got %d: %s\n",
1959                                         rc, ldap_err2string( rc ) );
1960                     return -1;
1961 
1962           case Intr_Abandon:
1963                     rc = ldap_abandon_ext( ld, msgid, sctrls, NULL );
1964                     fprintf( stderr, "got interrupt, abandon got %d: %s\n",
1965                                         rc, ldap_err2string( rc ) );
1966                     return -1;
1967 
1968           case Intr_Ignore:
1969                     /* just unbind, ignoring the request */
1970                     return -1;
1971           }
1972 
1973           return 0;
1974 }
1975 
1976 static int
print_prepostread(LDAP * ld,LDAPControl * ctrl,struct berval * what)1977 print_prepostread( LDAP *ld, LDAPControl *ctrl, struct berval *what)
1978 {
1979           BerElement          *ber;
1980           struct berval       bv;
1981 
1982           tool_write_ldif( LDIF_PUT_COMMENT, "==> ",
1983                     what->bv_val, what->bv_len );
1984           ber = ber_init( &ctrl->ldctl_value );
1985           if ( ber == NULL ) {
1986                     /* error? */
1987                     return 1;
1988 
1989           } else if ( ber_scanf( ber, "{m{" /*}}*/, &bv ) == LBER_ERROR ) {
1990                     /* error? */
1991                     return 1;
1992 
1993           } else {
1994                     tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
1995 
1996                     while ( ber_scanf( ber, "{m" /*}*/, &bv ) != LBER_ERROR ) {
1997                               int                 i;
1998                               BerVarray vals = NULL;
1999                               char                *str = NULL;
2000 
2001                               if ( ber_scanf( ber, "[W]", &vals ) == LBER_ERROR ||
2002                                         vals == NULL )
2003                               {
2004                                         /* error? */
2005                                         return 1;
2006                               }
2007 
2008                               if ( ldif ) {
2009                                         char *ptr;
2010 
2011                                         str = malloc( bv.bv_len + STRLENOF(": ") + 1 );
2012 
2013                                         ptr = str;
2014                                         ptr = lutil_strncopy( ptr, bv.bv_val, bv.bv_len );
2015                                         ptr = lutil_strcopy( ptr, ": " );
2016                               }
2017 
2018                               for ( i = 0; vals[ i ].bv_val != NULL; i++ ) {
2019                                         tool_write_ldif(
2020                                                   ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2021                                                   ldif ? str : bv.bv_val, vals[ i ].bv_val, vals[ i ].bv_len );
2022                               }
2023 
2024                               ber_bvarray_free( vals );
2025                               if ( str ) free( str );
2026                     }
2027           }
2028 
2029           if ( ber != NULL ) {
2030                     ber_free( ber, 1 );
2031           }
2032 
2033           tool_write_ldif( LDIF_PUT_COMMENT, "<== ",
2034                     what->bv_val, what->bv_len );
2035 
2036           return 0;
2037 }
2038 
2039 static int
print_preread(LDAP * ld,LDAPControl * ctrl)2040 print_preread( LDAP *ld, LDAPControl *ctrl )
2041 {
2042           static struct berval what = BER_BVC( "preread" );
2043 
2044           return print_prepostread( ld, ctrl, &what );
2045 }
2046 
2047 static int
print_postread(LDAP * ld,LDAPControl * ctrl)2048 print_postread( LDAP *ld, LDAPControl *ctrl )
2049 {
2050           static struct berval what = BER_BVC( "postread" );
2051 
2052           return print_prepostread( ld, ctrl, &what );
2053 }
2054 
2055 static int
print_paged_results(LDAP * ld,LDAPControl * ctrl)2056 print_paged_results( LDAP *ld, LDAPControl *ctrl )
2057 {
2058           ber_int_t estimate;
2059 
2060           /* note: pr_cookie is being malloced; it's freed
2061            * the next time the control is sent, but the last
2062            * time it's not; we don't care too much, because
2063            * the last time an empty value is returned... */
2064           if ( ldap_parse_pageresponse_control( ld, ctrl, &estimate, &pr_cookie )
2065                     != LDAP_SUCCESS )
2066           {
2067                     /* error? */
2068                     return 1;
2069 
2070           } else {
2071                     char      buf[ BUFSIZ ], *ptr = buf;
2072                     int plen;
2073 
2074                     if ( estimate > 0 ) {
2075                               plen = sprintf( buf, "estimate=%d cookie=", estimate );
2076                     } else {
2077                               plen = sprintf( buf, "cookie=" );
2078                     }
2079 
2080                     if ( pr_cookie.bv_len > 0 ) {
2081                               struct berval       bv;
2082 
2083                               bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2084                                         pr_cookie.bv_len ) + 1;
2085                               ptr = ber_memalloc( bv.bv_len + 1 + plen );
2086                               bv.bv_val = ptr + plen;
2087 
2088                               strcpy( ptr, buf );
2089 
2090                               bv.bv_len = lutil_b64_ntop(
2091                                         (unsigned char *) pr_cookie.bv_val,
2092                                         pr_cookie.bv_len,
2093                                         bv.bv_val, bv.bv_len );
2094 
2095                               pr_morePagedResults = 1;
2096                               plen += bv.bv_len;
2097                     }
2098 
2099                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2100                               ldif ? "pagedresults: " : "pagedresults",
2101                               ptr, plen );
2102 
2103                     if ( ptr != buf )
2104                               ber_memfree( ptr );
2105           }
2106 
2107           return 0;
2108 }
2109 
2110 static int
print_psearch(LDAP * ld,LDAPControl * ctrl)2111 print_psearch( LDAP *ld, LDAPControl *ctrl )
2112 {
2113           int rc;
2114           int chgtype;
2115           int chgpres;
2116           long chgnum;
2117           struct berval prevdn;
2118 
2119           rc = ldap_parse_entrychange_control( ld, ctrl, &chgtype, &prevdn,
2120                     &chgpres, &chgnum );
2121           if ( rc == LDAP_SUCCESS ) {
2122                     char buf[ BUFSIZ ];
2123                     char *ptr = buf;
2124                     int blen = sizeof(buf), len;
2125 
2126                     switch( chgtype ) {
2127                     case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD:
2128                               len = snprintf( ptr, blen, "add" );
2129                               ptr += len;
2130                               blen -= len;
2131                               break;
2132                     case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE:
2133                               len = snprintf( ptr, blen, "delete" );
2134                               ptr += len;
2135                               blen -= len;
2136                               break;
2137                     case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY:
2138                               len = snprintf( ptr, blen, "modify" );
2139                               ptr += len;
2140                               blen -= len;
2141                               break;
2142                     case LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME:
2143                               len = snprintf( ptr, blen, "moddn" );
2144                               ptr += len;
2145                               blen -= len;
2146                               if ( prevdn.bv_val != NULL ) {
2147                                         len = snprintf( ptr, blen, " prevdn %s", prevdn.bv_val );
2148                                         ptr += len;
2149                                         blen -= len;
2150                               }
2151                               break;
2152                     }
2153                     if ( chgpres ) {
2154                               len = snprintf( ptr, blen, " changeNumber %ld", chgnum) ;
2155                               ptr += len;
2156                               blen -= len;
2157                     }
2158 
2159                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2160                               ldif ? "persistentSearch: " : "persistentSearch", buf, len );
2161           }
2162 
2163           return rc;
2164 }
2165 
2166 static int
print_sss(LDAP * ld,LDAPControl * ctrl)2167 print_sss( LDAP *ld, LDAPControl *ctrl )
2168 {
2169           int rc;
2170           ber_int_t err;
2171           char *attr;
2172 
2173           rc = ldap_parse_sortresponse_control( ld, ctrl, &err, &attr );
2174           if ( rc == LDAP_SUCCESS ) {
2175                     char buf[ BUFSIZ ];
2176                     rc = snprintf( buf, sizeof(buf), "(%d) %s%s%s",
2177                               err, ldap_err2string(err), attr ? " " : "", attr ? attr : "" );
2178 
2179                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2180                               ldif ? "sortResult: " : "sortResult", buf, rc );
2181           }
2182 
2183           return rc;
2184 }
2185 
2186 static int
print_vlv(LDAP * ld,LDAPControl * ctrl)2187 print_vlv( LDAP *ld, LDAPControl *ctrl )
2188 {
2189           int rc;
2190           ber_int_t err;
2191           struct berval bv;
2192 
2193           rc = ldap_parse_vlvresponse_control( ld, ctrl, &vlvPos, &vlvCount,
2194                     &vlvContext, &err );
2195           if ( rc == LDAP_SUCCESS ) {
2196                     char buf[ BUFSIZ ];
2197 
2198                     if ( vlvContext && vlvContext->bv_len > 0 ) {
2199                               bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2200                                         vlvContext->bv_len ) + 1;
2201                               bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2202 
2203                               bv.bv_len = lutil_b64_ntop(
2204                                         (unsigned char *) vlvContext->bv_val,
2205                                         vlvContext->bv_len,
2206                                         bv.bv_val, bv.bv_len );
2207                     } else {
2208                               bv.bv_val = "";
2209                               bv.bv_len = 0;
2210                     }
2211 
2212                     rc = snprintf( buf, sizeof(buf), "pos=%d count=%d context=%s (%d) %s",
2213                               vlvPos, vlvCount, bv.bv_val,
2214                               err, ldap_err2string(err));
2215 
2216                     if ( bv.bv_len )
2217                               ber_memfree( bv.bv_val );
2218 
2219                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2220                               ldif ? "vlvResult" : "vlvResult", buf, rc );
2221           }
2222 
2223           return rc;
2224 }
2225 
2226 #ifdef LDAP_CONTROL_X_DEREF
2227 static int
print_deref(LDAP * ld,LDAPControl * ctrl)2228 print_deref( LDAP *ld, LDAPControl *ctrl )
2229 {
2230           LDAPDerefRes    *drhead = NULL, *dr;
2231           int                 rc;
2232 
2233           rc = ldap_parse_derefresponse_control( ld, ctrl, &drhead );
2234           if ( rc != LDAP_SUCCESS ) {
2235                     return rc;
2236           }
2237 
2238           for ( dr = drhead; dr != NULL; dr = dr->next ) {
2239                     LDAPDerefVal        *dv;
2240                     ber_len_t len;
2241                     char                *buf, *ptr;
2242 
2243                     len = strlen( dr->derefAttr ) + STRLENOF(": ");
2244 
2245                     for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
2246                               if ( dv->vals != NULL ) {
2247                                         int j;
2248                                         ber_len_t tlen = strlen(dv->type);
2249 
2250                                         for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
2251                                                   len += STRLENOF("<:=>;") + tlen + 4*((dv->vals[ j ].bv_len - 1)/3 + 1);
2252                                         }
2253                               }
2254                     }
2255                     len += dr->derefVal.bv_len + STRLENOF("\n");
2256                     buf = ldap_memalloc( len + 1 );
2257                     if ( buf == NULL ) {
2258                               rc = LDAP_NO_MEMORY;
2259                               goto done;
2260                     }
2261 
2262                     ptr = buf;
2263                     ptr = lutil_strcopy( ptr, dr->derefAttr );
2264                     *ptr++ = ':';
2265                     *ptr++ = ' ';
2266                     for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) {
2267                               if ( dv->vals != NULL ) {
2268                                         int j;
2269                                         for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) {
2270                                                   int k = ldif_is_not_printable( dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
2271 
2272                                                   *ptr++ = '<';
2273                                                   ptr = lutil_strcopy( ptr, dv->type );
2274                                                   if ( k ) {
2275                                                             *ptr++ = ':';
2276                                                   }
2277                                                   *ptr++ = '=';
2278                                                   if ( k ) {
2279                                                             k = lutil_b64_ntop(
2280                                                                       (unsigned char *) dv->vals[ j ].bv_val,
2281                                                                       dv->vals[ j ].bv_len,
2282                                                                       ptr, buf + len - ptr );
2283                                                             assert( k >= 0 );
2284                                                             ptr += k;
2285 
2286                                                   } else {
2287                                                             ptr = lutil_memcopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len );
2288                                                   }
2289                                                   *ptr++ = '>';
2290                                                   *ptr++ = ';';
2291                                         }
2292                               }
2293                     }
2294                     ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len );
2295                     *ptr = '\0';
2296                     assert( ptr <= buf + len );
2297 
2298                     tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, ptr - buf);
2299 
2300                     ldap_memfree( buf );
2301           }
2302 
2303           rc = LDAP_SUCCESS;
2304 
2305 done:;
2306           ldap_derefresponse_free( drhead );
2307 
2308           return rc;
2309 }
2310 #endif
2311 
2312 #ifdef LDAP_CONTROL_X_WHATFAILED
2313 static int
print_whatfailed(LDAP * ld,LDAPControl * ctrl)2314 print_whatfailed( LDAP *ld, LDAPControl *ctrl )
2315 {
2316           BerElement *ber;
2317           ber_tag_t tag;
2318           ber_len_t siz;
2319           BerVarray bva = NULL;
2320 
2321           /* Create a BerElement from the berval returned in the control. */
2322           ber = ber_init( &ctrl->ldctl_value );
2323 
2324           if ( ber == NULL ) {
2325                     return LDAP_NO_MEMORY;
2326           }
2327 
2328           siz = sizeof(struct berval);
2329           tag = ber_scanf( ber, "[M]", &bva, &siz, 0 );
2330           if ( tag != LBER_ERROR ) {
2331                     int i;
2332 
2333                     tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 );
2334 
2335                     for ( i = 0; bva[i].bv_val != NULL; i++ ) {
2336                               tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len );
2337                     }
2338 
2339                     ldap_memfree( bva );
2340           }
2341 
2342         ber_free( ber, 1 );
2343 
2344 
2345           return 0;
2346 }
2347 #endif
2348 
2349 static int
print_syncstate(LDAP * ld,LDAPControl * ctrl)2350 print_syncstate( LDAP *ld, LDAPControl *ctrl )
2351 {
2352           struct berval syncUUID, syncCookie = BER_BVNULL;
2353           char buf[LDAP_LUTIL_UUIDSTR_BUFSIZE], *uuidstr = "(UUID malformed)";
2354           BerElement *ber;
2355           ber_tag_t tag;
2356           ber_int_t state;
2357           int rc;
2358 
2359           if ( ldif ) {
2360                     return 0;
2361           }
2362 
2363           /* Create a BerElement from the berval returned in the control. */
2364           ber = ber_init( &ctrl->ldctl_value );
2365 
2366           if ( ber == NULL ) {
2367                     return LDAP_NO_MEMORY;
2368           }
2369 
2370           if ( ber_scanf( ber, "{em", &state, &syncUUID ) == LBER_ERROR ) {
2371                     ber_free( ber, 1 );
2372                     return 1;
2373           }
2374 
2375           tag = ber_get_stringbv( ber, &syncCookie, 0 );
2376 
2377           rc = lutil_uuidstr_from_normalized(
2378                               syncUUID.bv_val, syncUUID.bv_len,
2379                               buf, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2380 
2381           if ( rc > 0 && rc < LDAP_LUTIL_UUIDSTR_BUFSIZE ) {
2382                     uuidstr = buf;
2383           }
2384 
2385           switch ( state ) {
2386                     case LDAP_SYNC_PRESENT:
2387                               printf(_("# SyncState control, UUID %s present\n"), uuidstr);
2388                               break;
2389                     case LDAP_SYNC_ADD:
2390                               printf(_("# SyncState control, UUID %s added\n"), uuidstr);
2391                               break;
2392                     case LDAP_SYNC_MODIFY:
2393                               printf(_("# SyncState control, UUID %s modified\n"), uuidstr);
2394                               break;
2395                     case LDAP_SYNC_DELETE:
2396                               printf(_("# SyncState control, UUID %s deleted\n"), uuidstr);
2397                               break;
2398                     default:
2399                               ber_free( ber, 1 );
2400                               return 1;
2401           }
2402 
2403           if ( tag != LBER_ERROR ) {
2404                     if ( ldif_is_not_printable( syncCookie.bv_val, syncCookie.bv_len ) ) {
2405                               struct berval bv;
2406 
2407                               bv.bv_len = LUTIL_BASE64_ENCODE_LEN( syncCookie.bv_len ) + 1;
2408                               bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2409 
2410                               bv.bv_len = lutil_b64_ntop(
2411                                                   (unsigned char *) syncCookie.bv_val, syncCookie.bv_len,
2412                                                   bv.bv_val, bv.bv_len );
2413 
2414                               printf(_("# cookie:: %s\n"), bv.bv_val );
2415                               ber_memfree( bv.bv_val );
2416                     } else {
2417                               printf(_("# cookie: %s\n"), syncCookie.bv_val );
2418                     }
2419           }
2420 
2421           ber_free( ber, 1 );
2422           return 0;
2423 }
2424 
2425 static int
print_syncdone(LDAP * ld,LDAPControl * ctrl)2426 print_syncdone( LDAP *ld, LDAPControl *ctrl )
2427 {
2428           BerElement *ber;
2429           struct berval cookie = BER_BVNULL;
2430           ber_len_t len;
2431           ber_int_t refreshDeletes = 0;
2432 
2433           if ( ldif ) {
2434                     return 0;
2435           }
2436 
2437           /* Create a BerElement from the berval returned in the control. */
2438           ber = ber_init( &ctrl->ldctl_value );
2439 
2440           if ( ber == NULL ) {
2441                     return LDAP_NO_MEMORY;
2442           }
2443 
2444           ber_skip_tag( ber, &len );
2445           if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
2446                     ber_scanf( ber, "m", &cookie );
2447           }
2448           if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
2449                     ber_scanf( ber, "b", &refreshDeletes );
2450           }
2451 
2452           printf(_("# SyncDone control refreshDeletes=%d\n"), refreshDeletes ? 1 : 0 );
2453 
2454           if ( !BER_BVISNULL( &cookie ) ) {
2455                     if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2456                               struct berval bv;
2457 
2458                               bv.bv_len = LUTIL_BASE64_ENCODE_LEN( cookie.bv_len ) + 1;
2459                               bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2460 
2461                               bv.bv_len = lutil_b64_ntop(
2462                                                   (unsigned char *) cookie.bv_val, cookie.bv_len,
2463                                                   bv.bv_val, bv.bv_len );
2464 
2465                               printf(_("# cookie:: %s\n"), bv.bv_val );
2466                               ber_memfree( bv.bv_val );
2467                     } else {
2468                               printf(_("# cookie: %s\n"), cookie.bv_val );
2469                     }
2470           }
2471 
2472           ber_free( ber, 1 );
2473           return 0;
2474 }
2475 
2476 #ifdef LDAP_CONTROL_X_DIRSYNC
2477 static int
print_dirsync(LDAP * ld,LDAPControl * ctrl)2478 print_dirsync( LDAP *ld, LDAPControl *ctrl )
2479 {
2480           int rc, continueFlag;
2481           struct berval cookie;
2482 
2483           rc = ldap_parse_dirsync_control( ld, ctrl,
2484                     &continueFlag, &cookie );
2485           if ( rc == LDAP_SUCCESS ) {
2486                     printf(_("# DirSync control continueFlag=%d\n"), continueFlag );
2487                     if ( !BER_BVISNULL( &cookie )) {
2488                               if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2489                                         struct berval bv;
2490 
2491                                         bv.bv_len = LUTIL_BASE64_ENCODE_LEN( cookie.bv_len ) + 1;
2492                                         bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2493 
2494                                         bv.bv_len = lutil_b64_ntop(
2495                                                             (unsigned char *) cookie.bv_val, cookie.bv_len,
2496                                                             bv.bv_val, bv.bv_len );
2497 
2498                                         printf(_("# cookie:: %s\n"), bv.bv_val );
2499                                         ber_memfree( bv.bv_val );
2500                               } else {
2501                                         printf(_("# cookie: %s\n"), cookie.bv_val );
2502                               }
2503                     }
2504           }
2505           return rc;
2506 }
2507 #endif
2508 
2509 #ifdef LDAP_CONTROL_AUTHZID_RESPONSE
2510 static int
print_authzid(LDAP * ld,LDAPControl * ctrl)2511 print_authzid( LDAP *ld, LDAPControl *ctrl )
2512 {
2513           if ( ctrl->ldctl_value.bv_len ) {
2514                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2515                               ldif ? "authzid: " : "authzid",
2516                     ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len );
2517           } else {
2518                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2519                               ldif ? "authzid: " : "authzid",
2520                               "anonymous",  STRLENOF("anonymous") );
2521           }
2522 
2523           return 0;
2524 }
2525 #endif
2526 
2527 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
2528 static int
print_ppolicy(LDAP * ld,LDAPControl * ctrl)2529 print_ppolicy( LDAP *ld, LDAPControl *ctrl )
2530 {
2531           int expire = 0, grace = 0, rc;
2532           LDAPPasswordPolicyError       pperr;
2533 
2534           rc = ldap_parse_passwordpolicy_control( ld, ctrl,
2535                     &expire, &grace, &pperr );
2536           if ( rc == LDAP_SUCCESS ) {
2537                     char      buf[ BUFSIZ ], *ptr = buf;
2538 
2539                     if ( expire != -1 ) {
2540                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2541                                         "expire=%d", expire );
2542                     }
2543 
2544                     if ( grace != -1 ) {
2545                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2546                                         "%sgrace=%d", ptr == buf ? "" : " ", grace );
2547                     }
2548 
2549                     if ( pperr != PP_noError ) {
2550                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2551                                         "%serror=%d (%s)", ptr == buf ? "" : " ",
2552                                         pperr,
2553                                         ldap_passwordpolicy_err2txt( pperr ) );
2554                     }
2555 
2556                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2557                               ldif ? "ppolicy: " : "ppolicy", buf, ptr - buf );
2558           }
2559 
2560           return rc;
2561 }
2562 #endif
2563 
2564 #ifdef LDAP_CONTROL_X_PASSWORD_EXPIRED
2565 static int
print_netscape_pwexpired(LDAP * ld,LDAPControl * ctrl)2566 print_netscape_pwexpired( LDAP *ld, LDAPControl *ctrl )
2567 {
2568           printf(_("# PasswordExpired control\n") );
2569           return 0;
2570 }
2571 
2572 static int
print_netscape_pwexpiring(LDAP * ld,LDAPControl * ctrl)2573 print_netscape_pwexpiring( LDAP *ld, LDAPControl *ctrl )
2574 {
2575           long expiring = 0;
2576           int rc;
2577 
2578           rc = ldap_parse_password_expiring_control( ld, ctrl, &expiring );
2579           if ( rc == LDAP_SUCCESS ) {
2580                     printf(_("# PasswordExpiring control seconds=%ld\n"), expiring );
2581           }
2582           return rc;
2583 }
2584 #endif
2585 
2586 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
2587 static int
print_account_usability(LDAP * ld,LDAPControl * ctrl)2588 print_account_usability( LDAP *ld, LDAPControl *ctrl )
2589 {
2590           LDAPAccountUsability usability;
2591           ber_int_t available = 0;
2592           int rc;
2593 
2594           rc = ldap_parse_accountusability_control( ld, ctrl, &available, &usability );
2595           if ( rc == LDAP_SUCCESS ) {
2596                     char      buf[ BUFSIZ ], *ptr = buf;
2597 
2598                     ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2599                                  "%savailable", available ? "" : "not " );
2600                     if ( available ) {
2601                               if ( usability.seconds_remaining == -1 ) {
2602                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2603                                                   " and does not expire" );
2604                               } else {
2605                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2606                                                   " expire=%d", usability.seconds_remaining );
2607                               }
2608                     } else {
2609                               int added = 0;
2610                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2611                                         " (" /* ')' */ );
2612 
2613                               if ( usability.more_info.inactive ) {
2614                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2615                                                   "inactive " );
2616                                         added++;
2617                               }
2618                               if ( usability.more_info.reset ) {
2619                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2620                                                   "reset " );
2621                                         added++;
2622                               }
2623                               if ( usability.more_info.expired ) {
2624                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2625                                                   "expired " );
2626                                         added++;
2627                               }
2628 
2629                               if ( added ) {
2630                                         ptr[-1] = ')';
2631                                         *ptr++ = ' ';
2632                               } else {
2633                                         *(--ptr) = '\0';
2634                               }
2635 
2636                               if ( usability.more_info.remaining_grace != -1 ) {
2637                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2638                                                   "grace=%d ", usability.more_info.remaining_grace );
2639                               }
2640 
2641                               if ( usability.more_info.seconds_before_unlock != -1 ) {
2642                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
2643                                                   "seconds_before_unlock=%d ", usability.more_info.seconds_before_unlock );
2644                               }
2645 
2646                               *(--ptr) = '\0';
2647                     }
2648 
2649                     tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2650                               ldif ? "accountUsability: " : "accountUsability", buf, ptr - buf );
2651           }
2652 
2653           return rc;
2654 }
2655 #endif
2656 
tool_print_ctrls(LDAP * ld,LDAPControl ** ctrls)2657 void tool_print_ctrls(
2658           LDAP                *ld,
2659           LDAPControl         **ctrls )
2660 {
2661           int       i;
2662           char      *ptr;
2663 
2664           for ( i = 0; ctrls[i] != NULL; i++ ) {
2665                     /* control: OID criticality base64value */
2666                     struct berval b64 = BER_BVNULL;
2667                     ber_len_t len;
2668                     char *str;
2669                     int j;
2670 
2671                     /* FIXME: there might be cases where a control has NULL OID;
2672                      * this makes little sense, especially when returned by the
2673                      * server, but libldap happily allows it */
2674                     if ( ctrls[i]->ldctl_oid == NULL ) {
2675                               continue;
2676                     }
2677 
2678                     len = ldif ? 2 : 0;
2679                     len += strlen( ctrls[i]->ldctl_oid );
2680 
2681                     /* add enough for space after OID and the critical value itself */
2682                     len += ctrls[i]->ldctl_iscritical
2683                               ? sizeof("true") : sizeof("false");
2684 
2685                     /* convert to base64 */
2686                     if ( !BER_BVISNULL( &ctrls[i]->ldctl_value ) ) {
2687                               b64.bv_len = LUTIL_BASE64_ENCODE_LEN(
2688                                         ctrls[i]->ldctl_value.bv_len ) + 1;
2689                               b64.bv_val = ber_memalloc( b64.bv_len + 1 );
2690 
2691                               b64.bv_len = lutil_b64_ntop(
2692                                         (unsigned char *) ctrls[i]->ldctl_value.bv_val,
2693                                         ctrls[i]->ldctl_value.bv_len,
2694                                         b64.bv_val, b64.bv_len );
2695                     }
2696 
2697                     if ( b64.bv_len ) {
2698                               len += 1 + b64.bv_len;
2699                     }
2700 
2701                     ptr = str = malloc( len + 1 );
2702                     if ( ldif ) {
2703                               ptr = lutil_strcopy( ptr, ": " );
2704                     }
2705                     ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_oid );
2706                     ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_iscritical
2707                               ? " true" : " false" );
2708 
2709                     if ( b64.bv_len ) {
2710                               ptr = lutil_strcopy( ptr, " " );
2711                               ptr = lutil_strcopy( ptr, b64.bv_val );
2712                     }
2713 
2714                     if ( ldif < 2 ) {
2715                               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2716                                         "control", str, len );
2717                     }
2718 
2719                     free( str );
2720                     if ( b64.bv_len ) {
2721                               ber_memfree( b64.bv_val );
2722                     }
2723 
2724                     /* known controls */
2725                     for ( j = 0; tool_ctrl_response[j].oid != NULL; j++ ) {
2726                               if ( strcmp( tool_ctrl_response[j].oid, ctrls[i]->ldctl_oid ) == 0 ) {
2727                                         if ( !(tool_ctrl_response[j].mask & tool_type )) {
2728                                                   /* this control should not appear
2729                                                    * with this tool; warning? */
2730                                         }
2731                                         break;
2732                               }
2733                     }
2734 
2735                     if ( tool_ctrl_response[j].oid != NULL && tool_ctrl_response[j].func ) {
2736                               (void)tool_ctrl_response[j].func( ld, ctrls[i] );
2737                     }
2738           }
2739 }
2740 
2741 int
tool_write_ldif(int type,char * name,char * value,ber_len_t vallen)2742 tool_write_ldif( int type, char *name, char *value, ber_len_t vallen )
2743 {
2744           char      *ldif;
2745 
2746           if (( ldif = ldif_put_wrap( type, name, value, vallen, ldif_wrap )) == NULL ) {
2747                     return( -1 );
2748           }
2749 
2750           fputs( ldif, stdout );
2751           ber_memfree( ldif );
2752 
2753           return( 0 );
2754 }
2755 
2756 int
tool_is_oid(const char * s)2757 tool_is_oid( const char *s )
2758 {
2759           int                 first = 1;
2760 
2761           if ( !isdigit( (unsigned char) s[ 0 ] ) ) {
2762                     return 0;
2763           }
2764 
2765           for ( ; s[ 0 ]; s++ ) {
2766                     if ( s[ 0 ] == '.' ) {
2767                               if ( s[ 1 ] == '\0' ) {
2768                                         return 0;
2769                               }
2770                               first = 1;
2771                               continue;
2772                     }
2773 
2774                     if ( !isdigit( (unsigned char) s[ 0 ] ) ) {
2775                               return 0;
2776                     }
2777 
2778                     if ( first == 1 && s[ 0 ] == '0' && s[ 1 ] != '.' ) {
2779                               return 0;
2780                     }
2781                     first = 0;
2782           }
2783 
2784           return 1;
2785 }
2786