]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-bind.c
silence warning
[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,
44         int force, int chaserefs, int noinit, LDAP **ldp );
45
46 static int
47 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
48         int force, int chaserefs, int noinit, int delay );
49
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.
56  */
57 static void
58 usage( char *name )
59 {
60         fprintf( stderr, "usage: %s "
61                 "[-h <host>] "
62                 "-p port "
63                 "(-D <dn>|-b <baseDN> [-f <searchfilter>]) "
64                 "-w <passwd> "
65                 "[-l <loops>] "
66                 "[-L <outerloops>] "
67                 "[-F] "
68                 "[-C] "
69                 "[-I] "
70                 "[-t delay]\n",
71                 name );
72         exit( EXIT_FAILURE );
73 }
74
75 static char *filter = "(objectClass=person)";
76
77 int
78 main( int argc, char **argv )
79 {
80         int             i;
81         char            *uri = NULL;
82         char            *host = "localhost";
83         char            *dn = NULL;
84         struct berval   base = { 0, NULL };
85         struct berval   pass = { 0, NULL };
86         int             port = -1;
87         int             loops = LOOPS;
88         int             outerloops = 1;
89         int             force = 0;
90         int             chaserefs = 0;
91         int             noinit = 0;
92         int             delay = 0;
93
94         tester_init( "slapd-bind" );
95
96         while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:L:f:FIt:" )) != EOF ) {
97                 switch( i ) {
98                 case 'b':               /* base DN of a tree of user DNs */
99                         ber_str2bv( optarg, 0, 0, &base );
100                         break;
101
102                 case 'C':
103                         chaserefs++;
104                         break;
105
106                 case 'H':               /* the server uri */
107                         uri = strdup( optarg );
108                         break;
109
110                 case 'h':               /* the servers host */
111                         host = strdup( optarg );
112                         break;
113
114                 case 'p':               /* the servers port */
115                         if ( lutil_atoi( &port, optarg ) != 0 ) {
116                                 usage( argv[0] );
117                         }
118                         break;
119
120                 case 'D':
121                         dn = strdup( optarg );
122                         break;
123
124                 case 'w':
125                         pass.bv_val = strdup( optarg );
126                         pass.bv_len = strlen( optarg );
127                         break;
128
129                 case 'l':               /* the number of loops */
130                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
131                                 usage( argv[0] );
132                         }
133                         break;
134
135                 case 'L':               /* the number of outerloops */
136                         if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
137                                 usage( argv[0] );
138                         }
139                         break;
140
141                 case 'f':
142                         filter = optarg;
143                         break;
144
145                 case 'F':
146                         force++;
147                         break;
148
149                 case 'I':
150                         /* reuse connection */
151                         noinit++;
152                         break;
153
154                 case 't':
155                         /* sleep between binds */
156                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
157                                 usage( argv[0] );
158                         }
159                         break;
160
161                 default:
162                         usage( argv[0] );
163                         break;
164                 }
165         }
166
167         if ( port == -1 && uri == NULL ) {
168                 usage( argv[0] );
169         }
170
171         uri = tester_uri( uri, host, port );
172
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 );
177                 } else {
178                         do_bind( uri, dn, &pass, loops,
179                                 force, chaserefs, noinit, NULL );
180                 }
181         }
182
183         exit( EXIT_SUCCESS );
184 }
185
186
187 static int
188 do_bind( char *uri, char *dn, struct berval *pass, int maxloop,
189         int force, int chaserefs, int noinit, LDAP **ldp )
190 {
191         LDAP    *ld = ldp ? *ldp : NULL;
192         int     i, first = 1, rc = -1;
193         pid_t   pid = getpid();
194
195         if ( maxloop > 1 )
196                 fprintf( stderr, "PID=%ld - Bind(%d): dn=\"%s\".\n",
197                          (long) pid, maxloop, dn );
198
199         for ( i = 0; i < maxloop; i++ ) {
200                 if ( !noinit || ld == NULL ) {
201                         int version = LDAP_VERSION3;
202                         ldap_initialize( &ld, uri );
203                         if ( ld == NULL ) {
204                                 tester_perror( "ldap_initialize" );
205                                 rc = -1;
206                                 break;
207                         }
208
209                         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
210                                 &version ); 
211                         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
212                                 chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
213                 }
214
215                 rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
216                 switch ( rc ) {
217                 case LDAP_SUCCESS:
218                         break;
219
220                 case LDAP_INVALID_CREDENTIALS:
221                         /* don't log: it's intended */
222                         if ( force >= 2 ) {
223                                 if ( !first ) {
224                                         break;
225                                 }
226                                 first = 0;
227                         }
228                         /* fallthru */
229
230                 default:
231                         tester_ldap_error( ld, "ldap_sasl_bind_s" );
232                 }
233
234                 if ( !noinit ) {
235                         ldap_unbind_ext( ld, NULL, NULL );
236                         ld = NULL;
237                 }
238                 if ( rc != LDAP_SUCCESS && !force ) {
239                         break;
240                 }
241         }
242
243         if ( maxloop > 1 ) {
244                 fprintf( stderr, " PID=%ld - Bind done (%d).\n", (long) pid, rc );
245         }
246
247         if ( ldp ) {
248                 *ldp = ld;
249
250         } else if ( ld != NULL ) {
251                 ldap_unbind_ext( ld, NULL, NULL );
252         }
253
254         return rc;
255 }
256
257
258 static int
259 do_base( char *uri, struct berval *base, struct berval *pass, int maxloop,
260         int force, int chaserefs, int noinit, int delay )
261 {
262         LDAP    *ld = NULL;
263         int     i = 0;
264         pid_t   pid = getpid();
265         int     rc = LDAP_SUCCESS;
266         ber_int_t msgid;
267         LDAPMessage *res, *msg;
268         struct berval *rdns = NULL;
269         char *attrs[] = { LDAP_NO_ATTRS, NULL };
270         int nrdns = 0;
271 #ifdef _WIN32
272         DWORD beg, end;
273 #else
274         struct timeval beg, end;
275 #endif
276         int version = LDAP_VERSION3;
277         struct berval pw = { 0, NULL };
278
279         srand(pid);
280
281         ldap_initialize( &ld, uri );
282         if ( ld == NULL ) {
283                 tester_perror( "ldap_initialize" );
284                 exit( EXIT_FAILURE );
285         }
286
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 );
290
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" );
294                 exit( EXIT_FAILURE );
295         }
296
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" );
301                 exit( EXIT_FAILURE );
302         }
303
304         while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
305                 BerElement *ber;
306                 struct berval bv;
307                 char *ptr;
308                 int done = 0;
309
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 );
320                                 nrdns++;
321                                 ber_free( ber, 0 );
322                                 break;
323                         case LDAP_RES_SEARCH_RESULT:
324                                 done = 1;
325                                 break;
326                         }
327                         if ( done )
328                                 break;
329                 }
330                 ldap_msgfree( res );
331                 if ( done ) break;
332         }
333
334 #ifdef _WIN32
335         beg = GetTickCount();
336 #else
337         gettimeofday( &beg, NULL );
338 #endif
339
340         if ( nrdns == 0 ) {
341                 tester_error( "No RDNs" );
342                 return 1;
343         }
344
345         /* Ok, got list of RDNs, now start binding to each */
346         for ( i = 0; i < maxloop; i++ ) {
347                 char dn[BUFSIZ], *ptr;
348                 int j, k;
349
350                 for ( j = 0, k = 0; k < nrdns; k++) {
351                         j = rand() % nrdns;
352                         if ( base->bv_len + rdns[j].bv_len < sizeof( dn ) ) {
353                                 break;
354                         }
355                 }
356
357                 if ( k == nrdns ) {
358                         
359                 }
360                 
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 )
364                         && !force )
365                 {
366                         break;
367                 }
368
369                 if ( delay ) {
370                         sleep( delay );
371                 }
372         }
373
374         if ( ld != NULL ) {
375                 ldap_unbind_ext( ld, NULL, NULL );
376                 ld = NULL;
377         }
378
379 #ifdef _WIN32
380         end = GetTickCount();
381         end -= beg;
382
383         fprintf( stderr, "Done %d Binds in %d.%03d seconds.\n", i,
384                 end / 1000, end % 1000 );
385 #else
386         gettimeofday( &end, NULL );
387         end.tv_usec -= beg.tv_usec;
388         if (end.tv_usec < 0 ) {
389                 end.tv_usec += 1000000;
390                 end.tv_sec -= 1;
391         }
392         end.tv_sec -= beg.tv_sec;
393
394         fprintf( stderr, "Done %d Binds in %ld.%06ld seconds.\n", i,
395                 (long) end.tv_sec, (long) end.tv_usec );
396 #endif
397
398         if ( rdns ) {
399                 for ( i = 0; i < nrdns; i++ ) {
400                         free( rdns[i].bv_val );
401                 }
402                 free( rdns );
403         }
404
405         return 0;
406 }