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.30 $
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 TA_setactivity(input);
139 TA_increment();
140
141 UT_timeget( &begintime );
142
143 /* read_result < 0 is an error and connection should be closed */
144 if (read_result < 0 ) {
145 /* XXX log the fact, rtc was set */
146 /* EMPTY */
147 }
148
149 qc = QC_create(input, qe);
150
151 /* ADDRESS PASSING: check if -V option has passed IP in it */
152 if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) {
153 if(acl_rip.trustpass) {
154 acc_st pass_acc;
155
156 /* accounting */
157 memset(&pass_acc, 0, sizeof(acc_st));
158 pass_acc.addrpasses=1;
159 AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip);
160
161 /* set eIP to this IP */
162 qe->condat.eIP = qe->pIP;
163 }
164 else {
165 /* XXX shall we deny such user ? Now we can... */
166 ER_inf_va(FAC_PW, ASP_PWI_PASSUN,
167 "unauthorised address passing by %s", hostaddress);
168 }
169 }
170
171
172 /* start setting counters in the connection acc from here on
173 decrement the credit counter (needed to prevent QI_execute from
174 returning too many results */
175
176 /* check ACL. Get the proper acl record. Calculate credit */
177 AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip);
178 /* save the original credit, later check how much was used */
179 copy_credit = acc_credit;
180
181 if( acl_eip.deny ) {
182 permanent_ban = 1;
183 }
184
185 if( qe->condat.rtc == 0 ) {
186 print_hello_banner(qe);
187
188 if( permanent_ban ) {
189 SK_cd_puts(&(qe->condat),
190 "% Sorry, access from your host has been permanently denied\n"
191 "% because of a repeated abusive behaviour.\n"
192 "% Please contact <ripe-dbm@ripe.net> for unblocking\n");
193
194 ER_inf_va(FAC_PW, ASP_PWI_DENTRY,
195 "connection from host %s DENIED", hostaddress);
196
197 }
198 else {
199 switch( qc->query_type ) {
200 case QC_ERROR:
201 SK_cd_puts(&(qe->condat), USAGE);
202 qe->condat.rtc = SK_NOTEXT;
203 break;
204 case QC_NOKEY:
205 /* no key (this is OK for some operational stuff, like -k) */
206 break;
207 case QC_EMPTY:
208
209 /* The user didn't specify a key, so
210 - print moron banner
211 - force disconnection of the user. */
212 SK_cd_puts(&(qe->condat), "% No search key specified\n");
213 qe->condat.rtc = SK_NOTEXT;
214 break;
215 case QC_HELP:
216 SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n");
217 break;
218 case QC_TEMPLATE:
219 switch(qc->q) {
220 case QC_Q_SOURCES:
221 /* print source & mirroring info */
222 {
223 GString *srcs = PM_get_nrtm_sources( & qe->condat.rIP, NULL);
224 SK_cd_puts(&(qe->condat), srcs->str);
225 g_string_free (srcs, TRUE);
226 }
227 break;
228 case QC_Q_VERSION:
229 SK_cd_puts(&(qe->condat), DF_get_server_query(qc->q));
230 break;
231 default:
232 /* EMPTY */;
233 } /* -q */
234
235 if (qc->t >= 0) {
236 SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t));
237 }
238 if (qc->v >= 0) {
239 SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v));
240 }
241 break;
242
243 case QC_FILTERED:
244 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");
245
246 /* FALLTROUGH */
247 case QC_REAL:
248 qis = QI_new(qc,qe);
249
250 /* stop as soon as further action considered meaningless */
251 for( qitem = g_list_first(qe->sources_list);
252 qitem != NULL && qe->condat.rtc == 0;
253 qitem = g_list_next(qitem)) {
254
255 /* QI will decrement the credit counters */
256 err = QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip );
257
258 if( !NOERR(err) ) {
259 if( err == QI_CANTDB ) {
260 SK_cd_puts(&(qe->condat), "% WARNING: Failed to make connection to ");
261 SK_cd_puts(&(qe->condat), (char *)qitem->data);
262 SK_cd_puts(&(qe->condat), " database.\n\n");
263 }
264
265 break; /* quit the loop after any error */
266 }/* if */
267
268 }/* for */
269
270 /* end-of-result -> one extra line */
271 SK_cd_puts(&(qe->condat), "\n");
272
273 QI_free(qis);
274 copy_credit.queries ++;
275
276 if( AC_credit_isdenied(&acc_credit) ) {
277 SK_cd_puts(&(qe->condat),
278 "% You have reached the limit of returned contact information objects.\n"
279 "% This connection will be terminated now.\n"
280 "% This is a mechanism to prevent abusive use of contact data in the RIPE Database.\n"
281 "% You will not be allowed to query for more CONTACT information for a while.\n"
282 "% Continued attempts to return excessive amounts of contact\n"
283 "% information will result in permanent denial of service.\n"
284 "% Please do not try to use CONTACT information in the\n"
285 "% RIPE Database for non-operational purposes.\n"
286 "% Refer to http://www.ripe.net/db/dbcopyright.html for more information.\n"
287 );
288 }
289
290 break;
291 default: die;
292 }
293 /* calc. the credit used, result into copy_credit */
294 AC_acc_addup(©_credit, &acc_credit, ACC_MINUS);
295
296 {
297 char *qrystat = AC_credit_to_string(©_credit);
298 float elapsed;
299 char *qrytypestr =
300 qc->query_type == QC_REAL ? "" : QC_get_qrytype(qc->query_type);
301
302 UT_timeget(&endtime);
303
304 elapsed = UT_timediff( &begintime, &endtime);
305
306 /* log the connection/query/#results/time/denial to file */
307 ER_inf_va(FAC_PW, ASP_PWI_QRYLOG,
308 "<%s> %s%s %.2fs [%s] -- %s",
309 qrystat,
310 qe->condat.rtc ? "INT " : "",
311 qrytypestr,
312 elapsed, hostaddress, input
313 );
314 wr_free(qrystat);
315 }
316
317 }/* if denied ... else */
318
319 QC_free(qc);
320
321 copy_credit.connections = 1;
322 /* Commit the credit. This will deny if bonus limit hit */
323 AC_commit(&(qe->condat.eIP), ©_credit, &acl_eip);
324 } /* if still considered connected */
325
326 } /* do */
327 while( qe->k && qe->condat.rtc == 0
328 && AC_credit_isdenied( ©_credit ) == 0
329 && CO_get_whois_suspended() == 0);
330
331 /* Free the hostaddress */
332 wr_free(hostaddress);
333
334 SK_cd_close(&(qe->condat));
335
336 /* Free the query_environ */
337 QC_environ_free(qe);
338
339 } /* PW_interact() */