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