xref: /netbsd-src/external/bsd/openldap/dist/clients/tools/ldapcompare.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: ldapcompare.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* ldapcompare.c -- LDAP compare tool */
4 /* OpenLDAP: pkg/ldap/clients/tools/ldapcompare.c,v 1.43.2.7 2009/08/13 00:55:06 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2009 The OpenLDAP Foundation.
8  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
9  * Portions Copyright 1998-2001 Net Boolean Incorporated.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted only as authorized by the OpenLDAP
14  * Public License.
15  *
16  * A copy of this license is available in the file LICENSE in the
17  * top-level directory of the distribution or, alternatively, at
18  * <http://www.OpenLDAP.org/license.html>.
19  */
20 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms are permitted
24  * provided that this notice is preserved and that due credit is given
25  * to the University of Michigan at Ann Arbor.  The name of the
26  * University may not be used to endorse or promote products derived
27  * from this software without specific prior written permission.  This
28  * software is provided ``as is'' without express or implied warranty.
29  */
30 /* Portions Copyright 2002, F5 Networks, Inc, All rights reserved.
31  * This software is not subject to any license of F5 Networks.
32  * This is free software; you can redistribute and use it
33  * under the same terms as OpenLDAP itself.
34  */
35 /* ACKNOWLEDGEMENTS:
36  * This work was originally developed by Jeff Costlow (F5 Networks)
37  * based, in part, on existing LDAP tools and adapted for inclusion
38  * into OpenLDAP Software by Kurt D. Zeilenga.
39  */
40 
41 #include "portable.h"
42 
43 #include <stdio.h>
44 
45 #include <ac/stdlib.h>
46 
47 #include <ac/ctype.h>
48 #include <ac/string.h>
49 #include <ac/unistd.h>
50 #include <ac/errno.h>
51 #include <ac/socket.h>
52 #include <ac/time.h>
53 #include <sys/stat.h>
54 
55 #ifdef HAVE_FCNTL_H
56 #include <fcntl.h>
57 #endif
58 #ifdef HAVE_SYS_TYPES_H
59 #include <sys/types.h>
60 #endif
61 #ifdef HAVE_IO_H
62 #include <io.h>
63 #endif
64 
65 #include <ldap.h>
66 
67 #include "lutil.h"
68 #include "lutil_ldap.h"
69 #include "ldap_defaults.h"
70 
71 #include "common.h"
72 
73 
74 static int quiet = 0;
75 
76 
77 void
78 usage( void )
79 {
80 	fprintf( stderr, _("usage: %s [options] DN <attr:value|attr::b64value>\n"), prog);
81 	fprintf( stderr, _("where:\n"));
82 	fprintf( stderr, _("  DN\tDistinguished Name\n"));
83 	fprintf( stderr, _("  attr\tassertion attribute\n"));
84 	fprintf( stderr, _("  value\tassertion value\n"));
85 	fprintf( stderr, _("  b64value\tbase64 encoding of assertion value\n"));
86 
87 	fprintf( stderr, _("Compare options:\n"));
88 	fprintf( stderr, _("  -E [!]<ext>[=<extparam>] compare extensions (! indicates criticality)\n"));
89 	fprintf( stderr, _("             !dontUseCopy                (Don't Use Copy)\n"));
90 	fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
91 	fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
92 	fprintf( stderr, _("  -z         Quiet mode,"
93 		" don't print anything, use return values\n"));
94 	tool_common_usage();
95 	exit( EXIT_FAILURE );
96 }
97 
98 static int docompare LDAP_P((
99 	LDAP *ld,
100 	char *dn,
101 	char *attr,
102 	struct berval *bvalue,
103 	int quiet,
104 	LDAPControl **sctrls,
105 	LDAPControl **cctrls));
106 
107 
108 const char options[] = "z"
109 	"Cd:D:e:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
110 
111 #ifdef LDAP_CONTROL_DONTUSECOPY
112 int dontUseCopy = 0;
113 #endif
114 
115 int
116 handle_private_option( int i )
117 {
118 	char	*control, *cvalue;
119 	int		crit;
120 
121 	switch ( i ) {
122 	case 'E': /* compare extensions */
123 		if( protocol == LDAP_VERSION2 ) {
124 			fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
125 				prog, protocol );
126 			exit( EXIT_FAILURE );
127 		}
128 
129 		/* should be extended to support comma separated list of
130 		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
131 		 */
132 
133 		crit = 0;
134 		cvalue = NULL;
135 		if( optarg[0] == '!' ) {
136 			crit = 1;
137 			optarg++;
138 		}
139 
140 		control = ber_strdup( optarg );
141 		if ( (cvalue = strchr( control, '=' )) != NULL ) {
142 			*cvalue++ = '\0';
143 		}
144 
145 #ifdef LDAP_CONTROL_DONTUSECOPY
146 		if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
147 			if( dontUseCopy ) {
148 				fprintf( stderr,
149 					_("dontUseCopy control previously specified\n"));
150 				exit( EXIT_FAILURE );
151 			}
152 			if( cvalue != NULL ) {
153 				fprintf( stderr,
154 					_("dontUseCopy: no control value expected\n") );
155 				usage();
156 			}
157 			if( !crit ) {
158 				fprintf( stderr,
159 					_("dontUseCopy: critical flag required\n") );
160 				usage();
161 			}
162 
163 			dontUseCopy = 1 + crit;
164 		} else
165 #endif
166 		{
167 			fprintf( stderr,
168 				_("Invalid compare extension name: %s\n"), control );
169 			usage();
170 		}
171 		break;
172 
173 	case 'z':
174 		quiet = 1;
175 		break;
176 
177 	default:
178 		return 0;
179 	}
180 	return 1;
181 }
182 
183 
184 int
185 main( int argc, char **argv )
186 {
187 	char		*compdn = NULL, *attrs = NULL;
188 	char		*sep;
189 	int		rc;
190 	LDAP		*ld = NULL;
191 	struct berval	bvalue = { 0, NULL };
192 	int		i = 0;
193 	LDAPControl	c[1];
194 
195 
196 	tool_init( TOOL_COMPARE );
197 	prog = lutil_progname( "ldapcompare", argc, argv );
198 
199 	tool_args( argc, argv );
200 
201 	if ( argc - optind != 2 ) {
202 		usage();
203 	}
204 
205 	compdn = argv[optind++];
206 	attrs = argv[optind++];
207 
208 	/* user passed in only 2 args, the last one better be in
209 	 * the form attr:value or attr::b64value
210 	 */
211 	sep = strchr(attrs, ':');
212 	if (!sep) {
213 		usage();
214 	}
215 
216 	*sep++='\0';
217 	if ( *sep != ':' ) {
218 		bvalue.bv_val = strdup( sep );
219 		bvalue.bv_len = strlen( bvalue.bv_val );
220 
221 	} else {
222 		/* it's base64 encoded. */
223 		bvalue.bv_val = malloc( strlen( &sep[1] ));
224 		bvalue.bv_len = lutil_b64_pton( &sep[1],
225 			(unsigned char *) bvalue.bv_val, strlen( &sep[1] ));
226 
227 		if (bvalue.bv_len == (ber_len_t)-1) {
228 			fprintf(stderr, _("base64 decode error\n"));
229 			exit(-1);
230 		}
231 	}
232 
233 	ld = tool_conn_setup( 0, 0 );
234 
235 	if ( pw_file || want_bindpw ) {
236 		if ( pw_file ) {
237 			rc = lutil_get_filed_password( pw_file, &passwd );
238 			if( rc ) return EXIT_FAILURE;
239 		} else {
240 			passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") );
241 			passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
242 		}
243 	}
244 
245 	tool_bind( ld );
246 
247 	if ( 0
248 #ifdef LDAP_CONTROL_DONTUSECOPY
249 		|| dontUseCopy
250 #endif
251 		)
252 	{
253 #ifdef LDAP_CONTROL_DONTUSECOPY
254 		if ( dontUseCopy ) {
255 			c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
256 			c[i].ldctl_value.bv_val = NULL;
257 			c[i].ldctl_value.bv_len = 0;
258 			c[i].ldctl_iscritical = dontUseCopy > 1;
259 			i++;
260 		}
261 #endif
262 	}
263 
264 	tool_server_controls( ld, c, i );
265 
266 	if ( verbose ) {
267 		fprintf( stderr, _("DN:%s, attr:%s, value:%s\n"),
268 			compdn, attrs, sep );
269 	}
270 
271 	rc = docompare( ld, compdn, attrs, &bvalue, quiet, NULL, NULL );
272 
273 	free( bvalue.bv_val );
274 
275 	tool_unbind( ld );
276 	tool_destroy();
277 	return rc;
278 }
279 
280 
281 static int docompare(
282 	LDAP *ld,
283 	char *dn,
284 	char *attr,
285 	struct berval *bvalue,
286 	int quiet,
287 	LDAPControl **sctrls,
288 	LDAPControl **cctrls )
289 {
290 	int		rc, msgid, code;
291 	LDAPMessage	*res;
292 	char		*matcheddn;
293 	char		*text;
294 	char		**refs;
295 	LDAPControl **ctrls = NULL;
296 
297 	if ( dont ) {
298 		return LDAP_SUCCESS;
299 	}
300 
301 	rc = ldap_compare_ext( ld, dn, attr, bvalue,
302 		sctrls, cctrls, &msgid );
303 	if ( rc == -1 ) {
304 		return( rc );
305 	}
306 
307 	for ( ; ; ) {
308 		struct timeval	tv;
309 
310 		tv.tv_sec = 0;
311 		tv.tv_usec = 100000;
312 
313 		if ( tool_check_abandon( ld, msgid ) ) {
314 			return LDAP_CANCELLED;
315 		}
316 
317 		rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
318 		if ( rc < 0 ) {
319 			tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
320 			return rc;
321 		}
322 
323 		if ( rc != 0 ) {
324 			break;
325 		}
326 	}
327 
328 	rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
329 
330 	if( rc != LDAP_SUCCESS ) {
331 		fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
332 			prog, ldap_err2string( rc ), rc );
333 		return rc;
334 	}
335 
336 	if ( !quiet && ( verbose || ( code != LDAP_SUCCESS && code != LDAP_COMPARE_TRUE && code != LDAP_COMPARE_FALSE )||
337 		(matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) )
338 	{
339 		printf( _("Compare Result: %s (%d)\n"),
340 			ldap_err2string( code ), code );
341 
342 		if( text && *text ) {
343 			printf( _("Additional info: %s\n"), text );
344 		}
345 
346 		if( matcheddn && *matcheddn ) {
347 			printf( _("Matched DN: %s\n"), matcheddn );
348 		}
349 
350 		if( refs ) {
351 			int i;
352 			for( i=0; refs[i]; i++ ) {
353 				printf(_("Referral: %s\n"), refs[i] );
354 			}
355 		}
356 	}
357 
358 	/* if we were told to be quiet, use the return value. */
359 	if ( !quiet ) {
360 		if ( code == LDAP_COMPARE_TRUE ) {
361 			printf(_("TRUE\n"));
362 		} else if ( code == LDAP_COMPARE_FALSE ) {
363 			printf(_("FALSE\n"));
364 		} else {
365 			printf(_("UNDEFINED\n"));
366 		}
367 	}
368 
369 	if ( ctrls ) {
370 		tool_print_ctrls( ld, ctrls );
371 		ldap_controls_free( ctrls );
372 	}
373 
374 	ber_memfree( text );
375 	ber_memfree( matcheddn );
376 	ber_memvfree( (void **) refs );
377 
378 	return( code );
379 }
380 
381