## modules/pw/protocol_whois.c

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

## FUNCTIONS

This source file includes following functions.

1. print_hello_banner
2. strchop
3. pw_log_query
4. PW_process_qc
5. PW_interact

       1 /***************************************
       2   $Revision: 1.35 $
       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
      79 void
      80 strchop(char *input)
         /* [<][>][^][v][top][bottom][index][help] */
      81 {
      82   char *co = strchr(input, '\0');
      83   while( co != input && (isspace(*co) || *co == '\0') ) {
      84     *co = '\0';
      85     co--;
      86   }
      87 }
      88
      89
      90 static
      91 void pw_log_query( Query_environ *qe,
         /* [<][>][^][v][top][bottom][index][help] */
      92                    Query_command *qc,
      93                    acc_st *copy_credit,
      94                    ut_timer_t begintime,
      95                    ut_timer_t endtime,
      96                    char *hostaddress,
      97                    char *input)
      98 {
      99   char *qrystat = AC_credit_to_string(copy_credit);
     100   float elapsed;
     101   char *qrytypestr =
     102     qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
     103
     104
     105   elapsed = UT_timediff( &begintime, &endtime);
     106
     107   /* log the connection/query/#results/time/denial to file */
     108   ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
     109             "<%s> %s%s %.2fs [%s] --  %s",
     110             qrystat,
     111             qe->condat.rtc ? "INT " : "",
     112             qrytypestr,
     113             elapsed, hostaddress, input
     114             );
     115   wr_free(qrystat);
     116 }
     117
     118
     119
     120
     121 er_ret_t PW_process_qc(Query_environ *qe,
         /* [<][>][^][v][top][bottom][index][help] */
     122                    Query_command *qc,
     123                    acc_st *acc_credit,
     124                    acl_st *acl_eip )
     125 {
     126   GList *qitem;
     127   Query_instructions *qis=NULL;
     128   er_ret_t err;
     129
     130   switch( qc->query_type ) {
     131       case QC_SYNERR:
     132         SK_cd_puts(&(qe->condat), USAGE);
     133         /* FALLTHROUGH */
     134       case QC_PARERR:
     135         /* parameter error. relevant error message is already printed */
     136
     137         /* force disconnection on error */
     138         qe->k = 0;
     139         break;
     140       case QC_NOKEY:
     141         /* no key (this is OK for some operational stuff, like -k) */
     142         break;
     143       case QC_EMPTY:
     144
     145         /* The user didn't specify a key, so
     146            - print moron banner
     147            - force disconnection of the user. */
     148         SK_cd_puts(&(qe->condat), "% No search key specified\n");
     149         qe->condat.rtc = SK_NOTEXT;
     150         break;
     151       case QC_HELP:
     152         SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
     153         break;
     154       case QC_TEMPLATE:
     155         switch(qc->q) {
     156         case QC_Q_SOURCES:
     157           /* print source & mirroring info */
     158           {
     159             GString *srcs = PM_get_nrtm_sources( & qe->condat.rIP, NULL);
     160             SK_cd_puts(&(qe->condat), srcs->str);
     161             g_string_free (srcs, TRUE);
     162           }
     163           break;
     164         case QC_Q_VERSION:
     165           SK_cd_puts(&(qe->condat), "% RIP version " VERSION "\n");
     166           break;
     167         default:
     168           /* EMPTY */;
     169         } /* -q */
     170
     171         if (qc->t >= 0) {
     172           SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
     173         }
     174         if (qc->v >= 0) {
     175           SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
     176         }
     177         break;
     178
     179       case QC_FILTERED:
     180         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");
     181
     182         /* FALLTROUGH */
     183       case QC_REAL:
     184         qis = QI_new(qc,qe);
     185
     186         /* stop as soon as further action considered meaningless */
     187         for( qitem = g_list_first(qe->sources_list);
     188              qitem != NULL && qe->condat.rtc == 0;
     189              qitem = g_list_next(qitem)) {
     190
     191           /* QI will decrement the credit counters */
     192           err = QI_execute(qitem->data, qis, qe, acc_credit, acl_eip );
     193
     194           if( !NOERR(err) ) {
     195             if( err == QI_CANTDB ) {
     196               SK_cd_puts(&(qe->condat), "% WARNING: Failed to make connection to ");
     197               SK_cd_puts(&(qe->condat), (char *)qitem->data);
     198               SK_cd_puts(&(qe->condat), " database.\n\n");
     199             }
     200
     201             break; /* quit the loop after any error */
     202           }/* if */
     203
     204         }/* for every source */
     205
     206         QI_free(qis);
     207
     208         if( AC_credit_isdenied(acc_credit) ) {
     209           SK_cd_puts(&(qe->condat),
     210  "% You have reached the limit of returned contact information objects.\n"
     211  "% This connection will be terminated now.\n"
     212  "% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
     213  "% You will not be allowed to query for more CONTACT information for a while.\n"
     214  "% Continued attempts to return excessive amounts of contact\n"
     215  "% information will result in permanent denial of service.\n"
     216  "% Please do not try to use CONTACT information in the\n"
     217  "% RIPE Database for non-operational purposes.\n"
     218  "% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
     219                        );
     220         }
     221
     222         break;
     223       default: die;
     224       }
     225
     226   return err;
     227 }
     228
     229 /* PW_interact() */
     230 /*++++++++++++++++++++++++++++++++++++++
     231   Interact with the client.
     232
     233   int sock Socket that client is connected to.
     234
     235   More:
     236   +html+ <PRE>
     237   Authors:
     238         ottrey (original CP/M version)
     239         marek
     240
     241   +html+ </PRE><DL COMPACT>
     242   +html+ <DT>Online References:
     243   +html+ <DD><UL>
     244   +html+ </UL></DL>
     245
     246   ++++++++++++++++++++++++++++++++++++++*/
     247 void PW_interact(int sock) {
         /* [<][>][^][v][top][bottom][index][help] */
     248   char input[MAX_INPUT_SIZE];
     249   int read_result;
     250   char *hostaddress=NULL;
     251   acl_st acl_rip,   acl_eip;
     252   acc_st acc_credit, copy_credit;
     253   Query_environ *qe=NULL;
     254   Query_command *qc=NULL;
     255   ut_timer_t begintime, endtime;
     256
     257
     258   /* Get the IP of the client */
     259   hostaddress = SK_getpeername(sock);
     260   ER_dbg_va(FAC_PW, 1, "connection from %s", hostaddress);
     261
     262   /* Initialize the query environment. */
     263   qe = QC_environ_new(hostaddress, sock);
     264
     265   /* init to zeros */
     266   memset( &(qe->condat), 0, sizeof(sk_conn_st));
     267
     268   /* set the connection data: both rIP and eIP to real IP */
     269   qe->condat.sock = sock;
     270   qe->condat.ip = hostaddress;
     271   SK_getpeerip(sock, &(qe->condat.rIP));
     272   qe->condat.eIP = qe->condat.rIP;
     273
     274   qe->condat.rd_timeout.tv_sec = 180; /* read timeout */
     275
     276   /* see if we should be talking at all */
     277   /* check the acl using the realIP, get a copy applicable to this IP */
     278   AC_check_acl( &(qe->condat.rIP), NULL, &acl_rip);
     279
     280   do {
     281     int unauth_pass=0;
     282
     283     TA_setactivity("waiting for query");
     284     /* Read input */
     285     read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE);
     286     /* trash trailing whitespaces(including \n) */
     287     strchop(input);
     288
     289     TA_setactivity(input);
     290     TA_increment();
     291
     292     UT_timeget( &begintime );
     293
     294     qc = QC_create(input, qe);
     295
     296     print_hello_banner(qe);
     297
     298     /* ADDRESS PASSING: check if -V option has passed IP in it */
     299     if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
     300       if(acl_rip.trustpass) {
     301         acc_st pass_acc;
     302
     303         /* accounting */
     304         memset(&pass_acc, 0, sizeof(acc_st));
     305         pass_acc.addrpasses=1;
     306         AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
     307
     308         /* set eIP to this IP */
     309         qe->condat.eIP = qe->pIP;
     310       }
     311       else {
     312         /* XXX shall we deny such user ? Now we can... */
     313         ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
     314                   "unauthorised address passing by %s", hostaddress);
     315         unauth_pass = 1; /* keep in mind ... */
     316       }
     317     } /* if an address was passed */
     318
     319     /* start setting counters in the connection acc from here on
     320        decrement the credit counter (needed to prevent QI_execute from
     321        returning too many results */
     322
     323     /* check ACL. Get the proper acl record. Calculate credit */
     324     AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
     325     /* save the original credit, later check how much was used */
     326     copy_credit = acc_credit;
     327
     328     copy_credit.connections ++;
     329
     330     /* printing notices */
     331     if( unauth_pass && ! acl_rip.deny ) {
     332       SK_cd_puts(&(qe->condat), /* print only if not yet completely denied */
     333 "% Sorry, you are not allowed to pass addresses on the query line.\n"
     334 "% Please contact us for such permission. For the moment, continuing\n"
     335 "% this will cause permanent denial of the access\n");
     336     }
     337     if( acl_eip.deny || acl_rip.deny ) {
     338       SK_cd_puts(&(qe->condat),
     339
     340 "% Sorry, access from your host has been permanently denied\n"
     341 "% because of a repeated abusive behaviour.\n"
     342 "% Please contact <ripe-dbm@ripe.net> for unblocking\n");
     343     }
     344
     345     if( acl_eip.deny || acl_rip.deny || unauth_pass ) {
     346       copy_credit.denials ++;
     347     }
     348     else {
     349       /************ ACTUAL PROCESSING IS HERE ***********/
     350       PW_process_qc(qe, qc, &acc_credit, &acl_eip);
     351
     352       if( qc->query_type == QC_REAL ) {
     353         copy_credit.queries ++;
     354       }
     355     }/* if denied ... else */
     356
     357     /* calc. the credit used, result  into copy_credit
     358        This step MUST NOT be forgotten. It must complement
     359        the initial calculation of a credit, otherwise accounting
     360        will go bgzzzzzt.
     361     */
     362     AC_acc_addup(&copy_credit, &acc_credit, ACC_MINUS);
     363
     364     /* now we can check how many results there were, etc. */
     365     if(  ! AC_credit_isdenied(&acc_credit) ) {
     366       if( (qc->query_type == QC_REAL || qc->query_type == QC_FILTERED)
     367           && copy_credit.private_objects + copy_credit.public_objects
     368           + copy_credit.referrals == 0 ) {
     369         SK_cd_puts(&(qe->condat),
     370 "% No entries found for the selected source(s).\n"
     371 "%\n"
     372 "% If you would like to search on arbitrary strings,\n"
     373 "% please see the Database page on the RIPE NCC\n"
     374 "% web-site at http://www.ripe.net/ripencc/pub-services/db/\n"
     375 "% This will only work for RIPE data.\n"
     376 "%\n"
     377 "% Please note that the RIPE whoisd service temporarily\n"
     378 "% mirrors only ARIN and APNIC databases.\n");
     379       }
     380
     381       UT_timeget(&endtime);
     382       /* query logging */
     383       pw_log_query(qe, qc, &copy_credit, begintime, endtime,
     384                    hostaddress, input);
     385
     386       /* Commit the credit. This will deny if bonus limit hit
     387          and clear the copy */
     388       AC_commit(&(qe->condat.eIP), &copy_credit, &acl_eip);
     389
     390     } /* if ! denied ... (after credit addup) */
     391
     392     /* end-of-result -> one extra line */
     393     SK_cd_puts(&(qe->condat), "\n");
     394
     395     QC_free(qc);
     396   } /* do */
     397   while( qe->k && qe->condat.rtc == 0
     398          && AC_credit_isdenied( &copy_credit ) == 0
     399          && CO_get_whois_suspended() == 0);
     400
     401   /* Free the hostaddress */
     402   wr_free(hostaddress);
     403
     404   SK_cd_close(&(qe->condat));
     405
     406   /* Free the query_environ */
     407   QC_environ_free(qe);
     408
     409 } /* PW_interact() */

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