1 | /*************************************** 2 | $Revision: 1.19 $ 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 | wr_free(str1); 60 | SK_cd_puts(&(qe->condat), "}\n\n"); 61 | } 62 | 63 | /* PW_interact() */ 64 | /*++++++++++++++++++++++++++++++++++++++ 65 | Interact with the client. 66 | 67 | int sock Socket that client is connected to. 68 | 69 | More: 70 | +html+ <PRE> 71 | Authors: 72 | ottrey 73 | 74 | +html+ </PRE><DL COMPACT> 75 | +html+ <DT>Online References: 76 | +html+ <DD><UL> 77 | +html+ </UL></DL> 78 | 79 | ++++++++++++++++++++++++++++++++++++++*/ 80 | void PW_interact(int sock) { 81 | char input[MAX_INPUT_SIZE]; 82 | int read_result; 83 | char *hostaddress=NULL; 84 | acl_st acl_rip, acl_eip; 85 | acc_st acc_credit, copy_credit; 86 | int permanent_ban=0; 87 | Query_environ *qe=NULL; 88 | Query_instructions *qis=NULL; 89 | Query_command *qc=NULL; 90 | GList *qitem; 91 | int new_connection=1; 92 | int acc_deny=0; 93 | 94 | /* Get the IP of the client */ 95 | hostaddress = SK_getpeername(sock); 96 | printf("SK address: %s\n", hostaddress); 97 | 98 | /* Initialize the query environment. */ 99 | qe = QC_environ_new(hostaddress, sock); 100 | 101 | /* init to zeros */ 102 | memset( &(qe->condat), 0, sizeof(sk_conn_st)); 103 | 104 | /* set the connection data: both rIP and eIP to real IP */ 105 | qe->condat.sock = sock; 106 | qe->condat.ip = hostaddress; 107 | SK_getpeerip(sock, &(qe->condat.rIP)); 108 | memcpy( &(qe->condat.eIP), &(qe->condat.rIP), sizeof(ip_addr_t)); 109 | 110 | /* see if we should be talking at all */ 111 | /* check the acl using the realIP, get a copy applicable to this IP */ 112 | AC_check_acl( &(qe->condat.rIP), NULL, &acl_rip); 113 | if( acl_rip.deny ) { 114 | permanent_ban=1; 115 | } 116 | 117 | /* XXX log new connection here ?*/ 118 | 119 | do { 120 | /* Read input */ 121 | read_result = SK_cd_gets(&(qe->condat), input, MAX_INPUT_SIZE); 122 | 123 | /* read_result < 0 is an error and connection should be closed */ 124 | if (read_result < 0 ) { 125 | /* log the fact, rtc was set */ 126 | } 127 | 128 | qc = QC_create(input, qe); 129 | 130 | /* ADDRESS PASSING: check if -V option has passed IP in it */ 131 | if( ! STRUCT_EQUAL(qe->pIP,IP_ADDR_UNSPEC)) { 132 | if(acl_rip.trustpass) { 133 | acc_st pass_acc; 134 | 135 | /* accounting */ 136 | memset(&pass_acc, 0, sizeof(acc_st)); 137 | pass_acc.addrpasses=1; 138 | AC_commit( &qe->condat.rIP, &pass_acc, &acl_rip); 139 | 140 | /* set eIP to this IP */ 141 | qe->condat.eIP = qe->pIP; 142 | } 143 | else { 144 | /* XXX shall we deny such user ? Now we can... */ 145 | log_inst_print("unathorised address passing"); 146 | } 147 | } 148 | else { 149 | qe->condat.eIP = qe->condat.rIP; /* set eIP to rIP */ 150 | } 151 | 152 | /* start setting counters in the connection acc from here on 153 | decrement the credit counter (needed to prevent QI_execute from 154 | returning too many results */ 155 | 156 | /* check ACL. Get the proper acl record. Calculate credit */ 157 | AC_check_acl( &(qe->condat.eIP), &acc_credit, &acl_eip); 158 | /* save the original credit, later check how much was used */ 159 | copy_credit = acc_credit; 160 | 161 | if( acl_eip.deny ) { 162 | permanent_ban = 1; 163 | } 164 | 165 | if( qe->condat.rtc == 0 ) { 166 | print_hello_banner(qe); 167 | 168 | if( permanent_ban ) { 169 | SK_cd_puts(&(qe->condat), 170 | "% Sorry, access from your host has been permanently denied\n" 171 | "% because of a repeated abusive behaviour.\n" 172 | "% Please contact <ripe-dbm@ripe.net> for unblocking the access\n"); 173 | } 174 | else { 175 | 176 | switch( qc->query_type ) { 177 | case PW_NOKEY: 178 | /* some operational stuff, like -k */ 179 | break; 180 | case PW_EMPTY: 181 | 182 | /* The user didn't specify a key, so 183 | - print moron banner 184 | - force disconnection of the user. */ 185 | SK_cd_puts(&(qe->condat), "% No search key specified\n"); 186 | qe->condat.rtc = SK_NOTEXT; 187 | break; 188 | case PW_HELP: 189 | SK_cd_puts(&(qe->condat), "% Nothing can help you anymore...:-)\n"); 190 | break; 191 | case PW_TEMPLATE: 192 | if (qc->q != 0) { 193 | SK_cd_puts(&(qe->condat), DF_get_server_query(qc->q)); 194 | } 195 | if (qc->t != 0) { 196 | SK_cd_puts(&(qe->condat), DF_get_class_template(qc->t)); 197 | } 198 | if (qc->v != 0) { 199 | SK_cd_puts(&(qe->condat), DF_get_class_template_v(qc->v)); 200 | } 201 | break; 202 | case PW_REAL: 203 | qis = QI_new(qc,qe); 204 | 205 | /* stop as soon as further action considered meaningless */ 206 | for( qitem = g_list_first(qe->sources_list); 207 | qitem != NULL && qe->condat.rtc == 0; 208 | qitem = g_list_next(qitem)) { 209 | 210 | /* QI will decrement the credit counters */ 211 | QI_execute(qitem->data, qis, qe, &acc_credit, &acl_eip ); 212 | 213 | } 214 | QI_free(qis); 215 | copy_credit.queries ++; 216 | break; 217 | default: die; 218 | } 219 | 220 | /* log the connection/query/#results/time/denial to file */ 221 | 222 | } 223 | QC_free(qc); 224 | 225 | /* calc. the credit used, result into copy_credit */ 226 | AC_acc_addup(©_credit, &acc_credit, ACC_MINUS); 227 | 228 | if( new_connection ) { 229 | copy_credit.connections = 1; 230 | new_connection = 0; 231 | } 232 | 233 | if( copy_credit.denials != 0 ) { 234 | acc_deny = 1; 235 | } 236 | 237 | /* Commit the credit. This will deny if bonus limit hit */ 238 | AC_commit(&(qe->condat.eIP), ©_credit, &acl_eip); 239 | 240 | } /* if still considered connected */ 241 | 242 | } /* do */ 243 | while( qe->k && qe->condat.rtc == 0 && acc_deny == 0 244 | && CO_get_whois_suspended() == 0); 245 | 246 | /* Free the hostaddress */ 247 | wr_free(hostaddress); 248 | 249 | SK_cd_close(&(qe->condat)); 250 | 251 | /* Free the query_environ */ 252 | QC_environ_free(qe); 253 | 254 | } /* PW_interact() */