Source File modules/pw/protocol_whois.c

    1    | /***************************************
    2    |   $Revision: 1.30 $
    3    |
    4    |   Protocol whois module (pw).  Whois protocol.
    5    |
    6    |   Status: NOT REVUED, TESTED
    7    |
    8    |   ******************/ /******************
    9    |   Filename            : protocol_whois.c
    10   |   Authors             : ottrey@ripe.net
    11   |                         marek@ripe.net
    12   |   OSs Tested          : Solaris
    13   |   ******************/ /******************
    14   |   Copyright (c) 1999                              RIPE NCC
    15   |
    16   |   All Rights Reserved
    17   |
    18   |   Permission to use, copy, modify, and distribute this software and its
    19   |   documentation for any purpose and without fee is hereby granted,
    20   |   provided that the above copyright notice appear in all copies and that
    21   |   both that copyright notice and this permission notice appear in
    22   |   supporting documentation, and that the name of the author not be
    23   |   used in advertising or publicity pertaining to distribution of the
    24   |   software without specific, written prior permission.
    25   |
    26   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    27   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    28   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    29   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    30   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    31   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    32   |   ***************************************/
    33   | #include <stdio.h>
    34   | #include <glib.h>
    35   |
    36   | #include "NAME"
    37   |
    38   | #include "defs.h"
    39   | #include "protocol_whois.h"
    40   | #include "mysql_driver.h"
    41   | #include "query_command.h"
    42   | #include "query_instructions.h"
    43   | #include "constants.h"
    44   | /*
    45   | #include "objects.h"
    46   | */
    47   | #include "access_control.h"
    48   | #include "socket.h"
    49   | #include "stubs.h"
    50   |
    51   | #include "ca_configFns.h"
    52   | #include "ca_dictSyms.h"
    53   | #include "ca_macros.h"
    54   | #include "ca_srcAttribs.h"
    55   |
    56   | #include "protocol_mirror.h"
    57   |
    58   | #include "ta.h"
    59   |
    60   | #include  "timediff.h"
    61   |
    62   | void print_hello_banner(Query_environ *qe) {
    63   |   SK_cd_puts(&(qe->condat), CVS_NAME);
    64   |   SK_cd_puts(&(qe->condat), "% Rights restricted by copyright. \n% See http://www.ripe.net/ripencc/pub-services/db/copyright.html\n");
    65   |
    66   | #if 0
    67   |   /* Send the environment aswell. */
    68   |   SK_cd_puts(&(qe->condat), "% Environment={");
    69   |   str1 = QC_environ_to_string(*qe);
    70   |   SK_cd_puts(&(qe->condat), str1);
    71   |   wr_free(str1);
    72   |   SK_cd_puts(&(qe->condat), "}\n");
    73   | #endif
    74   |
    75   |   SK_cd_puts(&(qe->condat), "\n");
    76   | }
    77   |
    78   | /* PW_interact() */
    79   | /*++++++++++++++++++++++++++++++++++++++
    80   |   Interact with the client.
    81   |
    82   |   int sock Socket that client is connected to.
    83   |
    84   |   More:
    85   |   +html+ <PRE>
    86   |   Authors:
    87   |         ottrey
    88   |
    89   |   +html+ </PRE><DL COMPACT>
    90   |   +html+ <DT>Online References:
    91   |   +html+ <DD><UL>
    92   |   +html+ </UL></DL>
    93   |
    94   |   ++++++++++++++++++++++++++++++++++++++*/
    95   | void PW_interact(int sock) {
    96   |   char input[MAX_INPUT_SIZE];
    97   |   int read_result;
    98   |   char *hostaddress=NULL;
    99   |   acl_st acl_rip,   acl_eip;
    100  |   acc_st acc_credit, copy_credit;
    101  |   int permanent_ban=0;
    102  |   Query_environ *qe=NULL;
    103  |   Query_instructions *qis=NULL;
    104  |   Query_command *qc=NULL;
    105  |   GList *qitem;
    106  |   ut_timer_t begintime, endtime;
    107  |   er_ret_t err;
    108  |
    109  |   /* Get the IP of the client */
    110  |   hostaddress = SK_getpeername(sock);
    111  |   ER_dbg_va(FAC_PW, 1, "connection from %s", hostaddress);
    112  |
    113  |   /* Initialize the query environment. */
    114  |   qe = QC_environ_new(hostaddress, sock);
    115  |
    116  |   /* init to zeros */
    117  |   memset( &(qe->condat), 0, sizeof(sk_conn_st));
    118  |
    119  |   /* set the connection data: both rIP and eIP to real IP */
    120  |   qe->condat.sock = sock;
    121  |   qe->condat.ip = hostaddress;
    122  |   SK_getpeerip(sock, &(qe->condat.rIP));
    123  |   qe->condat.eIP = qe->condat.rIP;
    124  |
    125  |   qe->condat.rd_timeout.tv_sec = 180; /* read timeout */
    126  |
    127  |   /* see if we should be talking at all */
    128  |   /* check the acl using the realIP, get a copy applicable to this IP */
    129  |   AC_check_acl( &(qe->condat.rIP), NULL, &acl_rip);
    130  |   if( acl_rip.deny ) {
    131  |     permanent_ban=1;
    132  |   }
    133  |
    134  |   do {
    135  |     /* Read input */
    136  |     read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE);
    137  |
    138  |     TA_setactivity(input);
    139  |     TA_increment();
    140  |
    141  |     UT_timeget( &begintime );
    142  |
    143  |     /* read_result < 0 is an error and connection should be closed */
    144  |     if (read_result < 0 ) {
    145  |       /*  XXX log the fact, rtc was set */
    146  |       /* EMPTY */
    147  |     }
    148  |
    149  |     qc = QC_create(input, qe);
    150  |
    151  |     /* ADDRESS PASSING: check if -V option has passed IP in it */
    152  |     if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
    153  |       if(acl_rip.trustpass) {
    154  | 	acc_st pass_acc;
    155  |
    156  | 	/* accounting */
    157  | 	memset(&pass_acc, 0, sizeof(acc_st));
    158  | 	pass_acc.addrpasses=1;
    159  | 	AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
    160  |
    161  | 	/* set eIP to this IP */
    162  | 	qe->condat.eIP = qe->pIP;
    163  |       }
    164  |       else {
    165  | 	/* XXX shall we deny such user ? Now we can... */
    166  | 	ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
    167  | 		  "unauthorised address passing by %s", hostaddress);
    168  |       }
    169  |     }
    170  |
    171  |
    172  |     /* start setting counters in the connection acc from here on
    173  |        decrement the credit counter (needed to prevent QI_execute from
    174  |        returning too many results */
    175  |
    176  |     /* check ACL. Get the proper acl record. Calculate credit */
    177  |     AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
    178  |     /* save the original credit, later check how much was used */
    179  |     copy_credit = acc_credit;
    180  |
    181  |     if( acl_eip.deny ) {
    182  |       permanent_ban = 1;
    183  |     }
    184  |
    185  |     if( qe->condat.rtc == 0 ) {
    186  |       print_hello_banner(qe);
    187  |
    188  |       if( permanent_ban ) {
    189  |         SK_cd_puts(&(qe->condat),
    190  | "% Sorry, access from your host has been permanently denied\n"
    191  | "% because of a repeated abusive behaviour.\n"
    192  | "% Please contact <ripe-dbm@ripe.net> for unblocking\n");
    193  |
    194  | 	ER_inf_va(FAC_PW, ASP_PWI_DENTRY,
    195  | 		  "connection from host %s DENIED", hostaddress);
    196  |
    197  |       }
    198  |       else {
    199  | 	switch( qc->query_type ) {
    200  | 	case QC_ERROR:
    201  | 	  SK_cd_puts(&(qe->condat), USAGE);
    202  | 	  qe->condat.rtc = SK_NOTEXT;
    203  | 	  break;
    204  | 	case QC_NOKEY:
    205  | 	  /* no key (this is OK for some operational stuff, like -k) */
    206  | 	  break;
    207  |         case QC_EMPTY:
    208  |
    209  |           /* The user didn't specify a key, so
    210  |              - print moron banner
    211  |              - force disconnection of the user. */
    212  |           SK_cd_puts(&(qe->condat), "% No search key specified\n");
    213  |           qe->condat.rtc = SK_NOTEXT;
    214  |           break;
    215  |         case QC_HELP:
    216  |           SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
    217  |           break;
    218  |         case QC_TEMPLATE:
    219  | 	  switch(qc->q) {
    220  | 	  case QC_Q_SOURCES:
    221  | 	    /* print source & mirroring info */
    222  | 	    {
    223  | 	      GString *srcs = PM_get_nrtm_sources( & qe->condat.rIP, NULL);
    224  | 	      SK_cd_puts(&(qe->condat), srcs->str);
    225  | 	      g_string_free (srcs, TRUE);
    226  | 	    }
    227  | 	    break;
    228  | 	  case QC_Q_VERSION:
    229  | 	    SK_cd_puts(&(qe->condat), DF_get_server_query(qc->q));
    230  | 	    break;
    231  | 	  default:
    232  | 	    /* EMPTY */;
    233  | 	  } /* -q */
    234  |
    235  | 	  if (qc->t >= 0) {
    236  | 	    SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
    237  |           }
    238  |           if (qc->v >= 0) {
    239  |             SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
    240  |           }
    241  |           break;
    242  |
    243  | 	case QC_FILTERED:
    244  | 	  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");
    245  |
    246  | 	  /* FALLTROUGH */
    247  |         case QC_REAL:
    248  |           qis = QI_new(qc,qe);
    249  |
    250  | 	  /* stop as soon as further action considered meaningless */
    251  |           for( qitem = g_list_first(qe->sources_list);
    252  |                qitem != NULL && qe->condat.rtc == 0;
    253  |                qitem = g_list_next(qitem)) {
    254  |
    255  |             /* QI will decrement the credit counters */
    256  |             err = QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip );
    257  |
    258  | 	    if( !NOERR(err) ) {
    259  | 	      if( err == QI_CANTDB ) {
    260  | 		SK_cd_puts(&(qe->condat), "% WARNING: Failed to make connection to ");
    261  | 		SK_cd_puts(&(qe->condat), (char *)qitem->data);
    262  | 		SK_cd_puts(&(qe->condat), " database.\n\n");
    263  | 	      }
    264  |
    265  | 	      break; /* quit the loop after any error */
    266  | 	    }/* if */
    267  |
    268  | 	  }/* for */
    269  |
    270  | 	  /* end-of-result -> one extra line */
    271  | 	  SK_cd_puts(&(qe->condat), "\n");
    272  |
    273  | 	  QI_free(qis);
    274  | 	  copy_credit.queries ++;
    275  |
    276  | 	  if( AC_credit_isdenied(&acc_credit) ) {
    277  | 	    SK_cd_puts(&(qe->condat),
    278  |  "% You have reached the limit of returned contact information objects.\n"
    279  |  "% This connection will be terminated now.\n"
    280  |  "% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
    281  |  "% You will not be allowed to query for more CONTACT information for a while.\n"
    282  |  "% Continued attempts to return excessive amounts of contact\n"
    283  |  "% information will result in permanent denial of service.\n"
    284  |  "% Please do not try to use CONTACT information in the\n"
    285  |  "% RIPE Database for non-operational purposes.\n"
    286  |  "% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
    287  | 		       );
    288  | 	  }
    289  |
    290  |           break;
    291  |         default: die;
    292  |         }
    293  | 	/* calc. the credit used, result  into copy_credit */
    294  | 	AC_acc_addup(&copy_credit, &acc_credit, ACC_MINUS);
    295  |
    296  | 	{
    297  | 	  char *qrystat = AC_credit_to_string(&copy_credit);
    298  | 	  float elapsed;
    299  | 	  char *qrytypestr =
    300  | 	    qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
    301  |
    302  | 	  UT_timeget(&endtime);
    303  |
    304  | 	  elapsed = UT_timediff( &begintime, &endtime);
    305  |
    306  | 	  /* log the connection/query/#results/time/denial to file */
    307  | 	  ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
    308  | 		    "<%s> %s%s %.2fs [%s] --  %s",
    309  | 		    qrystat,
    310  | 		    qe->condat.rtc ? "INT " : "",
    311  | 		    qrytypestr,
    312  | 		    elapsed, hostaddress, input
    313  | 		    );
    314  | 	  wr_free(qrystat);
    315  | 	}
    316  |
    317  |       }/* if denied ... else */
    318  |
    319  |       QC_free(qc);
    320  |
    321  |       copy_credit.connections = 1;
    322  |       /* Commit the credit. This will deny if bonus limit hit */
    323  |       AC_commit(&(qe->condat.eIP), &copy_credit, &acl_eip);
    324  |     } /* if still considered connected */
    325  |
    326  |   } /* do */
    327  |   while( qe->k && qe->condat.rtc == 0
    328  | 	 && AC_credit_isdenied( &copy_credit ) == 0
    329  | 	 && CO_get_whois_suspended() == 0);
    330  |
    331  |   /* Free the hostaddress */
    332  |   wr_free(hostaddress);
    333  |
    334  |   SK_cd_close(&(qe->condat));
    335  |
    336  |   /* Free the query_environ */
    337  |   QC_environ_free(qe);
    338  |
    339  | } /* PW_interact() */