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