#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 #include #include 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=" ); printFormatted( lineLength, TRUE, stdout, " linelength=" ); printFormatted( lineLength, TRUE, stdout, " maxhits=" ); 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; }