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() */