1 /* $NetBSD: common.c,v 1.1.1.3 2010/03/08 02:14:20 lukem 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 if ( use_tls ) { 1290 rc = ldap_start_tls_s( ld, NULL, NULL ); 1291 if ( rc != LDAP_SUCCESS ) { 1292 char *msg=NULL; 1293 ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); 1294 tool_perror( "ldap_start_tls", rc, NULL, NULL, msg, NULL ); 1295 ldap_memfree(msg); 1296 if ( use_tls > 1 ) { 1297 exit( EXIT_FAILURE ); 1298 } 1299 } 1300 } 1301 1302 if ( nettimeout.tv_sec > 0 ) { 1303 if ( ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, (void *) &nettimeout ) 1304 != LDAP_OPT_SUCCESS ) 1305 { 1306 fprintf( stderr, "Could not set LDAP_OPT_NETWORK_TIMEOUT %ld\n", 1307 (long)nettimeout.tv_sec ); 1308 exit( EXIT_FAILURE ); 1309 } 1310 } 1311 } 1312 1313 return ld; 1314 } 1315 1316 1317 void 1318 tool_bind( LDAP *ld ) 1319 { 1320 LDAPControl **sctrlsp = NULL; 1321 LDAPControl *sctrls[3]; 1322 LDAPControl sctrl[3]; 1323 int nsctrls = 0; 1324 1325 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 1326 if ( ppolicy ) { 1327 LDAPControl c; 1328 c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST; 1329 c.ldctl_value.bv_val = NULL; 1330 c.ldctl_value.bv_len = 0; 1331 c.ldctl_iscritical = 0; 1332 sctrl[nsctrls] = c; 1333 sctrls[nsctrls] = &sctrl[nsctrls]; 1334 sctrls[++nsctrls] = NULL; 1335 } 1336 #endif 1337 1338 #ifdef LDAP_CONTROL_X_SESSION_TRACKING 1339 if ( sessionTracking ) { 1340 LDAPControl c; 1341 1342 if (stValue.bv_val == NULL && st_value( ld, &stValue ) ) { 1343 exit( EXIT_FAILURE ); 1344 } 1345 1346 c.ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; 1347 c.ldctl_iscritical = 0; 1348 ber_dupbv( &c.ldctl_value, &stValue ); 1349 1350 sctrl[nsctrls] = c; 1351 sctrls[nsctrls] = &sctrl[nsctrls]; 1352 sctrls[++nsctrls] = NULL; 1353 } 1354 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 1355 1356 if ( nsctrls ) { 1357 sctrlsp = sctrls; 1358 } 1359 1360 assert( nsctrls < (int) (sizeof(sctrls)/sizeof(sctrls[0])) ); 1361 1362 if ( authmethod == LDAP_AUTH_SASL ) { 1363 #ifdef HAVE_CYRUS_SASL 1364 void *defaults; 1365 int rc; 1366 1367 if( sasl_secprops != NULL ) { 1368 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, 1369 (void *) sasl_secprops ); 1370 1371 if( rc != LDAP_OPT_SUCCESS ) { 1372 fprintf( stderr, 1373 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", 1374 sasl_secprops ); 1375 exit( LDAP_LOCAL_ERROR ); 1376 } 1377 } 1378 1379 defaults = lutil_sasl_defaults( ld, 1380 sasl_mech, 1381 sasl_realm, 1382 sasl_authc_id, 1383 passwd.bv_val, 1384 sasl_authz_id ); 1385 1386 rc = ldap_sasl_interactive_bind_s( ld, binddn, sasl_mech, 1387 sctrlsp, 1388 NULL, sasl_flags, lutil_sasl_interact, defaults ); 1389 1390 lutil_sasl_freedefs( defaults ); 1391 if( rc != LDAP_SUCCESS ) { 1392 char *msg=NULL; 1393 ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); 1394 tool_perror( "ldap_sasl_interactive_bind_s", 1395 rc, NULL, NULL, msg, NULL ); 1396 ldap_memfree(msg); 1397 exit( rc ); 1398 } 1399 #else 1400 fprintf( stderr, "%s: not compiled with SASL support\n", prog ); 1401 exit( LDAP_NOT_SUPPORTED ); 1402 #endif 1403 } else { 1404 int msgid, err, rc; 1405 LDAPMessage *result; 1406 LDAPControl **ctrls; 1407 char msgbuf[256]; 1408 char *matched = NULL; 1409 char *info = NULL; 1410 char **refs = NULL; 1411 1412 msgbuf[0] = 0; 1413 1414 { 1415 /* simple bind */ 1416 rc = ldap_sasl_bind( ld, binddn, LDAP_SASL_SIMPLE, &passwd, 1417 sctrlsp, NULL, &msgid ); 1418 if ( msgid == -1 ) { 1419 tool_perror( "ldap_sasl_bind(SIMPLE)", rc, 1420 NULL, NULL, NULL, NULL ); 1421 exit( rc ); 1422 } 1423 } 1424 1425 rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); 1426 if ( rc == -1 ) { 1427 tool_perror( "ldap_result", -1, NULL, NULL, NULL, NULL ); 1428 exit( LDAP_LOCAL_ERROR ); 1429 } 1430 1431 if ( rc == 0 ) { 1432 tool_perror( "ldap_result", LDAP_TIMEOUT, NULL, NULL, NULL, NULL ); 1433 exit( LDAP_LOCAL_ERROR ); 1434 } 1435 1436 rc = ldap_parse_result( ld, result, &err, &matched, &info, &refs, 1437 &ctrls, 1 ); 1438 if ( rc != LDAP_SUCCESS ) { 1439 tool_perror( "ldap_bind parse result", rc, NULL, matched, info, refs ); 1440 exit( LDAP_LOCAL_ERROR ); 1441 } 1442 1443 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 1444 if ( ctrls && ppolicy ) { 1445 LDAPControl *ctrl; 1446 int expire, grace, len = 0; 1447 LDAPPasswordPolicyError pErr = -1; 1448 1449 ctrl = ldap_control_find( LDAP_CONTROL_PASSWORDPOLICYRESPONSE, 1450 ctrls, NULL ); 1451 1452 if ( ctrl && ldap_parse_passwordpolicy_control( ld, ctrl, 1453 &expire, &grace, &pErr ) == LDAP_SUCCESS ) 1454 { 1455 if ( pErr != PP_noError ){ 1456 msgbuf[0] = ';'; 1457 msgbuf[1] = ' '; 1458 strcpy( msgbuf+2, ldap_passwordpolicy_err2txt( pErr )); 1459 len = strlen( msgbuf ); 1460 } 1461 if ( expire >= 0 ) { 1462 sprintf( msgbuf+len, 1463 " (Password expires in %d seconds)", 1464 expire ); 1465 } else if ( grace >= 0 ) { 1466 sprintf( msgbuf+len, 1467 " (Password expired, %d grace logins remain)", 1468 grace ); 1469 } 1470 } 1471 } 1472 #endif 1473 1474 if ( ctrls ) { 1475 ldap_controls_free( ctrls ); 1476 } 1477 1478 if ( err != LDAP_SUCCESS 1479 || msgbuf[0] 1480 || ( matched && matched[ 0 ] ) 1481 || ( info && info[ 0 ] ) 1482 || refs ) 1483 { 1484 tool_perror( "ldap_bind", err, msgbuf, matched, info, refs ); 1485 1486 if( matched ) ber_memfree( matched ); 1487 if( info ) ber_memfree( info ); 1488 if( refs ) ber_memvfree( (void **)refs ); 1489 1490 if ( err != LDAP_SUCCESS ) exit( err ); 1491 } 1492 } 1493 } 1494 1495 void 1496 tool_unbind( LDAP *ld ) 1497 { 1498 int err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL ); 1499 1500 if ( err != LDAP_OPT_SUCCESS ) { 1501 fprintf( stderr, "Could not unset controls\n"); 1502 } 1503 1504 (void) ldap_unbind_ext( ld, NULL, NULL ); 1505 } 1506 1507 1508 /* Set server controls. Add controls extra_c[0..count-1], if set. */ 1509 void 1510 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) 1511 { 1512 int i = 0, j, crit = 0, err; 1513 LDAPControl c[16], **ctrls; 1514 1515 if ( ! ( assertctl 1516 || authzid 1517 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ 1518 || proxydn 1519 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */ 1520 || manageDIT 1521 || manageDSAit 1522 || noop 1523 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 1524 || ppolicy 1525 #endif 1526 || preread 1527 || postread 1528 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR 1529 || chaining 1530 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ 1531 #ifdef LDAP_CONTROL_X_SESSION_TRACKING 1532 || sessionTracking 1533 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 1534 || count 1535 || unknown_ctrls_num ) ) 1536 { 1537 return; 1538 } 1539 1540 ctrls = (LDAPControl**) malloc(sizeof(c) + (count + unknown_ctrls_num + 1)*sizeof(LDAPControl*)); 1541 if ( ctrls == NULL ) { 1542 fprintf( stderr, "No memory\n" ); 1543 exit( EXIT_FAILURE ); 1544 } 1545 1546 if ( assertctl ) { 1547 if ( BER_BVISNULL( &assertionvalue ) ) { 1548 err = ldap_create_assertion_control_value( ld, 1549 assertion, &assertionvalue ); 1550 if ( err ) { 1551 fprintf( stderr, 1552 "Unable to create assertion value " 1553 "\"%s\" (%d)\n", assertion, err ); 1554 } 1555 } 1556 1557 c[i].ldctl_oid = LDAP_CONTROL_ASSERT; 1558 c[i].ldctl_value = assertionvalue; 1559 c[i].ldctl_iscritical = assertctl > 1; 1560 ctrls[i] = &c[i]; 1561 i++; 1562 } 1563 1564 if ( authzid ) { 1565 c[i].ldctl_value.bv_val = authzid; 1566 c[i].ldctl_value.bv_len = strlen( authzid ); 1567 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; 1568 c[i].ldctl_iscritical = 1; 1569 ctrls[i] = &c[i]; 1570 i++; 1571 } 1572 1573 #ifdef LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ 1574 /* NOTE: doesn't need an extra count because it's incompatible 1575 * with authzid */ 1576 if ( proxydn ) { 1577 BerElementBuffer berbuf; 1578 BerElement *ber = (BerElement *)&berbuf; 1579 1580 ber_init2( ber, NULL, LBER_USE_DER ); 1581 1582 if ( ber_printf( ber, "s", proxydn ) == -1 ) { 1583 exit( EXIT_FAILURE ); 1584 } 1585 1586 if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) { 1587 exit( EXIT_FAILURE ); 1588 } 1589 1590 c[i].ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ; 1591 c[i].ldctl_iscritical = 1; 1592 ctrls[i] = &c[i]; 1593 i++; 1594 } 1595 #endif /* LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ */ 1596 1597 if ( manageDIT ) { 1598 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDIT; 1599 BER_BVZERO( &c[i].ldctl_value ); 1600 c[i].ldctl_iscritical = manageDIT > 1; 1601 ctrls[i] = &c[i]; 1602 i++; 1603 } 1604 1605 if ( manageDSAit ) { 1606 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; 1607 BER_BVZERO( &c[i].ldctl_value ); 1608 c[i].ldctl_iscritical = manageDSAit > 1; 1609 ctrls[i] = &c[i]; 1610 i++; 1611 } 1612 1613 if ( noop ) { 1614 c[i].ldctl_oid = LDAP_CONTROL_NOOP; 1615 BER_BVZERO( &c[i].ldctl_value ); 1616 c[i].ldctl_iscritical = noop > 1; 1617 ctrls[i] = &c[i]; 1618 i++; 1619 } 1620 1621 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 1622 if ( ppolicy ) { 1623 c[i].ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST; 1624 BER_BVZERO( &c[i].ldctl_value ); 1625 c[i].ldctl_iscritical = 0; 1626 ctrls[i] = &c[i]; 1627 i++; 1628 } 1629 #endif 1630 1631 if ( preread ) { 1632 BerElementBuffer berbuf; 1633 BerElement *ber = (BerElement *)&berbuf; 1634 char **attrs = NULL; 1635 1636 if( preread_attrs ) { 1637 attrs = ldap_str2charray( preread_attrs, "," ); 1638 } 1639 1640 ber_init2( ber, NULL, LBER_USE_DER ); 1641 1642 if( ber_printf( ber, "{v}", attrs ) == -1 ) { 1643 fprintf( stderr, "preread attrs encode failed.\n" ); 1644 exit( EXIT_FAILURE ); 1645 } 1646 1647 err = ber_flatten2( ber, &c[i].ldctl_value, 0 ); 1648 if( err < 0 ) { 1649 fprintf( stderr, "preread flatten failed (%d)\n", err ); 1650 exit( EXIT_FAILURE ); 1651 } 1652 1653 c[i].ldctl_oid = LDAP_CONTROL_PRE_READ; 1654 c[i].ldctl_iscritical = preread > 1; 1655 ctrls[i] = &c[i]; 1656 i++; 1657 1658 if( attrs ) ldap_charray_free( attrs ); 1659 } 1660 1661 if ( postread ) { 1662 BerElementBuffer berbuf; 1663 BerElement *ber = (BerElement *)&berbuf; 1664 char **attrs = NULL; 1665 1666 if( postread_attrs ) { 1667 attrs = ldap_str2charray( postread_attrs, "," ); 1668 } 1669 1670 ber_init2( ber, NULL, LBER_USE_DER ); 1671 1672 if( ber_printf( ber, "{v}", attrs ) == -1 ) { 1673 fprintf( stderr, "postread attrs encode failed.\n" ); 1674 exit( EXIT_FAILURE ); 1675 } 1676 1677 err = ber_flatten2( ber, &c[i].ldctl_value, 0 ); 1678 if( err < 0 ) { 1679 fprintf( stderr, "postread flatten failed (%d)\n", err ); 1680 exit( EXIT_FAILURE ); 1681 } 1682 1683 c[i].ldctl_oid = LDAP_CONTROL_POST_READ; 1684 c[i].ldctl_iscritical = postread > 1; 1685 ctrls[i] = &c[i]; 1686 i++; 1687 1688 if( attrs ) ldap_charray_free( attrs ); 1689 } 1690 1691 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR 1692 if ( chaining ) { 1693 if ( chainingResolve > -1 ) { 1694 BerElementBuffer berbuf; 1695 BerElement *ber = (BerElement *)&berbuf; 1696 1697 ber_init2( ber, NULL, LBER_USE_DER ); 1698 1699 err = ber_printf( ber, "{e" /* } */, chainingResolve ); 1700 if ( err == -1 ) { 1701 ber_free( ber, 1 ); 1702 fprintf( stderr, _("Chaining behavior control encoding error!\n") ); 1703 exit( EXIT_FAILURE ); 1704 } 1705 1706 if ( chainingContinuation > -1 ) { 1707 err = ber_printf( ber, "e", chainingContinuation ); 1708 if ( err == -1 ) { 1709 ber_free( ber, 1 ); 1710 fprintf( stderr, _("Chaining behavior control encoding error!\n") ); 1711 exit( EXIT_FAILURE ); 1712 } 1713 } 1714 1715 err = ber_printf( ber, /* { */ "N}" ); 1716 if ( err == -1 ) { 1717 ber_free( ber, 1 ); 1718 fprintf( stderr, _("Chaining behavior control encoding error!\n") ); 1719 exit( EXIT_FAILURE ); 1720 } 1721 1722 if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) { 1723 exit( EXIT_FAILURE ); 1724 } 1725 1726 } else { 1727 BER_BVZERO( &c[i].ldctl_value ); 1728 } 1729 1730 c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR; 1731 c[i].ldctl_iscritical = chaining > 1; 1732 ctrls[i] = &c[i]; 1733 i++; 1734 } 1735 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ 1736 1737 #ifdef LDAP_CONTROL_X_SESSION_TRACKING 1738 if ( sessionTracking ) { 1739 if ( stValue.bv_val == NULL && st_value( ld, &stValue ) ) { 1740 exit( EXIT_FAILURE ); 1741 } 1742 1743 c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; 1744 c[i].ldctl_iscritical = 0; 1745 ber_dupbv( &c[i].ldctl_value, &stValue ); 1746 1747 ctrls[i] = &c[i]; 1748 i++; 1749 } 1750 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 1751 1752 while ( count-- ) { 1753 ctrls[i++] = extra_c++; 1754 } 1755 for ( count = 0; count < unknown_ctrls_num; count++ ) { 1756 ctrls[i++] = &unknown_ctrls[count]; 1757 } 1758 ctrls[i] = NULL; 1759 1760 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); 1761 1762 if ( err != LDAP_OPT_SUCCESS ) { 1763 for ( j = 0; j < i; j++ ) { 1764 if ( ctrls[j]->ldctl_iscritical ) crit = 1; 1765 } 1766 fprintf( stderr, "Could not set %scontrols\n", 1767 crit ? "critical " : "" ); 1768 } 1769 1770 free( ctrls ); 1771 if ( crit ) { 1772 exit( EXIT_FAILURE ); 1773 } 1774 } 1775 1776 int 1777 tool_check_abandon( LDAP *ld, int msgid ) 1778 { 1779 int rc; 1780 1781 switch ( gotintr ) { 1782 case Intr_Cancel: 1783 rc = ldap_cancel_s( ld, msgid, NULL, NULL ); 1784 fprintf( stderr, "got interrupt, cancel got %d: %s\n", 1785 rc, ldap_err2string( rc ) ); 1786 return -1; 1787 1788 case Intr_Abandon: 1789 rc = ldap_abandon_ext( ld, msgid, NULL, NULL ); 1790 fprintf( stderr, "got interrupt, abandon got %d: %s\n", 1791 rc, ldap_err2string( rc ) ); 1792 return -1; 1793 1794 case Intr_Ignore: 1795 /* just unbind, ignoring the request */ 1796 return -1; 1797 } 1798 1799 return 0; 1800 } 1801 1802 static int 1803 print_prepostread( LDAP *ld, LDAPControl *ctrl, struct berval *what) 1804 { 1805 BerElement *ber; 1806 struct berval bv; 1807 1808 tool_write_ldif( LDIF_PUT_COMMENT, "==> ", 1809 what->bv_val, what->bv_len ); 1810 ber = ber_init( &ctrl->ldctl_value ); 1811 if ( ber == NULL ) { 1812 /* error? */ 1813 return 1; 1814 1815 } else if ( ber_scanf( ber, "{m{" /*}}*/, &bv ) == LBER_ERROR ) { 1816 /* error? */ 1817 return 1; 1818 1819 } else { 1820 tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len ); 1821 1822 while ( ber_scanf( ber, "{m" /*}*/, &bv ) != LBER_ERROR ) { 1823 int i; 1824 BerVarray vals = NULL; 1825 1826 if ( ber_scanf( ber, "[W]", &vals ) == LBER_ERROR || 1827 vals == NULL ) 1828 { 1829 /* error? */ 1830 return 1; 1831 } 1832 1833 for ( i = 0; vals[ i ].bv_val != NULL; i++ ) { 1834 tool_write_ldif( 1835 ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1836 bv.bv_val, vals[ i ].bv_val, vals[ i ].bv_len ); 1837 } 1838 1839 ber_bvarray_free( vals ); 1840 } 1841 } 1842 1843 if ( ber != NULL ) { 1844 ber_free( ber, 1 ); 1845 } 1846 1847 tool_write_ldif( LDIF_PUT_COMMENT, "<== ", 1848 what->bv_val, what->bv_len ); 1849 1850 return 0; 1851 } 1852 1853 static int 1854 print_preread( LDAP *ld, LDAPControl *ctrl ) 1855 { 1856 static struct berval what = BER_BVC( "preread" ); 1857 1858 return print_prepostread( ld, ctrl, &what ); 1859 } 1860 1861 static int 1862 print_postread( LDAP *ld, LDAPControl *ctrl ) 1863 { 1864 static struct berval what = BER_BVC( "postread" ); 1865 1866 return print_prepostread( ld, ctrl, &what ); 1867 } 1868 1869 static int 1870 print_paged_results( LDAP *ld, LDAPControl *ctrl ) 1871 { 1872 ber_int_t estimate; 1873 1874 /* note: pr_cookie is being malloced; it's freed 1875 * the next time the control is sent, but the last 1876 * time it's not; we don't care too much, because 1877 * the last time an empty value is returned... */ 1878 if ( ldap_parse_pageresponse_control( ld, ctrl, &estimate, &pr_cookie ) 1879 != LDAP_SUCCESS ) 1880 { 1881 /* error? */ 1882 return 1; 1883 1884 } else { 1885 /* FIXME: check buffer overflow */ 1886 char buf[ BUFSIZ ], *ptr = buf; 1887 1888 if ( estimate > 0 ) { 1889 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 1890 "estimate=%d", estimate ); 1891 } 1892 1893 if ( pr_cookie.bv_len > 0 ) { 1894 struct berval bv; 1895 1896 bv.bv_len = LUTIL_BASE64_ENCODE_LEN( 1897 pr_cookie.bv_len ) + 1; 1898 bv.bv_val = ber_memalloc( bv.bv_len + 1 ); 1899 1900 bv.bv_len = lutil_b64_ntop( 1901 (unsigned char *) pr_cookie.bv_val, 1902 pr_cookie.bv_len, 1903 bv.bv_val, bv.bv_len ); 1904 1905 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 1906 "%scookie=%s", ptr == buf ? "" : " ", 1907 bv.bv_val ); 1908 1909 ber_memfree( bv.bv_val ); 1910 1911 pr_morePagedResults = 1; 1912 1913 } else { 1914 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 1915 "%scookie=", ptr == buf ? "" : " " ); 1916 } 1917 1918 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1919 "pagedresults", buf, ptr - buf ); 1920 } 1921 1922 return 0; 1923 } 1924 1925 static int 1926 print_sss( LDAP *ld, LDAPControl *ctrl ) 1927 { 1928 int rc; 1929 ber_int_t err; 1930 char *attr; 1931 1932 rc = ldap_parse_sortresponse_control( ld, ctrl, &err, &attr ); 1933 if ( rc == LDAP_SUCCESS ) { 1934 char buf[ BUFSIZ ]; 1935 rc = snprintf( buf, sizeof(buf), "(%d) %s%s%s", 1936 err, ldap_err2string(err), attr ? " " : "", attr ? attr : "" ); 1937 1938 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1939 "sortResult", buf, rc ); 1940 } 1941 1942 return rc; 1943 } 1944 1945 static int 1946 print_vlv( LDAP *ld, LDAPControl *ctrl ) 1947 { 1948 int rc; 1949 ber_int_t err; 1950 struct berval bv; 1951 1952 rc = ldap_parse_vlvresponse_control( ld, ctrl, &vlvPos, &vlvCount, 1953 &vlvContext, &err ); 1954 if ( rc == LDAP_SUCCESS ) { 1955 char buf[ BUFSIZ ]; 1956 1957 if ( vlvContext && vlvContext->bv_len > 0 ) { 1958 bv.bv_len = LUTIL_BASE64_ENCODE_LEN( 1959 vlvContext->bv_len ) + 1; 1960 bv.bv_val = ber_memalloc( bv.bv_len + 1 ); 1961 1962 bv.bv_len = lutil_b64_ntop( 1963 (unsigned char *) vlvContext->bv_val, 1964 vlvContext->bv_len, 1965 bv.bv_val, bv.bv_len ); 1966 } else { 1967 bv.bv_val = ""; 1968 bv.bv_len = 0; 1969 } 1970 1971 rc = snprintf( buf, sizeof(buf), "pos=%d count=%d context=%s (%d) %s", 1972 vlvPos, vlvCount, bv.bv_val, 1973 err, ldap_err2string(err)); 1974 1975 if ( bv.bv_len ) 1976 ber_memfree( bv.bv_val ); 1977 1978 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1979 "vlvResult", buf, rc ); 1980 } 1981 1982 return rc; 1983 } 1984 1985 #ifdef LDAP_CONTROL_X_DEREF 1986 static int 1987 print_deref( LDAP *ld, LDAPControl *ctrl ) 1988 { 1989 LDAPDerefRes *drhead = NULL, *dr; 1990 int rc; 1991 1992 rc = ldap_parse_derefresponse_control( ld, ctrl, &drhead ); 1993 if ( rc != LDAP_SUCCESS ) { 1994 return rc; 1995 } 1996 1997 for ( dr = drhead; dr != NULL; dr = dr->next ) { 1998 LDAPDerefVal *dv; 1999 ber_len_t len; 2000 char *buf, *ptr; 2001 2002 len = strlen( dr->derefAttr ) + STRLENOF(": "); 2003 2004 for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) { 2005 if ( dv->vals != NULL ) { 2006 int j; 2007 ber_len_t tlen = strlen(dv->type); 2008 2009 for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) { 2010 len += STRLENOF("<:=>;") + tlen + 4*((dv->vals[ j ].bv_len - 1)/3 + 1); 2011 } 2012 } 2013 } 2014 len += dr->derefVal.bv_len + STRLENOF("\n"); 2015 buf = ldap_memalloc( len + 1 ); 2016 if ( buf == NULL ) { 2017 rc = LDAP_NO_MEMORY; 2018 goto done; 2019 } 2020 2021 ptr = buf; 2022 ptr = lutil_strcopy( ptr, dr->derefAttr ); 2023 *ptr++ = ':'; 2024 *ptr++ = ' '; 2025 for ( dv = dr->attrVals; dv != NULL; dv = dv->next ) { 2026 if ( dv->vals != NULL ) { 2027 int j; 2028 for ( j = 0; dv->vals[ j ].bv_val != NULL; j++ ) { 2029 int k = ldif_is_not_printable( dv->vals[ j ].bv_val, dv->vals[ j ].bv_len ); 2030 2031 *ptr++ = '<'; 2032 ptr = lutil_strcopy( ptr, dv->type ); 2033 if ( k ) { 2034 *ptr++ = ':'; 2035 } 2036 *ptr++ = '='; 2037 if ( k ) { 2038 k = lutil_b64_ntop( 2039 (unsigned char *) dv->vals[ j ].bv_val, 2040 dv->vals[ j ].bv_len, 2041 ptr, buf + len - ptr ); 2042 assert( k >= 0 ); 2043 ptr += k; 2044 2045 } else { 2046 ptr = lutil_memcopy( ptr, dv->vals[ j ].bv_val, dv->vals[ j ].bv_len ); 2047 } 2048 *ptr++ = '>'; 2049 *ptr++ = ';'; 2050 } 2051 } 2052 } 2053 ptr = lutil_strncopy( ptr, dr->derefVal.bv_val, dr->derefVal.bv_len ); 2054 *ptr++ = '\n'; 2055 *ptr = '\0'; 2056 assert( ptr <= buf + len ); 2057 2058 tool_write_ldif( LDIF_PUT_COMMENT, NULL, buf, ptr - buf); 2059 2060 ldap_memfree( buf ); 2061 } 2062 2063 rc = LDAP_SUCCESS; 2064 2065 done:; 2066 ldap_derefresponse_free( drhead ); 2067 2068 return rc; 2069 } 2070 #endif 2071 2072 #ifdef LDAP_CONTROL_X_WHATFAILED 2073 static int 2074 print_whatfailed( LDAP *ld, LDAPControl *ctrl ) 2075 { 2076 BerElement *ber; 2077 ber_tag_t tag; 2078 ber_len_t siz; 2079 BerVarray bva = NULL; 2080 2081 /* Create a BerElement from the berval returned in the control. */ 2082 ber = ber_init( &ctrl->ldctl_value ); 2083 2084 if ( ber == NULL ) { 2085 return LDAP_NO_MEMORY; 2086 } 2087 2088 siz = sizeof(struct berval); 2089 tag = ber_scanf( ber, "[M]", &bva, &siz, 0 ); 2090 if ( tag != LBER_ERROR ) { 2091 int i; 2092 2093 tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 ); 2094 2095 for ( i = 0; bva[i].bv_val != NULL; i++ ) { 2096 tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len ); 2097 } 2098 2099 ldap_memfree( bva ); 2100 } 2101 2102 ber_free( ber, 1 ); 2103 2104 2105 return 0; 2106 } 2107 #endif 2108 2109 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST 2110 static int 2111 print_ppolicy( LDAP *ld, LDAPControl *ctrl ) 2112 { 2113 int expire = 0, grace = 0, rc; 2114 LDAPPasswordPolicyError pperr; 2115 2116 rc = ldap_parse_passwordpolicy_control( ld, ctrl, 2117 &expire, &grace, &pperr ); 2118 if ( rc == LDAP_SUCCESS ) { 2119 char buf[ BUFSIZ ], *ptr = buf; 2120 2121 if ( expire != -1 ) { 2122 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 2123 "expire=%d", expire ); 2124 } 2125 2126 if ( grace != -1 ) { 2127 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 2128 "%sgrace=%d", ptr == buf ? "" : " ", grace ); 2129 } 2130 2131 if ( pperr != PP_noError ) { 2132 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 2133 "%serror=%d (%s)", ptr == buf ? "" : " ", 2134 pperr, 2135 ldap_passwordpolicy_err2txt( pperr ) ); 2136 } 2137 2138 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 2139 "ppolicy", buf, ptr - buf ); 2140 } 2141 2142 return rc; 2143 } 2144 #endif 2145 2146 void tool_print_ctrls( 2147 LDAP *ld, 2148 LDAPControl **ctrls ) 2149 { 2150 int i; 2151 char *ptr; 2152 2153 for ( i = 0; ctrls[i] != NULL; i++ ) { 2154 /* control: OID criticality base64value */ 2155 struct berval b64 = BER_BVNULL; 2156 ber_len_t len; 2157 char *str; 2158 int j; 2159 2160 /* FIXME: there might be cases where a control has NULL OID; 2161 * this makes little sense, especially when returned by the 2162 * server, but libldap happily allows it */ 2163 if ( ctrls[i]->ldctl_oid == NULL ) { 2164 continue; 2165 } 2166 2167 len = ldif ? 2 : 0; 2168 len += strlen( ctrls[i]->ldctl_oid ); 2169 2170 /* add enough for space after OID and the critical value itself */ 2171 len += ctrls[i]->ldctl_iscritical 2172 ? sizeof("true") : sizeof("false"); 2173 2174 /* convert to base64 */ 2175 if ( !BER_BVISNULL( &ctrls[i]->ldctl_value ) ) { 2176 b64.bv_len = LUTIL_BASE64_ENCODE_LEN( 2177 ctrls[i]->ldctl_value.bv_len ) + 1; 2178 b64.bv_val = ber_memalloc( b64.bv_len + 1 ); 2179 2180 b64.bv_len = lutil_b64_ntop( 2181 (unsigned char *) ctrls[i]->ldctl_value.bv_val, 2182 ctrls[i]->ldctl_value.bv_len, 2183 b64.bv_val, b64.bv_len ); 2184 } 2185 2186 if ( b64.bv_len ) { 2187 len += 1 + b64.bv_len; 2188 } 2189 2190 ptr = str = malloc( len + 1 ); 2191 if ( ldif ) { 2192 ptr = lutil_strcopy( ptr, ": " ); 2193 } 2194 ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_oid ); 2195 ptr = lutil_strcopy( ptr, ctrls[i]->ldctl_iscritical 2196 ? " true" : " false" ); 2197 2198 if ( b64.bv_len ) { 2199 ptr = lutil_strcopy( ptr, " " ); 2200 ptr = lutil_strcopy( ptr, b64.bv_val ); 2201 } 2202 2203 if ( ldif < 2 ) { 2204 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 2205 "control", str, len ); 2206 } 2207 2208 free( str ); 2209 if ( b64.bv_len ) { 2210 ber_memfree( b64.bv_val ); 2211 } 2212 2213 /* known controls */ 2214 for ( j = 0; tool_ctrl_response[j].oid != NULL; j++ ) { 2215 if ( strcmp( tool_ctrl_response[j].oid, ctrls[i]->ldctl_oid ) == 0 ) { 2216 if ( !tool_ctrl_response[j].mask & tool_type ) { 2217 /* this control should not appear 2218 * with this tool; warning? */ 2219 } 2220 break; 2221 } 2222 } 2223 2224 if ( tool_ctrl_response[j].oid != NULL && tool_ctrl_response[j].func ) { 2225 (void)tool_ctrl_response[j].func( ld, ctrls[i] ); 2226 } 2227 } 2228 } 2229 2230 int 2231 tool_write_ldif( int type, char *name, char *value, ber_len_t vallen ) 2232 { 2233 char *ldif; 2234 2235 if (( ldif = ldif_put( type, name, value, vallen )) == NULL ) { 2236 return( -1 ); 2237 } 2238 2239 fputs( ldif, stdout ); 2240 ber_memfree( ldif ); 2241 2242 return( 0 ); 2243 } 2244 2245 int 2246 tool_is_oid( const char *s ) 2247 { 2248 int first = 1; 2249 2250 if ( !isdigit( (unsigned char) s[ 0 ] ) ) { 2251 return 0; 2252 } 2253 2254 for ( ; s[ 0 ]; s++ ) { 2255 if ( s[ 0 ] == '.' ) { 2256 if ( s[ 1 ] == '\0' ) { 2257 return 0; 2258 } 2259 first = 1; 2260 continue; 2261 } 2262 2263 if ( !isdigit( (unsigned char) s[ 0 ] ) ) { 2264 return 0; 2265 } 2266 2267 if ( first == 1 && s[ 0 ] == '0' && s[ 1 ] != '.' ) { 2268 return 0; 2269 } 2270 first = 0; 2271 } 2272 2273 return 1; 2274 } 2275 2276