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