modules/pw/protocol_whois.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- print_hello_banner
- PW_interact
/***************************************
$Revision: 1.24 $
Protocol whois module (pw). Whois protocol.
Status: NOT REVUED, TESTED
******************/ /******************
Filename : protocol_whois.c
Authors : ottrey@ripe.net
marek@ripe.net
OSs Tested : Solaris
******************/ /******************
Copyright (c) 1999 RIPE NCC
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the author not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
***************************************/
#include <stdio.h>
#include <glib.h>
#include "NAME"
#include "defs.h"
#include "protocol_whois.h"
#include "mysql_driver.h"
#include "query_command.h"
#include "query_instructions.h"
#include "constants.h"
/*
#include "objects.h"
*/
#include "access_control.h"
#include "socket.h"
#include "stubs.h"
#include <sys/time.h> /* in Solaris, or time.h in BSD,
wrrrr... the fun begins... */
void print_hello_banner(Query_environ *qe) {
/* [<][>][^][v][top][bottom][index][help] */
SK_cd_puts(&(qe->condat), CVS_NAME);
SK_cd_puts(&(qe->condat), "% Rights restricted by copyright. \n% See http://www.ripe.net/ripencc/pub-services/db/copyright.html\n");
#if 0
/* Send the environment aswell. */
SK_cd_puts(&(qe->condat), "% Environment={");
str1 = QC_environ_to_string(*qe);
SK_cd_puts(&(qe->condat), str1);
wr_free(str1);
SK_cd_puts(&(qe->condat), "}\n");
#endif
SK_cd_puts(&(qe->condat), "\n");
}
/* PW_interact() */
/*++++++++++++++++++++++++++++++++++++++
Interact with the client.
int sock Socket that client is connected to.
More:
+html+ <PRE>
Authors:
ottrey
+html+ </PRE><DL COMPACT>
+html+ <DT>Online References:
+html+ <DD><UL>
+html+ </UL></DL>
++++++++++++++++++++++++++++++++++++++*/
void PW_interact(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
char input[MAX_INPUT_SIZE];
int read_result;
char *hostaddress=NULL;
acl_st acl_rip, acl_eip;
acc_st acc_credit, copy_credit;
int permanent_ban=0;
Query_environ *qe=NULL;
Query_instructions *qis=NULL;
Query_command *qc=NULL;
GList *qitem;
int new_connection=1;
int acc_deny=0;
struct timeval begintime, endtime;
/* Get the IP of the client */
hostaddress = SK_getpeername(sock);
ER_dbg_va(FAC_PW, 1, "connection from %s", hostaddress);
/* Initialize the query environment. */
qe = QC_environ_new(hostaddress, sock);
/* init to zeros */
memset( &(qe->condat), 0, sizeof(sk_conn_st));
/* set the connection data: both rIP and eIP to real IP */
qe->condat.sock = sock;
qe->condat.ip = hostaddress;
SK_getpeerip(sock, &(qe->condat.rIP));
qe->condat.eIP = qe->condat.rIP;
/* see if we should be talking at all */
/* check the acl using the realIP, get a copy applicable to this IP */
AC_check_acl( &(qe->condat.rIP), NULL, &acl_rip);
if( acl_rip.deny ) {
permanent_ban=1;
}
/* XXX log new connection here ?*/
do {
/* Read input */
read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE);
gettimeofday(&begintime, NULL);
/* read_result < 0 is an error and connection should be closed */
if (read_result < 0 ) {
/* XXX log the fact, rtc was set */
/* EMPTY */
}
qc = QC_create(input, qe);
/* ADDRESS PASSING: check if -V option has passed IP in it */
if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
if(acl_rip.trustpass) {
acc_st pass_acc;
/* accounting */
memset(&pass_acc, 0, sizeof(acc_st));
pass_acc.addrpasses=1;
AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
/* set eIP to this IP */
qe->condat.eIP = qe->pIP;
}
else {
/* XXX shall we deny such user ? Now we can... */
ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
"unauthorised address passing by %s", hostaddress);
}
}
/* start setting counters in the connection acc from here on
decrement the credit counter (needed to prevent QI_execute from
returning too many results */
/* check ACL. Get the proper acl record. Calculate credit */
AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
/* save the original credit, later check how much was used */
copy_credit = acc_credit;
if( acl_eip.deny ) {
permanent_ban = 1;
}
if( qe->condat.rtc == 0 ) {
print_hello_banner(qe);
if( permanent_ban ) {
SK_cd_puts(&(qe->condat),
"% Sorry, access from your host has been permanently denied\n"
"% because of a repeated abusive behaviour.\n"
"% Please contact <ripe-dbm@ripe.net> for unblocking\n");
ER_inf_va(FAC_PW, ASP_PWI_DENTRY,
"connection from host %s DENIED", hostaddress);
}
else {
switch( qc->query_type ) {
case QC_ERROR:
SK_cd_puts(&(qe->condat), USAGE);
break;
case QC_NOKEY:
/* some operational stuff, like -k */
break;
case QC_EMPTY:
/* The user didn't specify a key, so
- print moron banner
- force disconnection of the user. */
SK_cd_puts(&(qe->condat), "% No search key specified\n");
qe->condat.rtc = SK_NOTEXT;
break;
case QC_HELP:
SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
break;
case QC_TEMPLATE:
if (qc->q >= 0) {
SK_cd_puts(&(qe->condat), DF_get_server_query(qc->q));
}
if (qc->t >= 0) {
SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
}
if (qc->v >= 0) {
SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
}
break;
case QC_FILTERED:
SK_cd_puts(&(qe->condat), "% Note: this output has been filtered.\n% Only primary keys will be visible.\n% Contact information will not be shown\n\n");
/* FALLTROUGH */
case QC_REAL:
qis = QI_new(qc,qe);
/* stop as soon as further action considered meaningless */
for( qitem = g_list_first(qe->sources_list);
qitem != NULL && qe->condat.rtc == 0;
qitem = g_list_next(qitem)) {
/* QI will decrement the credit counters */
QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip );
}
QI_free(qis);
copy_credit.queries ++;
if( acc_credit.denials != 0 ) {
SK_cd_puts(&(qe->condat),
"% You have reached the limit of returned contact information objects.\n"
"% This connection will be terminated now.\n"
"% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
"% You will not be allowed to query for more CONTACT information for a while.\n"
"% Continued attempts to return excessive amounts of contact\n"
"% information will result in permanent denial of service.\n"
"% Please do not try to use CONTACT information information in the\n"
"% RIPE Database for non-operational purposes.\n"
"% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
);
}
break;
default: die;
}
/* calc. the credit used, result into copy_credit */
AC_acc_addup(©_credit, &acc_credit, ACC_MINUS);
{
char *qrystat = AC_credit_to_string(©_credit);
float elapsed;
char *qrytypestr =
qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
gettimeofday(&endtime, NULL);
elapsed = ( endtime.tv_sec - begintime.tv_sec ) +
1e-6 * ( endtime.tv_usec - begintime.tv_usec ) ;
/* log the connection/query/#results/time/denial to file */
ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
"<%s> %s %.2fs [%s] -- %s",
qrystat, qrytypestr,
elapsed, hostaddress, input
);
wr_free(qrystat);
}
}/* if denied ... else */
QC_free(qc);
if( new_connection ) {
copy_credit.connections = 1;
new_connection = 0;
}
if( copy_credit.denials != 0 ) {
acc_deny = 1;
}
/* Commit the credit. This will deny if bonus limit hit */
AC_commit(&(qe->condat.eIP), ©_credit, &acl_eip);
} /* if still considered connected */
} /* do */
while( qe->k && qe->condat.rtc == 0 && acc_deny == 0
&& CO_get_whois_suspended() == 0);
/* Free the hostaddress */
wr_free(hostaddress);
SK_cd_close(&(qe->condat));
/* Free the query_environ */
QC_environ_free(qe);
} /* PW_interact() */