1/* $NetBSD$ */ 2 3/* OpenLDAP: pkg/ldap/tests/progs/slapd-tester.c,v 1.46.2.10 2010/04/13 20:23:59 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2010 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17/* ACKNOWLEDGEMENTS: 18 * This work was initially developed by Kurt Spanier for inclusion 19 * in OpenLDAP Software. 20 */ 21 22#include "portable.h" 23 24#include <stdio.h> 25 26#include "ac/stdlib.h" 27 28#include "ac/ctype.h" 29#include "ac/dirent.h" 30#include "ac/param.h" 31#include "ac/socket.h" 32#include "ac/string.h" 33#include "ac/unistd.h" 34#include "ac/wait.h" 35 36 37#include "ldap_defaults.h" 38#include "lutil.h" 39 40#include "ldap.h" 41#include "ldap_pvt.h" 42#include "lber_pvt.h" 43#include "slapd-common.h" 44 45#define SEARCHCMD "slapd-search" 46#define READCMD "slapd-read" 47#define ADDCMD "slapd-addel" 48#define MODRDNCMD "slapd-modrdn" 49#define MODIFYCMD "slapd-modify" 50#define BINDCMD "slapd-bind" 51#define MAXARGS 100 52#define MAXREQS 5000 53#define LOOPS 100 54#define OUTERLOOPS "1" 55#define RETRIES "0" 56 57#define TSEARCHFILE "do_search.0" 58#define TREADFILE "do_read.0" 59#define TADDFILE "do_add." 60#define TMODRDNFILE "do_modrdn.0" 61#define TMODIFYFILE "do_modify.0" 62#define TBINDFILE "do_bind.0" 63 64static char *get_file_name( char *dirname, char *filename ); 65static int get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] ); 66static int get_read_entries( char *filename, char *entries[], char *filters[] ); 67static void fork_child( char *prog, char **args ); 68static void wait4kids( int nkidval ); 69 70static int maxkids = 20; 71static int nkids; 72 73#ifdef HAVE_WINSOCK 74static HANDLE *children; 75static char argbuf[BUFSIZ]; 76#define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\"")) 77#else 78#define ArgDup(x) strdup(x) 79#endif 80 81static void 82usage( char *name, char opt ) 83{ 84 if ( opt ) { 85 fprintf( stderr, "%s: unable to handle option \'%c\'\n\n", 86 name, opt ); 87 } 88 89 fprintf( stderr, 90 "usage: %s " 91 "-H <uri> | ([-h <host>] -p <port>) " 92 "-D <manager> " 93 "-w <passwd> " 94 "-d <datadir> " 95 "[-i <ignore>] " 96 "[-j <maxchild>] " 97 "[-l {<loops>|<type>=<loops>[,...]}] " 98 "[-L <outerloops>] " 99 "-P <progdir> " 100 "[-r <maxretries>] " 101 "[-t <delay>] " 102 "[-C] " 103 "[-F] " 104 "[-I] " 105 "[-N]\n", 106 name ); 107 exit( EXIT_FAILURE ); 108} 109 110int 111main( int argc, char **argv ) 112{ 113 int i, j; 114 char *uri = NULL; 115 char *host = "localhost"; 116 char *port = NULL; 117 char *manager = NULL; 118 char *passwd = NULL; 119 char *dirname = NULL; 120 char *progdir = NULL; 121 int loops = LOOPS; 122 char *outerloops = OUTERLOOPS; 123 char *retries = RETRIES; 124 char *delay = "0"; 125 DIR *datadir; 126 struct dirent *file; 127 int friendly = 0; 128 int chaserefs = 0; 129 int noattrs = 0; 130 int nobind = 0; 131 int noinit = 1; 132 char *ignore = NULL; 133 /* search */ 134 char *sfile = NULL; 135 char *sreqs[MAXREQS]; 136 char *sattrs[MAXREQS]; 137 char *sbase[MAXREQS]; 138 LDAPURLDesc *slud[MAXREQS]; 139 int snum = 0; 140 char *sargs[MAXARGS]; 141 int sanum; 142 int sextra_args = 0; 143 char scmd[MAXPATHLEN]; 144 /* static so that its address can be used in initializer below. */ 145 static char sloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 146 /* read */ 147 char *rfile = NULL; 148 char *rreqs[MAXREQS]; 149 int rnum = 0; 150 char *rargs[MAXARGS]; 151 char *rflts[MAXREQS]; 152 int ranum; 153 int rextra_args = 0; 154 char rcmd[MAXPATHLEN]; 155 static char rloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 156 /* addel */ 157 char *afiles[MAXREQS]; 158 int anum = 0; 159 char *aargs[MAXARGS]; 160 int aanum; 161 char acmd[MAXPATHLEN]; 162 static char aloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 163 /* modrdn */ 164 char *nfile = NULL; 165 char *nreqs[MAXREQS]; 166 int nnum = 0; 167 char *nargs[MAXARGS]; 168 int nanum; 169 char ncmd[MAXPATHLEN]; 170 static char nloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 171 /* modify */ 172 char *mfile = NULL; 173 char *mreqs[MAXREQS]; 174 char *mdn[MAXREQS]; 175 int mnum = 0; 176 char *margs[MAXARGS]; 177 int manum; 178 char mcmd[MAXPATHLEN]; 179 static char mloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 180 /* bind */ 181 char *bfile = NULL; 182 char *breqs[MAXREQS]; 183 char *bcreds[MAXREQS]; 184 char *battrs[MAXREQS]; 185 int bnum = 0; 186 char *bargs[MAXARGS]; 187 int banum; 188 char bcmd[MAXPATHLEN]; 189 static char bloops[LDAP_PVT_INTTYPE_CHARS(unsigned long)]; 190 char **bargs_extra = NULL; 191 192 char *friendlyOpt = NULL; 193 int pw_ask = 0; 194 char *pw_file = NULL; 195 196 /* extra action to do after bind... */ 197 typedef struct extra_t { 198 char *action; 199 struct extra_t *next; 200 } extra_t; 201 202 extra_t *extra = NULL; 203 int nextra = 0; 204 205 tester_init( "slapd-tester", TESTER_TESTER ); 206 207 sloops[0] = '\0'; 208 rloops[0] = '\0'; 209 aloops[0] = '\0'; 210 nloops[0] = '\0'; 211 mloops[0] = '\0'; 212 bloops[0] = '\0'; 213 214 while ( ( i = getopt( argc, argv, "AB:CD:d:FH:h:Ii:j:L:l:NP:p:r:t:Ww:y:" ) ) != EOF ) 215 { 216 switch ( i ) { 217 case 'A': 218 noattrs++; 219 break; 220 221 case 'B': { 222 char **p, 223 **b = ldap_str2charray( optarg, "," ); 224 extra_t **epp; 225 226 for ( epp = &extra; *epp; epp = &(*epp)->next ) 227 ; 228 229 for ( p = b; p[0]; p++ ) { 230 *epp = calloc( 1, sizeof( extra_t ) ); 231 (*epp)->action = p[0]; 232 epp = &(*epp)->next; 233 nextra++; 234 } 235 236 ldap_memfree( b ); 237 } break; 238 239 case 'C': 240 chaserefs++; 241 break; 242 243 case 'D': /* slapd manager */ 244 manager = ArgDup( optarg ); 245 break; 246 247 case 'd': /* data directory */ 248 dirname = strdup( optarg ); 249 break; 250 251 case 'F': 252 friendly++; 253 break; 254 255 case 'H': /* slapd uri */ 256 uri = strdup( optarg ); 257 break; 258 259 case 'h': /* slapd host */ 260 host = strdup( optarg ); 261 break; 262 263 case 'I': 264 noinit = 0; 265 break; 266 267 case 'i': 268 ignore = optarg; 269 break; 270 271 case 'j': /* the number of parallel clients */ 272 if ( lutil_atoi( &maxkids, optarg ) != 0 ) { 273 usage( argv[0], 'j' ); 274 } 275 break; 276 277 case 'l': /* the number of loops per client */ 278 if ( !isdigit( (unsigned char) optarg[0] ) ) { 279 char **p, 280 **l = ldap_str2charray( optarg, "," ); 281 282 for ( p = l; p[0]; p++) { 283 struct { 284 struct berval type; 285 char *buf; 286 } types[] = { 287 { BER_BVC( "add=" ), aloops }, 288 { BER_BVC( "bind=" ), bloops }, 289 { BER_BVC( "modify=" ), mloops }, 290 { BER_BVC( "modrdn=" ), nloops }, 291 { BER_BVC( "read=" ), rloops }, 292 { BER_BVC( "search=" ), sloops }, 293 { BER_BVNULL, NULL } 294 }; 295 int c, n; 296 297 for ( c = 0; types[c].type.bv_val; c++ ) { 298 if ( strncasecmp( p[0], types[c].type.bv_val, types[c].type.bv_len ) == 0 ) { 299 break; 300 } 301 } 302 303 if ( types[c].type.bv_val == NULL ) { 304 usage( argv[0], 'l' ); 305 } 306 307 if ( lutil_atoi( &n, &p[0][types[c].type.bv_len] ) != 0 ) { 308 usage( argv[0], 'l' ); 309 } 310 311 snprintf( types[c].buf, sizeof( aloops ), "%d", n ); 312 } 313 314 ldap_charray_free( l ); 315 316 } else if ( lutil_atoi( &loops, optarg ) != 0 ) { 317 usage( argv[0], 'l' ); 318 } 319 break; 320 321 case 'L': /* the number of outerloops per client */ 322 outerloops = strdup( optarg ); 323 break; 324 325 case 'N': 326 nobind++; 327 break; 328 329 case 'P': /* prog directory */ 330 progdir = strdup( optarg ); 331 break; 332 333 case 'p': /* the servers port number */ 334 port = strdup( optarg ); 335 break; 336 337 case 'r': /* the number of retries in case of error */ 338 retries = strdup( optarg ); 339 break; 340 341 case 't': /* the delay in seconds between each retry */ 342 delay = strdup( optarg ); 343 break; 344 345 case 'w': /* the managers passwd */ 346 passwd = ArgDup( optarg ); 347 memset( optarg, '*', strlen( optarg ) ); 348 break; 349 350 case 'W': 351 pw_ask++; 352 break; 353 354 case 'y': 355 pw_file = optarg; 356 break; 357 358 default: 359 usage( argv[0], '\0' ); 360 break; 361 } 362 } 363 364 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) || 365 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL )) 366 { 367 usage( argv[0], '\0' ); 368 } 369 370#ifdef HAVE_WINSOCK 371 children = malloc( maxkids * sizeof(HANDLE) ); 372#endif 373 /* get the file list */ 374 if ( ( datadir = opendir( dirname )) == NULL ) { 375 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n", 376 argv[0], dirname ); 377 exit( EXIT_FAILURE ); 378 } 379 380 /* look for search, read, modrdn, and add/delete files */ 381 for ( file = readdir( datadir ); file; file = readdir( datadir )) { 382 383 if ( !strcasecmp( file->d_name, TSEARCHFILE )) { 384 sfile = get_file_name( dirname, file->d_name ); 385 continue; 386 } else if ( !strcasecmp( file->d_name, TREADFILE )) { 387 rfile = get_file_name( dirname, file->d_name ); 388 continue; 389 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) { 390 nfile = get_file_name( dirname, file->d_name ); 391 continue; 392 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) { 393 mfile = get_file_name( dirname, file->d_name ); 394 continue; 395 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE )) 396 && ( anum < MAXREQS )) { 397 afiles[anum++] = get_file_name( dirname, file->d_name ); 398 continue; 399 } else if ( !strcasecmp( file->d_name, TBINDFILE )) { 400 bfile = get_file_name( dirname, file->d_name ); 401 continue; 402 } 403 } 404 405 closedir( datadir ); 406 407 if ( pw_ask ) { 408 passwd = getpassphrase( _("Enter LDAP Password: ") ); 409 410 } else if ( pw_file ) { 411 struct berval pw; 412 413 if ( lutil_get_filed_password( pw_file, &pw ) ) { 414 exit( EXIT_FAILURE ); 415 } 416 417 passwd = pw.bv_val; 418 } 419 420 if ( !sfile && !rfile && !nfile && !mfile && !bfile && !anum ) { 421 fprintf( stderr, "no data files found.\n" ); 422 exit( EXIT_FAILURE ); 423 } 424 425 /* look for search requests */ 426 if ( sfile ) { 427 snum = get_search_filters( sfile, sreqs, sattrs, sbase, slud ); 428 if ( snum < 0 ) { 429 fprintf( stderr, 430 "unable to parse file \"%s\" line %d\n", 431 sfile, -2*(snum + 1)); 432 exit( EXIT_FAILURE ); 433 } 434 } 435 436 /* look for read requests */ 437 if ( rfile ) { 438 rnum = get_read_entries( rfile, rreqs, rflts ); 439 if ( rnum < 0 ) { 440 fprintf( stderr, 441 "unable to parse file \"%s\" line %d\n", 442 rfile, -2*(rnum + 1) ); 443 exit( EXIT_FAILURE ); 444 } 445 } 446 447 /* look for modrdn requests */ 448 if ( nfile ) { 449 nnum = get_read_entries( nfile, nreqs, NULL ); 450 if ( nnum < 0 ) { 451 fprintf( stderr, 452 "unable to parse file \"%s\" line %d\n", 453 nfile, -2*(nnum + 1) ); 454 exit( EXIT_FAILURE ); 455 } 456 } 457 458 /* look for modify requests */ 459 if ( mfile ) { 460 mnum = get_search_filters( mfile, mreqs, NULL, mdn, NULL ); 461 if ( mnum < 0 ) { 462 fprintf( stderr, 463 "unable to parse file \"%s\" line %d\n", 464 mfile, -2*(mnum + 1) ); 465 exit( EXIT_FAILURE ); 466 } 467 } 468 469 /* look for bind requests */ 470 if ( bfile ) { 471 bnum = get_search_filters( bfile, bcreds, battrs, breqs, NULL ); 472 if ( bnum < 0 ) { 473 fprintf( stderr, 474 "unable to parse file \"%s\" line %d\n", 475 bfile, -2*(bnum + 1) ); 476 exit( EXIT_FAILURE ); 477 } 478 } 479 480 /* setup friendly option */ 481 482 switch ( friendly ) { 483 case 0: 484 break; 485 486 case 1: 487 friendlyOpt = "-F"; 488 break; 489 490 default: 491 /* NOTE: right now we don't need it more than twice */ 492 case 2: 493 friendlyOpt = "-FF"; 494 break; 495 } 496 497 if ( sloops[0] == '\0' ) snprintf( sloops, sizeof( sloops ), "%d", 10 * loops ); 498 if ( rloops[0] == '\0' ) snprintf( rloops, sizeof( rloops ), "%d", 20 * loops ); 499 if ( aloops[0] == '\0' ) snprintf( aloops, sizeof( aloops ), "%d", loops ); 500 if ( nloops[0] == '\0' ) snprintf( nloops, sizeof( nloops ), "%d", loops ); 501 if ( mloops[0] == '\0' ) snprintf( mloops, sizeof( mloops ), "%d", loops ); 502 if ( bloops[0] == '\0' ) snprintf( bloops, sizeof( bloops ), "%d", 20 * loops ); 503 504 /* 505 * generate the search clients 506 */ 507 508 sanum = 0; 509 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD, 510 progdir ); 511 sargs[sanum++] = scmd; 512 if ( uri ) { 513 sargs[sanum++] = "-H"; 514 sargs[sanum++] = uri; 515 } else { 516 sargs[sanum++] = "-h"; 517 sargs[sanum++] = host; 518 sargs[sanum++] = "-p"; 519 sargs[sanum++] = port; 520 } 521 sargs[sanum++] = "-D"; 522 sargs[sanum++] = manager; 523 sargs[sanum++] = "-w"; 524 sargs[sanum++] = passwd; 525 sargs[sanum++] = "-l"; 526 sargs[sanum++] = sloops; 527 sargs[sanum++] = "-L"; 528 sargs[sanum++] = outerloops; 529 sargs[sanum++] = "-r"; 530 sargs[sanum++] = retries; 531 sargs[sanum++] = "-t"; 532 sargs[sanum++] = delay; 533 if ( friendly ) { 534 sargs[sanum++] = friendlyOpt; 535 } 536 if ( chaserefs ) { 537 sargs[sanum++] = "-C"; 538 } 539 if ( noattrs ) { 540 sargs[sanum++] = "-A"; 541 } 542 if ( nobind ) { 543 sargs[sanum++] = "-N"; 544 } 545 if ( ignore ) { 546 sargs[sanum++] = "-i"; 547 sargs[sanum++] = ignore; 548 } 549 sargs[sanum++] = "-b"; 550 sargs[sanum++] = NULL; /* will hold the search base */ 551 sargs[sanum++] = "-s"; 552 sargs[sanum++] = NULL; /* will hold the search scope */ 553 sargs[sanum++] = "-f"; 554 sargs[sanum++] = NULL; /* will hold the search request */ 555 556 sargs[sanum++] = NULL; 557 sargs[sanum++] = NULL; /* might hold the "attr" request */ 558 sextra_args += 2; 559 560 sargs[sanum] = NULL; 561 562 /* 563 * generate the read clients 564 */ 565 566 ranum = 0; 567 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD, 568 progdir ); 569 rargs[ranum++] = rcmd; 570 if ( uri ) { 571 rargs[ranum++] = "-H"; 572 rargs[ranum++] = uri; 573 } else { 574 rargs[ranum++] = "-h"; 575 rargs[ranum++] = host; 576 rargs[ranum++] = "-p"; 577 rargs[ranum++] = port; 578 } 579 rargs[ranum++] = "-D"; 580 rargs[ranum++] = manager; 581 rargs[ranum++] = "-w"; 582 rargs[ranum++] = passwd; 583 rargs[ranum++] = "-l"; 584 rargs[ranum++] = rloops; 585 rargs[ranum++] = "-L"; 586 rargs[ranum++] = outerloops; 587 rargs[ranum++] = "-r"; 588 rargs[ranum++] = retries; 589 rargs[ranum++] = "-t"; 590 rargs[ranum++] = delay; 591 if ( friendly ) { 592 rargs[ranum++] = friendlyOpt; 593 } 594 if ( chaserefs ) { 595 rargs[ranum++] = "-C"; 596 } 597 if ( noattrs ) { 598 rargs[ranum++] = "-A"; 599 } 600 if ( ignore ) { 601 rargs[ranum++] = "-i"; 602 rargs[ranum++] = ignore; 603 } 604 rargs[ranum++] = "-e"; 605 rargs[ranum++] = NULL; /* will hold the read entry */ 606 607 rargs[ranum++] = NULL; 608 rargs[ranum++] = NULL; /* might hold the filter arg */ 609 rextra_args += 2; 610 611 rargs[ranum] = NULL; 612 613 /* 614 * generate the modrdn clients 615 */ 616 617 nanum = 0; 618 snprintf( ncmd, sizeof ncmd, "%s" LDAP_DIRSEP MODRDNCMD, 619 progdir ); 620 nargs[nanum++] = ncmd; 621 if ( uri ) { 622 nargs[nanum++] = "-H"; 623 nargs[nanum++] = uri; 624 } else { 625 nargs[nanum++] = "-h"; 626 nargs[nanum++] = host; 627 nargs[nanum++] = "-p"; 628 nargs[nanum++] = port; 629 } 630 nargs[nanum++] = "-D"; 631 nargs[nanum++] = manager; 632 nargs[nanum++] = "-w"; 633 nargs[nanum++] = passwd; 634 nargs[nanum++] = "-l"; 635 nargs[nanum++] = nloops; 636 nargs[nanum++] = "-L"; 637 nargs[nanum++] = outerloops; 638 nargs[nanum++] = "-r"; 639 nargs[nanum++] = retries; 640 nargs[nanum++] = "-t"; 641 nargs[nanum++] = delay; 642 if ( friendly ) { 643 nargs[nanum++] = friendlyOpt; 644 } 645 if ( chaserefs ) { 646 nargs[nanum++] = "-C"; 647 } 648 if ( ignore ) { 649 nargs[nanum++] = "-i"; 650 nargs[nanum++] = ignore; 651 } 652 nargs[nanum++] = "-e"; 653 nargs[nanum++] = NULL; /* will hold the modrdn entry */ 654 nargs[nanum] = NULL; 655 656 /* 657 * generate the modify clients 658 */ 659 660 manum = 0; 661 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODIFYCMD, 662 progdir ); 663 margs[manum++] = mcmd; 664 if ( uri ) { 665 margs[manum++] = "-H"; 666 margs[manum++] = uri; 667 } else { 668 margs[manum++] = "-h"; 669 margs[manum++] = host; 670 margs[manum++] = "-p"; 671 margs[manum++] = port; 672 } 673 margs[manum++] = "-D"; 674 margs[manum++] = manager; 675 margs[manum++] = "-w"; 676 margs[manum++] = passwd; 677 margs[manum++] = "-l"; 678 margs[manum++] = mloops; 679 margs[manum++] = "-L"; 680 margs[manum++] = outerloops; 681 margs[manum++] = "-r"; 682 margs[manum++] = retries; 683 margs[manum++] = "-t"; 684 margs[manum++] = delay; 685 if ( friendly ) { 686 margs[manum++] = friendlyOpt; 687 } 688 if ( chaserefs ) { 689 margs[manum++] = "-C"; 690 } 691 if ( ignore ) { 692 margs[manum++] = "-i"; 693 margs[manum++] = ignore; 694 } 695 margs[manum++] = "-e"; 696 margs[manum++] = NULL; /* will hold the modify entry */ 697 margs[manum++] = "-a";; 698 margs[manum++] = NULL; /* will hold the ava */ 699 margs[manum] = NULL; 700 701 /* 702 * generate the add/delete clients 703 */ 704 705 aanum = 0; 706 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD, 707 progdir ); 708 aargs[aanum++] = acmd; 709 if ( uri ) { 710 aargs[aanum++] = "-H"; 711 aargs[aanum++] = uri; 712 } else { 713 aargs[aanum++] = "-h"; 714 aargs[aanum++] = host; 715 aargs[aanum++] = "-p"; 716 aargs[aanum++] = port; 717 } 718 aargs[aanum++] = "-D"; 719 aargs[aanum++] = manager; 720 aargs[aanum++] = "-w"; 721 aargs[aanum++] = passwd; 722 aargs[aanum++] = "-l"; 723 aargs[aanum++] = aloops; 724 aargs[aanum++] = "-L"; 725 aargs[aanum++] = outerloops; 726 aargs[aanum++] = "-r"; 727 aargs[aanum++] = retries; 728 aargs[aanum++] = "-t"; 729 aargs[aanum++] = delay; 730 if ( friendly ) { 731 aargs[aanum++] = friendlyOpt; 732 } 733 if ( chaserefs ) { 734 aargs[aanum++] = "-C"; 735 } 736 if ( ignore ) { 737 aargs[aanum++] = "-i"; 738 aargs[aanum++] = ignore; 739 } 740 aargs[aanum++] = "-f"; 741 aargs[aanum++] = NULL; /* will hold the add data file */ 742 aargs[aanum] = NULL; 743 744 /* 745 * generate the bind clients 746 */ 747 748 banum = 0; 749 snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD, 750 progdir ); 751 bargs[banum++] = bcmd; 752 if ( !noinit ) { 753 bargs[banum++] = "-I"; /* init on each bind */ 754 } 755 if ( uri ) { 756 bargs[banum++] = "-H"; 757 bargs[banum++] = uri; 758 } else { 759 bargs[banum++] = "-h"; 760 bargs[banum++] = host; 761 bargs[banum++] = "-p"; 762 bargs[banum++] = port; 763 } 764 bargs[banum++] = "-l"; 765 bargs[banum++] = bloops; 766 bargs[banum++] = "-L"; 767 bargs[banum++] = outerloops; 768#if 0 769 bargs[banum++] = "-r"; 770 bargs[banum++] = retries; 771 bargs[banum++] = "-t"; 772 bargs[banum++] = delay; 773#endif 774 if ( friendly ) { 775 bargs[banum++] = friendlyOpt; 776 } 777 if ( chaserefs ) { 778 bargs[banum++] = "-C"; 779 } 780 if ( ignore ) { 781 bargs[banum++] = "-i"; 782 bargs[banum++] = ignore; 783 } 784 if ( nextra ) { 785 bargs[banum++] = "-B"; 786 bargs_extra = &bargs[banum++]; 787 } 788 bargs[banum++] = "-D"; 789 bargs[banum++] = NULL; 790 bargs[banum++] = "-w"; 791 bargs[banum++] = NULL; 792 bargs[banum] = NULL; 793 794#define DOREQ(n,j) ((n) && ((maxkids > (n)) ? ((j) < maxkids ) : ((j) < (n)))) 795 796 for ( j = 0; j < MAXREQS; j++ ) { 797 /* search */ 798 if ( DOREQ( snum, j ) ) { 799 int jj = j % snum; 800 int x = sanum - sextra_args; 801 802 /* base */ 803 if ( sbase[jj] != NULL ) { 804 sargs[sanum - 7] = sbase[jj]; 805 806 } else { 807 sargs[sanum - 7] = slud[jj]->lud_dn; 808 } 809 810 /* scope */ 811 if ( slud[jj] != NULL ) { 812 sargs[sanum - 5] = (char *)ldap_pvt_scope2str( slud[jj]->lud_scope ); 813 814 } else { 815 sargs[sanum - 5] = "sub"; 816 } 817 818 /* filter */ 819 if ( sreqs[jj] != NULL ) { 820 sargs[sanum - 3] = sreqs[jj]; 821 822 } else if ( slud[jj]->lud_filter != NULL ) { 823 sargs[sanum - 3] = slud[jj]->lud_filter; 824 825 } else { 826 sargs[sanum - 3] = "(objectClass=*)"; 827 } 828 829 /* extras */ 830 sargs[x] = NULL; 831 832 /* attr */ 833 if ( sattrs[jj] != NULL ) { 834 sargs[x++] = "-a"; 835 sargs[x++] = sattrs[jj]; 836 } 837 838 /* attrs */ 839 if ( slud[jj] != NULL && slud[jj]->lud_attrs != NULL ) { 840 int i; 841 842 for ( i = 0; slud[jj]->lud_attrs[ i ] != NULL && x + i < MAXARGS - 1; i++ ) { 843 sargs[x + i] = slud[jj]->lud_attrs[ i ]; 844 } 845 sargs[x + i] = NULL; 846 } 847 848 fork_child( scmd, sargs ); 849 } 850 851 /* read */ 852 if ( DOREQ( rnum, j ) ) { 853 int jj = j % rnum; 854 int x = ranum - rextra_args; 855 856 rargs[ranum - 3] = rreqs[jj]; 857 if ( rflts[jj] != NULL ) { 858 rargs[x++] = "-f"; 859 rargs[x++] = rflts[jj]; 860 } 861 rargs[x] = NULL; 862 fork_child( rcmd, rargs ); 863 } 864 865 /* rename */ 866 if ( j < nnum ) { 867 nargs[nanum - 1] = nreqs[j]; 868 fork_child( ncmd, nargs ); 869 } 870 871 /* modify */ 872 if ( j < mnum ) { 873 margs[manum - 3] = mdn[j]; 874 margs[manum - 1] = mreqs[j]; 875 fork_child( mcmd, margs ); 876 } 877 878 /* add/delete */ 879 if ( j < anum ) { 880 aargs[aanum - 1] = afiles[j]; 881 fork_child( acmd, aargs ); 882 } 883 884 /* bind */ 885 if ( DOREQ( bnum, j ) ) { 886 int jj = j % bnum; 887 888 if ( nextra ) { 889 int n = ((double)nextra)*rand()/(RAND_MAX + 1.0); 890 extra_t *e; 891 892 for ( e = extra; n-- > 0; e = e->next ) 893 ; 894 *bargs_extra = e->action; 895 } 896 897 if ( battrs[jj] != NULL ) { 898 bargs[banum - 3] = manager ? manager : ""; 899 bargs[banum - 1] = passwd ? passwd : ""; 900 901 bargs[banum + 0] = "-b"; 902 bargs[banum + 1] = breqs[jj]; 903 bargs[banum + 2] = "-f"; 904 bargs[banum + 3] = bcreds[jj]; 905 bargs[banum + 4] = "-a"; 906 bargs[banum + 5] = battrs[jj]; 907 bargs[banum + 6] = NULL; 908 909 } else { 910 bargs[banum - 3] = breqs[jj]; 911 bargs[banum - 1] = bcreds[jj]; 912 bargs[banum] = NULL; 913 } 914 915 fork_child( bcmd, bargs ); 916 bargs[banum] = NULL; 917 } 918 } 919 920 wait4kids( -1 ); 921 922 exit( EXIT_SUCCESS ); 923} 924 925static char * 926get_file_name( char *dirname, char *filename ) 927{ 928 char buf[MAXPATHLEN]; 929 930 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s", 931 dirname, filename ); 932 return( strdup( buf )); 933} 934 935 936static int 937get_search_filters( char *filename, char *filters[], char *attrs[], char *bases[], LDAPURLDesc *luds[] ) 938{ 939 FILE *fp; 940 int filter = 0; 941 942 if ( (fp = fopen( filename, "r" )) != NULL ) { 943 char line[BUFSIZ]; 944 945 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) { 946 char *nl; 947 int got_URL = 0; 948 949 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 950 *nl = '\0'; 951 952 if ( luds ) luds[filter] = NULL; 953 954 if ( luds && strncmp( line, "ldap:///", STRLENOF( "ldap:///" ) ) == 0 ) { 955 LDAPURLDesc *lud; 956 957 got_URL = 1; 958 bases[filter] = NULL; 959 if ( ldap_url_parse( line, &lud ) != LDAP_URL_SUCCESS ) { 960 filter = -filter - 1; 961 break; 962 } 963 964 if ( lud->lud_dn == NULL || lud->lud_exts != NULL ) { 965 filter = -filter - 1; 966 ldap_free_urldesc( lud ); 967 break; 968 } 969 970 luds[filter] = lud; 971 972 } else { 973 bases[filter] = ArgDup( line ); 974 } 975 fgets( line, BUFSIZ, fp ); 976 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 977 *nl = '\0'; 978 979 filters[filter] = ArgDup( line ); 980 if ( attrs ) { 981 if ( filters[filter][0] == '+') { 982 char *sep = strchr( filters[filter], ':' ); 983 984 attrs[ filter ] = &filters[ filter ][ 1 ]; 985 if ( sep != NULL ) { 986 sep[ 0 ] = '\0'; 987 /* NOTE: don't free this! */ 988 filters[ filter ] = &sep[ 1 ]; 989 } 990 991 } else { 992 attrs[ filter ] = NULL; 993 } 994 } 995 filter++; 996 997 } 998 fclose( fp ); 999 } 1000 1001 return filter; 1002} 1003 1004 1005static int 1006get_read_entries( char *filename, char *entries[], char *filters[] ) 1007{ 1008 FILE *fp; 1009 int entry = 0; 1010 1011 if ( (fp = fopen( filename, "r" )) != NULL ) { 1012 char line[BUFSIZ]; 1013 1014 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) { 1015 char *nl; 1016 1017 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) 1018 *nl = '\0'; 1019 if ( filters != NULL && line[0] == '+' ) { 1020 LDAPURLDesc *lud; 1021 1022 if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) { 1023 entry = -entry - 1; 1024 break; 1025 } 1026 1027 if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) { 1028 ldap_free_urldesc( lud ); 1029 entry = -entry - 1; 1030 break; 1031 } 1032 1033 entries[entry] = ArgDup( lud->lud_dn ); 1034 1035 if ( lud->lud_filter ) { 1036 filters[entry] = ArgDup( lud->lud_filter ); 1037 1038 } else { 1039 filters[entry] = ArgDup( "(objectClass=*)" ); 1040 } 1041 ldap_free_urldesc( lud ); 1042 1043 } else { 1044 entries[entry] = ArgDup( line ); 1045 } 1046 1047 entry++; 1048 1049 } 1050 fclose( fp ); 1051 } 1052 1053 return( entry ); 1054} 1055 1056#ifndef HAVE_WINSOCK 1057static void 1058fork_child( char *prog, char **args ) 1059{ 1060 /* note: obscures global pid var; intended */ 1061 pid_t pid; 1062 1063 wait4kids( maxkids ); 1064 1065 switch ( pid = fork() ) { 1066 case 0: /* child */ 1067#ifdef HAVE_EBCDIC 1068 /* The __LIBASCII execvp only handles ASCII "prog", 1069 * we still need to translate the arg vec ourselves. 1070 */ 1071 { char *arg2[MAXREQS]; 1072 int i; 1073 1074 for (i=0; args[i]; i++) { 1075 arg2[i] = ArgDup(args[i]); 1076 __atoe(arg2[i]); 1077 } 1078 arg2[i] = NULL; 1079 args = arg2; } 1080#endif 1081 execvp( prog, args ); 1082 tester_perror( "execvp", NULL ); 1083 { int i; 1084 for (i=0; args[i]; i++); 1085 fprintf(stderr,"%d args\n", i); 1086 for (i=0; args[i]; i++) 1087 fprintf(stderr,"%d %s\n", i, args[i]); 1088 } 1089 1090 exit( EXIT_FAILURE ); 1091 break; 1092 1093 case -1: /* trouble */ 1094 tester_perror( "fork", NULL ); 1095 break; 1096 1097 default: /* parent */ 1098 nkids++; 1099 break; 1100 } 1101} 1102 1103static void 1104wait4kids( int nkidval ) 1105{ 1106 int status; 1107 1108 while ( nkids >= nkidval ) { 1109 wait( &status ); 1110 1111 if ( WIFSTOPPED(status) ) { 1112 fprintf( stderr, 1113 "stopping: child stopped with signal %d\n", 1114 (int) WSTOPSIG(status) ); 1115 1116 } else if ( WIFSIGNALED(status) ) { 1117 fprintf( stderr, 1118 "stopping: child terminated with signal %d%s\n", 1119 (int) WTERMSIG(status), 1120#ifdef WCOREDUMP 1121 WCOREDUMP(status) ? ", core dumped" : "" 1122#else 1123 "" 1124#endif 1125 ); 1126 exit( WEXITSTATUS(status) ); 1127 1128 } else if ( WEXITSTATUS(status) != 0 ) { 1129 fprintf( stderr, 1130 "stopping: child exited with status %d\n", 1131 (int) WEXITSTATUS(status) ); 1132 exit( WEXITSTATUS(status) ); 1133 1134 } else { 1135 nkids--; 1136 } 1137 } 1138} 1139#else 1140 1141static void 1142wait4kids( int nkidval ) 1143{ 1144 int rc, i; 1145 1146 while ( nkids >= nkidval ) { 1147 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE ); 1148 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++) 1149 children[i] = children[i+1]; 1150 nkids--; 1151 } 1152} 1153 1154static void 1155fork_child( char *prog, char **args ) 1156{ 1157 int rc; 1158 1159 wait4kids( maxkids ); 1160 1161 rc = _spawnvp( _P_NOWAIT, prog, args ); 1162 1163 if ( rc == -1 ) { 1164 tester_perror( "_spawnvp", NULL ); 1165 } else { 1166 children[nkids++] = (HANDLE)rc; 1167 } 1168} 1169#endif 1170