1 /* ldapsearch -- a tool for searching LDAP directories */ 2 /* $OpenLDAP: pkg/ldap/clients/tools/ldapsearch.c,v 1.234.2.9 2008/02/12 19:59:52 quanah Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * Portions Copyright 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_log.h" 70 #include "ldap_pvt.h" 71 72 #include "common.h" 73 74 #if !LDAP_DEPRECATED 75 /* 76 * NOTE: we use this deprecated function only because 77 * we want ldapsearch to provide some client-side sorting 78 * capability. 79 */ 80 /* from ldap.h */ 81 typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */ 82 LDAP_CONST char *left, 83 LDAP_CONST char *right )); 84 85 LDAP_F( int ) /* deprecated */ 86 ldap_sort_entries LDAP_P(( LDAP *ld, 87 LDAPMessage **chain, 88 LDAP_CONST char *attr, 89 LDAP_SORT_AD_CMP_PROC *cmp )); 90 #endif 91 92 static int scope = LDAP_SCOPE_SUBTREE; 93 static int deref = -1; 94 static int attrsonly; 95 static int timelimit = -1; 96 static int sizelimit = -1; 97 98 static char *control; 99 100 static char *def_tmpdir; 101 static char *def_urlpre; 102 103 #if defined(__CYGWIN__) || defined(__MINGW32__) 104 /* Turn off commandline globbing, otherwise you cannot search for 105 * attribute '*' 106 */ 107 int _CRT_glob = 0; 108 #endif 109 110 void 111 usage( void ) 112 { 113 fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog); 114 fprintf( stderr, _(" filter\tRFC 4515 compliant LDAP search filter\n")); 115 fprintf( stderr, _(" attributes\twhitespace-separated list of attribute descriptions\n")); 116 fprintf( stderr, _(" which may include:\n")); 117 fprintf( stderr, _(" 1.1 no attributes\n")); 118 fprintf( stderr, _(" * all user attributes\n")); 119 fprintf( stderr, _(" + all operational attributes\n")); 120 121 122 fprintf( stderr, _("Search options:\n")); 123 fprintf( stderr, _(" -a deref one of never (default), always, search, or find\n")); 124 fprintf( stderr, _(" -A retrieve attribute names only (no values)\n")); 125 fprintf( stderr, _(" -b basedn base dn for search\n")); 126 fprintf( stderr, _(" -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n")); 127 fprintf( stderr, _(" [!]domainScope (domain scope)\n")); 128 fprintf( stderr, _(" !dontUseCopy (Don't Use Copy)\n")); 129 fprintf( stderr, _(" [!]mv=<filter> (matched values filter)\n")); 130 fprintf( stderr, _(" [!]pr=<size>[/prompt|noprompt] (paged results/prompt)\n")); 131 fprintf( stderr, _(" [!]subentries[=true|false] (subentries)\n")); 132 fprintf( stderr, _(" [!]sync=ro[/<cookie>] (LDAP Sync refreshOnly)\n")); 133 fprintf( stderr, _(" rp[/<cookie>][/<slimit>] (LDAP Sync refreshAndPersist)\n")); 134 fprintf( stderr, _(" [!]<oid>=:<value> (generic control; no response handling)\n")); 135 fprintf( stderr, _(" -F prefix URL prefix for files (default: %s)\n"), def_urlpre); 136 fprintf( stderr, _(" -l limit time limit (in seconds, or \"none\" or \"max\") for search\n")); 137 fprintf( stderr, _(" -L print responses in LDIFv1 format\n")); 138 fprintf( stderr, _(" -LL print responses in LDIF format without comments\n")); 139 fprintf( stderr, _(" -LLL print responses in LDIF format without comments\n")); 140 fprintf( stderr, _(" and version\n")); 141 fprintf( stderr, _(" -s scope one of base, one, sub or children (search scope)\n")); 142 fprintf( stderr, _(" -S attr sort the results by attribute `attr'\n")); 143 fprintf( stderr, _(" -t write binary values to files in temporary directory\n")); 144 fprintf( stderr, _(" -tt write all values to files in temporary directory\n")); 145 fprintf( stderr, _(" -T path write files to directory specified by path (default: %s)\n"), def_tmpdir); 146 fprintf( stderr, _(" -u include User Friendly entry names in the output\n")); 147 fprintf( stderr, _(" -z limit size limit (in entries, or \"none\" or \"max\") for search\n")); 148 tool_common_usage(); 149 exit( EXIT_FAILURE ); 150 } 151 152 static void print_entry LDAP_P(( 153 LDAP *ld, 154 LDAPMessage *entry, 155 int attrsonly)); 156 157 static void print_reference( 158 LDAP *ld, 159 LDAPMessage *reference ); 160 161 static void print_extended( 162 LDAP *ld, 163 LDAPMessage *extended ); 164 165 static void print_partial( 166 LDAP *ld, 167 LDAPMessage *partial ); 168 169 static int print_result( 170 LDAP *ld, 171 LDAPMessage *result, 172 int search ); 173 174 static int dosearch LDAP_P(( 175 LDAP *ld, 176 char *base, 177 int scope, 178 char *filtpatt, 179 char *value, 180 char **attrs, 181 int attrsonly, 182 LDAPControl **sctrls, 183 LDAPControl **cctrls, 184 struct timeval *timeout, 185 int sizelimit )); 186 187 static char *tmpdir = NULL; 188 static char *urlpre = NULL; 189 static char *base = NULL; 190 static char *sortattr = NULL; 191 static int includeufn, vals2tmp = 0; 192 193 static int subentries = 0, valuesReturnFilter = 0; 194 static char *vrFilter = NULL; 195 196 #ifdef LDAP_CONTROL_DONTUSECOPY 197 static int dontUseCopy = 0; 198 #endif 199 200 static int domainScope = 0; 201 202 static int ldapsync = 0; 203 static struct berval sync_cookie = { 0, NULL }; 204 static int sync_slimit = -1; 205 206 /* cookie and morePagedResults moved to common.c */ 207 static int pagedResults = 0; 208 static int pagePrompt = 1; 209 static ber_int_t pageSize = 0; 210 static ber_int_t entriesLeft = 0; 211 static int npagedresponses; 212 static int npagedentries; 213 static int npagedreferences; 214 static int npagedextended; 215 static int npagedpartial; 216 217 static LDAPControl *c = NULL; 218 static int nctrls = 0; 219 static int save_nctrls = 0; 220 221 static int 222 ctrl_add( void ) 223 { 224 LDAPControl *tmpc; 225 226 nctrls++; 227 tmpc = realloc( c, sizeof( LDAPControl ) * nctrls ); 228 if ( tmpc == NULL ) { 229 nctrls--; 230 fprintf( stderr, 231 _("unable to make room for control; out of memory?\n")); 232 return -1; 233 } 234 c = tmpc; 235 236 return 0; 237 } 238 239 static void 240 urlize(char *url) 241 { 242 char *p; 243 244 if (*LDAP_DIRSEP != '/') { 245 for (p = url; *p; p++) { 246 if (*p == *LDAP_DIRSEP) 247 *p = '/'; 248 } 249 } 250 } 251 252 253 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:" 254 "Cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z"; 255 256 int 257 handle_private_option( int i ) 258 { 259 int crit, ival; 260 char *cvalue, *next; 261 switch ( i ) { 262 case 'a': /* set alias deref option */ 263 if ( strcasecmp( optarg, "never" ) == 0 ) { 264 deref = LDAP_DEREF_NEVER; 265 } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) { 266 deref = LDAP_DEREF_SEARCHING; 267 } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) { 268 deref = LDAP_DEREF_FINDING; 269 } else if ( strcasecmp( optarg, "always" ) == 0 ) { 270 deref = LDAP_DEREF_ALWAYS; 271 } else { 272 fprintf( stderr, 273 _("alias deref should be never, search, find, or always\n") ); 274 usage(); 275 } 276 break; 277 case 'A': /* retrieve attribute names only -- no values */ 278 ++attrsonly; 279 break; 280 case 'b': /* search base */ 281 base = ber_strdup( optarg ); 282 break; 283 case 'E': /* search extensions */ 284 if( protocol == LDAP_VERSION2 ) { 285 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"), 286 prog, protocol ); 287 exit( EXIT_FAILURE ); 288 } 289 290 /* should be extended to support comma separated list of 291 * [!]key[=value] parameters, e.g. -E !foo,bar=567 292 */ 293 294 crit = 0; 295 cvalue = NULL; 296 if( optarg[0] == '!' ) { 297 crit = 1; 298 optarg++; 299 } 300 301 control = ber_strdup( optarg ); 302 if ( (cvalue = strchr( control, '=' )) != NULL ) { 303 *cvalue++ = '\0'; 304 } 305 306 if ( strcasecmp( control, "mv" ) == 0 ) { 307 /* ValuesReturnFilter control */ 308 if( valuesReturnFilter ) { 309 fprintf( stderr, 310 _("ValuesReturnFilter previously specified\n")); 311 exit( EXIT_FAILURE ); 312 } 313 valuesReturnFilter= 1 + crit; 314 315 if ( cvalue == NULL ) { 316 fprintf( stderr, 317 _("missing filter in ValuesReturnFilter control\n")); 318 exit( EXIT_FAILURE ); 319 } 320 321 vrFilter = cvalue; 322 protocol = LDAP_VERSION3; 323 324 } else if ( strcasecmp( control, "pr" ) == 0 ) { 325 int num, tmp; 326 /* PagedResults control */ 327 if ( pagedResults != 0 ) { 328 fprintf( stderr, 329 _("PagedResultsControl previously specified\n") ); 330 exit( EXIT_FAILURE ); 331 } 332 333 if( cvalue != NULL ) { 334 char *promptp; 335 336 promptp = strchr( cvalue, '/' ); 337 if ( promptp != NULL ) { 338 *promptp++ = '\0'; 339 if ( strcasecmp( promptp, "prompt" ) == 0 ) { 340 pagePrompt = 1; 341 } else if ( strcasecmp( promptp, "noprompt" ) == 0) { 342 pagePrompt = 0; 343 } else { 344 fprintf( stderr, 345 _("Invalid value for PagedResultsControl," 346 " %s/%s.\n"), cvalue, promptp ); 347 exit( EXIT_FAILURE ); 348 } 349 } 350 num = sscanf( cvalue, "%d", &tmp ); 351 if ( num != 1 ) { 352 fprintf( stderr, 353 _("Invalid value for PagedResultsControl, %s.\n"), 354 cvalue ); 355 exit( EXIT_FAILURE ); 356 } 357 } else { 358 fprintf(stderr, _("Invalid value for PagedResultsControl.\n")); 359 exit( EXIT_FAILURE ); 360 } 361 pageSize = (ber_int_t) tmp; 362 pagedResults = 1 + crit; 363 364 #ifdef LDAP_CONTROL_DONTUSECOPY 365 } else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) { 366 if( dontUseCopy ) { 367 fprintf( stderr, 368 _("dontUseCopy control previously specified\n")); 369 exit( EXIT_FAILURE ); 370 } 371 if( cvalue != NULL ) { 372 fprintf( stderr, 373 _("dontUseCopy: no control value expected\n") ); 374 usage(); 375 } 376 if( !crit ) { 377 fprintf( stderr, 378 _("dontUseCopy: critical flag required\n") ); 379 usage(); 380 } 381 382 dontUseCopy = 1 + crit; 383 #endif 384 } else if ( strcasecmp( control, "domainScope" ) == 0 ) { 385 if( domainScope ) { 386 fprintf( stderr, 387 _("domainScope control previously specified\n")); 388 exit( EXIT_FAILURE ); 389 } 390 if( cvalue != NULL ) { 391 fprintf( stderr, 392 _("domainScope: no control value expected\n") ); 393 usage(); 394 } 395 396 domainScope = 1 + crit; 397 398 } else if ( strcasecmp( control, "subentries" ) == 0 ) { 399 if( subentries ) { 400 fprintf( stderr, 401 _("subentries control previously specified\n")); 402 exit( EXIT_FAILURE ); 403 } 404 if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) { 405 subentries = 2; 406 } else if ( strcasecmp( cvalue, "false") == 0 ) { 407 subentries = 1; 408 } else { 409 fprintf( stderr, 410 _("subentries control value \"%s\" invalid\n"), 411 cvalue ); 412 exit( EXIT_FAILURE ); 413 } 414 if( crit ) subentries *= -1; 415 416 } else if ( strcasecmp( control, "sync" ) == 0 ) { 417 char *cookiep; 418 char *slimitp; 419 if ( ldapsync ) { 420 fprintf( stderr, _("sync control previously specified\n") ); 421 exit( EXIT_FAILURE ); 422 } 423 if ( cvalue == NULL ) { 424 fprintf( stderr, _("missing specification of sync control\n")); 425 exit( EXIT_FAILURE ); 426 } 427 if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) { 428 ldapsync = LDAP_SYNC_REFRESH_ONLY; 429 cookiep = strchr( cvalue, '/' ); 430 if ( cookiep != NULL ) { 431 cookiep++; 432 if ( *cookiep != '\0' ) { 433 ber_str2bv( cookiep, 0, 0, &sync_cookie ); 434 } 435 } 436 } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) { 437 ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST; 438 cookiep = strchr( cvalue, '/' ); 439 if ( cookiep != NULL ) { 440 *cookiep++ = '\0'; 441 cvalue = cookiep; 442 } 443 slimitp = strchr( cvalue, '/' ); 444 if ( slimitp != NULL ) { 445 *slimitp++ = '\0'; 446 } 447 if ( cookiep != NULL && *cookiep != '\0' ) 448 ber_str2bv( cookiep, 0, 0, &sync_cookie ); 449 if ( slimitp != NULL && *slimitp != '\0' ) { 450 ival = strtol( slimitp, &next, 10 ); 451 if ( next == NULL || next[0] != '\0' ) { 452 fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp ); 453 exit( EXIT_FAILURE ); 454 } 455 sync_slimit = ival; 456 } 457 } else { 458 fprintf( stderr, _("sync control value \"%s\" invalid\n"), 459 cvalue ); 460 exit( EXIT_FAILURE ); 461 } 462 if ( crit ) ldapsync *= -1; 463 464 } else if ( tool_is_oid( control ) ) { 465 if ( ctrl_add() ) { 466 exit( EXIT_FAILURE ); 467 } 468 469 /* OID */ 470 c[ nctrls - 1 ].ldctl_oid = control; 471 472 /* value */ 473 if ( cvalue == NULL ) { 474 c[ nctrls - 1 ].ldctl_value.bv_val = NULL; 475 c[ nctrls - 1 ].ldctl_value.bv_len = 0; 476 477 } else if ( cvalue[ 0 ] == ':' ) { 478 struct berval type; 479 struct berval value; 480 int freeval; 481 482 cvalue++; 483 484 /* dummy type "x" 485 * to use ldif_parse_line2() */ 486 cvalue[ -2 ] = 'x'; 487 ldif_parse_line2( &cvalue[ -2 ], &type, 488 &value, &freeval ); 489 cvalue[ -2 ] = '\0'; 490 491 if ( freeval ) { 492 c[ nctrls - 1 ].ldctl_value = value; 493 494 } else { 495 ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value ); 496 } 497 } 498 499 /* criticality */ 500 c[ nctrls - 1 ].ldctl_iscritical = crit; 501 502 } else { 503 fprintf( stderr, _("Invalid search extension name: %s\n"), 504 control ); 505 usage(); 506 } 507 break; 508 case 'F': /* uri prefix */ 509 if( urlpre ) free( urlpre ); 510 urlpre = strdup( optarg ); 511 break; 512 case 'l': /* time limit */ 513 if ( strcasecmp( optarg, "none" ) == 0 ) { 514 timelimit = 0; 515 516 } else if ( strcasecmp( optarg, "max" ) == 0 ) { 517 timelimit = LDAP_MAXINT; 518 519 } else { 520 ival = strtol( optarg, &next, 10 ); 521 if ( next == NULL || next[0] != '\0' ) { 522 fprintf( stderr, 523 _("Unable to parse time limit \"%s\"\n"), optarg ); 524 exit( EXIT_FAILURE ); 525 } 526 timelimit = ival; 527 } 528 if( timelimit < 0 || timelimit > LDAP_MAXINT ) { 529 fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"), 530 prog, timelimit ); 531 exit( EXIT_FAILURE ); 532 } 533 break; 534 case 'L': /* print entries in LDIF format */ 535 ++ldif; 536 break; 537 case 's': /* search scope */ 538 if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) { 539 scope = LDAP_SCOPE_BASE; 540 } else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) { 541 scope = LDAP_SCOPE_ONELEVEL; 542 } else if (( strcasecmp( optarg, "subordinate" ) == 0 ) 543 || ( strcasecmp( optarg, "children" ) == 0 )) 544 { 545 scope = LDAP_SCOPE_SUBORDINATE; 546 } else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) { 547 scope = LDAP_SCOPE_SUBTREE; 548 } else { 549 fprintf( stderr, _("scope should be base, one, or sub\n") ); 550 usage(); 551 } 552 break; 553 case 'S': /* sort attribute */ 554 sortattr = strdup( optarg ); 555 break; 556 case 't': /* write attribute values to TMPDIR files */ 557 ++vals2tmp; 558 break; 559 case 'T': /* tmpdir */ 560 if( tmpdir ) free( tmpdir ); 561 tmpdir = strdup( optarg ); 562 break; 563 case 'u': /* include UFN */ 564 ++includeufn; 565 break; 566 case 'z': /* size limit */ 567 if ( strcasecmp( optarg, "none" ) == 0 ) { 568 sizelimit = 0; 569 570 } else if ( strcasecmp( optarg, "max" ) == 0 ) { 571 sizelimit = LDAP_MAXINT; 572 573 } else { 574 ival = strtol( optarg, &next, 10 ); 575 if ( next == NULL || next[0] != '\0' ) { 576 fprintf( stderr, 577 _("Unable to parse size limit \"%s\"\n"), optarg ); 578 exit( EXIT_FAILURE ); 579 } 580 sizelimit = ival; 581 } 582 if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) { 583 fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"), 584 prog, sizelimit ); 585 exit( EXIT_FAILURE ); 586 } 587 break; 588 default: 589 return 0; 590 } 591 return 1; 592 } 593 594 595 static void 596 private_conn_setup( LDAP *ld ) 597 { 598 if (deref != -1 && 599 ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) 600 != LDAP_OPT_SUCCESS ) 601 { 602 fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref ); 603 exit( EXIT_FAILURE ); 604 } 605 if (timelimit > 0 && 606 ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) 607 != LDAP_OPT_SUCCESS ) 608 { 609 fprintf( stderr, 610 _("Could not set LDAP_OPT_TIMELIMIT %d\n"), timelimit ); 611 exit( EXIT_FAILURE ); 612 } 613 if (sizelimit > 0 && 614 ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) 615 != LDAP_OPT_SUCCESS ) 616 { 617 fprintf( stderr, 618 _("Could not set LDAP_OPT_SIZELIMIT %d\n"), sizelimit ); 619 exit( EXIT_FAILURE ); 620 } 621 } 622 623 int 624 main( int argc, char **argv ) 625 { 626 char *filtpattern, **attrs = NULL, line[BUFSIZ]; 627 FILE *fp = NULL; 628 int rc, rc1, i, first; 629 LDAP *ld = NULL; 630 BerElement *seber = NULL, *vrber = NULL; 631 632 BerElement *syncber = NULL; 633 struct berval *syncbvalp = NULL; 634 int err; 635 636 tool_init( TOOL_SEARCH ); 637 638 npagedresponses = npagedentries = npagedreferences = 639 npagedextended = npagedpartial = 0; 640 641 prog = lutil_progname( "ldapsearch", argc, argv ); 642 643 if((def_tmpdir = getenv("TMPDIR")) == NULL && 644 (def_tmpdir = getenv("TMP")) == NULL && 645 (def_tmpdir = getenv("TEMP")) == NULL ) 646 { 647 def_tmpdir = LDAP_TMPDIR; 648 } 649 650 if ( !*def_tmpdir ) 651 def_tmpdir = LDAP_TMPDIR; 652 653 def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) ); 654 655 if( def_urlpre == NULL ) { 656 perror( "malloc" ); 657 return EXIT_FAILURE; 658 } 659 660 sprintf( def_urlpre, "file:///%s/", 661 def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir ); 662 663 urlize( def_urlpre ); 664 665 tool_args( argc, argv ); 666 667 if (( argc - optind < 1 ) || 668 ( *argv[optind] != '(' /*')'*/ && 669 ( strchr( argv[optind], '=' ) == NULL ) ) ) 670 { 671 filtpattern = "(objectclass=*)"; 672 } else { 673 filtpattern = argv[optind++]; 674 } 675 676 if ( argv[optind] != NULL ) { 677 attrs = &argv[optind]; 678 } 679 680 if ( infile != NULL ) { 681 int percent = 0; 682 683 if ( infile[0] == '-' && infile[1] == '\0' ) { 684 fp = stdin; 685 } else if (( fp = fopen( infile, "r" )) == NULL ) { 686 perror( infile ); 687 return EXIT_FAILURE; 688 } 689 690 for( i=0 ; filtpattern[i] ; i++ ) { 691 if( filtpattern[i] == '%' ) { 692 if( percent ) { 693 fprintf( stderr, _("Bad filter pattern \"%s\"\n"), 694 filtpattern ); 695 return EXIT_FAILURE; 696 } 697 698 percent++; 699 700 if( filtpattern[i+1] != 's' ) { 701 fprintf( stderr, _("Bad filter pattern \"%s\"\n"), 702 filtpattern ); 703 return EXIT_FAILURE; 704 } 705 } 706 } 707 } 708 709 if ( tmpdir == NULL ) { 710 tmpdir = def_tmpdir; 711 712 if ( urlpre == NULL ) 713 urlpre = def_urlpre; 714 } 715 716 if( urlpre == NULL ) { 717 urlpre = malloc( sizeof("file:////") + strlen(tmpdir) ); 718 719 if( urlpre == NULL ) { 720 perror( "malloc" ); 721 return EXIT_FAILURE; 722 } 723 724 sprintf( urlpre, "file:///%s/", 725 tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir ); 726 727 urlize( urlpre ); 728 } 729 730 if ( debug ) 731 ldif_debug = debug; 732 733 ld = tool_conn_setup( 0, &private_conn_setup ); 734 735 if ( pw_file || want_bindpw ) { 736 if ( pw_file ) { 737 rc = lutil_get_filed_password( pw_file, &passwd ); 738 if( rc ) return EXIT_FAILURE; 739 } else { 740 passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") ); 741 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; 742 } 743 } 744 745 tool_bind( ld ); 746 747 getNextPage: 748 save_nctrls = nctrls; 749 i = nctrls; 750 if ( nctrls > 0 751 #ifdef LDAP_CONTROL_DONTUSECOPY 752 || dontUseCopy 753 #endif 754 || domainScope 755 || pagedResults 756 || ldapsync 757 || subentries 758 || valuesReturnFilter ) 759 { 760 761 #ifdef LDAP_CONTROL_DONTUSECOPY 762 if ( dontUseCopy ) { 763 if ( ctrl_add() ) { 764 return EXIT_FAILURE; 765 } 766 767 c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY; 768 c[i].ldctl_value.bv_val = NULL; 769 c[i].ldctl_value.bv_len = 0; 770 c[i].ldctl_iscritical = dontUseCopy > 1; 771 i++; 772 } 773 #endif 774 775 if ( domainScope ) { 776 if ( ctrl_add() ) { 777 return EXIT_FAILURE; 778 } 779 780 c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE; 781 c[i].ldctl_value.bv_val = NULL; 782 c[i].ldctl_value.bv_len = 0; 783 c[i].ldctl_iscritical = domainScope > 1; 784 i++; 785 } 786 787 if ( subentries ) { 788 if ( ctrl_add() ) { 789 return EXIT_FAILURE; 790 } 791 792 if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 793 return EXIT_FAILURE; 794 } 795 796 err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 ); 797 if ( err == -1 ) { 798 ber_free( seber, 1 ); 799 fprintf( stderr, _("Subentries control encoding error!\n") ); 800 return EXIT_FAILURE; 801 } 802 803 if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) { 804 return EXIT_FAILURE; 805 } 806 807 c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES; 808 c[i].ldctl_iscritical = subentries < 1; 809 i++; 810 } 811 812 if ( ldapsync ) { 813 if ( ctrl_add() ) { 814 return EXIT_FAILURE; 815 } 816 817 if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 818 return EXIT_FAILURE; 819 } 820 821 if ( sync_cookie.bv_len == 0 ) { 822 err = ber_printf( syncber, "{e}", abs(ldapsync) ); 823 } else { 824 err = ber_printf( syncber, "{eO}", abs(ldapsync), 825 &sync_cookie ); 826 } 827 828 if ( err == LBER_ERROR ) { 829 ber_free( syncber, 1 ); 830 fprintf( stderr, _("ldap sync control encoding error!\n") ); 831 return EXIT_FAILURE; 832 } 833 834 if ( ber_flatten( syncber, &syncbvalp ) == LBER_ERROR ) { 835 return EXIT_FAILURE; 836 } 837 838 c[i].ldctl_oid = LDAP_CONTROL_SYNC; 839 c[i].ldctl_value = (*syncbvalp); 840 c[i].ldctl_iscritical = ldapsync < 0; 841 i++; 842 } 843 844 if ( valuesReturnFilter ) { 845 if ( ctrl_add() ) { 846 return EXIT_FAILURE; 847 } 848 849 if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) { 850 return EXIT_FAILURE; 851 } 852 853 if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) { 854 ber_free( vrber, 1 ); 855 fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter ); 856 return EXIT_FAILURE; 857 } 858 859 if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) { 860 return EXIT_FAILURE; 861 } 862 863 c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER; 864 c[i].ldctl_iscritical = valuesReturnFilter > 1; 865 i++; 866 } 867 868 if ( pagedResults ) { 869 if ( ctrl_add() ) { 870 return EXIT_FAILURE; 871 } 872 873 if ( ldap_create_page_control_value( ld, 874 pageSize, &pr_cookie, &c[i].ldctl_value ) ) 875 { 876 return EXIT_FAILURE; 877 } 878 879 if ( pr_cookie.bv_val != NULL ) { 880 ber_memfree( pr_cookie.bv_val ); 881 pr_cookie.bv_val = NULL; 882 pr_cookie.bv_len = 0; 883 } 884 885 c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; 886 c[i].ldctl_iscritical = pagedResults > 1; 887 i++; 888 } 889 } 890 891 tool_server_controls( ld, c, i ); 892 893 ber_free( seber, 1 ); 894 ber_free( vrber, 1 ); 895 896 /* step back to the original number of controls, so that 897 * those set while parsing args are preserved */ 898 nctrls = save_nctrls; 899 900 if ( verbose ) { 901 fprintf( stderr, _("filter%s: %s\nrequesting: "), 902 infile != NULL ? _(" pattern") : "", 903 filtpattern ); 904 905 if ( attrs == NULL ) { 906 fprintf( stderr, _("All userApplication attributes") ); 907 } else { 908 for ( i = 0; attrs[ i ] != NULL; ++i ) { 909 fprintf( stderr, "%s ", attrs[ i ] ); 910 } 911 } 912 fprintf( stderr, "\n" ); 913 } 914 915 if ( ldif == 0 ) { 916 printf( _("# extended LDIF\n") ); 917 } else if ( ldif < 3 ) { 918 printf( _("version: %d\n\n"), 1 ); 919 } 920 921 if (ldif < 2 ) { 922 char *realbase = base; 923 924 if ( realbase == NULL ) { 925 ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase ); 926 } 927 928 printf( "#\n" ); 929 printf(_("# LDAPv%d\n"), protocol); 930 printf(_("# base <%s>%s with scope %s\n"), 931 realbase ? realbase : "", 932 ( realbase == NULL || realbase != base ) ? " (default)" : "", 933 ((scope == LDAP_SCOPE_BASE) ? "baseObject" 934 : ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel" 935 : ((scope == LDAP_SCOPE_SUBORDINATE) ? "children" 936 : "subtree" )))); 937 printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "", 938 filtpattern); 939 printf(_("# requesting: ")); 940 941 if ( attrs == NULL ) { 942 printf( _("ALL") ); 943 } else { 944 for ( i = 0; attrs[ i ] != NULL; ++i ) { 945 printf( "%s ", attrs[ i ] ); 946 } 947 } 948 949 if ( manageDSAit ) { 950 printf(_("\n# with manageDSAit %scontrol"), 951 manageDSAit > 1 ? _("critical ") : "" ); 952 } 953 if ( noop ) { 954 printf(_("\n# with noop %scontrol"), 955 noop > 1 ? _("critical ") : "" ); 956 } 957 if ( subentries ) { 958 printf(_("\n# with subentries %scontrol: %s"), 959 subentries < 0 ? _("critical ") : "", 960 abs(subentries) == 1 ? "false" : "true" ); 961 } 962 if ( valuesReturnFilter ) { 963 printf(_("\n# with valuesReturnFilter %scontrol: %s"), 964 valuesReturnFilter > 1 ? _("critical ") : "", vrFilter ); 965 } 966 if ( pagedResults ) { 967 printf(_("\n# with pagedResults %scontrol: size=%d"), 968 (pagedResults > 1) ? _("critical ") : "", 969 pageSize ); 970 } 971 972 printf( _("\n#\n\n") ); 973 974 if ( realbase && realbase != base ) { 975 ldap_memfree( realbase ); 976 } 977 } 978 979 if ( infile == NULL ) { 980 rc = dosearch( ld, base, scope, NULL, filtpattern, 981 attrs, attrsonly, NULL, NULL, NULL, -1 ); 982 983 } else { 984 rc = 0; 985 first = 1; 986 while ( fgets( line, sizeof( line ), fp ) != NULL ) { 987 line[ strlen( line ) - 1 ] = '\0'; 988 if ( !first ) { 989 putchar( '\n' ); 990 } else { 991 first = 0; 992 } 993 rc1 = dosearch( ld, base, scope, filtpattern, line, 994 attrs, attrsonly, NULL, NULL, NULL, -1 ); 995 996 if ( rc1 != 0 ) { 997 rc = rc1; 998 if ( !contoper ) 999 break; 1000 } 1001 } 1002 if ( fp != stdin ) { 1003 fclose( fp ); 1004 } 1005 } 1006 1007 if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) { 1008 char buf[6]; 1009 int i, moreEntries, tmpSize; 1010 1011 /* Loop to get the next pages when 1012 * enter is pressed on the terminal. 1013 */ 1014 if ( pagePrompt != 0 ) { 1015 if ( entriesLeft > 0 ) { 1016 printf( _("Estimate entries: %d\n"), entriesLeft ); 1017 } 1018 printf( _("Press [size] Enter for the next {%d|size} entries.\n"), 1019 (int)pageSize ); 1020 i = 0; 1021 moreEntries = getchar(); 1022 while ( moreEntries != EOF && moreEntries != '\n' ) { 1023 if ( i < (int)sizeof(buf) - 1 ) { 1024 buf[i] = moreEntries; 1025 i++; 1026 } 1027 moreEntries = getchar(); 1028 } 1029 buf[i] = '\0'; 1030 1031 if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) { 1032 int num = sscanf( buf, "%d", &tmpSize ); 1033 if ( num != 1 ) { 1034 fprintf( stderr, 1035 _("Invalid value for PagedResultsControl, %s.\n"), buf); 1036 return EXIT_FAILURE; 1037 1038 } 1039 pageSize = (ber_int_t)tmpSize; 1040 } 1041 } 1042 1043 goto getNextPage; 1044 } 1045 1046 tool_unbind( ld ); 1047 tool_destroy(); 1048 if ( base != NULL ) { 1049 ber_memfree( base ); 1050 } 1051 if ( control != NULL ) { 1052 ber_memfree( control ); 1053 } 1054 1055 if ( c ) { 1056 for ( ; save_nctrls-- > 0; ) { 1057 ber_memfree( c[ save_nctrls ].ldctl_value.bv_val ); 1058 } 1059 free( c ); 1060 c = NULL; 1061 } 1062 1063 return( rc ); 1064 } 1065 1066 1067 static int dosearch( 1068 LDAP *ld, 1069 char *base, 1070 int scope, 1071 char *filtpatt, 1072 char *value, 1073 char **attrs, 1074 int attrsonly, 1075 LDAPControl **sctrls, 1076 LDAPControl **cctrls, 1077 struct timeval *timeout, 1078 int sizelimit ) 1079 { 1080 char *filter; 1081 int rc; 1082 int nresponses; 1083 int nentries; 1084 int nreferences; 1085 int nextended; 1086 int npartial; 1087 LDAPMessage *res, *msg; 1088 ber_int_t msgid; 1089 char *retoid = NULL; 1090 struct berval *retdata = NULL; 1091 int nresponses_psearch = -1; 1092 int cancel_msgid = -1; 1093 1094 if( filtpatt != NULL ) { 1095 size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1; 1096 filter = malloc( max_fsize ); 1097 if( filter == NULL ) { 1098 perror( "malloc" ); 1099 return EXIT_FAILURE; 1100 } 1101 1102 if( snprintf( filter, max_fsize, filtpatt, value ) >= max_fsize ) { 1103 fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt ); 1104 free( filter ); 1105 return EXIT_FAILURE; 1106 } 1107 1108 if ( verbose ) { 1109 fprintf( stderr, _("filter: %s\n"), filter ); 1110 } 1111 1112 if( ldif < 2 ) { 1113 printf( _("#\n# filter: %s\n#\n"), filter ); 1114 } 1115 1116 } else { 1117 filter = value; 1118 } 1119 1120 if ( dont ) { 1121 if ( filtpatt != NULL ) { 1122 free( filter ); 1123 } 1124 return LDAP_SUCCESS; 1125 } 1126 1127 rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, 1128 sctrls, cctrls, timeout, sizelimit, &msgid ); 1129 1130 if ( filtpatt != NULL ) { 1131 free( filter ); 1132 } 1133 1134 if( rc != LDAP_SUCCESS ) { 1135 fprintf( stderr, _("%s: ldap_search_ext: %s (%d)\n"), 1136 prog, ldap_err2string( rc ), rc ); 1137 return( rc ); 1138 } 1139 1140 nresponses = nentries = nreferences = nextended = npartial = 0; 1141 1142 res = NULL; 1143 1144 while ((rc = ldap_result( ld, LDAP_RES_ANY, 1145 sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE, 1146 NULL, &res )) > 0 ) 1147 { 1148 rc = tool_check_abandon( ld, msgid ); 1149 if ( rc ) { 1150 return rc; 1151 } 1152 1153 if( sortattr ) { 1154 (void) ldap_sort_entries( ld, &res, 1155 ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp ); 1156 } 1157 1158 for ( msg = ldap_first_message( ld, res ); 1159 msg != NULL; 1160 msg = ldap_next_message( ld, msg ) ) 1161 { 1162 if ( nresponses++ ) putchar('\n'); 1163 if ( nresponses_psearch >= 0 ) 1164 nresponses_psearch++; 1165 1166 switch( ldap_msgtype( msg ) ) { 1167 case LDAP_RES_SEARCH_ENTRY: 1168 nentries++; 1169 print_entry( ld, msg, attrsonly ); 1170 break; 1171 1172 case LDAP_RES_SEARCH_REFERENCE: 1173 nreferences++; 1174 print_reference( ld, msg ); 1175 break; 1176 1177 case LDAP_RES_EXTENDED: 1178 nextended++; 1179 print_extended( ld, msg ); 1180 1181 if ( ldap_msgid( msg ) == 0 ) { 1182 /* unsolicited extended operation */ 1183 goto done; 1184 } 1185 1186 if ( cancel_msgid != -1 && 1187 cancel_msgid == ldap_msgid( msg ) ) { 1188 printf(_("Cancelled \n")); 1189 printf(_("cancel_msgid = %d\n"), cancel_msgid); 1190 goto done; 1191 } 1192 break; 1193 1194 case LDAP_RES_SEARCH_RESULT: 1195 /* pagedResults stuff is dealt with 1196 * in tool_print_ctrls(), called by 1197 * print_results(). */ 1198 rc = print_result( ld, msg, 1 ); 1199 if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) { 1200 break; 1201 } 1202 1203 goto done; 1204 1205 case LDAP_RES_INTERMEDIATE: 1206 npartial++; 1207 ldap_parse_intermediate( ld, msg, 1208 &retoid, &retdata, NULL, 0 ); 1209 1210 nresponses_psearch = 0; 1211 1212 if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) { 1213 printf(_("SyncInfo Received\n")); 1214 ldap_memfree( retoid ); 1215 ber_bvfree( retdata ); 1216 break; 1217 } 1218 1219 print_partial( ld, msg ); 1220 ldap_memfree( retoid ); 1221 ber_bvfree( retdata ); 1222 goto done; 1223 } 1224 1225 if ( ldapsync && sync_slimit != -1 && 1226 nresponses_psearch >= sync_slimit ) { 1227 BerElement *msgidber = NULL; 1228 struct berval *msgidvalp = NULL; 1229 msgidber = ber_alloc_t(LBER_USE_DER); 1230 ber_printf(msgidber, "{i}", msgid); 1231 ber_flatten(msgidber, &msgidvalp); 1232 ldap_extended_operation(ld, LDAP_EXOP_CANCEL, 1233 msgidvalp, NULL, NULL, &cancel_msgid); 1234 nresponses_psearch = -1; 1235 } 1236 } 1237 1238 ldap_msgfree( res ); 1239 } 1240 1241 done: 1242 if ( rc == -1 ) { 1243 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 1244 return( rc ); 1245 } 1246 1247 ldap_msgfree( res ); 1248 1249 if ( pagedResults ) { 1250 npagedresponses += nresponses; 1251 npagedentries += nentries; 1252 npagedextended += nextended; 1253 npagedpartial += npartial; 1254 npagedreferences += nreferences; 1255 if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) { 1256 printf( _("\n# numResponses: %d\n"), npagedresponses ); 1257 if( npagedentries ) { 1258 printf( _("# numEntries: %d\n"), npagedentries ); 1259 } 1260 if( npagedextended ) { 1261 printf( _("# numExtended: %d\n"), npagedextended ); 1262 } 1263 if( npagedpartial ) { 1264 printf( _("# numPartial: %d\n"), npagedpartial ); 1265 } 1266 if( npagedreferences ) { 1267 printf( _("# numReferences: %d\n"), npagedreferences ); 1268 } 1269 } 1270 } else if ( ldif < 2 ) { 1271 printf( _("\n# numResponses: %d\n"), nresponses ); 1272 if( nentries ) printf( _("# numEntries: %d\n"), nentries ); 1273 if( nextended ) printf( _("# numExtended: %d\n"), nextended ); 1274 if( npartial ) printf( _("# numPartial: %d\n"), npartial ); 1275 if( nreferences ) printf( _("# numReferences: %d\n"), nreferences ); 1276 } 1277 1278 return( rc ); 1279 } 1280 1281 /* This is the proposed new way of doing things. 1282 * It is more efficient, but the API is non-standard. 1283 */ 1284 static void 1285 print_entry( 1286 LDAP *ld, 1287 LDAPMessage *entry, 1288 int attrsonly) 1289 { 1290 char *ufn = NULL; 1291 char tmpfname[ 256 ]; 1292 char url[ 256 ]; 1293 int i, rc; 1294 BerElement *ber = NULL; 1295 struct berval bv, *bvals, **bvp = &bvals; 1296 LDAPControl **ctrls = NULL; 1297 FILE *tmpfp; 1298 1299 rc = ldap_get_dn_ber( ld, entry, &ber, &bv ); 1300 1301 if ( ldif < 2 ) { 1302 ufn = ldap_dn2ufn( bv.bv_val ); 1303 tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 ); 1304 } 1305 tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len ); 1306 1307 rc = ldap_get_entry_controls( ld, entry, &ctrls ); 1308 if( rc != LDAP_SUCCESS ) { 1309 fprintf(stderr, _("print_entry: %d\n"), rc ); 1310 tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL ); 1311 exit( EXIT_FAILURE ); 1312 } 1313 1314 if( ctrls ) { 1315 tool_print_ctrls( ld, ctrls ); 1316 ldap_controls_free( ctrls ); 1317 } 1318 1319 if ( includeufn ) { 1320 if( ufn == NULL ) { 1321 ufn = ldap_dn2ufn( bv.bv_val ); 1322 } 1323 tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 ); 1324 } 1325 1326 if( ufn != NULL ) ldap_memfree( ufn ); 1327 1328 if ( attrsonly ) bvp = NULL; 1329 1330 for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ); 1331 rc == LDAP_SUCCESS; 1332 rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) ) 1333 { 1334 if (bv.bv_val == NULL) break; 1335 1336 if ( attrsonly ) { 1337 tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 ); 1338 1339 } else if ( bvals ) { 1340 for ( i = 0; bvals[i].bv_val != NULL; i++ ) { 1341 if ( vals2tmp > 1 || ( vals2tmp && 1342 ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len ))) 1343 { 1344 int tmpfd; 1345 /* write value to file */ 1346 snprintf( tmpfname, sizeof tmpfname, 1347 "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX", 1348 tmpdir, bv.bv_val ); 1349 tmpfp = NULL; 1350 1351 tmpfd = mkstemp( tmpfname ); 1352 1353 if ( tmpfd < 0 ) { 1354 perror( tmpfname ); 1355 continue; 1356 } 1357 1358 if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) { 1359 perror( tmpfname ); 1360 continue; 1361 } 1362 1363 if ( fwrite( bvals[ i ].bv_val, 1364 bvals[ i ].bv_len, 1, tmpfp ) == 0 ) 1365 { 1366 perror( tmpfname ); 1367 fclose( tmpfp ); 1368 continue; 1369 } 1370 1371 fclose( tmpfp ); 1372 1373 snprintf( url, sizeof url, "%s%s", urlpre, 1374 &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] ); 1375 1376 urlize( url ); 1377 tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url )); 1378 1379 } else { 1380 tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val, 1381 bvals[ i ].bv_val, bvals[ i ].bv_len ); 1382 } 1383 } 1384 ber_memfree( bvals ); 1385 } 1386 } 1387 1388 if( ber != NULL ) { 1389 ber_free( ber, 0 ); 1390 } 1391 } 1392 1393 static void print_reference( 1394 LDAP *ld, 1395 LDAPMessage *reference ) 1396 { 1397 int rc; 1398 char **refs = NULL; 1399 LDAPControl **ctrls; 1400 1401 if( ldif < 2 ) { 1402 printf(_("# search reference\n")); 1403 } 1404 1405 rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 ); 1406 1407 if( rc != LDAP_SUCCESS ) { 1408 tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL ); 1409 exit( EXIT_FAILURE ); 1410 } 1411 1412 if( refs ) { 1413 int i; 1414 for( i=0; refs[i] != NULL; i++ ) { 1415 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1416 "ref", refs[i], strlen(refs[i]) ); 1417 } 1418 ber_memvfree( (void **) refs ); 1419 } 1420 1421 if( ctrls ) { 1422 tool_print_ctrls( ld, ctrls ); 1423 ldap_controls_free( ctrls ); 1424 } 1425 } 1426 1427 static void print_extended( 1428 LDAP *ld, 1429 LDAPMessage *extended ) 1430 { 1431 int rc; 1432 char *retoid = NULL; 1433 struct berval *retdata = NULL; 1434 1435 if( ldif < 2 ) { 1436 printf(_("# extended result response\n")); 1437 } 1438 1439 rc = ldap_parse_extended_result( ld, extended, 1440 &retoid, &retdata, 0 ); 1441 1442 if( rc != LDAP_SUCCESS ) { 1443 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); 1444 exit( EXIT_FAILURE ); 1445 } 1446 1447 if ( ldif < 2 ) { 1448 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1449 "extended", retoid, retoid ? strlen(retoid) : 0 ); 1450 } 1451 ber_memfree( retoid ); 1452 1453 if(retdata) { 1454 if ( ldif < 2 ) { 1455 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, 1456 "data", retdata->bv_val, retdata->bv_len ); 1457 } 1458 ber_bvfree( retdata ); 1459 } 1460 1461 print_result( ld, extended, 0 ); 1462 } 1463 1464 static void print_partial( 1465 LDAP *ld, 1466 LDAPMessage *partial ) 1467 { 1468 int rc; 1469 char *retoid = NULL; 1470 struct berval *retdata = NULL; 1471 LDAPControl **ctrls = NULL; 1472 1473 if( ldif < 2 ) { 1474 printf(_("# extended partial response\n")); 1475 } 1476 1477 rc = ldap_parse_intermediate( ld, partial, 1478 &retoid, &retdata, &ctrls, 0 ); 1479 1480 if( rc != LDAP_SUCCESS ) { 1481 tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL ); 1482 exit( EXIT_FAILURE ); 1483 } 1484 1485 if ( ldif < 2 ) { 1486 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 1487 "partial", retoid, retoid ? strlen(retoid) : 0 ); 1488 } 1489 1490 ber_memfree( retoid ); 1491 1492 if( retdata ) { 1493 if ( ldif < 2 ) { 1494 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, 1495 "data", retdata->bv_val, retdata->bv_len ); 1496 } 1497 1498 ber_bvfree( retdata ); 1499 } 1500 1501 if( ctrls ) { 1502 tool_print_ctrls( ld, ctrls ); 1503 ldap_controls_free( ctrls ); 1504 } 1505 } 1506 1507 static int print_result( 1508 LDAP *ld, 1509 LDAPMessage *result, int search ) 1510 { 1511 int rc; 1512 int err; 1513 char *matcheddn = NULL; 1514 char *text = NULL; 1515 char **refs = NULL; 1516 LDAPControl **ctrls = NULL; 1517 1518 if( search ) { 1519 if ( ldif < 2 ) { 1520 printf(_("# search result\n")); 1521 } 1522 if ( ldif < 1 ) { 1523 printf("%s: %d\n", _("search"), ldap_msgid(result) ); 1524 } 1525 } 1526 1527 rc = ldap_parse_result( ld, result, 1528 &err, &matcheddn, &text, &refs, &ctrls, 0 ); 1529 1530 if( rc != LDAP_SUCCESS ) { 1531 tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL ); 1532 exit( EXIT_FAILURE ); 1533 } 1534 1535 1536 if( !ldif ) { 1537 printf( _("result: %d %s\n"), err, ldap_err2string(err) ); 1538 1539 } else if ( err != LDAP_SUCCESS ) { 1540 fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err ); 1541 } 1542 1543 if( matcheddn ) { 1544 if( *matcheddn ) { 1545 if( !ldif ) { 1546 tool_write_ldif( LDIF_PUT_VALUE, 1547 "matchedDN", matcheddn, strlen(matcheddn) ); 1548 } else { 1549 fprintf( stderr, _("Matched DN: %s\n"), matcheddn ); 1550 } 1551 } 1552 1553 ber_memfree( matcheddn ); 1554 } 1555 1556 if( text ) { 1557 if( *text ) { 1558 if( !ldif ) { 1559 if ( err == LDAP_PARTIAL_RESULTS ) { 1560 char *line; 1561 1562 for ( line = text; line != NULL; ) { 1563 char *next = strchr( line, '\n' ); 1564 1565 tool_write_ldif( LDIF_PUT_TEXT, 1566 "text", line, 1567 next ? next - line : strlen( line ) ); 1568 1569 line = next ? next + 1 : NULL; 1570 } 1571 1572 } else { 1573 tool_write_ldif( LDIF_PUT_TEXT, "text", 1574 text, strlen(text) ); 1575 } 1576 } else { 1577 fprintf( stderr, _("Additional information: %s\n"), text ); 1578 } 1579 } 1580 1581 ber_memfree( text ); 1582 } 1583 1584 if( refs ) { 1585 int i; 1586 for( i=0; refs[i] != NULL; i++ ) { 1587 if( !ldif ) { 1588 tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) ); 1589 } else { 1590 fprintf( stderr, _("Referral: %s\n"), refs[i] ); 1591 } 1592 } 1593 1594 ber_memvfree( (void **) refs ); 1595 } 1596 1597 pr_morePagedResults = 0; 1598 1599 if( ctrls ) { 1600 tool_print_ctrls( ld, ctrls ); 1601 ldap_controls_free( ctrls ); 1602 } 1603 1604 return err; 1605 } 1606 1607