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 */ 65tool_type_t tool_type; 66int contoper = 0; 67int debug = 0; 68char *infile = NULL; 69int dont = 0; 70int nocanon = 0; 71int referrals = 0; 72int verbose = 0; 73int ldif = 0; 74ber_len_t ldif_wrap = 0; 75char *prog = NULL; 76 77/* connection */ 78char *ldapuri = NULL; 79int use_tls = 0; 80int protocol = -1; 81int version = 0; 82 83/* authc/authz */ 84int authmethod = -1; 85char *binddn = NULL; 86int want_bindpw = 0; 87struct berval passwd = { 0, NULL }; 88char *pw_file = NULL; 89#ifdef HAVE_CYRUS_SASL 90unsigned sasl_flags = LDAP_SASL_AUTOMATIC; 91char *sasl_realm = NULL; 92char *sasl_authc_id = NULL; 93char *sasl_authz_id = NULL; 94char *sasl_mech = NULL; 95char *sasl_secprops = NULL; 96#endif 97 98/* controls */ 99int assertctl; 100char *assertion = NULL; 101struct berval assertionvalue = BER_BVNULL; 102char *authzid = NULL; 103int 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 107char *proxydn = NULL; 108#endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */ 109int manageDIT = 0; 110int manageDSAit = 0; 111int noop = 0; 112int ppolicy = 0; 113int preread = 0; 114static char *preread_attrs = NULL; 115int postread = 0; 116static char *postread_attrs = NULL; 117ber_int_t pr_morePagedResults = 1; 118struct berval pr_cookie = { 0, NULL }; 119#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR 120int chaining = 0; 121static int chainingResolve = -1; 122static int chainingContinuation = -1; 123#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ 124#ifdef LDAP_CONTROL_X_SESSION_TRACKING 125static int sessionTracking = 0; 126static char *sessionTrackingName; 127struct berval stValue; 128#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 129ber_int_t vlvPos; 130ber_int_t vlvCount; 131struct berval *vlvContext; 132static int bauthzid; 133 134LDAPControl *unknown_ctrls = NULL; 135int unknown_ctrls_num = 0; 136 137/* options */ 138struct timeval nettimeout = { -1 , 0 }; 139 140typedef int (*print_ctrl_fn)( LDAP *ld, LDAPControl *ctrl ); 141 142static int print_preread( LDAP *ld, LDAPControl *ctrl ); 143static int print_postread( LDAP *ld, LDAPControl *ctrl ); 144static int print_paged_results( LDAP *ld, LDAPControl *ctrl ); 145static int print_psearch( LDAP *ld, LDAPControl *ctrl ); 146#ifdef LDAP_CONTROL_AUTHZID_RESPONSE 147static int print_authzid( LDAP *ld, LDAPControl *ctrl ); 148#endif 149#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 150static int print_ppolicy( LDAP *ld, LDAPControl *ctrl ); 151#endif 152static int print_sss( LDAP *ld, LDAPControl *ctrl ); 153static int print_vlv( LDAP *ld, LDAPControl *ctrl ); 154#ifdef LDAP_CONTROL_X_DEREF 155static int print_deref( LDAP *ld, LDAPControl *ctrl ); 156#endif 157#ifdef LDAP_CONTROL_X_WHATFAILED 158static int print_whatfailed( LDAP *ld, LDAPControl *ctrl ); 159#endif 160static int print_syncstate( LDAP *ld, LDAPControl *ctrl ); 161static int print_syncdone( LDAP *ld, LDAPControl *ctrl ); 162#ifdef LDAP_CONTROL_X_DIRSYNC 163static int print_dirsync( LDAP *ld, LDAPControl *ctrl ); 164#endif 165#ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY 166static int print_account_usability( LDAP *ld, LDAPControl *ctrl ); 167#endif 168#ifdef LDAP_CONTROL_X_PASSWORD_EXPIRED 169static int print_netscape_pwexpired( LDAP *ld, LDAPControl *ctrl ); 170static int print_netscape_pwexpiring( LDAP *ld, LDAPControl *ctrl ); 171#endif 172 173static 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" */ 213enum { Intr_None = 0, Intr_Abandon, Intr_Cancel, Intr_Ignore }; 214static volatile sig_atomic_t gotintr, abcan; 215 216int backlog; 217 218 219#ifdef LDAP_CONTROL_X_SESSION_TRACKING 220static int 221st_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 268RETSIGTYPE 269do_sig( int sig ) 270{ 271 gotintr = abcan; 272} 273 274void 275tool_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 283void 284tool_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 321void 322tool_common_usage( void ) 323{ 324 static const char *const descriptions[] = { 325N_(" -d level set LDAP debugging level to `level'\n"), 326N_(" -D binddn bind DN\n"), 327N_(" -e [!]<ext>[=<extparam>] general extensions (! indicates criticality)\n") 328N_(" [!]assert=<filter> (RFC 4528; a RFC 4515 Filter string)\n") 329N_(" [!]authzid=<authzid> (RFC 4370; \"dn:<dn>\" or \"u:<user>\")\n") 330N_(" [!]bauthzid (RFC 3829)\n") 331#ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ 332#if 0 333 /* non-advertized support for proxyDN */ 334N_(" [!]proxydn=<dn> (a RFC 4514 DN string)\n") 335#endif 336#endif 337#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR 338N_(" [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n") 339N_(" one of \"chainingPreferred\", \"chainingRequired\",\n") 340N_(" \"referralsPreferred\", \"referralsRequired\"\n") 341#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ 342N_(" [!]manageDSAit (RFC 3296)\n") 343N_(" [!]noop\n") 344#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 345N_(" ppolicy\n") 346#endif 347N_(" [!]postread[=<attrs>] (RFC 4527; comma-separated attr list)\n") 348N_(" [!]preread[=<attrs>] (RFC 4527; comma-separated attr list)\n") 349N_(" [!]relax\n") 350#ifdef LDAP_CONTROL_X_SESSION_TRACKING 351N_(" [!]sessiontracking[=<username>]\n") 352#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 353N_(" 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") 356N_(" -H URI LDAP Uniform Resource Identifier(s)\n"), 357N_(" -I use SASL Interactive mode\n"), 358N_(" -n show what would be done but don't actually do it\n"), 359N_(" -N do not use reverse DNS to canonicalize SASL host name\n"), 360N_(" -O props SASL security properties\n"), 361N_(" -o <opt>[=<optparam>] any libldap ldap.conf options, plus\n"), 362N_(" ldif_wrap=<width> (in columns, or \"no\" for no wrapping)\n"), 363N_(" nettimeout=<timeout> (in seconds, or \"none\" or \"max\")\n"), 364N_(" -Q use SASL Quiet mode\n"), 365N_(" -R realm SASL realm\n"), 366N_(" -U authcid SASL authentication identity\n"), 367N_(" -v run in verbose mode (diagnostics to standard output)\n"), 368N_(" -V print version info (-VV only)\n"), 369N_(" -w passwd bind password (for simple authentication)\n"), 370N_(" -W prompt for bind password\n"), 371N_(" -x Simple authentication\n"), 372N_(" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"), 373N_(" -y file Read password from file\n"), 374N_(" -Y mech SASL mechanism\n"), 375N_(" -Z Start TLS request (-ZZ to require successful response)\n"), 376NULL 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 390void 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 419void 420tool_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 1168LDAP * 1169tool_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 1288dnssrv_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 1403void 1404tool_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 1658void 1659tool_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 1670void 1671tool_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. */ 1682void 1683tool_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 1949int 1950tool_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 1976static int 1977print_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 2039static int 2040print_preread( LDAP *ld, LDAPControl *ctrl ) 2041{ 2042 static struct berval what = BER_BVC( "preread" ); 2043 2044 return print_prepostread( ld, ctrl, &what ); 2045} 2046 2047static int 2048print_postread( LDAP *ld, LDAPControl *ctrl ) 2049{ 2050 static struct berval what = BER_BVC( "postread" ); 2051 2052 return print_prepostread( ld, ctrl, &what ); 2053} 2054 2055static int 2056print_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 2110static int 2111print_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 2166static int 2167print_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 2186static int 2187print_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 2227static int 2228print_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 2305done:; 2306 ldap_derefresponse_free( drhead ); 2307 2308 return rc; 2309} 2310#endif 2311 2312#ifdef LDAP_CONTROL_X_WHATFAILED 2313static int 2314print_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 2349static int 2350print_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 2425static int 2426print_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 2477static int 2478print_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 2510static int 2511print_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 2528static int 2529print_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 2565static int 2566print_netscape_pwexpired( LDAP *ld, LDAPControl *ctrl ) 2567{ 2568 printf(_("# PasswordExpired control\n") ); 2569 return 0; 2570} 2571 2572static int 2573print_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 2587static int 2588print_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 2657void 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 2741int 2742tool_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 2756int 2757tool_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