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