1/* ldapsearch -- a tool for searching LDAP directories */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * Portions Copyright 1998-2003 Kurt D. Zeilenga. 7 * Portions Copyright 1998-2001 Net Boolean Incorporated. 8 * Portions Copyright 2001-2003 IBM Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms are permitted 23 * provided that this notice is preserved and that due credit is given 24 * to the University of Michigan at Ann Arbor. The name of the 25 * University may not be used to endorse or promote products derived 26 * from this software without specific prior written permission. This 27 * software is provided ``as is'' without express or implied warranty. 28 */ 29/* ACKNOWLEDGEMENTS: 30 * This work was originally developed by the University of Michigan 31 * (as part of U-MICH LDAP). Additional significant contributors 32 * include: 33 * Jong Hyuk Choi 34 * Lynn Moss 35 * Mikhail Sahalaev 36 * Kurt D. Zeilenga 37 */ 38 39#include "portable.h" 40 41#include <stdio.h> 42 43#include <ac/stdlib.h> 44 45#include <ac/ctype.h> 46#include <ac/string.h> 47#include <ac/unistd.h> 48#include <ac/errno.h> 49#include <sys/stat.h> 50 51#include <ac/signal.h> 52 53#ifdef HAVE_FCNTL_H 54#include <fcntl.h> 55#endif 56#ifdef HAVE_SYS_TYPES_H 57#include <sys/types.h> 58#endif 59#ifdef HAVE_IO_H 60#include <io.h> 61#endif 62 63#include <ldap.h> 64 65#include "ldif.h" 66#include "lutil.h" 67#include "lutil_ldap.h" 68#include "ldap_defaults.h" 69#include "ldap_pvt.h" 70 71#include "common.h" 72 73#ifdef __APPLE__ 74#include "ldap_pvt_thread.h" 75#endif 76 77#if !LDAP_DEPRECATED 78/* 79 * NOTE: we use this deprecated function only because 80 * we want ldapsearch to provide some client-side sorting 81 * capability. 82 */ 83/* from ldap.h */ 84typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */ 85 LDAP_CONST char *left, 86 LDAP_CONST char *right )); 87 88LDAP_F( int ) /* deprecated */ 89ldap_sort_entries LDAP_P(( LDAP *ld, 90 LDAPMessage **chain, 91 LDAP_CONST char *attr, 92 LDAP_SORT_AD_CMP_PROC *cmp )); 93#endif 94 95static int scope = LDAP_SCOPE_SUBTREE; 96static int deref = -1; 97static int attrsonly; 98static int timelimit = -1; 99static int sizelimit = -1; 100 101static char *control; 102 103static char *def_tmpdir; 104static char *def_urlpre; 105 106#if defined(__CYGWIN__) || defined(__MINGW32__) 107/* Turn off commandline globbing, otherwise you cannot search for 108 * attribute '*' 109 */ 110int _CRT_glob = 0; 111#endif 112 113void 114usage( void ) 115{ 116 fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog); 117 fprintf( stderr, _(" filter\tRFC 4515 compliant LDAP search filter\n")); 118 fprintf( stderr, _(" attributes\twhitespace-separated list of attribute descriptions\n")); 119 fprintf( stderr, _(" which may include:\n")); 120 fprintf( stderr, _(" 1.1 no attributes\n")); 121 fprintf( stderr, _(" * all user attributes\n")); 122 fprintf( stderr, _(" + all operational attributes\n")); 123 124 125 fprintf( stderr, _("Search options:\n")); 126 fprintf( stderr, _(" -a deref one of never (default), always, search, or find\n")); 127 fprintf( stderr, _(" -A retrieve attribute names only (no values)\n")); 128 fprintf( stderr, _(" -b basedn base dn for search\n")); 129 fprintf( stderr, _(" -c continuous operation mode (do not stop on errors)\n")); 130 fprintf( stderr, _(" -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n")); 131 fprintf( stderr, _(" [!]domainScope (domain scope)\n")); 132 fprintf( stderr, _(" !dontUseCopy (Don't Use Copy)\n")); 133 fprintf( stderr, _(" [!]mv=<filter> (RFC 3876 matched values filter)\n")); 134 fprintf( stderr, _(" [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n")); 135 fprintf( stderr, _(" [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n")); 136 fprintf( stderr, _(" (RFC 2891 server side sorting)\n")); 137 fprintf( stderr, _(" [!]subentries[=true|false] (RFC 3672 subentries)\n")); 138 fprintf( stderr, _(" [!]sync=ro[/<cookie>] (RFC 4533 LDAP Sync refreshOnly)\n")); 139 fprintf( stderr, _(" rp[/<cookie>][/<slimit>] (refreshAndPersist)\n")); 140 fprintf( stderr, _(" [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n")); 141 fprintf( stderr, _(" (ldapv3-vlv-09 virtual list views)\n")); 142#ifdef LDAP_CONTROL_X_DEREF 143 fprintf( stderr, _(" [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n")); 144#endif 145 fprintf( stderr, _(" [!]<oid>[=:<b64value>] (generic control; no response handling)\n")); 146 fprintf( stderr, _(" -f file read operations from `file'\n")); 147 fprintf( stderr, _(" -F prefix URL prefix for files (default: %s)\n"), def_urlpre); 148 fprintf( stderr, _(" -l limit time limit (in seconds, or \"none\" or \"max\") for search\n")); 149 fprintf( stderr, _(" -L print responses in LDIFv1 format\n")); 150 fprintf( stderr, _(" -LL print responses in LDIF format without comments\n")); 151 fprintf( stderr, _(" -LLL print responses in LDIF format without comments\n")); 152 fprintf( stderr, _(" and version\n")); 153 fprintf( stderr, _(" -M enable Manage DSA IT control (-MM to make critical)\n")); 154 fprintf( stderr, _(" -P version protocol version (default: 3)\n")); 155 fprintf( stderr, _(" -s scope one of base, one, sub or children (search scope)\n")); 156 fprintf( stderr, _(" -S attr sort the results by attribute `attr'\n")); 157 fprintf( stderr, _(" -t write binary values to files in temporary directory\n")); 158 fprintf( stderr, _(" -tt write all values to files in temporary directory\n")); 159 fprintf( stderr, _(" -T path write files to directory specified by path (default: %s)\n"), def_tmpdir); 160 fprintf( stderr, _(" -u include User Friendly entry names in the output\n")); 161 fprintf( stderr, _(" -z limit size limit (in entries, or \"none\" or \"max\") for search\n")); 162 tool_common_usage(); 163 exit( EXIT_FAILURE ); 164} 165 166static void print_entry LDAP_P(( 167 LDAP *ld, 168 LDAPMessage *entry, 169 int attrsonly)); 170 171static void print_reference( 172 LDAP *ld, 173 LDAPMessage *reference ); 174 175static void print_extended( 176 LDAP *ld, 177 LDAPMessage *extended ); 178 179static void print_partial( 180 LDAP *ld, 181 LDAPMessage *partial ); 182 183static int print_result( 184 LDAP *ld, 185 LDAPMessage *result, 186 int search ); 187 188static int dosearch LDAP_P(( 189 LDAP *ld, 190 char *base, 191 int scope, 192 char *filtpatt, 193 char *value, 194 char **attrs, 195 int attrsonly, 196 LDAPControl **sctrls, 197 LDAPControl **cctrls, 198 struct timeval *timeout, 199 int sizelimit )); 200 201#ifdef __APPLE__ 202static int 203search_results_async(LDAP *ld); 204 205static void 206search_results_async_callback( 207 LDAP *ld, 208 LDAPMessage *res, 209 int rc, 210 void *context); 211#endif 212 213static char *tmpdir = NULL; 214static char *urlpre = NULL; 215static char *base = NULL; 216static char *sortattr = NULL; 217static int includeufn, vals2tmp = 0; 218 219static int subentries = 0, valuesReturnFilter = 0; 220static char *vrFilter = NULL; 221 222#ifdef LDAP_CONTROL_DONTUSECOPY 223static int dontUseCopy = 0; 224#endif 225 226static int domainScope = 0; 227 228static int sss = 0; 229static LDAPSortKey **sss_keys = NULL; 230 231static int vlv = 0; 232static LDAPVLVInfo vlvInfo; 233static struct berval vlvValue; 234 235static int ldapsync = 0; 236static struct berval sync_cookie = { 0, NULL }; 237static int sync_slimit = -1; 238 239/* cookie and morePagedResults moved to common.c */ 240static int pagedResults = 0; 241static int pagePrompt = 1; 242static ber_int_t pageSize = 0; 243static ber_int_t entriesLeft = 0; 244static int npagedresponses; 245static int npagedentries; 246static int npagedreferences; 247static int npagedextended; 248static int npagedpartial; 249 250static LDAPControl *c = NULL; 251static int nctrls = 0; 252static int save_nctrls = 0; 253 254#ifdef LDAP_CONTROL_X_DEREF 255static int derefcrit; 256static LDAPDerefSpec *ds; 257static struct berval derefval; 258#endif 259 260#ifdef __APPLE__ 261static int use_callback = 0; 262static int callback_done = 0; 263static ldap_pvt_thread_mutex_t callback_mutex; 264static ldap_pvt_thread_cond_t callback_cond; 265#endif 266 267static int 268ctrl_add( void ) 269{ 270 LDAPControl *tmpc; 271 272 nctrls++; 273 tmpc = realloc( c, sizeof( LDAPControl ) * nctrls ); 274 if ( tmpc == NULL ) { 275 nctrls--; 276 fprintf( stderr, 277 _("unable to make room for control; out of memory?\n")); 278 return -1; 279 } 280 c = tmpc; 281 282 return 0; 283} 284 285static void 286urlize(char *url) 287{ 288 char *p; 289 290 if (*LDAP_DIRSEP != '/') { 291 for (p = url; *p; p++) { 292 if (*p == *LDAP_DIRSEP) 293 *p = '/'; 294 } 295 } 296} 297 298static int 299parse_vlv(char *cvalue) 300{ 301 char *keyp, *key2; 302 int num1, num2; 303 304 keyp = cvalue; 305 if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) { 306 fprintf( stderr, 307 _("VLV control value \"%s\" invalid\n"), 308 cvalue ); 309 return -1; 310 } 311 vlvInfo.ldvlv_before_count = num1; 312 vlvInfo.ldvlv_after_count = num2; 313 keyp = strchr( keyp, '/' ) + 1; 314 key2 = strchr( keyp, '/' ); 315 if ( key2 ) { 316 keyp = key2 + 1; 317 if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) { 318 fprintf( stderr, 319 _("VLV control value \"%s\" invalid\n"), 320 cvalue ); 321 return -1; 322 } 323 vlvInfo.ldvlv_offset = num1; 324 vlvInfo.ldvlv_count = num2; 325 vlvInfo.ldvlv_attrvalue = NULL; 326 } else { 327 key2 = strchr( keyp, ':' ); 328 if ( !key2 ) { 329 fprintf( stderr, 330 _("VLV control value \"%s\" invalid\n"), 331 cvalue ); 332 return -1; 333 } 334 ber_str2bv( key2+1, 0, 0, &vlvValue ); 335 vlvInfo.ldvlv_attrvalue = &vlvValue; 336 } 337 return 0; 338} 339 340const char options[] = "a:ABb:cE:F:l:Ls:S:tT:uz:" 341 "Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z"; 342 343int 344handle_private_option( int i ) 345{ 346 int crit, ival; 347 char *cvalue, *next; 348 switch ( i ) { 349 case 'a': /* set alias deref option */ 350 if ( strcasecmp( optarg, "never" ) == 0 ) { 351 deref = LDAP_DEREF_NEVER; 352 } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) { 353 deref = LDAP_DEREF_SEARCHING; 354 } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) { 355 deref = LDAP_DEREF_FINDING; 356 } else if ( strcasecmp( optarg, "always" ) == 0 ) { 357 deref = LDAP_DEREF_ALWAYS; 358 } else { 359 fprintf( stderr, 360 _("alias deref should be never, search, find, or always\n") ); 361 usage(); 362 } 363 break; 364 case 'A': /* retrieve attribute names only -- no values */ 365 ++attrsonly; 366 break; 367 case 'b': /* search base */ 368 base = ber_strdup( optarg ); 369 break; 370#ifdef __APPLE__ 371 case 'B': /* background search (i.e. callback) */ 372 use_callback = 1; 373 break; 374#endif 375 case 'E': /* search extensions */ 376 if( protocol == LDAP_VERSION2 ) { 377 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"), 378 prog, protocol ); 379 exit( EXIT_FAILURE ); 380 } 381 382 /* should be extended to support comma separated list of 383 * [!]key[=value] parameters, e.g. -E !foo,bar=567 384 */ 385 386 crit = 0; 387 cvalue = NULL; 388 if( optarg[0] == '!' ) { 389 crit = 1; 390 optarg++; 391 } 392 393 control = ber_strdup( optarg ); 394 if ( (cvalue = strchr( control, '=' )) != NULL ) { 395 *cvalue++ = '\0'; 396 } 397 398 if ( strcasecmp( control, "mv" ) == 0 ) { 399 /* ValuesReturnFilter control */ 400 if( valuesReturnFilter ) { 401 fprintf( stderr, 402 _("ValuesReturnFilter previously specified\n")); 403 exit( EXIT_FAILURE ); 404 } 405 valuesReturnFilter= 1 + crit; 406 407 if ( cvalue == NULL ) { 408 fprintf( stderr, 409 _("missing filter in ValuesReturnFilter control\n")); 410 exit( EXIT_FAILURE ); 411 } 412 413 vrFilter = cvalue; 414 protocol = LDAP_VERSION3; 415 416 } else if ( strcasecmp( control, "pr" ) == 0 ) { 417 int num, tmp; 418 /* PagedResults control */ 419 if ( pagedResults != 0 ) { 420 fprintf( stderr, 421 _("PagedResultsControl previously specified\n") ); 422 exit( EXIT_FAILURE ); 423 } 424 if ( vlv != 0 ) { 425 fprintf( stderr, 426 _("PagedResultsControl incompatible with VLV\n") ); 427 exit( EXIT_FAILURE ); 428 } 429 430 if( cvalue != NULL ) { 431 char *promptp; 432 433 promptp = strchr( cvalue, '/' ); 434 if ( promptp != NULL ) { 435 *promptp++ = '\0'; 436 if ( strcasecmp( promptp, "prompt" ) == 0 ) { 437 pagePrompt = 1; 438 } else if ( strcasecmp( promptp, "noprompt" ) == 0) { 439 pagePrompt = 0; 440 } else { 441 fprintf( stderr, 442 _("Invalid value for PagedResultsControl," 443 " %s/%s.\n"), cvalue, promptp ); 444 exit( EXIT_FAILURE ); 445 } 446 } 447 num = sscanf( cvalue, "%d", &tmp ); 448 if ( num != 1 ) { 449 fprintf( stderr, 450 _("Invalid value for PagedResultsControl, %s.\n"), 451 cvalue ); 452 exit( EXIT_FAILURE ); 453 } 454 } else { 455 fprintf(stderr, _("Invalid value for PagedResultsControl.\n")); 456 exit( EXIT_FAILURE ); 457 } 458 pageSize = (ber_int_t) tmp; 459 pagedResults = 1 + crit; 460 461#ifdef LDAP_CONTROL_DONTUSECOPY 462 } else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) { 463 if( dontUseCopy ) { 464 fprintf( stderr, 465 _("dontUseCopy control previously specified\n")); 466 exit( EXIT_FAILURE ); 467 } 468 if( cvalue != NULL ) { 469 fprintf( stderr, 470 _("dontUseCopy: no control value expected\n") ); 471 usage(); 472 } 473 if( !crit ) { 474 fprintf( stderr, 475 _("dontUseCopy: critical flag required\n") ); 476 usage(); 477 } 478 479 dontUseCopy = 1 + crit; 480#endif 481 } else if ( strcasecmp( control, "domainScope" ) == 0 ) { 482 if( domainScope ) { 483 fprintf( stderr, 484 _("domainScope control previously specified\n")); 485 exit( EXIT_FAILURE ); 486 } 487 if( cvalue != NULL ) { 488 fprintf( stderr, 489 _("domainScope: no control value expected\n") ); 490 usage(); 491 } 492 493 domainScope = 1 + crit; 494 495 } else if ( strcasecmp( control, "sss" ) == 0 ) { 496 char *keyp; 497 if( sss ) { 498 fprintf( stderr, 499 _("server side sorting control previously specified\n")); 500 exit( EXIT_FAILURE ); 501 } 502 if( cvalue == NULL ) { 503 fprintf( stderr, 504 _("missing specification of sss control\n") ); 505 exit( EXIT_FAILURE ); 506 } 507 keyp = cvalue; 508 while ( ( keyp = strchr(keyp, '/') ) != NULL ) { 509 *keyp++ = ' '; 510 } 511 if ( ldap_create_sort_keylist( &sss_keys, cvalue )) { 512 fprintf( stderr, 513 _("server side sorting control value \"%s\" invalid\n"), 514 cvalue ); 515 exit( EXIT_FAILURE ); 516 } 517 518 sss = 1 + crit; 519 520 } else if ( strcasecmp( control, "subentries" ) == 0 ) { 521 if( subentries ) { 522 fprintf( stderr, 523 _("subentries control previously specified\n")); 524 exit( EXIT_FAILURE ); 525 } 526 if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) { 527 subentries = 2; 528 } else if ( strcasecmp( cvalue, "false") == 0 ) { 529 subentries = 1; 530 } else { 531 fprintf( stderr, 532 _("subentries control value \"%s\" invalid\n"), 533 cvalue ); 534 exit( EXIT_FAILURE ); 535 } 536 if( crit ) subentries *= -1; 537 538 } else if ( strcasecmp( control, "sync" ) == 0 ) { 539 char *cookiep; 540 char *slimitp; 541 if ( ldapsync ) { 542 fprintf( stderr, _("sync control previously specified\n") ); 543 exit( EXIT_FAILURE ); 544 } 545 if ( cvalue == NULL ) { 546 fprintf( stderr, _("missing specification of sync control\n")); 547 exit( EXIT_FAILURE ); 548 } 549 if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) { 550 ldapsync = LDAP_SYNC_REFRESH_ONLY; 551 cookiep = strchr( cvalue, '/' ); 552 if ( cookiep != NULL ) { 553 cookiep++; 554 if ( *cookiep != '\0' ) { 555 ber_str2bv( cookiep, 0, 0, &sync_cookie ); 556 } 557 } 558 } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) { 559 ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST; 560 cookiep = strchr( cvalue, '/' ); 561 if ( cookiep != NULL ) { 562 *cookiep++ = '\0'; 563 cvalue = cookiep; 564 } 565 slimitp = strchr( cvalue, '/' ); 566 if ( slimitp != NULL ) { 567 *slimitp++ = '\0'; 568 } 569 if ( cookiep != NULL && *cookiep != '\0' ) 570 ber_str2bv( cookiep, 0, 0, &sync_cookie ); 571 if ( slimitp != NULL && *slimitp != '\0' ) { 572 ival = strtol( slimitp, &next, 10 ); 573 if ( next == NULL || next[0] != '\0' ) { 574 fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp ); 575 exit( EXIT_FAILURE ); 576 } 577 sync_slimit = ival; 578 } 579 } else { 580 fprintf( stderr, _("sync control value \"%s\" invalid\n"), 581 cvalue ); 582 exit( EXIT_FAILURE ); 583 } 584 if ( crit ) ldapsync *= -1; 585 586 } else if ( strcasecmp( control, "vlv" ) == 0 ) { 587 if( vlv ) { 588 fprintf( stderr, 589 _("virtual list view control previously specified\n")); 590 exit( EXIT_FAILURE ); 591 } 592 if ( pagedResults != 0 ) { 593 fprintf( stderr, 594 _("PagedResultsControl incompatible with VLV\n") ); 595 exit( EXIT_FAILURE ); 596 } 597 if( cvalue == NULL ) { 598 fprintf( stderr, 599 _("missing specification of vlv control\n") ); 600 exit( EXIT_FAILURE ); 601 } 602 if ( parse_vlv( cvalue )) 603 exit( EXIT_FAILURE ); 604 605 vlv = 1 + crit; 606 607#ifdef LDAP_CONTROL_X_DEREF 608 } else if ( strcasecmp( control, "deref" ) == 0 ) { 609 int ispecs; 610 char **specs; 611 612 /* cvalue is something like 613 * 614 * derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]" 615 */ 616 617 specs = ldap_str2charray( cvalue, ";" ); 618 if ( specs == NULL ) { 619 fprintf( stderr, _("deref specs \"%s\" invalid\n"), 620 cvalue ); 621 exit( EXIT_FAILURE ); 622 } 623 for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) 624 /* count'em */ ; 625 626 ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) ); 627 if ( ds == NULL ) { 628 perror( "malloc" ); 629 exit( EXIT_FAILURE ); 630 } 631 632 for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) { 633 char *ptr; 634 635 ptr = strchr( specs[ ispecs ], ':' ); 636 if ( ptr == NULL ) { 637 fprintf( stderr, _("deref specs \"%s\" invalid\n"), 638 cvalue ); 639 exit( EXIT_FAILURE ); 640 } 641 642 ds[ ispecs ].derefAttr = specs[ ispecs ]; 643 *ptr++ = '\0'; 644 ds[ ispecs ].attributes = ldap_str2charray( ptr, "," ); 645 } 646 647 derefcrit = 1 + crit; 648 649 ldap_memfree( specs ); 650#endif /* LDAP_CONTROL_X_DEREF */ 651 652 } else if ( tool_is_oid( control ) ) { 653 if ( ctrl_add() ) { 654 exit( EXIT_FAILURE ); 655 } 656 657 /* OID */ 658 c[ nctrls - 1 ].ldctl_oid = control; 659 660 /* value */ 661 if ( cvalue == NULL ) { 662 c[ nctrls - 1 ].ldctl_value.bv_val = NULL; 663 c[ nctrls - 1 ].ldctl_value.bv_len = 0; 664 665 } else if ( cvalue[ 0 ] == ':' ) { 666 struct berval type; 667 struct berval value; 668 int freeval; 669 char save_c; 670 671 cvalue++; 672 673 /* dummy type "x" 674 * to use ldif_parse_line2() */ 675 save_c = cvalue[ -2 ]; 676 cvalue[ -2 ] = 'x'; 677 ldif_parse_line2( &cvalue[ -2 ], &type, 678 &value, &freeval ); 679 cvalue[ -2 ] = save_c; 680 681 if ( freeval ) { 682 c[ nctrls - 1 ].ldctl_value = value; 683 684 } else { 685 ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value ); 686 } 687 688 } else { 689 fprintf( stderr, "unable to parse %s control value\n", control ); 690 exit( EXIT_FAILURE ); 691 692 } 693 694 /* criticality */ 695 c[ nctrls - 1 ].ldctl_iscritical = crit; 696 697 } else { 698 fprintf( stderr, _("Invalid search extension name: %s\n"), 699 control ); 700 usage(); 701 } 702 break; 703 case 'F': /* uri prefix */ 704 if( urlpre ) free( urlpre ); 705 urlpre = strdup( optarg ); 706 break; 707 case 'l': /* time limit */ 708 if ( strcasecmp( optarg, "none" ) == 0 ) { 709 timelimit = 0; 710 711 } else if ( strcasecmp( optarg, "max" ) == 0 ) { 712 timelimit = LDAP_MAXINT; 713 714 } else { 715 ival = strtol( optarg, &next, 10 ); 716 if ( next == NULL || next[0] != '\0' ) { 717 fprintf( stderr, 718 _("Unable to parse time limit \"%s\"\n"), optarg ); 719 exit( EXIT_FAILURE ); 720 } 721 timelimit = ival; 722 } 723 if( timelimit < 0 || timelimit > LDAP_MAXINT ) { 724 fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"), 725 prog, timelimit ); 726 exit( EXIT_FAILURE ); 727 } 728 break; 729 case 'L': /* print entries in LDIF format */ 730 ++ldif; 731 break; 732 case 's': /* search scope */ 733 if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) { 734 scope = LDAP_SCOPE_BASE; 735 } else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) { 736 scope = LDAP_SCOPE_ONELEVEL; 737 } else if (( strcasecmp( optarg, "subordinate" ) == 0 ) 738 || ( strcasecmp( optarg, "children" ) == 0 )) 739 { 740 scope = LDAP_SCOPE_SUBORDINATE; 741 } else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) { 742 scope = LDAP_SCOPE_SUBTREE; 743 } else { 744 fprintf( stderr, _("scope should be base, one, or sub\n") ); 745 usage(); 746 } 747 break; 748 case 'S': /* sort attribute */ 749 sortattr = strdup( optarg ); 750 break; 751 case 't': /* write attribute values to TMPDIR files */ 752 ++vals2tmp; 753 break; 754 case 'T': /* tmpdir */ 755 if( tmpdir ) free( tmpdir ); 756 tmpdir = strdup( optarg ); 757 break; 758 case 'u': /* include UFN */ 759 ++includeufn; 760 break; 761 case 'z': /* size limit */ 762 if ( strcasecmp( optarg, "none" ) == 0 ) { 763 sizelimit = 0; 764 765 } else if ( strcasecmp( optarg, "max" ) == 0 ) { 766 sizelimit = LDAP_MAXINT; 767 768 } else { 769 ival = strtol( optarg, &next, 10 ); 770 if ( next == NULL || next[0] != '\0' ) { 771 fprintf( stderr, 772 _("Unable to parse size limit \"%s\"\n"), optarg ); 773 exit( EXIT_FAILURE ); 774 } 775 sizelimit = ival; 776 } 777 if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) { 778 fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"), 779 prog, sizelimit ); 780 exit( EXIT_FAILURE ); 781 } 782 break; 783 default: 784 return 0; 785 } 786 return 1; 787} 788 789 790static void 791private_conn_setup( LDAP *ld ) 792{ 793 if (deref != -1 && 794 ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) 795 != LDAP_OPT_SUCCESS ) 796 { 797 fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref ); 798 tool_exit( ld, EXIT_FAILURE ); 799 } 800} 801 802int 803main( int argc, char **argv ) 804{ 805 char *filtpattern, **attrs = NULL, line[BUFSIZ]; 806 FILE *fp = NULL; 807 int rc, rc1, i, first; 808 LDAP *ld = NULL; 809 BerElement *seber = NULL, *vrber = NULL; 810 811 BerElement *syncber = NULL; 812 struct berval *syncbvalp = NULL; 813 int err; 814 815 tool_init( TOOL_SEARCH ); 816 817 npagedresponses = npagedentries = npagedreferences = 818 npagedextended = npagedpartial = 0; 819 820 prog = lutil_progname( "ldapsearch", argc, argv ); 821 822 if((def_tmpdir = getenv("TMPDIR")) == NULL && 823 (def_tmpdir = getenv("TMP")) == NULL && 824 (def_tmpdir = getenv("TEMP")) == NULL ) 825 { 826 def_tmpdir = LDAP_TMPDIR; 827 } 828 829 if ( !*def_tmpdir ) 830 def_tmpdir = LDAP_TMPDIR; 831 832 def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) ); 833 834 if( def_urlpre == NULL ) { 835 perror( "malloc" ); 836 return EXIT_FAILURE; 837 } 838 839 sprintf( def_urlpre, "file:///%s/", 840 def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir ); 841 842 urlize( def_urlpre ); 843 844 tool_args( argc, argv ); 845 846 if ( vlv && !sss ) { 847 fprintf( stderr, 848 _("VLV control requires server side sort control\n" )); 849 return EXIT_FAILURE; 850 } 851 852 if (( argc - optind < 1 ) || 853 ( *argv[optind] != '(' /*')'*/ && 854 ( strchr( argv[optind], '=' ) == NULL ) ) ) 855 { 856 filtpattern = "(objectclass=*)"; 857 } else { 858 filtpattern = argv[optind++]; 859 } 860 861 if ( argv[optind] != NULL ) { 862 attrs = &argv[optind]; 863 } 864 865 if ( infile != NULL ) { 866 int percent = 0; 867 868 if ( infile[0] == '-' && infile[1] == '\0' ) { 869 fp = stdin; 870 } else if (( fp = fopen( infile, "r" )) == NULL ) { 871 perror( infile ); 872 return EXIT_FAILURE; 873 } 874 875 for( i=0 ; filtpattern[i] ; i++ ) { 876 if( filtpattern[i] == '%' ) { 877 if( percent ) { 878 fprintf( stderr, _("Bad filter pattern \"%s\"\n"), 879 filtpattern ); 880 return EXIT_FAILURE; 881 } 882 883 percent++; 884 885 if( filtpattern[i+1] != 's' ) { 886 fprintf( stderr, _("Bad filter pattern \"%s\"\n"), 887 filtpattern ); 888 return EXIT_FAILURE; 889 } 890 } 891 } 892 } 893 894 if ( tmpdir == NULL ) { 895 tmpdir = def_tmpdir; 896 897 if ( urlpre == NULL ) 898 urlpre = def_urlpre; 899 } 900 901 if( urlpre == NULL ) { 902 urlpre = malloc( sizeof("file:////") + strlen(tmpdir) ); 903 904 if( urlpre == NULL ) { 905 perror( "malloc" ); 906 return EXIT_FAILURE; 907 } 908 909 sprintf( urlpre, "file:///%s/", 910 tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir ); 911 912 urlize( urlpre ); 913 } 914 915 if ( debug ) 916 ldif_debug = debug; 917 918 ld = tool_conn_setup( 0, &private_conn_setup ); 919 920 tool_bind( ld ); 921 922getNextPage: 923 /* fp may have been closed, need to reopen if code jumps 924 * back here to getNextPage. 925 */ 926 if ( !fp && infile ) { 927 if (( fp = fopen( infile, "r" )) == NULL ) { 928 perror( infile ); 929 tool_exit( ld, EXIT_FAILURE ); 930 } 931 } 932 save_nctrls = nctrls; 933 i = nctrls; 934 if ( nctrls > 0 935#ifdef LDAP_CONTROL_DONTUSECOPY 936 || dontUseCopy 937#endif 938#ifdef LDAP_CONTROL_X_DEREF 939 || derefcrit 940#endif 941 || domainScope 942 || pagedResults 943 || ldapsync 944 || sss 945 || subentries 946 || valuesReturnFilter 947 || vlv ) 948 { 949 950#ifdef LDAP_CONTROL_DONTUSECOPY 951 if ( dontUseCopy ) { 952 if ( ctrl_add() ) { 953 tool_exit( ld, EXIT_FAILURE ); 954 } 955 956 c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY; 957 c[i].ldctl_value.bv_val = NULL; 958 c[i].ldctl_value.bv_len = 0; 959 c[i].ldctl_iscritical = dontUseCopy > 1; 960 i++; 961 } 962#endif 963 964 if ( domainScope ) { 965 if ( ctrl_add() ) { 966 tool_exit( ld, EXIT_FAILURE ); 967 } 968 969 c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE; 970 c[i].ldctl_value.bv_val = NULL; 971 c[i].ldctl_value.bv_len = 0; 972 c[i].ldctl_iscritical = domainScope > 1; 973 i++; 974 } 975 976 if ( subentries ) { 977 if ( ctrl_add() ) { 978 tool_exit( ld, EXIT_FAILURE ); 979 } 980 981 if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 982 tool_exit( ld, EXIT_FAILURE ); 983 } 984 985 err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 ); 986 if ( err == -1 ) { 987 ber_free( seber, 1 ); 988 fprintf( stderr, _("Subentries control encoding error!\n") ); 989 tool_exit( ld, EXIT_FAILURE ); 990 } 991 992 if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) { 993 tool_exit( ld, EXIT_FAILURE ); 994 } 995 996 c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES; 997 c[i].ldctl_iscritical = subentries < 1; 998 i++; 999 } 1000 1001 if ( ldapsync ) { 1002 if ( ctrl_add() ) { 1003 tool_exit( ld, EXIT_FAILURE ); 1004 } 1005 1006 if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 1007 tool_exit( ld, EXIT_FAILURE ); 1008 } 1009 1010 if ( sync_cookie.bv_len == 0 ) { 1011 err = ber_printf( syncber, "{e}", abs(ldapsync) ); 1012 } else { 1013 err = ber_printf( syncber, "{eO}", abs(ldapsync), 1014 &sync_cookie ); 1015 } 1016 1017 if ( err == -1 ) { 1018 ber_free( syncber, 1 ); 1019 fprintf( stderr, _("ldap sync control encoding error!\n") ); 1020 tool_exit( ld, EXIT_FAILURE ); 1021 } 1022 1023 if ( ber_flatten( syncber, &syncbvalp ) == -1 ) { 1024 tool_exit( ld, EXIT_FAILURE ); 1025 } 1026 1027 c[i].ldctl_oid = LDAP_CONTROL_SYNC; 1028 c[i].ldctl_value = (*syncbvalp); 1029 c[i].ldctl_iscritical = ldapsync < 0; 1030 i++; 1031 } 1032 1033 if ( valuesReturnFilter ) { 1034 if ( ctrl_add() ) { 1035 tool_exit( ld, EXIT_FAILURE ); 1036 } 1037 1038 if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 1039 tool_exit( ld, EXIT_FAILURE ); 1040 } 1041 1042 if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) { 1043 ber_free( vrber, 1 ); 1044 fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter ); 1045 tool_exit( ld, EXIT_FAILURE ); 1046 } 1047 1048 if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) { 1049 tool_exit( ld, EXIT_FAILURE ); 1050 } 1051 1052 c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER; 1053 c[i].ldctl_iscritical = valuesReturnFilter > 1; 1054 i++; 1055 } 1056 1057 if ( pagedResults ) { 1058 if ( ctrl_add() ) { 1059 tool_exit( ld, EXIT_FAILURE ); 1060 } 1061 1062 if ( ldap_create_page_control_value( ld, 1063 pageSize, &pr_cookie, &c[i].ldctl_value ) ) 1064 { 1065 tool_exit( ld, EXIT_FAILURE ); 1066 } 1067 1068 if ( pr_cookie.bv_val != NULL ) { 1069 ber_memfree( pr_cookie.bv_val ); 1070 pr_cookie.bv_val = NULL; 1071 pr_cookie.bv_len = 0; 1072 } 1073 1074 c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; 1075 c[i].ldctl_iscritical = pagedResults > 1; 1076 i++; 1077 } 1078 1079 if ( sss ) { 1080 if ( ctrl_add() ) { 1081 tool_exit( ld, EXIT_FAILURE ); 1082 } 1083 1084 if ( ldap_create_sort_control_value( ld, 1085 sss_keys, &c[i].ldctl_value ) ) 1086 { 1087 tool_exit( ld, EXIT_FAILURE ); 1088 } 1089 1090 c[i].ldctl_oid = LDAP_CONTROL_SORTREQUEST; 1091 c[i].ldctl_iscritical = sss > 1; 1092 i++; 1093 } 1094 1095 if ( vlv ) { 1096 if ( ctrl_add() ) { 1097 tool_exit( ld, EXIT_FAILURE ); 1098 } 1099 1100 if ( ldap_create_vlv_control_value( ld, 1101 &vlvInfo, &c[i].ldctl_value ) ) 1102 { 1103 tool_exit( ld, EXIT_FAILURE ); 1104 } 1105 1106 c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST; 1107 c[i].ldctl_iscritical = sss > 1; 1108 i++; 1109 } 1110#ifdef LDAP_CONTROL_X_DEREF 1111 if ( derefcrit ) { 1112 if ( derefval.bv_val == NULL ) { 1113 int i; 1114 1115 assert( ds != NULL ); 1116 1117 if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) { 1118 tool_exit( ld, EXIT_FAILURE ); 1119 } 1120 1121 for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) { 1122 ldap_memfree( ds[ i ].derefAttr ); 1123 ldap_charray_free( ds[ i ].attributes ); 1124 } 1125 ldap_memfree( ds ); 1126 ds = NULL; 1127 } 1128 1129 if ( ctrl_add() ) { 1130 tool_exit( ld, EXIT_FAILURE ); 1131 } 1132 1133 c[ i ].ldctl_iscritical = derefcrit > 1; 1134 c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF; 1135 c[ i ].ldctl_value = derefval; 1136 i++; 1137 } 1138#endif /* LDAP_CONTROL_X_DEREF */ 1139 } 1140 1141 tool_server_controls( ld, c, i ); 1142 1143 if ( seber ) ber_free( seber, 1 ); 1144 if ( vrber ) ber_free( vrber, 1 ); 1145 1146 /* step back to the original number of controls, so that 1147 * those set while parsing args are preserved */ 1148 nctrls = save_nctrls; 1149 1150 if ( verbose ) { 1151 fprintf( stderr, _("filter%s: %s\nrequesting: "), 1152 infile != NULL ? _(" pattern") : "", 1153 filtpattern ); 1154 1155 if ( attrs == NULL ) { 1156 fprintf( stderr, _("All userApplication attributes") ); 1157 } else { 1158 for ( i = 0; attrs[ i ] != NULL; ++i ) { 1159 fprintf( stderr, "%s ", attrs[ i ] ); 1160 } 1161 } 1162 fprintf( stderr, "\n" ); 1163 } 1164 1165 if ( ldif == 0 ) { 1166 printf( _("# extended LDIF\n") ); 1167 } else if ( ldif < 3 ) { 1168 printf( _("version: %d\n\n"), 1 ); 1169 } 1170 1171 if (ldif < 2 ) { 1172 char *realbase = base; 1173 1174 if ( realbase == NULL ) { 1175 ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase ); 1176 } 1177 1178 printf( "#\n" ); 1179 printf(_("# LDAPv%d\n"), protocol); 1180 printf(_("# base <%s>%s with scope %s\n"), 1181 realbase ? realbase : "", 1182 ( realbase == NULL || realbase != base ) ? " (default)" : "", 1183 ((scope == LDAP_SCOPE_BASE) ? "baseObject" 1184 : ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel" 1185 : ((scope == LDAP_SCOPE_SUBORDINATE) ? "children" 1186 : "subtree" )))); 1187 printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "", 1188 filtpattern); 1189 printf(_("# requesting: ")); 1190 1191 if ( attrs == NULL ) { 1192 printf( _("ALL") ); 1193 } else { 1194 for ( i = 0; attrs[ i ] != NULL; ++i ) { 1195 printf( "%s ", attrs[ i ] ); 1196 } 1197 } 1198 1199 if ( manageDSAit ) { 1200 printf(_("\n# with manageDSAit %scontrol"), 1201 manageDSAit > 1 ? _("critical ") : "" ); 1202 } 1203 if ( noop ) { 1204 printf(_("\n# with noop %scontrol"), 1205 noop > 1 ? _("critical ") : "" ); 1206 } 1207 if ( subentries ) { 1208 printf(_("\n# with subentries %scontrol: %s"), 1209 subentries < 0 ? _("critical ") : "", 1210 abs(subentries) == 1 ? "false" : "true" ); 1211 } 1212 if ( valuesReturnFilter ) { 1213 printf(_("\n# with valuesReturnFilter %scontrol: %s"), 1214 valuesReturnFilter > 1 ? _("critical ") : "", vrFilter ); 1215 } 1216 if ( pagedResults ) { 1217 printf(_("\n# with pagedResults %scontrol: size=%d"), 1218 (pagedResults > 1) ? _("critical ") : "", 1219 pageSize ); 1220 } 1221 if ( sss ) { 1222 printf(_("\n# with server side sorting %scontrol"), 1223 sss > 1 ? _("critical ") : "" ); 1224 } 1225 if ( vlv ) { 1226 printf(_("\n# with virtual list view %scontrol: %d/%d"), 1227 vlv > 1 ? _("critical ") : "", 1228 vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count); 1229 if ( vlvInfo.ldvlv_attrvalue ) 1230 printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val ); 1231 else 1232 printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count ); 1233 } 1234#ifdef LDAP_CONTROL_X_DEREF 1235 if ( derefcrit ) { 1236 printf(_("\n# with dereference %scontrol"), 1237 derefcrit > 1 ? _("critical ") : "" ); 1238 } 1239#endif 1240 1241 printf( _("\n#\n\n") ); 1242 1243 if ( realbase && realbase != base ) { 1244 ldap_memfree( realbase ); 1245 } 1246 } 1247 1248 if ( infile == NULL ) { 1249 rc = dosearch( ld, base, scope, NULL, filtpattern, 1250 attrs, attrsonly, NULL, NULL, NULL, sizelimit ); 1251 1252 } else { 1253 rc = 0; 1254 first = 1; 1255 while ( fgets( line, sizeof( line ), fp ) != NULL ) { 1256 line[ strlen( line ) - 1 ] = '\0'; 1257 if ( !first ) { 1258 putchar( '\n' ); 1259 } else { 1260 first = 0; 1261 } 1262 rc1 = dosearch( ld, base, scope, filtpattern, line, 1263 attrs, attrsonly, NULL, NULL, NULL, sizelimit ); 1264 1265 if ( rc1 != 0 ) { 1266 rc = rc1; 1267 if ( !contoper ) 1268 break; 1269 } 1270 } 1271 if ( fp != stdin ) { 1272 fclose( fp ); 1273 fp = NULL; 1274 } 1275 } 1276 1277 if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) { 1278 char buf[12]; 1279 int i, moreEntries, tmpSize; 1280 1281 /* Loop to get the next pages when 1282 * enter is pressed on the terminal. 1283 */ 1284 if ( pagePrompt != 0 ) { 1285 if ( entriesLeft > 0 ) { 1286 printf( _("Estimate entries: %d\n"), entriesLeft ); 1287 } 1288 printf( _("Press [size] Enter for the next {%d|size} entries.\n"), 1289 (int)pageSize ); 1290 i = 0; 1291 moreEntries = getchar(); 1292 while ( moreEntries != EOF && moreEntries != '\n' ) { 1293 if ( i < (int)sizeof(buf) - 1 ) { 1294 buf[i] = moreEntries; 1295 i++; 1296 } 1297 moreEntries = getchar(); 1298 } 1299 buf[i] = '\0'; 1300 1301 if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) { 1302 int num = sscanf( buf, "%d", &tmpSize ); 1303 if ( num != 1 ) { 1304 fprintf( stderr, 1305 _("Invalid value for PagedResultsControl, %s.\n"), buf); 1306 tool_exit( ld, EXIT_FAILURE ); 1307 1308 } 1309 pageSize = (ber_int_t)tmpSize; 1310 } 1311 } 1312 1313 goto getNextPage; 1314 } 1315 1316 if (( rc == LDAP_SUCCESS ) && vlv ) { 1317 char buf[BUFSIZ]; 1318 int i, moreEntries; 1319 1320 /* Loop to get the next window when 1321 * enter is pressed on the terminal. 1322 */ 1323 printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n")); 1324 i = 0; 1325 moreEntries = getchar(); 1326 while ( moreEntries != EOF && moreEntries != '\n' ) { 1327 if ( i < (int)sizeof(buf) - 1 ) { 1328 buf[i] = moreEntries; 1329 i++; 1330 } 1331 moreEntries = getchar(); 1332 } 1333 buf[i] = '\0'; 1334 if ( buf[0] ) { 1335 i = parse_vlv( strdup( buf )); 1336 if ( i ) 1337 tool_exit( ld, EXIT_FAILURE ); 1338 } else { 1339 vlvInfo.ldvlv_attrvalue = NULL; 1340 vlvInfo.ldvlv_count = vlvCount; 1341 vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count; 1342 } 1343 1344 if ( vlvInfo.ldvlv_context ) 1345 ber_bvfree( vlvInfo.ldvlv_context ); 1346 vlvInfo.ldvlv_context = vlvContext; 1347 1348 goto getNextPage; 1349 } 1350 1351 if ( base != NULL ) { 1352 ber_memfree( base ); 1353 } 1354 if ( control != NULL ) { 1355 ber_memfree( control ); 1356 } 1357 if ( sss_keys != NULL ) { 1358 ldap_free_sort_keylist( sss_keys ); 1359 } 1360 if ( derefval.bv_val != NULL ) { 1361 ldap_memfree( derefval.bv_val ); 1362 } 1363 if ( urlpre != NULL ) { 1364 if ( def_urlpre != urlpre ) 1365 free( def_urlpre ); 1366 free( urlpre ); 1367 } 1368 1369 if ( c ) { 1370 for ( ; save_nctrls-- > 0; ) { 1371 ber_memfree( c[ save_nctrls ].ldctl_value.bv_val ); 1372 } 1373 free( c ); 1374 c = NULL; 1375 } 1376 1377 tool_exit( ld, rc ); 1378} 1379 1380 1381static int dosearch( 1382 LDAP *ld, 1383 char *base, 1384 int scope, 1385 char *filtpatt, 1386 char *value, 1387 char **attrs, 1388 int attrsonly, 1389 LDAPControl **sctrls, 1390 LDAPControl **cctrls, 1391 struct timeval *timeout, 1392 int sizelimit ) 1393{ 1394 char *filter; 1395 int rc, rc2 = LDAP_OTHER; 1396 int nresponses; 1397 int nentries; 1398 int nreferences; 1399 int nextended; 1400 int npartial; 1401 LDAPMessage *res, *msg; 1402 ber_int_t msgid; 1403 char *retoid = NULL; 1404 struct berval *retdata = NULL; 1405 int nresponses_psearch = -1; 1406 int cancel_msgid = -1; 1407 struct timeval tv, *tvp = NULL; 1408 struct timeval tv_timelimit, *tv_timelimitp = NULL; 1409 1410 if( filtpatt != NULL ) { 1411 size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1, outlen; 1412 filter = malloc( max_fsize ); 1413 if( filter == NULL ) { 1414 perror( "malloc" ); 1415 return EXIT_FAILURE; 1416 } 1417 1418 outlen = snprintf( filter, max_fsize, filtpatt, value ); 1419 if( outlen >= max_fsize ) { 1420 fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt ); 1421 free( filter ); 1422 return EXIT_FAILURE; 1423 } 1424 1425 if ( verbose ) { 1426 fprintf( stderr, _("filter: %s\n"), filter ); 1427 } 1428 1429 if( ldif < 2 ) { 1430 printf( _("#\n# filter: %s\n#\n"), filter ); 1431 } 1432 1433 } else { 1434 filter = value; 1435 } 1436 1437 if ( dont ) { 1438 if ( filtpatt != NULL ) { 1439 free( filter ); 1440 } 1441 return LDAP_SUCCESS; 1442 } 1443 1444 if ( timelimit > 0 ) { 1445 tv_timelimit.tv_sec = timelimit; 1446 tv_timelimit.tv_usec = 0; 1447 tv_timelimitp = &tv_timelimit; 1448 } 1449 1450 rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, 1451 sctrls, cctrls, tv_timelimitp, sizelimit, &msgid ); 1452 1453 if ( filtpatt != NULL ) { 1454 free( filter ); 1455 } 1456 1457 if( rc != LDAP_SUCCESS ) { 1458 tool_perror( "ldap_search_ext", rc, NULL, NULL, NULL, NULL ); 1459 return( rc ); 1460 } 1461 1462 nresponses = nentries = nreferences = nextended = npartial = 0; 1463 1464 res = NULL; 1465 1466 if ( timelimit > 0 ) { 1467 /* disable timeout */ 1468 tv.tv_sec = -1; 1469 tv.tv_usec = 0; 1470 tvp = &tv; 1471 } 1472#ifdef __APPLE__ 1473 if (use_callback) { 1474 return search_results_async(ld); 1475 } 1476#endif 1477 while ((rc = ldap_result( ld, LDAP_RES_ANY, 1478 sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE, 1479 tvp, &res )) > 0 ) 1480 { 1481 if ( tool_check_abandon( ld, msgid ) ) { 1482 return -1; 1483 } 1484 1485 if( sortattr ) { 1486 (void) ldap_sort_entries( ld, &res, 1487 ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp ); 1488 } 1489 1490 for ( msg = ldap_first_message( ld, res ); 1491 msg != NULL; 1492 msg = ldap_next_message( ld, msg ) ) 1493 { 1494 if ( nresponses++ ) putchar('\n'); 1495 if ( nresponses_psearch >= 0 ) 1496 nresponses_psearch++; 1497 1498 switch( ldap_msgtype( msg ) ) { 1499 case LDAP_RES_SEARCH_ENTRY: 1500 nentries++; 1501 print_entry( ld, msg, attrsonly ); 1502 break; 1503 1504 case LDAP_RES_SEARCH_REFERENCE: 1505 nreferences++; 1506 print_reference( ld, msg ); 1507 break; 1508 1509 case LDAP_RES_EXTENDED: 1510 nextended++; 1511 print_extended( ld, msg ); 1512 1513 if ( ldap_msgid( msg ) == 0 ) { 1514 /* unsolicited extended operation */ 1515 goto done; 1516 } 1517 1518 if ( cancel_msgid != -1 && 1519 cancel_msgid == ldap_msgid( msg ) ) { 1520 printf(_("Cancelled \n")); 1521 printf(_("cancel_msgid = %d\n"), cancel_msgid); 1522 goto done; 1523 } 1524 break; 1525 1526 case LDAP_RES_SEARCH_RESULT: 1527 /* pagedResults stuff is dealt with 1528 * in tool_print_ctrls(), called by 1529 * print_results(). */ 1530 rc2 = print_result( ld, msg, 1 ); 1531 if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) { 1532 break; 1533 } 1534 1535 goto done; 1536 1537 case LDAP_RES_INTERMEDIATE: 1538 npartial++; 1539 ldap_parse_intermediate( ld, msg, 1540 &retoid, &retdata, NULL, 0 ); 1541 1542 nresponses_psearch = 0; 1543 1544 if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) { 1545 printf(_("SyncInfo Received\n")); 1546 ldap_memfree( retoid ); 1547 ber_bvfree( retdata ); 1548 break; 1549 } 1550 1551 print_partial( ld, msg ); 1552 ldap_memfree( retoid ); 1553 ber_bvfree( retdata ); 1554 goto done; 1555 } 1556 1557 if ( ldapsync && sync_slimit != -1 && 1558 nresponses_psearch >= sync_slimit ) { 1559 BerElement *msgidber = NULL; 1560 struct berval *msgidvalp = NULL; 1561 msgidber = ber_alloc_t(LBER_USE_DER); 1562 ber_printf(msgidber, "{i}", msgid); 1563 ber_flatten(msgidber, &msgidvalp); 1564 ldap_extended_operation(ld, LDAP_EXOP_CANCEL, 1565 msgidvalp, NULL, NULL, &cancel_msgid); 1566 nresponses_psearch = -1; 1567 } 1568 } 1569 1570 ldap_msgfree( res ); 1571 } 1572 1573done: 1574 if ( tvp == NULL && rc != LDAP_RES_SEARCH_RESULT ) { 1575 ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&rc2 ); 1576 } 1577 1578 ldap_msgfree( res ); 1579 1580 if ( pagedResults ) { 1581 npagedresponses += nresponses; 1582 npagedentries += nentries; 1583 npagedextended += nextended; 1584 npagedpartial += npartial; 1585 npagedreferences += nreferences; 1586 if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) { 1587 printf( _("\n# numResponses: %d\n"), npagedresponses ); 1588 if( npagedentries ) { 1589 printf( _("# numEntries: %d\n"), npagedentries ); 1590 } 1591 if( npagedextended ) { 1592 printf( _("# numExtended: %d\n"), npagedextended ); 1593 } 1594 if( npagedpartial ) { 1595 printf( _("# numPartial: %d\n"), npagedpartial ); 1596 } 1597 if( npagedreferences ) { 1598 printf( _("# numReferences: %d\n"), npagedreferences ); 1599 } 1600 } 1601 } else if ( ldif < 2 ) { 1602 printf( _("\n# numResponses: %d\n"), nresponses ); 1603 if( nentries ) printf( _("# numEntries: %d\n"), nentries ); 1604 if( nextended ) printf( _("# numExtended: %d\n"), nextended ); 1605 if( npartial ) printf( _("# numPartial: %d\n"), npartial ); 1606 if( nreferences ) printf( _("# numReferences: %d\n"), nreferences ); 1607 } 1608 1609 if ( rc != LDAP_RES_SEARCH_RESULT ) { 1610 tool_perror( "ldap_result", rc2, NULL, NULL, NULL, NULL ); 1611 } 1612 1613 return( rc2 ); 1614} 1615 1616#ifdef __APPLE__ 1617static int 1618search_results_async(LDAP *ld) 1619{ 1620 int rc = ldap_pvt_thread_mutex_init(&callback_mutex); 1621 if (rc != 0) { 1622 tool_perror( "ldap_results_async: ldap_pvt_thread_mutex_init failed", rc, NULL, NULL, NULL, NULL ); 1623 return rc; 1624 } 1625 1626 rc = ldap_pvt_thread_cond_init(&callback_cond); 1627 if (rc != 0) { 1628 tool_perror( "ldap_results_async: ldap_pvt_thread_cond_init failed", rc, NULL, NULL, NULL, NULL ); 1629 ldap_pvt_thread_mutex_destroy(&callback_mutex); 1630 return rc; 1631 } 1632 1633 ldap_set_search_results_callback(ld, search_results_async_callback, NULL); 1634 1635 /* wait for the callback to finish */ 1636 ldap_pvt_thread_mutex_lock(&callback_mutex); 1637 while (!callback_done) { 1638 ldap_pvt_thread_cond_wait(&callback_cond, &callback_mutex); 1639 } 1640 1641 ldap_pvt_thread_mutex_unlock(&callback_mutex); 1642 1643 ldap_pvt_thread_cond_destroy(&callback_cond); 1644 ldap_pvt_thread_mutex_destroy(&callback_mutex); 1645 return LDAP_SUCCESS; 1646} 1647 1648static void 1649search_results_async_callback( 1650 LDAP *ld, 1651 LDAPMessage *res, 1652 int rc, 1653 void *context) 1654{ 1655 static int nresponses = 0; 1656 static int nentries = 0; 1657 static int nreferences = 0; 1658 static int nextended = 0; 1659 static int npartial = 0; 1660 LDAPMessage *msg; 1661 ber_int_t msgid; 1662 char *retoid = NULL; 1663 struct berval *retdata = NULL; 1664 int nresponses_psearch = -1; 1665 int cancel_msgid = -1; 1666 1667 if ( rc <= 0 ) { 1668 goto done; 1669 } 1670 1671 rc = tool_check_abandon( ld, msgid ); 1672 if ( rc ) { 1673 return; 1674 } 1675 1676 if( sortattr ) { 1677 (void) ldap_sort_entries( ld, &res, 1678 ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp ); 1679 } 1680 1681 for ( msg = ldap_first_message( ld, res ); 1682 msg != NULL; 1683 msg = ldap_next_message( ld, msg ) ) 1684 { 1685 if ( nresponses++ ) putchar('\n'); 1686 if ( nresponses_psearch >= 0 ) 1687 nresponses_psearch++; 1688 1689 switch( ldap_msgtype( msg ) ) { 1690 case LDAP_RES_SEARCH_ENTRY: 1691 nentries++; 1692 print_entry( ld, msg, attrsonly ); 1693 break; 1694 1695 case LDAP_RES_SEARCH_REFERENCE: 1696 nreferences++; 1697 print_reference( ld, msg ); 1698 break; 1699 1700 case LDAP_RES_EXTENDED: 1701 nextended++; 1702 print_extended( ld, msg ); 1703 1704 if ( ldap_msgid( msg ) == 0 ) { 1705 /* unsolicited extended operation */ 1706 goto done; 1707 } 1708 1709 if ( cancel_msgid != -1 && 1710 cancel_msgid == ldap_msgid( msg ) ) { 1711 printf(_("Cancelled \n")); 1712 printf(_("cancel_msgid = %d\n"), cancel_msgid); 1713 goto done; 1714 } 1715 break; 1716 1717 case LDAP_RES_SEARCH_RESULT: 1718 /* pagedResults stuff is dealt with 1719 * in tool_print_ctrls(), called by 1720 * print_results(). */ 1721 rc = print_result( ld, msg, 1 ); 1722 if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) { 1723 break; 1724 } 1725 1726 goto done; 1727 1728 case LDAP_RES_INTERMEDIATE: 1729 npartial++; 1730 ldap_parse_intermediate( ld, msg, 1731 &retoid, &retdata, NULL, 0 ); 1732 1733 nresponses_psearch = 0; 1734 1735 if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) { 1736 printf(_("SyncInfo Received\n")); 1737 ldap_memfree( retoid ); 1738 ber_bvfree( retdata ); 1739 break; 1740 } 1741 1742 print_partial( ld, msg ); 1743 ldap_memfree( retoid ); 1744 ber_bvfree( retdata ); 1745 goto done; 1746 } 1747 1748 if ( ldapsync && sync_slimit != -1 && 1749 nresponses_psearch >= sync_slimit ) { 1750 BerElement *msgidber = NULL; 1751 struct berval *msgidvalp = NULL; 1752 msgidber = ber_alloc_t(LBER_USE_DER); 1753 ber_printf(msgidber, "{i}", msgid); 1754 ber_flatten(msgidber, &msgidvalp); 1755 ldap_extended_operation(ld, LDAP_EXOP_CANCEL, 1756 msgidvalp, NULL, NULL, &cancel_msgid); 1757 nresponses_psearch = -1; 1758 } 1759 } 1760 1761not_done: 1762 return; 1763 1764done: 1765 if ( rc == -1 ) { 1766 tool_perror( "ldap_results_async_callback", rc, NULL, NULL, NULL, NULL ); 1767 } 1768 else { 1769 if ( pagedResults ) { 1770 npagedresponses += nresponses; 1771 npagedentries += nentries; 1772 npagedextended += nextended; 1773 npagedpartial += npartial; 1774 npagedreferences += nreferences; 1775 if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) { 1776 printf( _("\n# numResponses: %d\n"), npagedresponses ); 1777 if( npagedentries ) { 1778 printf( _("# numEntries: %d\n"), npagedentries ); 1779 } 1780 if( npagedextended ) { 1781 printf( _("# numExtended: %d\n"), npagedextended ); 1782 } 1783 if( npagedpartial ) { 1784 printf( _("# numPartial: %d\n"), npagedpartial ); 1785 } 1786 if( npagedreferences ) { 1787 printf( _("# numReferences: %d\n"), npagedreferences ); 1788 } 1789 } 1790 } else if ( ldif < 2 ) { 1791 printf( _("\n# numResponses: %d\n"), nresponses ); 1792 if( nentries ) printf( _("# numEntries: %d\n"), nentries ); 1793 if( nextended ) printf( _("# numExtended: %d\n"), nextended ); 1794 if( npartial ) printf( _("# numPartial: %d\n"), npartial ); 1795 if( nreferences ) printf( _("# numReferences: %d\n"), nreferences ); 1796 } 1797 } 1798 1799 /* Signal the waiting thread that we're done */ 1800 ldap_pvt_thread_mutex_lock(&callback_mutex); 1801 callback_done = 1; 1802 ldap_pvt_thread_cond_signal(&callback_cond); 1803 ldap_pvt_thread_mutex_unlock(&callback_mutex); 1804} 1805#endif /* __APPLE__ */ 1806 1807/* This is the proposed new way of doing things. 1808 * It is more efficient, but the API is non-standard. 1809 */ 1810static void 1811print_entry( 1812 LDAP *ld, 1813 LDAPMessage *entry, 1814 int attrsonly) 1815{ 1816 char *ufn = NULL; 1817 char tmpfname[ 256 ]; 1818 char url[ 256 ]; 1819 int i, rc; 1820 BerElement *ber = NULL; 1821 struct berval bv, *bvals, **bvp = &bvals; 1822 LDAPControl **ctrls = NULL; 1823 FILE *tmpfp; 1824 1825 rc = ldap_get_dn_ber( ld, entry, &ber, &bv ); 1826 1827 if ( ldif < 2 ) { 1828 ufn = ldap_dn2ufn( bv.bv_val ); 1829 tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 ); 1830 } 1831 tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len ); 1832 1833 rc = ldap_get_entry_controls( ld, entry, &ctrls ); 1834 if( rc != LDAP_SUCCESS ) { 1835 fprintf(stderr, _("print_entry: %d\n"), rc ); 1836 tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL ); 1837 tool_exit( ld, EXIT_FAILURE ); 1838 } 1839 1840 if( ctrls ) { 1841 tool_print_ctrls( ld, ctrls ); 1842 ldap_controls_free( ctrls ); 1843 } 1844 1845 if ( includeufn ) { 1846 if( ufn == NULL ) { 1847 ufn = ldap_dn2ufn( bv.bv_val ); 1848 } 1849 tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 ); 1850 } 1851 1852 if( ufn != NULL ) ldap_memfree( ufn ); 1853 1854 if ( attrsonly ) bvp = NULL; 1855 1856 for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ); 1857 rc == LDAP_SUCCESS; 1858 rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) ) 1859 { 1860 if (bv.bv_val == NULL) break; 1861 1862 if ( attrsonly ) { 1863 tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 ); 1864 1865 } else if ( bvals ) { 1866 for ( i = 0; bvals[i].bv_val != NULL; i++ ) { 1867 if ( vals2tmp > 1 || ( vals2tmp && 1868 ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len ))) 1869 { 1870 int tmpfd; 1871 /* write value to file */ 1872 snprintf( tmpfname, sizeof tmpfname, 1873 "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX", 1874 tmpdir, bv.bv_val ); 1875 tmpfp = NULL; 1876 1877 tmpfd = mkstemp( tmpfname ); 1878 1879 if ( tmpfd < 0 ) { 1880 perror( tmpfname ); 1881 continue; 1882 } 1883 1884 if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) { 1885 perror( tmpfname ); 1886 continue; 1887 } 1888 1889 if ( fwrite( bvals[ i ].bv_val, 1890 bvals[ i ].bv_len, 1, tmpfp ) == 0 ) 1891 { 1892 perror( tmpfname ); 1893 fclose( tmpfp ); 1894 continue; 1895 } 1896 1897 fclose( tmpfp ); 1898 1899 snprintf( url, sizeof url, "%s%s", urlpre, 1900 &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] ); 1901 1902 urlize( url ); 1903 tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url )); 1904 1905 } else { 1906 tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val, 1907 bvals[ i ].bv_val, bvals[ i ].bv_len ); 1908 } 1909 } 1910 ber_memfree( bvals ); 1911 } 1912 } 1913 1914 if( ber != NULL ) { 1915 ber_free( ber, 0 ); 1916 } 1917} 1918 1919static void print_reference( 1920 LDAP *ld, 1921 LDAPMessage *reference ) 1922{ 1923 int rc; 1924 char **refs = NULL; 1925 LDAPControl **ctrls; 1926 1927 if( ldif < 2 ) { 1928 printf(_("# search reference\n")); 1929 } 1930 1931 rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 ); 1932 1933 if( rc != LDAP_SUCCESS ) { 1934 tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL ); 1935 tool_exit( ld, EXIT_FAILURE ); 1936 } 1937 1938 if( refs ) { 1939 int i; 1940 for( i=0; refs[i] != NULL; i++ ) { 1941 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1942 "ref", refs[i], strlen(refs[i]) ); 1943 } 1944 ber_memvfree( (void **) refs ); 1945 } 1946 1947 if( ctrls ) { 1948 tool_print_ctrls( ld, ctrls ); 1949 ldap_controls_free( ctrls ); 1950 } 1951} 1952 1953static void print_extended( 1954 LDAP *ld, 1955 LDAPMessage *extended ) 1956{ 1957 int rc; 1958 char *retoid = NULL; 1959 struct berval *retdata = NULL; 1960 1961 if( ldif < 2 ) { 1962 printf(_("# extended result response\n")); 1963 } 1964 1965 rc = ldap_parse_extended_result( ld, extended, 1966 &retoid, &retdata, 0 ); 1967 1968 if( rc != LDAP_SUCCESS ) { 1969 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); 1970 tool_exit( ld, EXIT_FAILURE ); 1971 } 1972 1973 if ( ldif < 2 ) { 1974 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1975 "extended", retoid, retoid ? strlen(retoid) : 0 ); 1976 } 1977 ber_memfree( retoid ); 1978 1979 if(retdata) { 1980 if ( ldif < 2 ) { 1981 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, 1982 "data", retdata->bv_val, retdata->bv_len ); 1983 } 1984 ber_bvfree( retdata ); 1985 } 1986 1987 print_result( ld, extended, 0 ); 1988} 1989 1990static void print_partial( 1991 LDAP *ld, 1992 LDAPMessage *partial ) 1993{ 1994 int rc; 1995 char *retoid = NULL; 1996 struct berval *retdata = NULL; 1997 LDAPControl **ctrls = NULL; 1998 1999 if( ldif < 2 ) { 2000 printf(_("# extended partial response\n")); 2001 } 2002 2003 rc = ldap_parse_intermediate( ld, partial, 2004 &retoid, &retdata, &ctrls, 0 ); 2005 2006 if( rc != LDAP_SUCCESS ) { 2007 tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL ); 2008 tool_exit( ld, EXIT_FAILURE ); 2009 } 2010 2011 if ( ldif < 2 ) { 2012 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 2013 "partial", retoid, retoid ? strlen(retoid) : 0 ); 2014 } 2015 2016 ber_memfree( retoid ); 2017 2018 if( retdata ) { 2019 if ( ldif < 2 ) { 2020 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, 2021 "data", retdata->bv_val, retdata->bv_len ); 2022 } 2023 2024 ber_bvfree( retdata ); 2025 } 2026 2027 if( ctrls ) { 2028 tool_print_ctrls( ld, ctrls ); 2029 ldap_controls_free( ctrls ); 2030 } 2031} 2032 2033static int print_result( 2034 LDAP *ld, 2035 LDAPMessage *result, int search ) 2036{ 2037 int rc; 2038 int err; 2039 char *matcheddn = NULL; 2040 char *text = NULL; 2041 char **refs = NULL; 2042 LDAPControl **ctrls = NULL; 2043 2044 if( search ) { 2045 if ( ldif < 2 ) { 2046 printf(_("# search result\n")); 2047 } 2048 if ( ldif < 1 ) { 2049 printf("%s: %d\n", _("search"), ldap_msgid(result) ); 2050 } 2051 } 2052 2053 rc = ldap_parse_result( ld, result, 2054 &err, &matcheddn, &text, &refs, &ctrls, 0 ); 2055 2056 if( rc != LDAP_SUCCESS ) { 2057 tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL ); 2058 tool_exit( ld, EXIT_FAILURE ); 2059 } 2060 2061 2062 if( !ldif ) { 2063 printf( _("result: %d %s\n"), err, ldap_err2string(err) ); 2064 2065 } else if ( err != LDAP_SUCCESS ) { 2066 fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err ); 2067 } 2068 2069 if( matcheddn ) { 2070 if( *matcheddn ) { 2071 if( !ldif ) { 2072 tool_write_ldif( LDIF_PUT_VALUE, 2073 "matchedDN", matcheddn, strlen(matcheddn) ); 2074 } else { 2075 fprintf( stderr, _("Matched DN: %s\n"), matcheddn ); 2076 } 2077 } 2078 2079 ber_memfree( matcheddn ); 2080 } 2081 2082 if( text ) { 2083 if( *text ) { 2084 if( !ldif ) { 2085 if ( err == LDAP_PARTIAL_RESULTS ) { 2086 char *line; 2087 2088 for ( line = text; line != NULL; ) { 2089 char *next = strchr( line, '\n' ); 2090 2091 tool_write_ldif( LDIF_PUT_TEXT, 2092 "text", line, 2093 next ? (size_t) (next - line) : strlen( line )); 2094 2095 line = next ? next + 1 : NULL; 2096 } 2097 2098 } else { 2099 tool_write_ldif( LDIF_PUT_TEXT, "text", 2100 text, strlen(text) ); 2101 } 2102 } else { 2103 fprintf( stderr, _("Additional information: %s\n"), text ); 2104 } 2105 } 2106 2107 ber_memfree( text ); 2108 } 2109 2110 if( refs ) { 2111 int i; 2112 for( i=0; refs[i] != NULL; i++ ) { 2113 if( !ldif ) { 2114 tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) ); 2115 } else { 2116 fprintf( stderr, _("Referral: %s\n"), refs[i] ); 2117 } 2118 } 2119 2120 ber_memvfree( (void **) refs ); 2121 } 2122 2123 pr_morePagedResults = 0; 2124 2125 if( ctrls ) { 2126 tool_print_ctrls( ld, ctrls ); 2127 ldap_controls_free( ctrls ); 2128 } 2129 2130 return err; 2131} 2132