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