Commit 5f20cf1e authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Modify ldapsearch(1) significantly. Now handles LDAPv3 search

references, extended results, and extended partial results.  LDIF
extended to support these new features and reported version 2.
-L now limits output to LDIFv1 for compatibility reasons.  No
-L is now LDIFv2.  Old alternative form is no longer supported.

Use LDAP_TMPDIR (in ldap_config.h) instead of hardcoded /tmp
Use LDAP_FILE_URI_PREFIX (in ldap_config.h) instead of hardcoded
	file://tmp/
parent 49f41473
......@@ -63,7 +63,7 @@ usage( const char *s )
" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
" -n\t\tshow what would be done but don't actually delete\n"
" -p port\t\tport on LDAP server\n"
" -P version\tprocotol version (2 or 3)\n"
" -P version\tprocotol version (default: 3)\n"
" -r\t\tdelete recursively\n"
" -U user\t\tSASL authentication identity (username)\n"
" -v\t\trun in verbose mode (diagnostics to standard output)\n"
......@@ -303,10 +303,15 @@ main( int argc, char **argv )
/* don't chase referrals */
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
if (version != -1 &&
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
if (version == -1 ) {
version = 3;
}
if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
!= LDAP_OPT_SUCCESS )
{
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
version );
}
if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
......
......@@ -45,7 +45,7 @@ static int sasl_integrity = 0;
static int sasl_privacy = 0;
#endif
static int use_tls = 0;
static int new, replace, not, verbose, contoper, force, valsfromfiles;
static int ldapadd, replace, not, verbose, contoper, force;
static LDAP *ld;
#define LDAPMOD_MAXLINE 4096
......@@ -71,14 +71,12 @@ static LDAP *ld;
static void usage LDAP_P(( const char *prog )) LDAP_GCCATTR((noreturn));
static int process_ldapmod_rec LDAP_P(( char *rbuf ));
static int process_ldif_rec LDAP_P(( char *rbuf, int count ));
static void addmodifyop LDAP_P(( LDAPMod ***pmodsp, int modop, char *attr,
char *value, int vlen ));
static int domodify LDAP_P(( char *dn, LDAPMod **pmods, int newentry ));
static int dodelete LDAP_P(( char *dn ));
static int domodrdn LDAP_P(( char *dn, char *newrdn, int deleteoldrdn ));
static int fromfile LDAP_P(( char *path, struct berval *bv ));
static char *read_one_record LDAP_P(( FILE *fp ));
static void
......@@ -104,7 +102,7 @@ usage( const char *prog )
" -k\t\tuse Kerberos authentication\n"
" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
" -n\t\tprint adds, don't actually do them\n"
" -n\t\tprint changes, don't actually do them\n"
" -p port\t\tport on LDAP server\n"
" -r\t\treplace values\n"
" -U user\t\tSASL authentication identity (username)\n"
......@@ -121,9 +119,9 @@ usage( const char *prog )
int
main( int argc, char **argv )
{
char *infile, *rbuf, *start, *p, *q;
char *infile, *rbuf, *start;
FILE *fp;
int rc, i, use_ldif, authmethod, version, want_bindpw, debug, manageDSAit;
int rc, i, authmethod, version, want_bindpw, debug, manageDSAit;
int count;
if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) {
......@@ -133,23 +131,19 @@ main( int argc, char **argv )
}
/* Print usage when no parameters */
if( argc < 2 )
usage( prog );
if( argc < 2 ) usage( prog );
new = ( strcmp( prog, "ldapadd" ) == 0 );
ldapadd = ( strcmp( prog, "ldapadd" ) == 0 );
infile = NULL;
not = verbose = valsfromfiles = want_bindpw = debug = manageDSAit = 0;
not = verbose = want_bindpw = debug = manageDSAit = 0;
authmethod = LDAP_AUTH_SIMPLE;
version = -1;
while (( i = getopt( argc, argv, "abcD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) {
while (( i = getopt( argc, argv, "acD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) {
switch( i ) {
case 'a': /* add */
new = 1;
break;
case 'b': /* read values from files (for binary attributes) */
valsfromfiles = 1;
ldapadd = 1;
break;
case 'c': /* continuous operation */
contoper = 1;
......@@ -359,18 +353,18 @@ main( int argc, char **argv )
return( EXIT_FAILURE );
}
/* this seems prudent */
{
int deref = LDAP_DEREF_NEVER;
ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
}
/* don't chase referrals */
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
if (version != -1 &&
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
if (version == -1 ) {
version = 3;
}
if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
!= LDAP_OPT_SUCCESS )
{
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION to %d\n", version );
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
version );
}
if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
......@@ -464,49 +458,18 @@ main( int argc, char **argv )
while (( rc == 0 || contoper ) &&
( rbuf = read_one_record( fp )) != NULL ) {
count++;
/*
* we assume record is ldif/slapd.replog if the first line
* has a colon that appears to the left of any equal signs, OR
* if the first line consists entirely of digits (an entry id)
*/
#ifdef LDAP_LDIF
use_ldif = 1;
#else
use_ldif = ( *rbuf == '#' ) ||
(( p = strchr( rbuf, ':' )) != NULL &&
( q = strchr( rbuf, '\n' )) != NULL && p < q &&
(( q = strchr( rbuf, '=' )) == NULL || p < q ));
#endif
start = rbuf;
if ( !use_ldif && ( q = strchr( rbuf, '\n' )) != NULL ) {
for ( p = rbuf; p < q; ++p ) {
if ( !isdigit( (unsigned char) *p )) {
break;
}
}
if ( p >= q ) {
use_ldif = 1;
start = q + 1;
}
}
if ( use_ldif ) {
rc = process_ldif_rec( start, count );
} else {
rc = process_ldapmod_rec( start );
}
rc = process_ldif_rec( start, count );
if( rc )
fprintf( stderr, "%s() = %d\n",
use_ldif ? "ldif_rec" : "ldapmod_rec" , rc );
free( rbuf );
fprintf( stderr, "ldif_record() = %d\n", rc );
free( rbuf );
}
if ( !not ) {
ldap_unbind( ld );
ldap_unbind( ld );
}
return( rc );
......@@ -525,7 +488,7 @@ process_ldif_rec( char *rbuf, int count )
LDAPMod **pmods;
int version;
new_entry = new;
new_entry = ldapadd;
rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0;
expect_deleteoldrdn = expect_newrdn = expect_newsup = 0;
......@@ -617,7 +580,7 @@ process_ldif_rec( char *rbuf, int count )
rc = LDAP_PARAM_ERROR;
}
goto end_line;
} else if ( new ) { /* missing changetype => add */
} else if ( ldapadd ) { /* missing changetype => add */
new_entry = 1;
modop = LDAP_MOD_ADD;
} else {
......@@ -730,190 +693,85 @@ end_line:
}
static int
process_ldapmod_rec( char *rbuf )
static void
addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
{
char *line, *dn, *p, *q, *attr, *value;
int rc, linenum, modop;
LDAPMod **pmods;
pmods = NULL;
dn = NULL;
linenum = 0;
line = rbuf;
rc = 0;
while ( rc == 0 && rbuf != NULL && *rbuf != '\0' ) {
++linenum;
if (( p = strchr( rbuf, '\n' )) == NULL ) {
rbuf = NULL;
} else {
if ( *(p-1) == '\\' ) { /* lines ending in '\' are continued */
SAFEMEMCPY( p - 1, p, strlen( p ) + 1 );
rbuf = p;
continue;
}
*p++ = '\0';
rbuf = p;
LDAPMod **pmods;
int i, j;
struct berval *bvp;
pmods = *pmodsp;
modop |= LDAP_MOD_BVALUES;
i = 0;
if ( pmods != NULL ) {
for ( ; pmods[ i ] != NULL; ++i ) {
if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
pmods[ i ]->mod_op == modop )
{
break;
}
}
}
if ( dn == NULL ) { /* first line contains DN */
if (( dn = strdup( line )) == NULL ) {
perror( "strdup" );
exit( EXIT_FAILURE );
}
} else {
if (( p = strchr( line, '=' )) == NULL ) {
value = NULL;
p = line + strlen( line );
} else {
*p++ = '\0';
value = p;
}
for ( attr = line;
*attr != '\0' && isspace( (unsigned char) *attr ); ++attr ) {
; /* skip attribute leading white space */
}
for ( q = p - 1; q > attr && isspace( (unsigned char) *q ); --q ) {
*q = '\0'; /* remove attribute trailing white space */
}
if ( value != NULL ) {
while ( isspace( (unsigned char) *value )) {
++value; /* skip value leading white space */
}
for ( q = value + strlen( value ) - 1; q > value &&
isspace( (unsigned char) *q ); --q ) {
*q = '\0'; /* remove value trailing white space */
}
if ( *value == '\0' ) {
value = NULL;
if ( pmods == NULL || pmods[ i ] == NULL ) {
if (( pmods = (LDAPMod **)ber_memrealloc( pmods, (i + 2) *
sizeof( LDAPMod * ))) == NULL )
{
perror( "realloc" );
exit( EXIT_FAILURE );
}
}
*pmodsp = pmods;
pmods[ i + 1 ] = NULL;
if ( value == NULL && new ) {
fprintf( stderr, "%s: missing value on line %d (attr=\"%s\")\n",
prog, linenum, attr );
rc = LDAP_PARAM_ERROR;
} else {
switch ( *attr ) {
case '-':
modop = LDAP_MOD_DELETE;
++attr;
break;
case '+':
modop = LDAP_MOD_ADD;
++attr;
break;
default:
modop = replace ? LDAP_MOD_REPLACE : LDAP_MOD_ADD;
pmods[ i ] = (LDAPMod *)ber_memcalloc( 1, sizeof( LDAPMod ));
if ( pmods[ i ] == NULL ) {
perror( "calloc" );
exit( EXIT_FAILURE );
}
addmodifyop( &pmods, modop, attr, value,
( value == NULL ) ? 0 : strlen( value ));
}
}
line = rbuf;
}
if ( rc == 0 ) {
if ( dn == NULL ) {
rc = LDAP_PARAM_ERROR;
} else if (( rc = domodify( dn, pmods, new )) == LDAP_SUCCESS ) {
rc = 0;
pmods[ i ]->mod_op = modop;
pmods[ i ]->mod_type = ber_strdup( attr );
if ( pmods[ i ]->mod_type == NULL ) {
perror( "strdup" );
exit( EXIT_FAILURE );
}
}
}
if ( pmods != NULL ) {
ldap_mods_free( pmods, 1 );
}
if ( dn != NULL ) {
free( dn );
}
return( rc );
}
static void
addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
{
LDAPMod **pmods;
int i, j;
struct berval *bvp;
pmods = *pmodsp;
modop |= LDAP_MOD_BVALUES;
if ( value != NULL ) {
j = 0;
if ( pmods[ i ]->mod_bvalues != NULL ) {
for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
/* Empty */;
}
}
i = 0;
if ( pmods != NULL ) {
for ( ; pmods[ i ] != NULL; ++i ) {
if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
pmods[ i ]->mod_op == modop ) {
break;
}
}
}
pmods[ i ]->mod_bvalues = (struct berval **) ber_memrealloc(
pmods[ i ]->mod_bvalues, (j + 2) * sizeof( struct berval * ));
if ( pmods[ i ]->mod_bvalues == NULL ) {
perror( "ber_realloc" );
exit( EXIT_FAILURE );
}
if ( pmods == NULL || pmods[ i ] == NULL ) {
if (( pmods = (LDAPMod **)ber_memrealloc( pmods, (i + 2) *
sizeof( LDAPMod * ))) == NULL ) {
perror( "realloc" );
exit( EXIT_FAILURE );
}
*pmodsp = pmods;
pmods[ i + 1 ] = NULL;
if (( pmods[ i ] = (LDAPMod *)ber_memcalloc( 1, sizeof( LDAPMod )))
== NULL ) {
perror( "calloc" );
exit( EXIT_FAILURE );
}
pmods[ i ]->mod_op = modop;
if (( pmods[ i ]->mod_type = ber_strdup( attr )) == NULL ) {
perror( "strdup" );
exit( EXIT_FAILURE );
}
}
pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
bvp = (struct berval *)ber_memalloc( sizeof( struct berval ));
if ( bvp == NULL ) {
perror( "ber_memalloc" );
exit( EXIT_FAILURE );
}
pmods[ i ]->mod_bvalues[ j ] = bvp;
if ( value != NULL ) {
j = 0;
if ( pmods[ i ]->mod_bvalues != NULL ) {
for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
;
}
}
if (( pmods[ i ]->mod_bvalues =
(struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
(j + 2) * sizeof( struct berval * ))) == NULL ) {
perror( "ber_realloc" );
exit( EXIT_FAILURE );
}
pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
== NULL ) {
perror( "ber_memalloc" );
exit( EXIT_FAILURE );
}
pmods[ i ]->mod_bvalues[ j ] = bvp;
bvp->bv_len = vlen;
bvp->bv_val = (char *)ber_memalloc( vlen + 1 );
if ( bvp->bv_val == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
if ( valsfromfiles && *value == '/' ) { /* get value from file */
if ( fromfile( value, bvp ) < 0 ) {
exit( EXIT_FAILURE );
}
} else {
bvp->bv_len = vlen;
if (( bvp->bv_val = (char *)ber_memalloc( vlen + 1 )) == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
SAFEMEMCPY( bvp->bv_val, value, vlen );
bvp->bv_val[ vlen ] = '\0';
SAFEMEMCPY( bvp->bv_val, value, vlen );
bvp->bv_val[ vlen ] = '\0';
}
}
}
......@@ -1032,55 +890,6 @@ domodrdn( char *dn, char *newrdn, int deleteoldrdn )
}
static int
fromfile( char *path, struct berval *bv )
{
FILE *fp;
long rlen;
int eof;
if (( fp = fopen( path, "r" )) == NULL ) {
perror( path );
return( -1 );
}
if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
perror( path );
fclose( fp );
return( -1 );
}
bv->bv_len = ftell( fp );
if (( bv->bv_val = (char *)ber_memalloc( bv->bv_len )) == NULL ) {
perror( "malloc" );
fclose( fp );
return( -1 );
}
if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
perror( path );
fclose( fp );
ber_memfree( bv->bv_val );
bv->bv_val = NULL;
return( -1 );
}
rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
eof = feof( fp );
fclose( fp );
if ( (unsigned long) rlen != bv->bv_len ) {
perror( path );
ber_memfree( bv->bv_val );
bv->bv_val = NULL;
return( -1 );
}
return( bv->bv_len );
}
static char *
read_one_record( FILE *fp )
{
......
......@@ -75,7 +75,7 @@ usage( const char *s )
" -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
" -n\t\tshow what would be done but don't actually do it\n"
" -p port\t\tport on LDAP server\n"
" -P version\tprocotol version (2 or 3)\n"
" -P version\tprocotol version (default: 3)\n"
" -r\t\tremove old RDN\n"
" -s newsuperior\tnew superior entry\n"
" -U user\t\tSASL authentication identity (username)\n"
......@@ -341,19 +341,18 @@ main(int argc, char **argv)
return( EXIT_FAILURE );
}
/* this seems prudent */
{
int deref = LDAP_DEREF_NEVER;
ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
}
/* don't chase referrals */
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
if (version == -1 ) {
version = 3;
}
if (version != -1 &&
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS)
if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
!= LDAP_OPT_SUCCESS )
{
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
version );
}
if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
......
......@@ -30,64 +30,73 @@
#include <ldap.h>
#include "ldif.h"
#include "lutil.h"
#include "ldap_defaults.h"
static void
usage( const char *s )
{
fprintf( stderr,
"usage: %s [options] filter [attributes...]\nwhere:\n"
" filter\tRFC-1558 compliant LDAP search filter\n"
" attributes\twhitespace-separated list of attributes to retrieve\n"
"\t\t1.1 -- no attributes\n"
"\t\t* -- all user attributes\n"
"\t\t+ -- all operational attributes\n"
"\t\tempty list -- all non-operational attributes\n"
"usage: %s [options] [filter [attributes...]]\nwhere:\n"
"\tfilter\tRFC-2254 compliant LDAP search filter\n"
"\tattributes\twhitespace-separated list of attribute descriptions\n"
"\t which may include:\n"
"\t\t1.1 -- no attributes\n"
"\t\t* -- all user attributes\n"
"\t\t+ -- all operational attributes\n"
"options:\n"
" -a deref\tone of `never', `always', `search', or `find' (alias\n"
" \tdereferencing)\n"
" -A\t\tretrieve attribute names only (no values)\n"
" -b basedn\tbase dn for search\n"
" -d level\tset LDAP debugging level to `level'\n"
" -D binddn\tbind DN\n"
" -E\t\trequest SASL privacy (-EE to make it critical)\n"
" -f file\t\tperform sequence of searches listed in `file'\n"
" -h host\t\tLDAP server\n"
" -I\t\trequest SASL integrity checking (-II to make it\n"
" \tcritical)\n"
" -k\t\tuse Kerberos authentication\n"
" -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
" -l limit\ttime limit (in seconds) for search\n"
" -L\t\tprint entries in LDIF format (default)\n"
" -LL\t\tprint entries in LDIF format without comments\n"
" -LLL\t\tprint entries in LDIF format without comments and\n"
" \tversion\n"
" -M\t\tenable Manage DSA IT control (-MM to make critical)\n"
" -n\t\tshow what would be done but don't actually search\n"
" -p port\t\tport on LDAP server\n"
" -P version\tprocotol version (2 or 3)\n"
" -R\t\tdo not automatically follow referrals\n"
" -s scope\tone of base, one, or sub (search scope)\n"
" -S attr\t\tsort the results by attribute `attr'\n"
" -t\t\twrite binary values to files in TMPDIR\n"
" -tt\t\twrite all values to files in TMPDIR\n"
" -T path\t\twrite files to directory specified by path (default:\n"
" \t\"/tmp\")\n"
" -u\t\tinclude User Friendly entry names in the output\n"
" -U user\t\tSASL authentication identity (username)\n"
" -v\t\trun in verbose mode (diagnostics to standard output)\n"
" -V prefix\tURL prefix for files (default: \"file://tmp/\")\n"
" -w passwd\tbind passwd (for simple authentication)\n"