xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-modify.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: slapd-modify.c,v 1.2 2020/08/11 13:15:42 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2020 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: slapd-modify.c,v 1.2 2020/08/11 13:15:42 christos Exp $");
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include "ac/stdlib.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 
34 #include "ldap.h"
35 #include "lutil.h"
36 
37 #include "slapd-common.h"
38 
39 #define LOOPS	100
40 #define RETRIES 0
41 
42 static void
43 do_modify( char *uri, char *manager, struct berval *passwd,
44 		char *entry, char *attr, char *value, int maxloop,
45 		int maxretries, int delay, int friendly, int chaserefs );
46 
47 
48 static void
49 usage( char *name )
50 {
51         fprintf( stderr,
52 		"usage: %s "
53 		"-H <uri> | ([-h <host>] -p <port>) "
54 		"-D <manager> "
55 		"-w <passwd> "
56 		"-e <entry> "
57 		"[-i <ignore>] "
58 		"[-l <loops>] "
59 		"[-L <outerloops>] "
60 		"[-r <maxretries>] "
61 		"[-t <delay>] "
62 		"[-F] "
63 		"[-C]\n",
64 			name );
65 	exit( EXIT_FAILURE );
66 }
67 
68 int
69 main( int argc, char **argv )
70 {
71 	int		i;
72 	char		*uri = NULL;
73 	char		*host = "localhost";
74 	int		port = -1;
75 	char		*manager = NULL;
76 	struct berval	passwd = { 0, NULL };
77 	char		*entry = NULL;
78 	char		*ava = NULL;
79 	char		*value = 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 
87 	tester_init( "slapd-modify", TESTER_MODIFY );
88 
89 	while ( ( i = getopt( argc, argv, "a:CD:e:FH:h:i:L:l:p:r:t:w:" ) ) != EOF )
90 	{
91 		switch ( i ) {
92 		case 'C':
93 			chaserefs++;
94 			break;
95 
96 		case 'F':
97 			friendly++;
98 			break;
99 
100 		case 'H':		/* the server uri */
101 			uri = strdup( optarg );
102 			break;
103 
104 		case 'h':		/* the servers host */
105 			host = strdup( optarg );
106 			break;
107 
108 		case 'i':
109 			/* ignored (!) by now */
110 			break;
111 
112 		case 'p':		/* the servers port */
113 			if ( lutil_atoi( &port, optarg ) != 0 ) {
114 				usage( argv[0] );
115 			}
116 			break;
117 
118 		case 'D':		/* the servers manager */
119 			manager = strdup( optarg );
120 			break;
121 
122 		case 'w':		/* the server managers password */
123 			passwd.bv_val = strdup( optarg );
124 			passwd.bv_len = strlen( optarg );
125 			memset( optarg, '*', passwd.bv_len );
126 			break;
127 
128 		case 'e':		/* entry to modify */
129 			entry = strdup( optarg );
130 			break;
131 
132 		case 'a':
133 			ava = strdup( optarg );
134 			break;
135 
136 		case 'l':		/* the number of loops */
137 			if ( lutil_atoi( &loops, optarg ) != 0 ) {
138 				usage( argv[0] );
139 			}
140 			break;
141 
142 		case 'L':		/* the number of outerloops */
143 			if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
144 				usage( argv[0] );
145 			}
146 			break;
147 
148 		case 'r':		/* number of retries */
149 			if ( lutil_atoi( &retries, optarg ) != 0 ) {
150 				usage( argv[0] );
151 			}
152 			break;
153 
154 		case 't':		/* delay in seconds */
155 			if ( lutil_atoi( &delay, optarg ) != 0 ) {
156 				usage( argv[0] );
157 			}
158 			break;
159 
160 		default:
161 			usage( argv[0] );
162 			break;
163 		}
164 	}
165 
166 	if (( entry == NULL ) || ( ava == NULL ) || ( port == -1 && uri == NULL ))
167 		usage( argv[0] );
168 
169 	if ( *entry == '\0' ) {
170 
171 		fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
172 				argv[0] );
173 		exit( EXIT_FAILURE );
174 
175 	}
176 	if ( *ava  == '\0' ) {
177 		fprintf( stderr, "%s: invalid EMPTY AVA.\n",
178 				argv[0] );
179 		exit( EXIT_FAILURE );
180 	}
181 
182 	if ( !( value = strchr( ava, ':' ))) {
183 		fprintf( stderr, "%s: invalid AVA.\n",
184 				argv[0] );
185 		exit( EXIT_FAILURE );
186 	}
187 	*value++ = '\0';
188 	while ( *value && isspace( (unsigned char) *value ))
189 		value++;
190 
191 	uri = tester_uri( uri, host, port );
192 
193 	for ( i = 0; i < outerloops; i++ ) {
194 		do_modify( uri, manager, &passwd, entry, ava, value,
195 				loops, retries, delay, friendly, chaserefs );
196 	}
197 
198 	exit( EXIT_SUCCESS );
199 }
200 
201 
202 static void
203 do_modify( char *uri, char *manager,
204 	struct berval *passwd, char *entry, char* attr, char* value,
205 	int maxloop, int maxretries, int delay, int friendly, int chaserefs )
206 {
207 	LDAP	*ld = NULL;
208 	int  	i = 0, do_retry = maxretries;
209 	int     rc = LDAP_SUCCESS;
210 
211 	struct ldapmod mod;
212 	struct ldapmod *mods[2];
213 	char *values[2];
214 	int version = LDAP_VERSION3;
215 
216 	values[0] = value;
217 	values[1] = NULL;
218 	mod.mod_op = LDAP_MOD_ADD;
219 	mod.mod_type = attr;
220 	mod.mod_values = values;
221 	mods[0] = &mod;
222 	mods[1] = NULL;
223 
224 retry:;
225 	ldap_initialize( &ld, uri );
226 	if ( ld == NULL ) {
227 		tester_perror( "ldap_initialize", NULL );
228 		exit( EXIT_FAILURE );
229 	}
230 
231 	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
232 	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
233 		chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
234 
235 	if ( do_retry == maxretries ) {
236 		fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
237 			(long) pid, maxloop, entry );
238 	}
239 
240 	rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
241 	if ( rc != LDAP_SUCCESS ) {
242 		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
243 		switch ( rc ) {
244 		case LDAP_BUSY:
245 		case LDAP_UNAVAILABLE:
246 			if ( do_retry > 0 ) {
247 				do_retry--;
248 				if ( delay > 0 ) {
249 				    sleep( delay );
250 				}
251 				goto retry;
252 			}
253 		/* fallthru */
254 		default:
255 			break;
256 		}
257 		exit( EXIT_FAILURE );
258 	}
259 
260 	for ( ; i < maxloop; i++ ) {
261 		mod.mod_op = LDAP_MOD_ADD;
262 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
263 		if ( rc != LDAP_SUCCESS ) {
264 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
265 			switch ( rc ) {
266 			case LDAP_TYPE_OR_VALUE_EXISTS:
267 				/* NOTE: this likely means
268 				 * the second modify failed
269 				 * during the previous round... */
270 				if ( !friendly ) {
271 					goto done;
272 				}
273 				break;
274 
275 			case LDAP_BUSY:
276 			case LDAP_UNAVAILABLE:
277 				if ( do_retry > 0 ) {
278 					do_retry--;
279 					goto retry;
280 				}
281 				/* fall thru */
282 
283 			default:
284 				goto done;
285 			}
286 		}
287 
288 		mod.mod_op = LDAP_MOD_DELETE;
289 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
290 		if ( rc != LDAP_SUCCESS ) {
291 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
292 			switch ( rc ) {
293 			case LDAP_NO_SUCH_ATTRIBUTE:
294 				/* NOTE: this likely means
295 				 * the first modify failed
296 				 * during the previous round... */
297 				if ( !friendly ) {
298 					goto done;
299 				}
300 				break;
301 
302 			case LDAP_BUSY:
303 			case LDAP_UNAVAILABLE:
304 				if ( do_retry > 0 ) {
305 					do_retry--;
306 					goto retry;
307 				}
308 				/* fall thru */
309 
310 			default:
311 				goto done;
312 			}
313 		}
314 
315 	}
316 
317 done:;
318 	fprintf( stderr, "  PID=%ld - Modify done (%d).\n", (long) pid, rc );
319 
320 	ldap_unbind_ext( ld, NULL, NULL );
321 }
322 
323 
324