## modules/pw/protocol_whois.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. print_hello_banner
2. PW_interact

       1 /***************************************
       2   $Revision: 1.33 $
       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) {
         /* [<][>][^][v][top][bottom][index][help] */
      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) {
         /* [<][>][^][v][top][bottom][index][help] */
      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     /* trash trailing whitespaces(including \n) */
     139     {
     140       char *co = strchr(input, '\0');
     141       while( co != input && (isspace(*co) || *co == '\0') ) {
     142         *co = '\0';
     143         co--;
     144       }
     145     }
     146
     147     TA_setactivity(input);
     148     TA_increment();
     149
     150     UT_timeget( &begintime );
     151
     152 #if 0
     153     /* read_result < 0 is an error and connection should be closed */
     154     if (read_result < 0 ) {
     155       /*  XXX log the fact, rtc was set */
     156       /* EMPTY */
     157     }
     158 #endif
     159
     160     qc = QC_create(input, qe);
     161
     162     /* ADDRESS PASSING: check if -V option has passed IP in it */
     163     if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
     164       if(acl_rip.trustpass) {
     165         acc_st pass_acc;
     166
     167         /* accounting */
     168         memset(&pass_acc, 0, sizeof(acc_st));
     169         pass_acc.addrpasses=1;
     170         AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
     171
     172         /* set eIP to this IP */
     173         qe->condat.eIP = qe->pIP;
     174       }
     175       else {
     176         /* XXX shall we deny such user ? Now we can... */
     177         ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
     178                   "unauthorised address passing by %s", hostaddress);
     179       }
     180     }
     181
     182
     183     /* start setting counters in the connection acc from here on
     184        decrement the credit counter (needed to prevent QI_execute from
     185        returning too many results */
     186
     187     /* check ACL. Get the proper acl record. Calculate credit */
     188     AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
     189     /* save the original credit, later check how much was used */
     190     copy_credit = acc_credit;
     191
     192     if( acl_eip.deny ) {
     193       permanent_ban = 1;
     194     }
     195
     196     if( qe->condat.rtc == 0 ) {
     197       print_hello_banner(qe);
     198
     199       if( permanent_ban ) {
     200         SK_cd_puts(&(qe->condat),
     201 "% Sorry, access from your host has been permanently denied\n"
     202 "% because of a repeated abusive behaviour.\n"
     203 "% Please contact <ripe-dbm@ripe.net> for unblocking\n");
     204
     205         ER_inf_va(FAC_PW, ASP_PWI_DENTRY,
     206                   "connection from host %s DENIED", hostaddress);
     207
     208       }
     209       else {
     210         switch( qc->query_type ) {
     211         case QC_SYNERR:
     212           SK_cd_puts(&(qe->condat), USAGE);
     213           /* FALLTHROUGH */
     214         case QC_PARERR:
     215           /* parameter error. relevant error message is already printed */
     216
     217           /* force disconnection on error */
     218           qe->k = 0;
     219           break;
     220         case QC_NOKEY:
     221           /* no key (this is OK for some operational stuff, like -k) */
     222           break;
     223         case QC_EMPTY:
     224
     225           /* The user didn't specify a key, so
     226              - print moron banner
     227              - force disconnection of the user. */
     228           SK_cd_puts(&(qe->condat), "% No search key specified\n");
     229           qe->condat.rtc = SK_NOTEXT;
     230           break;
     231         case QC_HELP:
     232           SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
     233           break;
     234         case QC_TEMPLATE:
     235           switch(qc->q) {
     236           case QC_Q_SOURCES:
     237             /* print source & mirroring info */
     238             {
     239               GString *srcs = PM_get_nrtm_sources( & qe->condat.rIP, NULL);
     240               SK_cd_puts(&(qe->condat), srcs->str);
     241               g_string_free (srcs, TRUE);
     242             }
     243             break;
     244           case QC_Q_VERSION:
     245             SK_cd_puts(&(qe->condat), "% RIP version " VERSION "\n");
     246             break;
     247           default:
     248             /* EMPTY */;
     249           } /* -q */
     250
     251           if (qc->t >= 0) {
     252             SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
     253           }
     254           if (qc->v >= 0) {
     255             SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
     256           }
     257           break;
     258
     259         case QC_FILTERED:
     260           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");
     261
     262           /* FALLTROUGH */
     263         case QC_REAL:
     264           qis = QI_new(qc,qe);
     265
     266           /* stop as soon as further action considered meaningless */
     267           for( qitem = g_list_first(qe->sources_list);
     268                qitem != NULL && qe->condat.rtc == 0;
     269                qitem = g_list_next(qitem)) {
     270
     271             /* QI will decrement the credit counters */
     272             err = QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip );
     273
     274             if( !NOERR(err) ) {
     275               if( err == QI_CANTDB ) {
     276                 SK_cd_puts(&(qe->condat), "% WARNING: Failed to make connection to ");
     277                 SK_cd_puts(&(qe->condat), (char *)qitem->data);
     278                 SK_cd_puts(&(qe->condat), " database.\n\n");
     279               }
     280
     281               break; /* quit the loop after any error */
     282             }/* if */
     283
     284           }/* for */
     285
     286
     287
     288           QI_free(qis);
     289           copy_credit.queries ++;
     290
     291           if( AC_credit_isdenied(&acc_credit) ) {
     292             SK_cd_puts(&(qe->condat),
     293  "% You have reached the limit of returned contact information objects.\n"
     294  "% This connection will be terminated now.\n"
     295  "% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
     296  "% You will not be allowed to query for more CONTACT information for a while.\n"
     297  "% Continued attempts to return excessive amounts of contact\n"
     298  "% information will result in permanent denial of service.\n"
     299  "% Please do not try to use CONTACT information in the\n"
     300  "% RIPE Database for non-operational purposes.\n"
     301  "% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
     302                        );
     303           }
     304
     305           break;
     306         default: die;
     307         }
     308         /* calc. the credit used, result  into copy_credit
     309            This step MUST NOT be forgotten. It must complement
     310            the initial calculation of a credit, otherwise accounting
     311            will go bgzzzzzt.
     312          */
     313         AC_acc_addup(&copy_credit, &acc_credit, ACC_MINUS);
     314
     315         /* now we can check how many results there were, etc. */
     316         if( (qc->query_type == QC_REAL || qc->query_type == QC_FILTERED)
     317             && copy_credit.private_objects + copy_credit.public_objects
     318             + copy_credit.referrals == 0 ) {
     319
     320           SK_cd_puts(&(qe->condat),
     321 "% No entries found for the selected source(s).\n"
     322 "%\n"
     323 "% If you would like to search on arbitrary strings,\n"
     324 "% please see the Database page on the RIPE NCC\n"
     325 "% web-site at http://www.ripe.net/ripencc/pub-services/db/\n"
     326 "% This will only work for RIPE data.\n"
     327 "%\n"
     328 "% Please note that the RIPE whoisd service temporarily\n"
     329 "% mirrors only ARIN and APNIC databases.\n");
     330
     331         }
     332         /* end-of-result -> one extra line */
     333           SK_cd_puts(&(qe->condat), "\n");
     334
     335         /* query logging */
     336         {
     337           char *qrystat = AC_credit_to_string(&copy_credit);
     338           float elapsed;
     339           char *qrytypestr =
     340             qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
     341
     342           UT_timeget(&endtime);
     343
     344           elapsed = UT_timediff( &begintime, &endtime);
     345
     346           /* log the connection/query/#results/time/denial to file */
     347           ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
     348                     "<%s> %s%s %.2fs [%s] --  %s",
     349                     qrystat,
     350                     qe->condat.rtc ? "INT " : "",
     351                     qrytypestr,
     352                     elapsed, hostaddress, input
     353                     );
     354           wr_free(qrystat);
     355         }
     356
     357       }/* if denied ... else */
     358
     359       QC_free(qc);
     360
     361       copy_credit.connections = 1;
     362       /* Commit the credit. This will deny if bonus limit hit */
     363       AC_commit(&(qe->condat.eIP), &copy_credit, &acl_eip);
     364     } /* if still considered connected */
     365
     366   } /* do */
     367   while( qe->k && qe->condat.rtc == 0
     368          && AC_credit_isdenied( &copy_credit ) == 0
     369          && CO_get_whois_suspended() == 0);
     370
     371   /* Free the hostaddress */
     372   wr_free(hostaddress);
     373
     374   SK_cd_close(&(qe->condat));
     375
     376   /* Free the query_environ */
     377   QC_environ_free(qe);
     378
     379 } /* PW_interact() */

/* [<][>][^][v][top][bottom][index][help] */