Back to index

openldap  2.4.31
ldapcompare.c
Go to the documentation of this file.
00001 /* ldapcompare.c -- LDAP compare tool */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
00007  * Portions Copyright 1998-2001 Net Boolean Incorporated.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
00019  * All rights reserved.
00020  *
00021  * Redistribution and use in source and binary forms are permitted
00022  * provided that this notice is preserved and that due credit is given
00023  * to the University of Michigan at Ann Arbor.  The name of the
00024  * University may not be used to endorse or promote products derived
00025  * from this software without specific prior written permission.  This
00026  * software is provided ``as is'' without express or implied warranty.
00027  */
00028 /* Portions Copyright 2002, F5 Networks, Inc, All rights reserved.
00029  * This software is not subject to any license of F5 Networks.
00030  * This is free software; you can redistribute and use it
00031  * under the same terms as OpenLDAP itself.
00032  */
00033 /* ACKNOWLEDGEMENTS:
00034  * This work was originally developed by Jeff Costlow (F5 Networks)
00035  * based, in part, on existing LDAP tools and adapted for inclusion
00036  * into OpenLDAP Software by Kurt D. Zeilenga.
00037  */
00038 
00039 #include "portable.h"
00040 
00041 #include <stdio.h>
00042 
00043 #include <ac/stdlib.h>
00044 
00045 #include <ac/ctype.h>
00046 #include <ac/string.h>
00047 #include <ac/unistd.h>
00048 #include <ac/errno.h>
00049 #include <ac/socket.h>
00050 #include <ac/time.h>
00051 #include <sys/stat.h>
00052 
00053 #ifdef HAVE_FCNTL_H
00054 #include <fcntl.h>
00055 #endif
00056 #ifdef HAVE_SYS_TYPES_H
00057 #include <sys/types.h>
00058 #endif
00059 #ifdef HAVE_IO_H
00060 #include <io.h>
00061 #endif
00062 
00063 #include <ldap.h>
00064 
00065 #include "lutil.h"
00066 #include "lutil_ldap.h"
00067 #include "ldap_defaults.h"
00068 
00069 #include "common.h"
00070 
00071 
00072 static int quiet = 0;
00073 
00074 
00075 void
00076 usage( void )
00077 {
00078        fprintf( stderr, _("usage: %s [options] DN <attr:value|attr::b64value>\n"), prog);
00079        fprintf( stderr, _("where:\n"));
00080        fprintf( stderr, _("  DN\tDistinguished Name\n"));
00081        fprintf( stderr, _("  attr\tassertion attribute\n"));
00082        fprintf( stderr, _("  value\tassertion value\n"));
00083        fprintf( stderr, _("  b64value\tbase64 encoding of assertion value\n"));
00084 
00085        fprintf( stderr, _("Compare options:\n"));
00086        fprintf( stderr, _("  -E [!]<ext>[=<extparam>] compare extensions (! indicates criticality)\n"));
00087        fprintf( stderr, _("             !dontUseCopy                (Don't Use Copy)\n"));
00088        fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
00089        fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
00090        fprintf( stderr, _("  -z         Quiet mode,"
00091               " don't print anything, use return values\n"));
00092        tool_common_usage();
00093        exit( EXIT_FAILURE );
00094 }
00095 
00096 static int docompare LDAP_P((
00097        LDAP *ld,
00098        char *dn,
00099        char *attr,
00100        struct berval *bvalue,
00101        int quiet,
00102        LDAPControl **sctrls,
00103        LDAPControl **cctrls));
00104 
00105 
00106 const char options[] = "z"
00107        "Cd:D:e:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
00108 
00109 #ifdef LDAP_CONTROL_DONTUSECOPY
00110 int dontUseCopy = 0;
00111 #endif
00112 
00113 int
00114 handle_private_option( int i )
00115 {
00116        char   *control, *cvalue;
00117        int           crit;
00118 
00119        switch ( i ) {
00120        case 'E': /* compare extensions */
00121               if( protocol == LDAP_VERSION2 ) {
00122                      fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
00123                             prog, protocol );
00124                      exit( EXIT_FAILURE );
00125               }
00126 
00127               /* should be extended to support comma separated list of
00128                *     [!]key[=value] parameters, e.g.  -E !foo,bar=567
00129                */
00130 
00131               crit = 0;
00132               cvalue = NULL;
00133               if( optarg[0] == '!' ) {
00134                      crit = 1;
00135                      optarg++;
00136               }
00137 
00138               control = ber_strdup( optarg );
00139               if ( (cvalue = strchr( control, '=' )) != NULL ) {
00140                      *cvalue++ = '\0';
00141               }
00142 
00143 #ifdef LDAP_CONTROL_DONTUSECOPY
00144               if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
00145                      if( dontUseCopy ) {
00146                             fprintf( stderr,
00147                                    _("dontUseCopy control previously specified\n"));
00148                             exit( EXIT_FAILURE );
00149                      }
00150                      if( cvalue != NULL ) {
00151                             fprintf( stderr,
00152                                    _("dontUseCopy: no control value expected\n") );
00153                             usage();
00154                      }
00155                      if( !crit ) {
00156                             fprintf( stderr,
00157                                    _("dontUseCopy: critical flag required\n") );
00158                             usage();
00159                      }
00160 
00161                      dontUseCopy = 1 + crit;
00162               } else
00163 #endif
00164               {
00165                      fprintf( stderr,
00166                             _("Invalid compare extension name: %s\n"), control );
00167                      usage();
00168               }
00169               break;
00170 
00171        case 'z':
00172               quiet = 1;
00173               break;
00174 
00175        default:
00176               return 0;
00177        }
00178        return 1;
00179 }
00180 
00181 
00182 int
00183 main( int argc, char **argv )
00184 {
00185        char          *compdn = NULL, *attrs = NULL;
00186        char          *sep;
00187        int           rc;
00188        LDAP          *ld = NULL;
00189        struct berval bvalue = { 0, NULL };
00190        int           i = 0; 
00191        LDAPControl   c[1];
00192 
00193 
00194        tool_init( TOOL_COMPARE );
00195        prog = lutil_progname( "ldapcompare", argc, argv );
00196 
00197        tool_args( argc, argv );
00198 
00199        if ( argc - optind != 2 ) {
00200               usage();
00201        }
00202 
00203        compdn = argv[optind++];
00204        attrs = argv[optind++];
00205 
00206        /* user passed in only 2 args, the last one better be in
00207         * the form attr:value or attr::b64value
00208         */
00209        sep = strchr(attrs, ':');
00210        if (!sep) {
00211               usage();
00212        }
00213 
00214        *sep++='\0';
00215        if ( *sep != ':' ) {
00216               bvalue.bv_val = strdup( sep );
00217               bvalue.bv_len = strlen( bvalue.bv_val );
00218 
00219        } else {
00220               /* it's base64 encoded. */
00221               bvalue.bv_val = malloc( strlen( &sep[1] ));
00222               bvalue.bv_len = lutil_b64_pton( &sep[1],
00223                      (unsigned char *) bvalue.bv_val, strlen( &sep[1] ));
00224 
00225               if (bvalue.bv_len == (ber_len_t)-1) {
00226                      fprintf(stderr, _("base64 decode error\n"));
00227                      exit(-1);
00228               }
00229        }
00230 
00231        ld = tool_conn_setup( 0, 0 );
00232 
00233        tool_bind( ld );
00234 
00235        if ( 0
00236 #ifdef LDAP_CONTROL_DONTUSECOPY
00237               || dontUseCopy
00238 #endif
00239               )
00240        {
00241 #ifdef LDAP_CONTROL_DONTUSECOPY
00242               if ( dontUseCopy ) {  
00243                      c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
00244                      c[i].ldctl_value.bv_val = NULL;
00245                      c[i].ldctl_value.bv_len = 0;
00246                      c[i].ldctl_iscritical = dontUseCopy > 1;
00247                      i++;    
00248               }
00249 #endif
00250        }
00251 
00252        tool_server_controls( ld, c, i );
00253 
00254        if ( verbose ) {
00255               fprintf( stderr, _("DN:%s, attr:%s, value:%s\n"),
00256                      compdn, attrs, sep );
00257        }
00258 
00259        rc = docompare( ld, compdn, attrs, &bvalue, quiet, NULL, NULL );
00260 
00261        free( bvalue.bv_val );
00262 
00263        tool_exit( ld, rc );
00264 }
00265 
00266 
00267 static int docompare(
00268        LDAP *ld,
00269        char *dn,
00270        char *attr,
00271        struct berval *bvalue,
00272        int quiet,
00273        LDAPControl **sctrls,
00274        LDAPControl **cctrls )
00275 {
00276        int           rc, msgid, code;
00277        LDAPMessage   *res;
00278        char          *matcheddn;
00279        char          *text;
00280        char          **refs;
00281        LDAPControl **ctrls = NULL;
00282 
00283        if ( dont ) {
00284               return LDAP_SUCCESS;
00285        }
00286 
00287        rc = ldap_compare_ext( ld, dn, attr, bvalue,
00288               sctrls, cctrls, &msgid );
00289        if ( rc == -1 ) {
00290               return( rc );
00291        }
00292 
00293        for ( ; ; ) {
00294               struct timeval       tv;
00295 
00296               tv.tv_sec = 0;
00297               tv.tv_usec = 100000;
00298 
00299               if ( tool_check_abandon( ld, msgid ) ) {
00300                      return LDAP_CANCELLED;
00301               }
00302 
00303               rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
00304               if ( rc < 0 ) {
00305                      tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
00306                      return rc;
00307               }
00308 
00309               if ( rc != 0 ) {
00310                      break;
00311               }
00312        }
00313 
00314        rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 );
00315 
00316        if( rc != LDAP_SUCCESS ) {
00317               fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
00318                      prog, ldap_err2string( rc ), rc );
00319               return rc;
00320        }
00321 
00322        if ( !quiet && ( verbose || ( code != LDAP_SUCCESS && code != LDAP_COMPARE_TRUE && code != LDAP_COMPARE_FALSE )||
00323               (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) )
00324        {
00325               printf( _("Compare Result: %s (%d)\n"),
00326                      ldap_err2string( code ), code );
00327 
00328               if( text && *text ) {
00329                      printf( _("Additional info: %s\n"), text );
00330               }
00331 
00332               if( matcheddn && *matcheddn ) {
00333                      printf( _("Matched DN: %s\n"), matcheddn );
00334               }
00335 
00336               if( refs ) {
00337                      int i;
00338                      for( i=0; refs[i]; i++ ) {
00339                             printf(_("Referral: %s\n"), refs[i] );
00340                      }
00341               }
00342        }
00343 
00344        /* if we were told to be quiet, use the return value. */
00345        if ( !quiet ) {
00346               if ( code == LDAP_COMPARE_TRUE ) {
00347                      printf(_("TRUE\n"));
00348               } else if ( code == LDAP_COMPARE_FALSE ) {
00349                      printf(_("FALSE\n"));
00350               } else {
00351                      printf(_("UNDEFINED\n"));
00352               }
00353        }
00354 
00355        if ( ctrls ) {
00356               tool_print_ctrls( ld, ctrls );
00357               ldap_controls_free( ctrls );
00358        }
00359 
00360        ber_memfree( text );
00361        ber_memfree( matcheddn );
00362        ber_memvfree( (void **) refs );
00363 
00364        return( code );
00365 }
00366