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,609 @@
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 Howard Chu for inclusion
17
+ * in OpenLDAP Software.
18
+ */
19
+
20
+ #include "portable.h"
21
+
22
+ #include <stdio.h>
23
+
24
+ #include "ac/stdlib.h"
25
+ #include "ac/time.h"
26
+
27
+ #include "ac/ctype.h"
28
+ #include "ac/param.h"
29
+ #include "ac/socket.h"
30
+ #include "ac/string.h"
31
+ #include "ac/unistd.h"
32
+ #include "ac/wait.h"
33
+ #include "ac/time.h"
34
+
35
+ #include "ldap.h"
36
+ #include "lutil.h"
37
+ #include "lber_pvt.h"
38
+ #include "ldap_pvt.h"
39
+
40
+ #include "slapd-common.h"
41
+
42
+ #define LOOPS 100
43
+
44
+ static int
45
+ do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
46
+ int force, int chaserefs, int noinit, LDAP **ldp,
47
+ int action_type, void *action );
48
+
49
+ static int
50
+ do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr,
51
+ int maxloop, int force, int chaserefs, int noinit, int delay,
52
+ int action_type, void *action );
53
+
54
+ /* This program can be invoked two ways: if -D is used to specify a Bind DN,
55
+ * that DN will be used repeatedly for all of the Binds. If instead -b is used
56
+ * to specify a base DN, a search will be done for all "person" objects under
57
+ * that base DN. Then DNs from this list will be randomly selected for each
58
+ * Bind request. All of the users must have identical passwords. Also it is
59
+ * assumed that the users are all onelevel children of the base.
60
+ */
61
+ static void
62
+ usage( char *name, char opt )
63
+ {
64
+ if ( opt ) {
65
+ fprintf( stderr, "%s: unable to handle option \'%c\'\n\n",
66
+ name, opt );
67
+ }
68
+
69
+ fprintf( stderr, "usage: %s "
70
+ "[-H uri | -h <host> [-p port]] "
71
+ "[-D <dn> [-w <passwd>]] "
72
+ "[-b <baseDN> [-f <searchfilter>] [-a pwattr]] "
73
+ "[-l <loops>] "
74
+ "[-L <outerloops>] "
75
+ "[-B <extra>[,...]] "
76
+ "[-F] "
77
+ "[-C] "
78
+ "[-I] "
79
+ "[-i <ignore>] "
80
+ "[-t delay]\n",
81
+ name );
82
+ exit( EXIT_FAILURE );
83
+ }
84
+
85
+ int
86
+ main( int argc, char **argv )
87
+ {
88
+ int i;
89
+ char *uri = NULL;
90
+ char *host = "localhost";
91
+ char *dn = NULL;
92
+ char *base = NULL;
93
+ char *filter = "(objectClass=person)";
94
+ struct berval pass = { 0, NULL };
95
+ char *pwattr = NULL;
96
+ int port = -1;
97
+ int loops = LOOPS;
98
+ int outerloops = 1;
99
+ int force = 0;
100
+ int chaserefs = 0;
101
+ int noinit = 1;
102
+ int delay = 0;
103
+
104
+ /* extra action to do after bind... */
105
+ struct berval type[] = {
106
+ BER_BVC( "tester=" ),
107
+ BER_BVC( "add=" ),
108
+ BER_BVC( "bind=" ),
109
+ BER_BVC( "modify=" ),
110
+ BER_BVC( "modrdn=" ),
111
+ BER_BVC( "read=" ),
112
+ BER_BVC( "search=" ),
113
+ BER_BVNULL
114
+ };
115
+
116
+ LDAPURLDesc *extra_ludp = NULL;
117
+
118
+ tester_init( "slapd-bind", TESTER_BIND );
119
+
120
+ /* by default, tolerate invalid credentials */
121
+ tester_ignore_str2errlist( "INVALID_CREDENTIALS" );
122
+
123
+ while ( ( i = getopt( argc, argv, "a:B:b:D:Ff:H:h:Ii:L:l:p:t:w:" ) ) != EOF )
124
+ {
125
+ switch ( i ) {
126
+ case 'a':
127
+ pwattr = optarg;
128
+ break;
129
+
130
+ case 'b': /* base DN of a tree of user DNs */
131
+ base = optarg;
132
+ break;
133
+
134
+ case 'B':
135
+ {
136
+ int c;
137
+
138
+ for ( c = 0; type[c].bv_val; c++ ) {
139
+ if ( strncasecmp( optarg, type[c].bv_val, type[c].bv_len ) == 0 )
140
+ {
141
+ break;
142
+ }
143
+ }
144
+
145
+ if ( type[c].bv_val == NULL ) {
146
+ usage( argv[0], 'B' );
147
+ }
148
+
149
+ switch ( c ) {
150
+ case TESTER_TESTER:
151
+ case TESTER_BIND:
152
+ /* invalid */
153
+ usage( argv[0], 'B' );
154
+
155
+ case TESTER_SEARCH:
156
+ {
157
+ if ( ldap_url_parse( &optarg[type[c].bv_len], &extra_ludp ) != LDAP_URL_SUCCESS )
158
+ {
159
+ usage( argv[0], 'B' );
160
+ }
161
+ } break;
162
+
163
+ case TESTER_ADDEL:
164
+ case TESTER_MODIFY:
165
+ case TESTER_MODRDN:
166
+ case TESTER_READ:
167
+ /* nothing to do */
168
+ break;
169
+
170
+ default:
171
+ assert( 0 );
172
+ }
173
+
174
+ } break;
175
+
176
+ case 'C':
177
+ chaserefs++;
178
+ break;
179
+
180
+ case 'H': /* the server uri */
181
+ uri = optarg;
182
+ break;
183
+
184
+ case 'h': /* the servers host */
185
+ host = optarg;
186
+ break;
187
+
188
+ case 'i':
189
+ tester_ignore_str2errlist( optarg );
190
+ break;
191
+
192
+ case 'p': /* the servers port */
193
+ if ( lutil_atoi( &port, optarg ) != 0 ) {
194
+ usage( argv[0], 'p' );
195
+ }
196
+ break;
197
+
198
+ case 'D':
199
+ dn = optarg;
200
+ break;
201
+
202
+ case 'w':
203
+ ber_str2bv( optarg, 0, 1, &pass );
204
+ memset( optarg, '*', pass.bv_len );
205
+ break;
206
+
207
+ case 'l': /* the number of loops */
208
+ if ( lutil_atoi( &loops, optarg ) != 0 ) {
209
+ usage( argv[0], 'l' );
210
+ }
211
+ break;
212
+
213
+ case 'L': /* the number of outerloops */
214
+ if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
215
+ usage( argv[0], 'L' );
216
+ }
217
+ break;
218
+
219
+ case 'f':
220
+ filter = optarg;
221
+ break;
222
+
223
+ case 'F':
224
+ force++;
225
+ break;
226
+
227
+ case 'I':
228
+ /* reuse connection */
229
+ noinit = 0;
230
+ break;
231
+
232
+ case 't':
233
+ /* sleep between binds */
234
+ if ( lutil_atoi( &delay, optarg ) != 0 ) {
235
+ usage( argv[0], 't' );
236
+ }
237
+ break;
238
+
239
+ default:
240
+ usage( argv[0], i );
241
+ break;
242
+ }
243
+ }
244
+
245
+ if ( port == -1 && uri == NULL ) {
246
+ usage( argv[0], '\0' );
247
+ }
248
+
249
+ uri = tester_uri( uri, host, port );
250
+
251
+ for ( i = 0; i < outerloops; i++ ) {
252
+ int rc;
253
+
254
+ if ( base != NULL ) {
255
+ rc = do_base( uri, dn, &pass, base, filter, pwattr, loops,
256
+ force, chaserefs, noinit, delay, -1, NULL );
257
+ } else {
258
+ rc = do_bind( uri, dn, &pass, loops,
259
+ force, chaserefs, noinit, NULL, -1, NULL );
260
+ }
261
+ if ( rc == LDAP_SERVER_DOWN )
262
+ break;
263
+ }
264
+
265
+ exit( EXIT_SUCCESS );
266
+ }
267
+
268
+
269
+ static int
270
+ do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
271
+ int force, int chaserefs, int noinit, LDAP **ldp,
272
+ int action_type, void *action )
273
+ {
274
+ LDAP *ld = ldp ? *ldp : NULL;
275
+ int i, rc = -1;
276
+
277
+ /* for internal search */
278
+ int timelimit = 0;
279
+ int sizelimit = 0;
280
+
281
+ switch ( action_type ) {
282
+ case -1:
283
+ break;
284
+
285
+ case TESTER_SEARCH:
286
+ {
287
+ LDAPURLDesc *ludp = (LDAPURLDesc *)action;
288
+
289
+ assert( action != NULL );
290
+
291
+ if ( ludp->lud_exts != NULL ) {
292
+ for ( i = 0; ludp->lud_exts[ i ] != NULL; i++ ) {
293
+ char *ext = ludp->lud_exts[ i ];
294
+ int crit = 0;
295
+
296
+ if (ext[0] == '!') {
297
+ crit++;
298
+ ext++;
299
+ }
300
+
301
+ if ( strncasecmp( ext, "x-timelimit=", STRLENOF( "x-timelimit=" ) ) == 0 ) {
302
+ if ( lutil_atoi( &timelimit, &ext[ STRLENOF( "x-timelimit=" ) ] ) && crit ) {
303
+ tester_error( "unable to parse critical extension x-timelimit" );
304
+ }
305
+
306
+ } else if ( strncasecmp( ext, "x-sizelimit=", STRLENOF( "x-sizelimit=" ) ) == 0 ) {
307
+ if ( lutil_atoi( &sizelimit, &ext[ STRLENOF( "x-sizelimit=" ) ] ) && crit ) {
308
+ tester_error( "unable to parse critical extension x-sizelimit" );
309
+ }
310
+
311
+ } else if ( crit ) {
312
+ tester_error( "unknown critical extension" );
313
+ }
314
+ }
315
+ }
316
+ } break;
317
+
318
+ default:
319
+ /* nothing to do yet */
320
+ break;
321
+ }
322
+
323
+ if ( maxloop > 1 ) {
324
+ fprintf( stderr, "PID=%ld - Bind(%d): dn=\"%s\".\n",
325
+ (long) pid, maxloop, dn );
326
+ }
327
+
328
+ for ( i = 0; i < maxloop; i++ ) {
329
+ if ( !noinit || ld == NULL ) {
330
+ int version = LDAP_VERSION3;
331
+ ldap_initialize( &ld, uri );
332
+ if ( ld == NULL ) {
333
+ tester_perror( "ldap_initialize", NULL );
334
+ rc = -1;
335
+ break;
336
+ }
337
+
338
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
339
+ &version );
340
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
341
+ chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
342
+ }
343
+
344
+ rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
345
+ if ( rc ) {
346
+ int first = tester_ignore_err( rc );
347
+
348
+ /* if ignore.. */
349
+ if ( first ) {
350
+ /* only log if first occurrence */
351
+ if ( ( force < 2 && first > 0 ) || abs(first) == 1 ) {
352
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
353
+ }
354
+ rc = LDAP_SUCCESS;
355
+
356
+ } else {
357
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
358
+ }
359
+ }
360
+
361
+ switch ( action_type ) {
362
+ case -1:
363
+ break;
364
+
365
+ case TESTER_SEARCH:
366
+ {
367
+ LDAPURLDesc *ludp = (LDAPURLDesc *)action;
368
+ LDAPMessage *res = NULL;
369
+ struct timeval tv = { 0 }, *tvp = NULL;
370
+
371
+ if ( timelimit ) {
372
+ tv.tv_sec = timelimit;
373
+ tvp = &tv;
374
+ }
375
+
376
+ assert( action != NULL );
377
+
378
+ rc = ldap_search_ext_s( ld,
379
+ ludp->lud_dn, ludp->lud_scope,
380
+ ludp->lud_filter, ludp->lud_attrs, 0,
381
+ NULL, NULL, tvp, sizelimit, &res );
382
+ ldap_msgfree( res );
383
+ } break;
384
+
385
+ default:
386
+ /* nothing to do yet */
387
+ break;
388
+ }
389
+
390
+ if ( !noinit ) {
391
+ ldap_unbind_ext( ld, NULL, NULL );
392
+ ld = NULL;
393
+ }
394
+
395
+ if ( rc != LDAP_SUCCESS ) {
396
+ break;
397
+ }
398
+ }
399
+
400
+ if ( maxloop > 1 ) {
401
+ fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
402
+ }
403
+
404
+ if ( ldp && noinit ) {
405
+ *ldp = ld;
406
+
407
+ } else if ( ld != NULL ) {
408
+ ldap_unbind_ext( ld, NULL, NULL );
409
+ }
410
+
411
+ return rc;
412
+ }
413
+
414
+
415
+ static int
416
+ do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr,
417
+ int maxloop, int force, int chaserefs, int noinit, int delay,
418
+ int action_type, void *action )
419
+ {
420
+ LDAP *ld = NULL;
421
+ int i = 0;
422
+ int rc = LDAP_SUCCESS;
423
+ ber_int_t msgid;
424
+ LDAPMessage *res, *msg;
425
+ char **dns = NULL;
426
+ struct berval *creds = NULL;
427
+ char *attrs[] = { LDAP_NO_ATTRS, NULL };
428
+ int ndns = 0;
429
+ #ifdef _WIN32
430
+ DWORD beg, end;
431
+ #else
432
+ struct timeval beg, end;
433
+ #endif
434
+ int version = LDAP_VERSION3;
435
+ char *nullstr = "";
436
+
437
+ ldap_initialize( &ld, uri );
438
+ if ( ld == NULL ) {
439
+ tester_perror( "ldap_initialize", NULL );
440
+ exit( EXIT_FAILURE );
441
+ }
442
+
443
+ (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
444
+ (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
445
+ chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
446
+
447
+ rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
448
+ if ( rc != LDAP_SUCCESS ) {
449
+ tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
450
+ exit( EXIT_FAILURE );
451
+ }
452
+
453
+ fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
454
+ (long) pid, maxloop, base, filter, pwattr );
455
+
456
+ if ( pwattr != NULL ) {
457
+ attrs[ 0 ] = pwattr;
458
+ }
459
+ rc = ldap_search_ext( ld, base, LDAP_SCOPE_SUBTREE,
460
+ filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
461
+ if ( rc != LDAP_SUCCESS ) {
462
+ tester_ldap_error( ld, "ldap_search_ext", NULL );
463
+ exit( EXIT_FAILURE );
464
+ }
465
+
466
+ while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 )
467
+ {
468
+ BerElement *ber;
469
+ struct berval bv;
470
+ int done = 0;
471
+
472
+ for ( msg = ldap_first_message( ld, res ); msg;
473
+ msg = ldap_next_message( ld, msg ) )
474
+ {
475
+ switch ( ldap_msgtype( msg ) ) {
476
+ case LDAP_RES_SEARCH_ENTRY:
477
+ rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
478
+ dns = realloc( dns, (ndns + 1)*sizeof(char *) );
479
+ dns[ndns] = ber_strdup( bv.bv_val );
480
+ if ( pwattr != NULL ) {
481
+ struct berval **values = ldap_get_values_len( ld, msg, pwattr );
482
+
483
+ creds = realloc( creds, (ndns + 1)*sizeof(struct berval) );
484
+ if ( values == NULL ) {
485
+ novals:;
486
+ creds[ndns].bv_len = 0;
487
+ creds[ndns].bv_val = nullstr;
488
+
489
+ } else {
490
+ static struct berval cleartext = BER_BVC( "{CLEARTEXT} " );
491
+ struct berval value = *values[ 0 ];
492
+
493
+ if ( value.bv_val[ 0 ] == '{' ) {
494
+ char *end = ber_bvchr( &value, '}' );
495
+
496
+ if ( end ) {
497
+ if ( ber_bvcmp( &value, &cleartext ) == 0 ) {
498
+ value.bv_val += cleartext.bv_len;
499
+ value.bv_len -= cleartext.bv_len;
500
+
501
+ } else {
502
+ ldap_value_free_len( values );
503
+ goto novals;
504
+ }
505
+ }
506
+
507
+ }
508
+
509
+ ber_dupbv( &creds[ndns], &value );
510
+ ldap_value_free_len( values );
511
+ }
512
+ }
513
+ ndns++;
514
+ ber_free( ber, 0 );
515
+ break;
516
+
517
+ case LDAP_RES_SEARCH_RESULT:
518
+ done = 1;
519
+ break;
520
+ }
521
+ if ( done )
522
+ break;
523
+ }
524
+ ldap_msgfree( res );
525
+ if ( done ) break;
526
+ }
527
+
528
+ #ifdef _WIN32
529
+ beg = GetTickCount();
530
+ #else
531
+ gettimeofday( &beg, NULL );
532
+ #endif
533
+
534
+ if ( ndns == 0 ) {
535
+ tester_error( "No DNs" );
536
+ return 1;
537
+ }
538
+
539
+ fprintf( stderr, " PID=%ld - Bind base=\"%s\" filter=\"%s\" got %d values.\n",
540
+ (long) pid, base, filter, ndns );
541
+
542
+ /* Ok, got list of DNs, now start binding to each */
543
+ for ( i = 0; i < maxloop; i++ ) {
544
+ int j;
545
+ struct berval cred = { 0, NULL };
546
+
547
+
548
+ #if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */
549
+ j = rand() % ndns;
550
+ #endif
551
+ j = ((double)ndns)*rand()/(RAND_MAX + 1.0);
552
+
553
+ if ( creds && !BER_BVISEMPTY( &creds[j] ) ) {
554
+ cred = creds[j];
555
+ }
556
+
557
+ if ( do_bind( uri, dns[j], &cred, 1, force, chaserefs, noinit, &ld,
558
+ action_type, action ) && !force )
559
+ {
560
+ break;
561
+ }
562
+
563
+ if ( delay ) {
564
+ sleep( delay );
565
+ }
566
+ }
567
+
568
+ if ( ld != NULL ) {
569
+ ldap_unbind_ext( ld, NULL, NULL );
570
+ ld = NULL;
571
+ }
572
+
573
+ #ifdef _WIN32
574
+ end = GetTickCount();
575
+ end -= beg;
576
+
577
+ fprintf( stderr, " PID=%ld - Bind done %d in %d.%03d seconds.\n",
578
+ (long) pid, i, end / 1000, end % 1000 );
579
+ #else
580
+ gettimeofday( &end, NULL );
581
+ end.tv_usec -= beg.tv_usec;
582
+ if (end.tv_usec < 0 ) {
583
+ end.tv_usec += 1000000;
584
+ end.tv_sec -= 1;
585
+ }
586
+ end.tv_sec -= beg.tv_sec;
587
+
588
+ fprintf( stderr, " PID=%ld - Bind done %d in %ld.%06ld seconds.\n",
589
+ (long) pid, i, (long) end.tv_sec, (long) end.tv_usec );
590
+ #endif
591
+
592
+ if ( dns ) {
593
+ for ( i = 0; i < ndns; i++ ) {
594
+ ber_memfree( dns[i] );
595
+ }
596
+ free( dns );
597
+ }
598
+
599
+ if ( creds ) {
600
+ for ( i = 0; i < ndns; i++ ) {
601
+ if ( creds[i].bv_val != nullstr ) {
602
+ ber_memfree( creds[i].bv_val );
603
+ }
604
+ }
605
+ free( creds );
606
+ }
607
+
608
+ return 0;
609
+ }