]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-bind.c
add bind to stress tests
[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 #define LOOPS   100
39
40 static void
41 do_error( LDAP *ld, const char *func )
42 {
43         int err;
44         const char *text = "Success";
45
46         ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&err );
47         if ( err != LDAP_SUCCESS ) {
48                 ldap_get_option( ld, LDAP_OPT_ERROR_STRING, (void *)&text );
49         }
50
51         fprintf( stderr, "%s: (%d) %s\n", func, err, text == NULL ? "" : text );
52 }
53
54 static int
55 do_bind( char *uri, char *dn, struct berval *pass, int maxloop, int force );
56
57 static int
58 do_base( char *uri, char *base, struct berval *pass, int maxloop, int force );
59
60 /* This program can be invoked two ways: if -D is used to specify a Bind DN,
61  * that DN will be used repeatedly for all of the Binds. If instead -b is used
62  * to specify a base DN, a search will be done for all "person" objects under
63  * that base DN. Then DNs from this list will be randomly selected for each
64  * Bind request. All of the users must have identical passwords. Also it is
65  * assumed that the users are all onelevel children of the base.
66  */
67 static void
68 usage( char *name )
69 {
70         fprintf( stderr, "usage: %s [-h <host>] -p port (-D <dn>|-b <baseDN> [-f <searchfilter>]) -w <passwd> [-l <loops>] [-F]\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                         uribuf[ BUFSIZ ];
83         char            *host = "localhost";
84         char            *dn = NULL;
85         char            *base = NULL;
86         struct berval   pass = { 0, NULL };
87         int             port = -1;
88         int             loops = LOOPS;
89         int             force = 0;
90
91         while ( (i = getopt( argc, argv, "b:H:h:p:D:w:l:f:F" )) != EOF ) {
92                 switch( i ) {
93                         case 'b':               /* base DN of a tree of user DNs */
94                                 base = strdup( optarg );
95                                 break;
96
97                         case 'H':               /* the server uri */
98                                 uri = strdup( optarg );
99                                 break;
100
101                         case 'h':               /* the servers host */
102                                 host = strdup( optarg );
103                                 break;
104
105                         case 'p':               /* the servers port */
106                                 if ( lutil_atoi( &port, optarg ) != 0 ) {
107                                         usage( argv[0] );
108                                 }
109                                 break;
110
111                         case 'D':
112                                 dn = strdup( optarg );
113                                 break;
114
115                         case 'w':
116                                 pass.bv_val = strdup( optarg );
117                                 pass.bv_len = strlen( optarg );
118                                 break;
119
120                         case 'l':               /* the number of loops */
121                                 if ( lutil_atoi( &loops, optarg ) != 0 ) {
122                                         usage( argv[0] );
123                                 }
124                                 break;
125
126                         case 'f':
127                                 filter = optarg;
128                                 break;
129
130                         case 'F':
131                                 force = 1;
132                                 break;
133
134                         default:
135                                 usage( argv[0] );
136                                 break;
137                 }
138         }
139
140         if ( port == -1 && uri == NULL ) {
141                 usage( argv[0] );
142         }
143
144         if ( uri == NULL ) {
145                 snprintf( uribuf, sizeof( uribuf ), "ldap://%s:%d", host, port );
146                 uri = uribuf;
147         }
148
149         if ( base ) {
150                 do_base( uri, base, &pass, ( 20 * loops ), force );
151         } else {
152                 do_bind( uri, dn, &pass, ( 20 * loops ), force );
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 )
160 {
161         LDAP    *ld = NULL;
162         int     i, 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                 ldap_initialize( &ld, uri );
171                 if ( ld == NULL ) {
172                         perror( "ldap_initialize" );
173                         rc = -1;
174                         break;
175                 }
176
177                 {
178                         int version = LDAP_VERSION3;
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                 if ( rc != LDAP_SUCCESS ) {
185                         do_error( ld, "ldap_bind" );
186                 }
187                 ldap_unbind_ext( ld, NULL, NULL );
188                 if ( rc != LDAP_SUCCESS && !force ) {
189                         break;
190                 }
191         }
192
193         if ( maxloop > 1 )
194                 fprintf( stderr, " PID=%ld - Bind done.\n", (long) pid );
195
196         return rc;
197 }
198
199
200 static int
201 do_base( char *uri, char *base, struct berval *pass, int maxloop, int force )
202 {
203         LDAP    *ld = NULL;
204         int     i = 0;
205         pid_t   pid = getpid();
206         int     rc = LDAP_SUCCESS;
207         ber_int_t msgid;
208         LDAPMessage *res, *msg;
209         char **rdns = NULL;
210         char *attrs[] = { "dn", NULL };
211         int nrdns = 0;
212 #ifdef _WIN32
213         DWORD beg, end;
214 #else
215         struct timeval beg, end;
216 #endif
217         int version = LDAP_VERSION3;
218
219         srand(pid);
220
221         ldap_initialize( &ld, uri );
222         if ( ld == NULL ) {
223                 perror( "ldap_initialize" );
224                 exit( EXIT_FAILURE );
225         }
226
227         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
228         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
229
230         rc = ldap_sasl_bind_s( ld, NULL, LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL );
231         if ( rc != LDAP_SUCCESS ) {
232                 do_error( ld, "ldap_bind" );
233                 exit( EXIT_FAILURE );
234         }
235
236         rc = ldap_search_ext( ld, base, LDAP_SCOPE_ONE,
237                         filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
238         if ( rc != LDAP_SUCCESS ) {
239                 do_error( ld, "ldap_search_ext" );
240                 exit( EXIT_FAILURE );
241         }
242
243         while (( rc=ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){
244                 BerElement *ber;
245                 struct berval bv;
246                 char *ptr;
247                 int done = 0;
248
249                 for (msg = ldap_first_message( ld, res ); msg;
250                         msg = ldap_next_message( ld, msg )) {
251                         switch ( ldap_msgtype( msg )) {
252                         case LDAP_RES_SEARCH_ENTRY:
253                                 rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
254                                 ptr = strchr( bv.bv_val, ',');
255                                 i = ptr-bv.bv_val;
256                                 rdns = realloc( rdns, (nrdns+1)*sizeof(char *));
257                                 rdns[nrdns] = malloc( i+1 );
258                                 strncpy(rdns[nrdns], bv.bv_val, i );
259                                 rdns[nrdns][i] = '\0';
260                                 nrdns++;
261                                 ber_free( ber, 0 );
262                                 break;
263                         case LDAP_RES_SEARCH_RESULT:
264                                 done = 1;
265                                 break;
266                         }
267                         if ( done )
268                                 break;
269                 }
270                 ldap_msgfree( res );
271                 if ( done ) break;
272         }
273         ldap_unbind_ext( ld, NULL, NULL );
274
275 #ifdef _WIN32
276         beg = GetTickCount();
277 #else
278         gettimeofday( &beg, NULL );
279 #endif
280
281         if ( nrdns == 0 ) {
282                 fprintf( stderr, "No RDNs.\n" );
283                 return 1;
284         }
285
286         /* Ok, got list of RDNs, now start binding to each */
287         for (i=0; i<maxloop; i++) {
288                 char dn[BUFSIZ], *ptr;
289                 int j = rand() % nrdns;
290                 ptr = lutil_strcopy(dn, rdns[j]);
291                 *ptr++ = ',';
292                 strcpy(ptr, base);
293                 if ( do_bind( uri, dn, pass, 1, force ) && !force )
294                         break;
295         }
296 #ifdef _WIN32
297         end = GetTickCount();
298         end -= beg;
299
300         fprintf( stderr, "Done %d Binds in %d.%03d seconds.\n", i,
301                 end / 1000, end % 1000 );
302 #else
303         gettimeofday( &end, NULL );
304         end.tv_usec -= beg.tv_usec;
305         if (end.tv_usec < 0 ) {
306                 end.tv_usec += 1000000;
307                 end.tv_sec -= 1;
308         }
309         end.tv_sec -= beg.tv_sec;
310
311         fprintf( stderr, "Done %d Binds in %ld.%06ld seconds.\n", i,
312                 (long) end.tv_sec, (long) end.tv_usec );
313 #endif
314         return 0;
315 }