ruby-ldap 0.9.18 → 0.9.19

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,618 @@
1
+ /* $OpenLDAP$ */
2
+ /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
+ *
4
+ * Copyright 1999-2016 The OpenLDAP Foundation.
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted only as authorized by the OpenLDAP
9
+ * Public License.
10
+ *
11
+ * A copy of this license is available in file LICENSE in the
12
+ * top-level directory of the distribution or, alternatively, at
13
+ * <http://www.OpenLDAP.org/license.html>.
14
+ */
15
+ /* ACKNOWLEDGEMENTS:
16
+ * This work was initially developed by Kurt Spanier for inclusion
17
+ * in OpenLDAP Software.
18
+ */
19
+
20
+ #include "portable.h"
21
+
22
+ #include <stdio.h>
23
+
24
+ #include "ac/stdlib.h"
25
+
26
+ #include "ac/ctype.h"
27
+ #include "ac/param.h"
28
+ #include "ac/socket.h"
29
+ #include "ac/string.h"
30
+ #include "ac/unistd.h"
31
+ #include "ac/wait.h"
32
+
33
+ #include "ldap.h"
34
+ #include "lutil.h"
35
+ #include "ldap_pvt.h"
36
+
37
+ #include "slapd-common.h"
38
+
39
+ #define LOOPS 100
40
+ #define RETRIES 0
41
+
42
+ static void
43
+ do_search( char *uri, char *manager, struct berval *passwd,
44
+ char *sbase, int scope, char *filter, LDAP **ldp,
45
+ char **attrs, int noattrs, int nobind,
46
+ int innerloop, int maxretries, int delay, int force, int chaserefs );
47
+
48
+ static void
49
+ do_random( char *uri, char *manager, struct berval *passwd,
50
+ char *sbase, int scope, char *filter, char *attr,
51
+ char **attrs, int noattrs, int nobind,
52
+ int innerloop, int maxretries, int delay, int force, int chaserefs );
53
+
54
+ static void
55
+ usage( char *name, char o )
56
+ {
57
+ if ( o != '\0' ) {
58
+ fprintf( stderr, "unknown/incorrect option \"%c\"\n", o );
59
+ }
60
+
61
+ fprintf( stderr,
62
+ "usage: %s "
63
+ "-H <uri> | ([-h <host>] -p <port>) "
64
+ "-D <manager> "
65
+ "-w <passwd> "
66
+ "-b <searchbase> "
67
+ "-s <scope> "
68
+ "-f <searchfilter> "
69
+ "[-a <attr>] "
70
+ "[-A] "
71
+ "[-C] "
72
+ "[-F] "
73
+ "[-N] "
74
+ "[-S[S[S]]] "
75
+ "[-i <ignore>] "
76
+ "[-l <loops>] "
77
+ "[-L <outerloops>] "
78
+ "[-r <maxretries>] "
79
+ "[-t <delay>] "
80
+ "[<attrs>] "
81
+ "\n",
82
+ name );
83
+ exit( EXIT_FAILURE );
84
+ }
85
+
86
+ /* -S: just send requests without reading responses
87
+ * -SS: send all requests asynchronous and immediately start reading responses
88
+ * -SSS: send all requests asynchronous; then read responses
89
+ */
90
+ static int swamp;
91
+
92
+ int
93
+ main( int argc, char **argv )
94
+ {
95
+ int i;
96
+ char *uri = NULL;
97
+ char *host = "localhost";
98
+ int port = -1;
99
+ char *manager = NULL;
100
+ struct berval passwd = { 0, NULL };
101
+ char *sbase = NULL;
102
+ int scope = LDAP_SCOPE_SUBTREE;
103
+ char *filter = NULL;
104
+ char *attr = NULL;
105
+ char *srchattrs[] = { "cn", "sn", NULL };
106
+ char **attrs = srchattrs;
107
+ int loops = LOOPS;
108
+ int outerloops = 1;
109
+ int retries = RETRIES;
110
+ int delay = 0;
111
+ int force = 0;
112
+ int chaserefs = 0;
113
+ int noattrs = 0;
114
+ int nobind = 0;
115
+
116
+ tester_init( "slapd-search", TESTER_SEARCH );
117
+
118
+ /* by default, tolerate referrals and no such object */
119
+ tester_ignore_str2errlist( "REFERRAL,NO_SUCH_OBJECT" );
120
+
121
+ while ( ( i = getopt( argc, argv, "Aa:b:CD:f:FH:h:i:l:L:Np:r:Ss:t:T:w:" ) ) != EOF )
122
+ {
123
+ switch ( i ) {
124
+ case 'A':
125
+ noattrs++;
126
+ break;
127
+
128
+ case 'C':
129
+ chaserefs++;
130
+ break;
131
+
132
+ case 'H': /* the server uri */
133
+ uri = strdup( optarg );
134
+ break;
135
+
136
+ case 'h': /* the servers host */
137
+ host = strdup( optarg );
138
+ break;
139
+
140
+ case 'i':
141
+ tester_ignore_str2errlist( optarg );
142
+ break;
143
+
144
+ case 'N':
145
+ nobind++;
146
+ break;
147
+
148
+ case 'p': /* the servers port */
149
+ if ( lutil_atoi( &port, optarg ) != 0 ) {
150
+ usage( argv[0], i );
151
+ }
152
+ break;
153
+
154
+ case 'D': /* the servers manager */
155
+ manager = strdup( optarg );
156
+ break;
157
+
158
+ case 'w': /* the server managers password */
159
+ passwd.bv_val = strdup( optarg );
160
+ passwd.bv_len = strlen( optarg );
161
+ memset( optarg, '*', passwd.bv_len );
162
+ break;
163
+
164
+ case 'a':
165
+ attr = strdup( optarg );
166
+ break;
167
+
168
+ case 'b': /* file with search base */
169
+ sbase = strdup( optarg );
170
+ break;
171
+
172
+ case 'f': /* the search request */
173
+ filter = strdup( optarg );
174
+ break;
175
+
176
+ case 'F':
177
+ force++;
178
+ break;
179
+
180
+ case 'l': /* number of loops */
181
+ if ( lutil_atoi( &loops, optarg ) != 0 ) {
182
+ usage( argv[0], i );
183
+ }
184
+ break;
185
+
186
+ case 'L': /* number of loops */
187
+ if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
188
+ usage( argv[0], i );
189
+ }
190
+ break;
191
+
192
+ case 'r': /* number of retries */
193
+ if ( lutil_atoi( &retries, optarg ) != 0 ) {
194
+ usage( argv[0], i );
195
+ }
196
+ break;
197
+
198
+ case 't': /* delay in seconds */
199
+ if ( lutil_atoi( &delay, optarg ) != 0 ) {
200
+ usage( argv[0], i );
201
+ }
202
+ break;
203
+
204
+ case 'T':
205
+ attrs = ldap_str2charray( optarg, "," );
206
+ if ( attrs == NULL ) {
207
+ usage( argv[0], i );
208
+ }
209
+ break;
210
+
211
+ case 'S':
212
+ swamp++;
213
+ break;
214
+
215
+ case 's':
216
+ scope = ldap_pvt_str2scope( optarg );
217
+ if ( scope == -1 ) {
218
+ usage( argv[0], i );
219
+ }
220
+ break;
221
+
222
+ default:
223
+ usage( argv[0], i );
224
+ break;
225
+ }
226
+ }
227
+
228
+ if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 && uri == NULL ))
229
+ usage( argv[0], '\0' );
230
+
231
+ if ( *filter == '\0' ) {
232
+
233
+ fprintf( stderr, "%s: invalid EMPTY search filter.\n",
234
+ argv[0] );
235
+ exit( EXIT_FAILURE );
236
+
237
+ }
238
+
239
+ if ( argv[optind] != NULL ) {
240
+ attrs = &argv[optind];
241
+ }
242
+
243
+ uri = tester_uri( uri, host, port );
244
+
245
+ for ( i = 0; i < outerloops; i++ ) {
246
+ if ( attr != NULL ) {
247
+ do_random( uri, manager, &passwd,
248
+ sbase, scope, filter, attr,
249
+ attrs, noattrs, nobind,
250
+ loops, retries, delay, force, chaserefs );
251
+
252
+ } else {
253
+ do_search( uri, manager, &passwd,
254
+ sbase, scope, filter, NULL,
255
+ attrs, noattrs, nobind,
256
+ loops, retries, delay, force, chaserefs );
257
+ }
258
+ }
259
+
260
+ exit( EXIT_SUCCESS );
261
+ }
262
+
263
+
264
+ static void
265
+ do_random( char *uri, char *manager, struct berval *passwd,
266
+ char *sbase, int scope, char *filter, char *attr,
267
+ char **srchattrs, int noattrs, int nobind,
268
+ int innerloop, int maxretries, int delay, int force, int chaserefs )
269
+ {
270
+ LDAP *ld = NULL;
271
+ int i = 0, do_retry = maxretries;
272
+ char *attrs[ 2 ];
273
+ int rc = LDAP_SUCCESS;
274
+ int version = LDAP_VERSION3;
275
+ int nvalues = 0;
276
+ char **values = NULL;
277
+ LDAPMessage *res = NULL, *e = NULL;
278
+
279
+ attrs[ 0 ] = attr;
280
+ attrs[ 1 ] = NULL;
281
+
282
+ ldap_initialize( &ld, uri );
283
+ if ( ld == NULL ) {
284
+ tester_perror( "ldap_initialize", NULL );
285
+ exit( EXIT_FAILURE );
286
+ }
287
+
288
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
289
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
290
+ chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
291
+
292
+ if ( do_retry == maxretries ) {
293
+ fprintf( stderr, "PID=%ld - Search(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
294
+ (long) pid, innerloop, sbase, filter, attr );
295
+ }
296
+
297
+ if ( nobind == 0 ) {
298
+ rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
299
+ if ( rc != LDAP_SUCCESS ) {
300
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
301
+ switch ( rc ) {
302
+ case LDAP_BUSY:
303
+ case LDAP_UNAVAILABLE:
304
+ /* fallthru */
305
+ default:
306
+ break;
307
+ }
308
+ exit( EXIT_FAILURE );
309
+ }
310
+ }
311
+
312
+ rc = ldap_search_ext_s( ld, sbase, LDAP_SCOPE_SUBTREE,
313
+ filter, attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
314
+ switch ( rc ) {
315
+ case LDAP_SIZELIMIT_EXCEEDED:
316
+ case LDAP_TIMELIMIT_EXCEEDED:
317
+ case LDAP_SUCCESS:
318
+ if ( ldap_count_entries( ld, res ) == 0 ) {
319
+ if ( rc ) {
320
+ tester_ldap_error( ld, "ldap_search_ext_s", NULL );
321
+ }
322
+ break;
323
+ }
324
+
325
+ for ( e = ldap_first_entry( ld, res ); e != NULL; e = ldap_next_entry( ld, e ) )
326
+ {
327
+ struct berval **v = ldap_get_values_len( ld, e, attr );
328
+
329
+ if ( v != NULL ) {
330
+ int n = ldap_count_values_len( v );
331
+ int j;
332
+
333
+ values = realloc( values, ( nvalues + n + 1 )*sizeof( char * ) );
334
+ for ( j = 0; j < n; j++ ) {
335
+ values[ nvalues + j ] = strdup( v[ j ]->bv_val );
336
+ }
337
+ values[ nvalues + j ] = NULL;
338
+ nvalues += n;
339
+ ldap_value_free_len( v );
340
+ }
341
+ }
342
+
343
+ ldap_msgfree( res );
344
+
345
+ if ( !values ) {
346
+ fprintf( stderr, " PID=%ld - Search base=\"%s\" filter=\"%s\" got %d values.\n",
347
+ (long) pid, sbase, filter, nvalues );
348
+ exit(EXIT_FAILURE);
349
+ }
350
+
351
+ if ( do_retry == maxretries ) {
352
+ fprintf( stderr, " PID=%ld - Search base=\"%s\" filter=\"%s\" got %d values.\n",
353
+ (long) pid, sbase, filter, nvalues );
354
+ }
355
+
356
+ for ( i = 0; i < innerloop; i++ ) {
357
+ char buf[ BUFSIZ ];
358
+ #if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */
359
+ int r = rand() % nvalues;
360
+ #endif
361
+ int r = ((double)nvalues)*rand()/(RAND_MAX + 1.0);
362
+
363
+ snprintf( buf, sizeof( buf ), "(%s=%s)", attr, values[ r ] );
364
+
365
+ do_search( uri, manager, passwd,
366
+ sbase, scope, buf, &ld,
367
+ srchattrs, noattrs, nobind,
368
+ 1, maxretries, delay, force, chaserefs );
369
+ }
370
+ break;
371
+
372
+ default:
373
+ tester_ldap_error( ld, "ldap_search_ext_s", NULL );
374
+ break;
375
+ }
376
+
377
+ fprintf( stderr, " PID=%ld - Search done (%d).\n", (long) pid, rc );
378
+
379
+ if ( ld != NULL ) {
380
+ ldap_unbind_ext( ld, NULL, NULL );
381
+ }
382
+ }
383
+
384
+ static void
385
+ do_search( char *uri, char *manager, struct berval *passwd,
386
+ char *sbase, int scope, char *filter, LDAP **ldp,
387
+ char **attrs, int noattrs, int nobind,
388
+ int innerloop, int maxretries, int delay, int force, int chaserefs )
389
+ {
390
+ LDAP *ld = ldp ? *ldp : NULL;
391
+ int i = 0, do_retry = maxretries;
392
+ int rc = LDAP_SUCCESS;
393
+ int version = LDAP_VERSION3;
394
+ char buf[ BUFSIZ ];
395
+ int *msgids = NULL, active = 0;
396
+
397
+ /* make room for msgid */
398
+ if ( swamp > 1 ) {
399
+ msgids = (int *)calloc( sizeof(int), innerloop );
400
+ }
401
+
402
+ retry:;
403
+ if ( ld == NULL ) {
404
+ ldap_initialize( &ld, uri );
405
+ if ( ld == NULL ) {
406
+ tester_perror( "ldap_initialize", NULL );
407
+ exit( EXIT_FAILURE );
408
+ }
409
+
410
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
411
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
412
+ chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
413
+
414
+ if ( do_retry == maxretries ) {
415
+ fprintf( stderr,
416
+ "PID=%ld - Search(%d): "
417
+ "base=\"%s\" scope=%s filter=\"%s\" "
418
+ "attrs=%s%s.\n",
419
+ (long) pid, innerloop,
420
+ sbase, ldap_pvt_scope2str( scope ), filter,
421
+ attrs[0], attrs[1] ? " (more...)" : "" );
422
+ }
423
+
424
+ if ( nobind == 0 ) {
425
+ rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
426
+ if ( rc != LDAP_SUCCESS ) {
427
+ snprintf( buf, sizeof( buf ),
428
+ "bindDN=\"%s\"", manager );
429
+ tester_ldap_error( ld, "ldap_sasl_bind_s", buf );
430
+ switch ( rc ) {
431
+ case LDAP_BUSY:
432
+ case LDAP_UNAVAILABLE:
433
+ if ( do_retry > 0 ) {
434
+ ldap_unbind_ext( ld, NULL, NULL );
435
+ ld = NULL;
436
+ do_retry--;
437
+ if ( delay != 0 ) {
438
+ sleep( delay );
439
+ }
440
+ goto retry;
441
+ }
442
+ /* fallthru */
443
+ default:
444
+ break;
445
+ }
446
+ exit( EXIT_FAILURE );
447
+ }
448
+ }
449
+ }
450
+
451
+ if ( swamp > 1 ) {
452
+ do {
453
+ LDAPMessage *res = NULL;
454
+ int j, msgid;
455
+
456
+ if ( i < innerloop ) {
457
+ rc = ldap_search_ext( ld, sbase, scope,
458
+ filter, NULL, noattrs, NULL, NULL,
459
+ NULL, LDAP_NO_LIMIT, &msgids[i] );
460
+
461
+ active++;
462
+ #if 0
463
+ fprintf( stderr,
464
+ ">>> PID=%ld - Search maxloop=%d cnt=%d active=%d msgid=%d: "
465
+ "base=\"%s\" scope=%s filter=\"%s\"\n",
466
+ (long) pid, innerloop, i, active, msgids[i],
467
+ sbase, ldap_pvt_scope2str( scope ), filter );
468
+ #endif
469
+ i++;
470
+
471
+ if ( rc ) {
472
+ int first = tester_ignore_err( rc );
473
+ /* if ignore.. */
474
+ if ( first ) {
475
+ /* only log if first occurrence */
476
+ if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
477
+ tester_ldap_error( ld, "ldap_search_ext", NULL );
478
+ }
479
+ continue;
480
+ }
481
+
482
+ /* busy needs special handling */
483
+ snprintf( buf, sizeof( buf ),
484
+ "base=\"%s\" filter=\"%s\"\n",
485
+ sbase, filter );
486
+ tester_ldap_error( ld, "ldap_search_ext", buf );
487
+ if ( rc == LDAP_BUSY && do_retry > 0 ) {
488
+ ldap_unbind_ext( ld, NULL, NULL );
489
+ ld = NULL;
490
+ do_retry--;
491
+ goto retry;
492
+ }
493
+ break;
494
+ }
495
+
496
+ if ( swamp > 2 ) {
497
+ continue;
498
+ }
499
+ }
500
+
501
+ rc = ldap_result( ld, LDAP_RES_ANY, 0, NULL, &res );
502
+ switch ( rc ) {
503
+ case -1:
504
+ /* gone really bad */
505
+ goto cleanup;
506
+
507
+ case 0:
508
+ /* timeout (impossible) */
509
+ break;
510
+
511
+ case LDAP_RES_SEARCH_ENTRY:
512
+ case LDAP_RES_SEARCH_REFERENCE:
513
+ /* ignore */
514
+ break;
515
+
516
+ case LDAP_RES_SEARCH_RESULT:
517
+ /* just remove, no error checking (TODO?) */
518
+ msgid = ldap_msgid( res );
519
+ ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, NULL, 1 );
520
+ res = NULL;
521
+
522
+ /* linear search, bah */
523
+ for ( j = 0; j < i; j++ ) {
524
+ if ( msgids[ j ] == msgid ) {
525
+ msgids[ j ] = -1;
526
+ active--;
527
+ #if 0
528
+ fprintf( stderr,
529
+ "<<< PID=%ld - SearchDone maxloop=%d cnt=%d active=%d msgid=%d: "
530
+ "base=\"%s\" scope=%s filter=\"%s\"\n",
531
+ (long) pid, innerloop, j, active, msgid,
532
+ sbase, ldap_pvt_scope2str( scope ), filter );
533
+ #endif
534
+ break;
535
+ }
536
+ }
537
+ break;
538
+
539
+ default:
540
+ /* other messages unexpected */
541
+ fprintf( stderr,
542
+ "### PID=%ld - Search(%d): "
543
+ "base=\"%s\" scope=%s filter=\"%s\" "
544
+ "attrs=%s%s. unexpected response tag=%d\n",
545
+ (long) pid, innerloop,
546
+ sbase, ldap_pvt_scope2str( scope ), filter,
547
+ attrs[0], attrs[1] ? " (more...)" : "", rc );
548
+ break;
549
+ }
550
+
551
+ if ( res != NULL ) {
552
+ ldap_msgfree( res );
553
+ }
554
+ } while ( i < innerloop || active > 0 );
555
+
556
+ } else {
557
+ for ( ; i < innerloop; i++ ) {
558
+ LDAPMessage *res = NULL;
559
+
560
+ if (swamp) {
561
+ int msgid;
562
+ rc = ldap_search_ext( ld, sbase, scope,
563
+ filter, NULL, noattrs, NULL, NULL,
564
+ NULL, LDAP_NO_LIMIT, &msgid );
565
+ if ( rc == LDAP_SUCCESS ) continue;
566
+ else break;
567
+ }
568
+
569
+ rc = ldap_search_ext_s( ld, sbase, scope,
570
+ filter, attrs, noattrs, NULL, NULL,
571
+ NULL, LDAP_NO_LIMIT, &res );
572
+ if ( res != NULL ) {
573
+ ldap_msgfree( res );
574
+ }
575
+
576
+ if ( rc ) {
577
+ int first = tester_ignore_err( rc );
578
+ /* if ignore.. */
579
+ if ( first ) {
580
+ /* only log if first occurrence */
581
+ if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
582
+ tester_ldap_error( ld, "ldap_search_ext_s", NULL );
583
+ }
584
+ continue;
585
+ }
586
+
587
+ /* busy needs special handling */
588
+ snprintf( buf, sizeof( buf ),
589
+ "base=\"%s\" filter=\"%s\"\n",
590
+ sbase, filter );
591
+ tester_ldap_error( ld, "ldap_search_ext_s", buf );
592
+ if ( rc == LDAP_BUSY && do_retry > 0 ) {
593
+ ldap_unbind_ext( ld, NULL, NULL );
594
+ ld = NULL;
595
+ do_retry--;
596
+ goto retry;
597
+ }
598
+ break;
599
+ }
600
+ }
601
+ }
602
+
603
+ cleanup:;
604
+ if ( msgids != NULL ) {
605
+ free( msgids );
606
+ }
607
+
608
+ if ( ldp != NULL ) {
609
+ *ldp = ld;
610
+
611
+ } else {
612
+ fprintf( stderr, " PID=%ld - Search done (%d).\n", (long) pid, rc );
613
+
614
+ if ( ld != NULL ) {
615
+ ldap_unbind_ext( ld, NULL, NULL );
616
+ }
617
+ }
618
+ }