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