2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2006 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
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>.
16 * This work was initially developed by Howard Chu for inclusion
17 * in OpenLDAP Software.
24 #include <ac/stdlib.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
38 #include "slapd-common.h"
43 do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
44 int force, int chaserefs, int noinit, LDAP **ldp );
47 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
48 int force, int chaserefs, int noinit, int delay );
50 /* This program can be invoked two ways: if -D is used to specify a Bind DN,
51 * that DN will be used repeatedly for all of the Binds. If instead -b is used
52 * to specify a base DN, a search will be done for all "person" objects under
53 * that base DN. Then DNs from this list will be randomly selected for each
54 * Bind request. All of the users must have identical passwords. Also it is
55 * assumed that the users are all onelevel children of the base.
60 fprintf( stderr, "usage: %s "
63 "(-D <dn>|-b <baseDN> [-f <searchfilter>]) "
75 static char *filter = "(objectClass=person)";
78 main( int argc, char **argv )
82 char *host = "localhost";
84 struct berval base = { 0, NULL };
85 struct berval pass = { 0, NULL };
94 tester_init( "slapd-bind" );
96 while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
98 case 'b': /* base DN of a tree of user DNs */
99 ber_str2bv( optarg, 0, 0, &base );
106 case 'H': /* the server uri */
107 uri = strdup( optarg );
110 case 'h': /* the servers host */
111 host = strdup( optarg );
114 case 'p': /* the servers port */
115 if ( lutil_atoi( &port, optarg ) != 0 ) {
121 dn = strdup( optarg );
125 pass.bv_val = strdup( optarg );
126 pass.bv_len = strlen( optarg );
129 case 'l': /* the number of loops */
130 if ( lutil_atoi( &loops, optarg ) != 0 ) {
135 case 'L': /* the number of outerloops */
136 if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
150 /* reuse connection */
155 /* sleep between binds */
156 if ( lutil_atoi( &delay, optarg ) != 0 ) {
167 if ( port == -1 && uri == NULL ) {
171 uri = tester_uri( uri, host, port );
173 for ( i = 0; i < outerloops; i++ ) {
174 if ( base.bv_val != NULL ) {
175 do_base( uri, &base, &pass, loops,
176 force, chaserefs, noinit, delay );
178 do_bind( uri, dn, &pass, loops,
179 force, chaserefs, noinit, NULL );
183 exit( EXIT_SUCCESS );
188 do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
189 int force, int chaserefs, int noinit, LDAP **ldp )
191 LDAP *ld = ldp ? *ldp : NULL;
192 int i, first = 1, rc = -1;
193 pid_t pid = getpid();
196 fprintf( stderr, "PID=%ld - Bind(%d): dn=\"%s\".\n",
197 (long) pid, maxloop, dn );
199 for ( i = 0; i < maxloop; i++ ) {
200 if ( !noinit || ld == NULL ) {
201 int version = LDAP_VERSION3;
202 ldap_initialize( &ld, uri );
204 tester_perror( "ldap_initialize", NULL );
209 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
211 (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
212 chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
215 rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
220 case LDAP_INVALID_CREDENTIALS:
221 /* don't log: it's intended */
231 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
235 ldap_unbind_ext( ld, NULL, NULL );
238 if ( rc != LDAP_SUCCESS && !force ) {
244 fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
250 } else if ( ld != NULL ) {
251 ldap_unbind_ext( ld, NULL, NULL );
259 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
260 int force, int chaserefs, int noinit, int delay )
264 pid_t pid = getpid();
265 int rc = LDAP_SUCCESS;
267 LDAPMessage *res, *msg;
268 struct berval *rdns = NULL;
269 char *attrs[] = { LDAP_NO_ATTRS, NULL };
274 struct timeval beg, end;
276 int version = LDAP_VERSION3;
277 struct berval pw = { 0, NULL };
281 ldap_initialize( &ld, uri );
283 tester_perror( "ldap_initialize", NULL );
284 exit( EXIT_FAILURE );
287 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
288 (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
289 chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
291 rc = ldap_sasl_bind_s( ld, NULL, LDAP_SASL_SIMPLE, &pw, NULL, NULL, NULL );
292 if ( rc != LDAP_SUCCESS ) {
293 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
294 exit( EXIT_FAILURE );
297 rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_ONE,
298 filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
299 if ( rc != LDAP_SUCCESS ) {
300 tester_ldap_error( ld, "ldap_search_ext", NULL );
301 exit( EXIT_FAILURE );
304 while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
310 for (msg = ldap_first_message( ld, res ); msg;
311 msg = ldap_next_message( ld, msg )) {
312 switch ( ldap_msgtype( msg )) {
313 case LDAP_RES_SEARCH_ENTRY:
314 rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
315 ptr = strchr( bv.bv_val, ',');
316 assert( ptr != NULL );
317 bv.bv_len = ptr - bv.bv_val + 1;
318 rdns = realloc( rdns, (nrdns+1)*sizeof(struct berval));
319 ber_dupbv( &rdns[nrdns], &bv );
323 case LDAP_RES_SEARCH_RESULT:
335 beg = GetTickCount();
337 gettimeofday( &beg, NULL );
341 tester_error( "No RDNs" );
345 /* Ok, got list of RDNs, now start binding to each */
346 for ( i = 0; i < maxloop; i++ ) {
347 char dn[BUFSIZ], *ptr;
350 for ( j = 0, k = 0; k < nrdns; k++) {
352 if ( base->bv_len + rdns[j].bv_len < sizeof( dn ) ) {
361 ptr = lutil_strcopy(dn, rdns[j].bv_val);
362 strcpy(ptr, base->bv_val);
363 if ( do_bind( uri, dn, pass, 1, force, chaserefs, noinit, &ld )
375 ldap_unbind_ext( ld, NULL, NULL );
380 end = GetTickCount();
383 fprintf( stderr, "Done %d Binds in %d.%03d seconds.\n", i,
384 end / 1000, end % 1000 );
386 gettimeofday( &end, NULL );
387 end.tv_usec -= beg.tv_usec;
388 if (end.tv_usec < 0 ) {
389 end.tv_usec += 1000000;
392 end.tv_sec -= beg.tv_sec;
394 fprintf( stderr, "Done %d Binds in %ld.%06ld seconds.\n", i,
395 (long) end.tv_sec, (long) end.tv_usec );
399 for ( i = 0; i < nrdns; i++ ) {
400 free( rdns[i].bv_val );