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