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