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