]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-bind.c
refine previous commits
[openldap] / tests / progs / slapd-bind.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2006 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
38 #include "slapd-common.h"
39
40 #define LOOPS   100
41
42 static int
43 do_bind( char *uri, char *dn, struct berval *pass, int maxloop, int force, int noinit, LDAP **ldp );
44
45 static int
46 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop, int force, int noinit, int delay );
47
48 /* This program can be invoked two ways: if -D is used to specify a Bind DN,
49  * that DN will be used repeatedly for all of the Binds. If instead -b is used
50  * to specify a base DN, a search will be done for all "person" objects under
51  * that base DN. Then DNs from this list will be randomly selected for each
52  * Bind request. All of the users must have identical passwords. Also it is
53  * assumed that the users are all onelevel children of the base.
54  */
55 static void
56 usage( char *name )
57 {
58         fprintf( stderr, "usage: %s [-h <host>] -p port (-D <dn>|-b <baseDN> [-f <searchfilter>]) -w <passwd> [-l <loops>] [-F] [-I] [-t delay]\n",
59                         name );
60         exit( EXIT_FAILURE );
61 }
62
63 static char *filter = "(objectClass=person)";
64
65 int
66 main( int argc, char **argv )
67 {
68         int             i;
69         char            *uri = NULL;
70         char            *host = "localhost";
71         char            *dn = NULL;
72         struct berval   base = { 0, NULL };
73         struct berval   pass = { 0, NULL };
74         int             port = -1;
75         int             loops = LOOPS;
76         int             force = 0;
77         int             noinit = 0;
78         int             delay = 0;
79
80         tester_init( "slapd-bind" );
81
82         while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:f:FIt:" )) != EOF ) {
83                 switch( i ) {
84                         case 'b':               /* base DN of a tree of user DNs */
85                                 ber_str2bv( optarg, 0, 0, &base );
86                                 break;
87
88                         case 'H':               /* the server uri */
89                                 uri = strdup( optarg );
90                                 break;
91
92                         case 'h':               /* the servers host */
93                                 host = strdup( optarg );
94                                 break;
95
96                         case 'p':               /* the servers port */
97                                 if ( lutil_atoi( &port, optarg ) != 0 ) {
98                                         usage( argv[0] );
99                                 }
100                                 break;
101
102                         case 'D':
103                                 dn = strdup( optarg );
104                                 break;
105
106                         case 'w':
107                                 pass.bv_val = strdup( optarg );
108                                 pass.bv_len = strlen( optarg );
109                                 break;
110
111                         case 'l':               /* the number of loops */
112                                 if ( lutil_atoi( &loops, optarg ) != 0 ) {
113                                         usage( argv[0] );
114                                 }
115                                 break;
116
117                         case 'f':
118                                 filter = optarg;
119                                 break;
120
121                         case 'F':
122                                 force++;
123                                 break;
124
125                         case 'I':
126                                 /* reuse connection */
127                                 noinit++;
128                                 break;
129
130                         case 't':
131                                 /* sleep between binds */
132                                 if ( lutil_atoi( &delay, optarg ) != 0 ) {
133                                         usage( argv[0] );
134                                 }
135                                 break;
136
137                         default:
138                                 usage( argv[0] );
139                                 break;
140                 }
141         }
142
143         if ( port == -1 && uri == NULL ) {
144                 usage( argv[0] );
145         }
146
147         uri = tester_uri( uri, host, port );
148
149         if ( base.bv_val != NULL ) {
150                 do_base( uri, &base, &pass, ( 20 * loops ), force, noinit, delay );
151         } else {
152                 do_bind( uri, dn, &pass, ( 20 * loops ), force, noinit, NULL );
153         }
154         exit( EXIT_SUCCESS );
155 }
156
157
158 static int
159 do_bind( char *uri, char *dn, struct berval *pass, int maxloop, int force, int noinit, LDAP **ldp )
160 {
161         LDAP    *ld = ldp ? *ldp : NULL;
162         int     i, first = 1, rc = -1;
163         pid_t   pid = getpid();
164
165         if ( maxloop > 1 )
166                 fprintf( stderr, "PID=%ld - Bind(%d): dn=\"%s\".\n",
167                          (long) pid, maxloop, dn );
168
169         for ( i = 0; i < maxloop; i++ ) {
170                 if ( !noinit || ld == NULL ) {
171                         int version = LDAP_VERSION3;
172                         ldap_initialize( &ld, uri );
173                         if ( ld == NULL ) {
174                                 tester_perror( "ldap_initialize" );
175                                 rc = -1;
176                                 break;
177                         }
178
179                         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
180                                 &version ); 
181                 }
182
183                 rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
184                 switch ( rc ) {
185                 case LDAP_SUCCESS:
186                         break;
187
188                 case LDAP_INVALID_CREDENTIALS:
189                         /* don't log: it's intended */
190                         if ( force >= 2 ) {
191                                 if ( !first ) {
192                                         break;
193                                 }
194                                 first = 0;
195                         }
196                         /* fallthru */
197
198                 default:
199                         tester_ldap_error( ld, "ldap_sasl_bind_s" );
200                 }
201
202                 if ( !noinit ) {
203                         ldap_unbind_ext( ld, NULL, NULL );
204                         ld = NULL;
205                 }
206                 if ( rc != LDAP_SUCCESS && !force ) {
207                         break;
208                 }
209         }
210
211         if ( maxloop > 1 ) {
212                 fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
213         }
214
215         if ( ldp ) {
216                 *ldp = ld;
217
218         } else if ( ld != NULL ) {
219                 ldap_unbind_ext( ld, NULL, NULL );
220         }
221
222         return rc;
223 }
224
225
226 static int
227 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop, int force, int noinit, int delay )
228 {
229         LDAP    *ld = NULL;
230         int     i = 0;
231         pid_t   pid = getpid();
232         int     rc = LDAP_SUCCESS;
233         ber_int_t msgid;
234         LDAPMessage *res, *msg;
235         struct berval *rdns = NULL;
236         char *attrs[] = { LDAP_NO_ATTRS, NULL };
237         int nrdns = 0;
238 #ifdef _WIN32
239         DWORD beg, end;
240 #else
241         struct timeval beg, end;
242 #endif
243         int version = LDAP_VERSION3;
244         struct berval pw = { 0, NULL };
245
246         srand(pid);
247
248         ldap_initialize( &ld, uri );
249         if ( ld == NULL ) {
250                 tester_perror( "ldap_initialize" );
251                 exit( EXIT_FAILURE );
252         }
253
254         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
255         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
256
257         rc = ldap_sasl_bind_s( ld, NULL, LDAP_SASL_SIMPLE, &pw, NULL, NULL, NULL );
258         if ( rc != LDAP_SUCCESS ) {
259                 tester_ldap_error( ld, "ldap_sasl_bind_s" );
260                 exit( EXIT_FAILURE );
261         }
262
263         rc = ldap_search_ext( ld, base->bv_val, LDAP_SCOPE_ONE,
264                         filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
265         if ( rc != LDAP_SUCCESS ) {
266                 tester_ldap_error( ld, "ldap_search_ext" );
267                 exit( EXIT_FAILURE );
268         }
269
270         while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
271                 BerElement *ber;
272                 struct berval bv;
273                 char *ptr;
274                 int done = 0;
275
276                 for (msg = ldap_first_message( ld, res ); msg;
277                         msg = ldap_next_message( ld, msg )) {
278                         switch ( ldap_msgtype( msg )) {
279                         case LDAP_RES_SEARCH_ENTRY:
280                                 rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
281                                 ptr = strchr( bv.bv_val, ',');
282                                 assert( ptr != NULL );
283                                 bv.bv_len = ptr - bv.bv_val + 1;
284                                 rdns = realloc( rdns, (nrdns+1)*sizeof(struct berval));
285                                 ber_dupbv( &rdns[nrdns], &bv );
286                                 nrdns++;
287                                 ber_free( ber, 0 );
288                                 break;
289                         case LDAP_RES_SEARCH_RESULT:
290                                 done = 1;
291                                 break;
292                         }
293                         if ( done )
294                                 break;
295                 }
296                 ldap_msgfree( res );
297                 if ( done ) break;
298         }
299
300 #ifdef _WIN32
301         beg = GetTickCount();
302 #else
303         gettimeofday( &beg, NULL );
304 #endif
305
306         if ( nrdns == 0 ) {
307                 tester_error( "No RDNs" );
308                 return 1;
309         }
310
311         /* Ok, got list of RDNs, now start binding to each */
312         for ( i = 0; i < maxloop; i++ ) {
313                 char dn[BUFSIZ], *ptr;
314                 int j, k;
315
316                 for ( k = 0; k < nrdns; k++) {
317                         j = rand() % nrdns;
318                         if ( base->bv_len + rdns[j].bv_len < sizeof( dn ) ) {
319                                 break;
320                         }
321                 }
322
323                 if ( k == nrdns ) {
324                         
325                 }
326                 
327                 ptr = lutil_strcopy(dn, rdns[j].bv_val);
328                 strcpy(ptr, base->bv_val);
329                 if ( do_bind( uri, dn, pass, 1, force, noinit, &ld ) && !force ) {
330                         break;
331                 }
332
333                 if ( delay ) {
334                         sleep( delay );
335                 }
336         }
337
338         if ( ld != NULL ) {
339                 ldap_unbind_ext( ld, NULL, NULL );
340                 ld = NULL;
341         }
342
343 #ifdef _WIN32
344         end = GetTickCount();
345         end -= beg;
346
347         fprintf( stderr, "Done %d Binds in %d.%03d seconds.\n", i,
348                 end / 1000, end % 1000 );
349 #else
350         gettimeofday( &end, NULL );
351         end.tv_usec -= beg.tv_usec;
352         if (end.tv_usec < 0 ) {
353                 end.tv_usec += 1000000;
354                 end.tv_sec -= 1;
355         }
356         end.tv_sec -= beg.tv_sec;
357
358         fprintf( stderr, "Done %d Binds in %ld.%06ld seconds.\n", i,
359                 (long) end.tv_sec, (long) end.tv_usec );
360 #endif
361
362         if ( rdns ) {
363                 for ( i = 0; i < nrdns; i++ ) {
364                         free( rdns[i].bv_val );
365                 }
366                 free( rdns );
367         }
368
369         return 0;
370 }