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