xref: /netbsd-src/external/bsd/openldap/dist/clients/tools/ldapexop.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: ldapexop.c,v 1.3 2021/08/14 16:14:49 christos Exp $	*/
2 
3 /* ldapexop.c -- a tool for performing well-known extended operations */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2005-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was originally developed by Pierangelo Masarati for inclusion
20  * in OpenLDAP Software based, in part, on other client tools.
21  */
22 
23 #include <sys/cdefs.h>
24 __RCSID("$NetBSD: ldapexop.c,v 1.3 2021/08/14 16:14:49 christos Exp $");
25 
26 #include "portable.h"
27 
28 #include <stdio.h>
29 
30 #include <ac/stdlib.h>
31 
32 #include <ac/ctype.h>
33 #include <ac/socket.h>
34 #include <ac/string.h>
35 #include <ac/time.h>
36 #include <ac/unistd.h>
37 
38 #include <ldap.h>
39 #include "ldif.h"
40 #include "lutil.h"
41 #include "lutil_ldap.h"
42 #include "ldap_defaults.h"
43 
44 #include "common.h"
45 
46 void
usage(void)47 usage( void )
48 {
49 	fprintf( stderr, _("Issue LDAP extended operations\n\n"));
50 	fprintf( stderr, _("usage: %s [options] <oid|oid:data|oid::b64data>\n"), prog);
51 	fprintf( stderr, _("       %s [options] whoami\n"), prog);
52 	fprintf( stderr, _("       %s [options] cancel <id>\n"), prog);
53 	fprintf( stderr, _("       %s [options] refresh <DN> [<ttl>]\n"), prog);
54 	tool_common_usage();
55 	exit( EXIT_FAILURE );
56 }
57 
58 
59 const char options[] = ""
60 	"d:D:e:h:H:InNO:o:p:QR:U:vVw:WxX:y:Y:Z";
61 
62 int
handle_private_option(int i)63 handle_private_option( int i )
64 {
65 	switch ( i ) {
66 	default:
67 		return 0;
68 	}
69 	return 1;
70 }
71 
72 
73 int
main(int argc,char * argv[])74 main( int argc, char *argv[] )
75 {
76 	int		rc;
77 
78 	LDAP		*ld = NULL;
79 
80 	char		*matcheddn = NULL, *text = NULL, **refs = NULL;
81 	LDAPControl **ctrls = NULL;
82 	int		id, code;
83 	LDAPMessage	*res = NULL;
84 
85 	tool_init( TOOL_EXOP );
86 	prog = lutil_progname( "ldapexop", argc, argv );
87 
88 	/* LDAPv3 only */
89 	protocol = LDAP_VERSION3;
90 
91 	tool_args( argc, argv );
92 
93 	if ( argc - optind < 1 ) {
94 		usage();
95 	}
96 
97 	ld = tool_conn_setup( 0, 0 );
98 
99 	tool_bind( ld );
100 
101 	argv += optind;
102 	argc -= optind;
103 
104 	if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) {
105 		tool_server_controls( ld, NULL, 0 );
106 
107 		rc = ldap_whoami( ld, NULL, NULL, &id );
108 		if ( rc != LDAP_SUCCESS ) {
109 			tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
110 			rc = EXIT_FAILURE;
111 			goto skip;
112 		}
113 
114 	} else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
115 		int		cancelid;
116 
117 		switch ( argc ) {
118 		case 2:
119 			 if ( lutil_atoi( &cancelid, argv[ 1 ] ) != 0 || cancelid < 0 ) {
120 				fprintf( stderr, "invalid cancelid=%s\n\n", argv[ 1 ] );
121 				usage();
122 			}
123 			break;
124 
125 		default:
126 			fprintf( stderr, "need cancelid\n\n" );
127 			usage();
128 		}
129 
130 		rc = ldap_cancel( ld, cancelid, NULL, NULL, &id );
131 		if ( rc != LDAP_SUCCESS ) {
132 			tool_perror( "ldap_cancel", rc, NULL, NULL, NULL, NULL );
133 			rc = EXIT_FAILURE;
134 			goto skip;
135 		}
136 
137 	} else if ( strcasecmp( argv[ 0 ], "passwd" ) == 0 ) {
138 		fprintf( stderr, "use ldappasswd(1) instead.\n\n" );
139 		usage();
140 		/* TODO? */
141 
142 	} else if ( strcasecmp( argv[ 0 ], "refresh" ) == 0 ) {
143 		int		ttl = 3600;
144 		struct berval	dn;
145 
146 		switch ( argc ) {
147 		case 3:
148 			ttl = atoi( argv[ 2 ] );
149 
150 		case 2:
151 			dn.bv_val = argv[ 1 ];
152 			dn.bv_len = strlen( dn.bv_val );
153 			break;
154 
155 		default:
156 			fprintf( stderr, _("need DN [ttl]\n\n") );
157 			usage();
158 		}
159 
160 		tool_server_controls( ld, NULL, 0 );
161 
162 		rc = ldap_refresh( ld, &dn, ttl, NULL, NULL, &id );
163 		if ( rc != LDAP_SUCCESS ) {
164 			tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
165 			rc = EXIT_FAILURE;
166 			goto skip;
167 		}
168 
169 	} else {
170 		char *p;
171 
172 		if ( argc != 1 ) {
173 			usage();
174 		}
175 
176 		p = strchr( argv[ 0 ], ':' );
177 		if ( p == argv[ 0 ] ) {
178 			usage();
179 		}
180 
181 		if ( p != NULL )
182 			*p++ = '\0';
183 
184 		if ( tool_is_oid( argv[ 0 ] ) ) {
185 			struct berval	reqdata;
186 			struct berval	type;
187 			struct berval	value;
188 			int		freeval;
189 
190 			if ( p != NULL ) {
191 				p[ -1 ] = ':';
192 				ldif_parse_line2( argv[ 0 ], &type, &value, &freeval );
193 				p[ -1 ] = '\0';
194 
195 				if ( freeval ) {
196 					reqdata = value;
197 				} else {
198 					ber_dupbv( &reqdata, &value );
199 				}
200 			}
201 
202 
203 			tool_server_controls( ld, NULL, 0 );
204 
205 			rc = ldap_extended_operation( ld, argv[ 0 ], p ? &reqdata : NULL, NULL, NULL, &id );
206 			if ( rc != LDAP_SUCCESS ) {
207 				tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
208 				rc = EXIT_FAILURE;
209 				goto skip;
210 			}
211 		} else {
212 			fprintf( stderr, "unknown exop \"%s\"\n\n", argv[ 0 ] );
213 			usage();
214 		}
215 	}
216 
217 	for ( ; ; ) {
218 		struct timeval	tv;
219 
220 		if ( tool_check_abandon( ld, id ) ) {
221 			tool_exit( ld, LDAP_CANCELLED );
222 		}
223 
224 		tv.tv_sec = 0;
225 		tv.tv_usec = 100000;
226 
227 		rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
228 		if ( rc < 0 ) {
229 			tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
230 			rc = EXIT_FAILURE;
231 			goto skip;
232 		}
233 
234 		if ( rc != 0 ) {
235 			break;
236 		}
237 	}
238 
239 	rc = ldap_parse_result( ld, res,
240 		&code, &matcheddn, &text, &refs, &ctrls, 0 );
241 	if ( rc == LDAP_SUCCESS ) {
242 		rc = code;
243 	}
244 
245 	if ( rc != LDAP_SUCCESS ) {
246 		tool_perror( "ldap_parse_result", rc, NULL, matcheddn, text, refs );
247 		rc = EXIT_FAILURE;
248 		goto skip;
249 	}
250 
251 	if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) {
252 		char		*retoid = NULL;
253 		struct berval	*retdata = NULL;
254 
255 		rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 0 );
256 
257 		if ( rc != LDAP_SUCCESS ) {
258 			tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
259 			rc = EXIT_FAILURE;
260 			goto skip;
261 		}
262 
263 		if ( retdata != NULL ) {
264 			if ( retdata->bv_len == 0 ) {
265 				printf(_("anonymous\n") );
266 			} else {
267 				printf("%s\n", retdata->bv_val );
268 			}
269 		}
270 
271 		ber_memfree( retoid );
272 		ber_bvfree( retdata );
273 
274 	} else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
275 		/* no extended response; returns specific errors */
276 		assert( 0 );
277 
278 	} else if ( strcasecmp( argv[ 0 ], "passwd" ) == 0 ) {
279 		/* TODO */
280 
281 	} else if ( strcasecmp( argv[ 0 ], "refresh" ) == 0 ) {
282 		int	newttl;
283 
284 		rc = ldap_parse_refresh( ld, res, &newttl );
285 
286 		if ( rc != LDAP_SUCCESS ) {
287 			tool_perror( "ldap_parse_refresh", rc, NULL, NULL, NULL, NULL );
288 			rc = EXIT_FAILURE;
289 			goto skip;
290 		}
291 
292 		printf( "newttl=%d\n", newttl );
293 
294 	} else if ( tool_is_oid( argv[ 0 ] ) ) {
295 		char		*retoid = NULL;
296 		struct berval	*retdata = NULL;
297 
298 		if( ldif < 2 ) {
299 			printf(_("# extended operation response\n"));
300 		}
301 
302 		rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 0 );
303 		if ( rc != LDAP_SUCCESS ) {
304 			tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
305 			rc = EXIT_FAILURE;
306 			goto skip;
307 		}
308 
309 		if ( ldif < 2 && retoid != NULL ) {
310 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
311 				"oid", retoid, strlen(retoid) );
312 		}
313 
314 		ber_memfree( retoid );
315 
316 		if( retdata != NULL ) {
317 			if ( ldif < 2 ) {
318 				tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
319 					"data", retdata->bv_val, retdata->bv_len );
320 			}
321 
322 			ber_bvfree( retdata );
323 		}
324 	}
325 
326 	if( verbose || code != LDAP_SUCCESS ||
327 		( matcheddn && *matcheddn ) || ( text && *text ) || refs ) {
328 		printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
329 
330 		if( text && *text ) {
331 			printf( _("Additional info: %s\n"), text );
332 		}
333 
334 		if( matcheddn && *matcheddn ) {
335 			printf( _("Matched DN: %s\n"), matcheddn );
336 		}
337 
338 		if( refs ) {
339 			int i;
340 			for( i=0; refs[i]; i++ ) {
341 				printf(_("Referral: %s\n"), refs[i] );
342 			}
343 		}
344 	}
345 
346     if (ctrls) {
347 		tool_print_ctrls( ld, ctrls );
348 		ldap_controls_free( ctrls );
349 	}
350 
351 	ber_memfree( text );
352 	ber_memfree( matcheddn );
353 	ber_memvfree( (void **) refs );
354 
355 skip:
356 	/* disconnect from server */
357 	if ( res )
358 		ldap_msgfree( res );
359 	tool_exit( ld, rc );
360 }
361