]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-addel.c
Happy New Year
[openldap] / tests / progs / slapd-addel.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2018 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 Kurt Spanier for inclusion
17  * in OpenLDAP Software.
18  */
19  
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include "ac/stdlib.h"
25
26 #include "ac/ctype.h"
27 #include "ac/param.h"
28 #include "ac/socket.h"
29 #include "ac/string.h"
30 #include "ac/unistd.h"
31 #include "ac/wait.h"
32
33 #include "ldap.h"
34 #include "lutil.h"
35
36 #include "slapd-common.h"
37
38 #define LOOPS   100
39 #define RETRIES 0
40
41 static char *
42 get_add_entry( char *filename, LDAPMod ***mods );
43
44 static void
45 do_addel( char *uri, char *manager, struct berval *passwd,
46         char *dn, LDAPMod **attrs, int maxloop, int maxretries, int delay,
47         int friendly, int chaserefs );
48
49 static void
50 usage( char *name )
51 {
52         fprintf( stderr,
53                 "usage: %s "
54                 "-H <uri> | ([-h <host>] -p <port>) "
55                 "-D <manager> "
56                 "-w <passwd> "
57                 "-f <addfile> "
58                 "[-i <ignore>] "
59                 "[-l <loops>] "
60                 "[-L <outerloops>] "
61                 "[-r <maxretries>] "
62                 "[-t <delay>] "
63                 "[-F] "
64                 "[-C]\n",
65                         name );
66         exit( EXIT_FAILURE );
67 }
68
69 int
70 main( int argc, char **argv )
71 {
72         int             i;
73         char            *host = "localhost";
74         char            *uri = NULL;
75         int             port = -1;
76         char            *manager = NULL;
77         struct berval   passwd = { 0, NULL };
78         char            *filename = NULL;
79         char            *entry = NULL;
80         int             loops = LOOPS;
81         int             outerloops = 1;
82         int             retries = RETRIES;
83         int             delay = 0;
84         int             friendly = 0;
85         int             chaserefs = 0;
86         LDAPMod         **attrs = NULL;
87
88         tester_init( "slapd-addel", TESTER_ADDEL );
89
90         while ( ( i = getopt( argc, argv, "CD:Ff:H:h:i:L:l:p:r:t:w:" ) ) != EOF )
91         {
92                 switch ( i ) {
93                 case 'C':
94                         chaserefs++;
95                         break;
96
97                 case 'F':
98                         friendly++;
99                         break;
100                         
101                 case 'H':               /* the server's URI */
102                         uri = strdup( optarg );
103                         break;
104
105                 case 'h':               /* the servers host */
106                         host = strdup( optarg );
107                         break;
108
109                 case 'i':
110                         /* ignored (!) by now */
111                         break;
112
113                 case 'p':               /* the servers port */
114                         if ( lutil_atoi( &port, optarg ) != 0 ) {
115                                 usage( argv[0] );
116                         }
117                         break;
118
119                 case 'D':               /* the servers manager */
120                         manager = strdup( optarg );
121                         break;
122
123                 case 'w':               /* the server managers password */
124                         passwd.bv_val = strdup( optarg );
125                         passwd.bv_len = strlen( optarg );
126                         memset( optarg, '*', passwd.bv_len );
127                         break;
128
129                 case 'f':               /* file with entry search request */
130                         filename = strdup( optarg );
131                         break;
132
133                 case 'l':               /* the number of loops */
134                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
135                                 usage( argv[0] );
136                         }
137                         break;
138
139                 case 'L':               /* the number of outerloops */
140                         if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
141                                 usage( argv[0] );
142                         }
143                         break;
144
145                 case 'r':               /* number of retries */
146                         if ( lutil_atoi( &retries, optarg ) != 0 ) {
147                                 usage( argv[0] );
148                         }
149                         break;
150
151                 case 't':               /* delay in seconds */
152                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
153                                 usage( argv[0] );
154                         }
155                         break;
156
157                 default:
158                         usage( argv[0] );
159                         break;
160                 }
161         }
162
163         if (( filename == NULL ) || ( port == -1 && uri == NULL ) ||
164                                 ( manager == NULL ) || ( passwd.bv_val == NULL ))
165                 usage( argv[0] );
166
167         entry = get_add_entry( filename, &attrs );
168         if (( entry == NULL ) || ( *entry == '\0' )) {
169
170                 fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
171                                 argv[0], filename );
172                 exit( EXIT_FAILURE );
173
174         }
175
176         if (( attrs == NULL ) || ( *attrs == '\0' )) {
177
178                 fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
179                                 argv[0], filename );
180                 exit( EXIT_FAILURE );
181
182         }
183
184         uri = tester_uri( uri, host, port );
185
186         for ( i = 0; i < outerloops; i++ ) {
187                 do_addel( uri, manager, &passwd, entry, attrs,
188                                 loops, retries, delay, friendly, chaserefs );
189         }
190
191         exit( EXIT_SUCCESS );
192 }
193
194
195 static void
196 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
197 {
198     LDAPMod             **pmods;
199     int                 i, j;
200     struct berval       *bvp;
201
202     pmods = *pmodsp;
203     modop |= LDAP_MOD_BVALUES;
204
205     i = 0;
206     if ( pmods != NULL ) {
207                 for ( ; pmods[ i ] != NULL; ++i ) {
208                 if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
209                         pmods[ i ]->mod_op == modop ) {
210                                 break;
211                 }
212                 }
213     }
214
215     if ( pmods == NULL || pmods[ i ] == NULL ) {
216                 if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
217                         sizeof( LDAPMod * ))) == NULL ) {
218                         tester_perror( "realloc", NULL );
219                         exit( EXIT_FAILURE );
220                 }
221                 *pmodsp = pmods;
222                 pmods[ i + 1 ] = NULL;
223                 if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
224                         == NULL ) {
225                         tester_perror( "calloc", NULL );
226                         exit( EXIT_FAILURE );
227                 }
228                 pmods[ i ]->mod_op = modop;
229                 if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
230                 tester_perror( "strdup", NULL );
231                 exit( EXIT_FAILURE );
232                 }
233     }
234
235     if ( value != NULL ) {
236                 j = 0;
237                 if ( pmods[ i ]->mod_bvalues != NULL ) {
238                 for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
239                                 ;
240                 }
241                 }
242                 if (( pmods[ i ]->mod_bvalues =
243                         (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
244                         (j + 2) * sizeof( struct berval * ))) == NULL ) {
245                         tester_perror( "ber_memrealloc", NULL );
246                         exit( EXIT_FAILURE );
247                 }
248                 pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
249                 if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
250                         == NULL ) {
251                         tester_perror( "ber_memalloc", NULL );
252                         exit( EXIT_FAILURE );
253                 }
254                 pmods[ i ]->mod_bvalues[ j ] = bvp;
255
256             bvp->bv_len = vlen;
257             if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
258                         tester_perror( "malloc", NULL );
259                         exit( EXIT_FAILURE );
260             }
261             AC_MEMCPY( bvp->bv_val, value, vlen );
262             bvp->bv_val[ vlen ] = '\0';
263     }
264 }
265
266
267 static char *
268 get_add_entry( char *filename, LDAPMod ***mods )
269 {
270         FILE    *fp;
271         char    *entry = NULL;
272
273         if ( (fp = fopen( filename, "r" )) != NULL ) {
274                 char  line[BUFSIZ];
275
276                 if ( fgets( line, BUFSIZ, fp )) {
277                         char *nl;
278
279                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
280                                 *nl = '\0';
281                         nl = line;
282                         if ( !strncasecmp( nl, "dn: ", 4 ))
283                                 nl += 4;
284                         entry = strdup( nl );
285
286                 }
287
288                 while ( fgets( line, BUFSIZ, fp )) {
289                         char    *nl;
290                         char    *value;
291
292                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
293                                 *nl = '\0';
294
295                         if ( *line == '\0' ) break;
296                         if ( !( value = strchr( line, ':' ))) break;
297
298                         *value++ = '\0'; 
299                         while ( *value && isspace( (unsigned char) *value ))
300                                 value++;
301
302                         addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
303
304                 }
305                 fclose( fp );
306         }
307
308         return( entry );
309 }
310
311
312 static void
313 do_addel(
314         char *uri,
315         char *manager,
316         struct berval *passwd,
317         char *entry,
318         LDAPMod **attrs,
319         int maxloop,
320         int maxretries,
321         int delay,
322         int friendly,
323         int chaserefs )
324 {
325         LDAP    *ld = NULL;
326         int     i = 0, do_retry = maxretries;
327         int     rc = LDAP_SUCCESS;
328         int     version = LDAP_VERSION3;
329
330 retry:;
331         ldap_initialize( &ld, uri );
332         if ( ld == NULL ) {
333                 tester_perror( "ldap_initialize", NULL );
334                 exit( EXIT_FAILURE );
335         }
336
337         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
338         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
339                 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
340
341         if ( do_retry == maxretries ) {
342                 fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
343                         (long) pid, maxloop, entry );
344         }
345
346         rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
347         if ( rc != LDAP_SUCCESS ) {
348                 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
349                 switch ( rc ) {
350                 case LDAP_BUSY:
351                 case LDAP_UNAVAILABLE:
352                         if ( do_retry > 0 ) {
353                                 do_retry--;
354                                 if ( delay != 0 ) {
355                                     sleep( delay );
356                                 }
357                                 goto retry;
358                         }
359                 /* fallthru */
360                 default:
361                         break;
362                 }
363                 exit( EXIT_FAILURE );
364         }
365
366         for ( ; i < maxloop; i++ ) {
367
368                 /* add the entry */
369                 rc = ldap_add_ext_s( ld, entry, attrs, NULL, NULL );
370                 if ( rc != LDAP_SUCCESS ) {
371                         tester_ldap_error( ld, "ldap_add_ext_s", NULL );
372                         switch ( rc ) {
373                         case LDAP_ALREADY_EXISTS:
374                                 /* NOTE: this likely means
375                                  * the delete failed
376                                  * during the previous round... */
377                                 if ( !friendly ) {
378                                         goto done;
379                                 }
380                                 break;
381
382                         case LDAP_BUSY:
383                         case LDAP_UNAVAILABLE:
384                                 if ( do_retry > 0 ) {
385                                         do_retry--;
386                                         goto retry;
387                                 }
388                                 /* fall thru */
389
390                         default:
391                                 goto done;
392                         }
393                 }
394
395 #if 0
396                 /* wait a second for the add to really complete */
397                 /* This masks some race conditions though. */
398                 sleep( 1 );
399 #endif
400
401                 /* now delete the entry again */
402                 rc = ldap_delete_ext_s( ld, entry, NULL, NULL );
403                 if ( rc != LDAP_SUCCESS ) {
404                         tester_ldap_error( ld, "ldap_delete_ext_s", NULL );
405                         switch ( rc ) {
406                         case LDAP_NO_SUCH_OBJECT:
407                                 /* NOTE: this likely means
408                                  * the add failed
409                                  * during the previous round... */
410                                 if ( !friendly ) {
411                                         goto done;
412                                 }
413                                 break;
414
415                         case LDAP_BUSY:
416                         case LDAP_UNAVAILABLE:
417                                 if ( do_retry > 0 ) {
418                                         do_retry--;
419                                         goto retry;
420                                 }
421                                 /* fall thru */
422
423                         default:
424                                 goto done;
425                         }
426                 }
427         }
428
429 done:;
430         fprintf( stderr, "  PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
431
432         ldap_unbind_ext( ld, NULL, NULL );
433 }
434
435