Source File modules/pw/protocol_whois.c

    1    | /***************************************
    2    |   $Revision: 1.18 $
    3    |
    4    |   Protocol whois module (pw).  Whois protocol.
    5    |
    6    |   Status: NOT REVUED, NOT TESTED
    7    |
    8    |   ******************/ /******************
    9    |   Filename            : protocol_whois.c
    10   |   Author              : ottrey@ripe.net
    11   |   OSs Tested          : Solaris
    12   |   ******************/ /******************
    13   |   Copyright (c) 1999                              RIPE NCC
    14   |
    15   |   All Rights Reserved
    16   |
    17   |   Permission to use, copy, modify, and distribute this software and its
    18   |   documentation for any purpose and without fee is hereby granted,
    19   |   provided that the above copyright notice appear in all copies and that
    20   |   both that copyright notice and this permission notice appear in
    21   |   supporting documentation, and that the name of the author not be
    22   |   used in advertising or publicity pertaining to distribution of the
    23   |   software without specific, written prior permission.
    24   |
    25   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    26   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    27   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    28   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    29   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    30   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    31   |   ***************************************/
    32   | #include <stdio.h>
    33   | #include <glib.h>
    34   |
    35   | #include "NAME"
    36   |
    37   | #include "defs.h"
    38   | #include "protocol_whois.h"
    39   | #include "mysql_driver.h"
    40   | #include "query_command.h"
    41   | #include "query_instructions.h"
    42   | #include "constants.h"
    43   | /*
    44   | #include "objects.h"
    45   | */
    46   | #include "access_control.h"
    47   | #include "socket.h"
    48   | #include "stubs.h"
    49   |
    50   | void print_hello_banner(Query_environ *qe) {
    51   |   char *str1=NULL;
    52   |
    53   |   SK_cd_puts(&(qe->condat), CVS_NAME);
    54   |   SK_cd_puts(&(qe->condat), "% Rights restricted by copyright. See http://www.ripe.net/db/dbcopyright.html\n");
    55   |   /* Send the environment aswell. */
    56   |   SK_cd_puts(&(qe->condat), "% Environment={");
    57   |   str1 = QC_environ_to_string(*qe);
    58   |   SK_cd_puts(&(qe->condat), str1);
    59   |   free(str1);
    60   |   SK_cd_puts(&(qe->condat), "}\n\n");
    61   | }
    62   |
    63   |
    64   | /* process the whois query */
    65   | PW_qtype_t process_query(char *input,
    66   |                          Query_environ *qe,
    67   |                          Query_command **qc_store)
    68   | {
    69   |   Query_command *qc=NULL;
    70   |     PW_qtype_t query_type;
    71   |
    72   |   if ( strlen(input) == 0) {
    73   |     /* An empty query (Ie return) was sent */
    74   |     query_type = PW_EMPTY;
    75   |   }
    76   |   else {        /* else <==> input_length > 0 ) */
    77   |     /* parse query */
    78   |     printf("whois got %s\n", input);
    79   |
    80   |     /* Make a new query */
    81   |     qc = QC_new(input, qe);
    82   |     *qc_store = qc;
    83   |     /* Update the query environment */
    84   |     // qe = QC_environ_update(qc, qe);
    85   |
    86   |     /* Only do a query if there are keys. */
    87   |     if (qc->keys == NULL) {
    88   |       query_type = PW_NOKEY;
    89   |     }
    90   |     else {
    91   |       if( strlen(qc->keys) == 0 ) {
    92   |         query_type = PW_TEMPLATE;
    93   |       }
    94   |       else if ( strcmp(qc->keys, "help") == 0 ) {
    95   |         query_type = PW_HELP;
    96   |       }
    97   |       else {
    98   |         /* Some real query */
    99   |         query_type = PW_REAL;
    100  |       }
    101  |     }
    102  |   }
    103  |   return query_type;
    104  | }
    105  |
    106  |
    107  | /* PW_interact() */
    108  | /*++++++++++++++++++++++++++++++++++++++
    109  |   Interact with the client.
    110  |
    111  |   int sock Socket that client is connected to.
    112  |
    113  |   More:
    114  |   +html+ <PRE>
    115  |   Authors:
    116  |         ottrey
    117  |
    118  |   +html+ </PRE><DL COMPACT>
    119  |   +html+ <DT>Online References:
    120  |   +html+ <DD><UL>
    121  |   +html+ </UL></DL>
    122  |
    123  |   ++++++++++++++++++++++++++++++++++++++*/
    124  | void PW_interact(int sock) {
    125  |   char input[MAX_INPUT_SIZE];
    126  |
    127  |   int read_result;
    128  |
    129  |   char *hostaddress=NULL;
    130  |   acl_st acl_rip,   acl_eip;
    131  |   acc_st acc_conn,  acc_run, acc_credit;
    132  |   PW_qtype_t query_type;
    133  |   int will_deny=0;
    134  |
    135  |
    136  |   ip_addr_t acc_ip=IP_ADDR_UNSPEC; /* ip we run accounting for */
    137  |
    138  |   Query_environ *qe=NULL;
    139  |   Query_instructions *qis=NULL;
    140  |   Query_command *qc=NULL;
    141  |
    142  |   GList *qitem;
    143  |
    144  |   /* Get the IP of the client */
    145  |   hostaddress = SK_getpeername(sock);
    146  |   printf("SK address: %s\n", hostaddress);
    147  |
    148  |   /* Initialize the query environment. */
    149  |   qe = QC_environ_new(hostaddress, sock);
    150  |
    151  |   /* init to zeros */
    152  |   memset( &(qe->condat), 0, sizeof(sk_conn_st));
    153  |
    154  |   /* set the connection data: both rIP and eIP to real IP */
    155  |   qe->condat.sock = sock;
    156  |   qe->condat.ip = hostaddress;
    157  |   SK_getpeerip(sock, &(qe->condat.rIP));
    158  |   memcpy( &(qe->condat.eIP), &(qe->condat.rIP), sizeof(ip_addr_t));
    159  |
    160  |   /* check the acl using the realIP, get a copy applicable to this IP */
    161  |   AC_check_acl( &(qe->condat.rIP), NULL, NULL, NULL, &acl_rip);
    162  |   if( acl_rip.deny ) {
    163  |     will_deny=1;
    164  |   }
    165  |
    166  |   /* XXX log new connection here ?*/
    167  |
    168  |   do {
    169  |     /* Read input */
    170  |     read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE);
    171  |
    172  |     /* read_result < 0 is an error and connection should be closed */
    173  |     if (read_result < 0 ) {
    174  |       /* log the fact, rtc was set */
    175  |     }
    176  |
    177  |     query_type = process_query(input, qe, &qc);
    178  |
    179  |     /* check -V option */
    180  |     if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC) ) {     /* has pIP in it */
    181  |       qe->condat.eIP = qe->pIP;                   /* set eIP to this IP */
    182  |     }
    183  |     else {
    184  |       qe->condat.eIP = qe->condat.rIP;               /* set eIP to rIP */
    185  |     }
    186  |
    187  |     /* if we have acc already for any ip */
    188  |     if( ! STRUCT_EQUAL(acc_ip, IP_ADDR_UNSPEC) ) {
    189  |       /* but it's the current one */
    190  |       if( memcmp (&acc_ip, &(qe->condat.eIP), sizeof(ip_addr_t))
    191  |           == CMP_EQUAL ) {
    192  |         /* in principle, can do nothing.
    193  |            If accounting tree handling is fast enough,
    194  |            can commit changes and get new copy */
    195  |       }
    196  |       else { /* if it is different from current eIP (support for -k -V) */
    197  |         /* commit changes */
    198  |         AC_commit(&acc_ip, &acc_conn);
    199  |         acc_ip = IP_ADDR_UNSPEC;
    200  |       }
    201  |     }
    202  |
    203  |     /* get new acc structs for the eIP unless we already have */
    204  |     if( memcmp (&acc_ip, &(qe->condat.eIP), sizeof(ip_addr_t))
    205  |         != CMP_EQUAL ) {
    206  |       acc_ip = qe->condat.eIP;
    207  |       memset( &acc_conn, 0, sizeof(acc_st));
    208  |       memset( &acc_run,  0, sizeof(acc_st));
    209  |
    210  |       AC_fetch_acc( &(qe->condat.eIP), &acc_run, 100 );
    211  |         /* if != AC_OK then have to use the zeroed copy */
    212  |     }
    213  |
    214  | /* start setting counters in the connection acc from here on
    215  |    decrement the credit counter (needed to prevent QI_execute from
    216  |    returning too many results */
    217  |
    218  |     /* check ACL (will set denial if bonus limit hit). Calculate credit */
    219  |     AC_check_acl( &(qe->condat.eIP), &acc_run, &acc_conn,
    220  |                    &acc_credit, &acl_eip);
    221  |
    222  |     if( acl_eip.deny ) {
    223  |       acc_conn.denials++;
    224  |       will_deny = 1;
    225  |     }
    226  |
    227  |     if( qe->condat.rtc == 0 ) {
    228  |       print_hello_banner(qe);
    229  |
    230  |       if( will_deny ) {
    231  |         SK_cd_puts(&(qe->condat), "% Sorry, access denied\n");
    232  |       }
    233  |       else {
    234  |
    235  |         switch( query_type ) {
    236  |         case PW_EMPTY:
    237  |         case PW_NOKEY:
    238  |           /* The user didn't specify a key, so
    239  |              - print moron banner
    240  |              - force disconnection of the user. */
    241  |           SK_cd_puts(&(qe->condat), "% No search key specified\n");
    242  |           qe->condat.rtc = SK_NOTEXT;
    243  |           break;
    244  |         case PW_HELP:
    245  |           SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
    246  |           break;
    247  |         case PW_TEMPLATE:
    248  |           if (qc->q != 0) {
    249  |             SK_cd_puts(&(qe->condat), DF_get_server_query(qc->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  |         case PW_REAL:
    259  |           qis = QI_new(qc,qe);
    260  |           for( qitem = g_list_first(qe->sources_list);
    261  |                qitem != NULL;
    262  |                qitem = g_list_next(qitem)) {
    263  |             /* save the original credit, later check how much was used */
    264  |             acc_st copy_credit = acc_credit;
    265  |
    266  |             /* stop as soon as further action considered meaningless */
    267  |             if( qe->condat.rtc != 0 ) {
    268  |               break;
    269  |             }
    270  |
    271  |             /* QI will decrement the credit counters */
    272  |             QI_execute(qitem->data, qis, qe, &acc_credit );
    273  |
    274  |             /* calc. the credit used, result  into copy_credit */
    275  |             AC_acc_addup(&copy_credit, &acc_credit, ACC_MINUS);
    276  |
    277  |             /*  increment the person/role counters in the conn_acc by
    278  |                 the credit used */
    279  |             AC_acc_addup(&acc_conn, &copy_credit, ACC_PLUS);
    280  |             acc_conn.queries++;
    281  |           }
    282  |           QI_free(qis);
    283  |           break;
    284  |         default: die;
    285  |         }
    286  |
    287  |         /* log the connection/query/#results/time to file */
    288  |
    289  |         /* now add up to the connection acc */
    290  |       }
    291  |
    292  |       QC_free(qc);
    293  |
    294  |     } /* if still considered connected */
    295  |
    296  |   } /* do */
    297  |   while( qe->k && qe->condat.rtc == 0 && CO_get_whois_suspended() == 0);
    298  |
    299  |   /* Free the hostaddress */
    300  |   free(hostaddress);
    301  |
    302  |   SK_cd_close(&(qe->condat));
    303  |
    304  |   /* Free the query_environ */
    305  |   QC_environ_free(qe);
    306  |
    307  |   acc_conn.connections++;
    308  |   acc_conn.private_bonus += acc_conn.private_objects;
    309  |   AC_commit(&acc_ip, &acc_conn);
    310  |
    311  | } /* PW_interact() */