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