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