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.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(©_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(©_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), ©_credit, &acl_eip);
364 } /* if still considered connected */
365
366 } /* do */
367 while( qe->k && qe->condat.rtc == 0
368 && AC_credit_isdenied( ©_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() */