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