mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-15 03:01:09 +08:00
419 lines
11 KiB
C
419 lines
11 KiB
C
#if !defined(lint)
|
|
static char copyright[] = "Copyright 1992 The University of Adelaide";
|
|
#endif
|
|
|
|
/*
|
|
* W H O I S + +
|
|
*
|
|
* Author: Mark R. Prior
|
|
* Communications and Systems Branch
|
|
* Information Technology Division
|
|
* The University of Adelaide
|
|
* E-mail: mrp@itd.adelaide.edu.au
|
|
* Date: October 1992
|
|
* Version: 1.7
|
|
* Description:
|
|
* This is an experimental implementation of the proposed IETF
|
|
* WNILS WG update to the whois/nicname protocol (whois++).
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that the above copyright notice and this paragraph are
|
|
* duplicated in all such forms and that any documentation,
|
|
* advertising materials, and other materials related to such
|
|
* distribution and use acknowledge that the software was developed
|
|
* by the University of Adelaide. The name of the University may not
|
|
* be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*/
|
|
|
|
#include "whois++.h"
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
|
|
static initialise();
|
|
|
|
main( argc, argv )
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
FILE *tailorFile, *bannerFile;
|
|
char tailor[MAXPATHLEN];
|
|
char query[BUFSIZ], buffer[BUFSIZ];
|
|
char *s, *hostname, *remote;
|
|
char **info;
|
|
int i, printInfo = FALSE;
|
|
extern char *optarg;
|
|
LDAP *ld;
|
|
LDAPMessage *result, *entry;
|
|
int timelimit = DEFAULT_TIMELIMIT;
|
|
struct hostent *hp;
|
|
static struct sockaddr sa;
|
|
struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
|
|
/* #### length should be socklen_t when we include portable.h #### */
|
|
int length = sizeof(sa);
|
|
static char options[] = "[-b searchbase] [-d debug ] \
|
|
[-h ldaphost ] [-i] [-l] [-s sizelimit] [-t timelimit] [-T tailorfile ] \
|
|
[-u user] [-v]";
|
|
static char *attributes[] =
|
|
{ "businessCategory", "info", NULL };
|
|
|
|
if ( (program = strrchr( argv[0], '/' )) == NULL )
|
|
program = strdup( argv[0] );
|
|
else
|
|
program = strdup( program + 1 );
|
|
|
|
#if defined(LOG_DAEMON)
|
|
openlog(program, LOG_PID, FACILITY );
|
|
#else
|
|
openlog(program, LOG_PID );
|
|
#endif
|
|
|
|
initialise();
|
|
|
|
sprintf( tailor, "%s/%stailor", ETCDIR, program );
|
|
if ( (tailorFile = fopen( tailor, "r" )) != NULL ) {
|
|
readConfiguration( tailorFile );
|
|
fclose( tailorFile );
|
|
}
|
|
|
|
while ( (i = getopt( argc, argv, "b:d:h:ils:t:T:u:v?" )) != EOF ) {
|
|
switch ( i ) {
|
|
case 'b': /* search base */
|
|
base = strdup( optarg );
|
|
break;
|
|
|
|
case 'd': /* debug */
|
|
debug = atoi( optarg );
|
|
break;
|
|
|
|
case 'h': /* ldap host */
|
|
ldaphost = strdup( optarg );
|
|
break;
|
|
|
|
case 'i': /* print info attribute */
|
|
printInfo = TRUE;
|
|
break;
|
|
|
|
case 'l': /* enable logging via syslog */
|
|
log = TRUE;
|
|
break;
|
|
|
|
case 's': /* size limit */
|
|
if ( ( maxHits = atoi( optarg ) ) < 1 ) {
|
|
fprintf( stderr, "%s: Invalid maxhits value\n",
|
|
program );
|
|
syslog( LOG_ERR, "Invalid maxhits value" );
|
|
exit( 1 );
|
|
}
|
|
maximumSize = maxHits;
|
|
break;
|
|
|
|
case 't': /* time limit */
|
|
timelimit = atoi( optarg );
|
|
break;
|
|
|
|
case 'T': /* tailor file */
|
|
if ( (tailorFile = fopen( optarg, "r" )) != NULL ) {
|
|
readConfiguration( tailorFile );
|
|
fclose( tailorFile );
|
|
} else {
|
|
perror( program );
|
|
exit( 1 );
|
|
}
|
|
break;
|
|
|
|
case 'u': /* user to bind as */
|
|
user = strdup( optarg );
|
|
break;
|
|
|
|
case 'v': /* version */
|
|
fprintf( stderr, "%s: %s %d.%s\n",
|
|
program, RELEASE, REVISION, version() );
|
|
exit( 0 );
|
|
|
|
default: /* usage message, don't "fail" if ? */
|
|
fprintf( stderr, "usage: %s %s\n", program, options );
|
|
exit( i != '?' );
|
|
}
|
|
}
|
|
|
|
language = defaultLanguage;
|
|
|
|
/*
|
|
* We can cope without knowing most things but we do need to know
|
|
* where to start looking!
|
|
*/
|
|
if ( base == NULL ) {
|
|
syslog( LOG_ERR, "No base specified" );
|
|
fprintf( stderr, "%s: No base specified.\n", program );
|
|
exit( 1 );
|
|
}
|
|
|
|
if ( ! debug ) {
|
|
if ( getpeername(0, &sa, &length) < 0) {
|
|
perror( "getpeername" );
|
|
exit( 1 );
|
|
}
|
|
if ( log ) {
|
|
if ( ( hp = gethostbyaddr((char *) &sin->sin_addr,
|
|
sizeof(sin->sin_addr), AF_INET) ) != 0 ) {
|
|
hostname = strdup( hp->h_name );
|
|
if ( ( hp = gethostbyname( hostname ) ) == 0 ) {
|
|
free( hostname );
|
|
hostname = strdup( inet_ntoa(sin->sin_addr) );
|
|
}
|
|
} else
|
|
hostname = strdup( inet_ntoa(sin->sin_addr) );
|
|
#if defined(RFC931)
|
|
remote = rfc931_name( sin );
|
|
#else
|
|
remote = NULL;
|
|
#endif
|
|
syslog( LOG_INFO, "Connection from %s%s%s [%s]",
|
|
(remote)?remote:"", (remote)?"@":"",
|
|
hostname, inet_ntoa(sin->sin_addr) );
|
|
}
|
|
}
|
|
|
|
if ( (ld = ldap_init( ldaphost, LDAP_PORT )) == NULL ) {
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Connection to LDAP port on %s has failed", ldaphost );
|
|
syslog( LOG_ERR, "Initialization of LDAP session (%s)",
|
|
ldaphost );
|
|
exit( 1 );
|
|
}
|
|
ld->ld_timelimit = timelimit;
|
|
ld->ld_sizelimit = maxHits;
|
|
ld->ld_deref = LDAP_DEREF_FINDING;
|
|
|
|
ldap_simple_bind_s( ld, user, password );
|
|
switch ( ld->ld_errno ) {
|
|
case LDAP_SUCCESS:
|
|
break;
|
|
|
|
case LDAP_UNAVAILABLE:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Sorry, the X.500 service is temporarily unavailable. \
|
|
Please try again later." );
|
|
syslog( LOG_NOTICE, "X.500 service temporarily unavailable" );
|
|
exit( 1 );
|
|
|
|
default:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Bind to Directory failed, %s",
|
|
ldap_err2string( ld->ld_errno ) );
|
|
syslog( LOG_ERR, "Bind to Directory failed, %s",
|
|
ldap_err2string( ld->ld_errno ) );
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
ldap_search_s( ld, base, LDAP_SCOPE_BASE, "objectclass=*",
|
|
attributes, 0, &result );
|
|
if ( ld->ld_errno != LDAP_SUCCESS ) {
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Read of entry \"%s\" failed, %s",
|
|
base, ldap_err2string( ld->ld_errno ) );
|
|
exit( 1 );
|
|
}
|
|
entry = ldap_first_entry( ld, result );
|
|
organisation = ldap_dn2ufn( ldap_get_dn( ld, entry ) );
|
|
category = ldap_get_values( ld, entry, "businessCategory" );
|
|
|
|
printFormatted( lineLength, FALSE, stdout,
|
|
"Whois++ Service at %s.", ldap_dn2ufn( base ) );
|
|
printFormatted( lineLength, FALSE, stdout,
|
|
"For more information about this service send the \"help\" command." );
|
|
|
|
if ( printInfo && ( info = ldap_get_values( ld, entry, "info" ) ) != NULL ) {
|
|
for ( i = 0; info[i] != NULL; i++ ) {
|
|
printFormatted( lineLength, FALSE, stdout, "" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"%s", info[i] );
|
|
}
|
|
ldap_value_free( info );
|
|
}
|
|
if ( banner != NULL && ( bannerFile = fopen( banner, "r" ) ) != NULL ) {
|
|
printFormatted( lineLength, FALSE, stdout, "" );
|
|
while ( fgets( buffer, BUFSIZ, bannerFile ) != NULL ) {
|
|
i = strlen( buffer );
|
|
while ( i-- > 0 && ( buffer[i] == '\n' || buffer[i] == '\r' ) )
|
|
buffer[i] = '\0';
|
|
printFormatted( lineLength, TRUE, stdout, "%s", buffer );
|
|
}
|
|
fclose( bannerFile );
|
|
}
|
|
printFormatted( lineLength, FALSE, stdout, "" );
|
|
|
|
do {
|
|
*query = '\0';
|
|
holdConnection = FALSE;
|
|
switch ( parseCommand( query ) ) {
|
|
case READ:
|
|
/* No need to search, just read the entry given! */
|
|
ldap_search_s( ld, query, LDAP_SCOPE_BASE,
|
|
"objectclass=*", NULL, 0, &result );
|
|
switch( ld->ld_errno ) {
|
|
case LDAP_SUCCESS:
|
|
break;
|
|
|
|
case LDAP_NO_SUCH_OBJECT:
|
|
/**/ /* PROBABLY WANT SPECIAL PROCESSING HERE */
|
|
|
|
default:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Read failed, %s",
|
|
ldap_err2string( ld->ld_errno ) );
|
|
return 1;
|
|
|
|
}
|
|
displayResult( ld, result, outputFormat );
|
|
break;
|
|
|
|
case SEARCH:
|
|
if ( debug > 2 )
|
|
fprintf( stderr, "LDAP Query %s\n", query );
|
|
if ( log )
|
|
syslog( LOG_INFO, "LDAP Query %s", query );
|
|
|
|
ld->ld_sizelimit = maxHits;
|
|
ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, query,
|
|
NULL, 0, &result );
|
|
switch ( ld->ld_errno ) {
|
|
case LDAP_SUCCESS:
|
|
break;
|
|
|
|
case LDAP_SIZELIMIT_EXCEEDED:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Partial results only - a size limit \
|
|
was exceeded, only %d entries returned", ldap_count_entries( ld, result ) );
|
|
break;
|
|
|
|
case LDAP_TIMELIMIT_EXCEEDED:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Partial results only - a time limit \
|
|
was exceeded." );
|
|
break;
|
|
|
|
default:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Search failed, %s",
|
|
ldap_err2string( ld->ld_errno ) );
|
|
exit( 1 );
|
|
|
|
}
|
|
displayResult( ld, result, outputFormat );
|
|
break;
|
|
|
|
case HELP:
|
|
needHelp( lowerCase( query ) );
|
|
break;
|
|
|
|
case DESCRIBE:
|
|
displayDescribe( ld, base );
|
|
break;
|
|
|
|
case VERSION:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Whois++ Protocol version %s", PROTOCOL );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Program version %s %d.%s",
|
|
RELEASE, REVISION, version() );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Default language is %s", defaultLanguage );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Built by %s", BUILD );
|
|
break;
|
|
|
|
case LIST:
|
|
listTemplates( lowerCase( query ) );
|
|
break;
|
|
|
|
case SHOW:
|
|
showTemplate( lowerCase( query ) );
|
|
break;
|
|
|
|
case CONSTRAINTS:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"This implementation supports the following constraints." );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Local constraints are" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" match=(exact|fuzzy)" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Global constraints are" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" format=(full|abridged|handle|summary)" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" hold" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" language=<string>" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" linelength=<number>" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" maxhits=<number>" );
|
|
break;
|
|
|
|
case COMMAND:
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
"Commands supported by this implementation are" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" command" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" constraints" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" describe" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" help" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" list" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" show" );
|
|
printFormatted( lineLength, TRUE, stdout,
|
|
" version" );
|
|
break;
|
|
|
|
case ERROR:
|
|
break;
|
|
|
|
}
|
|
} while ( holdConnection );
|
|
closelog();
|
|
ldap_unbind( ld );
|
|
}
|
|
|
|
static initialise()
|
|
|
|
{
|
|
char buffer[BUFSIZ];
|
|
|
|
debug = FALSE;
|
|
maxHits = DEFAULT_SIZELIMIT;
|
|
maximumSize = maxHits;
|
|
outputFormat = NULL;
|
|
lineLength = DEFAULT_LINE_LENGTH;
|
|
ldaphost = DEFAULT_LDAPHOST;
|
|
defaultLanguage = DEFAULT_LANGUAGE;
|
|
locale = "";
|
|
base = NULL;
|
|
contact = NULL;
|
|
if ( gethostname( buffer, BUFSIZ ) == 0 )
|
|
hostname = strdup( buffer );
|
|
else
|
|
hostname = NULL;
|
|
user = NULL;
|
|
password = NULL;
|
|
helpDir = HELP_DIRECTORY;
|
|
configDir = CONFIG_DIRECTORY;
|
|
organisation = NULL;
|
|
banner = NULL;
|
|
log = FALSE;
|
|
numberOfTemplates = 0;
|
|
tableSize = TABLE_INCREMENT;
|
|
templateTranslationTable = NULL;
|
|
}
|