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] */