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