modules/pw/protocol_whois.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- print_hello_banner
- PW_interact
1 /***************************************
2 $Revision: 1.25 $
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 <sys/time.h> /* in Solaris, or time.h in BSD,
52 wrrrr... the fun begins... */
53
54 void print_hello_banner(Query_environ *qe) {
/* [<][>][^][v][top][bottom][index][help] */
55 SK_cd_puts(&(qe->condat), CVS_NAME);
56 SK_cd_puts(&(qe->condat), "% Rights restricted by copyright. \n% See http://www.ripe.net/ripencc/pub-services/db/copyright.html\n");
57
58 #if 0
59 /* Send the environment aswell. */
60 SK_cd_puts(&(qe->condat), "% Environment={");
61 str1 = QC_environ_to_string(*qe);
62 SK_cd_puts(&(qe->condat), str1);
63 wr_free(str1);
64 SK_cd_puts(&(qe->condat), "}\n");
65 #endif
66
67 SK_cd_puts(&(qe->condat), "\n");
68 }
69
70 /* PW_interact() */
71 /*++++++++++++++++++++++++++++++++++++++
72 Interact with the client.
73
74 int sock Socket that client is connected to.
75
76 More:
77 +html+ <PRE>
78 Authors:
79 ottrey
80
81 +html+ </PRE><DL COMPACT>
82 +html+ <DT>Online References:
83 +html+ <DD><UL>
84 +html+ </UL></DL>
85
86 ++++++++++++++++++++++++++++++++++++++*/
87 void PW_interact(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
88 char input[MAX_INPUT_SIZE];
89 int read_result;
90 char *hostaddress=NULL;
91 acl_st acl_rip, acl_eip;
92 acc_st acc_credit, copy_credit;
93 int permanent_ban=0;
94 Query_environ *qe=NULL;
95 Query_instructions *qis=NULL;
96 Query_command *qc=NULL;
97 GList *qitem;
98 int new_connection=1;
99 int acc_deny=0;
100 struct timeval begintime, endtime;
101 er_ret_t err;
102
103 /* Get the IP of the client */
104 hostaddress = SK_getpeername(sock);
105 ER_dbg_va(FAC_PW, 1, "connection from %s", hostaddress);
106
107 /* Initialize the query environment. */
108 qe = QC_environ_new(hostaddress, sock);
109
110 /* init to zeros */
111 memset( &(qe->condat), 0, sizeof(sk_conn_st));
112
113 /* set the connection data: both rIP and eIP to real IP */
114 qe->condat.sock = sock;
115 qe->condat.ip = hostaddress;
116 SK_getpeerip(sock, &(qe->condat.rIP));
117 qe->condat.eIP = qe->condat.rIP;
118
119 /* see if we should be talking at all */
120 /* check the acl using the realIP, get a copy applicable to this IP */
121 AC_check_acl( &(qe->condat.rIP), NULL, &acl_rip);
122 if( acl_rip.deny ) {
123 permanent_ban=1;
124 }
125
126 /* XXX log new connection here ?*/
127
128 do {
129 /* Read input */
130 read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE);
131
132
133 gettimeofday(&begintime, NULL);
134
135 /* read_result < 0 is an error and connection should be closed */
136 if (read_result < 0 ) {
137 /* XXX log the fact, rtc was set */
138 /* EMPTY */
139 }
140
141 qc = QC_create(input, qe);
142
143 /* ADDRESS PASSING: check if -V option has passed IP in it */
144 if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
145 if(acl_rip.trustpass) {
146 acc_st pass_acc;
147
148 /* accounting */
149 memset(&pass_acc, 0, sizeof(acc_st));
150 pass_acc.addrpasses=1;
151 AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
152
153 /* set eIP to this IP */
154 qe->condat.eIP = qe->pIP;
155 }
156 else {
157 /* XXX shall we deny such user ? Now we can... */
158 ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
159 "unauthorised address passing by %s", hostaddress);
160 }
161 }
162
163
164 /* start setting counters in the connection acc from here on
165 decrement the credit counter (needed to prevent QI_execute from
166 returning too many results */
167
168 /* check ACL. Get the proper acl record. Calculate credit */
169 AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
170 /* save the original credit, later check how much was used */
171 copy_credit = acc_credit;
172
173 if( acl_eip.deny ) {
174 permanent_ban = 1;
175 }
176
177 if( qe->condat.rtc == 0 ) {
178 print_hello_banner(qe);
179
180 if( permanent_ban ) {
181 SK_cd_puts(&(qe->condat),
182 "% Sorry, access from your host has been permanently denied\n"
183 "% because of a repeated abusive behaviour.\n"
184 "% Please contact <ripe-dbm@ripe.net> for unblocking\n");
185
186 ER_inf_va(FAC_PW, ASP_PWI_DENTRY,
187 "connection from host %s DENIED", hostaddress);
188
189 }
190 else {
191 switch( qc->query_type ) {
192 case QC_ERROR:
193 SK_cd_puts(&(qe->condat), USAGE);
194 break;
195 case QC_NOKEY:
196 /* some operational stuff, like -k */
197 break;
198 case QC_EMPTY:
199
200 /* The user didn't specify a key, so
201 - print moron banner
202 - force disconnection of the user. */
203 SK_cd_puts(&(qe->condat), "% No search key specified\n");
204 qe->condat.rtc = SK_NOTEXT;
205 break;
206 case QC_HELP:
207 SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
208 break;
209 case QC_TEMPLATE:
210 if (qc->q >= 0) {
211 SK_cd_puts(&(qe->condat), DF_get_server_query(qc->q));
212 }
213 if (qc->t >= 0) {
214 SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
215 }
216 if (qc->v >= 0) {
217 SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
218 }
219 break;
220
221 case QC_FILTERED:
222 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");
223
224 /* FALLTROUGH */
225 case QC_REAL:
226 qis = QI_new(qc,qe);
227
228 /* stop as soon as further action considered meaningless */
229 for( qitem = g_list_first(qe->sources_list);
230 qitem != NULL && qe->condat.rtc == 0;
231 qitem = g_list_next(qitem)) {
232
233 /* QI will decrement the credit counters */
234 err = QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip );
235
236 if( !NOERR(err) ) {
237 if( err == QI_CANTDB ) {
238 SK_cd_puts(&(qe->condat), "% WARNING: Failed to make connection to ");
239 SK_cd_puts(&(qe->condat), (char *)qitem->data);
240 SK_cd_puts(&(qe->condat), " database.\n\n");
241 }
242
243 break; /* quit the loop after any error */
244 }/* if */
245
246 }/* for */
247
248 /* end-of-result -> one extra line */
249 SK_cd_puts(&(qe->condat), "\n");
250
251 QI_free(qis);
252 copy_credit.queries ++;
253
254 if( acc_credit.denials != 0 ) {
255 SK_cd_puts(&(qe->condat),
256 "% You have reached the limit of returned contact information objects.\n"
257 "% This connection will be terminated now.\n"
258 "% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
259 "% You will not be allowed to query for more CONTACT information for a while.\n"
260 "% Continued attempts to return excessive amounts of contact\n"
261 "% information will result in permanent denial of service.\n"
262 "% Please do not try to use CONTACT information information in the\n"
263 "% RIPE Database for non-operational purposes.\n"
264 "% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
265 );
266 }
267
268 break;
269 default: die;
270 }
271 /* calc. the credit used, result into copy_credit */
272 AC_acc_addup(©_credit, &acc_credit, ACC_MINUS);
273
274 {
275 char *qrystat = AC_credit_to_string(©_credit);
276 float elapsed;
277 char *qrytypestr =
278 qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
279
280 gettimeofday(&endtime, NULL);
281
282 elapsed = ( endtime.tv_sec - begintime.tv_sec ) +
283 1e-6 * ( endtime.tv_usec - begintime.tv_usec ) ;
284
285 /* log the connection/query/#results/time/denial to file */
286 ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
287 "<%s> %s %.2fs [%s] -- %s",
288 qrystat, qrytypestr,
289 elapsed, hostaddress, input
290 );
291 wr_free(qrystat);
292 }
293
294 }/* if denied ... else */
295
296 QC_free(qc);
297
298 if( new_connection ) {
299 copy_credit.connections = 1;
300 new_connection = 0;
301 }
302
303 if( copy_credit.denials != 0 ) {
304 acc_deny = 1;
305 }
306
307 /* Commit the credit. This will deny if bonus limit hit */
308 AC_commit(&(qe->condat.eIP), ©_credit, &acl_eip);
309
310 } /* if still considered connected */
311
312 } /* do */
313 while( qe->k && qe->condat.rtc == 0 && acc_deny == 0
314 && CO_get_whois_suspended() == 0);
315
316 /* Free the hostaddress */
317 wr_free(hostaddress);
318
319 SK_cd_close(&(qe->condat));
320
321 /* Free the query_environ */
322 QC_environ_free(qe);
323
324 } /* PW_interact() */